Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Apollo Java 2.6.0
------------------

* [Fix Apollo client local cache fallback for Spring Boot 3 executable JARs](https://github.com/apolloconfig/apollo-java/pull/136)
* [Support `extendInfo`/`parentAppId` in OpenAPI `getNamespace(s)` client calls](https://github.com/apolloconfig/apollo-java/pull/144)

------------------
All issues and pull requests are [here](https://github.com/apolloconfig/apollo-java/milestone/6?closed=1)
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,20 @@ default OpenNamespaceDTO getNamespace(String appId, String env, String clusterNa
*/
OpenNamespaceDTO getNamespace(String appId, String env, String clusterName, String namespaceName, boolean fillItemDetail);

/**
* Retrieves a single namespace, optionally including extra info such as {@code parentAppId}
* of an associated public namespace.
* <p>
* Default implementation falls back to {@link #getNamespace(String, String, String, String, boolean)}
* and ignores {@code extendInfo}, for backward compatibility with implementations written
* before this method was introduced. Implementations that support extendInfo should override
* this method directly.
* @since 2.6.0
*/
default OpenNamespaceDTO getNamespace(String appId, String env, String clusterName, String namespaceName, boolean fillItemDetail, boolean extendInfo) {
return getNamespace(appId, env, clusterName, namespaceName, fillItemDetail);
}

default List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName) {
return getNamespaces(appId, env, clusterName, true);
}
Expand All @@ -46,6 +60,20 @@ default List<OpenNamespaceDTO> getNamespaces(String appId, String env, String cl
*/
List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName, boolean fillItemDetail);

/**
* Retrieves a list namespaces, optionally including extra info such as {@code parentAppId}
* of an associated public namespace.
* <p>
* Default implementation falls back to {@link #getNamespaces(String, String, String, boolean)}
* and ignores {@code extendInfo}, for backward compatibility with implementations written
* before this method was introduced. Implementations that support extendInfo should override
* this method directly.
* @since 2.6.0
*/
default List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName, boolean fillItemDetail, boolean extendInfo) {
return getNamespaces(appId, env, clusterName, fillItemDetail);
}

OpenAppNamespaceDTO createAppNamespace(OpenAppNamespaceDTO appNamespaceDTO);

OpenNamespaceLockDTO getNamespaceLock(String appId, String env, String clusterName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clu
return namespaceService.getNamespaces(appId, env, clusterName, fillItemDetail);
}


/**
* Get the namespaces with extendInfo
* @since 2.6.0
*/
public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName, boolean fillItemDetail, boolean extendInfo) {
return namespaceService.getNamespaces(appId, env, clusterName, fillItemDetail, extendInfo);
}

/**
* Get the cluster
*
Expand Down Expand Up @@ -159,6 +168,14 @@ public OpenNamespaceDTO getNamespace(String appId, String env, String clusterNam
return namespaceService.getNamespace(appId, env, clusterName, namespaceName, fillItemDetail);
}

/**
* Get the namespace with extendInfo
* @since 2.6.0
*/
public OpenNamespaceDTO getNamespace(String appId, String env, String clusterName, String namespaceName, boolean fillItemDetail, boolean extendInfo) {
return namespaceService.getNamespace(appId, env, clusterName, namespaceName, fillItemDetail, extendInfo);
}

/**
* Create the app namespace
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public NamespaceOpenApiService(CloseableHttpClient client, String baseUrl, Gson

@Override
public OpenNamespaceDTO getNamespace(String appId, String env, String clusterName, String namespaceName, boolean fillItemDetail) {
return getNamespace(appId, env, clusterName, namespaceName, fillItemDetail, false);
}

@Override
public OpenNamespaceDTO getNamespace(String appId, String env, String clusterName, String namespaceName, boolean fillItemDetail, boolean extendInfo) {
if (Strings.isNullOrEmpty(clusterName)) {
clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT;
}
Expand All @@ -59,6 +64,7 @@ public OpenNamespaceDTO getNamespace(String appId, String env, String clusterNam
.namespacesPathVal(namespaceName);

pathBuilder.addParam("fillItemDetail", fillItemDetail);
pathBuilder.addParam("extendInfo", extendInfo);

try (CloseableHttpResponse response = get(pathBuilder)) {
return gson.fromJson(EntityUtils.toString(response.getEntity()), OpenNamespaceDTO.class);
Expand All @@ -71,6 +77,11 @@ public OpenNamespaceDTO getNamespace(String appId, String env, String clusterNam

@Override
public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName, boolean fillItemDetail) {
return getNamespaces(appId, env, clusterName, fillItemDetail, false);
}

@Override
public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName, boolean fillItemDetail, boolean extendInfo) {
if (Strings.isNullOrEmpty(clusterName)) {
clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT;
}
Expand All @@ -85,6 +96,7 @@ public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clu
.customResource("namespaces");

pathBuilder.addParam("fillItemDetail", fillItemDetail);
pathBuilder.addParam("extendInfo", extendInfo);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

try (CloseableHttpResponse response = get(pathBuilder)) {
return gson.fromJson(EntityUtils.toString(response.getEntity()), OPEN_NAMESPACE_DTO_LIST_TYPE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class OpenNamespaceDTO extends BaseDTO {

private List<OpenItemDTO> items;

private OpenNamespaceExtendDTO extendInfo;

public String getAppId() {
return appId;
}
Expand Down Expand Up @@ -90,6 +92,14 @@ public void setItems(List<OpenItemDTO> items) {
this.items = items;
}

public OpenNamespaceExtendDTO getExtendInfo() {
return extendInfo;
}

public void setExtendInfo(OpenNamespaceExtendDTO extendInfo) {
this.extendInfo = extendInfo;
}

@Override
public String toString() {
return "OpenNamespaceDTO{" +
Expand All @@ -100,6 +110,7 @@ public String toString() {
", format='" + format + '\'' +
", isPublic=" + isPublic +
", items=" + items +
", extendInfo=" + extendInfo +
", dataChangeCreatedBy='" + dataChangeCreatedBy + '\'' +
", dataChangeLastModifiedBy='" + dataChangeLastModifiedBy + '\'' +
", dataChangeCreatedTime=" + dataChangeCreatedTime +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2022 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.openapi.dto;

/**
* Extra namespace info only returned when requesting with {@code extendInfo=true}.
*
* @since 2.6.0
*/
public class OpenNamespaceExtendDTO {

private Boolean isConfigHidden;

private String parentAppId;

private Integer itemModifiedCnt;

public Boolean getIsConfigHidden() {
return isConfigHidden;
}

public void setIsConfigHidden(Boolean isConfigHidden) {
this.isConfigHidden = isConfigHidden;
}

public String getParentAppId() {
return parentAppId;
}

public void setParentAppId(String parentAppId) {
this.parentAppId = parentAppId;
}

public Integer getItemModifiedCnt() {
return itemModifiedCnt;
}

public void setItemModifiedCnt(Integer itemModifiedCnt) {
this.itemModifiedCnt = itemModifiedCnt;
}

@Override
public String toString() {
return "OpenNamespaceExtendDTO{" +
"isConfigHidden=" + isConfigHidden +
", parentAppId='" + parentAppId + '\'' +
", itemModifiedCnt=" + itemModifiedCnt +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Copyright 2022 Apollo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.ctrip.framework.apollo.openapi.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;

import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO;
import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO;
import java.util.Collections;
import java.util.List;
import org.junit.Test;

/**
* Regression tests for the {@code extendInfo} default compatibility bridges added in 2.6.0.
* <p>
* {@link LegacyNamespaceOpenApiService} below only implements the pre-2.6.0 abstract contract
* (the {@code fillItemDetail} overloads), exactly like an external implementation or test double
* written before {@code extendInfo} was introduced. The fact that it compiles at all is itself
* part of the regression being guarded against.
*/
public class NamespaceOpenApiServiceTest {

@Test
public void testGetNamespaceDefaultBridgeDelegatesToLegacyMethod() {
LegacyNamespaceOpenApiService legacyService = new LegacyNamespaceOpenApiService();

OpenNamespaceDTO result = legacyService.getNamespace("someAppId", "someEnv", "someCluster",
"someNamespace", true, true);

assertSame(legacyService.lastNamespaceResult, result);
assertEquals(true, legacyService.lastFillItemDetail);
}

@Test
public void testGetNamespacesDefaultBridgeDelegatesToLegacyMethod() {
LegacyNamespaceOpenApiService legacyService = new LegacyNamespaceOpenApiService();

List<OpenNamespaceDTO> result = legacyService.getNamespaces("someAppId", "someEnv",
"someCluster", false, true);

assertSame(legacyService.lastNamespacesResult, result);
assertEquals(false, legacyService.lastFillItemDetail);
}

/**
* A minimal stand-in for an implementation written before the {@code extendInfo} overloads
* existed: it only overrides the {@code fillItemDetail} methods that were abstract prior to
* 2.6.0, and never touches {@code extendInfo} at all.
*/
private static class LegacyNamespaceOpenApiService implements NamespaceOpenApiService {

private final OpenNamespaceDTO lastNamespaceResult = new OpenNamespaceDTO();
private final List<OpenNamespaceDTO> lastNamespacesResult = Collections.emptyList();
private boolean lastFillItemDetail;

@Override
public OpenNamespaceDTO getNamespace(String appId, String env, String clusterName,
String namespaceName, boolean fillItemDetail) {
this.lastFillItemDetail = fillItemDetail;
return lastNamespaceResult;
}

@Override
public List<OpenNamespaceDTO> getNamespaces(String appId, String env, String clusterName,
boolean fillItemDetail) {
this.lastFillItemDetail = fillItemDetail;
return lastNamespacesResult;
}

@Override
public OpenAppNamespaceDTO createAppNamespace(OpenAppNamespaceDTO appNamespaceDTO) {
throw new UnsupportedOperationException();
}

@Override
public OpenNamespaceLockDTO getNamespaceLock(String appId, String env, String clusterName,
String namespaceName) {
throw new UnsupportedOperationException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,49 @@ public void shouldUseDefaultClusterAndNamespace() throws Exception {
assertEquals("GET", request.method);
assertEquals("/openapi/v1/envs/DEV/apps/SampleApp/clusters/default/namespaces/application",
request.path);
assertEquals("fillItemDetail=true", request.query);
assertEquals("fillItemDetail=true&extendInfo=false", request.query);
assertEquals("namespace-token", request.authorization);
}

@Test
public void shouldPassExtendInfoFlagAndParseItForGetNamespace() throws Exception {
handler.mock("GET", "/openapi/v1/envs/DEV/apps/SampleApp/clusters/default/namespaces/application",
200,
"{\"appId\":\"SampleApp\",\"clusterName\":\"default\",\"namespaceName\":\"application\","
+ "\"extendInfo\":{\"parentAppId\":\"public-app\",\"isConfigHidden\":true,\"itemModifiedCnt\":3}}");
ApolloOpenApiClient client = newClient("namespace-extend-token");

OpenNamespaceDTO namespaceDTO = client
.getNamespace("SampleApp", "DEV", null, null, true, true);
CapturedRequest request = handler.awaitRequest(5, TimeUnit.SECONDS);

assertEquals("fillItemDetail=true&extendInfo=true", request.query);
assertNotNull(namespaceDTO.getExtendInfo());
assertEquals("public-app", namespaceDTO.getExtendInfo().getParentAppId());
assertEquals(Boolean.TRUE, namespaceDTO.getExtendInfo().getIsConfigHidden());
assertEquals(3, namespaceDTO.getExtendInfo().getItemModifiedCnt().intValue());
}

@Test
public void shouldPassExtendInfoFlagAndParseItForGetNamespaces() throws Exception {
handler.mock("GET", "/openapi/v1/envs/DEV/apps/SampleApp/clusters/default/namespaces",
200,
"[{\"appId\":\"SampleApp\",\"clusterName\":\"default\",\"namespaceName\":\"application\","
+ "\"extendInfo\":{\"parentAppId\":\"public-app\",\"isConfigHidden\":false,\"itemModifiedCnt\":1}}]");
ApolloOpenApiClient client = newClient("namespaces-extend-token");

List<OpenNamespaceDTO> namespaceDTOs = client
.getNamespaces("SampleApp", "DEV", "default", true, true);
CapturedRequest request = handler.awaitRequest(5, TimeUnit.SECONDS);

assertEquals("fillItemDetail=true&extendInfo=true", request.query);
assertEquals(1, namespaceDTOs.size());
assertNotNull(namespaceDTOs.get(0).getExtendInfo());
assertEquals("public-app", namespaceDTOs.get(0).getExtendInfo().getParentAppId());
assertEquals(Boolean.FALSE, namespaceDTOs.get(0).getExtendInfo().getIsConfigHidden());
assertEquals(1, namespaceDTOs.get(0).getExtendInfo().getItemModifiedCnt().intValue());
}

@Test
public void shouldParseOrganizations() throws Exception {
handler.mock("GET", "/openapi/v1/organizations", 200,
Expand Down
Loading
Loading