From aaa356199515fd53265e1d61db1156f6b876e282 Mon Sep 17 00:00:00 2001 From: mghio <43461943+mghio@users.noreply.github.com> Date: Sun, 24 Jul 2022 09:06:53 +0800 Subject: [PATCH] feature(openapi): Add a new API to load items with pagination (#4468) --- CHANGES.md | 1 + .../controller/ItemController.java | 15 +++++ .../apollo/biz/repository/ItemRepository.java | 2 + .../apollo/biz/service/ItemService.java | 28 +++++---- .../framework/apollo/common/dto/PageDTO.java | 3 +- .../openapi/api/ItemOpenApiService.java | 5 ++ .../openapi/client/ApolloOpenApiClient.java | 18 +++--- .../service/AbstractOpenApiService.java | 8 +++ .../client/service/ItemOpenApiService.java | 39 ++++++++++++ .../apollo/openapi/dto/OpenPageDTO.java | 59 +++++++++++++++++++ .../service/ItemOpenApiServiceTest.java | 51 ++++++++++++++++ .../service/ServerItemOpenApiService.java | 12 ++++ .../openapi/v1/controller/ItemController.java | 34 ++++++++--- .../apollo/portal/api/AdminServiceAPI.java | 12 ++++ .../apollo/portal/service/ItemService.java | 11 ++-- docs/en/usage/apollo-open-api-platform.md | 41 +++++++++++++ docs/zh/usage/apollo-open-api-platform.md | 42 +++++++++++++ 17 files changed, 347 insertions(+), 34 deletions(-) create mode 100644 apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenPageDTO.java diff --git a/CHANGES.md b/CHANGES.md index fe43952a169..bbdeaa0d9e4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Apollo 2.1.0 * [Allow users to associate multiple public namespaces at a time](https://github.com/apolloconfig/apollo/pull/4437) * [Move apollo-demo, scripts/docker-quick-start and scripts/apollo-on-kubernetes out of main repository](https://github.com/apolloconfig/apollo/pull/4440) * [Add search key when comparing Configuration items](https://github.com/apolloconfig/apollo/pull/4459) +* [Add a new API to load items with pagination](https://github.com/apolloconfig/apollo/pull/4468) * [fix(#4474):'openjdk:8-jre-alpine' potentially causing wrong number of cpu cores](https://github.com/apolloconfig/apollo/pull/4475) ------------------ All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/11?closed=1) diff --git a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java index 5988a66224a..62297ceb941 100644 --- a/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java +++ b/apollo-adminservice/src/main/java/com/ctrip/framework/apollo/adminservice/controller/ItemController.java @@ -27,6 +27,7 @@ import com.ctrip.framework.apollo.biz.service.ReleaseService; import com.ctrip.framework.apollo.biz.utils.ConfigChangeContentBuilder; import com.ctrip.framework.apollo.common.dto.ItemDTO; +import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.exception.NotFoundException; import com.ctrip.framework.apollo.common.utils.BeanUtils; @@ -37,6 +38,9 @@ import java.util.List; import java.util.Objects; import java.util.stream.Collectors; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -236,4 +240,15 @@ public ItemDTO get(@PathVariable("appId") String appId, return BeanUtils.transform(ItemDTO.class, item); } + @GetMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items-with-page") + public PageDTO findItemsByNamespace(@PathVariable("appId") String appId, + @PathVariable("clusterName") String clusterName, + @PathVariable("namespaceName") String namespaceName, + Pageable pageable) { + Page itemPage = itemService.findItemsByNamespace(appId, clusterName, namespaceName, pageable); + + List itemDTOS = BeanUtils.batchTransform(ItemDTO.class, itemPage.getContent()); + return new PageDTO<>(itemDTOS, pageable, itemPage.getTotalElements()); + } + } diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java index 136bc269007..59781eda994 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/ItemRepository.java @@ -38,6 +38,8 @@ public interface ItemRepository extends PagingAndSortingRepository { List findByNamespaceIdAndDataChangeLastModifiedTimeGreaterThan(Long namespaceId, Date date); Page findByKey(String key, Pageable pageable); + + Page findByNamespaceId(Long namespaceId, Pageable pageable); Item findFirst1ByNamespaceIdOrderByLineNumDesc(Long namespaceId); diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java index 9dc7aff01b3..7ffd427e9e9 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/ItemService.java @@ -80,20 +80,12 @@ public int batchDelete(long namespaceId, String operator) { } public Item findOne(String appId, String clusterName, String namespaceName, String key) { - Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); - if (namespace == null) { - throw new NotFoundException( - String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); - } + Namespace namespace = findNamespaceByAppIdAndClusterNameAndNamespaceName(appId, clusterName, namespaceName); return itemRepository.findByNamespaceIdAndKey(namespace.getId(), key); } public Item findLastOne(String appId, String clusterName, String namespaceName) { - Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); - if (namespace == null) { - throw new NotFoundException( - String.format("namespace not found for %s %s %s", appId, clusterName, namespaceName)); - } + Namespace namespace = findNamespaceByAppIdAndClusterNameAndNamespaceName(appId, clusterName, namespaceName); return findLastOne(namespace.getId()); } @@ -145,6 +137,11 @@ public Page findItemsByKey(String key, Pageable pageable) { return itemRepository.findByKey(key, pageable); } + public Page findItemsByNamespace(String appId, String clusterName, String namespaceName, Pageable pageable) { + Namespace namespace = findNamespaceByAppIdAndClusterNameAndNamespaceName(appId, clusterName, namespaceName); + return itemRepository.findByNamespaceId(namespace.getId(), pageable); + } + @Transactional public Item save(Item entity) { checkItemKeyLength(entity.getKey()); @@ -222,4 +219,15 @@ private int getItemValueLengthLimit(long namespaceId) { return bizConfig.itemValueLengthLimit(); } + private Namespace findNamespaceByAppIdAndClusterNameAndNamespaceName(String appId, + String clusterName, + String namespaceName) { + Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName); + if (namespace == null) { + throw new NotFoundException(String.format("namespace not found for appId:%s clusterName:%s namespaceName:%s", + appId, clusterName, namespaceName)); + } + return namespace; + } + } diff --git a/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java b/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java index a679a7f6f28..89e980bdee9 100644 --- a/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java +++ b/apollo-common/src/main/java/com/ctrip/framework/apollo/common/dto/PageDTO.java @@ -37,7 +37,6 @@ public PageDTO(List content, Pageable pageable, long total) { this.size = pageable.getPageSize(); } - public long getTotal() { return total; } @@ -54,7 +53,7 @@ public int getSize() { return size; } - public boolean hasContent(){ + public boolean hasContent() { return content != null && content.size() > 0; } } diff --git a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/api/ItemOpenApiService.java b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/api/ItemOpenApiService.java index b38b9e3f606..f063cd23814 100644 --- a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/api/ItemOpenApiService.java +++ b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/api/ItemOpenApiService.java @@ -17,6 +17,7 @@ package com.ctrip.framework.apollo.openapi.api; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; +import com.ctrip.framework.apollo.openapi.dto.OpenPageDTO; /** * @author wxq @@ -37,4 +38,8 @@ void createOrUpdateItem(String appId, String env, String clusterName, String nam void removeItem(String appId, String env, String clusterName, String namespaceName, String key, String operator); + + OpenPageDTO findItemsByNamespace(String appId, String env, String clusterName, + String namespaceName, int page, int size); + } diff --git a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClient.java b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClient.java index 057f8743d6e..a0688238a44 100644 --- a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClient.java +++ b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/ApolloOpenApiClient.java @@ -22,15 +22,7 @@ import com.ctrip.framework.apollo.openapi.client.service.ItemOpenApiService; import com.ctrip.framework.apollo.openapi.client.service.NamespaceOpenApiService; import com.ctrip.framework.apollo.openapi.client.service.ReleaseOpenApiService; -import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenAppDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenAppNamespaceDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenClusterDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenEnvClusterDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenNamespaceLockDTO; -import com.ctrip.framework.apollo.openapi.dto.OpenReleaseDTO; +import com.ctrip.framework.apollo.openapi.dto.*; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Lists; @@ -160,6 +152,14 @@ public OpenItemDTO getItem(String appId, String env, String clusterName, String return itemService.getItem(appId, env, clusterName, namespaceName, key); } + /** + * Paging get configs + */ + public OpenPageDTO findItemsByNamespace(String appId, String env, String clusterName, + String namespaceName, int page, int size) { + return itemService.findItemsByNamespace(appId, env, clusterName, namespaceName, page, size); + } + /** * Add config * @return the created config diff --git a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/AbstractOpenApiService.java b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/AbstractOpenApiService.java index d34d6d6f69e..811ee890a06 100644 --- a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/AbstractOpenApiService.java +++ b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/AbstractOpenApiService.java @@ -101,4 +101,12 @@ protected void checkNotEmpty(String value, String name) { Preconditions.checkArgument(!Strings.isNullOrEmpty(value), name + " should not be null or empty"); } + protected void checkPage(int page) { + Preconditions.checkArgument(page >= 0, "page should be positive or 0"); + } + + protected void checkSize(int size) { + Preconditions.checkArgument(size > 0, "size should be positive number"); + } + } diff --git a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiService.java b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiService.java index 815d7064943..de5a86a9a5d 100644 --- a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiService.java +++ b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiService.java @@ -20,15 +20,22 @@ import com.ctrip.framework.apollo.openapi.client.exception.ApolloOpenApiException; import com.ctrip.framework.apollo.openapi.client.url.OpenApiPathBuilder; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; +import com.ctrip.framework.apollo.openapi.dto.OpenPageDTO; import com.google.common.base.Strings; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; +import java.lang.reflect.Type; + public class ItemOpenApiService extends AbstractOpenApiService implements com.ctrip.framework.apollo.openapi.api.ItemOpenApiService { + private static final Type OPEN_PAGE_DTO_OPEN_ITEM_DTO_TYPE_REFERENCE = new TypeToken>() { + }.getType(); + public ItemOpenApiService(CloseableHttpClient client, String baseUrl, Gson gson) { super(client, baseUrl, gson); } @@ -189,4 +196,36 @@ public void removeItem(String appId, String env, String clusterName, String name } } + + @Override + public OpenPageDTO findItemsByNamespace(String appId, String env, String clusterName, + String namespaceName, int page, int size) { + if (Strings.isNullOrEmpty(clusterName)) { + clusterName = ConfigConsts.CLUSTER_NAME_DEFAULT; + } + if (Strings.isNullOrEmpty(namespaceName)) { + namespaceName = ConfigConsts.NAMESPACE_APPLICATION; + } + + checkNotEmpty(appId, "App id"); + checkNotEmpty(env, "Env"); + checkPage(page); + checkSize(size); + + OpenApiPathBuilder pathBuilder = OpenApiPathBuilder.newBuilder() + .envsPathVal(env) + .appsPathVal(appId) + .clustersPathVal(clusterName) + .namespacesPathVal(namespaceName) + .itemsPathVal("") + .addParam("page", page) + .addParam("size", size); + + try (CloseableHttpResponse response = get(pathBuilder)) { + return gson.fromJson(EntityUtils.toString(response.getEntity()), OPEN_PAGE_DTO_OPEN_ITEM_DTO_TYPE_REFERENCE); + } catch (Throwable ex) { + throw new RuntimeException(String.format("Paging get items: appId: %s, cluster: %s, namespace: %s in env: %s failed", + appId, clusterName, namespaceName, env), ex); + } + } } diff --git a/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenPageDTO.java b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenPageDTO.java new file mode 100644 index 00000000000..4b4678cbfaf --- /dev/null +++ b/apollo-openapi/src/main/java/com/ctrip/framework/apollo/openapi/dto/OpenPageDTO.java @@ -0,0 +1,59 @@ +/* + * 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; + +import java.util.Collections; +import java.util.List; + +/** + * @author mghio (mghio.dev@gmail.com) + */ +public class OpenPageDTO { + + private final int page; + private final int size; + private final long total; + private final List content; + + public OpenPageDTO(int page, int size, long total, List content) { + this.page = page; + this.size = size; + this.total = total; + this.content = Collections.unmodifiableList(content); + } + + public int getPage() { + return page; + } + + public int getSize() { + return size; + } + + public long getTotal() { + return total; + } + + public List getContent() { + return content; + } + + public boolean hasContent() { + return content != null && content.size() > 0; + } + +} diff --git a/apollo-openapi/src/test/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiServiceTest.java b/apollo-openapi/src/test/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiServiceTest.java index 4af762352f4..a65f8fff5f2 100644 --- a/apollo-openapi/src/test/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiServiceTest.java +++ b/apollo-openapi/src/test/java/com/ctrip/framework/apollo/openapi/client/service/ItemOpenApiServiceTest.java @@ -236,4 +236,55 @@ public void testRemoveItemWithError() throws Exception { itemOpenApiService.removeItem(someAppId, someEnv, someCluster, someNamespace, someKey, someOperator); } + + @Test + public void testFindItemsByNamespace() throws Exception { + final int page = 0; + final int size = 50; + final ArgumentCaptor request = ArgumentCaptor.forClass(HttpGet.class); + + itemOpenApiService.findItemsByNamespace(someAppId, someEnv, someCluster, someNamespace, page, size); + + verify(httpClient, times(1)).execute(request.capture()); + + HttpGet get = request.getValue(); + + assertEquals(String.format("%s/envs/%s/apps/%s/clusters/%s/namespaces/%s/items?size=%s&page=%s", + someBaseUrl, someEnv, someAppId, someCluster, someNamespace, size, page), get.getURI().toString()); + } + + @Test(expected = RuntimeException.class) + public void testFindItemsByNamespaceWithError() { + final int page = 0; + final int size = 50; + + when(statusLine.getStatusCode()).thenReturn(400); + + itemOpenApiService.findItemsByNamespace(someAppId, someEnv, someCluster, someNamespace, page, size); + } + + @Test(expected = IllegalArgumentException.class) + public void testFindItemsByNamespaceWithPageNegativeError() { + final int page = -1; + final int size = 50; + + itemOpenApiService.findItemsByNamespace(someAppId, someEnv, someCluster, someNamespace, page, size); + } + + @Test(expected = IllegalArgumentException.class) + public void testFindItemsByNamespaceWithSizeNegativeError() { + final int page = 0; + final int size = -50; + + itemOpenApiService.findItemsByNamespace(someAppId, someEnv, someCluster, someNamespace, page, size); + } + + @Test(expected = IllegalArgumentException.class) + public void testFindItemsByNamespaceWithPageAndSizeAllNegativeError() { + final int page = -1; + final int size = -50; + + itemOpenApiService.findItemsByNamespace(someAppId, someEnv, someCluster, someNamespace, page, size); + } + } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/server/service/ServerItemOpenApiService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/server/service/ServerItemOpenApiService.java index 7c9a90847c4..11ab76651e3 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/server/service/ServerItemOpenApiService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/server/service/ServerItemOpenApiService.java @@ -17,8 +17,10 @@ package com.ctrip.framework.apollo.openapi.server.service; import com.ctrip.framework.apollo.common.dto.ItemDTO; +import com.ctrip.framework.apollo.common.dto.PageDTO; import com.ctrip.framework.apollo.openapi.api.ItemOpenApiService; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; +import com.ctrip.framework.apollo.openapi.dto.OpenPageDTO; import com.ctrip.framework.apollo.openapi.util.OpenApiBeanUtils; import com.ctrip.framework.apollo.portal.environment.Env; import com.ctrip.framework.apollo.portal.service.ItemService; @@ -99,4 +101,14 @@ public void removeItem(String appId, String env, String clusterName, String name ItemDTO toDeleteItem = this.itemService.loadItem(Env.valueOf(env), appId, clusterName, namespaceName, key); this.itemService.deleteItem(Env.valueOf(env), toDeleteItem.getId(), operator); } + + @Override + public OpenPageDTO findItemsByNamespace(String appId, String env, String clusterName, + String namespaceName, int page, int size) { + PageDTO commonOpenItemDTOPage = + this.itemService.findItemsByNamespace(appId, Env.valueOf(env), clusterName, namespaceName, page, size); + + return new OpenPageDTO<>(commonOpenItemDTOPage.getPage(), commonOpenItemDTOPage.getSize(), + commonOpenItemDTOPage.getTotal(), commonOpenItemDTOPage.getContent()); + } } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java index d04d82f807f..0a6a50895c5 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/openapi/v1/controller/ItemController.java @@ -19,13 +19,15 @@ import com.ctrip.framework.apollo.common.dto.ItemDTO; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.RequestPrecondition; -import com.ctrip.framework.apollo.openapi.api.ItemOpenApiService; -import com.ctrip.framework.apollo.portal.environment.Env; import com.ctrip.framework.apollo.core.utils.StringUtils; +import com.ctrip.framework.apollo.openapi.api.ItemOpenApiService; import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; +import com.ctrip.framework.apollo.openapi.dto.OpenPageDTO; +import com.ctrip.framework.apollo.portal.environment.Env; import com.ctrip.framework.apollo.portal.service.ItemService; import com.ctrip.framework.apollo.portal.spi.UserService; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -37,8 +39,11 @@ import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import javax.validation.constraints.Positive; +import javax.validation.constraints.PositiveOrZero; - +@Validated @RestController("openapiItemController") @RequestMapping("/openapi/v1/envs/{env}") public class ItemController { @@ -47,6 +52,8 @@ public class ItemController { private final UserService userService; private final ItemOpenApiService itemOpenApiService; + private static final int ITEM_COMMENT_MAX_LENGTH = 256; + public ItemController(final ItemService itemService, final UserService userService, ItemOpenApiService itemOpenApiService) { this.itemService = itemService; @@ -74,8 +81,8 @@ public OpenItemDTO createItem(@PathVariable String appId, @PathVariable String e throw new BadRequestException("User " + item.getDataChangeCreatedBy() + " doesn't exist!"); } - if(!StringUtils.isEmpty(item.getComment()) && item.getComment().length() > 256){ - throw new BadRequestException("Comment length should not exceed 256 characters"); + if (!StringUtils.isEmpty(item.getComment()) && item.getComment().length() > ITEM_COMMENT_MAX_LENGTH) { + throw new BadRequestException(String.format("Comment length should not exceed %s characters", ITEM_COMMENT_MAX_LENGTH)); } return this.itemOpenApiService.createItem(appId, env, clusterName, namespaceName, item); @@ -100,8 +107,8 @@ public void updateItem(@PathVariable String appId, @PathVariable String env, throw new BadRequestException("user(dataChangeLastModifiedBy) not exists"); } - if(!StringUtils.isEmpty(item.getComment()) && item.getComment().length() > 256){ - throw new BadRequestException("Comment length should not exceed 256 characters"); + if (!StringUtils.isEmpty(item.getComment()) && item.getComment().length() > ITEM_COMMENT_MAX_LENGTH) { + throw new BadRequestException(String.format("Comment length should not exceed %s characters", ITEM_COMMENT_MAX_LENGTH)); } if (createIfNotExists) { @@ -111,7 +118,6 @@ public void updateItem(@PathVariable String appId, @PathVariable String env, } } - @PreAuthorize(value = "@consumerPermissionValidator.hasModifyNamespacePermission(#request, #appId, #namespaceName, #env)") @DeleteMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}") public void deleteItem(@PathVariable String appId, @PathVariable String env, @@ -124,11 +130,21 @@ public void deleteItem(@PathVariable String appId, @PathVariable String env, } ItemDTO toDeleteItem = itemService.loadItem(Env.valueOf(env), appId, clusterName, namespaceName, key); - if (toDeleteItem == null){ + if (toDeleteItem == null) { throw new BadRequestException("item not exists"); } this.itemOpenApiService.removeItem(appId, env, clusterName, namespaceName, key, operator); } + @GetMapping(value = "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items") + public OpenPageDTO findItemsByNamespace(@PathVariable String appId, @PathVariable String env, + @PathVariable String clusterName, @PathVariable String namespaceName, + @Valid @PositiveOrZero(message = "page should be positive or 0") + @RequestParam(defaultValue = "0") int page, + @Valid @Positive(message = "size should be positive number") + @RequestParam(defaultValue = "50") int size) { + return this.itemOpenApiService.findItemsByNamespace(appId, env, clusterName, namespaceName, page, size); + } + } diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java index dc450453de1..9a586d557a8 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/api/AdminServiceAPI.java @@ -17,6 +17,7 @@ package com.ctrip.framework.apollo.portal.api; import com.ctrip.framework.apollo.common.dto.*; +import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; import com.ctrip.framework.apollo.portal.environment.Env; import com.google.common.base.Joiner; import org.springframework.boot.actuate.health.Health; @@ -164,6 +165,9 @@ public void deleteAppNamespace(Env env, String appId, String namespaceName, Stri @Service public static class ItemAPI extends API { + private final ParameterizedTypeReference> openItemPageDTO = + new ParameterizedTypeReference>() {}; + public List findItems(String appId, Env env, String clusterName, String namespaceName) { ItemDTO[] itemDTOs = restTemplate.get(env, "apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items", @@ -213,6 +217,14 @@ public void deleteItem(Env env, long itemId, String operator) { restTemplate.delete(env, "items/{itemId}?operator={operator}", itemId, operator); } + + public PageDTO findItemsByNamespace(String appId, Env env, String clusterName, + String namespaceName, int page, int size) { + ResponseEntity> entity = restTemplate.get(env, + "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items-with-page?page={page}&size={size}", + openItemPageDTO, appId, clusterName, namespaceName, page, size); + return entity.getBody(); + } } @Service diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java index 36072039fb8..e125bc11e7d 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ItemService.java @@ -18,13 +18,11 @@ import com.ctrip.framework.apollo.common.constants.GsonType; -import com.ctrip.framework.apollo.common.dto.ItemChangeSets; -import com.ctrip.framework.apollo.common.dto.ItemDTO; -import com.ctrip.framework.apollo.common.dto.NamespaceDTO; -import com.ctrip.framework.apollo.common.dto.ReleaseDTO; +import com.ctrip.framework.apollo.common.dto.*; import com.ctrip.framework.apollo.common.exception.BadRequestException; import com.ctrip.framework.apollo.common.utils.BeanUtils; import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; +import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI.ItemAPI; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI.NamespaceAPI; import com.ctrip.framework.apollo.portal.api.AdminServiceAPI.ReleaseAPI; @@ -268,6 +266,11 @@ public List compare(List comparedNamespaces, Lis return result; } + public PageDTO findItemsByNamespace(String appId, Env env, String clusterName, + String namespaceName, int page, int size) { + return itemAPI.findItemsByNamespace(appId, env, clusterName, namespaceName, page, size); + } + private long getNamespaceId(NamespaceIdentifier namespaceIdentifier) { String appId = namespaceIdentifier.getAppId(); String clusterName = namespaceIdentifier.getClusterName(); diff --git a/docs/en/usage/apollo-open-api-platform.md b/docs/en/usage/apollo-open-api-platform.md index c9ef7891db3..a287a9dc17c 100644 --- a/docs/en/usage/apollo-open-api-platform.md +++ b/docs/en/usage/apollo-open-api-platform.md @@ -563,6 +563,47 @@ This interface is the interface used to get whether the current namespace is loc * **Response Value** : None +##### 3.2.16 Get configuration items with pagination + +* **URL** : `http://{portal_address}/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items` +* **Method** : GET +* **Request Params** : + +| Parameter Name | Required | Type | Description | +|----------------|----------|------|--------------------------------------------| +| page | false | int | page number, starting from 0, default is 0 | +| size | false | int | records in each page, default is 50 | + +* **Response Sample** : + +``` json +{ + "content": [ + { + "key": "timeout", + "value": "3000", + "comment": "timeout", + "dataChangeCreatedBy": "mghio", + "dataChangeLastModifiedBy": "mghio", + "dataChangeCreatedTime": "2022-07-17T21:37:41.818+0800", + "dataChangeLastModifiedTime": "2022-07-17T21:37:41.818+0800" + }, + { + "key": "page.size", + "value": "200", + "comment": "page size", + "dataChangeCreatedBy": "mghio", + "dataChangeLastModifiedBy": "mghio", + "dataChangeCreatedTime": "2022-07-17T21:37:41.818+0800", + "dataChangeLastModifiedTime": "2022-07-17T21:37:41.818+0800" + } + ], + "page": 0, + "size": 50, + "total": 2 +} +``` + ### IV. Error code description Under normal circumstances, the Http status code returned by the interface is 200, the following lists the non-200 error code descriptions that Apollo will return. diff --git a/docs/zh/usage/apollo-open-api-platform.md b/docs/zh/usage/apollo-open-api-platform.md index 69fa57e22a7..a84e7e87e4b 100644 --- a/docs/zh/usage/apollo-open-api-platform.md +++ b/docs/zh/usage/apollo-open-api-platform.md @@ -101,6 +101,7 @@ namespaceName | 所管理的Namespace的名称,如果是非properties格式, - [3.2.13 发布 Namespace](#_3213-发布配置接口) - [3.2.14 获取 Namespace 最后一次发布的内容](#_3214-获取某个namespace当前生效的已发布配置接口) - [3.2.15 回滚 Namespace](#_3215-回滚已发布配置接口) +- [3.2.16 分页获取配置项](#_3216-分页获取配置项接口) ##### 3.2.1 获取App的环境,集群信息 @@ -566,6 +567,47 @@ operator | true | String | 删除配置的操作者,域账号 * **返回值** : 无 +##### 3.2.16 分页获取配置项接口 + +* **URL** : http://{portal_address}/openapi/v1/envs/{env}/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items +* **Method** : GET +* **Request Params** : + +参数名 | 必选 | 类型 | 说明 +--- |-------|-----| --- +page | false | int | 页码,从 0 开始,默认为 0 +size | false | int | 页大小,默认为 50 + +* **返回值Sample** : + +``` json +{ + "content": [ + { + "key": "timeout", + "value": "3000", + "comment": "超时时间", + "dataChangeCreatedBy": "mghio", + "dataChangeLastModifiedBy": "mghio", + "dataChangeCreatedTime": "2022-07-17T21:37:41.818+0800", + "dataChangeLastModifiedTime": "2022-07-17T21:37:41.818+0800" + }, + { + "key": "page.size", + "value": "200", + "comment": "页大小", + "dataChangeCreatedBy": "mghio", + "dataChangeLastModifiedBy": "mghio", + "dataChangeCreatedTime": "2022-07-17T21:37:41.818+0800", + "dataChangeLastModifiedTime": "2022-07-17T21:37:41.818+0800" + } + ], + "page": 0, + "size": 50, + "total": 2 +} +``` + ### 四、错误码说明 正常情况下,接口返回的Http状态码是200,下面列举了Apollo会返回的非200错误码说明。