From 841d1425974d40c5a677d31088b108a6619c1476 Mon Sep 17 00:00:00 2001 From: aias00 Date: Mon, 25 Nov 2024 17:36:05 +0800 Subject: [PATCH] [type:feature] namespace config import (#5771) * [type:feature] namespace config import * [type:feature] namespace config import export * [type:feature] namespace config import export * [type:feature] namespace config import export * [type:feature] namespace config import export * [type:feature] namespace import\export * [type:feature] namespace import\export * [type:feature] namespace import\export --- .../ConfigsExportImportController.java | 29 +- .../admin/mapper/DiscoveryHandlerMapper.java | 9 + .../admin/mapper/DiscoveryUpstreamMapper.java | 9 + .../mapper/NamespacePluginRelMapper.java | 4 +- .../admin/mapper/PluginHandleMapper.java | 10 + .../admin/mapper/ProxySelectorMapper.java | 8 + .../shenyu/admin/service/AppAuthService.java | 19 ++ .../shenyu/admin/service/ConfigsService.java | 19 ++ .../admin/service/DiscoveryService.java | 19 ++ .../service/DiscoveryUpstreamService.java | 18 ++ .../shenyu/admin/service/MetaDataService.java | 17 ++ .../admin/service/PluginHandleService.java | 9 + .../shenyu/admin/service/PluginService.java | 18 ++ .../admin/service/ProxySelectorService.java | 18 ++ .../shenyu/admin/service/RuleService.java | 18 ++ .../shenyu/admin/service/SelectorService.java | 17 ++ .../service/impl/AppAuthServiceImpl.java | 87 +++++- .../service/impl/ConfigsServiceImpl.java | 247 +++++++++++++++++- .../service/impl/DiscoveryServiceImpl.java | 103 +++++++- .../impl/DiscoveryUpstreamServiceImpl.java | 51 +++- .../service/impl/MetaDataServiceImpl.java | 43 ++- .../service/impl/PluginHandleServiceImpl.java | 14 +- .../admin/service/impl/PluginServiceImpl.java | 94 ++++++- .../impl/ProxySelectorServiceImpl.java | 48 +++- .../admin/service/impl/RuleServiceImpl.java | 52 +++- .../service/impl/SelectorServiceImpl.java | 59 ++++- .../mappers/discovery-handler-sqlmap.xml | 11 + .../mappers/discovery-upstream-sqlmap.xml | 7 + .../mappers/namespace-plugin-rel-sqlmap.xml | 14 +- .../mappers/plugin-handle-sqlmap.xml | 10 + .../mappers/proxy-selector-sqlmap.xml | 5 + .../ConfigsExportImportControllerTest.java | 4 +- 32 files changed, 1056 insertions(+), 34 deletions(-) diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java index 2898104f2f05..0967be80be6b 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java @@ -17,6 +17,7 @@ package org.apache.shenyu.admin.controller; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.shenyu.admin.aspect.annotation.RestApi; import org.apache.shenyu.admin.model.result.ShenyuAdminResult; @@ -83,6 +84,27 @@ public ResponseEntity exportConfigs(final HttpServletResponse response) return new ResponseEntity<>((byte[]) result.getData(), headers, HttpStatus.OK); } + /** + * Export all configs. + * + * @param namespace namespaceId + * @param response response + * @return the shenyu result + */ + @GetMapping("/exportByNamespace") + @RequiresPermissions("system:manager:exportConfig") + public ResponseEntity exportConfigsByNamespace(final String namespace, final HttpServletResponse response) { + ShenyuAdminResult result = configsService.configsExport(namespace); + if (!Objects.equals(CommonErrorCode.SUCCESSFUL, result.getCode())) { + throw new ShenyuException(result.getMessage()); + } + HttpHeaders headers = new HttpHeaders(); + String fileName = generateFileName(); + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); + headers.add("Content-Disposition", "attachment;filename=" + fileName); + return new ResponseEntity<>((byte[]) result.getData(), headers, HttpStatus.OK); + } + /** * generate export file name. * @@ -96,17 +118,18 @@ private String generateFileName() { /** * Import configs. * + * @param namespace namespace * @param file config file * @return shenyu admin result */ @PostMapping("/import") @RequiresPermissions("system:manager:importConfig") - public ShenyuAdminResult importConfigs(final MultipartFile file) { - if (Objects.isNull(file)) { + public ShenyuAdminResult importConfigs(final String namespace, final MultipartFile file) { + if (StringUtils.isBlank(namespace) || Objects.isNull(file)) { return ShenyuAdminResult.error(ShenyuResultMessage.PARAMETER_ERROR); } try { - ShenyuAdminResult importResult = configsService.configsImport(file.getBytes()); + ShenyuAdminResult importResult = configsService.configsImport(namespace, file.getBytes()); if (Objects.equals(CommonErrorCode.SUCCESSFUL, importResult.getCode())) { // sync data syncDataService.syncAll(DataEventTypeEnum.REFRESH); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java index d86e94a41eb0..52764fde0b35 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java @@ -23,6 +23,7 @@ import org.apache.shenyu.admin.validation.ExistProvider; import java.io.Serializable; +import java.util.Collection; import java.util.List; /** @@ -111,6 +112,14 @@ public interface DiscoveryHandlerMapper extends ExistProvider { */ List selectByDiscoveryId(@Param("discoveryId")String discoveryId); + /** + * selectByDiscoveryIds. + * + * @param discoveryIds discoveryIds + * @return DiscoveryHandlerDO list + */ + List selectByDiscoveryIds(@Param("discoveryIds")Collection discoveryIds); + /** * selectBySelectorId. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryUpstreamMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryUpstreamMapper.java index 019e7205c505..19d552edd102 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryUpstreamMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryUpstreamMapper.java @@ -69,6 +69,15 @@ public interface DiscoveryUpstreamMapper extends ExistProvider { */ List selectBySelectorId(@Param("selectorId") String selectorId); + + /** + * selectByNamespaceId. + * + * @param namespaceId namespaceId + * @return DiscoveryUpstreamDO list + */ + List selectByNamespaceId(String namespaceId); + /** * selectByDiscoveryHandlerId. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespacePluginRelMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespacePluginRelMapper.java index 60423c60ad50..69f69b071709 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespacePluginRelMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/NamespacePluginRelMapper.java @@ -153,9 +153,9 @@ public interface NamespacePluginRelMapper extends ExistProvider { * @return {@linkplain List} */ List selectAllByNamespaceId(String namespaceId); - + /** - * select all by namespaceId list. + * select all by namespaceIds. * * @param namespaceIds namespaceIds. * @return {@linkplain List} diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/PluginHandleMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/PluginHandleMapper.java index fe5ca7ed5590..66e292df6e54 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/PluginHandleMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/PluginHandleMapper.java @@ -24,6 +24,7 @@ import org.apache.shenyu.admin.validation.ExistProvider; import java.io.Serializable; +import java.util.Collection; import java.util.List; /** @@ -139,6 +140,15 @@ public interface PluginHandleMapper extends ExistProvider { */ List selectByPluginIdList(@Param("pluginIds") List pluginId); + + /** + * bach delete by idList. + * + * @param pluginIds a list of ids + * @return plugin handle list + */ + List selectByPluginIds(@Param("pluginIds") Collection pluginIds); + /** * delete string id. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/ProxySelectorMapper.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/ProxySelectorMapper.java index 6cfbbc05cb6a..17fff50f3080 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/ProxySelectorMapper.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/ProxySelectorMapper.java @@ -119,4 +119,12 @@ public interface ProxySelectorMapper extends ExistProvider { */ List selectAll(); + /** + * selectAllByNamespaceId. + * + * @param namespaceId namespaceId + * @return ProxySelectorDOList + */ + List selectByNamespaceId(String namespaceId); + } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java index ed3cf1a4942a..161f7c29601c 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/AppAuthService.java @@ -146,6 +146,14 @@ public interface AppAuthService extends PageService { */ List listAllData(); + /** + * List all vo list. + * + * @param namespace the namespace + * @return the vo list + */ + List listAllDataByNamespace(String namespace); + /** * Update app secret by app key shenyu result. * @@ -182,9 +190,20 @@ public interface AppAuthService extends PageService { /** * Import shenyu auth data. + * * @param authDataList app auth list * @return the config import result */ ConfigImportResult importData(List authDataList); + + /** + * Import shenyu auth data. + * + * @param namespace the namespace + * @param authDataList app auth list + * @return the config import result + */ + ConfigImportResult importData(String namespace, List authDataList); + } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ConfigsService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ConfigsService.java index d4980b0d3cf8..10647d256b05 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ConfigsService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ConfigsService.java @@ -26,15 +26,34 @@ public interface ConfigsService { /** * Export all configs. + * * @return shenyu admin result */ ShenyuAdminResult configsExport(); + + /** + * Export all configs. + * + * @param namespace namespace + * @return shenyu admin result + */ + ShenyuAdminResult configsExport(String namespace); /** * Import configs. + * * @param source configs * @return shenyu admin result */ ShenyuAdminResult configsImport(byte[] source); + /** + * Import configs. + * + * @param namespace namespace + * @param source configs + * @return shenyu admin result + */ + ShenyuAdminResult configsImport(String namespace, byte[] source); + } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java index 27cd7cfab394..1ffec289e115 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java @@ -86,10 +86,19 @@ public interface DiscoveryService { /** * list all vo. + * * @return discovery vo */ List listAllData(); + /** + * list all vo. + * + * @param namespaceId namespaceId + * @return discovery vo + */ + List listAllDataByNamespaceId(String namespaceId); + /** * findDiscoveryHandlerBySelectorId. * @@ -111,8 +120,18 @@ public interface DiscoveryService { /** * Import discovery data list. + * * @param discoveryList the discovery data * @return config import result */ ConfigImportResult importData(List discoveryList); + + /** + * Import discovery data list. + * + * @param namespace the namespace + * @param discoveryList the discovery data + * @return config import result + */ + ConfigImportResult importData(String namespace, List discoveryList); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java index 27e1a8643e29..c9828c9627b2 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java @@ -75,6 +75,14 @@ public interface DiscoveryUpstreamService { */ List listAllData(); + /** + * list all data. + * + * @param namespaceId namespaceId + * @return DiscoveryUpstreamVO + */ + List listAllDataByNamespaceId(String namespaceId); + /** * refresh and push event. * @@ -111,8 +119,18 @@ public interface DiscoveryUpstreamService { /** * Import the discoveryUpstream data list. + * * @param discoveryUpstreamList the discoveryUpstream data * @return config import result */ ConfigImportResult importData(List discoveryUpstreamList); + + /** + * Import the discoveryUpstream data list. + * + * @param namespace the namespace + * @param discoveryUpstreamList the discoveryUpstream data + * @return config import result + */ + ConfigImportResult importData(String namespace, List discoveryUpstreamList); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java index 170b634e8593..39d06fc1a4b1 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/MetaDataService.java @@ -104,6 +104,14 @@ public interface MetaDataService { */ List listAllData(); + /** + * List all vo list. + * + * @param namespaceId the namespaceId + * @return the vo list + */ + List listAllDataByNamespaceId(String namespaceId); + /** * Enabled by ids and namespaceId. * @@ -160,4 +168,13 @@ public interface MetaDataService { * @return the config import result */ ConfigImportResult importData(List metaDataList); + + /** + * Import shenyu meta data. + * + * @param namespace the namespace + * @param metaDataList meta data list + * @return the config import result + */ + ConfigImportResult importData(String namespace, List metaDataList); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginHandleService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginHandleService.java index 1f6ad1832158..731809ee03b7 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginHandleService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginHandleService.java @@ -24,6 +24,7 @@ import org.apache.shenyu.admin.model.result.ShenyuAdminResult; import org.apache.shenyu.admin.model.vo.PluginHandleVO; +import java.util.Collection; import java.util.List; /** @@ -95,6 +96,14 @@ default Integer createOrUpdate(PluginHandleDTO pluginHandleDTO) { * @return plugin handle list. */ List listAllData(); + + /** + * find all plugin handle list by plugin ids. + * + * @param pluginIds the plugin ids + * @return plugin handle list. + */ + List listAllDataByPluginIds(Collection pluginIds); /** * import plugin handle list. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginService.java index 06966f3194c8..4ee3cc9f5f7a 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/PluginService.java @@ -94,6 +94,14 @@ public interface PluginService extends PageService listAllData(); + + /** + * List all vo list. + * + * @param namespaceId the namespace id + * @return the vo list + */ + List listAllDataByNamespaceId(String namespaceId); /** * list all not in resource. @@ -136,8 +144,18 @@ public interface PluginService extends PageService pluginList); + + /** + * import plugin data. + * + * @param namespace the namespace + * @param pluginList the plugin data + * @return config import result + */ + ConfigImportResult importData(String namespace, List pluginList); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ProxySelectorService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ProxySelectorService.java index 2b96d3010173..3a08798112e4 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ProxySelectorService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/ProxySelectorService.java @@ -83,6 +83,14 @@ public interface ProxySelectorService { */ List listAll(); + /** + * listAll. + * + * @param namespaceId namespaceId + * @return ProxySelectorDTOList + */ + List listAllByNamespaceId(String namespaceId); + /** * list all data. * @@ -92,8 +100,18 @@ public interface ProxySelectorService { /** * Import proxy selector list. + * * @param proxySelectorList proxy selector data list * @return config import result */ ConfigImportResult importData(List proxySelectorList); + + /** + * Import proxy selector list. + * + * @param namespace namespace + * @param proxySelectorList proxy selector data list + * @return config import result + */ + ConfigImportResult importData(String namespace, List proxySelectorList); } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/RuleService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/RuleService.java index e14bd23915eb..298db53b0b64 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/RuleService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/RuleService.java @@ -134,6 +134,14 @@ default int createOrUpdate(final RuleDTO ruleDTO) { */ List listAllData(); + /** + * List all rule vo list. + * + * @param namespaceId the namespaceId + * @return the rule vo list + */ + List listAllDataByNamespaceId(String namespaceId); + /** * Find by selector id list. * @@ -169,11 +177,21 @@ default int createOrUpdate(final RuleDTO ruleDTO) { /** * Import data. + * * @param ruleList rule list * @return config import result */ ConfigImportResult importData(List ruleList); + /** + * Import data. + * + * @param namespace namespace + * @param ruleList rule list + * @return config import result + */ + ConfigImportResult importData(String namespace, List ruleList); + /** * Enabled string by ids and namespaceId. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/SelectorService.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/SelectorService.java index 5cc4dc88ed06..7ef418676555 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/SelectorService.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/SelectorService.java @@ -239,6 +239,14 @@ default int createOrUpdate(SelectorDTO selectorDTO) { */ List listAllData(); + /** + * List all export vo list. + * + * @param namespaceId the namespaceId + * @return the vo list + */ + List listAllDataByNamespaceId(String namespaceId); + /** * Import the plugin selector list. * @@ -247,6 +255,15 @@ default int createOrUpdate(SelectorDTO selectorDTO) { */ ConfigImportResult importData(List selectorList); + /** + * Import the plugin selector list. + * + * @param namespace the namespace + * @param selectorList the plugin selector list + * @return config import result + */ + ConfigImportResult importData(String namespace, List selectorList); + /** * Enabled by ids and namespaceId. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java index 1b89e8dbaba7..ee5bcb6e08c3 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java @@ -328,8 +328,68 @@ public ConfigImportResult importData(final List authDataList) { } return ConfigImportResult.success(successCount); } - - + + @Override + public ConfigImportResult importData(final String namespace, final List authDataList) { + if (CollectionUtils.isEmpty(authDataList)) { + return ConfigImportResult.success(); + } + StringBuilder errorMsgBuilder = new StringBuilder(); + int successCount = 0; + // exist appKey set + Set existAppKeySet = Optional.of( + this.appAuthMapper.selectAllByNamespaceId(namespace) + .stream() + .filter(Objects::nonNull) + .map(AppAuthDO::getAppKey) + .collect(Collectors.toSet())) + .orElseGet(Sets::newHashSet); + + for (AppAuthDTO appAuth : authDataList) { + String appKey = appAuth.getAppKey(); + if (existAppKeySet.contains(appKey)) { + // already exists, just record fail info, and continue + LOG.info("import auth data, appKey: {} already exists", appKey); + errorMsgBuilder + .append(appKey) + .append(","); + continue; + } + AppAuthDO appAuthDO = AppAuthTransfer.INSTANCE.mapToEntity(appAuth); + // create + String authId = UUIDUtils.getInstance().generateShortUuid(); + appAuthDO.setId(authId); + int inserted = appAuthMapper.insertSelective(appAuthDO); + if (inserted > 0) { + successCount++; + // auth path + List authPathDTOList = appAuth.getAuthPathList(); + if (CollectionUtils.isNotEmpty(authPathDTOList)) { + List authPathDOS = authPathDTOList + .stream() + .map(param -> AuthPathDO.create(param.getPath(), authId, param.getAppName())) + .collect(Collectors.toList()); + authPathMapper.batchSave(authPathDOS); + } + + // auth param + List authParamVOList = appAuth.getAuthParamList(); + if (CollectionUtils.isNotEmpty(authParamVOList)) { + List authParamDOS = authParamVOList + .stream() + .map(param -> AuthParamDO.create(authId, param.getAppName(), param.getAppParam())) + .collect(Collectors.toList()); + authParamMapper.batchSave(authParamDOS); + } + } + } + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + return ConfigImportResult.fail(successCount, "import fail appKey: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + + /** * create or update application authority. * @@ -540,7 +600,28 @@ public List listAllData() { } ).collect(Collectors.toList()); } - + + @Override + public List listAllDataByNamespace(final String namespace) { + + List appAuthDOList = appAuthMapper.selectAllByNamespaceId(namespace); + if (CollectionUtils.isEmpty(appAuthDOList)) { + return new ArrayList<>(); + } + + List idList = appAuthDOList.stream().map(BaseDO::getId).collect(Collectors.toList()); + Map> paramMap = this.prepareAuthParamVO(idList); + Map> pathMap = this.prepareAuthPathVO(idList); + + return appAuthDOList.stream().map(data -> { + AppAuthVO vo = AppAuthTransfer.INSTANCE.mapToVO(data); + vo.setAuthParamList(paramMap.get(vo.getId())); + vo.setAuthPathList(pathMap.get(vo.getId())); + return vo; + } + ).collect(Collectors.toList()); + } + @Override public ShenyuAdminResult updateAppSecretByAppKey(final String appKey, final String appSecret) { return ShenyuAdminResult.success(appAuthMapper.updateAppSecretByAppKey(appKey, appSecret)); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java index 7fb5dc0310ae..0b55842f5287 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java @@ -157,13 +157,45 @@ public ShenyuAdminResult configsExport() { return ShenyuAdminResult.success(ZipUtil.zip(zipItemList)); } - + + @Override + public ShenyuAdminResult configsExport(final String namespace) { + List zipItemList = Lists.newArrayList(); + + exportAuthData(namespace, zipItemList); + + exportMetadata(namespace, zipItemList); + + exportPluginData(namespace, zipItemList); + + exportSelectorData(namespace, zipItemList); + + exportRuleData(namespace, zipItemList); + + exportDictData(zipItemList); + + exportProxySelectorData(namespace, zipItemList); + + exportDiscoveryData(namespace, zipItemList); + + exportDiscoveryUpstreamData(namespace, zipItemList); + + return ShenyuAdminResult.success(ZipUtil.zip(zipItemList)); + } + private void exportDiscoveryUpstreamData(final List zipItemList) { List discoveryUpstreamList = discoveryUpstreamService.listAllData(); if (CollectionUtils.isNotEmpty(discoveryUpstreamList)) { zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.DISCOVERY_UPSTREAM_JSON, JsonUtils.toJson(discoveryUpstreamList))); } } + + private void exportDiscoveryUpstreamData(final String namespace, final List zipItemList) { + List discoveryUpstreamList = discoveryUpstreamService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(discoveryUpstreamList)) { + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.DISCOVERY_UPSTREAM_JSON, JsonUtils.toJson(discoveryUpstreamList))); + } + } private void exportDiscoveryData(final List zipItemList) { List discoveryList = discoveryService.listAllData(); @@ -172,6 +204,14 @@ private void exportDiscoveryData(final List zipItemList) { } } + private void exportDiscoveryData(final String namespace, final List zipItemList) { + List discoveryList = discoveryService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(discoveryList)) { + discoveryList.forEach(discoveryVO -> discoveryVO.setNamespaceId(null)); + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.DISCOVERY_JSON, JsonUtils.toJson(discoveryList))); + } + } + private void exportProxySelectorData(final List zipItemList) { List proxySelectorDataList = proxySelectorService.listAll(); if (CollectionUtils.isNotEmpty(proxySelectorDataList)) { @@ -179,6 +219,14 @@ private void exportProxySelectorData(final List zipItemList) { } } + private void exportProxySelectorData(final String namespace, final List zipItemList) { + List proxySelectorDataList = proxySelectorService.listAllByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(proxySelectorDataList)) { + proxySelectorDataList.forEach(proxySelectorData -> proxySelectorData.setNamespaceId(null)); + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.PROXY_SELECTOR_JSON, JsonUtils.toJson(proxySelectorDataList))); + } + } + private void exportDictData(final List zipItemList) { List dictDataList = shenyuDictService.listAllData(); if (CollectionUtils.isNotEmpty(dictDataList)) { @@ -193,6 +241,13 @@ private void exportRuleData(final List zipItemList) { } } + private void exportRuleData(final String namespace, final List zipItemList) { + List ruleDataList = ruleService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(ruleDataList)) { + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.RULE_JSON, JsonUtils.toJson(ruleDataList))); + } + } + private void exportSelectorData(final List zipItemList) { List selectorDataList = selectorService.listAllData(); if (CollectionUtils.isNotEmpty(selectorDataList)) { @@ -200,6 +255,14 @@ private void exportSelectorData(final List zipItemList) { } } + private void exportSelectorData(final String namespace, final List zipItemList) { + List selectorDataList = selectorService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(selectorDataList)) { + selectorDataList.forEach(selectorVO -> selectorVO.setNamespaceId(null)); + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.SELECTOR_JSON, JsonUtils.toJson(selectorDataList))); + } + } + private void exportPluginData(final List zipItemList) { List pluginDataList = pluginService.listAllData(); if (CollectionUtils.isNotEmpty(pluginDataList)) { @@ -207,6 +270,13 @@ private void exportPluginData(final List zipItemList) { } } + private void exportPluginData(final String namespace, final List zipItemList) { + List pluginDataList = pluginService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(pluginDataList)) { + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.PLUGIN_JSON, JsonUtils.toJson(pluginDataList))); + } + } + private void exportMetadata(final List zipItemList) { List metaDataList = metaDataService.listAllData(); if (CollectionUtils.isNotEmpty(metaDataList)) { @@ -214,6 +284,14 @@ private void exportMetadata(final List zipItemList) { } } + private void exportMetadata(final String namespace, final List zipItemList) { + List metaDataList = metaDataService.listAllDataByNamespaceId(namespace); + if (CollectionUtils.isNotEmpty(metaDataList)) { + metaDataList.forEach(metaDataVO -> metaDataVO.setNamespaceId(null)); + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.META_JSON, JsonUtils.toJson(metaDataList))); + } + } + private void exportAuthData(final List zipItemList) { List authDataList = appAuthService.listAllData(); if (CollectionUtils.isNotEmpty(authDataList)) { @@ -221,6 +299,14 @@ private void exportAuthData(final List zipItemList) { } } + private void exportAuthData(final String namespace, final List zipItemList) { + List authDataList = appAuthService.listAllDataByNamespace(namespace); + if (CollectionUtils.isNotEmpty(authDataList)) { + authDataList.forEach(appAuthVO -> appAuthVO.setNamespaceId(null)); + zipItemList.add(new ZipUtil.ZipItem(ExportImportConstants.AUTH_JSON, JsonUtils.toJson(authDataList))); + } + } + @Override public ShenyuAdminResult configsImport(final byte[] source) { ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source); @@ -265,7 +351,52 @@ public ShenyuAdminResult configsImport(final byte[] source) { } return ShenyuAdminResult.success(result); } - + + @Override + public ShenyuAdminResult configsImport(final String namespace, final byte[] source) { + ZipUtil.UnZipResult unZipResult = ZipUtil.unzip(source); + List zipItemList = unZipResult.getZipItemList(); + if (CollectionUtils.isEmpty(zipItemList)) { + LOG.info("import file is empty"); + return ShenyuAdminResult.success(); + } + Map result = Maps.newHashMap(); + for (ZipUtil.ZipItem zipItem : zipItemList) { + switch (zipItem.getItemName()) { + case ExportImportConstants.AUTH_JSON: + importAuthData(namespace, result, zipItem); + break; + case ExportImportConstants.META_JSON: + importMetaData(namespace, result, zipItem); + break; + case ExportImportConstants.PLUGIN_JSON: + importPluginData(namespace, result, zipItem); + break; + case ExportImportConstants.SELECTOR_JSON: + importSelectorData(namespace, result, zipItem); + break; + case ExportImportConstants.RULE_JSON: + importRuleData(namespace, result, zipItem); + break; + case ExportImportConstants.DICT_JSON: + importDictData(result, zipItem); + break; + case ExportImportConstants.PROXY_SELECTOR_JSON: + importProxySelectorData(namespace, result, zipItem); + break; + case ExportImportConstants.DISCOVERY_JSON: + importDiscoveryData(namespace, result, zipItem); + break; + case ExportImportConstants.DISCOVERY_UPSTREAM_JSON: + importDiscoveryUpstreamData(namespace, result, zipItem); + break; + default: + break; + } + } + return ShenyuAdminResult.success(result); + } + private void importDiscoveryUpstreamData(final Map result, final ZipUtil.ZipItem zipItem) { String discoveryUpstreamJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(discoveryUpstreamJson)) { @@ -277,6 +408,20 @@ private void importDiscoveryUpstreamData(final Map result, final } } } + + private void importDiscoveryUpstreamData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String discoveryUpstreamJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(discoveryUpstreamJson)) { + List discoveryUpstreamList = GsonUtils.getInstance().fromList(discoveryUpstreamJson, DiscoveryUpstreamDTO.class); + // set namespaceId + discoveryUpstreamList.forEach(discoveryUpstreamDTO -> discoveryUpstreamDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = discoveryUpstreamService.importData(namespace, discoveryUpstreamList); + result.put(ExportImportConstants.DISCOVERY_UPSTREAM_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.DISCOVERY_UPSTREAM_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } private void importDiscoveryData(final Map result, final ZipUtil.ZipItem zipItem) { String discoveryJson = zipItem.getItemData(); @@ -290,6 +435,20 @@ private void importDiscoveryData(final Map result, final ZipUtil } } + private void importDiscoveryData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String discoveryJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(discoveryJson)) { + List discoveryList = GsonUtils.getInstance().fromList(discoveryJson, DiscoveryDTO.class); + // set namespaceId + discoveryList.forEach(discoveryDTO -> discoveryDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = discoveryService.importData(namespace, discoveryList); + result.put(ExportImportConstants.DISCOVERY_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.DISCOVERY_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importProxySelectorData(final Map result, final ZipUtil.ZipItem zipItem) { String proxySelectorJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(proxySelectorJson)) { @@ -302,6 +461,20 @@ private void importProxySelectorData(final Map result, final Zip } } + private void importProxySelectorData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String proxySelectorJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(proxySelectorJson)) { + List proxySelectorList = GsonUtils.getInstance().fromList(proxySelectorJson, ProxySelectorData.class); + // set namespaceId + proxySelectorList.forEach(proxySelectorData -> proxySelectorData.setNamespaceId(namespace)); + ConfigImportResult configImportResult = proxySelectorService.importData(namespace, proxySelectorList); + result.put(ExportImportConstants.PROXY_SELECTOR_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.PROXY_SELECTOR_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importDictData(final Map result, final ZipUtil.ZipItem zipItem) { String dictJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(dictJson)) { @@ -326,6 +499,20 @@ private void importRuleData(final Map result, final ZipUtil.ZipI } } + private void importRuleData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String ruleJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(ruleJson)) { + List ruleList = GsonUtils.getInstance().fromList(ruleJson, RuleDTO.class); + // set namespaceId + ruleList.forEach(ruleDTO -> ruleDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = ruleService.importData(namespace, ruleList); + result.put(ExportImportConstants.RULE_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.RULE_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importSelectorData(final Map result, final ZipUtil.ZipItem zipItem) { String selectorJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(selectorJson)) { @@ -338,6 +525,20 @@ private void importSelectorData(final Map result, final ZipUtil. } } + private void importSelectorData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String selectorJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(selectorJson)) { + List selectorList = GsonUtils.getInstance().fromList(selectorJson, SelectorDTO.class); + // set namespaceId + selectorList.forEach(selectorDTO -> selectorDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = selectorService.importData(namespace, selectorList); + result.put(ExportImportConstants.SELECTOR_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.SELECTOR_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importPluginData(final Map result, final ZipUtil.ZipItem zipItem) { String pluginJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(pluginJson)) { @@ -350,6 +551,20 @@ private void importPluginData(final Map result, final ZipUtil.Zi } } + private void importPluginData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String pluginJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(pluginJson)) { + List pluginList = GsonUtils.getInstance().fromList(pluginJson, PluginDTO.class); + // set namespaceId + pluginList.forEach(pluginDTO -> pluginDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = pluginService.importData(pluginList); + result.put(ExportImportConstants.PLUGIN_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.PLUGIN_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importMetaData(final Map result, final ZipUtil.ZipItem zipItem) { String metaJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(metaJson)) { @@ -362,6 +577,20 @@ private void importMetaData(final Map result, final ZipUtil.ZipI } } + private void importMetaData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String metaJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(metaJson)) { + List metaDataList = GsonUtils.getInstance().fromList(metaJson, MetaDataDTO.class); + // set namespaceId + metaDataList.forEach(metaDataDTO -> metaDataDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = metaDataService.importData(namespace, metaDataList); + result.put(ExportImportConstants.META_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.META_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } + private void importAuthData(final Map result, final ZipUtil.ZipItem zipItem) { String authJson = zipItem.getItemData(); if (StringUtils.isNotEmpty(authJson)) { @@ -373,4 +602,18 @@ private void importAuthData(final Map result, final ZipUtil.ZipI } } } + + private void importAuthData(final String namespace, final Map result, final ZipUtil.ZipItem zipItem) { + String authJson = zipItem.getItemData(); + if (StringUtils.isNotEmpty(authJson)) { + List authDataList = GsonUtils.getInstance().fromList(authJson, AppAuthDTO.class); + // set namespaceId + authDataList.forEach(appAuthDTO -> appAuthDTO.setNamespaceId(namespace)); + ConfigImportResult configImportResult = appAuthService.importData(namespace, authDataList); + result.put(ExportImportConstants.AUTH_IMPORT_SUCCESS_COUNT, configImportResult.getSuccessCount()); + if (StringUtils.isNotEmpty(configImportResult.getFailMessage())) { + result.put(ExportImportConstants.AUTH_IMPORT_FAIL_MESSAGE, configImportResult.getFailMessage()); + } + } + } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java index 7983c94ceecf..24cc2a7019b8 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java @@ -18,6 +18,7 @@ package org.apache.shenyu.admin.service.impl; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shenyu.admin.discovery.DiscoveryLevel; @@ -309,7 +310,50 @@ public List listAllData() { }) .collect(Collectors.toList()); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + List discoveryDOList = discoveryMapper + .selectAllByNamespaceId(namespaceId); + if (CollectionUtils.isEmpty(discoveryDOList)) { + return Lists.newArrayList(); + } + + Set discoveryIdSet = discoveryDOList.stream().map(DiscoveryDO::getId).collect(Collectors.toSet()); + + List discoveryHandlerDOList = discoveryHandlerMapper + .selectByDiscoveryIds(Lists.newArrayList(discoveryIdSet)); + + Map discoveryHandlerMap = Maps.newHashMap(); + Map discoveryRelMap = Maps.newHashMap(); + if (CollectionUtils.isNotEmpty(discoveryHandlerDOList)) { + discoveryHandlerMap = discoveryHandlerDOList + .stream() + .map(DiscoveryTransfer.INSTANCE::mapToVo) + .collect(Collectors.toMap(DiscoveryHandlerVO::getDiscoveryId, x -> x)); + discoveryRelMap = discoveryRelMapper + .selectAll() + .stream() + .map(DiscoveryTransfer.INSTANCE::mapToVo) + .collect(Collectors.toMap(DiscoveryRelVO::getDiscoveryHandlerId, x -> x)); + } + final Map finalDiscoveryHandlerMap = discoveryHandlerMap; + final Map finalDiscoveryRelMap = discoveryRelMap; + return discoveryDOList + .stream() + .map(x -> { + DiscoveryVO discoveryVO = DiscoveryTransfer.INSTANCE.mapToVo(x); + DiscoveryHandlerVO discoveryHandlerVO = finalDiscoveryHandlerMap.getOrDefault(discoveryVO.getId(), new DiscoveryHandlerVO()); + discoveryVO.setDiscoveryHandler(discoveryHandlerVO); + if (StringUtils.isNotEmpty(discoveryHandlerVO.getId())) { + DiscoveryRelVO discoveryRelVO = finalDiscoveryRelMap.getOrDefault(discoveryHandlerVO.getId(), new DiscoveryRelVO()); + discoveryVO.setDiscoveryRel(discoveryRelVO); + } + return discoveryVO; + }) + .collect(Collectors.toList()); + } + @Override public DiscoveryHandlerDTO findDiscoveryHandlerBySelectorId(final String selectorId) { DiscoveryHandlerDO discoveryHandlerDO = discoveryHandlerMapper.selectBySelectorId(selectorId); @@ -405,4 +449,61 @@ public ConfigImportResult importData(final List discoveryList) { } return ConfigImportResult.success(successCount); } + + @Override + public ConfigImportResult importData(final String namespace, final List discoveryList) { + if (CollectionUtils.isEmpty(discoveryList)) { + return ConfigImportResult.success(); + } + + Map> pluginDiscoveryMap = discoveryMapper + .selectAllByNamespaceId(namespace) + .stream() + .collect(Collectors.groupingBy(DiscoveryDO::getPluginName)); + int successCount = 0; + StringBuilder errorMsgBuilder = new StringBuilder(); + for (DiscoveryDTO discoveryDTO : discoveryList) { + String pluginName = discoveryDTO.getPluginName(); + String discoveryName = discoveryDTO.getName(); + Set existDiscoveryNameSet = pluginDiscoveryMap + .getOrDefault(pluginName, Lists.newArrayList()) + .stream() + .map(DiscoveryDO::getName) + .collect(Collectors.toSet()); + if (existDiscoveryNameSet.contains(discoveryName)) { + errorMsgBuilder + .append(discoveryName) + .append(","); + continue; + } + String discoveryId = UUIDUtils.getInstance().generateShortUuid(); + discoveryDTO.setId(discoveryId); + create(discoveryDTO); + successCount++; + + // import discovery handler data + if (null != discoveryDTO.getDiscoveryHandler()) { + DiscoveryHandlerDO discoveryHandlerDO = DiscoveryTransfer + .INSTANCE + .mapToDO(discoveryDTO.getDiscoveryHandler()); + discoveryHandlerDO.setDiscoveryId(discoveryId); + discoveryHandlerMapper.insertSelective(discoveryHandlerDO); + } + + // import discovery rel data + if (null != discoveryDTO.getDiscoveryRel()) { + DiscoveryRelDO discoveryRelDO = DiscoveryTransfer + .INSTANCE + .mapToDO(discoveryDTO.getDiscoveryRel()); + discoveryRelMapper.insertSelective(discoveryRelDO); + } + } + + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail discovery: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java index dbe2eb8595ca..73789d900922 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java @@ -177,7 +177,16 @@ public List listAllData() { .map(DiscoveryTransfer.INSTANCE::mapToVo) .collect(Collectors.toList()); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + return discoveryUpstreamMapper + .selectByNamespaceId(namespaceId) + .stream() + .map(DiscoveryTransfer.INSTANCE::mapToVo) + .collect(Collectors.toList()); + } + @Override public void refreshBySelectorId(final String selectorId) { DiscoveryHandlerDO discoveryHandlerDO = discoveryHandlerMapper.selectBySelectorId(selectorId); @@ -278,7 +287,45 @@ public ConfigImportResult importData(final List discoveryU } return ConfigImportResult.success(successCount); } - + + @Override + public ConfigImportResult importData(final String namespace, final List discoveryUpstreamList) { + if (CollectionUtils.isEmpty(discoveryUpstreamList)) { + return ConfigImportResult.success(); + } + int successCount = 0; + StringBuilder errorMsgBuilder = new StringBuilder(); + Map> discoveryHandlerUpstreamMap = discoveryUpstreamMapper + .selectByNamespaceId(namespace) + .stream() + .collect(Collectors.groupingBy(DiscoveryUpstreamDO::getDiscoveryHandlerId)); + for (DiscoveryUpstreamDTO discoveryUpstreamDTO : discoveryUpstreamList) { + String discoveryHandlerId = discoveryUpstreamDTO.getDiscoveryHandlerId(); + String url = discoveryUpstreamDTO.getUrl(); + Set existsUpstreamUrlSet = discoveryHandlerUpstreamMap + .getOrDefault(discoveryHandlerId, Lists.newArrayList()) + .stream() + .map(DiscoveryUpstreamDO::getUrl) + .collect(Collectors.toSet()); + if (existsUpstreamUrlSet.contains(url)) { + errorMsgBuilder + .append(url) + .append(","); + continue; + } + discoveryUpstreamDTO.setId(null); + DiscoveryUpstreamDO discoveryUpstreamDO = DiscoveryUpstreamDO.buildDiscoveryUpstreamDO(discoveryUpstreamDTO); + discoveryUpstreamMapper.insert(discoveryUpstreamDO); + successCount++; + } + if (StringUtils.hasLength(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail discovery upstream: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + private void fetchAll(final String discoveryHandlerId) { List discoveryUpstreamDOS = discoveryUpstreamMapper.selectByDiscoveryHandlerId(discoveryHandlerId); DiscoveryHandlerDO discoveryHandlerDO = discoveryHandlerMapper.selectById(discoveryHandlerId); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java index fe245c218994..39eab5f28566 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java @@ -183,7 +183,12 @@ public List listAll() { public List listAllData() { return ListUtil.map(metaDataMapper.selectAll(), MetaDataTransfer.INSTANCE::mapToVO); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + return ListUtil.map(metaDataMapper.findAllByNamespaceId(namespaceId), MetaDataTransfer.INSTANCE::mapToVO); + } + @Override public MetaDataDO findByPathAndNamespaceId(final String path, final String namespaceId) { return metaDataMapper.findByPathAndNamespaceId(path, namespaceId); @@ -234,7 +239,41 @@ public ConfigImportResult importData(final List metaDataList) { } return ConfigImportResult.success(successCount); } - + + @Override + public ConfigImportResult importData(final String namespace, final List metaDataList) { + if (CollectionUtils.isEmpty(metaDataList)) { + return ConfigImportResult.success(); + } + Set existMetadataPathSet = Optional + .of(metaDataMapper.findAllByNamespaceId(namespace) + .stream() + .filter(Objects::nonNull) + .map(MetaDataDO::getPath) + .collect(Collectors.toSet())) + .orElseGet(Sets::newHashSet); + StringBuilder errorMsgBuilder = new StringBuilder(); + int successCount = 0; + for (MetaDataDTO metaDataDTO : metaDataList) { + String metaDataPath = metaDataDTO.getPath(); + if (existMetadataPathSet.contains(metaDataPath)) { + LOG.info("import metadata path: {} already exists", metaDataPath); + errorMsgBuilder + .append(metaDataPath) + .append(","); + continue; + } + create(metaDataDTO); + successCount++; + } + this.syncData(); + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult.fail(successCount, "import fail meta: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + private String create(final MetaDataDTO metaDataDTO) { Assert.isNull(metaDataMapper.pathExisted(metaDataDTO.getPath()), AdminConstants.DATA_PATH_IS_EXIST); MetaDataDO metaDataDO = MetaDataTransfer.INSTANCE.mapToEntity(metaDataDTO); diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginHandleServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginHandleServiceImpl.java index 528c4a9fbddf..d89cc87bec6d 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginHandleServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginHandleServiceImpl.java @@ -42,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -135,7 +136,16 @@ public List listAllData() { .build()); return buildPluginHandleVO(pluginHandleDOList); } - + + @Override + public List listAllDataByPluginIds(final Collection pluginIds) { + List pluginHandleDOList = pluginHandleMapper.selectByPluginIds(pluginIds); + if (CollectionUtils.isEmpty(pluginHandleDOList)) { + return Lists.newArrayList(); + } + return buildPluginHandleVO(pluginHandleDOList); + } + @Override @Transactional(rollbackFor = Exception.class) public ShenyuAdminResult importData(final List pluginHandleList) { @@ -173,7 +183,7 @@ public ShenyuAdminResult importData(final List pluginHandleList } return ShenyuAdminResult.success(); } - + /** * The associated Handle needs to be deleted synchronously. * diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginServiceImpl.java index de047f6d1d65..51acd2fc7f34 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/PluginServiceImpl.java @@ -18,13 +18,16 @@ package org.apache.shenyu.admin.service.impl; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shenyu.admin.aspect.annotation.Pageable; import org.apache.shenyu.admin.mapper.NamespacePluginRelMapper; import org.apache.shenyu.admin.mapper.PluginMapper; import org.apache.shenyu.admin.model.dto.PluginDTO; import org.apache.shenyu.admin.model.dto.PluginHandleDTO; +import org.apache.shenyu.admin.model.entity.NamespacePluginRelDO; import org.apache.shenyu.admin.model.entity.PluginDO; import org.apache.shenyu.admin.model.event.plugin.PluginCreatedEvent; import org.apache.shenyu.admin.model.page.CommonPager; @@ -231,7 +234,7 @@ public List listAllData() { .map(pluginDO -> { PluginVO exportVO = PluginVO.buildPluginVO(pluginDO); List pluginHandleList = Optional - .ofNullable(pluginHandleMap.get(exportVO.getId())) + .ofNullable(pluginHandleMap.getOrDefault(exportVO.getId(), Lists.newArrayList())) .orElse(Lists.newArrayList()) .stream() // to make less volume of export data @@ -241,7 +244,39 @@ public List listAllData() { return exportVO; }).collect(Collectors.toList()); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + List pluginRelDOList = namespacePluginRelMapper.listByNamespaceId(namespaceId); + if (CollectionUtils.isEmpty(pluginRelDOList)) { + return Lists.newArrayList(); + } + Set pluginIdSet = pluginRelDOList.stream().map(NamespacePluginRelDO::getPluginId).collect(Collectors.toSet()); + + List pluginDOList = pluginMapper.selectByIds(Lists.newArrayList(pluginIdSet)); + + // plugin handle + Map> pluginHandleMap = pluginHandleService.listAllDataByPluginIds(pluginIdSet) + .stream() + .collect(Collectors.groupingBy(PluginHandleVO::getPluginId)); + + return pluginDOList + .stream() + .filter(Objects::nonNull) + .map(pluginDO -> { + PluginVO exportVO = PluginVO.buildPluginVO(pluginDO); + List pluginHandleList = Optional + .ofNullable(pluginHandleMap.getOrDefault(exportVO.getId(), Lists.newArrayList())) + .orElse(Lists.newArrayList()) + .stream() + // to make less volume of export data + .peek(x -> x.setDictOptions(null)) + .collect(Collectors.toList()); + exportVO.setPluginHandleList(pluginHandleList); + return exportVO; + }).collect(Collectors.toList()); + } + @Override public List listAllNotInResource() { return ListUtil.map(pluginMapper.listAllNotInResource(), PluginTransfer.INSTANCE::mapToData); @@ -321,9 +356,60 @@ public ConfigImportResult importData(final List pluginList) { .fail(successCount, "import fail plugin: " + errorMsgBuilder); } return ConfigImportResult.success(successCount); - } - + + @Override + public ConfigImportResult importData(final String namespace, final List pluginList) { + if (CollectionUtils.isEmpty(pluginList)) { + return ConfigImportResult.success(); + } + List pluginRelDOList = namespacePluginRelMapper.listByNamespaceId(namespace); + Map existPluginMap = Maps.newHashMap(); + if (CollectionUtils.isNotEmpty(pluginRelDOList)) { + List pluginIds = pluginRelDOList.stream().map(NamespacePluginRelDO::getPluginId).distinct().collect(Collectors.toList()); + existPluginMap = pluginMapper.selectByIds(pluginIds) + .stream() + .filter(Objects::nonNull) + .collect(Collectors.toMap(PluginDO::getName, x -> x)); + } + StringBuilder errorMsgBuilder = new StringBuilder(); + int successCount = 0; + for (PluginDTO pluginDTO : pluginList) { + String pluginName = pluginDTO.getName(); + String pluginId; + // check plugin base info + if (MapUtils.isNotEmpty(existPluginMap) && existPluginMap.containsKey(pluginName)) { + PluginDO existPlugin = existPluginMap.get(pluginName); + pluginId = existPlugin.getId(); + errorMsgBuilder + .append(pluginName) + .append(","); + } else { + PluginDO pluginDO = PluginDO.buildPluginDO(pluginDTO); + pluginId = pluginDO.getId(); + if (pluginMapper.insertSelective(pluginDO) > 0) { + // publish create event. init plugin data + successCount++; + } + } + // check and import plugin handle + List pluginHandleList = pluginDTO.getPluginHandleList(); + if (CollectionUtils.isNotEmpty(pluginHandleList)) { + pluginHandleService + .importData(pluginHandleList + .stream() + .peek(x -> x.setPluginId(pluginId)) + .collect(Collectors.toList())); + } + } + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail plugin: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + /** * create plugin.
* insert plugin and insert plugin data. diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java index 2b390527f025..df7e5aaaf469 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java @@ -417,7 +417,13 @@ public List listAll() { return proxySelectorMapper.selectAll().stream() .map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList()); } - + + @Override + public List listAllByNamespaceId(final String namespaceId) { + return proxySelectorMapper.selectByNamespaceId(namespaceId).stream() + .map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList()); + } + @Override public List listAllData() { List result = Lists.newArrayList(); @@ -490,4 +496,44 @@ public ConfigImportResult importData(final List proxySelector } return ConfigImportResult.success(successCount); } + + @Override + public ConfigImportResult importData(final String namespace, final List proxySelectorList) { + if (CollectionUtils.isEmpty(proxySelectorList)) { + return ConfigImportResult.success(); + } + // TODO namespace + Map> pluginProxySelectorMap = proxySelectorMapper + .selectAll() + .stream() + .collect(Collectors.groupingBy(ProxySelectorDO::getPluginName)); + int successCount = 0; + StringBuilder errorMsgBuilder = new StringBuilder(); + for (ProxySelectorData selectorData : proxySelectorList) { + String pluginName = selectorData.getPluginName(); + String proxySelectorName = selectorData.getName(); + Set existProxySelectorNameSet = pluginProxySelectorMap + .getOrDefault(pluginName, Lists.newArrayList()) + .stream() + .map(ProxySelectorDO::getName) + .collect(Collectors.toSet()); + + if (existProxySelectorNameSet.contains(proxySelectorName)) { + errorMsgBuilder + .append(proxySelectorName) + .append(","); + continue; + } + ProxySelectorDO proxySelectorDO = ProxySelectorDO.buildProxySelectorDO(selectorData); + if (proxySelectorMapper.insert(proxySelectorDO) > 0) { + successCount++; + } + } + if (StringUtils.hasLength(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail proxy selector: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } } diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java index 87ab73e1e5fc..aa012c07e054 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java @@ -231,7 +231,12 @@ public List listAllByNamespaceId(final String namespaceId) { public List listAllData() { return this.buildRuleVOList(ruleMapper.selectAll()); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + return this.buildRuleVOList(ruleMapper.selectAllByNamespaceId(namespaceId)); + } + @Override public List findBySelectorId(final String selectorId) { return this.buildRuleDataList(ruleMapper.findBySelectorId(selectorId)); @@ -295,7 +300,50 @@ public ConfigImportResult importData(final List ruleList) { } return ConfigImportResult.success(successCount); } - + + @Override + public ConfigImportResult importData(final String namespace, final List ruleList) { + if (CollectionUtils.isEmpty(ruleList)) { + return ConfigImportResult.success(); + } + + Map> selectorRuleMap = ruleMapper + .selectAllByNamespaceId(namespace) + .stream() + .collect(Collectors.groupingBy(RuleDO::getSelectorId)); + + int successCount = 0; + StringBuilder errorMsgBuilder = new StringBuilder(); + for (RuleDTO ruleDTO : ruleList) { + String selectorId = ruleDTO.getSelectorId(); + String ruleName = ruleDTO.getName(); + Set existRuleNameSet = selectorRuleMap + .getOrDefault(selectorId, Lists.newArrayList()) + .stream() + .map(RuleDO::getName) + .collect(Collectors.toSet()); + + if (existRuleNameSet.contains(ruleName)) { + errorMsgBuilder + .append(ruleName) + .append(","); + continue; + } + RuleDO ruleDO = RuleDO.buildRuleDO(ruleDTO); + final int ruleCount = ruleMapper.insertSelective(ruleDO); + addCondition(ruleDO, ruleDTO.getRuleConditions()); + if (ruleCount > 0) { + successCount++; + } + } + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail rule: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + @Override @Transactional(rollbackFor = Exception.class) public Boolean enabledByIdsAndNamespaceId(final List ids, final Boolean enabled, final String namespaceId) { diff --git a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java index de9d9894e50e..58d890a67ed7 100644 --- a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java +++ b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java @@ -435,7 +435,12 @@ public List listAllByNamespaceId(final String namespaceId) { public List listAllData() { return this.buildSelectorExportVOList(selectorMapper.selectAll()); } - + + @Override + public List listAllDataByNamespaceId(final String namespaceId) { + return this.buildSelectorExportVOList(selectorMapper.selectAllByNamespaceId(namespaceId)); + } + @Override @Transactional(rollbackFor = Exception.class) public ConfigImportResult importData(final List selectorList) { @@ -486,7 +491,57 @@ public ConfigImportResult importData(final List selectorList) { } return ConfigImportResult.success(successCount); } - + + @Override + public ConfigImportResult importData(final String namespace, final List selectorList) { + if (CollectionUtils.isEmpty(selectorList)) { + return ConfigImportResult.success(); + } + StringBuilder errorMsgBuilder = new StringBuilder(); + int successCount = 0; + Map> pluginSelectorMap = selectorMapper.selectAllByNamespaceId(namespace).stream() + .filter(Objects::nonNull) + .collect(Collectors.groupingBy(SelectorDO::getPluginId)); + + Map> importSelectorMap = selectorList.stream() + .collect(Collectors.groupingBy(SelectorDTO::getPluginId)); + + for (Map.Entry> selectorEntry : importSelectorMap.entrySet()) { + // the import selector's pluginId + String pluginId = selectorEntry.getKey(); + List selectorDTOList = selectorEntry.getValue(); + if (CollectionUtils.isNotEmpty(selectorDTOList)) { + + Set existSelectorSet = Optional + .ofNullable(pluginSelectorMap.get(pluginId)) + .orElseGet(Lists::newArrayList) + .stream() + .map(SelectorDO::getName) + .collect(Collectors.toSet()); + + for (SelectorDTO selectorDTO : selectorDTOList) { + // filter by selectorName + String selectorName = selectorDTO.getName(); + if (CollectionUtils.isNotEmpty(existSelectorSet) + && existSelectorSet.contains(selectorName)) { + errorMsgBuilder + .append(selectorName) + .append(","); + } else { + create(selectorDTO); + successCount++; + } + } + } + } + if (StringUtils.isNotEmpty(errorMsgBuilder)) { + errorMsgBuilder.setLength(errorMsgBuilder.length() - 1); + return ConfigImportResult + .fail(successCount, "import fail selector: " + errorMsgBuilder); + } + return ConfigImportResult.success(successCount); + } + @Override @Transactional(rollbackFor = Exception.class) public Boolean enabledByIdsAndNamespaceId(final List ids, final Boolean enabled, final String namespaceId) { diff --git a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml index a3f0a86cdc14..6cbb6a91d673 100644 --- a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml +++ b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml @@ -76,6 +76,17 @@ where discovery_id = #{discoveryId , jdbcType=LONGVARCHAR} + + + + SELECT du.id, diff --git a/shenyu-admin/src/main/resources/mappers/namespace-plugin-rel-sqlmap.xml b/shenyu-admin/src/main/resources/mappers/namespace-plugin-rel-sqlmap.xml index a85c8a3f3b90..6970e65898ec 100644 --- a/shenyu-admin/src/main/resources/mappers/namespace-plugin-rel-sqlmap.xml +++ b/shenyu-admin/src/main/resources/mappers/namespace-plugin-rel-sqlmap.xml @@ -70,13 +70,6 @@ #{namespacePluginRelDO.dateUpdated, jdbcType=TIMESTAMP}) - - + + UPDATE namespace_plugin_rel diff --git a/shenyu-admin/src/main/resources/mappers/plugin-handle-sqlmap.xml b/shenyu-admin/src/main/resources/mappers/plugin-handle-sqlmap.xml index 2369c90bc73c..125c31331708 100644 --- a/shenyu-admin/src/main/resources/mappers/plugin-handle-sqlmap.xml +++ b/shenyu-admin/src/main/resources/mappers/plugin-handle-sqlmap.xml @@ -270,6 +270,16 @@ + + + + DELETE FROM proxy_selector WHERE id IN diff --git a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigsExportImportControllerTest.java b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigsExportImportControllerTest.java index e16c1f9d5233..f14d42173ab7 100644 --- a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigsExportImportControllerTest.java +++ b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/ConfigsExportImportControllerTest.java @@ -42,6 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.core.Is.is; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart; @@ -103,7 +104,7 @@ public void testImportConfigs() throws Exception { // mock import data List zipItemList = Lists.newArrayList(); - when(this.configsService.configsImport(any())).thenReturn( + when(this.configsService.configsImport(anyString(), any())).thenReturn( ShenyuAdminResult.success(ShenyuResultMessage.SUCCESS)); // mock file @@ -111,6 +112,7 @@ public void testImportConfigs() throws Exception { // Run the test final MockHttpServletResponse response = mockMvc.perform(multipart("/configs/import") .file(file) + .param("namespace", "test") .accept(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.message", is(ShenyuResultMessage.SUCCESS))) .andExpect(status().isOk())