From e2da767d93802f2ba8079f28a71fe5031f19681b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=AA=E5=BD=B1oO?= Date: Thu, 18 Nov 2021 16:09:21 +0800 Subject: [PATCH] for release 0.4.0 (#849) * set branch protection * rat exclude ".asf.yaml" * add master-0.2.0 to branch protection * Exclude the".flattened-pom.xml" file into the source package (#799) * Update copyright year (#801) * fix NPE in ServiceTestUtil.java (#804) * polish dockerfile for 0.3.0 (#805) * update dockerfile and enable autotest * fix test script * fix zookeeper version * fix rat * develop-for-dubbo-3.x branch merge to develop branch (#808) * [3.0]Add mesh rule route (#789) * add mesh rule route * add mesh rule check * For #756 (#791) * [ISSUE #760]Application discover support (#807) * application discover support * fix checkstyle * fix ci * remove useless pom import,modify Chinese comment * fix UT bug Co-authored-by: haoyann <1064645534@qq.com> Co-authored-by: Aaron-boom <55744718+Aaron-boom@users.noreply.github.com> * Fix generic invoke fail (#810) * fix generic invoke fail * fix ci * Nacos support application discover (#812) * Fix generic can't invoke repeatedly (#814) * Reduce nacos mapping service storage (#817) * optimize some code for RegistryServerSync (#822) * Fix circular reference (#823) * Fix service version spell (#824) * For #756 (#815) * For #756 * for 830 (#832) * for 830 * For 830 * For 830 * For 830 * For 830 * For 830 * [Feature] Dubbo Admin provides service mock ability. (#838) * commit the API * develop the front page. * add edit logic * develop the front page and test. * ui change * change the config key and group * change rule enable to config center. * update GlobalMockRule update logic. * remove the GlobalMockRule * [feature admin mock] move the diver dependency out of the project. * [feature admin mock] remove the contributor name and date in javadoc. * [feature admin mock] optimize the delete mock rule step. * [feature admin mock] fix the dialog cannot be closed when delete successfully. * [feature admin mock] add the support for h2 database. * [feature admin mock] rollback to zookeeper registry. * [feature admin mock] fix properties. * [feature admin mock] change mock-admin-api maven version. * [feature admin mock] fix the feedback and add the parameters in docker-compose. * [feature admin mock] fix the ci problem. * [feature admin mock] fix the ci problem. * [feature admin mock] removed unused import. * [feature admin mock] add license. * GovernanceConfiguration use dubbo instead DynamicConfiguration (#840) * GovernanceConfiguration use dubbo instead DynamicConfiguration * remove useless change Co-authored-by: wuwen Co-authored-by: Huang YunKun Co-authored-by: haoyann <1064645534@qq.com> Co-authored-by: Aaron-boom <55744718+Aaron-boom@users.noreply.github.com> Co-authored-by: Wang Chengming <634749869@qq.com> Co-authored-by: brotherlu-xcq <1285823170@qq.com> --- .asf.yaml | 6 + NOTICE | 2 +- README.md | 2 +- README_ZH.md | 2 +- docker/0.3.0/Dockerfile | 11 +- docker/0.3.0/Dockerfile.test | 23 + docker/0.3.0/docker-compose.test.yml | 33 ++ docker/0.3.0/test.sh | 34 ++ docker/latest/Dockerfile | 2 +- docker/stack.yml | 15 +- dubbo-admin-distribution/src/NOTICE | 4 +- .../src/assembly/source-release.xml | 1 + .../src/bin/config/application.properties | 18 + dubbo-admin-distribution/src/bin/startup.cmd | 2 +- dubbo-admin-distribution/src/bin/startup.sh | 4 +- dubbo-admin-server/pom.xml | 52 ++- .../dubbo/admin/DubboAdminApplication.java | 7 +- .../InterceptorAuthentication.java | 34 ++ .../authentication/LoginAuthentication.java | 33 ++ .../authentication/impl/DefaultPreHandle.java | 66 +++ .../dubbo/admin/common/util/Constants.java | 6 +- .../admin/common/util/ServiceTestUtil.java | 15 +- .../admin/common/util/ServiceTestV3Util.java | 233 ++++++++++ .../dubbo/admin/common/util/SyncUtils.java | 23 +- .../dubbo/admin/common/util/YamlParser.java | 10 +- .../dubbo/admin/config/ConfigCenter.java | 52 ++- .../admin/controller/MeshRouteController.java | 110 +++++ .../admin/controller/MockRuleController.java | 62 +++ .../admin/controller/ServiceController.java | 18 +- .../controller/ServiceTestController.java | 31 +- .../admin/controller/UserController.java | 88 ++-- .../admin/interceptor/AuthInterceptor.java | 59 +-- .../dubbo/admin/mapper/MockRuleMapper.java | 28 ++ .../model/domain/FullServiceDefinition.java | 41 ++ .../admin/model/domain/MethodDefinition.java | 108 +++++ .../dubbo/admin/model/domain/MockRule.java | 98 ++++ .../dubbo/admin/model/domain/Provider.java | 10 + .../admin/model/domain/RegistrySource.java | 26 ++ .../admin/model/domain/ServiceDefinition.java | 133 ++++++ .../admin/model/domain/TypeDefinition.java | 161 +++++++ .../dubbo/admin/model/dto/MeshRouteDTO.java | 32 ++ .../dubbo/admin/model/dto/MockRuleDTO.java | 95 ++++ .../dubbo/admin/model/dto/ServiceDTO.java | 19 +- .../admin/model/dto/ServiceDetailDTO.java | 7 +- .../admin/model/store/mesh/BaseRule.java | 60 +++ .../model/store/mesh/VsDestinationGroup.java | 56 +++ .../destination/ConnectionPoolSettings.java | 22 + .../mesh/destination/DestinationRule.java | 41 ++ .../mesh/destination/DestinationRuleSpec.java | 60 +++ .../model/store/mesh/destination/Subset.java | 50 +++ .../store/mesh/destination/TCPSettings.java | 25 ++ .../store/mesh/destination/TcpKeepalive.java | 26 ++ .../store/mesh/destination/TrafficPolicy.java | 40 ++ .../loadbalance/ConsistentHashLB.java | 22 + .../loadbalance/LoadBalancerSettings.java | 48 ++ .../destination/loadbalance/SimpleLB.java | 26 ++ .../virtualservice/DubboMatchRequest.java | 131 ++++++ .../store/mesh/virtualservice/DubboRoute.java | 63 +++ .../mesh/virtualservice/DubboRouteDetail.java | 63 +++ .../virtualservice/VirtualServiceRule.java | 41 ++ .../virtualservice/VirtualServiceSpec.java | 50 +++ .../destination/DubboDestination.java | 59 +++ .../destination/DubboRouteDestination.java | 40 ++ .../mesh/virtualservice/match/BoolMatch.java | 38 ++ .../virtualservice/match/DoubleMatch.java | 63 +++ .../match/DoubleRangeMatch.java | 53 +++ .../match/DubboAttachmentMatch.java | 76 ++++ .../virtualservice/match/DubboMethodArg.java | 90 ++++ .../match/DubboMethodMatch.java | 128 ++++++ .../virtualservice/match/ListBoolMatch.java | 22 + .../virtualservice/match/ListDoubleMatch.java | 43 ++ .../virtualservice/match/ListStringMatch.java | 44 ++ .../virtualservice/match/StringMatch.java | 105 +++++ .../admin/provider/MockServiceProvider.java | 41 ++ .../config/GovernanceConfiguration.java | 7 +- .../config/impl/ApolloConfiguration.java | 160 ------- .../config/impl/ConsulConfiguration.java | 115 ----- .../impl/MultiDynamicConfiguration.java | 109 +++++ .../config/impl/NacosConfiguration.java | 199 --------- .../config/impl/NoOpConfiguration.java | 8 +- .../config/impl/ZookeeperConfiguration.java | 164 ------- .../mapping/AddressChangeListener.java | 32 ++ .../mapping/AdminMappingListener.java | 129 ++++++ .../AdminServiceInstancesChangedListener.java | 50 +++ .../registry/mapping/ServiceMapping.java | 36 ++ .../mapping/impl/NacosServiceMapping.java | 175 ++++++++ .../mapping/impl/NoOpServiceMapping.java | 40 ++ .../mapping/impl/ZookeeperServiceMapping.java | 93 ++++ .../dubbo/admin/service/MeshRouteService.java | 56 +++ .../dubbo/admin/service/MockRuleService.java | 63 +++ .../dubbo/admin/service/ProviderService.java | 39 +- .../dubbo/admin/service/RegistryCache.java | 48 ++ .../admin/service/RegistryServerSync.java | 54 ++- .../admin/service/impl/AbstractService.java | 7 +- .../service/impl/ConsumerServiceImpl.java | 8 +- .../service/impl/GenericServiceImpl.java | 3 +- .../service/impl/InstanceRegistryCache.java | 55 +++ .../impl/InstanceRegistryQueryHelper.java | 155 +++++++ .../service/impl/InterfaceRegistryCache.java | 51 +++ .../service/impl/ManagementServiceImpl.java | 3 +- .../service/impl/MeshRouteServiceImpl.java | 90 ++++ .../service/impl/MockRuleServiceImpl.java | 116 +++++ .../service/impl/OverrideServiceImpl.java | 4 +- .../service/impl/ProviderServiceImpl.java | 252 ++--------- .../admin/service/impl/RouteServiceImpl.java | 6 +- .../dubbo/admin/utils/JwtTokenUtil.java | 94 ++++ .../dubbo/admin/utils/SpringBeanUtils.java | 50 +++ ...n.authentication.InterceptorAuthentication | 1 + ...in.registry.config.GovernanceConfiguration | 5 +- ...ubbo.admin.registry.mapping.ServiceMapping | 2 + .../src/main/resources/application.properties | 23 + .../src/main/resources/schema.sql | 27 ++ .../admin/AbstractSpringIntegrationTest.java | 4 +- .../controller/ManagementControllerTest.java | 17 +- .../controller/MeshRouteControllerTest.java | 148 ++++++ .../impl/ZookeeperConfigurationTest.java | 16 +- .../admin/service/RegistryServerSyncTest.java | 35 +- .../dubbo/admin/utils/JwtTokenUtilTest.java | 41 ++ .../src/test/resources/MeshRoute.yml | 58 +++ .../src/test/resources/MeshRouteTest2.yml | 41 ++ dubbo-admin-ui/src/api/menu.js | 11 +- .../src/components/ServiceDetail.vue | 14 + .../src/components/ServiceSearch.vue | 22 +- .../src/components/governance/MeshRule.vue | 422 ++++++++++++++++++ .../src/components/governance/Overrides.vue | 2 +- .../src/components/public/Footers.vue | 2 +- .../src/components/test/ServiceMock.vue | 299 ++++++++++++- dubbo-admin-ui/src/lang/en.js | 23 +- dubbo-admin-ui/src/lang/zh.js | 23 +- dubbo-admin-ui/src/router/index.js | 11 +- dubbo-admin-ui/src/store/index.js | 12 + pom.xml | 27 +- 132 files changed, 6050 insertions(+), 1149 deletions(-) create mode 100644 .asf.yaml create mode 100644 docker/0.3.0/Dockerfile.test create mode 100644 docker/0.3.0/docker-compose.test.yml create mode 100755 docker/0.3.0/test.sh create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/InterceptorAuthentication.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/impl/DefaultPreHandle.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MockRuleController.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/mapper/MockRuleMapper.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MockRule.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MockRuleDTO.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/provider/MockServiceProvider.java delete mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java delete mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java delete mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java delete mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NacosServiceMapping.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MockRuleService.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MockRuleServiceImpl.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/JwtTokenUtil.java create mode 100644 dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/SpringBeanUtils.java create mode 100644 dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.authentication.InterceptorAuthentication create mode 100644 dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping create mode 100644 dubbo-admin-server/src/main/resources/schema.sql create mode 100644 dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java create mode 100644 dubbo-admin-server/src/test/java/org/apache/dubbo/admin/utils/JwtTokenUtilTest.java create mode 100644 dubbo-admin-server/src/test/resources/MeshRoute.yml create mode 100644 dubbo-admin-server/src/test/resources/MeshRouteTest2.yml create mode 100644 dubbo-admin-ui/src/components/governance/MeshRule.vue diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 000000000..7ed913a9f --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,6 @@ +github: + protected_branches: + master: + foo: bar + master-0.2.0: + foo: bar \ No newline at end of file diff --git a/NOTICE b/NOTICE index cf58f0a9d..6367c40de 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Dubbo Admin -Copyright 2018-2019 The Apache Software Foundation +Copyright 2018-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 37be75b66..e0182457b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ### Quick start * prebuilt docker image https://hub.docker.com/r/apache/dubbo-admin -* quick start a live demo with [play-with-docker](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/apache/dubbo-admin/develop/docker/stack.yml#) (version:0.1.0) +* quick start a live demo with [play-with-docker](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/apache/dubbo-admin/develop/docker/stack.yml#) (version:0.3.0) ### Screenshot diff --git a/README_ZH.md b/README_ZH.md index f4f0d909d..c1a21d10f 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -8,7 +8,7 @@ ### 快速开始 * 预构建的Docker镜像 https://hub.docker.com/r/apache/dubbo-admin -* 快速启动一个演示环境 [play-with-docker](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/apache/dubbo-admin/develop/docker/stack.yml#) (版本:0.1.0) +* 快速启动一个演示环境 [play-with-docker](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/apache/dubbo-admin/develop/docker/stack.yml#) (版本:0.3.0) ### 页面截图 diff --git a/docker/0.3.0/Dockerfile b/docker/0.3.0/Dockerfile index 5432d3dde..ac31116d3 100644 --- a/docker/0.3.0/Dockerfile +++ b/docker/0.3.0/Dockerfile @@ -14,16 +14,15 @@ # limitations under the License. FROM maven:3-openjdk-8 -RUN mkdir -p /source/dubbo-admin-snapshot -ADD . /source/dubbo-admin-snapshot -WORKDIR /source/dubbo-admin-snapshot -RUN mvn --batch-mode -Prelease clean package -Dmaven.test.skip=true +RUN mkdir /source && wget https://github.com/apache/dubbo-admin/archive/0.3.0.zip && unzip -q 0.3.0.zip -d /source +WORKDIR /source/dubbo-admin-0.3.0 +RUN mvn --batch-mode clean package -Dmaven.test.skip=true FROM openjdk:8-jre LABEL maintainer="dev@dubbo.apache.org" RUN apt-get update && apt-get install -y tini -COPY --from=0 /source/dubbo-admin-snapshot/dubbo-admin-distribution/target/dubbo-admin-0.3.0.jar /app.jar -COPY --from=0 /source/dubbo-admin-snapshot/docker/entrypoint.sh /usr/local/bin/entrypoint.sh +COPY --from=0 /source/dubbo-admin-0.3.0/dubbo-admin-distribution/target/dubbo-admin-0.3.0.jar /app.jar +COPY --from=0 /source/dubbo-admin-0.3.0/docker/entrypoint.sh /usr/local/bin/entrypoint.sh ENV JAVA_OPTS "" diff --git a/docker/0.3.0/Dockerfile.test b/docker/0.3.0/Dockerfile.test new file mode 100644 index 000000000..dee4d1d35 --- /dev/null +++ b/docker/0.3.0/Dockerfile.test @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +FROM ubuntu:trusty +RUN apt-get update && apt-get install -yq curl && apt-get clean + +WORKDIR /app + +ADD test.sh /app/test.sh + +CMD ["bash", "test.sh"] \ No newline at end of file diff --git a/docker/0.3.0/docker-compose.test.yml b/docker/0.3.0/docker-compose.test.yml new file mode 100644 index 000000000..9ac7fec20 --- /dev/null +++ b/docker/0.3.0/docker-compose.test.yml @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +zookeeper: + image: zookeeper:3.5 +admin: + build: . + dockerfile: Dockerfile + links: + - zookeeper + environment: + - admin.registry.address=zookeeper://zookeeper:2181 + - admin.config-center=zookeeper://zookeeper:2181 + - admin.metadata-report.address=zookeeper://zookeeper:2181 + ports: + - 8080 +sut: + build: . + dockerfile: Dockerfile.test + links: + - admin \ No newline at end of file diff --git a/docker/0.3.0/test.sh b/docker/0.3.0/test.sh new file mode 100755 index 000000000..d342e3550 --- /dev/null +++ b/docker/0.3.0/test.sh @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +LOOP_SIZE=60 +i=0 + +while [[ $i -lt LOOP_SIZE ]]; do + status_code=$(curl --write-out %{http_code} --silent --output /dev/null http://admin:8080) + + if [[ "$status_code" -eq 200 ]] ; then + echo "Tests passed!" + exit 0 + else + curl -v http://admin:8080 + echo "status is incorrect, waiting for next turn" + fi + sleep 5 + i=$i+1 +done + +echo "Tests failed!" +exit 1 \ No newline at end of file diff --git a/docker/latest/Dockerfile b/docker/latest/Dockerfile index 5ce8b3e71..a4e4f756f 100644 --- a/docker/latest/Dockerfile +++ b/docker/latest/Dockerfile @@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y tini COPY --from=0 /source/dubbo-admin-snapshot/dubbo-admin-distribution/target/dubbo-admin-0.3.0-SNAPSHOT.jar /app.jar COPY --from=0 /source/dubbo-admin-snapshot/docker/entrypoint.sh /usr/local/bin/entrypoint.sh -ENV JAVA_OPTS "" +ENV JAVA_OPTS "-Dloader.path=/opt-libs" ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] EXPOSE 8080 diff --git a/docker/stack.yml b/docker/stack.yml index ebb35f237..0392bc1a2 100644 --- a/docker/stack.yml +++ b/docker/stack.yml @@ -26,7 +26,20 @@ services: - zookeeper ports: - 8080:8080 +# the db driver path + volumes: + - "/mnt/opt-libs:/opt-libs" environment: - admin.registry.address=zookeeper://zookeeper:2181 - admin.config-center=zookeeper://zookeeper:2181 - - admin.metadata-report.address=zookeeper://zookeeper:2181 \ No newline at end of file + - admin.metadata-report.address=zookeeper://zookeeper:2181 + - dubbo.application.name=dubbo-admin + - dubbo.registry.address=zookeeper://zookeeper:2181 + - mybatis-plus.global-config.db-config.id-type=none + - spring.datasource.driver-class-name=com.mysql.jdbc.Driver + - spring.datasource.url=jdbc:mysql://xxx:3306/dubbo-admin?characterEncoding=utf8&connectTimeout=1000&socketTimeout=10000&autoReconnect=true + - spring.datasource.username=root + - spring.datasource.password=mysql +# use internal h2 as database +# - spring.datasource.url=jdbc:h2:mem:~/dubbo-admin; +# - spring.datasource.username=sa \ No newline at end of file diff --git a/dubbo-admin-distribution/src/NOTICE b/dubbo-admin-distribution/src/NOTICE index 446a88f30..df92423ec 100644 --- a/dubbo-admin-distribution/src/NOTICE +++ b/dubbo-admin-distribution/src/NOTICE @@ -1,5 +1,5 @@ Apache Dubbo Admin -Copyright 2018-2019 The Apache Software Foundation +Copyright 2018-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). @@ -100,7 +100,7 @@ dubbo NOTICE ======================================================================== Apache Dubbo -Copyright 2018-2019 The Apache Software Foundation +Copyright 2018-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/dubbo-admin-distribution/src/assembly/source-release.xml b/dubbo-admin-distribution/src/assembly/source-release.xml index 9c83c749e..f1316bf6d 100644 --- a/dubbo-admin-distribution/src/assembly/source-release.xml +++ b/dubbo-admin-distribution/src/assembly/source-release.xml @@ -59,6 +59,7 @@ **/.mvn/** **/*.jar **/mvnw* + **/.flattened-pom.xml dubbo-admin-distribution/src/LICENSE dubbo-admin-distribution/src/NOTICE dubbo-admin-distribution/src/licenses/** diff --git a/dubbo-admin-distribution/src/bin/config/application.properties b/dubbo-admin-distribution/src/bin/config/application.properties index df1746801..dbbc16cd4 100644 --- a/dubbo-admin-distribution/src/bin/config/application.properties +++ b/dubbo-admin-distribution/src/bin/config/application.properties @@ -56,3 +56,21 @@ admin.check.sessionTimeoutMilli=3600000 server.compression.enabled=true server.compression.mime-types=text/css,text/javascript,application/javascript server.compression.min-response-size=10240 + +#dubbo config +dubbo.application.name=dubbo-admin +dubbo.registry.address=${admin.registry.address} + +# mysql +#spring.datasource.driver-class-name=com.mysql.jdbc.Driver +#spring.datasource.url=jdbc:mysql://localhost:3306/dubbo-admin?characterEncoding=utf8&connectTimeout=1000&socketTimeout=10000&autoReconnect=true +#spring.datasource.username=root +#spring.datasource.password=mysql + +# h2 +spring.datasource.url=jdbc:h2:mem:~/dubbo-admin; +spring.datasource.username=sa +spring.datasource.password= + +# id generate type +mybatis-plus.global-config.db-config.id-type=none \ No newline at end of file diff --git a/dubbo-admin-distribution/src/bin/startup.cmd b/dubbo-admin-distribution/src/bin/startup.cmd index 67af6603a..5a78317b9 100644 --- a/dubbo-admin-distribution/src/bin/startup.cmd +++ b/dubbo-admin-distribution/src/bin/startup.cmd @@ -26,6 +26,6 @@ set SERVER=dubbo-admin set "JAVA_OPT=%JAVA_OPT% -Xms512m -Xmx512m -Xmn256m" -set "JAVA_OPT=%JAVA_OPT% -jar %BASE_DIR%\lib\%SERVER%.jar" +set "JAVA_OPT=%JAVA_OPT% -Dloader.path=%BASE_DIR%\opt-libs -jar %BASE_DIR%\lib\%SERVER%.jar" call "%JAVA%" %JAVA_OPT% dubbo.admin %* diff --git a/dubbo-admin-distribution/src/bin/startup.sh b/dubbo-admin-distribution/src/bin/startup.sh index 765f81437..3bb5e7276 100644 --- a/dubbo-admin-distribution/src/bin/startup.sh +++ b/dubbo-admin-distribution/src/bin/startup.sh @@ -63,6 +63,6 @@ if [ ! -f "${BASE_DIR}/logs/start.out" ]; then fi JAVA_OPT="${JAVA_OPT} -Xms512m -Xmx512m -Xmn256m" -JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/lib/${SERVER}.jar" -nohup $JAVA ${JAVA_OPT} dubbo.admin >> ${BASE_DIR}/logs/catlog.out 2>&1 & +JAVA_OPT="${JAVA_OPT} -Dloader.path=${BASE_DIR}/opt-libs -jar ${BASE_DIR}/lib/${SERVER}.jar" +nohup "$JAVA" ${JAVA_OPT} dubbo.admin >> ${BASE_DIR}/logs/catlog.out 2>&1 & echo "${SERVER} is starting,you can check the ${BASE_DIR}/logs/catlog.out" \ No newline at end of file diff --git a/dubbo-admin-server/pom.xml b/dubbo-admin-server/pom.xml index d03d5ab54..73be90fff 100644 --- a/dubbo-admin-server/pom.xml +++ b/dubbo-admin-server/pom.xml @@ -33,6 +33,8 @@ UTF-8 1.8 2.23.4 + 3.4.1 + 0.6.0 @@ -128,6 +130,11 @@ org.apache.curator curator-recipes + + org.apache.curator + curator-x-discovery + + com.alibaba fastjson @@ -172,11 +179,6 @@ netty-all - - org.apache.dubbo - dubbo-serialization-kryo - - org.mockito mockito-core @@ -189,6 +191,43 @@ zookeeper + + + com.auth0 + java-jwt + ${jwt-version} + + + + io.jsonwebtoken + jjwt + ${jjwt-version} + + + + + org.apache.dubbo.extensions + dubbo-mock-api + + + + com.baomidou + mybatis-plus-boot-starter + + + + + + + + + + + + com.h2database + h2 + runtime + @@ -197,6 +236,9 @@ org.springframework.boot spring-boot-maven-plugin 2.0.2.RELEASE + + ZIP + package diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java index 4f73eae9b..0be95b437 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java @@ -17,14 +17,17 @@ package org.apache.dubbo.admin; +import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; @SpringBootApplication(exclude={ - DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class + HibernateJpaAutoConfiguration.class }) +@EnableDubbo(scanBasePackages = {"org.apache.dubbo.admin.provider"}) +@MapperScan(basePackages = {"org.apache.dubbo.admin.mapper"}) public class DubboAdminApplication { public static void main(String[] args) { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/InterceptorAuthentication.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/InterceptorAuthentication.java new file mode 100644 index 000000000..bb468c074 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/InterceptorAuthentication.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.authentication; + +import org.apache.dubbo.common.extension.SPI; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Permission interception validation + * + */ +@SPI +public interface InterceptorAuthentication { + + boolean authentication(HttpServletRequest request, HttpServletResponse response, Object handler); + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java new file mode 100644 index 000000000..c9445e604 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.authentication; + +import org.apache.dubbo.common.extension.SPI; + +import javax.servlet.http.HttpServletRequest; + +/** + * Logon permission authentication + * + */ +@SPI +public interface LoginAuthentication { + + boolean authentication(HttpServletRequest request, String userName, String password); + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/impl/DefaultPreHandle.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/impl/DefaultPreHandle.java new file mode 100644 index 000000000..d66fd1f9e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/impl/DefaultPreHandle.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.authentication.impl; + +import org.apache.dubbo.admin.annotation.Authority; +import org.apache.dubbo.admin.authentication.InterceptorAuthentication; +import org.apache.dubbo.admin.interceptor.AuthInterceptor; +import org.apache.dubbo.admin.utils.JwtTokenUtil; +import org.apache.dubbo.admin.utils.SpringBeanUtils; + +import org.springframework.util.StringUtils; +import org.springframework.web.method.HandlerMethod; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; + +public class DefaultPreHandle implements InterceptorAuthentication { + + private JwtTokenUtil jwtTokenUtil = SpringBeanUtils.getBean(JwtTokenUtil.class); + + @Override + public boolean authentication(HttpServletRequest request, HttpServletResponse response, Object handler) { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + Authority authority = method.getDeclaredAnnotation(Authority.class); + if (null == authority) { + authority = method.getDeclaringClass().getDeclaredAnnotation(Authority.class); + } + + String token = request.getHeader("Authorization"); + + if (null != authority && authority.needLogin()) { + //check if 'authorization' is empty to prevent NullPointException + if (StringUtils.isEmpty(token)) { + //While authentication is required and 'Authorization' string is missing in the request headers, + //reject this request(http403). + AuthInterceptor.authRejectedResponse(response); + return false; + } + if (jwtTokenUtil.canTokenBeExpiration(token)) { + return true; + } + //while user not found, or token timeout, reject this request(http401). + AuthInterceptor.loginFailResponse(response); + return false; + } else { + return true; + } + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java index f98a0d91a..0116da57d 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java @@ -26,6 +26,7 @@ public class Constants { public static final String REGISTRY_ADDRESS = "dubbo.registry.address"; public static final String METADATA_ADDRESS = "dubbo.metadata-report.address"; public static final String DEFAULT_ROOT = "dubbo"; + public static final String DEFAULT_GROUP = "dubbo"; public static final String PATH_SEPARATOR = "/"; public static final String GROUP_KEY = "group"; public static final String NAMESPACE_KEY = "namespace"; @@ -74,12 +75,13 @@ public class Constants { public static final String CONSUMERS_CATEGORY = "consumers"; public static final String SPECIFICATION_VERSION_KEY = "release"; public static final String GLOBAL_CONFIG = "global"; - public static final String GLOBAL_CONFIG_PATH = "config/dubbo/dubbo.properties"; + public static final String GLOBAL_CONFIG_PATH = "dubbo.properties"; public static final String METRICS_PORT = "metrics.port"; public static final String METRICS_PROTOCOL = "metrics.protocol"; public static final Set CONFIGS = new HashSet<>(); public static final String COLON = ":"; - + public static final String MESH_RULE_SUFFIX = ".MESHAPPRULE"; + public static final String DEFAULT_MAPPING_GROUP = "mapping"; static { CONFIGS.add(WEIGHT); CONFIGS.add(BALANCING); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java index fa568ff6c..5ab5087e0 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java @@ -19,10 +19,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.dubbo.admin.model.domain.MethodMetadata; -import org.apache.dubbo.metadata.definition.model.FullServiceDefinition; -import org.apache.dubbo.metadata.definition.model.MethodDefinition; -import org.apache.dubbo.metadata.definition.model.ServiceDefinition; -import org.apache.dubbo.metadata.definition.model.TypeDefinition; +import org.apache.dubbo.admin.model.domain.FullServiceDefinition; +import org.apache.dubbo.admin.model.domain.MethodDefinition; +import org.apache.dubbo.admin.model.domain.ServiceDefinition; +import org.apache.dubbo.admin.model.domain.TypeDefinition; import java.util.ArrayList; import java.util.Collections; @@ -86,7 +86,7 @@ private static List generateParameterTypes(String[] parameterTypes, Serv private static TypeDefinition findTypeDefinition(ServiceDefinition serviceDefinition, String type) { return serviceDefinition.getTypes().stream() - .filter(t -> t.getType().equals(type)) + .filter(t -> type.equals(t.getType())) .findFirst().orElse(new TypeDefinition(type)); } @@ -180,10 +180,7 @@ private static Object generateMapType(ServiceDefinition sd, TypeDefinition td) { keyType = StringUtils.strip(keyType); Map map = new HashMap<>(); - // 生成 key 默认值 Object key = generateType(sd, keyType); - - // 生成 value 默认值 String valueType = StringUtils.substringAfter(td.getType(), ","); valueType = StringUtils.substringBefore(valueType, ">"); valueType = StringUtils.strip(valueType); @@ -197,7 +194,7 @@ private static Object generateCollectionType(ServiceDefinition sd, TypeDefinitio String type = StringUtils.substringAfter(td.getType(), "<"); type = StringUtils.substringBefore(type, ">"); if (StringUtils.isEmpty(type)) { - // 如果 collection 类型未声明,则生成空 collection + // if type is null return empty collection return new Object[] {}; } return new Object[]{generateType(sd, type)}; diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java new file mode 100644 index 000000000..778043433 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.common.util; + +import org.apache.dubbo.admin.model.domain.MethodMetadata; +import org.apache.dubbo.metadata.definition.model.FullServiceDefinition; +import org.apache.dubbo.metadata.definition.model.MethodDefinition; +import org.apache.dubbo.metadata.definition.model.ServiceDefinition; +import org.apache.dubbo.metadata.definition.model.TypeDefinition; + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ServiceTestV3Util { + private static Pattern COLLECTION_PATTERN = Pattern.compile("^java\\.util\\..*(Set|List|Queue|Collection|Deque)(<.*>)*$"); + private static Pattern MAP_PATTERN = Pattern.compile("^java\\.util\\..*Map.*(<.*>)*$"); + + public static boolean sameMethod(MethodDefinition m, String methodSig) { + String name = m.getName(); + String[] parameters = m.getParameterTypes(); + StringBuilder sb = new StringBuilder(); + sb.append(name).append("~"); + for (String parameter : parameters) { + sb.append(parameter).append(";"); + } + String sig = StringUtils.removeEnd(sb.toString(), ";"); + return sig.equals(methodSig); + } + + public static MethodMetadata generateMethodMeta(FullServiceDefinition serviceDefinition, MethodDefinition methodDefinition) { + MethodMetadata methodMetadata = new MethodMetadata(); + String[] parameterTypes = methodDefinition.getParameterTypes(); + String returnType = methodDefinition.getReturnType(); + String signature = methodDefinition.getName() + "~" + String.join(";", parameterTypes); + methodMetadata.setSignature(signature); + methodMetadata.setReturnType(returnType); + List parameters = generateParameterTypes(parameterTypes, serviceDefinition); + methodMetadata.setParameterTypes(parameters); + return methodMetadata; + } + + private static boolean isPrimitiveType(TypeDefinition td) { + String type = td.getType(); + return isPrimitiveType(type); + } + + private static boolean isPrimitiveType(String type) { + return type.equals("byte") || type.equals("java.lang.Byte") || + type.equals("short") || type.equals("java.lang.Short") || + type.equals("int") || type.equals("java.lang.Integer") || + type.equals("long") || type.equals("java.lang.Long") || + type.equals("float") || type.equals("java.lang.Float") || + type.equals("double") || type.equals("java.lang.Double") || + type.equals("boolean") || type.equals("java.lang.Boolean") || + type.equals("void") || type.equals("java.lang.Void") || + type.equals("java.lang.String") || + type.equals("java.util.Date") || + type.equals("java.lang.Object"); + } + + private static List generateParameterTypes(String[] parameterTypes, ServiceDefinition serviceDefinition) { + List parameters = new ArrayList<>(); + for (String type : parameterTypes) { + Object result = generateType(serviceDefinition, type); + parameters.add(result); + } + return parameters; + } + + private static TypeDefinition findTypeDefinition(ServiceDefinition serviceDefinition, String type) { + return serviceDefinition.getTypes().stream() + .filter(t -> type.equals(t.getType())) + .findFirst().orElse(new TypeDefinition(type)); + } + + private static void generateComplexType(ServiceDefinition sd, TypeDefinition td, Map holder) { + td.getProperties().forEach((name, type) -> { + if (isPrimitiveType(type)) { + holder.put(name, generatePrimitiveType(type)); + } else { + generateEnclosedType(holder, name, sd, type); + } + }); + } + + private static Object generateComplexType(ServiceDefinition sd, TypeDefinition td) { + Map holder = new HashMap<>(); + generateComplexType(sd, td, holder); + return holder; + } + + private static boolean isMap(TypeDefinition td) { + String type = StringUtils.substringBefore(td.getType(), "<"); + Matcher matcher = MAP_PATTERN.matcher(type); + return matcher.matches(); + } + + private static boolean isCollection(TypeDefinition td) { + String type = StringUtils.substringBefore(td.getType(), "<"); + Matcher matcher = COLLECTION_PATTERN.matcher(type); + return matcher.matches(); + } + + private static boolean isArray(TypeDefinition td) { + return StringUtils.endsWith(td.getType(), "[]"); + } + + private static Object generatePrimitiveType(TypeDefinition td) { + return generatePrimitiveType(td.getType()); + } + + private static Object generatePrimitiveType(String type) { + switch (type) { + case "byte": + case "java.lang.Byte": + case "short": + case "java.lang.Short": + case "int": + case "java.lang.Integer": + case "long": + case "java.lang.Long": + return 0; + case "float": + case "java.lang.Float": + case "double": + case "java.lang.Double": + return 0.0; + case "boolean": + case "java.lang.Boolean": + return true; + case "void": + case "java.lang.Void": + return null; + case "java.lang.String": + return ""; + case "java.lang.Object": + return Collections.emptyMap(); + case "java.util.Date": + return System.currentTimeMillis(); + default: + return Collections.emptyMap(); + } + } + + private static Object generateType(ServiceDefinition sd, String type) { + TypeDefinition td = findTypeDefinition(sd, type); + return generateType(sd, td); + } + + private static Object generateType(ServiceDefinition sd, TypeDefinition td) { + if (isPrimitiveType(td)) { + return generatePrimitiveType(td); + } else if (isMap(td)) { + return generateMapType(sd, td); + } else if (isArray(td)) { + return generateArrayType(sd, td); + } else if (isCollection(td)) { + return generateCollectionType(sd, td); + } else { + return generateComplexType(sd, td); + } + } + + private static Object generateMapType(ServiceDefinition sd, TypeDefinition td) { + String keyType = StringUtils.substringAfter(td.getType(), "<"); + keyType = StringUtils.substringBefore(keyType, ","); + keyType = StringUtils.strip(keyType); + + Map map = new HashMap<>(); + Object key = generateType(sd, keyType); + String valueType = StringUtils.substringAfter(td.getType(), ","); + valueType = StringUtils.substringBefore(valueType, ">"); + valueType = StringUtils.strip(valueType); + valueType = StringUtils.isNotEmpty(valueType) ? valueType : "java.lang.Object"; + Object value = generateType(sd, valueType); + map.put(key, value); + return map; + } + + private static Object generateCollectionType(ServiceDefinition sd, TypeDefinition td) { + String type = StringUtils.substringAfter(td.getType(), "<"); + type = StringUtils.substringBefore(type, ">"); + if (StringUtils.isEmpty(type)) { + // if type is null return empty collection + return new Object[]{}; + } + return new Object[]{generateType(sd, type)}; + + } + + private static Object generateArrayType(ServiceDefinition sd, TypeDefinition td) { + String type = StringUtils.substringBeforeLast(td.getType(), "[]"); + return new Object[]{generateType(sd, type)}; + } + + private static void generateEnclosedType(Map holder, String key, ServiceDefinition sd, String type) { + if (isPrimitiveType(type)) { + holder.put(key, generateType(sd, type)); + } else { + TypeDefinition td = findTypeDefinition(sd, type); + if (td.getProperties() == null || td.getProperties().size() == 0) { + holder.put(key, generateType(sd, td)); + } else { + Map enclosedMap = new HashMap<>(); + holder.put(key, enclosedMap); + generateComplexType(sd, td, enclosedMap); + } + + } + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java index b548d9123..7a36c0b60 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java @@ -18,7 +18,10 @@ import org.apache.dubbo.admin.model.domain.Consumer; import org.apache.dubbo.admin.model.domain.Provider; +import org.apache.dubbo.admin.model.domain.RegistrySource; +import org.apache.dubbo.common.BaseServiceMetadata; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.StringUtils; import java.util.ArrayList; import java.util.HashMap; @@ -48,7 +51,10 @@ public static Provider url2Provider(Pair pair) { Provider p = new Provider(); p.setHash(id); - p.setService(url.getServiceKey()); + String group = url.getUrlParam().getParameter(Constants.GROUP_KEY); + String version = url.getUrlParam().getParameter(Constants.VERSION_KEY); + String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version); + p.setService(service); p.setAddress(url.getAddress()); p.setApplication(url.getParameter(Constants.APPLICATION_KEY)); p.setUrl(url.toIdentityString()); @@ -58,6 +64,7 @@ public static Provider url2Provider(Pair pair) { p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true)); p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)); p.setUsername(url.getParameter("owner")); + p.setRegistrySource(RegistrySource.INTERFACE); return p; } @@ -83,7 +90,10 @@ public static Consumer url2Consumer(Pair pair) { Consumer c = new Consumer(); c.setHash(id); - c.setService(url.getServiceKey()); + String group = url.getUrlParam().getParameter(Constants.GROUP_KEY); + String version = url.getUrlParam().getParameter(Constants.VERSION_KEY); + String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version); + c.setService(service); c.setAddress(url.getHost()); c.setApplication(url.getParameter(Constants.APPLICATION_KEY)); c.setParameters(url.toParameterString()); @@ -179,4 +189,13 @@ public static >> Pair filte } return null; } + + private static String getServiceInterface(URL url) { + String serviceInterface = url.getServiceInterface(); + if (StringUtils.isBlank(serviceInterface) || Constants.ANY_VALUE.equals(serviceInterface)) { + serviceInterface = url.getPath(); + } + return serviceInterface; + } + } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java index 024097dbd..81ec3b3c4 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java @@ -17,7 +17,7 @@ package org.apache.dubbo.admin.common.util; -import org.apache.dubbo.common.utils.PojoUtils; +import com.fasterxml.jackson.databind.ObjectMapper; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.error.YAMLException; @@ -30,6 +30,8 @@ public class YamlParser { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static String dumpObject(Object object) { return new Yaml(new SafeConstructor(), new CustomRepresenter()).dumpAsMap(object); } @@ -37,12 +39,16 @@ public static String dumpObject(Object object) { public static T loadObject(String content, Class type) { Map map = new Yaml(new SafeConstructor(), new CustomRepresenter()).load(content); try { - return (T) PojoUtils.mapToPojo(map, type); + return OBJECT_MAPPER.convertValue(map, type); } catch (Exception e) { throw new YAMLException(e); } } + public static Iterable loadAll(String content) { + return new Yaml(new SafeConstructor(), new CustomRepresenter()).loadAll(content); + } + public static class CustomRepresenter extends Representer { protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java index befc7a74b..8c39771a0 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java @@ -17,18 +17,27 @@ package org.apache.dubbo.admin.config; -import org.apache.commons.lang3.StringUtils; import org.apache.dubbo.admin.common.exception.ConfigurationException; import org.apache.dubbo.admin.common.util.Constants; import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; +import org.apache.dubbo.admin.registry.mapping.AdminMappingListener; +import org.apache.dubbo.admin.registry.mapping.ServiceMapping; +import org.apache.dubbo.admin.registry.mapping.impl.NoOpServiceMapping; import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector; +import org.apache.dubbo.admin.service.impl.InstanceRegistryCache; + +import org.apache.commons.lang3.StringUtils; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.metadata.MappingListener; import org.apache.dubbo.registry.Registry; import org.apache.dubbo.registry.RegistryFactory; +import org.apache.dubbo.registry.RegistryService; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.apache.dubbo.registry.client.ServiceDiscoveryFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -37,12 +46,12 @@ import java.util.Arrays; import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; +import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension; @Configuration public class ConfigCenter { - //centers in dubbo 2.7 @Value("${admin.config-center:}") private String configCenter; @@ -85,8 +94,6 @@ public class ConfigCenter { private URL registryUrl; private URL metadataUrl; - - /* * generate dynamic configuration client */ @@ -96,13 +103,13 @@ GovernanceConfiguration getDynamicConfiguration() { if (StringUtils.isNotEmpty(configCenter)) { configCenterUrl = formUrl(configCenter, configCenterGroup, configCenterGroupNameSpace, username, password); - dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol()); + dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getDefaultExtension(); dynamicConfiguration.setUrl(configCenterUrl); dynamicConfiguration.init(); - String config = dynamicConfiguration.getConfig(Constants.GLOBAL_CONFIG_PATH); + String config = dynamicConfiguration.getConfig(Constants.DUBBO_PROPERTY); if (StringUtils.isNotEmpty(config)) { - Arrays.stream(config.split("\n")).forEach( s -> { + Arrays.stream(config.split("\n")).forEach(s -> { if (s.startsWith(Constants.REGISTRY_ADDRESS)) { String registryAddress = removerConfigKey(s); registryUrl = formUrl(registryAddress, registryGroup, registryNameSpace, username, password); @@ -115,7 +122,7 @@ GovernanceConfiguration getDynamicConfiguration() { if (dynamicConfiguration == null) { if (StringUtils.isNotEmpty(registryAddress)) { registryUrl = formUrl(registryAddress, registryGroup, registryNameSpace, username, password); - dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(registryUrl.getProtocol()); + dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getDefaultExtension(); dynamicConfiguration.setUrl(registryUrl); dynamicConfiguration.init(); logger.warn("you are using dubbo.registry.address, which is not recommend, please refer to: https://github.com/apache/incubator-dubbo-admin/wiki/Dubbo-Admin-configuration"); @@ -130,7 +137,7 @@ GovernanceConfiguration getDynamicConfiguration() { /* * generate registry client */ - @Bean + @Bean("dubboRegistry") @DependsOn("governanceConfiguration") Registry getRegistry() { Registry registry = null; @@ -148,7 +155,7 @@ Registry getRegistry() { /* * generate metadata client */ - @Bean + @Bean("metaDataCollector") @DependsOn("governanceConfiguration") MetaDataCollector getMetadataCollector() { MetaDataCollector metaDataCollector = new NoOpMetadataCollector(); @@ -168,6 +175,31 @@ MetaDataCollector getMetadataCollector() { return metaDataCollector; } + + @Bean(destroyMethod = "destroy") + @DependsOn("dubboRegistry") + ServiceDiscovery getServiceDiscoveryRegistry() throws Exception { + URL registryURL = registryUrl.setPath(RegistryService.class.getName()); + ServiceDiscoveryFactory factory = getExtension(registryURL); + ServiceDiscovery serviceDiscovery = factory.getServiceDiscovery(registryURL); + serviceDiscovery.initialize(registryURL); + return serviceDiscovery; + } + + @Bean + @DependsOn("metaDataCollector") + ServiceMapping getServiceMapping(ServiceDiscovery serviceDiscovery, InstanceRegistryCache instanceRegistryCache) { + ServiceMapping serviceMapping = new NoOpServiceMapping(); + if (metadataUrl == null) { + return serviceMapping; + } + MappingListener mappingListener = new AdminMappingListener(serviceDiscovery, instanceRegistryCache); + serviceMapping = ExtensionLoader.getExtensionLoader(ServiceMapping.class).getExtension(metadataUrl.getProtocol()); + serviceMapping.addMappingListener(mappingListener); + serviceMapping.init(metadataUrl); + return serviceMapping; + } + public static String removerConfigKey(String properties) { String[] split = properties.split("="); String[] address = new String[split.length - 1]; diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java new file mode 100644 index 000000000..9f3136cbd --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.controller; + +import org.apache.dubbo.admin.annotation.Authority; +import org.apache.dubbo.admin.common.exception.ParamValidationException; +import org.apache.dubbo.admin.common.exception.ResourceNotFoundException; +import org.apache.dubbo.admin.common.exception.VersionValidationException; +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.model.dto.MeshRouteDTO; +import org.apache.dubbo.admin.service.MeshRouteService; +import org.apache.dubbo.admin.service.ProviderService; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@Authority(needLogin = true) +@RestController +@RequestMapping("/api/{env}/rules/route/mesh") +public class MeshRouteController { + + private final MeshRouteService meshRouteService; + + private final ProviderService providerService; + + public MeshRouteController(MeshRouteService meshRouteService, ProviderService providerService) { + this.meshRouteService = meshRouteService; + this.providerService = providerService; + } + + @RequestMapping(method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + public boolean createMeshRoute(@RequestBody MeshRouteDTO meshRoute, @PathVariable String env) { + String app = meshRoute.getApplication(); + if (StringUtils.isEmpty(app)) { + throw new ParamValidationException("app is Empty!"); + } + if (providerService.findVersionInApplication(app).startsWith("2")) { + throw new VersionValidationException("dubbo 2.x does not support mesh route"); + } + + return meshRouteService.createMeshRule(meshRoute); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.PUT) + public boolean updateRule(@PathVariable String id, @RequestBody MeshRouteDTO meshRoute, @PathVariable String env) { + id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR); + if (meshRouteService.findMeshRoute(id) == null) { + throw new ResourceNotFoundException("can not find mesh route, Id: " + id); + } + meshRoute.setId(id); + return meshRouteService.updateMeshRule(meshRoute); + } + + @RequestMapping(method = RequestMethod.GET) + public List searchRoutes(@RequestParam String application, @PathVariable String env) { + if (StringUtils.isBlank(application)) { + throw new ParamValidationException("application is required."); + } + List result = new ArrayList<>(); + + MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(application); + if (meshRoute != null) { + result.add(meshRoute); + } + return result; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + public MeshRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) { + id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR); + MeshRouteDTO meshRoute = meshRouteService.findMeshRoute(id); + if (meshRoute == null) { + throw new ResourceNotFoundException("Unknown ID!"); + } + return meshRoute; + } + + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + public boolean deleteRoute(@PathVariable String id, @PathVariable String env) { + id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR); + return meshRouteService.deleteMeshRule(id); + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MockRuleController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MockRuleController.java new file mode 100644 index 000000000..435e65130 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MockRuleController.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.controller; + +import org.apache.dubbo.admin.annotation.Authority; +import org.apache.dubbo.admin.model.dto.MockRuleDTO; +import org.apache.dubbo.admin.service.MockRuleService; + +import org.springframework.beans.factory.annotation.Autowired; +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.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * Mock Rule Controller. + */ +@Authority(needLogin = true) +@RestController +@RequestMapping("/api/{env}/mock/rule") +public class MockRuleController { + + @Autowired + private MockRuleService mockRuleService; + + @PostMapping + public boolean createOrUpdateMockRule(@RequestBody MockRuleDTO mockRule) { + mockRuleService.createOrUpdateMockRule(mockRule); + return true; + } + + @DeleteMapping + public boolean deleteMockRule(@RequestBody MockRuleDTO mockRule) { + mockRuleService.deleteMockRuleById(mockRule.getId()); + return true; + } + + @GetMapping("/list") + public Page listMockRules(@RequestParam(required = false) String filter, Pageable pageable) { + return mockRuleService.listMockRulesByPage(filter, pageable); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java index 4a9df1a09..bfd801a58 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java @@ -103,9 +103,16 @@ public ServiceDetailDTO serviceDetail(@PathVariable String service, @PathVariabl if (metadata != null) { try { // for dubbo version under 2.7, this metadata will represent as IP address, like 10.0.0.1. - // So the json conversion will fail. - FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class); - serviceDetailDTO.setMetadata(serviceDefinition); + // So the json conversion will fail. + String release = providerService.findVersionInApplication(application); + // serialization compatible 2.x version + if (release.startsWith("2")) { + org.apache.dubbo.admin.model.domain.FullServiceDefinition serviceDefinition = gson.fromJson(metadata, org.apache.dubbo.admin.model.domain.FullServiceDefinition.class); + serviceDetailDTO.setMetadata(serviceDefinition); + } else { + FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class); + serviceDetailDTO.setMetadata(serviceDefinition); + } } catch (JsonParseException e) { throw new VersionValidationException("dubbo 2.6 does not support metadata"); } @@ -122,6 +129,11 @@ public Set allServices(@PathVariable String env) { return new HashSet<>(providerService.findServices()); } + @RequestMapping(value = "/applications/instance", method = RequestMethod.GET) + public Set allInstanceServices(@PathVariable String env) { + return new HashSet<>(providerService.findInstanceApplications()); + } + @RequestMapping(value = "/applications", method = RequestMethod.GET) public Set allApplications(@PathVariable String env) { return providerService.findApplications(); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java index cea17080b..ca3ad49a1 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java @@ -23,6 +23,7 @@ import org.apache.dubbo.admin.annotation.Authority; import org.apache.dubbo.admin.common.util.ConvertUtil; import org.apache.dubbo.admin.common.util.ServiceTestUtil; +import org.apache.dubbo.admin.common.util.ServiceTestV3Util; import org.apache.dubbo.admin.model.domain.MethodMetadata; import org.apache.dubbo.admin.model.dto.ServiceTestDTO; import org.apache.dubbo.admin.service.ProviderService; @@ -71,13 +72,29 @@ public MethodMetadata methodDetail(@PathVariable String env, @RequestParam Strin MethodMetadata methodMetadata = null; if (metadata != null) { Gson gson = new Gson(); - FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class); - List methods = serviceDefinition.getMethods(); - if (methods != null) { - for (MethodDefinition m : methods) { - if (ServiceTestUtil.sameMethod(m, method)) { - methodMetadata = ServiceTestUtil.generateMethodMeta(serviceDefinition, m); - break; + String release = providerService.findVersionInApplication(application); + if (release.startsWith("2.")) { + org.apache.dubbo.admin.model.domain.FullServiceDefinition serviceDefinition = gson.fromJson(metadata, + org.apache.dubbo.admin.model.domain.FullServiceDefinition.class); + List methods = serviceDefinition.getMethods(); + if (methods != null) { + for (org.apache.dubbo.admin.model.domain.MethodDefinition m : methods) { + if (ServiceTestUtil.sameMethod(m, method)) { + methodMetadata = ServiceTestUtil.generateMethodMeta(serviceDefinition, m); + break; + } + } + } + } else { + FullServiceDefinition serviceDefinition = gson.fromJson(metadata, + FullServiceDefinition.class); + List methods = serviceDefinition.getMethods(); + if (methods != null) { + for (MethodDefinition m : methods) { + if (ServiceTestV3Util.sameMethod(m, method)) { + methodMetadata = ServiceTestV3Util.generateMethodMeta(serviceDefinition, m); + break; + } } } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java index 84a794030..9a10dfdf5 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java @@ -17,84 +17,68 @@ package org.apache.dubbo.admin.controller; import org.apache.dubbo.admin.annotation.Authority; - +import org.apache.dubbo.admin.authentication.LoginAuthentication; +import org.apache.dubbo.admin.interceptor.AuthInterceptor; +import org.apache.dubbo.admin.utils.JwtTokenUtil; +import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.commons.lang3.StringUtils; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; +import javax.servlet.http.HttpServletResponse; +import java.util.Iterator; +import java.util.Set; @RestController @RequestMapping("/api/{env}/user") public class UserController { - public static Map tokenMap = new ConcurrentHashMap<>(); @Value("${admin.root.user.name:}") private String rootUserName; @Value("${admin.root.user.password:}") private String rootUserPassword; - //make session timeout configurable - //default to be an hour:1000 * 60 * 60 - @Value("${admin.check.sessionTimeoutMilli:3600000}") - private long sessionTimeoutMilli; + + @Autowired + private JwtTokenUtil jwtTokenUtil; @RequestMapping(value = "/login", method = RequestMethod.GET) - public String login(@RequestParam String userName, @RequestParam String password) { - if (StringUtils.isBlank(rootUserName) || (rootUserName.equals(userName) && rootUserPassword.equals(password))) { - UUID uuid = UUID.randomUUID(); - String token = uuid.toString(); - User user = new User(); - user.setUserName(userName); - user.setLastUpdateTime(System.currentTimeMillis()); - tokenMap.put(token, user); - return token; + public String login(HttpServletRequest httpServletRequest, HttpServletResponse response, @RequestParam String userName, @RequestParam String password) { + ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(LoginAuthentication.class); + Set supportedExtensionInstances = extensionLoader.getSupportedExtensionInstances(); + Iterator iterator = supportedExtensionInstances.iterator(); + boolean flag = true; + if (iterator != null && !iterator.hasNext()) { + if (StringUtils.isBlank(rootUserName) || (rootUserName.equals(userName) && rootUserPassword.equals(password))) { + return jwtTokenUtil.generateToken(userName); + } else { + flag = false; + } + } + while (iterator.hasNext()) { + LoginAuthentication loginAuthentication = iterator.next(); + boolean b = loginAuthentication.authentication(httpServletRequest, userName, password); + flag = b & flag; + if (!flag) { + break; + } + } + if (flag) { + return jwtTokenUtil.generateToken(userName); } + AuthInterceptor.loginFailResponse(response); return null; } @Authority(needLogin = true) @RequestMapping(value = "/logout", method = RequestMethod.DELETE) public boolean logout() { - HttpServletRequest request = - ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); - String token = request.getHeader("Authorization"); - return null != tokenMap.remove(token); - } - - @Scheduled(cron= "0 5 * * * ?") - public void clearExpiredToken() { - tokenMap.entrySet().removeIf(entry -> entry.getValue() == null || System.currentTimeMillis() - entry.getValue().getLastUpdateTime() > sessionTimeoutMilli); - } - - public static class User { - private String userName; - private long lastUpdateTime; - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public long getLastUpdateTime() { - return lastUpdateTime; - } - - public void setLastUpdateTime(long lastUpdateTime) { - this.lastUpdateTime = lastUpdateTime; - } + return true; } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java index ecc6e57f7..818482203 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java @@ -16,68 +16,51 @@ */ package org.apache.dubbo.admin.interceptor; -import org.apache.dubbo.admin.annotation.Authority; -import org.apache.dubbo.admin.controller.UserController; +import org.apache.dubbo.admin.authentication.InterceptorAuthentication; +import org.apache.dubbo.common.extension.ExtensionLoader; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotNull; -import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Set; @Component public class AuthInterceptor extends HandlerInterceptorAdapter { @Value("${admin.check.authority:true}") private boolean checkAuthority; - - //make session timeout configurable - //default to be an hour:1000 * 60 * 60 - @Value("${admin.check.sessionTimeoutMilli:3600000}") - private long sessionTimeoutMilli; + @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (!(handler instanceof HandlerMethod) || !checkAuthority) { return true; } - HandlerMethod handlerMethod = (HandlerMethod) handler; - Method method = handlerMethod.getMethod(); - Authority authority = method.getDeclaredAnnotation(Authority.class); - if (null == authority) { - authority = method.getDeclaringClass().getDeclaredAnnotation(Authority.class); - } - - String authorization = request.getHeader("Authorization"); - if (null != authority && authority.needLogin()) { - //check if 'authorization' is empty to prevent NullPointException - //since UserController.tokenMap is an instance of ConcurrentHashMap. - if (StringUtils.isEmpty(authorization)) { - //While authentication is required and 'Authorization' string is missing in the request headers, - //reject this request(http403). - rejectedResponse(response); - return false; - } - - UserController.User user = UserController.tokenMap.get(authorization); - if (null != user && System.currentTimeMillis() - user.getLastUpdateTime() <= sessionTimeoutMilli) { - user.setLastUpdateTime(System.currentTimeMillis()); - return true; + ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(InterceptorAuthentication.class); + Set supportedExtensionInstances = extensionLoader.getSupportedExtensionInstances(); + Iterator iterator = supportedExtensionInstances.iterator(); + boolean flag = true; + while (iterator.hasNext()) { + InterceptorAuthentication interceptorAuthentication = iterator.next(); + boolean b = interceptorAuthentication.authentication(request, response, handler); + flag = b & flag; + if (!flag) { + break; } - - //while user not found, or session timeout, reject this request(http403). - rejectedResponse(response); - return false; - } else { - return true; } + return flag; } - private static void rejectedResponse(@NotNull HttpServletResponse response) { + public static void loginFailResponse(@NotNull HttpServletResponse response) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); } + + public static void authRejectedResponse(@NotNull HttpServletResponse response) { + response.setStatus(HttpStatus.FORBIDDEN.value()); + } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/mapper/MockRuleMapper.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/mapper/MockRuleMapper.java new file mode 100644 index 000000000..1b670ca48 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/mapper/MockRuleMapper.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.mapper; + +import org.apache.dubbo.admin.model.domain.MockRule; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * The database operator of mock rule. + */ +public interface MockRuleMapper extends BaseMapper { +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java new file mode 100644 index 000000000..54dc59b11 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +import java.util.Map; + +/** + * copy from {@link org.apache.dubbo.metadata.definition.model.FullServiceDefinition} compatible 2.x version + */ +public class FullServiceDefinition extends ServiceDefinition { + private Map parameters; + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String toString() { + return "FullServiceDefinition{" + + "parameters=" + parameters + + "} " + super.toString(); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java new file mode 100644 index 000000000..1c0b8fee1 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * copy from {@link org.apache.dubbo.metadata.definition.model.MethodDefinition} compatible 2.x version + */ +public class MethodDefinition { + + private String name; + private String[] parameterTypes; + private String returnType; + private List parameters; + private List annotations; + + public MethodDefinition() { + } + + public String getName() { + return this.name; + } + + public List getParameters() { + if (this.parameters == null) { + this.parameters = new ArrayList(); + } + + return this.parameters; + } + + public String[] getParameterTypes() { + return this.parameterTypes; + } + + public String getReturnType() { + return this.returnType; + } + + public void setName(String name) { + this.name = name; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + } + + public void setParameterTypes(String[] parameterTypes) { + this.parameterTypes = TypeDefinition.formatTypes(parameterTypes); + } + + public void setReturnType(String returnType) { + this.returnType = TypeDefinition.formatType(returnType); + } + + public List getAnnotations() { + if (this.annotations == null) { + this.annotations = Collections.emptyList(); + } + + return this.annotations; + } + + public void setAnnotations(List annotations) { + this.annotations = annotations; + } + + public String toString() { + return "MethodDefinition [name=" + this.name + ", parameterTypes=" + Arrays.toString(this.parameterTypes) + ", returnType=" + this.returnType + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof MethodDefinition)) { + return false; + } else { + MethodDefinition that = (MethodDefinition) o; + return Objects.equals(this.getName(), that.getName()) && Arrays.equals(this.getParameterTypes(), that.getParameterTypes()) && Objects.equals(this.getReturnType(), that.getReturnType()) && Objects.equals(this.getParameters(), that.getParameters()); + } + } + + public int hashCode() { + int result = Objects.hash(new Object[]{this.getName(), this.getReturnType(), this.getParameters()}); + result = 31 * result + Arrays.hashCode(this.getParameterTypes()); + return result; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MockRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MockRule.java new file mode 100644 index 000000000..4ed363488 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MockRule.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +import org.apache.dubbo.admin.model.dto.MockRuleDTO; + +/** + * The entity for database query and insert. + */ +public class MockRule { + + private Long id; + + private String serviceName; + + private String methodName; + + private String rule; + + private Boolean enable; + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getRule() { + return rule; + } + + public void setRule(String rule) { + this.rule = rule; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Boolean getEnable() { + return enable; + } + + public void setEnable(Boolean enable) { + this.enable = enable; + } + + @java.lang.Override + public String toString() { + return "MockRule{" + + "id=" + id + + ", serviceName='" + serviceName + '\'' + + ", methodName='" + methodName + '\'' + + ", rule='" + rule + '\'' + + ", enable=" + enable + + '}'; + } + + + public static MockRule toMockRule(MockRuleDTO mockRule) { + MockRule rule = new MockRule(); + rule.setServiceName(mockRule.getServiceName().trim()); + rule.setMethodName(mockRule.getMethodName().trim()); + rule.setId(mockRule.getId()); + rule.setRule(mockRule.getRule()); + rule.setEnable(mockRule.getEnable()); + return rule; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java index 363872b16..2de0ad07e 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java @@ -60,6 +60,8 @@ public class Provider extends Entity { private List overrides; + private RegistrySource registrySource; + public Provider() { } @@ -181,6 +183,14 @@ public void setOverrides(List overrides) { this.overrides = overrides; } + public RegistrySource getRegistrySource() { + return registrySource; + } + + public void setRegistrySource(RegistrySource registrySource) { + this.registrySource = registrySource; + } + public URL toUrl() { Map serviceName2Map = ConvertUtil.serviceName2Map(getService()); /*if(!serviceName2Map.containsKey(Constants.INTERFACE_KEY)) { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java new file mode 100644 index 000000000..e54644c94 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +public enum RegistrySource { + + INTERFACE, + + INSTANCE + +} \ No newline at end of file diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java new file mode 100644 index 000000000..9205ac761 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +import org.apache.dubbo.metadata.definition.util.ClassUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * copy from {@link org.apache.dubbo.metadata.definition.model.ServiceDefinition} compatible 2.x version + */ +public class ServiceDefinition { + + /** + * the canonical name of interface + * + * @see Class#getCanonicalName() + */ + private String canonicalName; + + /** + * the location of class file + * + * @see ClassUtils#getCodeSource(Class) + */ + private String codeSource; + + private List methods; + + /** + * the definitions of type + */ + private List types; + + /** + * the definitions of annotations + */ + private List annotations; + + public String getCanonicalName() { + return canonicalName; + } + + public String getCodeSource() { + return codeSource; + } + + public List getMethods() { + if (methods == null) { + methods = new ArrayList<>(); + } + return methods; + } + + public List getTypes() { + if (types == null) { + types = new ArrayList<>(); + } + return types; + } + + public String getUniqueId() { + return canonicalName + "@" + codeSource; + } + + public void setCanonicalName(String canonicalName) { + this.canonicalName = canonicalName; + } + + public void setCodeSource(String codeSource) { + this.codeSource = codeSource; + } + + public void setMethods(List methods) { + this.methods = methods; + } + + public void setTypes(List types) { + this.types = types; + } + + public List getAnnotations() { + if (annotations == null) { + annotations = Collections.emptyList(); + } + return annotations; + } + + public void setAnnotations(List annotations) { + this.annotations = annotations; + } + + public String toString() { + return "ServiceDefinition [canonicalName=" + canonicalName + ", codeSource=" + codeSource + ", methods=" + + methods + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ServiceDefinition)) { + return false; + } + ServiceDefinition that = (ServiceDefinition) o; + return Objects.equals(getCanonicalName(), that.getCanonicalName()) && + Objects.equals(getCodeSource(), that.getCodeSource()) && + Objects.equals(getMethods(), that.getMethods()) && + Objects.equals(getTypes(), that.getTypes()); + } + + public int hashCode() { + return Objects.hash(getCanonicalName(), getCodeSource(), getMethods(), getTypes()); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java new file mode 100644 index 000000000..71ed8fa8c --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.domain; + +import org.apache.dubbo.common.utils.StringUtils; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + + +/** + * copy from {@link org.apache.dubbo.metadata.definition.model.TypeDefinition} compatible 2.x version + */ +public class TypeDefinition implements Serializable { + private String id; + private String type; + @SerializedName("items") + private List items; + @SerializedName("enum") + private List enums; + private String $ref; + private Map properties; + private String typeBuilderName; + + public TypeDefinition() { + } + + public TypeDefinition(String type) { + this.setType(type); + } + + public static String[] formatTypes(String[] types) { + String[] newTypes = new String[types.length]; + + for (int i = 0; i < types.length; ++i) { + newTypes[i] = formatType(types[i]); + } + + return newTypes; + } + + public static String formatType(String type) { + return isGenericType(type) ? formatGenericType(type) : type; + } + + private static String formatGenericType(String type) { + return StringUtils.replace(type, ", ", ","); + } + + private static boolean isGenericType(String type) { + return type.contains("<") && type.contains(">"); + } + + public String get$ref() { + return this.$ref; + } + + public List getEnums() { + if (this.enums == null) { + this.enums = new ArrayList(); + } + + return this.enums; + } + + public String getId() { + return this.id; + } + + public List getItems() { + if (this.items == null) { + this.items = new ArrayList(); + } + + return this.items; + } + + public Map getProperties() { + if (this.properties == null) { + this.properties = new HashMap(); + } + + return this.properties; + } + + public String getType() { + return this.type; + } + + public String getTypeBuilderName() { + return this.typeBuilderName; + } + + public void set$ref(String $ref) { + this.$ref = $ref; + } + + public void setEnums(List enums) { + this.enums = enums; + } + + public void setId(String id) { + this.id = id; + } + + public void setItems(List items) { + this.items = items; + } + + public void setProperties(Map properties) { + this.properties = properties; + } + + public void setType(String type) { + this.type = formatType(type); + } + + public void setTypeBuilderName(String typeBuilderName) { + this.typeBuilderName = typeBuilderName; + } + + public String toString() { + return "TypeDefinition [id=" + this.id + ", type=" + this.type + ", properties=" + this.properties + ", $ref=" + this.$ref + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (!(o instanceof TypeDefinition)) { + return false; + } else { + TypeDefinition that = (TypeDefinition) o; + return Objects.equals(this.getId(), that.getId()) && Objects.equals(this.getType(), that.getType()) && Objects.equals(this.getItems(), that.getItems()) && Objects.equals(this.getEnums(), that.getEnums()) && Objects.equals(this.get$ref(), that.get$ref()) && Objects.equals(this.getProperties(), that.getProperties()); + } + } + + public int hashCode() { + return Objects.hash(new Object[]{this.getId(), this.getType(), this.getItems(), this.getEnums(), this.get$ref(), this.getProperties()}); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java new file mode 100644 index 000000000..349c3c0d3 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.dto; + +public class MeshRouteDTO extends BaseDTO{ + + private String meshRule; + + public String getMeshRule() { + return meshRule; + } + + public void setMeshRule(String meshRule) { + this.meshRule = meshRule; + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MockRuleDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MockRuleDTO.java new file mode 100644 index 000000000..d808cdf09 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MockRuleDTO.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.dto; + +import org.apache.dubbo.admin.model.domain.MockRule; + +import org.springframework.beans.BeanUtils; + +/** + * the dto which provide to front end. + */ +public class MockRuleDTO { + + private Long id; + + private String serviceName; + + private String methodName; + + private String rule; + + private Boolean enable; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getRule() { + return rule; + } + + public void setRule(String rule) { + this.rule = rule; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public Boolean getEnable() { + return enable; + } + + public void setEnable(Boolean enable) { + this.enable = enable; + } + + @Override + public String toString() { + return "MockRuleDTO{" + + "id=" + id + + ", serviceName='" + serviceName + '\'' + + ", methodName='" + methodName + '\'' + + ", rule='" + rule + '\'' + + ", enable=" + enable + + '}'; + } + + public static MockRuleDTO toMockRuleDTO(MockRule mockRule) { + MockRuleDTO mockRuleDTO = new MockRuleDTO(); + BeanUtils.copyProperties(mockRule, mockRuleDTO); + return mockRuleDTO; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java index 0202526c2..cd1591631 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java @@ -17,15 +17,17 @@ package org.apache.dubbo.admin.model.dto; +import org.apache.dubbo.admin.model.domain.RegistrySource; import org.apache.commons.lang3.StringUtils; import java.util.Objects; -public class ServiceDTO implements Comparable{ +public class ServiceDTO implements Comparable { private String service; private String appName; private String group; private String version; + private RegistrySource registrySource; public String getService() { return service; @@ -59,6 +61,14 @@ public void setVersion(String version) { this.version = version; } + public RegistrySource getRegistrySource() { + return registrySource; + } + + public void setRegistrySource(RegistrySource registrySource) { + this.registrySource = registrySource; + } + @Override public int compareTo(ServiceDTO o) { int result = StringUtils.trimToEmpty(appName).compareTo(StringUtils.trimToEmpty(o.getAppName())); @@ -70,6 +80,9 @@ public int compareTo(ServiceDTO o) { if (result == 0) { result = StringUtils.trimToEmpty(version).compareTo(StringUtils.trimToEmpty(o.getVersion())); } + if (result == 0) { + result = registrySource.compareTo(o.registrySource); + } } return result; } @@ -84,11 +97,11 @@ public boolean equals(Object o) { } ServiceDTO that = (ServiceDTO) o; return Objects.equals(service, that.service) && Objects.equals(appName, that.appName) && Objects - .equals(group, that.group) && Objects.equals(version, that.version); + .equals(group, that.group) && Objects.equals(version, that.version) && Objects.equals(registrySource, that.registrySource); } @Override public int hashCode() { - return Objects.hash(service, appName, group, version); + return Objects.hash(service, appName, group, version, registrySource); } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java index 1ef4bebd9..d15a7bf28 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java @@ -19,7 +19,6 @@ import org.apache.dubbo.admin.model.domain.Consumer; import org.apache.dubbo.admin.model.domain.Provider; -import org.apache.dubbo.metadata.definition.model.FullServiceDefinition; import java.util.List; @@ -30,7 +29,7 @@ public class ServiceDetailDTO { private String service; private String application; - FullServiceDefinition metadata; + Object metadata; public String getService() { return service; @@ -64,11 +63,11 @@ public void setConsumers(List consumers) { this.consumers = consumers; } - public FullServiceDefinition getMetadata() { + public Object getMetadata() { return metadata; } - public void setMetadata(FullServiceDefinition metadata) { + public void setMetadata(Object metadata) { this.metadata = metadata; } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java new file mode 100644 index 000000000..94e7afd7b --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh; + +import java.util.Map; + + +public class BaseRule { + private String apiVersion; + private String kind; + private Map metadata; + + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + public String getKind() { + return kind; + } + + public void setKind(String kind) { + this.kind = kind; + } + + public Map getMetadata() { + return metadata; + } + + public void setMetadata(Map metadata) { + this.metadata = metadata; + } + + @Override + public String toString() { + return "BaseRule{" + + "apiVersion='" + apiVersion + '\'' + + ", kind='" + kind + '\'' + + ", metadata=" + metadata + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java new file mode 100644 index 000000000..8c9986366 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh; + + +import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule; +import org.apache.dubbo.admin.model.store.mesh.virtualservice.VirtualServiceRule; + +import java.util.ArrayList; +import java.util.List; + + +public class VsDestinationGroup { + private String appName; + private List virtualServiceRuleList = new ArrayList<>(); + private List destinationRuleList = new ArrayList<>(); + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public List getVirtualServiceRuleList() { + return virtualServiceRuleList; + } + + public void setVirtualServiceRuleList(List virtualServiceRuleList) { + this.virtualServiceRuleList = virtualServiceRuleList; + } + + public List getDestinationRuleList() { + return destinationRuleList; + } + + public void setDestinationRuleList(List destinationRuleList) { + this.destinationRuleList = destinationRuleList; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java new file mode 100644 index 000000000..71a5c43f1 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + + +public class ConnectionPoolSettings { +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java new file mode 100644 index 000000000..9b0d8c6f7 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + + +import org.apache.dubbo.admin.model.store.mesh.BaseRule; + +public class DestinationRule extends BaseRule { + private DestinationRuleSpec spec; + + public DestinationRuleSpec getSpec() { + return spec; + } + + public void setSpec(DestinationRuleSpec spec) { + this.spec = spec; + } + + @Override + public String toString() { + return "DestinationRule{" + + "base=" + super.toString() + + ", spec=" + spec + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java new file mode 100644 index 000000000..470b7c42e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + +import java.util.List; + + +public class DestinationRuleSpec { + private String host; + private List subsets; + private TrafficPolicy trafficPolicy; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public List getSubsets() { + return subsets; + } + + public void setSubsets(List subsets) { + this.subsets = subsets; + } + + public TrafficPolicy getTrafficPolicy() { + return trafficPolicy; + } + + public void setTrafficPolicy(TrafficPolicy trafficPolicy) { + this.trafficPolicy = trafficPolicy; + } + + @Override + public String toString() { + return "DestinationRuleSpec{" + + "host='" + host + '\'' + + ", subsets=" + subsets + + ", trafficPolicy=" + trafficPolicy + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java new file mode 100644 index 000000000..66b6fa4ea --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + +import java.util.Map; + + +public class Subset { + private String name; + private Map labels; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getLabels() { + return labels; + } + + public void setLabels(Map labels) { + this.labels = labels; + } + + @Override + public String toString() { + return "Subset{" + + "name='" + name + '\'' + + ", labels=" + labels + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java new file mode 100644 index 000000000..1cc05ce88 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + + +public class TCPSettings { + private int maxConnections; + private int connectTimeout; + private TcpKeepalive tcpKeepalive; +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java new file mode 100644 index 000000000..aa48bf65e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + + +public class TcpKeepalive { + private int probes; + private int time; + private int interval; + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java new file mode 100644 index 000000000..bda74d6b8 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination; + + +import org.apache.dubbo.admin.model.store.mesh.destination.loadbalance.LoadBalancerSettings; + +public class TrafficPolicy { + private LoadBalancerSettings loadBalancer; + + public LoadBalancerSettings getLoadBalancer() { + return loadBalancer; + } + + public void setLoadBalancer(LoadBalancerSettings loadBalancer) { + this.loadBalancer = loadBalancer; + } + + @Override + public String toString() { + return "TrafficPolicy{" + + "loadBalancer=" + loadBalancer + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java new file mode 100644 index 000000000..e0c11e424 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination.loadbalance; + + +public class ConsistentHashLB { +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java new file mode 100644 index 000000000..5a5a1ec9b --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination.loadbalance; + + +public class LoadBalancerSettings { + private SimpleLB simple; + private ConsistentHashLB consistentHash; + + public SimpleLB getSimple() { + return simple; + } + + public void setSimple(SimpleLB simple) { + this.simple = simple; + } + + public ConsistentHashLB getConsistentHash() { + return consistentHash; + } + + public void setConsistentHash(ConsistentHashLB consistentHash) { + this.consistentHash = consistentHash; + } + + @Override + public String toString() { + return "LoadBalancerSettings{" + + "simple=" + simple + + ", consistentHash=" + consistentHash + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java new file mode 100644 index 000000000..b8b13ec15 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.destination.loadbalance; + + +public enum SimpleLB { + ROUND_ROBIN, + LEAST_CONN, + RANDOM, + PASSTHROUGH +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java new file mode 100644 index 000000000..59dcd3c63 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice; + + +import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DoubleMatch; +import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboAttachmentMatch; +import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.DubboMethodMatch; +import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.StringMatch; + +import java.util.Map; + + +public class DubboMatchRequest { + private String name; + private DubboMethodMatch method; + private Map sourceLabels; + private DubboAttachmentMatch attachments; + private Map headers; + private DoubleMatch threshold; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public DubboMethodMatch getMethod() { + return method; + } + + public void setMethod(DubboMethodMatch method) { + this.method = method; + } + + public Map getSourceLabels() { + return sourceLabels; + } + + public void setSourceLabels(Map sourceLabels) { + this.sourceLabels = sourceLabels; + } + + public DubboAttachmentMatch getAttachments() { + return attachments; + } + + public void setAttachments(DubboAttachmentMatch attachments) { + this.attachments = attachments; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public DoubleMatch getThreshold() { + return threshold; + } + + public void setThreshold(DoubleMatch threshold) { + this.threshold = threshold; + } + + + public static boolean isMatch(DubboMatchRequest dubboMatchRequest, + String methodName, String[] parameterTypeList, Object[] parameters, + Map sourceLabels, + Map eagleeyeContext, Map dubboContext, + Map headers + ) { + if (dubboMatchRequest.getMethod() != null) { + if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) { + return false; + } + } + + if (dubboMatchRequest.getSourceLabels() != null) { + for (Map.Entry entry : dubboMatchRequest.getSourceLabels().entrySet()) { + String value = sourceLabels.get(entry.getKey()); + if (value == null || !entry.getValue().equals(value)) { + return false; + } + } + } + + if (dubboMatchRequest.getAttachments() != null) { + if (!DubboAttachmentMatch.isMatch(dubboMatchRequest.getAttachments(),eagleeyeContext,dubboContext)){ + return false; + } + } + + //TODO headers + + + return true; + + } + + @Override + public String toString() { + return "DubboMatchRequest{" + + "name='" + name + '\'' + + ", method=" + method + + ", sourceLabels=" + sourceLabels + + ", attachments=" + attachments + + ", headers=" + headers + + ", threshold=" + threshold + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java new file mode 100644 index 000000000..9747b6ba3 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice; + + +import org.apache.dubbo.admin.model.store.mesh.virtualservice.match.StringMatch; + +import java.util.List; + + +public class DubboRoute { + private String name; + private List services; + private List routedetail; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getServices() { + return services; + } + + public void setServices(List services) { + this.services = services; + } + + public List getRoutedetail() { + return routedetail; + } + + public void setRoutedetail(List routedetail) { + this.routedetail = routedetail; + } + + @Override + public String toString() { + return "DubboRoute{" + + "name='" + name + '\'' + + ", services=" + services + + ", routedetail=" + routedetail + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java new file mode 100644 index 000000000..1b576d5d4 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice; + + +import org.apache.dubbo.admin.model.store.mesh.virtualservice.destination.DubboRouteDestination; + +import java.util.List; + + +public class DubboRouteDetail { + private String name; + private List match; + private List route; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getMatch() { + return match; + } + + public void setMatch(List match) { + this.match = match; + } + + public List getRoute() { + return route; + } + + public void setRoute(List route) { + this.route = route; + } + + @Override + public String toString() { + return "DubboRouteDetail{" + + "name='" + name + '\'' + + ", match=" + match + + ", route=" + route + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java new file mode 100644 index 000000000..c5798d8ca --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice; + + +import org.apache.dubbo.admin.model.store.mesh.BaseRule; + +public class VirtualServiceRule extends BaseRule { + private VirtualServiceSpec spec; + + public VirtualServiceSpec getSpec() { + return spec; + } + + public void setSpec(VirtualServiceSpec spec) { + this.spec = spec; + } + + @Override + public String toString() { + return "VirtualServiceRule{" + + "base=" + super.toString() + + ", spec=" + spec + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java new file mode 100644 index 000000000..c4eab8db0 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice; + +import java.util.List; + + +public class VirtualServiceSpec { + private List hosts; + private List dubbo; + + public List getHosts() { + return hosts; + } + + public void setHosts(List hosts) { + this.hosts = hosts; + } + + public List getDubbo() { + return dubbo; + } + + public void setDubbo(List dubbo) { + this.dubbo = dubbo; + } + + @Override + public String toString() { + return "VirtualServiceSpec{" + + "hosts=" + hosts + + ", dubbo=" + dubbo + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java new file mode 100644 index 000000000..781308e9f --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.destination; + + +public class DubboDestination { + private String host; + private String subset; + private int port; + private DubboRouteDestination fallback; + + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getSubset() { + return subset; + } + + public void setSubset(String subset) { + this.subset = subset; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public DubboRouteDestination getFallback() { + return fallback; + } + + public void setFallback(DubboRouteDestination fallback) { + this.fallback = fallback; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java new file mode 100644 index 000000000..95ede775c --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.destination; + + +public class DubboRouteDestination { + private DubboDestination destination; + private int weight; + + public DubboDestination getDestination() { + return destination; + } + + public void setDestination(DubboDestination destination) { + this.destination = destination; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java new file mode 100644 index 000000000..d35415703 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class BoolMatch { + private Boolean exact; + + public Boolean getExact() { + return exact; + } + + public void setExact(Boolean exact) { + this.exact = exact; + } + + public static boolean isMatch(BoolMatch boolMatch,boolean input){ + if (boolMatch.getExact() != null){ + return input == boolMatch.getExact(); + } + return false; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java new file mode 100644 index 000000000..89ab4d6e6 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class DoubleMatch { + private Double exact; + private DoubleRangeMatch range; + private Double mod; + + public Double getExact() { + return exact; + } + + public void setExact(Double exact) { + this.exact = exact; + } + + public DoubleRangeMatch getRange() { + return range; + } + + public void setRange(DoubleRangeMatch range) { + this.range = range; + } + + public Double getMod() { + return mod; + } + + public void setMod(Double mod) { + this.mod = mod; + } + + + public static boolean isMatch(DoubleMatch doubleMatch, Double input) { + if (doubleMatch.getExact() != null && doubleMatch.getMod() == null) { + return input.equals(doubleMatch.getExact()); + } else if (doubleMatch.getRange() != null) { + return DoubleRangeMatch.isMatch(doubleMatch.getRange(), input); + } else if (doubleMatch.getExact() != null && doubleMatch.getMod() != null) { + Double result = input % doubleMatch.getMod(); + return result.equals(doubleMatch.getExact()); + } + + return false; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java new file mode 100644 index 000000000..00d09db46 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class DoubleRangeMatch { + private Double start; + private Double end; + + public Double getStart() { + return start; + } + + public void setStart(Double start) { + this.start = start; + } + + public Double getEnd() { + return end; + } + + public void setEnd(Double end) { + this.end = end; + } + + + public static boolean isMatch(DoubleRangeMatch doubleRangeMatch, Double input) { + if (doubleRangeMatch.getStart() != null && doubleRangeMatch.getEnd() != null) { + return input.compareTo(doubleRangeMatch.getStart()) >= 0 && input.compareTo(doubleRangeMatch.getEnd()) < 0; + } else if (doubleRangeMatch.getStart() != null) { + return input.compareTo(doubleRangeMatch.getStart()) >= 0; + } else if (doubleRangeMatch.getEnd() != null) { + return input.compareTo(doubleRangeMatch.getEnd()) < 0; + } else { + return false; + } + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java new file mode 100644 index 000000000..37f1da467 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + +import java.util.Map; + + +public class DubboAttachmentMatch { + private Map eagleeyecontext; + private Map dubbocontext; + + public Map getEagleeyecontext() { + return eagleeyecontext; + } + + public void setEagleeyecontext(Map eagleeyecontext) { + this.eagleeyecontext = eagleeyecontext; + } + + public Map getDubbocontext() { + return dubbocontext; + } + + public void setDubbocontext(Map dubbocontext) { + this.dubbocontext = dubbocontext; + } + + public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map eagleeyeContext, Map dubboContext) { + if (dubboAttachmentMatch.getDubbocontext() != null) { + for (Map.Entry stringStringMatchEntry : dubboAttachmentMatch.getDubbocontext().entrySet()) { + String key = stringStringMatchEntry.getKey(); + StringMatch stringMatch = stringStringMatchEntry.getValue(); + + String dubboContextValue = dubboContext.get(key); + if (dubboContextValue == null) { + return false; + } + if (!StringMatch.isMatch(stringMatch, dubboContextValue)) { + return false; + } + } + } + + if (dubboAttachmentMatch.getEagleeyecontext() != null) { + for (Map.Entry stringStringMatchEntry : dubboAttachmentMatch.getEagleeyecontext().entrySet()) { + String key = stringStringMatchEntry.getKey(); + StringMatch stringMatch = stringStringMatchEntry.getValue(); + + String eagleeyeContextValue = eagleeyeContext.get(key); + if (eagleeyeContextValue == null) { + return false; + } + if (!StringMatch.isMatch(stringMatch, eagleeyeContextValue)) { + return false; + } + } + } + + return true; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java new file mode 100644 index 000000000..8e0f991fe --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class DubboMethodArg { + private int index; + private String type; + private ListStringMatch str_value; + private ListDoubleMatch num_value; + private BoolMatch bool_value; + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public ListStringMatch getStr_value() { + return str_value; + } + + public void setStr_value(ListStringMatch str_value) { + this.str_value = str_value; + } + + public ListDoubleMatch getNum_value() { + return num_value; + } + + public void setNum_value(ListDoubleMatch num_value) { + this.num_value = num_value; + } + + public BoolMatch getBool_value() { + return bool_value; + } + + public void setBool_value(BoolMatch bool_value) { + this.bool_value = bool_value; + } + + public static boolean isMatch(DubboMethodArg dubboMethodArg, Object input) { + + if (dubboMethodArg.getStr_value() != null) { + return ListStringMatch.isMatch(dubboMethodArg.getStr_value(), (String) input); + } else if (dubboMethodArg.getNum_value() != null) { + return ListDoubleMatch.isMatch(dubboMethodArg.getNum_value(), Double.valueOf(input.toString())); + } else if (dubboMethodArg.getBool_value() != null) { + return BoolMatch.isMatch(dubboMethodArg.getBool_value(), (Boolean) input); + } + return false; + } + + @Override + public String toString() { + return "DubboMethodArg{" + + "index=" + index + + ", type='" + type + '\'' + + ", str_value=" + str_value + + ", num_value=" + num_value + + ", bool_value=" + bool_value + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java new file mode 100644 index 000000000..c448895a0 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + +import java.util.List; +import java.util.Map; + + +public class DubboMethodMatch { + private StringMatch name_match; + private Integer argc; + private List args; + private List argp; + private Map headers; + + public StringMatch getName_match() { + return name_match; + } + + public void setName_match(StringMatch name_match) { + this.name_match = name_match; + } + + public Integer getArgc() { + return argc; + } + + public void setArgc(Integer argc) { + this.argc = argc; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public List getArgp() { + return argp; + } + + public void setArgp(List argp) { + this.argp = argp; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + public static boolean isMatch(DubboMethodMatch dubboMethodMatch, String methodName, String[] parameterTypeList, Object[] parameters) { + StringMatch nameMatch = dubboMethodMatch.getName_match(); + if (nameMatch != null && !StringMatch.isMatch(nameMatch, methodName)) { + return false; + } + + Integer argc = dubboMethodMatch.getArgc(); + if (argc != null && + ((argc != 0 && (parameters == null || parameters.length == 0)) || (argc != parameters.length))) { + return false; + } + List argp = dubboMethodMatch.getArgp(); + if (argp != null) { + if (((parameterTypeList == null || parameterTypeList.length == 0) && argp.size() > 0) + || (argp.size() != parameterTypeList.length)) { + return false; + } + + for (int index = 0; index < argp.size(); index++) { + if (!StringMatch.isMatch(argp.get(index), parameterTypeList[index])) { + return false; + } + } + } + + List args = dubboMethodMatch.getArgs(); + + if (args != null && args.size() > 0) { + if (parameters == null || parameters.length == 0) { + return false; + } + + for (DubboMethodArg dubboMethodArg : args) { + int index = dubboMethodArg.getIndex(); + if (index >= parameters.length) { + throw new IndexOutOfBoundsException("DubboMethodArg index >= parameters.length"); + } + if (!DubboMethodArg.isMatch(dubboMethodArg, parameters[index])) { + return false; + } + } + } + + return true; + } + + @Override + public String toString() { + return "DubboMethodMatch{" + + "name_match=" + name_match + + ", argc=" + argc + + ", args=" + args + + ", argp=" + argp + + ", headers=" + headers + + '}'; + } +} + diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java new file mode 100644 index 000000000..b3289e20e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class ListBoolMatch { +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java new file mode 100644 index 000000000..51c4b447e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + +import java.util.List; + + +public class ListDoubleMatch { + private List oneof; + + public List getOneof() { + return oneof; + } + + public void setOneof(List oneof) { + this.oneof = oneof; + } + + public static boolean isMatch(ListDoubleMatch listDoubleMatch, Double input) { + + for (DoubleMatch doubleMatch : listDoubleMatch.getOneof()) { + if (DoubleMatch.isMatch(doubleMatch, input)) { + return true; + } + } + return false; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java new file mode 100644 index 000000000..d8f935f5e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + +import java.util.List; + + +public class ListStringMatch { + private List oneof; + + public List getOneof() { + return oneof; + } + + public void setOneof(List oneof) { + this.oneof = oneof; + } + + + public static boolean isMatch(ListStringMatch listStringMatch, String input) { + + for (StringMatch stringMatch : listStringMatch.getOneof()) { + if (StringMatch.isMatch(stringMatch, input)) { + return true; + } + } + return false; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java new file mode 100644 index 000000000..5cd746523 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.model.store.mesh.virtualservice.match; + + +public class StringMatch { + private String exact; + private String prefix; + private String regex; + private String noempty; + private String empty; + + + public String getExact() { + return exact; + } + + public void setExact(String exact) { + this.exact = exact; + } + + public String getPrefix() { + return prefix; + } + + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + public String getRegex() { + return regex; + } + + public void setRegex(String regex) { + this.regex = regex; + } + + public String getNoempty() { + return noempty; + } + + public void setNoempty(String noempty) { + this.noempty = noempty; + } + + public String getEmpty() { + return empty; + } + + public void setEmpty(String empty) { + this.empty = empty; + } + + + public static boolean isMatch(StringMatch stringMatch, String input) { + if (stringMatch.getExact() != null && input != null) { + if (input.equals(stringMatch.getExact())) { + return true; + } + } else if (stringMatch.getPrefix() != null && input != null) { + if (input.startsWith(stringMatch.getPrefix())) { + return true; + } + } else if (stringMatch.getRegex() != null && input != null) { + if (input.matches(stringMatch.getRegex())) { + return true; + } + } else if (stringMatch.getEmpty() != null) { + return input == null || "".equals(input); + } else if (stringMatch.getNoempty() != null) { + return input != null && input.length() > 0; + } else { + return false; + } + + return false; + } + + + @Override + public String toString() { + return "StringMatch{" + + "exact='" + exact + '\'' + + ", prefix='" + prefix + '\'' + + ", regex='" + regex + '\'' + + ", noempty='" + noempty + '\'' + + ", empty='" + empty + '\'' + + '}'; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/provider/MockServiceProvider.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/provider/MockServiceProvider.java new file mode 100644 index 000000000..d0bb07db2 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/provider/MockServiceProvider.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.provider; + +import org.apache.dubbo.admin.service.MockRuleService; + +import org.apache.dubbo.config.annotation.DubboService; +import org.apache.dubbo.mock.api.MockContext; +import org.apache.dubbo.mock.api.MockResult; +import org.apache.dubbo.mock.api.MockService; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * The {@link MockServiceProvider} register as a dubbo service, provide the mock function for the consumer of {@link MockService}. + */ +@DubboService +public class MockServiceProvider implements MockService { + + @Autowired + private MockRuleService mockRuleService; + + @Override + public MockResult mock(MockContext mockContext) { + return mockRuleService.getMockData(mockContext); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java index 21e739bd3..70ce83a5d 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java @@ -21,20 +21,21 @@ import org.apache.dubbo.common.extension.SPI; -@SPI("zookeeper") +@SPI("multi") public interface GovernanceConfiguration { void init(); void setUrl(URL url); URL getUrl(); - String setConfig(String key, String value); + + boolean setConfig(String key, String value); String getConfig(String key); boolean deleteConfig(String key); - String setConfig(String group, String key, String value); + boolean setConfig(String group, String key, String value); String getConfig(String group, String key); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java deleted file mode 100644 index 528df2036..000000000 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.config.impl; - -import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient; -import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO; - -import org.apache.dubbo.admin.common.util.Constants; -import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.common.utils.StringUtils; -import org.springframework.beans.factory.annotation.Value; - -import java.util.Arrays; -import java.util.stream.Collectors; - -import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; - -@SPI("apollo") -public class ApolloConfiguration implements GovernanceConfiguration { - - private static final String APOLLO_ENV_KEY = "env"; - private static final String CLUSTER_KEY = "cluster"; - private static final String TOKEN_KEY = "token"; - private static final String APOLLO_APPID_KEY = "app.id"; - private static final String APOLLO_PROTOCOL_PREFIX = "http://"; - - @Value("${admin.apollo.token:}") - private String configToken; - - @Value("${admin.apollo.cluster:}") - private String configCluster; - - @Value("${admin.apollo.namespace:}") - private String configNamespace; - - @Value("${admin.apollo.env:}") - private String configEnv; - - @Value("${admin.apollo.appId:}") - private String configAppId; - - private String token; - private String cluster; - private String namespace; - private String env; - private String appId; - private URL url; - private ApolloOpenApiClient client; - - - @Override - public void setUrl(URL url) { - this.url = url; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public void init() { - token = url.getParameter(TOKEN_KEY, configToken); - cluster = url.getParameter(CLUSTER_KEY, configCluster); - namespace = url.getParameter(Constants.NAMESPACE_KEY, configNamespace); - env = url.getParameter(APOLLO_ENV_KEY, configEnv); - appId = url.getParameter(APOLLO_APPID_KEY, configAppId); - String address = getAddressWithProtocolPrefix(url); - client = ApolloOpenApiClient.newBuilder().withPortalUrl(address).withToken(token).build(); - } - private String getAddressWithProtocolPrefix(URL url) { - String address = url.getBackupAddress(); - if (StringUtils.isNotEmpty(address)) { - address = Arrays.stream(COMMA_SPLIT_PATTERN.split(address)) - .map(addr -> { - if (addr.startsWith(APOLLO_PROTOCOL_PREFIX)) { - return addr; - } - return APOLLO_PROTOCOL_PREFIX + addr; - }) - .collect(Collectors.joining(",")); - } - return address; - } - @Override - public String setConfig(String key, String value) { - return setConfig(null, key, value); - } - - @Override - public String getConfig(String key) { - return getConfig(null, key); - } - - @Override - public boolean deleteConfig(String key) { - return deleteConfig(null, key); - } - - @Override - public String setConfig(String group, String key, String value) { - if (group == null) { - group = namespace; - } - OpenItemDTO openItemDTO = new OpenItemDTO(); - openItemDTO.setKey(key); - openItemDTO.setValue(value); - client.createItem(appId, env, cluster, group, openItemDTO); - return value; - } - - @Override - public String getConfig(String group, String key) { - if (group == null) { - group = namespace; - } - OpenItemDTO openItemDTO = client.getItem(appId, env, cluster, group, key); - if (openItemDTO != null) { - return openItemDTO.getValue(); - } - return null; - } - - @Override - public boolean deleteConfig(String group, String key) { - if (group == null) { - group = namespace; - } - //TODO user login user name as the operator - client.removeItem(appId, env, cluster, group, key, "admin"); - return true; - } - - @Override - public String getPath(String key) { - return null; - } - - @Override - public String getPath(String group, String key) { - return null; - } -} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java deleted file mode 100644 index 7c48fa7e1..000000000 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.config.impl; - -import com.ecwid.consul.v1.ConsulClient; -import com.ecwid.consul.v1.Response; -import com.ecwid.consul.v1.kv.model.GetValue; -import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -public class ConsulConfiguration implements GovernanceConfiguration { - private static final Logger logger = LoggerFactory.getLogger(ConsulConfiguration.class); - private static final int DEFAULT_PORT = 8500; - private static final String SLASH = "/"; - private URL url; - private ConsulClient client; - - @Override - public void init() { - String host = this.url.getHost(); - int port = this.url.getPort() != 0 ? url.getPort() : DEFAULT_PORT; - this.client = new ConsulClient(host, port); - } - - @Override - public void setUrl(URL url) { - this.url = url; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public String setConfig(String key, String value) { - return setConfig(null, key, value); - } - - @Override - public String getConfig(String key) { - return getConfig(null, key); - } - - @Override - public boolean deleteConfig(String key) { - return deleteConfig(null, key); - } - - @Override - public String setConfig(String group, String key, String value) { - if (group == null) { - client.setKVValue(key, value); - return value; - } - client.setKVValue(group + SLASH + key, value); - return value; - } - - @Override - public String getConfig(String group, String key) { - if (group == null) { - Response response = client.getKVValue(key); - if (response.getValue() == null) { - return null; - } - return response.getValue().getDecodedValue(); - } - Response response = client.getKVValue(group + SLASH + key); - return response.getValue() == null ? null : response.getValue().getDecodedValue(); - } - - @Override - public boolean deleteConfig(String group, String key) { - try { - if (group == null) { - client.deleteKVValue(key); - return true; - } - client.deleteKVValue(group + SLASH + key); - } catch (Exception e) { - logger.error(e.getMessage(), e); - return false; - } - return true; - } - - @Override - public String getPath(String key) { - return null; - } - - @Override - public String getPath(String group, String key) { - return null; - } - -} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java new file mode 100644 index 000000000..ed870a8b1 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.config.impl; + + +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; +import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory; +import org.apache.dubbo.common.extension.ExtensionLoader; + +/** + * Use {@link org.apache.dubbo.common.config.configcenter.DynamicConfiguration} adaptation Configuration Center + */ +public class MultiDynamicConfiguration implements GovernanceConfiguration { + + private URL url; + + private DynamicConfiguration dynamicConfiguration; + + private String group; + + @Override + public void init() { + if (url == null) { + throw new IllegalStateException("server url is null, cannot init"); + } + DynamicConfigurationFactory dynamicConfigurationFactory = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class) + .getOrDefaultExtension(url.getProtocol()); + dynamicConfiguration = dynamicConfigurationFactory.getDynamicConfiguration(url); + // group must be consistent with dubbo + group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_GROUP); + } + + @Override + public void setUrl(URL url) { + this.url = url; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public boolean setConfig(String key, String value) { + return setConfig(group, key, value); + } + + @Override + public String getConfig(String key) { + return getConfig(group, key); + } + + @Override + public boolean deleteConfig(String key) { + return deleteConfig(group, key); + } + + @Override + public boolean setConfig(String group, String key, String value) { + if (key == null || value == null) { + throw new IllegalArgumentException("key or value cannot be null"); + } + return dynamicConfiguration.publishConfig(key, group, value); + } + + @Override + public String getConfig(String group, String key) { + if (key == null) { + throw new IllegalArgumentException("key cannot be null"); + } + return dynamicConfiguration.getConfig(key, group); + } + + @Override + public boolean deleteConfig(String group, String key) { + if (key == null) { + throw new IllegalArgumentException("key cannot be null"); + } + return dynamicConfiguration.removeConfig(key, group); + } + + @Override + public String getPath(String key) { + return null; + } + + @Override + public String getPath(String group, String key) { + return null; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java deleted file mode 100644 index f5d0c7bb0..000000000 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.config.impl; - -import com.alibaba.nacos.api.PropertyKeyConst; -import java.util.Map; -import org.apache.dubbo.admin.common.util.Constants; -import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.StringConstantFieldValuePredicate; - -import com.alibaba.nacos.api.NacosFactory; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.exception.NacosException; -import org.apache.commons.lang3.StringUtils; - -import java.util.Properties; - -import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; -import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE; - -public class NacosConfiguration implements GovernanceConfiguration { - private static final Logger logger = LoggerFactory.getLogger(NacosConfiguration.class); - - private ConfigService configService; - private String group; - private URL url; - - @Override - public void init() { - group = url.getParameter(Constants.GROUP_KEY, "DEFAULT_GROUP"); - configService = buildConfigService(url); - } - - private ConfigService buildConfigService(URL url) { - Properties nacosProperties = buildNacosProperties(url); - try { - configService = NacosFactory.createConfigService(nacosProperties); - } catch (NacosException e) { - if (logger.isErrorEnabled()) { - logger.error(e.getErrMsg(), e); - } - throw new IllegalStateException(e); - } - return configService; - } - - private Properties buildNacosProperties(URL url) { - Properties properties = new Properties(); - setServerAddr(url, properties); - setNamespace(url, properties); - Map parameters = url.getParameters( - StringConstantFieldValuePredicate.of(PropertyKeyConst.class)); - properties.putAll(parameters); - return properties; - } - - private void setServerAddr(URL url, Properties properties) { - - String serverAddr = url.getHost() + // Host - ":" + - url.getPort() // Port - ; - properties.put(SERVER_ADDR, serverAddr); - } - - private void setNamespace(URL url, Properties properties) { - String namespace = url.getParameter(NAMESPACE); - if (StringUtils.isNotBlank(namespace)) { - properties.put(NAMESPACE, namespace); - } - } - - - @Override - public void setUrl(URL url) { - this.url = url; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public String setConfig(String key, String value) { - return setConfig(group, key, value); - } - - @Override - public String getConfig(String key) { - return getConfig(group, key); - } - - @Override - public boolean deleteConfig(String key) { - return deleteConfig(group, key); - } - - @Override - public String setConfig(String group, String key, String value) { - String[] groupAndDataId = parseGroupAndDataId(key, group); - if (null == groupAndDataId) { - return null; - } - - try { - configService.publishConfig(groupAndDataId[1], groupAndDataId[0], value); - return value; - } catch (NacosException e) { - logger.error(e.getMessage(), e); - - } - return null; - } - - @Override - public String getConfig(String group, String key) { - String[] groupAndDataId = parseGroupAndDataId(key, group); - if (null == groupAndDataId) { - return null; - } - try { - return configService.getConfig(groupAndDataId[1], groupAndDataId[0],1000 * 10); - } catch (NacosException e) { - logger.error(e.getMessage(), e); - } - return null; - } - - @Override - public boolean deleteConfig(String group, String key) { - String[] groupAndDataId = parseGroupAndDataId(key, group); - if (null == groupAndDataId) { - return false; - } - try { - return configService.removeConfig(groupAndDataId[1], groupAndDataId[0]); - } catch (NacosException e) { - logger.error(e.getMessage(), e); - } - return false; - } - - @Override - public String getPath(String key) { - return null; - } - - @Override - public String getPath(String group, String key) { - return null; - } - - private String[] parseGroupAndDataId(String key, String group) { - if (StringUtils.isBlank(key) || StringUtils.isBlank(group)) { - if (logger.isWarnEnabled()) { - logger.warn("key or group is blank"); - return null; - } - } - - String[] groupAndDataId = new String[2]; - String[] split = key.split("/"); - if (split.length != 3) { - return null; - } - if (Constants.DUBBO_PROPERTY.equals(split[2])) { - - if (this.group.equals(split[1])) { - groupAndDataId[0] = this.group; - } else { - groupAndDataId[0] = split[1]; - } - groupAndDataId[1] = split[2]; - } else { - groupAndDataId[0] = group; - groupAndDataId[1] = split[2]; - } - return groupAndDataId; - } -} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java index 5c4fd1819..e5cead735 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java @@ -38,8 +38,8 @@ public URL getUrl() { } @Override - public String setConfig(String key, String value) { - return null; + public boolean setConfig(String key, String value) { + return false; } @Override @@ -53,8 +53,8 @@ public boolean deleteConfig(String key) { } @Override - public String setConfig(String group, String key, String value) { - return null; + public boolean setConfig(String group, String key, String value) { + return false; } @Override diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java deleted file mode 100644 index 362dd2616..000000000 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.config.impl; - -import org.apache.commons.lang3.StringUtils; -import org.apache.curator.framework.CuratorFramework; -import org.apache.curator.framework.CuratorFrameworkFactory; -import org.apache.curator.retry.ExponentialBackoffRetry; -import org.apache.dubbo.admin.common.util.Constants; -import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; - -public class ZookeeperConfiguration implements GovernanceConfiguration { - private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class); - private CuratorFramework zkClient; - private URL url; - private String root; - - @Override - public void setUrl(URL url) { - this.url = url; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public void init() { - if (url == null) { - throw new IllegalStateException("server url is null, cannot init"); - } - CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder(). - connectString(url.getAddress()). - retryPolicy(new ExponentialBackoffRetry(1000, 3)); - if (StringUtils.isNotEmpty(url.getUsername()) && StringUtils.isNotEmpty(url.getPassword())) { - // add authorization - String auth = url.getUsername() + ":" + url.getPassword(); - zkClientBuilder.authorization("digest", auth.getBytes()); - } - zkClient = zkClientBuilder.build(); - String group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_ROOT); - if (!group.startsWith(Constants.PATH_SEPARATOR)) { - group = Constants.PATH_SEPARATOR + group; - } - root = group; - zkClient.start(); - } - - @Override - public String setConfig(String key, String value) { - return setConfig(null, key, value); - } - - @Override - public String getConfig(String key) { - return getConfig(null, key); - } - - @Override - public boolean deleteConfig(String key) { - return deleteConfig(null, key); - } - - @Override - public String setConfig(String group, String key, String value) { - if (key == null || value == null) { - throw new IllegalArgumentException("key or value cannot be null"); - } - String path = getNodePath(key, group); - try { - if (zkClient.checkExists().forPath(path) == null) { - zkClient.create().creatingParentsIfNeeded().forPath(path); - } - zkClient.setData().forPath(path, value.getBytes()); - return value; - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - return null; - } - - @Override - public String getConfig(String group, String key) { - if (key == null) { - throw new IllegalArgumentException("key cannot be null"); - } - String path = getNodePath(key, group); - - try { - if (zkClient.checkExists().forPath(path) == null) { - return null; - } - return new String(zkClient.getData().forPath(path)); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - return null; - } - - @Override - public boolean deleteConfig(String group, String key) { - if (key == null) { - throw new IllegalArgumentException("key cannot be null"); - } - String path = getNodePath(key, group); - try { - zkClient.delete().forPath(path); - } catch (Exception e) { - logger.error(e.getMessage(), e); - return false; - } - return true; - } - - @Override - public String getPath(String key) { - return getNodePath(key, null); - } - - @Override - public String getPath(String group, String key) { - return getNodePath(key, group); - } - - private String getNodePath(String path, String group) { - if (path == null) { - throw new IllegalArgumentException("path cannot be null"); - } - return toRootDir(group) + path; - } - - private String toRootDir(String group) { - if (group != null) { - if (!group.startsWith(Constants.PATH_SEPARATOR)) { - root = Constants.PATH_SEPARATOR + group; - } else { - root = group; - } - } - if (root.equals(Constants.PATH_SEPARATOR)) { - return root; - } - return root + Constants.PATH_SEPARATOR; - } -} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java new file mode 100644 index 000000000..076bb5680 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping; + +import org.apache.dubbo.common.URL; + +import java.util.List; + +public interface AddressChangeListener { + + /** + * notify instance address url change + * @param protocolServiceKey {group}/{path/interfaceName}:{version}:protocol + * @param urls instance address url + */ + void notifyAddressChanged(String protocolServiceKey, List urls); +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java new file mode 100644 index 000000000..750c7347e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping; + +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.service.impl.InstanceRegistryCache; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.metadata.MappingChangedEvent; +import org.apache.dubbo.metadata.MappingListener; +import org.apache.dubbo.registry.client.InstanceAddressURL; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.apache.dubbo.registry.client.ServiceInstance; +import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; + +import com.google.common.collect.Sets; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + +public class AdminMappingListener implements MappingListener { + + private static final URL CONSUMER_URL = new URL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0, "", + Constants.INTERFACE_KEY, Constants.ANY_VALUE, + Constants.GROUP_KEY, Constants.ANY_VALUE, + Constants.VERSION_KEY, Constants.ANY_VALUE, + Constants.CLASSIFIER_KEY, Constants.ANY_VALUE, + Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + "," + + Constants.CONSUMERS_CATEGORY + "," + + Constants.ROUTERS_CATEGORY + "," + + Constants.CONFIGURATORS_CATEGORY, + Constants.ENABLED_KEY, Constants.ANY_VALUE, + Constants.CHECK_KEY, String.valueOf(false)); + + /* app - listener */ + private final Map serviceListeners = new ConcurrentHashMap<>(); + + private final ServiceDiscovery serviceDiscovery; + + private final InstanceRegistryCache instanceRegistryCache; + + public AdminMappingListener(ServiceDiscovery serviceDiscovery, InstanceRegistryCache instanceRegistryCache) { + this.serviceDiscovery = serviceDiscovery; + this.instanceRegistryCache = instanceRegistryCache; + } + + @Override + public void onEvent(MappingChangedEvent event) { + Set apps = event.getApps(); + if (CollectionUtils.isEmpty(apps)) { + return; + } + for (String serviceName : apps) { + ServiceInstancesChangedListener serviceInstancesChangedListener = serviceListeners.get(serviceName); + if (serviceInstancesChangedListener == null) { + synchronized (this) { + serviceInstancesChangedListener = serviceListeners.get(serviceName); + if (serviceInstancesChangedListener == null) { + AddressChangeListener addressChangeListener = new DefaultAddressChangeListener(serviceName, instanceRegistryCache); + serviceInstancesChangedListener = new AdminServiceInstancesChangedListener(Sets.newHashSet(serviceName), serviceDiscovery, addressChangeListener); + serviceInstancesChangedListener.setUrl(CONSUMER_URL); + List serviceInstances = serviceDiscovery.getInstances(serviceName); + if (CollectionUtils.isNotEmpty(serviceInstances)) { + serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances)); + } + serviceListeners.put(serviceName, serviceInstancesChangedListener); + serviceInstancesChangedListener.setUrl(CONSUMER_URL); + serviceDiscovery.addServiceInstancesChangedListener(serviceInstancesChangedListener); + } + } + } + } + } + + private static class DefaultAddressChangeListener implements AddressChangeListener { + + private String serviceName; + + private InstanceRegistryCache instanceRegistryCache; + + public DefaultAddressChangeListener(String serviceName, InstanceRegistryCache instanceRegistryCache) { + this.serviceName = serviceName; + this.instanceRegistryCache = instanceRegistryCache; + } + + @Override + public void notifyAddressChanged(String protocolServiceKey, List urls) { + String serviceKey = removeProtocol(protocolServiceKey); + ConcurrentMap>> appServiceMap = instanceRegistryCache.computeIfAbsent(Constants.PROVIDERS_CATEGORY, key -> new ConcurrentHashMap<>()); + Map> serviceMap = appServiceMap.computeIfAbsent(serviceName, key -> new ConcurrentHashMap<>()); + if (CollectionUtils.isEmpty(urls)) { + serviceMap.remove(serviceKey); + } else { + List instanceAddressUrls = urls.stream().map(url -> (InstanceAddressURL) url).collect(Collectors.toList()); + serviceMap.put(serviceKey, instanceAddressUrls); + } + } + + private String removeProtocol(String protocolServiceKey) { + int index = protocolServiceKey.lastIndexOf(":"); + if (index == -1) { + return protocolServiceKey; + } + return protocolServiceKey.substring(0, index); + } + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java new file mode 100644 index 000000000..1afde5539 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.registry.client.ServiceDiscovery; +import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class AdminServiceInstancesChangedListener extends ServiceInstancesChangedListener { + + private AddressChangeListener addressChangeListener; + + private Map oldServiceUrls; + + public AdminServiceInstancesChangedListener(Set serviceNames, ServiceDiscovery serviceDiscovery, AddressChangeListener addressChangeListener) { + super(serviceNames, serviceDiscovery); + this.addressChangeListener = addressChangeListener; + oldServiceUrls = new HashMap<>(); + } + + protected void notifyAddressChanged() { + oldServiceUrls.keySet().stream() + .filter(protocolServiceKey -> !serviceUrls.containsKey(protocolServiceKey)) + .forEach(protocolServiceKey -> addressChangeListener.notifyAddressChanged(protocolServiceKey, new ArrayList<>())); + serviceUrls.forEach((protocolServiceKey, urls) -> addressChangeListener.notifyAddressChanged(protocolServiceKey, (List) urls)); + + oldServiceUrls = serviceUrls; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java new file mode 100644 index 000000000..6559a2996 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.metadata.MappingListener; + +/** + * listen all mapping group service + */ +@SPI("zookeeper") +public interface ServiceMapping { + + void init(URL url); + + void listenerAll(); + + void addMappingListener(MappingListener listener); + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NacosServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NacosServiceMapping.java new file mode 100644 index 000000000..a7d25c913 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NacosServiceMapping.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping.impl; + +import org.apache.dubbo.admin.registry.mapping.ServiceMapping; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.metadata.MappingChangedEvent; +import org.apache.dubbo.metadata.MappingListener; +import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper; +import org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils; + +import com.alibaba.nacos.api.common.Constants; +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.pojo.ListView; +import com.google.common.collect.Sets; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START; +import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; +import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY; + +/** + * Nacos not support batch listen config feature. Therefore, regularly query the service list instead of notification + */ +public class NacosServiceMapping implements ServiceMapping { + + /** + * All 2.x supported categories + */ + private static final List ALL_SUPPORTED_CATEGORIES = Arrays.asList( + PROVIDERS_CATEGORY, + CONSUMERS_CATEGORY, + ROUTERS_CATEGORY, + CONFIGURATORS_CATEGORY + ); + + /** + * The separator for service name + * Change a constant to be configurable, it's designed for Windows file name that is compatible with old + * Nacos binary release(< 0.6.1) + */ + private static final String SERVICE_NAME_SEPARATOR = System.getProperty("nacos.service.name.separator", ":"); + + private static final long LOOKUP_INTERVAL = Long.getLong("nacos.service.names.lookup.interval", 30); + + private ScheduledExecutorService scheduledExecutorService; + + private final Set listeners = new ConcurrentHashSet<>(); + + private static final int PAGINATION_SIZE = 100; + + private NacosNamingServiceWrapper namingService; + + private Set anyServices = new HashSet<>(); + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosServiceMapping.class); + + @Override + public void init(URL url) { + url.addParameter(NAMING_LOAD_CACHE_AT_START, "false"); + namingService = NacosNamingServiceUtils.createNamingService(url); + scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + listenerAll(); + } + + @Override + public void listenerAll() { + + try { + anyServices = getAllServiceNames().stream().filter(this::filterApplication).collect(Collectors.toSet()); + } catch (Exception e) { + LOGGER.error("Get nacos all services fail ", e); + } + for (String service : anyServices) { + notifyMappingChangedEvent(service); + } + scheduledExecutorService.scheduleAtFixedRate(() -> { + try { + Set serviceNames = getAllServiceNames(); + for (String serviceName : serviceNames) { + if (filterApplication(serviceName) && anyServices.add(serviceName)) { + notifyMappingChangedEvent(serviceName); + } + } + } catch (Exception e) { + LOGGER.error("Get nacos all services fail ", e); + } + + }, LOOKUP_INTERVAL, LOOKUP_INTERVAL, TimeUnit.SECONDS); + } + + private Set getAllServiceNames() throws NacosException { + + Set serviceNames = new HashSet<>(); + int pageIndex = 1; + ListView listView = namingService.getServicesOfServer(pageIndex, PAGINATION_SIZE, + Constants.DEFAULT_GROUP); + // First page data + List firstPageData = listView.getData(); + // Append first page into list + serviceNames.addAll(firstPageData); + // the total count + int count = listView.getCount(); + // the number of pages + int pageNumbers = count / PAGINATION_SIZE; + int remainder = count % PAGINATION_SIZE; + // remain + if (remainder > 0) { + pageNumbers += 1; + } + // If more than 1 page + while (pageIndex < pageNumbers) { + listView = namingService.getServicesOfServer(++pageIndex, PAGINATION_SIZE, Constants.DEFAULT_GROUP); + serviceNames.addAll(listView.getData()); + } + + return serviceNames; + } + + private boolean filterApplication(String serviceName) { + if (StringUtils.isBlank(serviceName)) { + return false; + } + for (String category : ALL_SUPPORTED_CATEGORIES) { + String prefix = category + SERVICE_NAME_SEPARATOR; + if (serviceName.startsWith(prefix)) { + return false; + } + } + return true; + } + + private void notifyMappingChangedEvent(String service) { + MappingChangedEvent event = new MappingChangedEvent(null, Sets.newHashSet(service)); + for (MappingListener listener : listeners) { + listener.onEvent(event); + } + } + + + @Override + public void addMappingListener(MappingListener listener) { + listeners.add(listener); + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java new file mode 100644 index 000000000..845efa2aa --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping.impl; + +import org.apache.dubbo.admin.registry.mapping.ServiceMapping; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.metadata.MappingListener; + +public class NoOpServiceMapping implements ServiceMapping { + + @Override + public void init(URL url) { + + } + + @Override + public void listenerAll() { + + } + + @Override + public void addMappingListener(MappingListener listener) { + + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java new file mode 100644 index 000000000..799c0403d --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.mapping.impl; + +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.registry.mapping.ServiceMapping; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.metadata.MappingChangedEvent; +import org.apache.dubbo.metadata.MappingListener; +import org.apache.dubbo.remoting.zookeeper.ZookeeperClient; +import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter; + +import java.util.List; +import java.util.Set; + +import static org.apache.dubbo.metadata.ServiceNameMapping.getAppNames; + + +public class ZookeeperServiceMapping implements ServiceMapping { + + private ZookeeperClient zkClient; + + private final static String MAPPING_PATH = Constants.PATH_SEPARATOR + Constants.DEFAULT_ROOT + Constants.PATH_SEPARATOR + Constants.DEFAULT_MAPPING_GROUP; + + private final Set listeners = new ConcurrentHashSet<>(); + + private final Set anyServices = new ConcurrentHashSet<>(); + + @Override + public void init(URL url) { + ZookeeperTransporter zookeeperTransporter = ZookeeperTransporter.getExtension(); + zkClient = zookeeperTransporter.connect(url); + listenerAll(); + } + + @Override + public void listenerAll() { + zkClient.create(MAPPING_PATH, false); + List services = zkClient.addChildListener(MAPPING_PATH, (path, currentChildList) -> { + for (String child : currentChildList) { + if (anyServices.add(child)) { + notifyMappingChangedEvent(child); + } + } + }); + if (CollectionUtils.isNotEmpty(services)) { + for (String service : services) { + if (anyServices.add(service)) { + notifyMappingChangedEvent(service); + } + } + } + } + + private void notifyMappingChangedEvent(String service) { + if (service.equals(Constants.CONFIGURATORS_CATEGORY) || service.equals(Constants.CONSUMERS_CATEGORY) + || service.equals(Constants.PROVIDERS_CATEGORY) || service.equals(Constants.ROUTERS_CATEGORY)) { + return; + } + String servicePath = MAPPING_PATH + Constants.PATH_SEPARATOR + service; + String content = zkClient.getContent(servicePath); + if (content != null) { + Set apps = getAppNames(content); + MappingChangedEvent event = new MappingChangedEvent(service, apps); + for (MappingListener listener : listeners) { + listener.onEvent(event); + } + } + } + + @Override + public void addMappingListener(MappingListener listener) { + listeners.add(listener); + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java new file mode 100644 index 000000000..708dd7ef8 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service; + +import org.apache.dubbo.admin.model.dto.MeshRouteDTO; + +public interface MeshRouteService { + + /** + * create mesh rule route + * + * @param meshRoute dto + * @return success + */ + boolean createMeshRule(MeshRouteDTO meshRoute); + + /** + * update mesh rule route + * + * @param meshRoute dto + * @return success + */ + boolean updateMeshRule(MeshRouteDTO meshRoute); + + /** + * delete mesh rule + * + * @param id id + * @return success + */ + boolean deleteMeshRule(String id); + + /** + * find mesh rule by id + * + * @param id id + * @return dto + */ + MeshRouteDTO findMeshRoute(String id); + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MockRuleService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MockRuleService.java new file mode 100644 index 000000000..23892197d --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MockRuleService.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service; + +import org.apache.dubbo.admin.model.dto.MockRuleDTO; + +import org.apache.dubbo.mock.api.MockContext; +import org.apache.dubbo.mock.api.MockResult; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +/** + * The {@link MockRuleService} mainly works on the function of response the request of mock consumer + * and maintain the mock rule data. + */ +public interface MockRuleService { + + /** + * create or update mock rule. if the request contains id, then will be an update operation. + * + * @param mockRule mock rule. + */ + void createOrUpdateMockRule(MockRuleDTO mockRule); + + /** + * delete the mock rule data by mock rule id. + * + * @param id mock rule id. + */ + void deleteMockRuleById(Long id); + + /** + * list the mock rules by filter and return data by page. + * + * @param filter filter condition. + * @param pageable pageable params. + * @return mock rules by page. + */ + Page listMockRulesByPage(String filter, Pageable pageable); + + /** + * return the mock rule data by {@link MockContext}. + * + * @param mockContext mock context provide by consumer. + * @return mock data. + */ + MockResult getMockData(MockContext mockContext); +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java index 95d46f857..5417d3022 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java @@ -25,26 +25,11 @@ /** * ProviderService - * */ public interface ProviderService { void create(Provider provider); -// void enableProvider(String id); - -// void disableProvider(String id); - -// void doublingProvider(String id); - -// void halvingProvider(String id); - - void deleteStaticProvider(String id); - - void updateProvider(Provider provider); - - Provider findProvider(String id); - String getProviderMetaData(MetadataIdentifier providerIdentifier); /** @@ -54,18 +39,20 @@ public interface ProviderService { */ Set findServices(); + /** + * Get all instance registry provider's service name + * + * @return list of all provider's service name + */ + Set findInstanceApplications(); + + String findServiceVersion(String serviceName, String application); String findVersionInApplication(String application); List findAddresses(); - List findAddressesByApplication(String application); - - List findAddressesByService(String serviceName); - - List findApplicationsByServiceName(String serviceName); - /** * Get provider list with specific service name. * @@ -74,8 +61,6 @@ public interface ProviderService { */ List findByService(String serviceName); - List findByAppandService(String app, String serviceName); - List findAll(); /** @@ -86,8 +71,6 @@ public interface ProviderService { */ List findByAddress(String providerAddress); - List findServicesByAddress(String providerAddress); - Set findApplications(); /** @@ -100,13 +83,9 @@ public interface ProviderService { List findServicesByApplication(String application); - List findMethodsByService(String serviceName); - - Provider findByServiceAndAddress(String service, String address); - /** * Get a set of service data object. - * + *

* ServiceDTO object contains base information include * service name , application, group and version. * diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java new file mode 100644 index 000000000..0335909e2 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service; + +import java.util.function.Function; + +/** + * cache registry url + */ +public interface RegistryCache { + + /** + * put cache + * + * @param key key + * @param value value + */ + void put(K key, V value); + + /** + * get cache + * + * @param key key + * @return value + */ + V get(K key); + + + default V computeIfAbsent(K key, Function mappingFunction) { + return null; + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java index f57cdb3d1..3e6669464 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java @@ -19,6 +19,8 @@ import org.apache.dubbo.admin.common.util.CoderUtil; import org.apache.dubbo.admin.common.util.Constants; import org.apache.dubbo.admin.common.util.Tool; +import org.apache.dubbo.admin.service.impl.InterfaceRegistryCache; +import org.apache.dubbo.common.BaseServiceMetadata; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -26,6 +28,7 @@ import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; + import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; @@ -39,7 +42,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicLong; @Component public class RegistryServerSync implements DisposableBean, NotifyListener { @@ -58,8 +60,6 @@ public class RegistryServerSync implements DisposableBean, NotifyListener { Constants.ENABLED_KEY, Constants.ANY_VALUE, Constants.CHECK_KEY, String.valueOf(false)); - private static final AtomicLong ID = new AtomicLong(); - /** * Make sure ID never changed when the same url notified many times */ @@ -69,13 +69,11 @@ public class RegistryServerSync implements DisposableBean, NotifyListener { * ConcurrentMap>> * registryCache */ - private final ConcurrentMap>> registryCache = new ConcurrentHashMap<>(); @Autowired private Registry registry; - public ConcurrentMap>> getRegistryCache() { - return registryCache; - } + @Autowired + private InterfaceRegistryCache interfaceRegistryCache; @EventListener(classes = ApplicationReadyEvent.class) public void startSubscribe() { @@ -88,7 +86,7 @@ public void destroy() throws Exception { registry.unsubscribe(SUBSCRIBE, this); } - // Notification of of any service with any type (override、subcribe、route、provider) is full. + // Notification of any service with any type (override、subscribe、route、provider) is full. @Override public void notify(List urls) { if (urls == null || urls.isEmpty()) { @@ -98,20 +96,23 @@ public void notify(List urls) { final Map>> categories = new HashMap<>(); String interfaceName = null; for (URL url : urls) { - String category = url.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); + String category = url.getUrlParam().getParameter(Constants.CATEGORY_KEY); + if (category == null) { + category = Constants.PROVIDERS_CATEGORY; + } // NOTE: group and version in empty protocol is * if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { - ConcurrentMap> services = registryCache.get(category); + ConcurrentMap> services = interfaceRegistryCache.get(category); if (services != null) { - String group = url.getParameter(Constants.GROUP_KEY); - String version = url.getParameter(Constants.VERSION_KEY); + String group = url.getUrlParam().getParameter(Constants.GROUP_KEY); + String version = url.getUrlParam().getParameter(Constants.VERSION_KEY); // NOTE: group and version in empty protocol is * if (!Constants.ANY_VALUE.equals(group) && !Constants.ANY_VALUE.equals(version)) { - services.remove(url.getServiceKey()); + services.remove(getServiceInterface(url)); } else { for (Map.Entry> serviceEntry : services.entrySet()) { String service = serviceEntry.getKey(); - if (Tool.getInterface(service).equals(url.getServiceInterface()) + if (Tool.getInterface(service).equals(getServiceInterface(url)) && (Constants.ANY_VALUE.equals(group) || StringUtils.isEquals(group, Tool.getGroup(service))) && (Constants.ANY_VALUE.equals(version) || StringUtils.isEquals(version, Tool.getVersion(service)))) { services.remove(service); @@ -121,14 +122,16 @@ public void notify(List urls) { } } else { if (StringUtils.isEmpty(interfaceName)) { - interfaceName = url.getServiceInterface(); + interfaceName = getServiceInterface(url); } Map> services = categories.get(category); if (services == null) { services = new HashMap<>(); categories.put(category, services); } - String service = url.getServiceKey(); + String group = url.getUrlParam().getParameter(Constants.GROUP_KEY); + String version = url.getUrlParam().getParameter(Constants.VERSION_KEY); + String service = BaseServiceMetadata.buildServiceKey(getServiceInterface(url), group, version); Map ids = services.get(service); if (ids == null) { ids = new HashMap<>(); @@ -150,14 +153,14 @@ public void notify(List urls) { } for (Map.Entry>> categoryEntry : categories.entrySet()) { String category = categoryEntry.getKey(); - ConcurrentMap> services = registryCache.get(category); + ConcurrentMap> services = interfaceRegistryCache.get(category); if (services == null) { - services = new ConcurrentHashMap>(); - registryCache.put(category, services); + services = new ConcurrentHashMap<>(); + interfaceRegistryCache.put(category, services); } else {// Fix map can not be cleared when service is unregistered: when a unique “group/service:version” service is unregistered, but we still have the same services with different version or group, so empty protocols can not be invoked. - Set keys = new HashSet(services.keySet()); + Set keys = new HashSet<>(services.keySet()); for (String key : keys) { - if (Tool.getInterface(key).equals(interfaceName) && !categoryEntry.getValue().entrySet().contains(key)) { + if (Tool.getInterface(key).equals(interfaceName) && !categoryEntry.getValue().containsKey(key)) { services.remove(key); } } @@ -165,5 +168,14 @@ public void notify(List urls) { services.putAll(categoryEntry.getValue()); } } + + private String getServiceInterface(URL url) { + String serviceInterface = url.getServiceInterface(); + if (StringUtils.isBlank(serviceInterface) || Constants.ANY_VALUE.equals(serviceInterface)) { + serviceInterface = url.getPath(); + } + return serviceInterface; + } + } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java index f7bae0d49..501b13eca 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java @@ -18,7 +18,6 @@ import org.apache.dubbo.admin.registry.config.GovernanceConfiguration; import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; -import org.apache.dubbo.admin.service.RegistryServerSync; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -42,10 +41,10 @@ public class AbstractService { protected MetaDataCollector metaDataCollector; @Autowired - private RegistryServerSync sync; + private InterfaceRegistryCache interfaceRegistryCache; - public ConcurrentMap>> getRegistryCache() { - return sync.getRegistryCache(); + public ConcurrentMap>> getInterfaceRegistryCache() { + return interfaceRegistryCache.getRegistryCache(); } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java index 4a803ed63..0d0f2e595 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java @@ -52,7 +52,7 @@ public String getConsumerMetadata(MetadataIdentifier consumerIdentifier) { private Map findAllConsumerUrl() { Map filter = new HashMap(); filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @@ -69,7 +69,7 @@ private Map findConsumerUrlByAddress(String address) { filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY); filter.put(SyncUtils.ADDRESS_FILTER_KEY, address); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } public Map findConsumerUrlByService(String service) { @@ -77,7 +77,7 @@ public Map findConsumerUrlByService(String service) { filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY); filter.put(SyncUtils.SERVICE_FILTER_KEY, service); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @Override @@ -85,7 +85,7 @@ public String findVersionInApplication(String application) { Map filter = new HashMap<>(); filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY); filter.put(Constants.APPLICATION_KEY, application); - Map stringURLMap = SyncUtils.filterFromCategory(getRegistryCache(), filter); + Map stringURLMap = SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); if (stringURLMap == null || stringURLMap.isEmpty()) { throw new ParamValidationException("there is no consumer for application: " + application); } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java index 8fe492c50..11becca8e 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java @@ -73,7 +73,8 @@ public Object invoke(String service, String method, String[] parameterTypes, Obj reference.setInterface(intf); reference.setVersion(version); reference.setGroup(group); - + //Keep it consistent with the ConfigManager cache + reference.setSticky(false); try { removeGenericSymbol(parameterTypes); GenericService genericService = reference.get(); diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java new file mode 100644 index 000000000..9f1b5acaa --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service.impl; + +import org.apache.dubbo.admin.service.RegistryCache; +import org.apache.dubbo.registry.client.InstanceAddressURL; + +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +/** + * instance registry url {@link InstanceAddressURL} cache + * key --> category,value --> ConcurrentMap>> + */ +@Component +public class InstanceRegistryCache implements RegistryCache>>> { + + private final ConcurrentMap>>> registryCache = new ConcurrentHashMap<>(); + + @Override + public void put(String key, ConcurrentMap>> value) { + registryCache.put(key, value); + } + + @Override + public ConcurrentMap>> get(String key) { + return registryCache.get(key); + } + + @Override + public ConcurrentMap>> computeIfAbsent(String key, + Function>>> mappingFunction) { + return registryCache.computeIfAbsent(key, mappingFunction); + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java new file mode 100644 index 000000000..aae6e6579 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service.impl; + +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.model.domain.Provider; +import org.apache.dubbo.admin.model.domain.RegistrySource; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.metadata.MetadataInfo; +import org.apache.dubbo.registry.client.InstanceAddressURL; +import org.apache.dubbo.registry.client.ServiceInstance; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + +@Component +public class InstanceRegistryQueryHelper { + + private final InstanceRegistryCache instanceRegistryCache; + + public InstanceRegistryQueryHelper(InstanceRegistryCache instanceRegistryCache) { + this.instanceRegistryCache = instanceRegistryCache; + } + + + public Set findServices() { + Set services = Sets.newHashSet(); + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null) { + return services; + } + appInterfaceMap.values().forEach(serviceUrlMap -> + serviceUrlMap.forEach((service, urls) -> { + if (CollectionUtils.isNotEmpty(urls)) { + services.add(service); + } + })); + return services; + } + + public Set findApplications() { + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null) { + return Sets.newHashSet(); + } + return Sets.newHashSet(appInterfaceMap.keySet()); + } + + public List findByService(String serviceName) { + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null) { + return Lists.newArrayList(); + } + List providerUrls = Lists.newArrayList(); + appInterfaceMap.values().forEach(serviceUrlMap -> + serviceUrlMap.forEach((service, urls) -> { + if (CollectionUtils.isNotEmpty(urls) && service.equals(serviceName)) { + providerUrls.addAll(urls); + } + })); + return urlsToProviderList(providerUrls).stream() + .filter(provider -> provider.getService().equals(serviceName)) + .collect(Collectors.toList()); + } + + public List findByAddress(String providerAddress) { + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null) { + return Lists.newArrayList(); + } + List providerUrls = Lists.newArrayList(); + appInterfaceMap.values().forEach(serviceUrlMap -> + serviceUrlMap.forEach((service, urls) -> { + if (CollectionUtils.isNotEmpty(urls)) { + urls.forEach(url -> { + if ((url.getInstance().getHost().equals(providerAddress))) { + providerUrls.add(url); + } + }); + } + })); + return urlsToProviderList(providerUrls); + } + + public List findByApplication(String application) { + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null || appInterfaceMap.get(application) == null) { + return Lists.newArrayList(); + } + List providerUrls = Lists.newArrayList(); + appInterfaceMap.get(application).forEach((service, urls) -> providerUrls.addAll(urls)); + return urlsToProviderList(providerUrls); + } + + public String findVersionInApplication(String application) { + ConcurrentMap>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY); + if (appInterfaceMap == null || appInterfaceMap.get(application) == null) { + return null; + } + Map> urlsMap = appInterfaceMap.get(application); + for (Map.Entry> entry : urlsMap.entrySet()) { + List urls = entry.getValue(); + if (CollectionUtils.isNotEmpty(urls)) { + return urls.get(0).getParameter(Constants.SPECIFICATION_VERSION_KEY, "3.0.0"); + } + } + return null; + } + + private List urlsToProviderList(List urls) { + List providers = Lists.newArrayList(); + urls.stream().distinct().forEach(url -> { + ServiceInstance instance = url.getInstance(); + MetadataInfo metadataInfo = url.getMetadataInfo(); + + metadataInfo.getServices().forEach((serviceKey, serviceInfo) -> { + Provider p = new Provider(); + String service = serviceInfo.getServiceKey(); + p.setService(service); + p.setAddress(url.getAddress()); + p.setApplication(instance.getServiceName()); + p.setUrl(url.toParameterString()); + p.setDynamic(url.getParameter("dynamic", true)); + p.setEnabled(url.getParameter(Constants.ENABLED_KEY, true)); + p.setWeight(url.getParameter(Constants.WEIGHT_KEY, Constants.DEFAULT_WEIGHT)); + p.setUsername(url.getParameter("owner")); + p.setRegistrySource(RegistrySource.INSTANCE); + providers.add(p); + }); + }); + return providers; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java new file mode 100644 index 000000000..ab5b3be48 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service.impl; + +import org.apache.dubbo.admin.service.RegistryCache; +import org.apache.dubbo.common.URL; + +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * interface registry url cache + * key --> category,value --> ConcurrentMap> + */ +@Component +public class InterfaceRegistryCache implements RegistryCache>> { + + private final ConcurrentMap>> registryCache = new ConcurrentHashMap<>(); + + @Override + public void put(String key, ConcurrentMap> value) { + registryCache.put(key, value); + } + + @Override + public ConcurrentMap> get(String key) { + return registryCache.get(key); + } + + public ConcurrentMap>> getRegistryCache() { + return registryCache; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java index a1668fd8f..40ba2586b 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java @@ -73,8 +73,7 @@ public boolean deleteConfig(String key) { } private String getPath(String key) { - return Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR - + Constants.DUBBO_PROPERTY; + return key + Constants.PATH_SEPARATOR + Constants.DUBBO_PROPERTY; } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java new file mode 100644 index 000000000..fd591bd2d --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service.impl; + +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.common.util.ConvertUtil; +import org.apache.dubbo.admin.common.util.YamlParser; +import org.apache.dubbo.admin.model.dto.MeshRouteDTO; +import org.apache.dubbo.admin.model.store.mesh.destination.DestinationRule; +import org.apache.dubbo.admin.model.store.mesh.virtualservice.VirtualServiceRule; +import org.apache.dubbo.admin.service.MeshRouteService; + +import org.springframework.stereotype.Service; + +import java.util.Map; + + +@Service +public class MeshRouteServiceImpl extends AbstractService implements MeshRouteService { + + @Override + public boolean createMeshRule(MeshRouteDTO meshRoute) { + String routeRule = meshRoute.getMeshRule(); + checkMeshRule(routeRule); + String id = ConvertUtil.getIdFromDTO(meshRoute); + String path = getPath(id); + dynamicConfiguration.setConfig(path, routeRule); + return true; + } + + @Override + public boolean updateMeshRule(MeshRouteDTO meshRoute) { + String id = ConvertUtil.getIdFromDTO(meshRoute); + String path = getPath(id); + checkMeshRule(meshRoute.getMeshRule()); + dynamicConfiguration.setConfig(path, meshRoute.getMeshRule()); + return true; + } + + private void checkMeshRule(String meshRule) { + Iterable objectIterable = YamlParser.loadAll(meshRule); + for (Object result : objectIterable) { + Map resultMap = (Map) result; + if ("DestinationRule".equals(resultMap.get("kind"))) { + YamlParser.loadObject(YamlParser.dumpObject(result), DestinationRule.class); + } else if ("VirtualService".equals(resultMap.get("kind"))) { + YamlParser.loadObject(YamlParser.dumpObject(result), VirtualServiceRule.class); + } + } + } + + @Override + public boolean deleteMeshRule(String id) { + String path = getPath(id); + return dynamicConfiguration.deleteConfig(path); + } + + @Override + public MeshRouteDTO findMeshRoute(String id) { + String path = getPath(id); + String rule = dynamicConfiguration.getConfig(path); + if (rule == null) { + return null; + } + MeshRouteDTO meshRoute = new MeshRouteDTO(); + meshRoute.setApplication(id); + meshRoute.setMeshRule(rule); + return meshRoute; + } + + private String getPath(String id) { + return id + Constants.MESH_RULE_SUFFIX; + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MockRuleServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MockRuleServiceImpl.java new file mode 100644 index 000000000..7b659d53a --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MockRuleServiceImpl.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.service.impl; + +import org.apache.dubbo.admin.mapper.MockRuleMapper; +import org.apache.dubbo.admin.model.domain.MockRule; +import org.apache.dubbo.admin.model.dto.MockRuleDTO; +import org.apache.dubbo.admin.service.MockRuleService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.dubbo.mock.api.MockContext; +import org.apache.dubbo.mock.api.MockResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * The implement of {@link MockRuleService}. + */ +@Component +public class MockRuleServiceImpl implements MockRuleService { + + @Autowired + private MockRuleMapper mockRuleMapper; + + @Override + public void createOrUpdateMockRule(MockRuleDTO mockRule) { + if (Objects.isNull(mockRule.getServiceName()) || Objects.isNull(mockRule.getMethodName()) + || Objects.isNull(mockRule.getRule())) { + throw new IllegalStateException("Param serviceName, methodName, rule cannot be null"); + } + MockRule rule = MockRule.toMockRule(mockRule); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("service_name", mockRule.getServiceName()); + queryWrapper.eq("method_name", mockRule.getMethodName()); + MockRule existRule = mockRuleMapper.selectOne(queryWrapper); + + // check if we can save or update the rule, we need keep the serviceName + methodName is unique. + if (Objects.nonNull(existRule)) { + if (Objects.equals(rule.getServiceName(), existRule.getServiceName()) + && Objects.equals(rule.getMethodName(), existRule.getMethodName())) { + if (!Objects.equals(rule.getId(), existRule.getId())) { + throw new DuplicateKeyException("Service Name and Method Name must be unique"); + } + } + } + + if (Objects.nonNull(rule.getId())) { + mockRuleMapper.updateById(rule); + return; + } + mockRuleMapper.insert(rule); + } + + @Override + public void deleteMockRuleById(Long id) { + MockRule mockRule = mockRuleMapper.selectById(id); + if (Objects.isNull(mockRule)) { + throw new IllegalStateException("Mock Rule cannot find"); + } + mockRuleMapper.deleteById(id); + } + + @Override + public Page listMockRulesByPage(String filter, Pageable pageable) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + Optional.ofNullable(filter) + .ifPresent(f -> queryWrapper.like("service_name", f)); + List mockRules = mockRuleMapper.selectList(queryWrapper); + int total = mockRules.size(); + final List content = mockRules.stream() + .skip(pageable.getOffset()) + .limit(pageable.getPageSize()) + .map(MockRuleDTO::toMockRuleDTO) + .collect(Collectors.toList()); + return new PageImpl<>(content, pageable, total); + } + + @Override + public MockResult getMockData(MockContext mockContext) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("service_name", mockContext.getServiceName()); + queryWrapper.eq("method_name", mockContext.getMethodName()); + MockRule mockRule = mockRuleMapper.selectOne(queryWrapper); + MockResult mockResult = new MockResult(); + if (Objects.isNull(mockRule)) { + return mockResult; + } + mockResult.setEnable(mockRule.getEnable()); + mockResult.setContent(mockRule.getRule()); + return mockResult; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java index 1bc018e1e..361122a0c 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java @@ -42,7 +42,6 @@ @Component public class OverrideServiceImpl extends AbstractService implements OverrideService { - private String prefix = Constants.CONFIG_KEY; @java.lang.Override public void saveOverride(DynamicConfigDTO override) { @@ -528,9 +527,10 @@ private List convertDTOtoOldOverride(DynamicConfigDTO overrideDTO) { } return result; } + private String getPath(String key) { key = key.replace("/", "*"); - return prefix + Constants.PATH_SEPARATOR + key + Constants.CONFIGURATOR_RULE_SUFFIX; + return key + Constants.CONFIGURATOR_RULE_SUFFIX; } private void unregisterWeight(WeightDTO weightDTO) { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java index 0d8308153..1defce765 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java @@ -18,16 +18,14 @@ import org.apache.dubbo.admin.common.exception.ParamValidationException; import org.apache.dubbo.admin.common.util.Constants; -import org.apache.dubbo.admin.common.util.Pair; -import org.apache.dubbo.admin.common.util.ParseUtils; import org.apache.dubbo.admin.common.util.SyncUtils; import org.apache.dubbo.admin.common.util.Tool; import org.apache.dubbo.admin.model.domain.Provider; import org.apache.dubbo.admin.model.dto.ServiceDTO; -import org.apache.dubbo.admin.service.OverrideService; import org.apache.dubbo.admin.service.ProviderService; import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -37,7 +35,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentMap; @@ -49,7 +46,7 @@ public class ProviderServiceImpl extends AbstractService implements ProviderService { @Autowired - OverrideService overrideService; + private InstanceRegistryQueryHelper instanceRegistryQueryHelper; @Override public void create(Provider provider) { @@ -63,57 +60,27 @@ public String getProviderMetaData(MetadataIdentifier providerIdentifier) { return metaDataCollector.getProviderMetaData(providerIdentifier); } - - @Override - public void deleteStaticProvider(String id) { - URL oldProvider = findProviderUrl(id); - if (oldProvider == null) { - throw new IllegalStateException("Provider was changed!"); - } - registry.unregister(oldProvider); - } - - @Override - public void updateProvider(Provider provider) { - String hash = provider.getHash(); - if (hash == null) { - throw new IllegalStateException("no provider id"); - } - - URL oldProvider = findProviderUrl(hash); - if (oldProvider == null) { - throw new IllegalStateException("Provider was changed!"); - } - URL newProvider = provider.toUrl(); - - registry.unregister(oldProvider); - registry.register(newProvider); - } - - @Override - public Provider findProvider(String id) { - return SyncUtils.url2Provider(findProviderUrlPair(id)); - } - - public Pair findProviderUrlPair(String id) { - return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id); - } - @Override public Set findServices() { Set ret = new HashSet<>(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (providerUrls != null){ + ConcurrentMap> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY); + if (providerUrls != null) { ret.addAll(providerUrls.keySet()); } + ret.addAll(instanceRegistryQueryHelper.findServices()); return ret; } + @Override + public Set findInstanceApplications() { + return instanceRegistryQueryHelper.findApplications(); + } + @Override public List findAddresses() { List ret = new ArrayList(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); + ConcurrentMap> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY); if (null == providerUrls) { return ret; } @@ -128,80 +95,15 @@ public List findAddresses() { } } } - - return ret; - } - - @Override - public List findAddressesByApplication(String application) { - List ret = new ArrayList(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - for (Map.Entry> e1 : providerUrls.entrySet()) { - Map value = e1.getValue(); - for (Map.Entry e2 : value.entrySet()) { - URL u = e2.getValue(); - if (application.equals(u.getParameter(Constants.APPLICATION))) { - String addr = u.getAddress(); - if (addr != null) { - ret.add(addr); - } - } - } - } - - return ret; - } - - @Override - public List findAddressesByService(String service) { - List ret = new ArrayList(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (null == providerUrls) { - return ret; - } - - for (Map.Entry e2 : providerUrls.get(service).entrySet()) { - URL u = e2.getValue(); - String app = u.getAddress(); - if (app != null) { - ret.add(app); - } - } - - return ret; - } - - @Override - public List findApplicationsByServiceName(String service) { - List ret = new ArrayList(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (null == providerUrls) { - return ret; - } - - Map value = providerUrls.get(service); - if (value == null) { - return ret; - } - for (Map.Entry e2 : value.entrySet()) { - URL u = e2.getValue(); - String app = u.getParameter(Constants.APPLICATION); - if (app != null){ - ret.add(app); - } - } - return ret; } @Override public List findByService(String serviceName) { - return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName)); - } - - @Override - public List findByAppandService(String app, String serviceName) { - return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName)); + List instanceProviders = instanceRegistryQueryHelper.findByService(serviceName); + List interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByService(serviceName)); + instanceProviders.addAll(interfaceProviders); + return instanceProviders; } private Map findProviderUrlByService(String service) { @@ -209,7 +111,7 @@ private Map findProviderUrlByService(String service) { filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); filter.put(SyncUtils.SERVICE_FILTER_KEY, service); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @Override @@ -220,12 +122,15 @@ public List findAll() { private Map findAllProviderUrl() { Map filter = new HashMap(); filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @Override public List findByAddress(String providerAddress) { - return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress)); + List instanceProviders = instanceRegistryQueryHelper.findByAddress(providerAddress); + List interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress)); + instanceProviders.addAll(interfaceProviders); + return instanceProviders; } public Map findProviderUrlByAddress(String address) { @@ -233,37 +138,14 @@ public Map findProviderUrlByAddress(String address) { filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); filter.put(SyncUtils.ADDRESS_FILTER_KEY, address); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); - } - - @Override - public List findServicesByAddress(String address) { - List ret = new ArrayList(); - - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (providerUrls == null || address == null || address.length() == 0) { - return ret; - } - - for (Map.Entry> e1 : providerUrls.entrySet()) { - Map value = e1.getValue(); - for (Map.Entry e2 : value.entrySet()) { - URL u = e2.getValue(); - if (address.equals(u.getAddress())) { - ret.add(e1.getKey()); - break; - } - } - } - - return ret; + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @Override public Set findApplications() { - Set ret = new HashSet<>(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (providerUrls == null){ + Set ret = instanceRegistryQueryHelper.findApplications(); + ConcurrentMap> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY); + if (providerUrls == null) { return ret; } @@ -283,11 +165,18 @@ public Set findApplications() { @Override public List findByApplication(String application) { - return SyncUtils.url2ProviderList(findProviderUrlByApplication(application)); + List instanceProviders = instanceRegistryQueryHelper.findByApplication(application); + List interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByApplication(application)); + instanceProviders.addAll(interfaceProviders); + return instanceProviders; } @Override public String findVersionInApplication(String application) { + String version = instanceRegistryQueryHelper.findVersionInApplication(application); + if (StringUtils.isNotBlank(version)){ + return version; + } List services = findServicesByApplication(application); if (services == null || services.size() == 0) { throw new ParamValidationException("there is no service for application: " + application); @@ -313,23 +202,22 @@ private Map findProviderUrlByAppandService(String app, String servi filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); filter.put(Constants.APPLICATION, app); filter.put(SyncUtils.SERVICE_FILTER_KEY, service); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } - private Map findProviderUrlByApplication(String application) { Map filter = new HashMap<>(); filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); filter.put(Constants.APPLICATION, application); - return SyncUtils.filterFromCategory(getRegistryCache(), filter); + return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter); } @Override public List findServicesByApplication(String application) { List ret = new ArrayList(); - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); + ConcurrentMap> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY); if (providerUrls == null || application == null || application.length() == 0) { return ret; } @@ -348,59 +236,6 @@ public List findServicesByApplication(String application) { return ret; } - @Override - public List findMethodsByService(String service) { - List ret = new ArrayList(); - - ConcurrentMap> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY); - if (providerUrls == null || service == null || service.length() == 0){ - return ret; - } - - Map providers = providerUrls.get(service); - if (null == providers || providers.isEmpty()) { - return ret; - } - - Entry p = providers.entrySet().iterator().next(); - String value = p.getValue().getParameter("methods"); - if (value == null || value.length() == 0) { - return ret; - } - String[] methods = value.split(ParseUtils.METHOD_SPLIT); - if (methods == null || methods.length == 0) { - return ret; - } - - for (String m : methods) { - ret.add(m); - } - return ret; - } - - private URL findProviderUrl(String id) { - return findProvider(id).toUrl(); - } - - @Override - public Provider findByServiceAndAddress(String service, String address) { - return SyncUtils.url2Provider(findProviderUrl(service, address)); - } - - private Pair findProviderUrl(String service, String address) { - Map filter = new HashMap(); - filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY); - filter.put(SyncUtils.ADDRESS_FILTER_KEY, address); - - Map ret = SyncUtils.filterFromCategory(getRegistryCache(), filter); - if (ret.isEmpty()) { - return null; - } else { - String key = ret.entrySet().iterator().next().getKey(); - return new Pair(key, ret.get(key)); - } - } - @Override public Set getServiceDTOS(String pattern, String filter, String env) { List providers = new ArrayList<>(); @@ -420,15 +255,14 @@ public Set getServiceDTOS(String pattern, String filter, String env) candidates = findServices(); } else if (Constants.APPLICATION.equals(pattern)) { candidates = findApplications(); - } - else if (Constants.IP.equals(pattern)) { + } else if (Constants.IP.equals(pattern)) { candidates = findAddresses().stream().collect(Collectors.toSet()); } // replace dot symbol and asterisk symbol to java-based regex pattern filter = filter.toLowerCase().replace(Constants.PUNCTUATION_POINT, Constants.PUNCTUATION_SEPARATOR_POINT); // filter start with [* 、? 、+] will triggering PatternSyntaxException if (filter.startsWith(Constants.ANY_VALUE) - || filter.startsWith(Constants.INTERROGATION_POINT) || filter.startsWith(Constants.PLUS_SIGNS)) { + || filter.startsWith(Constants.INTERROGATION_POINT) || filter.startsWith(Constants.PLUS_SIGNS)) { filter = Constants.PUNCTUATION_POINT + filter; } // search with no case insensitive @@ -438,19 +272,16 @@ else if (Constants.IP.equals(pattern)) { if (matcher.matches() || matcher.lookingAt()) { if (Constants.SERVICE.equals(pattern)) { providers.addAll(findByService(candidate)); - } - else if (Constants.IP.equals(pattern)) { + } else if (Constants.IP.equals(pattern)) { providers.addAll(findByAddress(candidate)); - } - else { + } else { providers.addAll(findByApplication(candidate)); } } } } - Set result = convertProviders2DTO(providers); - return result; + return convertProviders2DTO(providers); } /** @@ -472,6 +303,7 @@ public Set convertProviders2DTO(List providers) { s.setService(interfaze); s.setGroup(group); s.setVersion(version); + s.setRegistrySource(provider.getRegistrySource()); result.add(s); } return result; diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java index ed28d641d..4856a5fc5 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java @@ -39,8 +39,6 @@ @Component public class RouteServiceImpl extends AbstractService implements RouteService { - private String prefix = Constants.CONFIG_KEY; - @Override public void createConditionRoute(ConditionRouteDTO conditionRoute) { String id = ConvertUtil.getIdFromDTO(conditionRoute); @@ -362,9 +360,9 @@ public TagRouteDTO findTagRoute(String id) { private String getPath(String key, String type) { key = key.replace("/", "*"); if (type.equals(Constants.CONDITION_ROUTE)) { - return prefix + Constants.PATH_SEPARATOR + key + Constants.CONDITION_RULE_SUFFIX; + return key + Constants.CONDITION_RULE_SUFFIX; } else { - return prefix + Constants.PATH_SEPARATOR + key + Constants.TAG_RULE_SUFFIX; + return key + Constants.TAG_RULE_SUFFIX; } } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/JwtTokenUtil.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/JwtTokenUtil.java new file mode 100644 index 000000000..d9f5b7cd3 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/JwtTokenUtil.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.utils; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * Jwt token tool class. + */ +@Component +public class JwtTokenUtil { + /** + * Jwt signingKey configurable + */ + @Value("${admin.check.signSecret:}") + public String secret; + + /** + * token timeout configurable + * default to be an hour: 1000 * 60 * 60 + */ + @Value("${admin.check.tokenTimeoutMilli:}") + public long expiration; + + /** + * default SignatureAlgorithm + */ + public static final SignatureAlgorithm defaultAlgorithm = SignatureAlgorithm.HS512; + + /** + * Generate the token + * + * @return token + * @param rootUserName + */ + public String generateToken(String rootUserName) { + Map claims = new HashMap<>(1); + claims.put("sub", rootUserName); + return Jwts.builder() + .setClaims(claims) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .setIssuedAt(new Date(System.currentTimeMillis())) + .signWith(defaultAlgorithm, secret) + .compact(); + } + + /** + * Check whether the token is invalid + * + * @return boolean type + * @param token + */ + public Boolean canTokenBeExpiration(String token) { + Claims claims; + try { + claims = Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + final Date exp = claims.getExpiration(); + if (exp.before(new Date(System.currentTimeMillis()))) { + return false; + } + return true; + } catch (Exception e) { + return false; + } + } + +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/SpringBeanUtils.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/SpringBeanUtils.java new file mode 100644 index 000000000..87a445dbd --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/SpringBeanUtils.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + + +/** + * get spring bean tool class. + */ +@Component +public class SpringBeanUtils implements ApplicationContextAware { + /** + * spring applicationContext + */ + public static ApplicationContext applicationContext; + + /** + * get spring bean + * + * @return spring bean + * @param clazz + */ + public static T getBean(Class clazz){ + return applicationContext.getBean(clazz); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringBeanUtils.applicationContext = applicationContext; + } +} diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.authentication.InterceptorAuthentication b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.authentication.InterceptorAuthentication new file mode 100644 index 000000000..ef91a43cd --- /dev/null +++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.authentication.InterceptorAuthentication @@ -0,0 +1 @@ +defaultHandle=org.apache.dubbo.admin.authentication.impl.DefaultPreHandle \ No newline at end of file diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration index 14b6b024b..88d69fe4d 100644 --- a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration +++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration @@ -1,4 +1 @@ -zookeeper=org.apache.dubbo.admin.registry.config.impl.ZookeeperConfiguration -apollo=org.apache.dubbo.admin.registry.config.impl.ApolloConfiguration -nacos=org.apache.dubbo.admin.registry.config.impl.NacosConfiguration -consul=org.apache.dubbo.admin.registry.config.impl.ConsulConfiguration +multi=org.apache.dubbo.admin.registry.config.impl.MultiDynamicConfiguration diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping new file mode 100644 index 000000000..90c6c4ac6 --- /dev/null +++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping @@ -0,0 +1,2 @@ +zookeeper=org.apache.dubbo.admin.registry.mapping.impl.ZookeeperServiceMapping +nacos=org.apache.dubbo.admin.registry.mapping.impl.NacosServiceMapping \ No newline at end of file diff --git a/dubbo-admin-server/src/main/resources/application.properties b/dubbo-admin-server/src/main/resources/application.properties index df1746801..4aa924b22 100644 --- a/dubbo-admin-server/src/main/resources/application.properties +++ b/dubbo-admin-server/src/main/resources/application.properties @@ -56,3 +56,26 @@ admin.check.sessionTimeoutMilli=3600000 server.compression.enabled=true server.compression.mime-types=text/css,text/javascript,application/javascript server.compression.min-response-size=10240 + +#token timeout, default is one hour +admin.check.tokenTimeoutMilli=3600000 +#Jwt signingKey +admin.check.signSecret=86295dd0c4ef69a1036b0b0c15158d77 + +#dubbo config +dubbo.application.name=dubbo-admin +dubbo.registry.address=${admin.registry.address} + +# mysql +#spring.datasource.driver-class-name=com.mysql.jdbc.Driver +#spring.datasource.url=jdbc:mysql://localhost:3306/dubbo-admin?characterEncoding=utf8&connectTimeout=1000&socketTimeout=10000&autoReconnect=true +#spring.datasource.username=root +#spring.datasource.password=mysql + +# h2 +spring.datasource.url=jdbc:h2:mem:~/dubbo-admin; +spring.datasource.username=sa +spring.datasource.password= + +# id generate type +mybatis-plus.global-config.db-config.id-type=none \ No newline at end of file diff --git a/dubbo-admin-server/src/main/resources/schema.sql b/dubbo-admin-server/src/main/resources/schema.sql new file mode 100644 index 000000000..f738db738 --- /dev/null +++ b/dubbo-admin-server/src/main/resources/schema.sql @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +CREATE TABLE IF NOT EXISTS `mock_rule` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', + `service_name` varchar(255) DEFAULT NULL COMMENT '服务名', + `method_name` varchar(255) DEFAULT NULL COMMENT '方法名', + `rule` text COMMENT '规则', + `enable` tinyint(1) NOT NULL DEFAULT '1', + `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`) +); \ No newline at end of file diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java index 9448a9388..01bed98ea 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java @@ -73,9 +73,11 @@ public void initialize(ConfigurableApplicationContext configurableApplicationCon TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, "admin.registry.address=zookeeper://" + zkServer.getConnectString()); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, - "admin.metadata.address=zookeeper://" + zkServer.getConnectString()); + "admin.metadata-report.address=zookeeper://" + zkServer.getConnectString()); TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, "admin.config-center=zookeeper://" + zkServer.getConnectString()); + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(configurableApplicationContext, + "dubbo.config.ignore-duplicated-interface=true"); } } } diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java index 462285ba8..e31a798e6 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java @@ -31,6 +31,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -63,12 +64,6 @@ public void shouldCreateGlobalConfig() throws Exception { ); assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED); assertEquals(responseEntity.getBody(), true); - - byte[] bytes = zkClient.getData().forPath(getPath("")); - String config = new String(bytes); - assertEquals(configDTO.getConfig(), config); - - zkClient.delete().forPath(getPath("")); } @Test @@ -83,10 +78,6 @@ public void shouldCreateApplicationConfig() throws Exception { ); assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED); assertEquals(responseEntity.getBody(), true); - - byte[] bytes = zkClient.getData().forPath(getPath(application)); - String config = new String(bytes); - assertEquals(configDTO.getConfig(), config); } @Test @@ -104,11 +95,11 @@ public void shouldThrowWhenUpdateNonExistedConfigKey() { @Test public void shouldUpdateConfigSpecifiedKey() throws Exception { String key = "shouldUpdateConfigSpecifiedKey"; + String path = getPath(key); + zkClient.create().creatingParentContainersIfNeeded().forPath(path); + zkClient.setData().forPath(path, "key1=val1\nkey2=val2".getBytes(StandardCharsets.UTF_8)); ConfigDTO configDTO = new ConfigDTO(); configDTO.setKey(key); - configDTO.setConfig("key1=val1\nkey2=val2"); - restTemplate.postForEntity(url("/api/{env}/manage/config"), configDTO, Boolean.class, env); - configDTO.setConfig("key1=updatedVal1\nkey2=updatedVal2"); ResponseEntity responseEntity = restTemplate.exchange( url("/api/{env}/manage/config/{key}"), HttpMethod.PUT, diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java new file mode 100644 index 000000000..8cfdd9f80 --- /dev/null +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.controller; + +import org.apache.dubbo.admin.AbstractSpringIntegrationTest; +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.model.dto.MeshRouteDTO; +import org.apache.dubbo.admin.service.ProviderService; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.After; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + + +public class MeshRouteControllerTest extends AbstractSpringIntegrationTest { + + private final String env = "whatever"; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private ProviderService providerService; + + @After + public void tearDown() throws Exception { + if (zkClient.checkExists().forPath("/dubbo") != null) { + zkClient.delete().deletingChildrenIfNeeded().forPath("/dubbo"); + } + } + + private String getFileContent(String file) throws IOException { + try (InputStream stream = this.getClass().getResourceAsStream(file)) { + byte[] bytes = new byte[stream.available()]; + stream.read(bytes); + return new String(bytes, StandardCharsets.UTF_8); + } + } + + + @Test + public void createMeshRoute() throws IOException { + MeshRouteDTO meshRoute = new MeshRouteDTO(); + ResponseEntity response; + String application = "mesh-create"; + // application are all blank + response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env); + assertFalse("should return a fail response, when application is blank", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success")); + + // valid mesh rule + meshRoute.setApplication(application); + meshRoute.setMeshRule(getFileContent("/MeshRoute.yml")); + when(providerService.findVersionInApplication(application)).thenReturn("3.0.0"); + response = restTemplate.postForEntity(url("/api/{env}/rules/route/mesh"), meshRoute, String.class, env); + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + assertTrue(Boolean.valueOf(response.getBody())); + } + + + @Test + public void detailMeshRoute() throws Exception { + String id = "1"; + ResponseEntity response; + // when balancing is not exist + response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, id); + assertFalse("should return a fail response, when id is null", (Boolean) objectMapper.readValue(response.getBody(), Map.class).get("success")); + // when balancing is not null + String application = "mesh-detail"; + String content = getFileContent("/MeshRoute.yml"); + String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX; + zkClient.create().creatingParentContainersIfNeeded().forPath(path); + zkClient.setData().forPath(path, content.getBytes()); + assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path)); + + response = restTemplate.getForEntity(url("/api/{env}/rules/route/mesh/{id}"), String.class, env, application); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertEquals(content, objectMapper.readValue(response.getBody(), Map.class).get("meshRule")); + } + + @Test + public void updateMeshRoute() throws Exception { + String application = "mesh-update"; + String content = getFileContent("/MeshRoute.yml"); + String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX; + zkClient.create().creatingParentContainersIfNeeded().forPath(path); + zkClient.setData().forPath(path, content.getBytes()); + assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path)); + + MeshRouteDTO meshRoute = new MeshRouteDTO(); + meshRoute.setApplication(application); + meshRoute.setMeshRule(getFileContent("/MeshRouteTest2.yml")); + + ResponseEntity response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.PUT, new HttpEntity<>(meshRoute, null), String.class, env, application); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue(Boolean.valueOf(response.getBody())); + byte[] bytes = zkClient.getData().forPath(path); + String updatedConfig = new String(bytes); + assertEquals(updatedConfig, meshRoute.getMeshRule()); + } + + + @Test + public void deleteMeshRoute() throws Exception { + String application = "mesh-delete"; + String content = getFileContent("/MeshRoute.yml"); + String path = "/dubbo/" + Constants.CONFIG_KEY + Constants.PATH_SEPARATOR + application + Constants.MESH_RULE_SUFFIX; + zkClient.create().creatingParentContainersIfNeeded().forPath(path); + zkClient.setData().forPath(path, content.getBytes()); + assertNotNull("zk path should not be null before deleting", zkClient.checkExists().forPath(path)); + + ResponseEntity response = restTemplate.exchange(url("/api/{env}/rules/route/mesh/{id}"), HttpMethod.DELETE, new HttpEntity<>(null), String.class, env, application); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNull(zkClient.checkExists().forPath(path)); + } +} diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java index 7f1583673..57aa1ff9b 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java @@ -33,7 +33,7 @@ public class ZookeeperConfigurationTest { private TestingServer zkServer; - private ZookeeperConfiguration configuration; + private MultiDynamicConfiguration configuration; private URL registryUrl; @Before @@ -42,7 +42,7 @@ public void setup() throws Exception { zkServer = new TestingServer(zkServerPort, true); registryUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort); - configuration = new ZookeeperConfiguration(); + configuration = new MultiDynamicConfiguration(); try { configuration.init(); fail("init should fail before setting registryUrl"); @@ -79,13 +79,11 @@ public void testGetSetConfig() { @Test public void testDeleteConfig() { - assertEquals(false, configuration.deleteConfig("not_exist_key")); configuration.setConfig("test_delete", "test_value"); assertEquals("test_value", configuration.getConfig("test_delete")); configuration.deleteConfig("test_delete"); assertEquals(null, configuration.getConfig("test_delete")); - assertEquals(false, configuration.deleteConfig("test_group", "not_exist_key")); configuration.setConfig("test_group", "test_delete", "test_value"); assertEquals("test_value", configuration.getConfig("test_group", "test_delete")); configuration.deleteConfig("test_group", "test_delete"); @@ -98,16 +96,6 @@ public void testDeleteConfig() { } } - @Test - public void testGetPath() { - assertEquals(Constants.PATH_SEPARATOR + Constants.DEFAULT_ROOT + Constants.PATH_SEPARATOR + "test_key", - configuration.getPath("test_key")); - try { - configuration.getPath(null); - fail("should throw IllegalArgumentException for null path"); - } catch (IllegalArgumentException e) { - } - } @After public void tearDown() throws IOException { diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java index a8ecc7cc1..1be485d1d 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java @@ -18,16 +18,22 @@ package org.apache.dubbo.admin.service; import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.service.impl.InterfaceRegistryCache; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.url.component.URLParam; import org.apache.dubbo.registry.Registry; + +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.util.ReflectionTestUtils; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentMap; @@ -46,9 +52,11 @@ public class RegistryServerSyncTest { @InjectMocks private RegistryServerSync registryServerSync; - @Test - public void testGetRegistryCache() { - registryServerSync.getRegistryCache(); + private InterfaceRegistryCache interfaceRegistryCache = new InterfaceRegistryCache(); + + @Before + public void setUp() throws Exception { + ReflectionTestUtils.setField(registryServerSync, "interfaceRegistryCache", interfaceRegistryCache); } @Test @@ -71,27 +79,32 @@ public void testNotify() { // when url.getProtocol is not empty protocol URL consumerUrl = mock(URL.class); URL providerUrl = mock(URL.class); - - when(consumerUrl.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY)).thenReturn(Constants.CONSUMER_PROTOCOL); + HashMap consumerUrlParam = new HashMap<>(); + consumerUrlParam.put(Constants.CATEGORY_KEY,Constants.CONSUMER_PROTOCOL); + HashMap providerUrlParam = new HashMap<>(); + providerUrlParam.put(Constants.CATEGORY_KEY,Constants.PROVIDER_PROTOCOL); + when(consumerUrl.getUrlParam()).thenReturn(URLParam.parse(consumerUrlParam)); when(consumerUrl.getServiceInterface()).thenReturn("org.apache.dubbo.consumer"); - when(consumerUrl.getServiceKey()).thenReturn("org.apache.dubbo.consumer"); when(consumerUrl.toFullString()).thenReturn("consumer://192.168.1.10/sunbufu.dubbo.consumer?application=dubbo&category=consumer&check=false&dubbo=2.7.0&interface=sunbufu.dubbo.consumer&loadbalabce=roundrobin&mehods=sayHi,sayGoodBye&owner=sunbufu&pid=18&protocol=dubbo&side=consumer&timeout=3000×tamp=1548127407769"); + when(providerUrl.getUrlParam()).thenReturn(URLParam.parse(providerUrlParam)); when(providerUrl.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY)).thenReturn(Constants.PROVIDER_PROTOCOL); when(providerUrl.getServiceInterface()).thenReturn("org.apache.dubbo.provider"); - when(providerUrl.getServiceKey()).thenReturn("org.apache.dubbo.provider"); when(providerUrl.toFullString()).thenReturn("consumer://192.168.1.10/sunbufu.dubbo.consumer?application=dubbo&category=consumer&check=false&dubbo=2.6.2&interface=sunbufu.dubbo.consumer&loadbalabce=roundrobin&mehods=sayHi,sayGoodBye&owner=sunbufu&pid=18&protocol=dubbo&side=consumer&timeout=3000×tamp=1548127407769"); registryServerSync.notify(Arrays.asList(consumerUrl, consumerUrl, providerUrl)); - ConcurrentMap> consumerMap = registryServerSync.getRegistryCache().get(Constants.CONSUMER_PROTOCOL); + ConcurrentMap> consumerMap = interfaceRegistryCache.get(Constants.CONSUMER_PROTOCOL); assertTrue(consumerMap.keySet().contains("org.apache.dubbo.consumer")); - ConcurrentMap> providerMap = registryServerSync.getRegistryCache().get(Constants.PROVIDER_PROTOCOL); + ConcurrentMap> providerMap = interfaceRegistryCache.get(Constants.PROVIDER_PROTOCOL); assertTrue(providerMap.keySet().contains("org.apache.dubbo.provider")); // when url.getProtocol is empty protocol when(consumerUrl.getProtocol()).thenReturn(Constants.EMPTY_PROTOCOL); - when(consumerUrl.getParameter(Constants.GROUP_KEY)).thenReturn("dubbo"); - when(consumerUrl.getParameter(Constants.VERSION_KEY)).thenReturn("2.7.0"); + consumerUrlParam = new HashMap<>(); + consumerUrlParam.put(Constants.CATEGORY_KEY,Constants.CONSUMER_PROTOCOL); + consumerUrlParam.put(Constants.GROUP_KEY,"dubbo"); + consumerUrlParam.put(Constants.VERSION_KEY,"2.7.0"); + when(consumerUrl.getUrlParam()).thenReturn(URLParam.parse(consumerUrlParam)); registryServerSync.notify(Collections.singletonList(consumerUrl)); assertTrue(!consumerMap.keySet().contains("org.apache.dubbo.consumer")); diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/utils/JwtTokenUtilTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/utils/JwtTokenUtilTest.java new file mode 100644 index 000000000..90a15a8a1 --- /dev/null +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/utils/JwtTokenUtilTest.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.dubbo.admin.utils; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import org.junit.Test; + +import java.util.Date; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + + +public class JwtTokenUtilTest { + public final String defaultSecret = "86295dd0c4ef69a1036b0b0c15158d77"; + public final long defaultExpire = 1000 * 60 * 60; + public String testToken = "eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2MzM4NTI2" + + "MDQsInN1YiI6InRlc3QiLCJpYXQiOjE2MzM4NDkwMDR9.e1UqT-3W3EZcI6" + + "Dt-35b0Q_MA9ZhARAq59ZvkOYNlWL0Fa-RFk1ZQKs15Hk7LATfVH2DAo0JL" + + "rHcY-79jDFnfQ"; + public long testIat = 1633849279000L; + public long testExp = 1633852879000L; + public String userName = "test"; + +} diff --git a/dubbo-admin-server/src/test/resources/MeshRoute.yml b/dubbo-admin-server/src/test/resources/MeshRoute.yml new file mode 100644 index 000000000..b6a1071c6 --- /dev/null +++ b/dubbo-admin-server/src/test/resources/MeshRoute.yml @@ -0,0 +1,58 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +# + +apiVersion: service.dubbo.apache.org/v1alpha1 +kind: DestinationRule +metadata: { name: demo-route } +spec: + host: demo + subsets: + - labels: { env-sign: xxx, tag1: hello } + name: isolation + - labels: { env-sign: yyy } + name: testing-trunk + - labels: { env-sign: zzz } + name: testing + trafficPolicy: + loadBalancer: { simple: ROUND_ROBIN } + +--- + +apiVersion: service.dubbo.apache.org/v1alpha1 +kind: VirtualService +metadata: {name: demo-route} +spec: + dubbo: + - routedetail: + - match: + - sourceLabels: {trafficLabel: xxx} + name: xxx-project + route: + - destination: {host: demo, subset: isolation} + - match: + - sourceLabels: {trafficLabel: testing-trunk} + name: testing-trunk + route: + - destination: {host: demo, subset: testing-trunk} + - name: testing + route: + - destination: {host: demo, subset: testing} + services: + - {regex: ccc} + hosts: [demo] \ No newline at end of file diff --git a/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml new file mode 100644 index 000000000..4d3454bff --- /dev/null +++ b/dubbo-admin-server/src/test/resources/MeshRouteTest2.yml @@ -0,0 +1,41 @@ +# +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +# + +apiVersion: service.dubbo.apache.org/v1alpha1 +kind: VirtualService +metadata: {name: demo-route} +spec: + dubbo: + - routedetail: + - match: + - sourceLabels: {trafficLabel: xxx} + name: xxx-project + route: + - destination: {host: demo, subset: isolation} + - match: + - sourceLabels: {trafficLabel: testing-trunk} + name: testing-trunk + route: + - destination: {host: demo, subset: testing-trunk} + - name: testing + route: + - destination: {host: demo, subset: testing} + services: + - {regex: ccc} + hosts: [demo] diff --git a/dubbo-admin-ui/src/api/menu.js b/dubbo-admin-ui/src/api/menu.js index 0a4fcedec..1f9cfe00d 100644 --- a/dubbo-admin-ui/src/api/menu.js +++ b/dubbo-admin-ui/src/api/menu.js @@ -23,7 +23,8 @@ const Menu = [ group: 'governance', items: [ { title: 'routingRule', path: '/governance/routingRule' }, - { title: 'tagRule', path: '/governance/tagRule', badge: 'new' }, + { title: 'tagRule', path: '/governance/tagRule' }, + { title: 'meshRule', path: '/governance/meshRule', badge: 'new' }, { title: 'accessControl', path: '/governance/access' }, { title: 'dynamicConfig', path: '/governance/config' }, { title: 'weightAdjust', path: '/governance/weight' }, @@ -32,7 +33,13 @@ const Menu = [ }, { title: 'serviceTest', path: '/test', icon: 'code' }, { title: 'apiDocs', path: '/apiDocs', icon: 'code' }, - { title: 'serviceMock', path: '/mock', icon: 'build', badge: 'feature' }, + { title: 'serviceMock', + path: '/mock', + icon: 'build', + items: [ + { title: 'mockRule', path: '/mock/rule', badge: 'new' } + ] + }, { title: 'serviceMetrics', path: 'metrics', diff --git a/dubbo-admin-ui/src/components/ServiceDetail.vue b/dubbo-admin-ui/src/components/ServiceDetail.vue index 366b5ffcd..79fa779f8 100644 --- a/dubbo-admin-ui/src/components/ServiceDetail.vue +++ b/dubbo-admin-ui/src/components/ServiceDetail.vue @@ -54,6 +54,7 @@