for release 0.4.0 (#849) master
author邪影oO <ranke@apache.org>
Thu, 18 Nov 2021 08:09:21 +0000 (16:09 +0800)
committerGitHub <noreply@github.com>
Thu, 18 Nov 2021 08:09:21 +0000 (16:09 +0800)
* 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 <wuwen.55@aliyun.com>
Co-authored-by: Huang YunKun <htynkn@gmail.com>
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>
132 files changed:
.asf.yaml [new file with mode: 0644]
NOTICE
README.md
README_ZH.md
docker/0.3.0/Dockerfile
docker/0.3.0/Dockerfile.test [new file with mode: 0644]
docker/0.3.0/docker-compose.test.yml [new file with mode: 0644]
docker/0.3.0/test.sh [new file with mode: 0755]
docker/latest/Dockerfile
docker/stack.yml
dubbo-admin-distribution/src/NOTICE
dubbo-admin-distribution/src/assembly/source-release.xml
dubbo-admin-distribution/src/bin/config/application.properties
dubbo-admin-distribution/src/bin/startup.cmd
dubbo-admin-distribution/src/bin/startup.sh
dubbo-admin-server/pom.xml
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/InterceptorAuthentication.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/LoginAuthentication.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/authentication/impl/DefaultPreHandle.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestV3Util.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MeshRouteController.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/MockRuleController.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/controller/UserController.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/interceptor/AuthInterceptor.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/mapper/MockRuleMapper.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/FullServiceDefinition.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MethodDefinition.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/MockRule.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/RegistrySource.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/ServiceDefinition.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/domain/TypeDefinition.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MeshRouteDTO.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/MockRuleDTO.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/BaseRule.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/VsDestinationGroup.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/ConnectionPoolSettings.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRule.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/DestinationRuleSpec.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/Subset.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TCPSettings.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TcpKeepalive.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/TrafficPolicy.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/ConsistentHashLB.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/LoadBalancerSettings.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/destination/loadbalance/SimpleLB.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboMatchRequest.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRoute.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/DubboRouteDetail.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceRule.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/VirtualServiceSpec.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboDestination.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/destination/DubboRouteDestination.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/BoolMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DoubleRangeMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboAttachmentMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodArg.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/DubboMethodMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListBoolMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListDoubleMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/ListStringMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/model/store/mesh/virtualservice/match/StringMatch.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/provider/MockServiceProvider.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java [deleted file]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ConsulConfiguration.java [deleted file]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/MultiDynamicConfiguration.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NacosConfiguration.java [deleted file]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java [deleted file]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AddressChangeListener.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminMappingListener.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/AdminServiceInstancesChangedListener.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/ServiceMapping.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NacosServiceMapping.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/NoOpServiceMapping.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/mapping/impl/ZookeeperServiceMapping.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MeshRouteService.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/MockRuleService.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryCache.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryCache.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InstanceRegistryQueryHelper.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/InterfaceRegistryCache.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ManagementServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MeshRouteServiceImpl.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/MockRuleServiceImpl.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/JwtTokenUtil.java [new file with mode: 0644]
dubbo-admin-server/src/main/java/org/apache/dubbo/admin/utils/SpringBeanUtils.java [new file with mode: 0644]
dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.authentication.InterceptorAuthentication [new file with mode: 0644]
dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.mapping.ServiceMapping [new file with mode: 0644]
dubbo-admin-server/src/main/resources/application.properties
dubbo-admin-server/src/main/resources/schema.sql [new file with mode: 0644]
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/AbstractSpringIntegrationTest.java
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/ManagementControllerTest.java
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/controller/MeshRouteControllerTest.java [new file with mode: 0644]
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfigurationTest.java
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/service/RegistryServerSyncTest.java
dubbo-admin-server/src/test/java/org/apache/dubbo/admin/utils/JwtTokenUtilTest.java [new file with mode: 0644]
dubbo-admin-server/src/test/resources/MeshRoute.yml [new file with mode: 0644]
dubbo-admin-server/src/test/resources/MeshRouteTest2.yml [new file with mode: 0644]
dubbo-admin-ui/src/api/menu.js
dubbo-admin-ui/src/components/ServiceDetail.vue
dubbo-admin-ui/src/components/ServiceSearch.vue
dubbo-admin-ui/src/components/governance/MeshRule.vue [new file with mode: 0644]
dubbo-admin-ui/src/components/governance/Overrides.vue
dubbo-admin-ui/src/components/public/Footers.vue
dubbo-admin-ui/src/components/test/ServiceMock.vue
dubbo-admin-ui/src/lang/en.js
dubbo-admin-ui/src/lang/zh.js
dubbo-admin-ui/src/router/index.js
dubbo-admin-ui/src/store/index.js
pom.xml

diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644 (file)
index 0000000..7ed913a
--- /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 cf58f0a9d8bca8d45dcfbb7cc6f5f705e164d16f..6367c40de16f0bc9cf2fb8b0696cd0e4042f45da 100644 (file)
--- 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/).
index 37be75b66e243aa586e10b440f32ad92d5afd22a..e0182457bdea195668460220d152e6c7f4a91706 100644 (file)
--- 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
 
index f4f0d909d3443c7787d55ef9454317e2b20dbf9c..c1a21d10f02bb88647fd41efa143aebf3728de0c 100644 (file)
@@ -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)
 
 ### 页面截图
 
index 5432d3dded34a4f970541eb63981ca3ba3630697..ac31116d3f387562c2b687ad8f85b10949754821 100644 (file)
 # 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 (file)
index 0000000..dee4d1d
--- /dev/null
@@ -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 (file)
index 0000000..9ac7fec
--- /dev/null
@@ -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 (executable)
index 0000000..d342e35
--- /dev/null
@@ -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
index 5ce8b3e71f8f6bc65e9a70a2e553d6a8c1aa34af..a4e4f756f6dfa30eb9403a87b51206f2e6af1a2d 100644 (file)
@@ -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
index ebb35f237d0d89c34f361da6a9fad3279fd83b00..0392bc1a2640d5fec4131b9a4a4b5eb971e7f880 100644 (file)
@@ -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
index 446a88f30bebaba2e0bee010cf92d700a4cbd129..df92423ec66960e6d511991eadc415b4e551aac9 100644 (file)
@@ -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/).
index 9c83c749e96d2011d0a96061740eb862d9292a66..f1316bf6d59b40335c59e642df8943f4b8f55e14 100644 (file)
@@ -59,6 +59,7 @@
                 <exclude>**/.mvn/**</exclude>
                 <exclude>**/*.jar</exclude>
                 <exclude>**/mvnw*</exclude>
+                <exclude>**/.flattened-pom.xml</exclude>
                 <exclude>dubbo-admin-distribution/src/LICENSE</exclude>
                 <exclude>dubbo-admin-distribution/src/NOTICE</exclude>
                 <exclude>dubbo-admin-distribution/src/licenses/**</exclude>
index df17468019acd329ccb4d1733e05850474d73ad5..dbbc16cd4e41a2ea30169a1ec338f789a899c894 100644 (file)
@@ -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
index 67af6603a7f7132bfbb580836c3a75423e4db21a..5a78317b914fb2b095e55212e88b72824335ac40 100644 (file)
@@ -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 %*
index 765f814371ee369ecaece79e32cc0f717ceaa047..3bb5e7276ca7f346a1b7f3f80f900443ae8f075c 100644 (file)
@@ -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
index d03d5ab54124e42eba063f770e5957df0a7fff33..73be90ffff60fa3836ba0e3eff4e025d44629a21 100644 (file)
@@ -33,6 +33,8 @@
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
         <mockito-version>2.23.4</mockito-version>
+        <jwt-version>3.4.1</jwt-version>
+        <jjwt-version>0.6.0</jjwt-version>
     </properties>
 
     <dependencies>
             <groupId>org.apache.curator</groupId>
             <artifactId>curator-recipes</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-x-discovery</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
             <artifactId>netty-all</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-serialization-kryo</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <artifactId>zookeeper</artifactId>
         </dependency>
 
+        <!--JWT-->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>${jwt-version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>${jjwt-version}</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.apache.dubbo.extensions</groupId>
+            <artifactId>dubbo-mock-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+        </dependency>
+
+        <!-- the mysql db driver need user put it in /opt-libs path -->
+<!--        <dependency>-->
+<!--            <groupId>mysql</groupId>-->
+<!--            <artifactId>mysql-connector-java</artifactId>-->
+<!--            <version>5.1.49</version>-->
+<!--            <scope>provided</scope>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <scope>runtime</scope>
+        </dependency>
     </dependencies>
 
     <build>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
                 <version>2.0.2.RELEASE</version>
+                <configuration>
+                    <layout>ZIP</layout>
+                </configuration>
                 <executions>
                     <execution>
                         <phase>package</phase>
index 4f73eae9bde2c7f0eb6b0d0cefb6925c44fcf61f..0be95b43789c2e3804369c1033260b8f76a04a40 100644 (file)
 
 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 (file)
index 0000000..bb468c0
--- /dev/null
@@ -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 (file)
index 0000000..c9445e6
--- /dev/null
@@ -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 (file)
index 0000000..d66fd1f
--- /dev/null
@@ -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;
+        }
+    }
+}
index f98a0d91a59a3290b7f2a12fd9d75cef631eaf62..0116da57dc4865cb379552ba78d6106e40521c07 100644 (file)
@@ -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<String> 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);
index fa568ff6cdfc2c363e9741f11e2a790f06fa569f..5ab5087e065739e674857b50788ac4a4d3387281 100644 (file)
@@ -19,10 +19,10 @@ package org.apache.dubbo.admin.common.util;
 
 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 @@ public class ServiceTestUtil {
 
     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 @@ public class ServiceTestUtil {
         keyType = StringUtils.strip(keyType);
 
         Map<Object, Object> 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 @@ public class ServiceTestUtil {
         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 (file)
index 0000000..7780434
--- /dev/null
@@ -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<Object> 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<Object> generateParameterTypes(String[] parameterTypes, ServiceDefinition serviceDefinition) {
+        List<Object> 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<String, Object> 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<String, Object> 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<Object, Object> 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<String, Object> 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<String, Object> enclosedMap = new HashMap<>();
+                holder.put(key, enclosedMap);
+                generateComplexType(sd, td, enclosedMap);
+            }
+
+        }
+    }
+}
index b548d91237cb20a065f586040c909e381173bb96..7a36c0b606f2b4b0a05bba14772aea06d157e30d 100644 (file)
@@ -18,7 +18,10 @@ package org.apache.dubbo.admin.common.util;
 
 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 class SyncUtils {
 
         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 class SyncUtils {
         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 class SyncUtils {
 
         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 class SyncUtils {
         }
         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;
+    }
+
 }
index 024097dbda1b87e96c8df1da3702e668984f62bb..81ec3b3c4da2ab37712109de4cd4fc24377ebcaa 100644 (file)
@@ -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 @@ import java.util.Map;
 
 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 class YamlParser {
     public static <T> T loadObject(String content, Class<T> type) {
         Map<String, Object> 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<Object> 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) {
index befc7a74bc9f3bda99b5cfe1b54233249ada6af2..8c39771a00dd9e971334efc3d0b81661b0dbe000 100644 (file)
 
 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 org.springframework.context.annotation.DependsOn;
 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 @@ public class ConfigCenter {
 
         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 @@ public class ConfigCenter {
         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 @@ public class ConfigCenter {
     /*
      * generate registry client
      */
-    @Bean
+    @Bean("dubboRegistry")
     @DependsOn("governanceConfiguration")
     Registry getRegistry() {
         Registry registry = null;
@@ -148,7 +155,7 @@ public class ConfigCenter {
     /*
      * generate metadata client
      */
-    @Bean
+    @Bean("metaDataCollector")
     @DependsOn("governanceConfiguration")
     MetaDataCollector getMetadataCollector() {
         MetaDataCollector metaDataCollector = new NoOpMetadataCollector();
@@ -168,6 +175,31 @@ public class ConfigCenter {
         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 (file)
index 0000000..9f3136c
--- /dev/null
@@ -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<MeshRouteDTO> searchRoutes(@RequestParam String application, @PathVariable String env) {
+        if (StringUtils.isBlank(application)) {
+            throw new ParamValidationException("application is required.");
+        }
+        List<MeshRouteDTO> 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 (file)
index 0000000..435e651
--- /dev/null
@@ -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<MockRuleDTO> listMockRules(@RequestParam(required = false) String filter, Pageable pageable) {
+        return mockRuleService.listMockRulesByPage(filter, pageable);
+    }
+}
index 4a9df1a09e87bca9569acf5a74a19d886d7f8bbb..bfd801a580ede2475b61092580a455457d9f8c12 100644 (file)
@@ -103,9 +103,16 @@ public class ServiceController {
         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 class ServiceController {
         return new HashSet<>(providerService.findServices());
     }
 
+    @RequestMapping(value = "/applications/instance", method = RequestMethod.GET)
+    public Set<String> allInstanceServices(@PathVariable String env) {
+        return new HashSet<>(providerService.findInstanceApplications());
+    }
+
     @RequestMapping(value = "/applications", method = RequestMethod.GET)
     public Set<String> allApplications(@PathVariable String env) {
         return providerService.findApplications();
index cea17080bd68b6b5f36fd37e2e60296a600a5e6f..ca3ad49a1713650289293e148d8feb0cc2f4ed76 100644 (file)
@@ -23,6 +23,7 @@ import org.apache.dubbo.admin.common.util.Constants;
 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 class ServiceTestController {
         MethodMetadata methodMetadata = null;
         if (metadata != null) {
             Gson gson = new Gson();
-            FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
-            List<MethodDefinition> 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<org.apache.dubbo.admin.model.domain.MethodDefinition> 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<MethodDefinition> methods = serviceDefinition.getMethods();
+                if (methods != null) {
+                    for (MethodDefinition m : methods) {
+                        if (ServiceTestV3Util.sameMethod(m, method)) {
+                            methodMetadata = ServiceTestV3Util.generateMethodMeta(serviceDefinition, m);
+                            break;
+                        }
                     }
                 }
             }
index 84a7940301d201bc25bef7659d5d4e133665a293..9a10dfdf5de865f5c42e0fc6e7aefee8337b29ed 100644 (file)
 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<String /*token*/, User /*user info*/> 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<LoginAuthentication> extensionLoader = ExtensionLoader.getExtensionLoader(LoginAuthentication.class);
+        Set<LoginAuthentication> supportedExtensionInstances = extensionLoader.getSupportedExtensionInstances();
+        Iterator<LoginAuthentication> 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;
     }
 
 }
index ecc6e57f7fe424c6cb43cb8a08b2d761c100ee62..818482203548dde1f57c7630548a9433757c96cf 100644 (file)
  */
 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<InterceptorAuthentication> extensionLoader = ExtensionLoader.getExtensionLoader(InterceptorAuthentication.class);
+        Set<InterceptorAuthentication> supportedExtensionInstances = extensionLoader.getSupportedExtensionInstances();
+        Iterator<InterceptorAuthentication> 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 (file)
index 0000000..1b670ca
--- /dev/null
@@ -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<MockRule> {
+}
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 (file)
index 0000000..54dc59b
--- /dev/null
@@ -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<String, String> parameters;
+
+    public Map<String, String> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, String> 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 (file)
index 0000000..1c0b8fe
--- /dev/null
@@ -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<TypeDefinition> parameters;
+    private List<String> annotations;
+
+    public MethodDefinition() {
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public List<TypeDefinition> 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<TypeDefinition> 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<String> getAnnotations() {
+        if (this.annotations == null) {
+            this.annotations = Collections.emptyList();
+        }
+
+        return this.annotations;
+    }
+
+    public void setAnnotations(List<String> 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 (file)
index 0000000..4ed3634
--- /dev/null
@@ -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;
+    }
+}
index 363872b1648bdfa4c3f7c28c47fc08238647d92a..2de0ad07efff9a5b50f0109167ae16f787fbef3e 100644 (file)
@@ -60,6 +60,8 @@ public class Provider extends Entity {
 
     private List<Override> overrides;
 
+    private RegistrySource registrySource;
+
     public Provider() {
     }
 
@@ -181,6 +183,14 @@ public class Provider extends Entity {
         this.overrides = overrides;
     }
 
+    public RegistrySource getRegistrySource() {
+        return registrySource;
+    }
+
+    public void setRegistrySource(RegistrySource registrySource) {
+        this.registrySource = registrySource;
+    }
+
     public URL toUrl() {
         Map<String, String> 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 (file)
index 0000000..e54644c
--- /dev/null
@@ -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 (file)
index 0000000..9205ac7
--- /dev/null
@@ -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<MethodDefinition> methods;
+
+    /**
+     * the definitions of type
+     */
+    private List<TypeDefinition> types;
+
+    /**
+     * the definitions of annotations
+     */
+    private List<String> annotations;
+
+    public String getCanonicalName() {
+        return canonicalName;
+    }
+
+    public String getCodeSource() {
+        return codeSource;
+    }
+
+    public List<MethodDefinition> getMethods() {
+        if (methods == null) {
+            methods = new ArrayList<>();
+        }
+        return methods;
+    }
+
+    public List<TypeDefinition> 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<MethodDefinition> methods) {
+        this.methods = methods;
+    }
+
+    public void setTypes(List<TypeDefinition> types) {
+        this.types = types;
+    }
+
+    public List<String> getAnnotations() {
+        if (annotations == null) {
+            annotations = Collections.emptyList();
+        }
+        return annotations;
+    }
+
+    public void setAnnotations(List<String> 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 (file)
index 0000000..71ed8fa
--- /dev/null
@@ -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<TypeDefinition> items;
+    @SerializedName("enum")
+    private List<String> enums;
+    private String $ref;
+    private Map<String, TypeDefinition> 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<String> getEnums() {
+        if (this.enums == null) {
+            this.enums = new ArrayList();
+        }
+
+        return this.enums;
+    }
+
+    public String getId() {
+        return this.id;
+    }
+
+    public List<TypeDefinition> getItems() {
+        if (this.items == null) {
+            this.items = new ArrayList();
+        }
+
+        return this.items;
+    }
+
+    public Map<String, TypeDefinition> 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<String> enums) {
+        this.enums = enums;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setItems(List<TypeDefinition> items) {
+        this.items = items;
+    }
+
+    public void setProperties(Map<String, TypeDefinition> 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 (file)
index 0000000..349c3c0
--- /dev/null
@@ -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 (file)
index 0000000..d808cdf
--- /dev/null
@@ -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;
+    }
+}
index 0202526c24329f2771e9d7fc62d09697ba9ee4f8..cd159163196f0d223aaf3d50ffebf34415d090c1 100644 (file)
 
 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<ServiceDTO>{
+public class ServiceDTO implements Comparable<ServiceDTO> {
     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 class ServiceDTO implements Comparable<ServiceDTO>{
         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 class ServiceDTO implements Comparable<ServiceDTO>{
             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 class ServiceDTO implements Comparable<ServiceDTO>{
         }
         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);
     }
 }
index 1ef4bebd96f8e70ef1ee887b37a760500d272eb3..d15a7bf280846cb4a6d9259ab85ce27eeb4773f4 100644 (file)
@@ -19,7 +19,6 @@ package org.apache.dubbo.admin.model.dto;
 
 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 class ServiceDetailDTO {
         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 (file)
index 0000000..94e7afd
--- /dev/null
@@ -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<String,String> 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<String, String> getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(Map<String, String> 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 (file)
index 0000000..8c99863
--- /dev/null
@@ -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<VirtualServiceRule> virtualServiceRuleList = new ArrayList<>();
+    private List<DestinationRule> destinationRuleList = new ArrayList<>();
+
+    public String getAppName() {
+        return appName;
+    }
+
+    public void setAppName(String appName) {
+        this.appName = appName;
+    }
+
+    public List<VirtualServiceRule> getVirtualServiceRuleList() {
+        return virtualServiceRuleList;
+    }
+
+    public void setVirtualServiceRuleList(List<VirtualServiceRule> virtualServiceRuleList) {
+        this.virtualServiceRuleList = virtualServiceRuleList;
+    }
+
+    public List<DestinationRule> getDestinationRuleList() {
+        return destinationRuleList;
+    }
+
+    public void setDestinationRuleList(List<DestinationRule> 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 (file)
index 0000000..71a5c43
--- /dev/null
@@ -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 (file)
index 0000000..9b0d8c6
--- /dev/null
@@ -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 (file)
index 0000000..470b7c4
--- /dev/null
@@ -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<Subset> subsets;
+    private TrafficPolicy trafficPolicy;
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public List<Subset> getSubsets() {
+        return subsets;
+    }
+
+    public void setSubsets(List<Subset> 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 (file)
index 0000000..66b6fa4
--- /dev/null
@@ -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<String, String> labels;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getLabels() {
+        return labels;
+    }
+
+    public void setLabels(Map<String, String> 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 (file)
index 0000000..1cc05ce
--- /dev/null
@@ -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 (file)
index 0000000..aa48bf6
--- /dev/null
@@ -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 (file)
index 0000000..bda74d6
--- /dev/null
@@ -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 (file)
index 0000000..e0c11e4
--- /dev/null
@@ -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 (file)
index 0000000..5a5a1ec
--- /dev/null
@@ -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 (file)
index 0000000..b8b13ec
--- /dev/null
@@ -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 (file)
index 0000000..59dcd3c
--- /dev/null
@@ -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<String, String> sourceLabels;
+    private DubboAttachmentMatch attachments;
+    private Map<String, StringMatch> 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<String, String> getSourceLabels() {
+        return sourceLabels;
+    }
+
+    public void setSourceLabels(Map<String, String> sourceLabels) {
+        this.sourceLabels = sourceLabels;
+    }
+
+    public DubboAttachmentMatch getAttachments() {
+        return attachments;
+    }
+
+    public void setAttachments(DubboAttachmentMatch attachments) {
+        this.attachments = attachments;
+    }
+
+    public Map<String, StringMatch> getHeaders() {
+        return headers;
+    }
+
+    public void setHeaders(Map<String, StringMatch> 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<String, String> sourceLabels,
+                                  Map<String, String> eagleeyeContext, Map<String, String> dubboContext,
+                                  Map<String, String> headers
+    ) {
+        if (dubboMatchRequest.getMethod() != null) {
+            if (!DubboMethodMatch.isMatch(dubboMatchRequest.getMethod(), methodName, parameterTypeList, parameters)) {
+                return false;
+            }
+        }
+
+        if (dubboMatchRequest.getSourceLabels() != null) {
+            for (Map.Entry<String, String> 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 (file)
index 0000000..9747b6b
--- /dev/null
@@ -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<StringMatch> services;
+    private List<DubboRouteDetail> routedetail;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<StringMatch> getServices() {
+        return services;
+    }
+
+    public void setServices(List<StringMatch> services) {
+        this.services = services;
+    }
+
+    public List<DubboRouteDetail> getRoutedetail() {
+        return routedetail;
+    }
+
+    public void setRoutedetail(List<DubboRouteDetail> 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 (file)
index 0000000..1b576d5
--- /dev/null
@@ -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<DubboMatchRequest> match;
+    private List<DubboRouteDestination> route;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<DubboMatchRequest> getMatch() {
+        return match;
+    }
+
+    public void setMatch(List<DubboMatchRequest> match) {
+        this.match = match;
+    }
+
+    public List<DubboRouteDestination> getRoute() {
+        return route;
+    }
+
+    public void setRoute(List<DubboRouteDestination> 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 (file)
index 0000000..c5798d8
--- /dev/null
@@ -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 (file)
index 0000000..c4eab8d
--- /dev/null
@@ -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<String> hosts;
+    private List<DubboRoute> dubbo;
+
+    public List<String> getHosts() {
+        return hosts;
+    }
+
+    public void setHosts(List<String> hosts) {
+        this.hosts = hosts;
+    }
+
+    public List<DubboRoute> getDubbo() {
+        return dubbo;
+    }
+
+    public void setDubbo(List<DubboRoute> 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 (file)
index 0000000..781308e
--- /dev/null
@@ -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 (file)
index 0000000..95ede77
--- /dev/null
@@ -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 (file)
index 0000000..d354157
--- /dev/null
@@ -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 (file)
index 0000000..89ab4d6
--- /dev/null
@@ -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 (file)
index 0000000..00d09db
--- /dev/null
@@ -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 (file)
index 0000000..37f1da4
--- /dev/null
@@ -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<String, StringMatch> eagleeyecontext;
+    private Map<String, StringMatch> dubbocontext;
+
+    public Map<String, StringMatch> getEagleeyecontext() {
+        return eagleeyecontext;
+    }
+
+    public void setEagleeyecontext(Map<String, StringMatch> eagleeyecontext) {
+        this.eagleeyecontext = eagleeyecontext;
+    }
+
+    public Map<String, StringMatch> getDubbocontext() {
+        return dubbocontext;
+    }
+
+    public void setDubbocontext(Map<String, StringMatch> dubbocontext) {
+        this.dubbocontext = dubbocontext;
+    }
+
+    public static boolean isMatch(DubboAttachmentMatch dubboAttachmentMatch, Map<String, String> eagleeyeContext, Map<String, String> dubboContext) {
+        if (dubboAttachmentMatch.getDubbocontext() != null) {
+            for (Map.Entry<String, StringMatch> 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<String, StringMatch> 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 (file)
index 0000000..8e0f991
--- /dev/null
@@ -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 (file)
index 0000000..c448895
--- /dev/null
@@ -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<DubboMethodArg> args;
+    private List<StringMatch> argp;
+    private Map<String, StringMatch> 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<DubboMethodArg> getArgs() {
+        return args;
+    }
+
+    public void setArgs(List<DubboMethodArg> args) {
+        this.args = args;
+    }
+
+    public List<StringMatch> getArgp() {
+        return argp;
+    }
+
+    public void setArgp(List<StringMatch> argp) {
+        this.argp = argp;
+    }
+
+    public Map<String, StringMatch> getHeaders() {
+        return headers;
+    }
+
+    public void setHeaders(Map<String, StringMatch> 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<StringMatch> 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<DubboMethodArg> 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 (file)
index 0000000..b3289e2
--- /dev/null
@@ -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 (file)
index 0000000..51c4b44
--- /dev/null
@@ -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<DoubleMatch> oneof;
+
+    public List<DoubleMatch> getOneof() {
+        return oneof;
+    }
+
+    public void setOneof(List<DoubleMatch> 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 (file)
index 0000000..d8f935f
--- /dev/null
@@ -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<StringMatch> oneof;
+
+    public List<StringMatch> getOneof() {
+        return oneof;
+    }
+
+    public void setOneof(List<StringMatch> 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 (file)
index 0000000..5cd7465
--- /dev/null
@@ -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 (file)
index 0000000..d0bb07d
--- /dev/null
@@ -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);
+    }
+}
index 21e739bd35c8fb4f2b32348c870a8d3db877c36c..70ce83a5d44dd4617f14aa5f4a8aca60a2f9e8d6 100644 (file)
@@ -21,20 +21,21 @@ import org.apache.dubbo.common.URL;
 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 (file)
index 528df20..0000000
+++ /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 (file)
index 7c48fa7..0000000
+++ /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<GetValue> response = client.getKVValue(key);
-                       if (response.getValue() == null) {
-                               return null;
-                       }
-                       return response.getValue().getDecodedValue();
-               }
-               Response<GetValue> 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 (file)
index 0000000..ed870a8
--- /dev/null
@@ -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 (file)
index f5d0c7b..0000000
+++ /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<String, String> 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;
-    }
-}
index 5c4fd1819942f18d36e6cf4368183e611751f68f..e5cead735fa8abde3c59fedce7305a2030703151 100644 (file)
@@ -38,8 +38,8 @@ public class NoOpConfiguration implements GovernanceConfiguration {
     }
 
     @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 class NoOpConfiguration implements GovernanceConfiguration {
     }
 
     @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 (file)
index 362dd26..0000000
+++ /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 (file)
index 0000000..076bb56
--- /dev/null
@@ -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<URL> 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 (file)
index 0000000..750c734
--- /dev/null
@@ -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<String, ServiceInstancesChangedListener> 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<String> 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<ServiceInstance> 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<URL> urls) {
+            String serviceKey = removeProtocol(protocolServiceKey);
+            ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appServiceMap = instanceRegistryCache.computeIfAbsent(Constants.PROVIDERS_CATEGORY, key -> new ConcurrentHashMap<>());
+            Map<String, List<InstanceAddressURL>> serviceMap = appServiceMap.computeIfAbsent(serviceName, key -> new ConcurrentHashMap<>());
+            if (CollectionUtils.isEmpty(urls)) {
+                serviceMap.remove(serviceKey);
+            } else {
+                List<InstanceAddressURL> 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 (file)
index 0000000..1afde55
--- /dev/null
@@ -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<String, Object> oldServiceUrls;
+
+    public AdminServiceInstancesChangedListener(Set<String> 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<URL>) 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 (file)
index 0000000..6559a29
--- /dev/null
@@ -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 (file)
index 0000000..a7d25c9
--- /dev/null
@@ -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<String> 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<MappingListener> listeners = new ConcurrentHashSet<>();
+
+    private static final int PAGINATION_SIZE = 100;
+
+    private NacosNamingServiceWrapper namingService;
+
+    private Set<String> 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<String> 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<String> getAllServiceNames() throws NacosException {
+
+        Set<String> serviceNames = new HashSet<>();
+        int pageIndex = 1;
+        ListView<String> listView = namingService.getServicesOfServer(pageIndex, PAGINATION_SIZE,
+                Constants.DEFAULT_GROUP);
+        // First page data
+        List<String> 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 (file)
index 0000000..845efa2
--- /dev/null
@@ -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 (file)
index 0000000..799c040
--- /dev/null
@@ -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<MappingListener> listeners = new ConcurrentHashSet<>();
+
+    private final Set<String> 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<String> 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<String> 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 (file)
index 0000000..708dd7e
--- /dev/null
@@ -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 (file)
index 0000000..2389219
--- /dev/null
@@ -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<MockRuleDTO> 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);
+}
index 95d46f857882be48afec61f2f3914adb2f3241e9..5417d302231af844140b0a8c9ce0edeaa41694bd 100644 (file)
@@ -25,26 +25,11 @@ import java.util.Set;
 
 /**
  * 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<String> findServices();
 
+    /**
+     * Get all instance registry provider's service name
+     *
+     * @return list of all provider's service name
+     */
+    Set<String> findInstanceApplications();
+
+
     String findServiceVersion(String serviceName, String application);
 
     String findVersionInApplication(String application);
 
     List<String> findAddresses();
 
-    List<String> findAddressesByApplication(String application);
-
-    List<String> findAddressesByService(String serviceName);
-
-    List<String> findApplicationsByServiceName(String serviceName);
-
     /**
      * Get provider list with specific service name.
      *
@@ -74,8 +61,6 @@ public interface ProviderService {
      */
     List<Provider> findByService(String serviceName);
 
-    List<Provider> findByAppandService(String app, String serviceName);
-
     List<Provider> findAll();
 
     /**
@@ -86,8 +71,6 @@ public interface ProviderService {
      */
     List<Provider> findByAddress(String providerAddress);
 
-    List<String> findServicesByAddress(String providerAddress);
-
     Set<String> findApplications();
 
     /**
@@ -100,13 +83,9 @@ public interface ProviderService {
 
     List<String> findServicesByApplication(String application);
 
-    List<String> findMethodsByService(String serviceName);
-
-    Provider findByServiceAndAddress(String service, String address);
-
     /**
      * Get a set of service data object.
-     *
+     * <p>
      * 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 (file)
index 0000000..0335909
--- /dev/null
@@ -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<K, V> {
+
+    /**
+     * 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<? super K, ? extends V> mappingFunction) {
+        return null;
+    }
+
+}
index f57cdb3d13a1f50e6bb424d85969267ccad3e999..3e66694646999516abd18707cf2d565b5ce7c2df 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.dubbo.admin.service;
 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.NetUtils;
 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.Map;
 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<category, ConcurrentMap<servicename, Map<MD5, URL>>>
      * registryCache
      */
-    private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> registryCache = new ConcurrentHashMap<>();
     @Autowired
     private Registry registry;
 
-    public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
-        return registryCache;
-    }
+    @Autowired
+    private InterfaceRegistryCache interfaceRegistryCache;
 
     @EventListener(classes = ApplicationReadyEvent.class)
     public void startSubscribe() {
@@ -88,7 +86,7 @@ public class RegistryServerSync implements DisposableBean, NotifyListener {
         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<URL> urls) {
         if (urls == null || urls.isEmpty()) {
@@ -98,20 +96,23 @@ public class RegistryServerSync implements DisposableBean, NotifyListener {
         final Map<String, Map<String, Map<String, URL>>> 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<String, Map<String, URL>> services = registryCache.get(category);
+                ConcurrentMap<String, Map<String, URL>> 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<String, Map<String, URL>> 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 class RegistryServerSync implements DisposableBean, NotifyListener {
                 }
             } else {
                 if (StringUtils.isEmpty(interfaceName)) {
-                    interfaceName = url.getServiceInterface();
+                    interfaceName = getServiceInterface(url);
                 }
                 Map<String, Map<String, URL>> 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<String, URL> ids = services.get(service);
                 if (ids == null) {
                     ids = new HashMap<>();
@@ -150,14 +153,14 @@ public class RegistryServerSync implements DisposableBean, NotifyListener {
         }
         for (Map.Entry<String, Map<String, Map<String, URL>>> categoryEntry : categories.entrySet()) {
             String category = categoryEntry.getKey();
-            ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
+            ConcurrentMap<String, Map<String, URL>> services = interfaceRegistryCache.get(category);
             if (services == null) {
-                services = new ConcurrentHashMap<String, Map<String, URL>>();
-                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<String> keys = new HashSet<String>(services.keySet());
+                Set<String> 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 class RegistryServerSync implements DisposableBean, NotifyListener {
             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;
+    }
+
 }
 
index f7bae0d49f5291c721aeb42000ed1a7dfc86eb15..501b13eca5cea6e5f4d42cb3ae40a734200b4d2d 100644 (file)
@@ -18,7 +18,6 @@ package org.apache.dubbo.admin.service.impl;
 
 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<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
-        return sync.getRegistryCache();
+    public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getInterfaceRegistryCache() {
+        return interfaceRegistryCache.getRegistryCache();
     }
 
 }
index 4a803ed63ec036abc4d1f7eb0f573f8cd5d1e355..0d0f2e5957cf348d96a028491b2b0a79753048dc 100644 (file)
@@ -52,7 +52,7 @@ public class ConsumerServiceImpl extends AbstractService implements ConsumerServ
     private Map<String, URL> findAllConsumerUrl() {
         Map<String, String> filter = new HashMap<String, String>();
         filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+        return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
     }
 
 
@@ -69,7 +69,7 @@ public class ConsumerServiceImpl extends AbstractService implements ConsumerServ
         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<String, URL> findConsumerUrlByService(String service) {
@@ -77,7 +77,7 @@ public class ConsumerServiceImpl extends AbstractService implements ConsumerServ
         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 class ConsumerServiceImpl extends AbstractService implements ConsumerServ
         Map<String, String> filter = new HashMap<>();
         filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
         filter.put(Constants.APPLICATION_KEY, application);
-        Map<String, URL> stringURLMap = SyncUtils.filterFromCategory(getRegistryCache(), filter);
+        Map<String, URL> stringURLMap = SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
         if (stringURLMap == null || stringURLMap.isEmpty()) {
             throw new ParamValidationException("there is no consumer for application: " + application);
         }
index 8fe492c509699833bd389f03d026c7d1d4be3a81..11becca8ef64cb4bc6c04b8683fecfd54dc91897 100644 (file)
@@ -73,7 +73,8 @@ public class GenericServiceImpl {
         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 (file)
index 0000000..9f1b5ac
--- /dev/null
@@ -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<appName, Map<serviceKey, List<InstanceAddressURL>>>
+ */
+@Component
+public class InstanceRegistryCache implements RegistryCache<String, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> {
+
+    private final ConcurrentMap<String, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> registryCache = new ConcurrentHashMap<>();
+
+    @Override
+    public void put(String key, ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> value) {
+        registryCache.put(key, value);
+    }
+
+    @Override
+    public ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> get(String key) {
+        return registryCache.get(key);
+    }
+
+    @Override
+    public ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> computeIfAbsent(String key,
+                                                                                        Function<? super String, ? extends ConcurrentMap<String, Map<String, List<InstanceAddressURL>>>> 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 (file)
index 0000000..aae6e65
--- /dev/null
@@ -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<String> findServices() {
+        Set<String> services = Sets.newHashSet();
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> 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<String> findApplications() {
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+        if (appInterfaceMap == null) {
+            return Sets.newHashSet();
+        }
+        return Sets.newHashSet(appInterfaceMap.keySet());
+    }
+
+    public List<Provider> findByService(String serviceName) {
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+        if (appInterfaceMap == null) {
+            return Lists.newArrayList();
+        }
+        List<InstanceAddressURL> 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<Provider> findByAddress(String providerAddress) {
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+        if (appInterfaceMap == null) {
+            return Lists.newArrayList();
+        }
+        List<InstanceAddressURL> 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<Provider> findByApplication(String application) {
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+        if (appInterfaceMap == null || appInterfaceMap.get(application) == null) {
+            return Lists.newArrayList();
+        }
+        List<InstanceAddressURL> providerUrls = Lists.newArrayList();
+        appInterfaceMap.get(application).forEach((service, urls) -> providerUrls.addAll(urls));
+        return urlsToProviderList(providerUrls);
+    }
+
+    public String findVersionInApplication(String application) {
+        ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appInterfaceMap = instanceRegistryCache.get(Constants.PROVIDERS_CATEGORY);
+        if (appInterfaceMap == null || appInterfaceMap.get(application) == null) {
+            return null;
+        }
+        Map<String, List<InstanceAddressURL>> urlsMap = appInterfaceMap.get(application);
+        for (Map.Entry<String, List<InstanceAddressURL>> entry : urlsMap.entrySet()) {
+            List<InstanceAddressURL> urls = entry.getValue();
+            if (CollectionUtils.isNotEmpty(urls)) {
+                return urls.get(0).getParameter(Constants.SPECIFICATION_VERSION_KEY, "3.0.0");
+            }
+        }
+        return null;
+    }
+
+    private List<Provider> urlsToProviderList(List<InstanceAddressURL> urls) {
+        List<Provider> 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 (file)
index 0000000..ab5b3be
--- /dev/null
@@ -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<serviceKey, Map<hash, URL>>
+ */
+@Component
+public class InterfaceRegistryCache implements RegistryCache<String, ConcurrentMap<String, Map<String, URL>>> {
+
+    private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> registryCache = new ConcurrentHashMap<>();
+
+    @Override
+    public void put(String key, ConcurrentMap<String, Map<String, URL>> value) {
+        registryCache.put(key, value);
+    }
+
+    @Override
+    public ConcurrentMap<String, Map<String, URL>> get(String key) {
+        return registryCache.get(key);
+    }
+
+    public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
+        return registryCache;
+    }
+}
index a1668fd8f31589b33265216a58f865e7360cabba..40ba2586bca7e2f3f994c6549aef30b29a88c57a 100644 (file)
@@ -73,8 +73,7 @@ public class ManagementServiceImpl extends AbstractService implements Management
     }
 
     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 (file)
index 0000000..fd591bd
--- /dev/null
@@ -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<Object> 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 (file)
index 0000000..7b659d5
--- /dev/null
@@ -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<MockRule> 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<MockRuleDTO> listMockRulesByPage(String filter, Pageable pageable) {
+        QueryWrapper<MockRule> queryWrapper = new QueryWrapper<>();
+        Optional.ofNullable(filter)
+                .ifPresent(f -> queryWrapper.like("service_name", f));
+        List<MockRule> mockRules = mockRuleMapper.selectList(queryWrapper);
+        int total = mockRules.size();
+        final List<MockRuleDTO> 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<MockRule> 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;
+    }
+}
index 1bc018e1e878647aa0c41c66a15284a8d2a04bd0..361122a0cdb47a5b398e670a5ea061e6c68da249 100644 (file)
@@ -42,7 +42,6 @@ import java.util.Map;
 
 @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 @@ public class OverrideServiceImpl extends AbstractService implements OverrideServ
         }
         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) {
index 0d8308153d792057e548e51f536fcb7298c3b706..1defce7656bc3776ac92518a6e09ced3fd6f44d9 100644 (file)
@@ -18,16 +18,14 @@ package org.apache.dubbo.admin.service.impl;
 
 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.HashMap;
 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 @@ import java.util.stream.Collectors;
 public class ProviderServiceImpl extends AbstractService implements ProviderService {
 
     @Autowired
-    OverrideService overrideService;
+    private InstanceRegistryQueryHelper instanceRegistryQueryHelper;
 
     @Override
     public void create(Provider provider) {
@@ -63,57 +60,27 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         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<String, URL> findProviderUrlPair(String id) {
-        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id);
-    }
-
     @Override
     public Set<String> findServices() {
         Set<String> ret = new HashSet<>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls != null){
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls != null) {
             ret.addAll(providerUrls.keySet());
         }
+        ret.addAll(instanceRegistryQueryHelper.findServices());
         return ret;
     }
 
+    @Override
+    public Set<String> findInstanceApplications() {
+        return instanceRegistryQueryHelper.findApplications();
+    }
+
     @Override
     public List<String> findAddresses() {
         List<String> ret = new ArrayList<String>();
 
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
         if (null == providerUrls) {
             return ret;
         }
@@ -128,80 +95,15 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
                 }
             }
         }
-
-        return ret;
-    }
-
-    @Override
-    public List<String> findAddressesByApplication(String application) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> 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<String> findAddressesByService(String service) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (null == providerUrls) {
-            return ret;
-        }
-
-        for (Map.Entry<String, URL> e2 : providerUrls.get(service).entrySet()) {
-            URL u = e2.getValue();
-            String app = u.getAddress();
-            if (app != null) {
-                ret.add(app);
-            }
-        }
-
-        return ret;
-    }
-
-    @Override
-    public List<String> findApplicationsByServiceName(String service) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (null == providerUrls) {
-            return ret;
-        }
-
-        Map<String, URL> value = providerUrls.get(service);
-        if (value == null) {
-            return ret;
-        }
-        for (Map.Entry<String, URL> e2 : value.entrySet()) {
-            URL u = e2.getValue();
-            String app = u.getParameter(Constants.APPLICATION);
-            if (app != null){
-                ret.add(app);
-            }
-        }
-
         return ret;
     }
 
     @Override
     public List<Provider> findByService(String serviceName) {
-        return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
-    }
-
-    @Override
-    public List<Provider> findByAppandService(String app, String serviceName) {
-        return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName));
+        List<Provider> instanceProviders = instanceRegistryQueryHelper.findByService(serviceName);
+        List<Provider> interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
+        instanceProviders.addAll(interfaceProviders);
+        return instanceProviders;
     }
 
     private Map<String, URL> findProviderUrlByService(String service) {
@@ -209,7 +111,7 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         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 class ProviderServiceImpl extends AbstractService implements ProviderServ
     private Map<String, URL> findAllProviderUrl() {
         Map<String, String> filter = new HashMap<String, String>();
         filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+        return SyncUtils.filterFromCategory(getInterfaceRegistryCache(), filter);
     }
 
     @Override
     public List<Provider> findByAddress(String providerAddress) {
-        return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
+        List<Provider> instanceProviders = instanceRegistryQueryHelper.findByAddress(providerAddress);
+        List<Provider> interfaceProviders = SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
+        instanceProviders.addAll(interfaceProviders);
+        return instanceProviders;
     }
 
     public Map<String, URL> findProviderUrlByAddress(String address) {
@@ -233,37 +138,14 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
         filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
 
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    @Override
-    public List<String> findServicesByAddress(String address) {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null || address == null || address.length() == 0) {
-            return ret;
-        }
-
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> 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<String> findApplications() {
-        Set<String> ret = new HashSet<>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null){
+        Set<String> ret = instanceRegistryQueryHelper.findApplications();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls == null) {
             return ret;
         }
 
@@ -283,11 +165,18 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
 
     @Override
     public List<Provider> findByApplication(String application) {
-        return SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
+        List<Provider> instanceProviders = instanceRegistryQueryHelper.findByApplication(application);
+        List<Provider> 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<String> services = findServicesByApplication(application);
         if (services == null || services.size() == 0) {
             throw new ParamValidationException("there is no service for application: " + application);
@@ -313,23 +202,22 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         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<String, URL> findProviderUrlByApplication(String application) {
         Map<String, String> 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<String> findServicesByApplication(String application) {
         List<String> ret = new ArrayList<String>();
 
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getInterfaceRegistryCache().get(Constants.PROVIDERS_CATEGORY);
         if (providerUrls == null || application == null || application.length() == 0) {
             return ret;
         }
@@ -348,59 +236,6 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         return ret;
     }
 
-    @Override
-    public List<String> findMethodsByService(String service) {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null || service == null || service.length() == 0){
-            return ret;
-        }
-
-        Map<String, URL> providers = providerUrls.get(service);
-        if (null == providers || providers.isEmpty()) {
-            return ret;
-        }
-
-        Entry<String, URL> 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<String, URL> findProviderUrl(String service, String address) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
-
-        Map<String, URL> ret = SyncUtils.filterFromCategory(getRegistryCache(), filter);
-        if (ret.isEmpty()) {
-            return null;
-        } else {
-            String key = ret.entrySet().iterator().next().getKey();
-            return new Pair<String, URL>(key, ret.get(key));
-        }
-    }
-
     @Override
     public Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env) {
         List<Provider> providers = new ArrayList<>();
@@ -420,15 +255,14 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
                 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 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
                 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<ServiceDTO> result = convertProviders2DTO(providers);
-        return result;
+        return convertProviders2DTO(providers);
     }
 
     /**
@@ -472,6 +303,7 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
             s.setService(interfaze);
             s.setGroup(group);
             s.setVersion(version);
+            s.setRegistrySource(provider.getRegistrySource());
             result.add(s);
         }
         return result;
index ed28d641d7e6864a003798f04afa1e1efb467eac..4856a5fc517f4bb68965351a662de686a421092d 100644 (file)
@@ -39,8 +39,6 @@ import java.util.List;
 @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 class RouteServiceImpl extends AbstractService implements RouteService {
     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 (file)
index 0000000..d9f5b7c
--- /dev/null
@@ -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<String, Object> 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 (file)
index 0000000..87a445d
--- /dev/null
@@ -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> T getBean(Class<T> 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 (file)
index 0000000..ef91a43
--- /dev/null
@@ -0,0 +1 @@
+defaultHandle=org.apache.dubbo.admin.authentication.impl.DefaultPreHandle
\ No newline at end of file
index 14b6b024bf5db46ce77f674ec16bc6df772bbaae..88d69fe4d7ecf060304c4e1b4576300f81dd0393 100644 (file)
@@ -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 (file)
index 0000000..90c6c4a
--- /dev/null
@@ -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
index df17468019acd329ccb4d1733e05850474d73ad5..4aa924b221de2c39a7460c1f3434b437e83e42ff 100644 (file)
@@ -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 (file)
index 0000000..f738db7
--- /dev/null
@@ -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
index 9448a93884d472543e2a63a167672d5530dfa60b..01bed98ea6b93c771057818aeea656ae81d81a7f 100644 (file)
@@ -73,9 +73,11 @@ public abstract class AbstractSpringIntegrationTest {
             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");
         }
     }
 }