This is an automated email from the ASF dual-hosted git repository.
jooks pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 9b5b84485 Adding a Dubbo plugin to shenyu ingress-controller (#5000)
9b5b84485 is described below
commit 9b5b844859bfe9aa714a1028079413c30bfd625a
Author: Runqi Zhao <[email protected]>
AuthorDate: Sun Aug 13 14:19:18 2023 +0800
Adding a Dubbo plugin to shenyu ingress-controller (#5000)
* Add dubbo annotation analysis for shenyu ingress controller
* Add dubbo annotation analysis for shenyu ingress controller
* fix: fix checkstyle
* style: Improve coding style
* fix: Fix the encoding format, set the id value and dubboIngerssParser
* style: Fix code style
* fix: Replace upstream with metdata and fix the ID
* fix
* fix
* fix
* fix
* fix
* style: ci
* fix: fix
* fix: fix
* fix: fix
---------
Co-authored-by: Kunshuai Zhu <[email protected]>
---
.../k8s/ingress.yml | 85 ++++++
.../k8s/script/healthcheck.sh | 48 ++++
.../k8s/script/services.list | 19 ++
.../k8s/shenyu-deployment.yml | 82 ++++++
.../k8s/shenyu-examples-dubbo.yml | 75 ++++++
.../k8s/shenyu-service.yml | 52 ++++
.../k8s/shenyu-zookeeper.yml | 78 ++++++
.../shenyu/k8s/common/IngressConfiguration.java | 67 +++++
.../apache/shenyu/k8s/common/IngressConstants.java | 29 ++
.../shenyu/k8s/common/ShenyuMemoryConfig.java | 14 +-
...IngressParser.java => DivideIngressParser.java} | 94 +++----
...{IngressParser.java => DubboIngressParser.java} | 279 ++++++++++---------
.../apache/shenyu/k8s/parser/IngressParser.java | 296 +--------------------
.../shenyu/k8s/reconciler/IngressReconciler.java | 187 +++++++------
.../k8s/repository/ShenyuCacheRepository.java | 33 ++-
.../k8s/IngressControllerConfiguration.java | 8 +-
16 files changed, 891 insertions(+), 555 deletions(-)
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/ingress.yml
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/ingress.yml
new file mode 100644
index 000000000..41b0e8df8
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/ingress.yml
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+apiVersion: v1
+kind: Service
+metadata:
+ name: dubbo-findbyid
+ annotations:
+ kubernetes.io/ingress.class: shenyu
+ shenyu.apache.org/plugin-dubbo-enabled: 'true'
+ shenyu.apache.org/plugin-dubbo-app-name: dubbo
+ shenyu.apache.org/plugin-context-path: /dubbo
+ shenyu.apache.org/plugin-dubbo-path: /dubbo/findById
+ shenyu.apache.org/plugin-dubbo-rpc-type: dubbo
+ shenyu.apache.org/plugin-dubbo-servive-name:
org.apache.shenyu.examples.dubbo.api.service.DubboTestService
+ shenyu.apache.org/plugin-dubbo-method-name: findById
+ shenyu.apache.org/plugin-dubbo-rule-name: /dubbo/findById
+ shenyu.apache.org/plugin-dubbo-param-types: java.lang.String
+spec:
+ selector:
+ app: shenyu-examples-dubbo
+ ports:
+ - port: 20880 # Assuming this is the Dubbo service port
+
+---
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: dubbo-findall
+ annotations:
+ kubernetes.io/ingress.class: shenyu
+ shenyu.apache.org/plugin-dubbo-enabled: 'true'
+ shenyu.apache.org/plugin-dubbo-app-name: dubbo
+ shenyu.apache.org/plugin-context-path: /dubbo
+ shenyu.apache.org/plugin-dubbo-path: /dubbo/findAll
+ shenyu.apache.org/plugin-dubbo-rpc-type: dubbo
+ shenyu.apache.org/plugin-dubbo-servive-name:
org.dromara.shenyu.examples.dubbo.api.service.DubboTestService
+ shenyu.apache.org/plugin-dubbo-method-name: findAll
+ shenyu.apache.org/plugin-dubbo-rule-name: /dubbo/findAll
+spec:
+ selector:
+ app: shenyu-examples-dubbo
+ ports:
+ - port: 20880 # Assuming this is the Dubbo service port
+
+---
+
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: shenyu
+ shenyu.apache.org/plugin-dubbo-enabled: 'true'
+ name: demo-ingress
+spec:
+ rules:
+ - http:
+ paths:
+ - backend:
+ service:
+ name: dubbo-findbyid
+ port:
+ number: 20880
+ path: /dubbo/findById
+ pathType: ImplementationSpecific
+ - backend:
+ service:
+ name: dubbo-findall
+ port:
+ number: 20880
+ path: /dubbo/findAll
+ pathType: ImplementationSpecific
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/healthcheck.sh
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/healthcheck.sh
new file mode 100644
index 000000000..c7a4c7b44
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/healthcheck.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+#
+# 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.
+#
+
+PRGDIR=`dirname "$0"`
+for service in `grep -v -E "^$|^#" ${PRGDIR}/services.list`
+do
+ for loop in `seq 1 30`
+ do
+ status=`curl -o /dev/null -s -w %{http_code} $service`
+ echo -e "curl $service response $status"
+
+ if [ $status -eq 200 ]; then
+ break
+ fi
+
+ sleep 2
+ done
+done
+
+sleep 5
+
+status=`curl -s -o /dev/null -w "%{http_code}" -X POST -H
"Content-Type:application/json" http://localhost:31195/http/order/save --data
'{"name":"test", "id": 123}'`
+
+sleep 3
+
+if [ $status -eq 200 ]; then
+ echo -e "Success to send request: $status"
+ echo -e "\n-------------------"
+ exit 0
+fi
+echo -e "Failed to send request from shenyu-bootstrap to dubbo example:
$status"
+echo -e "\n-------------------"
+exit 1
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/services.list
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/services.list
new file mode 100644
index 000000000..fb77cd36a
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/script/services.list
@@ -0,0 +1,19 @@
+# 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.
+
+http://localhost:31095/actuator/health
+http://localhost:31195/actuator/health
+http://localhost:31189/test/path/123?name=tom
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-deployment.yml
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-deployment.yml
new file mode 100644
index 000000000..05d8c10c0
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-deployment.yml
@@ -0,0 +1,82 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: shenyu-admin
+ labels:
+ app: shenyu-admin
+ all: shenyu-examples-dubbo
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: shenyu-admin
+ all: shenyu-examples-dubbo
+ template:
+ metadata:
+ labels:
+ app: shenyu-admin
+ all: shenyu-examples-dubbo
+ spec:
+ containers:
+ - name: shenyu-admin
+ image: apache/shenyu-admin:latest
+ resources: {}
+ env:
+ - name: SPRING_PROFILES_ACTIVE
+ value: h2
+ - name: shenyu.database.init_script
+ value: sql-script/h2/schema.sql
+ ports:
+ - containerPort: 9095
+ imagePullPolicy: IfNotPresent
+ restartPolicy: Always
+status: {}
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: shenyu-bootstrap
+ labels:
+ app: shenyu-bootstrap
+ all: shenyu-examples-dubbo
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: shenyu-bootstrap
+ all: shenyu-examples-dubbo
+ template:
+ metadata:
+ labels:
+ app: shenyu-bootstrap
+ all: shenyu-examples-dubbo
+ spec:
+ containers:
+ - name: shenyu-bootstrap
+ image: apache/shenyu-bootstrap:latest
+ resources: {}
+ env:
+ - name: shenyu.sync.websocket.urls
+ value: ws://shenyu-admin:9095/websocket
+ ports:
+ - containerPort: 9195
+ imagePullPolicy: IfNotPresent
+ restartPolicy: Always
+status: {}
\ No newline at end of file
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-examples-dubbo.yml
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-examples-dubbo.yml
new file mode 100644
index 000000000..3fec08640
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-examples-dubbo.yml
@@ -0,0 +1,75 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: shenyu-examples-dubbo-deployment
+ labels:
+ app: shenyu-examples-dubbo
+ all: shenyu-examples-dubbo
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: shenyu-examples-dubbo
+ all: shenyu-examples-dubbo
+ strategy: {}
+ template:
+ metadata:
+ labels:
+ app: shenyu-examples-dubbo
+ all: shenyu-examples-dubbo
+ spec:
+ containers:
+ - image: shenyu-examples-dubbo
+ name: shenyu-examples-dubbo
+ livenessProbe:
+ exec:
+ command:
+ - wget -q -O - http://localhost:8189/actuator/health | grep UP
|| exit 1
+ initialDelaySeconds: 10
+ failureThreshold: 3
+ timeoutSeconds: 2
+ env:
+ - name: shenyu.register.serverLists
+ value: http://shenyu-admin:9095
+ ports:
+ - containerPort: 8189
+ imagePullPolicy: IfNotPresent
+ restartPolicy: Always
+status: {}
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: shenyu-examples-apache-dubbo-service
+ labels:
+ app: shenyu-examples-dubbo
+ all: shenyu-examples-dubbo
+spec:
+ selector:
+ app: shenyu-examples-dubbo
+ all: shenyu-examples-dubbo
+ type: NodePort
+ ports:
+ - name: "8189"
+ port: 8189
+ targetPort: 8189
+ nodePort: 31190
+status:
+ loadBalancer: {}
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-service.yml
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-service.yml
new file mode 100644
index 000000000..57f720aaf
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-service.yml
@@ -0,0 +1,52 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v1
+kind: Service
+metadata:
+ name: shenyu-admin
+ labels:
+ app: shenyu-admin
+ all: shenyu-examples-dubbo
+spec:
+ type: NodePort
+ selector:
+ app: shenyu-admin
+ all: shenyu-examples-dubbo
+ ports:
+ - name: "9095"
+ port: 9095
+ targetPort: 9095
+ nodePort: 31095
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: shenyu-bootstrap
+ labels:
+ app: shenyu-bootstrap
+ all: shenyu-examples-dubbo
+spec:
+ type: NodePort
+ selector:
+ app: shenyu-bootstrap
+ all: shenyu-examples-dubbo
+ ports:
+ - name: "9195"
+ port: 9195
+ targetPort: 9195
+ nodePort: 31195
\ No newline at end of file
diff --git
a/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-zookeeper.yml
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-zookeeper.yml
new file mode 100644
index 000000000..e311194fb
--- /dev/null
+++
b/shenyu-examples/shenyu-examples-dubbo/shenyu-examples-apache-dubbo-service/k8s/shenyu-zookeeper.yml
@@ -0,0 +1,78 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: shenyu-zk
+ all: shenyu-examples-dubbo
+ name: shenyu-zk
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: shenyu-zk
+ all: shenyu-examples-dubbo
+ strategy: {}
+ template:
+ metadata:
+ labels:
+ app: shenyu-zk
+ all: shenyu-examples-dubbo
+ spec:
+ containers:
+ - image: zookeeper:3.5
+ name: shenyu-zk
+ resources: {}
+ ports:
+ - containerPort: 2181
+ name: client
+ - containerPort: 2888
+ name: server
+ - containerPort: 3888
+ name: leader-election
+ - containerPort: 8080
+ name: website
+ restartPolicy: Always
+status: {}
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: shenyu-zk
+ labels:
+ app: shenyu-zk
+ all: shenyu-examples-dubbo
+spec:
+ type: NodePort
+ selector:
+ app: shenyu-zk
+ all: shenyu-examples-dubbo
+ ports:
+ - name: "client"
+ port: 2181
+ targetPort: 2181
+ - name: "server"
+ port: 2888
+ targetPort: 2888
+ - name: "election"
+ port: 3888
+ targetPort: 3888
+ - name: "website"
+ port: 8080
+ targetPort: 8080
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConfiguration.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConfiguration.java
new file mode 100644
index 000000000..e0fd7bb6d
--- /dev/null
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConfiguration.java
@@ -0,0 +1,67 @@
+/*
+ * 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.shenyu.k8s.common;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+
+public class IngressConfiguration {
+
+ private final SelectorData selectorData;
+
+ private final RuleData ruleData;
+
+ private final MetaData metaData;
+
+ /**
+ * constructor.
+ * @param selectorData selectorData
+ * @param ruleData ruleData
+ * @param metaData metaData
+ */
+ public IngressConfiguration(final SelectorData selectorData, final
RuleData ruleData, final MetaData metaData) {
+ this.selectorData = selectorData;
+ this.ruleData = ruleData;
+ this.metaData = metaData;
+ }
+
+ /**
+ * get selectorData.
+ * @return selectorData
+ */
+ public SelectorData getSelectorData() {
+ return selectorData;
+ }
+
+ /**
+ * get ruleData.
+ * @return ruleData
+ */
+ public RuleData getRuleData() {
+ return ruleData;
+ }
+
+ /**
+ * get metaData.
+ * @return metaData
+ */
+ public MetaData getMetaData() {
+ return metaData;
+ }
+}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConstants.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConstants.java
index e3383c171..2d48ee615 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConstants.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/IngressConstants.java
@@ -23,6 +23,8 @@ public class IngressConstants {
public static final String SHENYU_INGRESS_CLASS = "shenyu";
+ public static final String ID = "1";
+
// Load balance type name, refer to LoadBalanceEnum
public static final String LOADBALANCER_ANNOTATION_KEY =
"shenyu.apache.org/loadbalancer";
@@ -37,4 +39,31 @@ public class IngressConstants {
// The maximum length of the request header, in bytes
public static final String REQUEST_MAX_SIZE_ANNOTATION_KEY =
"shenyu.apache.org/request-max-size";
+
+ //Determine if the dubbo plugin is enabled, in bool
+ public static final String PLUGIN_DUBBO_ENABLED =
"shenyu.apache.org/plugin-dubbo-enabled";
+
+ // The configuration key to specify the Dubbo application name for the
plugin, in string
+ public static final String PLUGIN_DUBBO_APP_NAME =
"shenyu.apache.org/plugin-dubbo-app-name";
+
+ // The configuration key to specify the Dubbo method name for the plugin,
in string
+ public static final String PLUGIN_DUBBO_METHOD_NAME =
"shenyu.apache.org/plugin-dubbo-method-name";
+
+ // The configuration key to specify the Dubbo path for the plugin, in
string
+ public static final String PLUGIN_DUBBO_PATH =
"shenyu.apache.org/plugin-dubbo-PATH";
+
+ // The configuration key to specify the Dubbo RPC type for the plugin, in
string
+ public static final String PLUGIN_DUBBO_RPC_TYPE =
"shenyu.apache.org/plugin-dubbo-rpc-type";
+
+ // The configuration key to specify the Dubbo service name for the plugin,
in string
+ public static final String PLUGIN_DUBBO_SERVICE_NAME =
"shenyu.apache.org/plugin-dubbo-service-name";
+
+ // The configuration key to specify the context path for the Dubbo
service, in string
+ public static final String PLUGIN_DUBBO_CONTEXT_PATH =
"shenyu.apache.org/plugin-dubbo-context-path";
+
+ // The configuration key to specify additional RPC extension for the Dubbo
plugin, in string
+ public static final String PLUGIN_DUBBO_RPC_EXT =
"shenyu.apache.org/plugin-dubbo-rpc-ext";
+
+ // The configuration key to specify parameter types for the Dubbo plugin,
in string
+ public static final String PLUGIN_DUBBO_PARAMENT_TYPE =
"shenyu.apache.org/plugin-dubbo-parament-type";
}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/ShenyuMemoryConfig.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/ShenyuMemoryConfig.java
index 702000413..96011398d 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/ShenyuMemoryConfig.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/common/ShenyuMemoryConfig.java
@@ -19,8 +19,6 @@ package org.apache.shenyu.k8s.common;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shenyu.common.config.ssl.SslCrtAndKeyStream;
-import org.apache.shenyu.common.dto.RuleData;
-import org.apache.shenyu.common.dto.SelectorData;
import java.util.List;
@@ -29,9 +27,9 @@ import java.util.List;
*/
public class ShenyuMemoryConfig {
- private Pair<Pair<String, String>, Pair<SelectorData, RuleData>>
globalDefaultBackend;
+ private Pair<Pair<String, String>, IngressConfiguration>
globalDefaultBackend;
- private List<Pair<SelectorData, RuleData>> routeConfigList;
+ private List<IngressConfiguration> routeConfigList;
private List<SslCrtAndKeyStream> tlsConfigList;
@@ -46,7 +44,7 @@ public class ShenyuMemoryConfig {
*
* @return GlobalDefaultBackend
*/
- public Pair<Pair<String, String>, Pair<SelectorData, RuleData>>
getGlobalDefaultBackend() {
+ public Pair<Pair<String, String>, IngressConfiguration>
getGlobalDefaultBackend() {
return globalDefaultBackend;
}
@@ -55,7 +53,7 @@ public class ShenyuMemoryConfig {
*
* @param globalDefaultBackend GlobalDefaultBackend
*/
- public void setGlobalDefaultBackend(final Pair<Pair<String, String>,
Pair<SelectorData, RuleData>> globalDefaultBackend) {
+ public void setGlobalDefaultBackend(final Pair<Pair<String, String>,
IngressConfiguration> globalDefaultBackend) {
this.globalDefaultBackend = globalDefaultBackend;
}
@@ -64,7 +62,7 @@ public class ShenyuMemoryConfig {
*
* @return RouteConfigList
*/
- public List<Pair<SelectorData, RuleData>> getRouteConfigList() {
+ public List<IngressConfiguration> getRouteConfigList() {
return routeConfigList;
}
@@ -73,7 +71,7 @@ public class ShenyuMemoryConfig {
*
* @param routeConfigList RouteConfigList
*/
- public void setRouteConfigList(final List<Pair<SelectorData, RuleData>>
routeConfigList) {
+ public void setRouteConfigList(final List<IngressConfiguration>
routeConfigList) {
this.routeConfigList = routeConfigList;
}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DivideIngressParser.java
similarity index 84%
copy from
shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
copy to
shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DivideIngressParser.java
index 2483c7bc4..f065ae3b4 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DivideIngressParser.java
@@ -17,21 +17,21 @@
package org.apache.shenyu.k8s.parser;
-import io.kubernetes.client.informer.SharedIndexInformer;
import io.kubernetes.client.informer.cache.Lister;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.models.V1Endpoints;
-import io.kubernetes.client.openapi.models.V1EndpointSubset;
import io.kubernetes.client.openapi.models.V1EndpointAddress;
+import io.kubernetes.client.openapi.models.V1EndpointSubset;
+import io.kubernetes.client.openapi.models.V1Endpoints;
+import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1IngressBackend;
import io.kubernetes.client.openapi.models.V1IngressRule;
-import io.kubernetes.client.openapi.models.V1IngressTLS;
-import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
-import io.kubernetes.client.openapi.models.V1Service;
import io.kubernetes.client.openapi.models.V1IngressServiceBackend;
+import io.kubernetes.client.openapi.models.V1IngressTLS;
import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1Service;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shenyu.common.config.ssl.SslCrtAndKeyStream;
import org.apache.shenyu.common.dto.ConditionData;
@@ -39,13 +39,14 @@ import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
-import org.apache.shenyu.common.enums.MatchModeEnum;
import org.apache.shenyu.common.enums.LoadBalanceEnum;
+import org.apache.shenyu.common.enums.MatchModeEnum;
import org.apache.shenyu.common.enums.OperatorEnum;
import org.apache.shenyu.common.enums.ParamTypeEnum;
import org.apache.shenyu.common.enums.PluginEnum;
import org.apache.shenyu.common.enums.SelectorTypeEnum;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.k8s.common.IngressConfiguration;
import org.apache.shenyu.k8s.common.IngressConstants;
import org.apache.shenyu.k8s.common.ShenyuMemoryConfig;
import org.slf4j.Logger;
@@ -56,13 +57,13 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Map;
+import java.util.Objects;
/**
- * Parser of Ingress.
+ * Parser of Ingress Divide Annotations.
*/
-public class IngressParser implements K8sResourceParser<V1Ingress> {
+public class DivideIngressParser implements K8sResourceParser<V1Ingress> {
private static final Logger LOG =
LoggerFactory.getLogger(IngressParser.class);
@@ -73,12 +74,12 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
/**
* IngressParser Constructor.
*
- * @param serviceInformer serviceInformer
- * @param endpointsInformer endpointsInformer
+ * @param serviceLister serviceLister
+ * @param endpointsLister endpointsLister
*/
- public IngressParser(final SharedIndexInformer<V1Service> serviceInformer,
final SharedIndexInformer<V1Endpoints> endpointsInformer) {
- this.serviceLister = new Lister<>(serviceInformer.getIndexer());
- this.endpointsLister = new Lister<>(endpointsInformer.getIndexer());
+ public DivideIngressParser(final Lister<V1Service> serviceLister, final
Lister<V1Endpoints> endpointsLister) {
+ this.serviceLister = serviceLister;
+ this.endpointsLister = endpointsLister;
}
/**
@@ -92,7 +93,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
public ShenyuMemoryConfig parse(final V1Ingress ingress, final CoreV1Api
coreV1Api) {
ShenyuMemoryConfig res = new ShenyuMemoryConfig();
- if (ingress.getSpec() != null) {
+ if (Objects.nonNull(ingress.getSpec())) {
// Parse the default backend
V1IngressBackend defaultBackend =
ingress.getSpec().getDefaultBackend();
List<V1IngressRule> rules = ingress.getSpec().getRules();
@@ -101,18 +102,18 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
String namespace =
Objects.requireNonNull(ingress.getMetadata()).getNamespace();
List<DivideUpstream> defaultUpstreamList =
parseDefaultService(defaultBackend, namespace);
- if (rules == null || rules.isEmpty()) {
+ if (Objects.isNull(rules) || CollectionUtils.isEmpty(rules)) {
// if rules is null, defaultBackend become global default
- if (defaultBackend != null && defaultBackend.getService() !=
null) {
- Pair<SelectorData, RuleData> defaultRouteConfig =
getDefaultRouteConfig(defaultUpstreamList,
ingress.getMetadata().getAnnotations());
+ if (Objects.nonNull(defaultBackend) &&
Objects.nonNull(defaultBackend.getService())) {
+ IngressConfiguration defaultRouteConfig =
getDefaultRouteConfig(defaultUpstreamList,
ingress.getMetadata().getAnnotations());
res.setGlobalDefaultBackend(Pair.of(Pair.of(namespace +
"/" + ingress.getMetadata().getName(), defaultBackend.getService().getName()),
defaultRouteConfig));
}
} else {
// if rules is not null, defaultBackend is default in this
ingress
- List<Pair<SelectorData, RuleData>> routeList = new
ArrayList<>(rules.size());
+ List<IngressConfiguration> routeList = new
ArrayList<>(rules.size());
for (V1IngressRule ingressRule : rules) {
- List<Pair<SelectorData, RuleData>> routes =
parseIngressRule(ingressRule, defaultUpstreamList,
+ List<IngressConfiguration> routes =
parseIngressRule(ingressRule, defaultUpstreamList,
Objects.requireNonNull(ingress.getMetadata()).getNamespace(),
ingress.getMetadata().getAnnotations());
routeList.addAll(routes);
}
@@ -120,17 +121,17 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
}
// Parse tls
- if (tlsList != null && !tlsList.isEmpty()) {
+ if (Objects.nonNull(tlsList) &&
CollectionUtils.isNotEmpty(tlsList)) {
List<SslCrtAndKeyStream> sslList = new ArrayList<>();
for (V1IngressTLS tls : tlsList) {
- if (tls.getSecretName() != null && tls.getHosts() != null
&& !tls.getHosts().isEmpty()) {
+ if (tls.getSecretName() != null && tls.getHosts() != null
&& CollectionUtils.isNotEmpty(tls.getHosts())) {
try {
V1Secret secret =
coreV1Api.readNamespacedSecret(tls.getSecretName(), namespace, "ture");
- if (secret.getData() != null) {
+ if (Objects.nonNull(secret.getData())) {
InputStream keyCertChainInputStream = new
ByteArrayInputStream(secret.getData().get("tls.crt"));
InputStream keyInputStream = new
ByteArrayInputStream(secret.getData().get("tls.key"));
tls.getHosts().forEach(host ->
- sslList.add(new SslCrtAndKeyStream(host,
keyCertChainInputStream, keyInputStream))
+ sslList.add(new
SslCrtAndKeyStream(host, keyCertChainInputStream, keyInputStream))
);
}
} catch (ApiException e) {
@@ -146,23 +147,23 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
private List<DivideUpstream> parseDefaultService(final V1IngressBackend
defaultBackend, final String namespace) {
List<DivideUpstream> defaultUpstreamList = new ArrayList<>();
- if (defaultBackend != null && defaultBackend.getService() != null) {
+ if (Objects.nonNull(defaultBackend) &&
Objects.nonNull(defaultBackend.getService())) {
String serviceName = defaultBackend.getService().getName();
// shenyu routes directly to the container
V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
+ if (Objects.isNull(subsets) || CollectionUtils.isEmpty(subsets)) {
LOG.info("Endpoints {} do not have subsets", serviceName);
} else {
for (V1EndpointSubset subset : subsets) {
List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
+ if (Objects.isNull(addresses) ||
CollectionUtils.isEmpty(addresses)) {
continue;
}
for (V1EndpointAddress address : addresses) {
String upstreamIp = address.getIp();
String defaultPort =
parsePort(defaultBackend.getService());
- if (defaultPort != null) {
+ if (Objects.nonNull(defaultPort)) {
DivideUpstream upstream = new DivideUpstream();
upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
upstream.setWeight(100);
@@ -180,20 +181,20 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
return defaultUpstreamList;
}
- private List<Pair<SelectorData, RuleData>> parseIngressRule(final
V1IngressRule ingressRule,
+ private List<IngressConfiguration> parseIngressRule(final V1IngressRule
ingressRule,
final
List<DivideUpstream> defaultUpstream,
final String
namespace,
final
Map<String, String> annotations) {
- List<Pair<SelectorData, RuleData>> res = new ArrayList<>();
+ List<IngressConfiguration> res = new ArrayList<>();
ConditionData hostCondition = null;
- if (ingressRule.getHost() != null) {
+ if (Objects.nonNull(ingressRule.getHost())) {
hostCondition = new ConditionData();
hostCondition.setParamType(ParamTypeEnum.DOMAIN.getName());
hostCondition.setOperator(OperatorEnum.EQ.getAlias());
hostCondition.setParamValue(ingressRule.getHost());
}
- if (ingressRule.getHttp() != null) {
+ if (Objects.nonNull(ingressRule.getHttp())) {
List<V1HTTPIngressPath> paths = ingressRule.getHttp().getPaths();
if (paths != null) {
for (V1HTTPIngressPath path : paths) {
@@ -218,7 +219,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
pathCondition.setParamType(ParamTypeEnum.URI.getName());
pathCondition.setParamValue(path.getPath());
List<ConditionData> conditionList = new ArrayList<>(2);
- if (hostCondition != null) {
+ if (Objects.nonNull(hostCondition)) {
conditionList.add(hostCondition);
}
conditionList.add(pathCondition);
@@ -240,7 +241,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
selectorData.setHandle(GsonUtils.getInstance().toJson(upstreamList));
DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- if (annotations != null) {
+ if (Objects.nonNull(annotations)) {
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
@@ -256,7 +257,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
.loged(false)
.enabled(true).build();
- res.add(Pair.of(selectorData, ruleData));
+ res.add(new IngressConfiguration(selectorData, ruleData,
null));
}
}
}
@@ -264,7 +265,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
}
private String parsePort(final V1IngressServiceBackend service) {
- if (service.getPort() != null) {
+ if (Objects.nonNull(service.getPort())) {
if (service.getPort().getNumber() != null &&
service.getPort().getNumber() > 0) {
return String.valueOf(service.getPort().getNumber());
} else if (service.getPort().getName() != null &&
!"".equals(service.getPort().getName().trim())) {
@@ -276,23 +277,23 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
private List<DivideUpstream> parseUpstream(final V1IngressBackend backend,
final String namespace) {
List<DivideUpstream> upstreamList = new ArrayList<>();
- if (backend != null && backend.getService() != null &&
backend.getService().getName() != null) {
+ if (Objects.nonNull(backend) && Objects.nonNull(backend.getService())
&& Objects.nonNull(backend.getService().getName())) {
String serviceName = backend.getService().getName();
// shenyu routes directly to the container
V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
+ if (Objects.isNull(subsets) || CollectionUtils.isEmpty(subsets)) {
LOG.info("Endpoints {} do not have subsets", serviceName);
} else {
for (V1EndpointSubset subset : subsets) {
List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
+ if (Objects.isNull(addresses) || addresses.isEmpty()) {
continue;
}
for (V1EndpointAddress address : addresses) {
String upstreamIp = address.getIp();
String defaultPort = parsePort(backend.getService());
- if (defaultPort != null) {
+ if (Objects.nonNull(defaultPort)) {
DivideUpstream upstream = new DivideUpstream();
upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
upstream.setWeight(100);
@@ -310,7 +311,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
return upstreamList;
}
- private Pair<SelectorData, RuleData> getDefaultRouteConfig(final
List<DivideUpstream> divideUpstream, final Map<String, String> annotations) {
+ private IngressConfiguration getDefaultRouteConfig(final
List<DivideUpstream> divideUpstream, final Map<String, String> annotations) {
final ConditionData conditionData = new ConditionData();
conditionData.setParamName("default");
conditionData.setParamType(ParamTypeEnum.URI.getName());
@@ -323,7 +324,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
.conditionList(Collections.singletonList(conditionData))
.handle(GsonUtils.getInstance().toJson(divideUpstream))
.enabled(true)
- .id("1")
+ .id(IngressConstants.ID)
.pluginName(PluginEnum.DIVIDE.getName())
.pluginId(String.valueOf(PluginEnum.DIVIDE.getCode()))
.logged(false)
@@ -332,8 +333,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
.type(SelectorTypeEnum.FULL_FLOW.getCode()).build();
DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- // TODO need an annotation parsing common way
- if (annotations != null) {
+ if (Objects.nonNull(annotations)) {
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
@@ -341,7 +341,7 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
divideRuleHandle.setRequestMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.REQUEST_MAX_SIZE_ANNOTATION_KEY,
"102400")));
}
final RuleData ruleData = RuleData.builder()
- .selectorId("1")
+ .selectorId(IngressConstants.ID)
.pluginName(PluginEnum.DIVIDE.getName())
.name("default-rule")
.matchMode(MatchModeEnum.AND.getCode())
@@ -351,6 +351,6 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
.enabled(true)
.sort(Integer.MAX_VALUE).build();
- return Pair.of(selectorData, ruleData);
+ return new IngressConfiguration(selectorData, ruleData, null);
}
}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
similarity index 53%
copy from
shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
copy to
shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
index 2483c7bc4..303e6cc00 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/DubboIngressParser.java
@@ -17,35 +17,38 @@
package org.apache.shenyu.k8s.parser;
-import io.kubernetes.client.informer.SharedIndexInformer;
import io.kubernetes.client.informer.cache.Lister;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.kubernetes.client.openapi.models.V1Endpoints;
-import io.kubernetes.client.openapi.models.V1EndpointSubset;
import io.kubernetes.client.openapi.models.V1EndpointAddress;
+import io.kubernetes.client.openapi.models.V1EndpointSubset;
+import io.kubernetes.client.openapi.models.V1Endpoints;
+import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
import io.kubernetes.client.openapi.models.V1Ingress;
import io.kubernetes.client.openapi.models.V1IngressBackend;
import io.kubernetes.client.openapi.models.V1IngressRule;
-import io.kubernetes.client.openapi.models.V1IngressTLS;
-import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
-import io.kubernetes.client.openapi.models.V1Service;
import io.kubernetes.client.openapi.models.V1IngressServiceBackend;
+import io.kubernetes.client.openapi.models.V1IngressTLS;
import io.kubernetes.client.openapi.models.V1Secret;
+import io.kubernetes.client.openapi.models.V1Service;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shenyu.common.config.ssl.SslCrtAndKeyStream;
import org.apache.shenyu.common.dto.ConditionData;
+import org.apache.shenyu.common.dto.MetaData;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
-import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
-import org.apache.shenyu.common.enums.MatchModeEnum;
+import org.apache.shenyu.common.dto.convert.rule.impl.DubboRuleHandle;
+import org.apache.shenyu.common.dto.convert.selector.DubboUpstream;
import org.apache.shenyu.common.enums.LoadBalanceEnum;
+import org.apache.shenyu.common.enums.MatchModeEnum;
import org.apache.shenyu.common.enums.OperatorEnum;
import org.apache.shenyu.common.enums.ParamTypeEnum;
import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
import org.apache.shenyu.common.enums.SelectorTypeEnum;
import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.k8s.common.IngressConfiguration;
import org.apache.shenyu.k8s.common.IngressConstants;
import org.apache.shenyu.k8s.common.ShenyuMemoryConfig;
import org.slf4j.Logger;
@@ -56,35 +59,35 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import java.util.Map;
+import java.util.Objects;
/**
- * Parser of Ingress.
+ * Parser of Ingress Dubbo Annotations.
*/
-public class IngressParser implements K8sResourceParser<V1Ingress> {
+public class DubboIngressParser implements K8sResourceParser<V1Ingress> {
- private static final Logger LOG =
LoggerFactory.getLogger(IngressParser.class);
+ private static final Logger LOG =
LoggerFactory.getLogger(DubboIngressParser.class);
private final Lister<V1Service> serviceLister;
private final Lister<V1Endpoints> endpointsLister;
/**
- * IngressParser Constructor.
+ * DubboIngressParser Constructor.
*
- * @param serviceInformer serviceInformer
+ * @param serviceInformer serviceInformer
* @param endpointsInformer endpointsInformer
*/
- public IngressParser(final SharedIndexInformer<V1Service> serviceInformer,
final SharedIndexInformer<V1Endpoints> endpointsInformer) {
- this.serviceLister = new Lister<>(serviceInformer.getIndexer());
- this.endpointsLister = new Lister<>(endpointsInformer.getIndexer());
+ public DubboIngressParser(final Lister<V1Service> serviceInformer, final
Lister<V1Endpoints> endpointsInformer) {
+ this.serviceLister = serviceInformer;
+ this.endpointsLister = endpointsInformer;
}
/**
* Parse ingress to ShenyuMemoryConfig.
*
- * @param ingress ingress resource
+ * @param ingress ingress resource
* @param coreV1Api coreV1Api
* @return ShenyuMemoryConfig
*/
@@ -92,27 +95,27 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
public ShenyuMemoryConfig parse(final V1Ingress ingress, final CoreV1Api
coreV1Api) {
ShenyuMemoryConfig res = new ShenyuMemoryConfig();
- if (ingress.getSpec() != null) {
- // Parse the default backend
- V1IngressBackend defaultBackend =
ingress.getSpec().getDefaultBackend();
+ if (Objects.nonNull(ingress.getSpec())) {
+ // Parse the dubbo backend
+ V1IngressBackend dubboBackend =
ingress.getSpec().getDefaultBackend();
List<V1IngressRule> rules = ingress.getSpec().getRules();
List<V1IngressTLS> tlsList = ingress.getSpec().getTls();
String namespace =
Objects.requireNonNull(ingress.getMetadata()).getNamespace();
- List<DivideUpstream> defaultUpstreamList =
parseDefaultService(defaultBackend, namespace);
+ List<DubboUpstream> dubboUpstreamList =
getDefaultDubboRouteConfig(dubboBackend, namespace);
- if (rules == null || rules.isEmpty()) {
- // if rules is null, defaultBackend become global default
- if (defaultBackend != null && defaultBackend.getService() !=
null) {
- Pair<SelectorData, RuleData> defaultRouteConfig =
getDefaultRouteConfig(defaultUpstreamList,
ingress.getMetadata().getAnnotations());
- res.setGlobalDefaultBackend(Pair.of(Pair.of(namespace +
"/" + ingress.getMetadata().getName(), defaultBackend.getService().getName()),
+ if (Objects.isNull(rules) || CollectionUtils.isEmpty(rules)) {
+ // if rules is null, dubboBackend become global default
+ if (Objects.nonNull(dubboBackend) &&
Objects.nonNull(dubboBackend.getService())) {
+ IngressConfiguration defaultRouteConfig =
getDubboRouteConfig(dubboUpstreamList, ingress.getMetadata().getAnnotations());
+ res.setGlobalDefaultBackend(Pair.of(Pair.of(namespace +
"/" + ingress.getMetadata().getName(), dubboBackend.getService().getName()),
defaultRouteConfig));
}
} else {
- // if rules is not null, defaultBackend is default in this
ingress
- List<Pair<SelectorData, RuleData>> routeList = new
ArrayList<>(rules.size());
+ // if rules is not null, dubboBackend is default in this
ingress
+ List<IngressConfiguration> routeList = new
ArrayList<>(rules.size());
for (V1IngressRule ingressRule : rules) {
- List<Pair<SelectorData, RuleData>> routes =
parseIngressRule(ingressRule, defaultUpstreamList,
+ List<IngressConfiguration> routes =
parseIngressRule(ingressRule, dubboUpstreamList,
Objects.requireNonNull(ingress.getMetadata()).getNamespace(),
ingress.getMetadata().getAnnotations());
routeList.addAll(routes);
}
@@ -120,17 +123,17 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
}
// Parse tls
- if (tlsList != null && !tlsList.isEmpty()) {
+ if (Objects.nonNull(tlsList) &&
CollectionUtils.isNotEmpty(tlsList)) {
List<SslCrtAndKeyStream> sslList = new ArrayList<>();
for (V1IngressTLS tls : tlsList) {
- if (tls.getSecretName() != null && tls.getHosts() != null
&& !tls.getHosts().isEmpty()) {
+ if (Objects.nonNull(tls.getSecretName()) &&
Objects.nonNull(tls.getHosts()) && CollectionUtils.isNotEmpty(tls.getHosts())) {
try {
V1Secret secret =
coreV1Api.readNamespacedSecret(tls.getSecretName(), namespace, "ture");
if (secret.getData() != null) {
InputStream keyCertChainInputStream = new
ByteArrayInputStream(secret.getData().get("tls.crt"));
InputStream keyInputStream = new
ByteArrayInputStream(secret.getData().get("tls.key"));
tls.getHosts().forEach(host ->
- sslList.add(new SslCrtAndKeyStream(host,
keyCertChainInputStream, keyInputStream))
+ sslList.add(new
SslCrtAndKeyStream(host, keyCertChainInputStream, keyInputStream))
);
}
} catch (ApiException e) {
@@ -144,56 +147,67 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
return res;
}
- private List<DivideUpstream> parseDefaultService(final V1IngressBackend
defaultBackend, final String namespace) {
- List<DivideUpstream> defaultUpstreamList = new ArrayList<>();
- if (defaultBackend != null && defaultBackend.getService() != null) {
+ private List<DubboUpstream> getDefaultDubboRouteConfig(final
V1IngressBackend defaultBackend, final String namespace) {
+ List<DubboUpstream> dubboUpstreamList = new ArrayList<>();
+ if (Objects.nonNull(defaultBackend) &&
Objects.nonNull(defaultBackend.getService())) {
String serviceName = defaultBackend.getService().getName();
// shenyu routes directly to the container
V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
+ if (Objects.isNull(subsets) || CollectionUtils.isEmpty(subsets)) {
LOG.info("Endpoints {} do not have subsets", serviceName);
} else {
for (V1EndpointSubset subset : subsets) {
List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
+ if (Objects.isNull(addresses) ||
CollectionUtils.isEmpty(addresses)) {
continue;
}
for (V1EndpointAddress address : addresses) {
String upstreamIp = address.getIp();
String defaultPort =
parsePort(defaultBackend.getService());
- if (defaultPort != null) {
- DivideUpstream upstream = new DivideUpstream();
- upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
- upstream.setWeight(100);
- // TODO support config protocol in annotation
- upstream.setProtocol("http://");
- upstream.setWarmup(0);
- upstream.setStatus(true);
- upstream.setUpstreamHost("");
- defaultUpstreamList.add(upstream);
+ if (Objects.nonNull(defaultPort)) {
+ DubboUpstream upstream = DubboUpstream.builder()
+ .upstreamUrl(upstreamIp + ":" +
defaultPort)
+ .weight(100)
+ .protocol("http://")
+ .warmup(0)
+ .status(true)
+ .upstreamHost("")
+ .build();
+ dubboUpstreamList.add(upstream);
}
}
}
}
}
- return defaultUpstreamList;
+ return dubboUpstreamList;
}
- private List<Pair<SelectorData, RuleData>> parseIngressRule(final
V1IngressRule ingressRule,
- final
List<DivideUpstream> defaultUpstream,
- final String
namespace,
- final
Map<String, String> annotations) {
- List<Pair<SelectorData, RuleData>> res = new ArrayList<>();
+ private String parsePort(final V1IngressServiceBackend service) {
+ if (Objects.nonNull(service.getPort())) {
+ if (service.getPort().getNumber() != null &&
service.getPort().getNumber() > 0) {
+ return String.valueOf(service.getPort().getNumber());
+ } else if (service.getPort().getName() != null &&
!"".equals(service.getPort().getName().trim())) {
+ return service.getPort().getName().trim();
+ }
+ }
+ return null;
+ }
+
+ private List<IngressConfiguration> parseIngressRule(final V1IngressRule
ingressRule,
+
final List<DubboUpstream> dubboUpstreamList,
+
final String namespace,
+
final Map<String, String> annotations) {
+ List<IngressConfiguration> res = new ArrayList<>();
ConditionData hostCondition = null;
- if (ingressRule.getHost() != null) {
+ if (Objects.nonNull(ingressRule.getHost())) {
hostCondition = new ConditionData();
hostCondition.setParamType(ParamTypeEnum.DOMAIN.getName());
hostCondition.setOperator(OperatorEnum.EQ.getAlias());
hostCondition.setParamValue(ingressRule.getHost());
}
- if (ingressRule.getHttp() != null) {
+ if (Objects.nonNull(ingressRule.getHttp())) {
List<V1HTTPIngressPath> paths = ingressRule.getHttp().getPaths();
if (paths != null) {
for (V1HTTPIngressPath path : paths) {
@@ -218,14 +232,14 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
pathCondition.setParamType(ParamTypeEnum.URI.getName());
pathCondition.setParamValue(path.getPath());
List<ConditionData> conditionList = new ArrayList<>(2);
- if (hostCondition != null) {
+ if (Objects.nonNull(hostCondition)) {
conditionList.add(hostCondition);
}
conditionList.add(pathCondition);
SelectorData selectorData = SelectorData.builder()
-
.pluginId(String.valueOf(PluginEnum.DIVIDE.getCode()))
- .pluginName(PluginEnum.DIVIDE.getName())
+
.pluginId(String.valueOf(PluginEnum.DUBBO.getCode()))
+ .pluginName(PluginEnum.DUBBO.getName())
.name(path.getPath())
.matchMode(MatchModeEnum.AND.getCode())
.type(SelectorTypeEnum.CUSTOM_FLOW.getCode())
@@ -233,76 +247,57 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
.logged(false)
.continued(true)
.conditionList(conditionList).build();
- List<DivideUpstream> upstreamList =
parseUpstream(path.getBackend(), namespace);
+ List<DubboUpstream> upstreamList =
parseUpstream(path.getBackend(), namespace);
if (upstreamList.isEmpty()) {
- upstreamList = defaultUpstream;
+ upstreamList = dubboUpstreamList;
}
selectorData.setHandle(GsonUtils.getInstance().toJson(upstreamList));
- DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- if (annotations != null) {
-
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
-
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
-
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
-
divideRuleHandle.setHeaderMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.HEADER_MAX_SIZE_ANNOTATION_KEY,
"10240")));
-
divideRuleHandle.setRequestMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.REQUEST_MAX_SIZE_ANNOTATION_KEY,
"102400")));
+ DubboRuleHandle dubboRuleHandle = new DubboRuleHandle();
+ if (Objects.nonNull(annotations)) {
+
dubboRuleHandle.setLoadbalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
}
RuleData ruleData = RuleData.builder()
.name(path.getPath())
- .pluginName(PluginEnum.DIVIDE.getName())
+ .pluginName(PluginEnum.DUBBO.getName())
.matchMode(MatchModeEnum.AND.getCode())
.conditionDataList(conditionList)
-
.handle(GsonUtils.getInstance().toJson(divideRuleHandle))
+
.handle(GsonUtils.getInstance().toJson(dubboRuleHandle))
.loged(false)
.enabled(true).build();
- res.add(Pair.of(selectorData, ruleData));
+ List<MetaData> metaDataList = parseMetaData(paths,
namespace);
+ for (MetaData metaData : metaDataList) {
+ res.add(new IngressConfiguration(selectorData,
ruleData, metaData));
+ }
}
}
}
return res;
}
- private String parsePort(final V1IngressServiceBackend service) {
- if (service.getPort() != null) {
- if (service.getPort().getNumber() != null &&
service.getPort().getNumber() > 0) {
- return String.valueOf(service.getPort().getNumber());
- } else if (service.getPort().getName() != null &&
!"".equals(service.getPort().getName().trim())) {
- return service.getPort().getName().trim();
- }
- }
- return null;
- }
-
- private List<DivideUpstream> parseUpstream(final V1IngressBackend backend,
final String namespace) {
- List<DivideUpstream> upstreamList = new ArrayList<>();
- if (backend != null && backend.getService() != null &&
backend.getService().getName() != null) {
+ private List<DubboUpstream> parseUpstream(final V1IngressBackend backend,
final String namespace) {
+ List<DubboUpstream> upstreamList = new ArrayList<>();
+ if (Objects.nonNull(backend) && Objects.nonNull(backend.getService())
&& Objects.nonNull(backend.getService().getName())) {
String serviceName = backend.getService().getName();
// shenyu routes directly to the container
- V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
- List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
- LOG.info("Endpoints {} do not have subsets", serviceName);
+ V1Service v1Service =
serviceLister.namespace(namespace).get(serviceName);
+ List<String> clusterIPs = v1Service.getSpec().getClusterIPs();
+ if (Objects.isNull(clusterIPs) ||
CollectionUtils.isEmpty(clusterIPs)) {
+ LOG.info("Endpoints {} do not have clusterIPs", serviceName);
} else {
- for (V1EndpointSubset subset : subsets) {
- List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
- continue;
- }
- for (V1EndpointAddress address : addresses) {
- String upstreamIp = address.getIp();
- String defaultPort = parsePort(backend.getService());
- if (defaultPort != null) {
- DivideUpstream upstream = new DivideUpstream();
- upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
- upstream.setWeight(100);
- // TODO support config protocol in annotation
- upstream.setProtocol("http://");
- upstream.setWarmup(0);
- upstream.setStatus(true);
- upstream.setUpstreamHost("");
- upstreamList.add(upstream);
- }
+ for (String clusterIP : clusterIPs) {
+ String defaultPort = parsePort(backend.getService());
+ if (Objects.nonNull(defaultPort)) {
+ DubboUpstream upstream = DubboUpstream.builder()
+ .upstreamUrl(clusterIP + ":" + defaultPort)
+ .weight(100)
+ .protocol("http://")
+ .warmup(0)
+ .status(true)
+ .upstreamHost("")
+ .build();
+ upstreamList.add(upstream);
}
}
}
@@ -310,47 +305,71 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
return upstreamList;
}
- private Pair<SelectorData, RuleData> getDefaultRouteConfig(final
List<DivideUpstream> divideUpstream, final Map<String, String> annotations) {
+ private List<MetaData> parseMetaData(final List<V1HTTPIngressPath> paths,
final String namespace) {
+ List<MetaData> metaData = new ArrayList<>();
+ for (V1HTTPIngressPath path : paths) {
+ if (path.getPath() == null) {
+ continue;
+ }
+ String serviceName = path.getBackend().getService().getName();
+ V1Service v1Service =
serviceLister.namespace(namespace).get(serviceName);
+ Map<String, String> annotations =
v1Service.getMetadata().getAnnotations();
+ metaData.add(MetaData.builder()
+
.appName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_APP_NAME,
"dubbo"))
+
.path(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_PATH,
"/dubbo/findById"))
+
.rpcType(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_RPC_TYPE,
RpcTypeEnum.DUBBO.getName()))
+
.serviceName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_SERVICE_NAME,
"org.apache.shenyu.examples.apache.dubbo.service.impl.DubboTestServiceImpl"))
+
.methodName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_METHOD_NAME,
"findById"))
+ .enabled(true)
+ .build());
+ }
+ return metaData;
+ }
+
+ private IngressConfiguration getDubboRouteConfig(final List<DubboUpstream>
dubboUpstreamList, final Map<String, String> annotations) {
final ConditionData conditionData = new ConditionData();
- conditionData.setParamName("default");
+ conditionData.setParamName("dubbo");
conditionData.setParamType(ParamTypeEnum.URI.getName());
conditionData.setOperator(OperatorEnum.PATH_PATTERN.getAlias());
conditionData.setParamValue("/**");
final SelectorData selectorData = SelectorData.builder()
- .name("default-selector")
+ .name("dubbo-selector")
.sort(Integer.MAX_VALUE)
.conditionList(Collections.singletonList(conditionData))
- .handle(GsonUtils.getInstance().toJson(divideUpstream))
+ .handle(GsonUtils.getInstance().toJson(dubboUpstreamList))
.enabled(true)
- .id("1")
- .pluginName(PluginEnum.DIVIDE.getName())
- .pluginId(String.valueOf(PluginEnum.DIVIDE.getCode()))
+ .id(IngressConstants.ID)
+ .pluginName(PluginEnum.DUBBO.getName())
+ .pluginId(String.valueOf(PluginEnum.DUBBO.getCode()))
.logged(false)
.continued(true)
.matchMode(MatchModeEnum.AND.getCode())
.type(SelectorTypeEnum.FULL_FLOW.getCode()).build();
- DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- // TODO need an annotation parsing common way
- if (annotations != null) {
-
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
-
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
-
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
-
divideRuleHandle.setHeaderMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.HEADER_MAX_SIZE_ANNOTATION_KEY,
"10240")));
-
divideRuleHandle.setRequestMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.REQUEST_MAX_SIZE_ANNOTATION_KEY,
"102400")));
- }
final RuleData ruleData = RuleData.builder()
- .selectorId("1")
- .pluginName(PluginEnum.DIVIDE.getName())
- .name("default-rule")
+ .selectorId(IngressConstants.ID)
+ .pluginName(PluginEnum.DUBBO.getName())
+ .name("dubbo-rule")
.matchMode(MatchModeEnum.AND.getCode())
.conditionDataList(Collections.singletonList(conditionData))
- .handle(GsonUtils.getInstance().toJson(divideRuleHandle))
.loged(false)
.enabled(true)
.sort(Integer.MAX_VALUE).build();
- return Pair.of(selectorData, ruleData);
+ MetaData metaData = new MetaData();
+ if (Objects.nonNull(annotations)) {
+
metaData.setAppName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_APP_NAME,
"dubbo"));
+
metaData.setMethodName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_METHOD_NAME,
"methodName"));
+
metaData.setPath(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_PATH,
"/dubbo/findAll"));
+
metaData.setRpcType(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_RPC_TYPE,
RpcTypeEnum.DUBBO.getName()));
+
metaData.setServiceName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_SERVICE_NAME,
"dubboService"));
+
metaData.setContextPath(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_CONTEXT_PATH,
"contextPath"));
+
metaData.setRpcExt(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_RPC_EXT,
"rpcExt"));
+
metaData.setServiceName(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_SERVICE_NAME,
"serviceName"));
+
metaData.setParameterTypes(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_PARAMENT_TYPE,
""));
+
metaData.setEnabled(Boolean.parseBoolean(annotations.getOrDefault(IngressConstants.PLUGIN_DUBBO_ENABLED,
"true")));
+ }
+ return new IngressConfiguration(selectorData, ruleData, metaData);
}
}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
index 2483c7bc4..8b523d210 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/parser/IngressParser.java
@@ -19,45 +19,16 @@ package org.apache.shenyu.k8s.parser;
import io.kubernetes.client.informer.SharedIndexInformer;
import io.kubernetes.client.informer.cache.Lister;
-import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Endpoints;
-import io.kubernetes.client.openapi.models.V1EndpointSubset;
-import io.kubernetes.client.openapi.models.V1EndpointAddress;
import io.kubernetes.client.openapi.models.V1Ingress;
-import io.kubernetes.client.openapi.models.V1IngressBackend;
-import io.kubernetes.client.openapi.models.V1IngressRule;
-import io.kubernetes.client.openapi.models.V1IngressTLS;
-import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
import io.kubernetes.client.openapi.models.V1Service;
-import io.kubernetes.client.openapi.models.V1IngressServiceBackend;
-import io.kubernetes.client.openapi.models.V1Secret;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.shenyu.common.config.ssl.SslCrtAndKeyStream;
-import org.apache.shenyu.common.dto.ConditionData;
-import org.apache.shenyu.common.dto.RuleData;
-import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
-import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
-import org.apache.shenyu.common.enums.MatchModeEnum;
-import org.apache.shenyu.common.enums.LoadBalanceEnum;
-import org.apache.shenyu.common.enums.OperatorEnum;
-import org.apache.shenyu.common.enums.ParamTypeEnum;
-import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.enums.SelectorTypeEnum;
-import org.apache.shenyu.common.utils.GsonUtils;
import org.apache.shenyu.k8s.common.IngressConstants;
import org.apache.shenyu.k8s.common.ShenyuMemoryConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.Objects;
-import java.util.Map;
/**
* Parser of Ingress.
@@ -90,267 +61,12 @@ public class IngressParser implements
K8sResourceParser<V1Ingress> {
*/
@Override
public ShenyuMemoryConfig parse(final V1Ingress ingress, final CoreV1Api
coreV1Api) {
- ShenyuMemoryConfig res = new ShenyuMemoryConfig();
-
- if (ingress.getSpec() != null) {
- // Parse the default backend
- V1IngressBackend defaultBackend =
ingress.getSpec().getDefaultBackend();
- List<V1IngressRule> rules = ingress.getSpec().getRules();
- List<V1IngressTLS> tlsList = ingress.getSpec().getTls();
-
- String namespace =
Objects.requireNonNull(ingress.getMetadata()).getNamespace();
- List<DivideUpstream> defaultUpstreamList =
parseDefaultService(defaultBackend, namespace);
-
- if (rules == null || rules.isEmpty()) {
- // if rules is null, defaultBackend become global default
- if (defaultBackend != null && defaultBackend.getService() !=
null) {
- Pair<SelectorData, RuleData> defaultRouteConfig =
getDefaultRouteConfig(defaultUpstreamList,
ingress.getMetadata().getAnnotations());
- res.setGlobalDefaultBackend(Pair.of(Pair.of(namespace +
"/" + ingress.getMetadata().getName(), defaultBackend.getService().getName()),
- defaultRouteConfig));
- }
- } else {
- // if rules is not null, defaultBackend is default in this
ingress
- List<Pair<SelectorData, RuleData>> routeList = new
ArrayList<>(rules.size());
- for (V1IngressRule ingressRule : rules) {
- List<Pair<SelectorData, RuleData>> routes =
parseIngressRule(ingressRule, defaultUpstreamList,
-
Objects.requireNonNull(ingress.getMetadata()).getNamespace(),
ingress.getMetadata().getAnnotations());
- routeList.addAll(routes);
- }
- res.setRouteConfigList(routeList);
- }
-
- // Parse tls
- if (tlsList != null && !tlsList.isEmpty()) {
- List<SslCrtAndKeyStream> sslList = new ArrayList<>();
- for (V1IngressTLS tls : tlsList) {
- if (tls.getSecretName() != null && tls.getHosts() != null
&& !tls.getHosts().isEmpty()) {
- try {
- V1Secret secret =
coreV1Api.readNamespacedSecret(tls.getSecretName(), namespace, "ture");
- if (secret.getData() != null) {
- InputStream keyCertChainInputStream = new
ByteArrayInputStream(secret.getData().get("tls.crt"));
- InputStream keyInputStream = new
ByteArrayInputStream(secret.getData().get("tls.key"));
- tls.getHosts().forEach(host ->
- sslList.add(new SslCrtAndKeyStream(host,
keyCertChainInputStream, keyInputStream))
- );
- }
- } catch (ApiException e) {
- LOG.error("parse tls failed ", e);
- }
- }
- }
- res.setTlsConfigList(sslList);
- }
+ if
(Objects.equals(ingress.getMetadata().getAnnotations().get(IngressConstants.PLUGIN_DUBBO_ENABLED),
"true")) {
+ DubboIngressParser dubboIngressParser = new
DubboIngressParser(serviceLister, endpointsLister);
+ return dubboIngressParser.parse(ingress, coreV1Api);
+ } else {
+ DivideIngressParser divideIngressParser = new
DivideIngressParser(serviceLister, endpointsLister);
+ return divideIngressParser.parse(ingress, coreV1Api);
}
- return res;
- }
-
- private List<DivideUpstream> parseDefaultService(final V1IngressBackend
defaultBackend, final String namespace) {
- List<DivideUpstream> defaultUpstreamList = new ArrayList<>();
- if (defaultBackend != null && defaultBackend.getService() != null) {
- String serviceName = defaultBackend.getService().getName();
- // shenyu routes directly to the container
- V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
- List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
- LOG.info("Endpoints {} do not have subsets", serviceName);
- } else {
- for (V1EndpointSubset subset : subsets) {
- List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
- continue;
- }
- for (V1EndpointAddress address : addresses) {
- String upstreamIp = address.getIp();
- String defaultPort =
parsePort(defaultBackend.getService());
- if (defaultPort != null) {
- DivideUpstream upstream = new DivideUpstream();
- upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
- upstream.setWeight(100);
- // TODO support config protocol in annotation
- upstream.setProtocol("http://");
- upstream.setWarmup(0);
- upstream.setStatus(true);
- upstream.setUpstreamHost("");
- defaultUpstreamList.add(upstream);
- }
- }
- }
- }
- }
- return defaultUpstreamList;
- }
-
- private List<Pair<SelectorData, RuleData>> parseIngressRule(final
V1IngressRule ingressRule,
- final
List<DivideUpstream> defaultUpstream,
- final String
namespace,
- final
Map<String, String> annotations) {
- List<Pair<SelectorData, RuleData>> res = new ArrayList<>();
-
- ConditionData hostCondition = null;
- if (ingressRule.getHost() != null) {
- hostCondition = new ConditionData();
- hostCondition.setParamType(ParamTypeEnum.DOMAIN.getName());
- hostCondition.setOperator(OperatorEnum.EQ.getAlias());
- hostCondition.setParamValue(ingressRule.getHost());
- }
- if (ingressRule.getHttp() != null) {
- List<V1HTTPIngressPath> paths = ingressRule.getHttp().getPaths();
- if (paths != null) {
- for (V1HTTPIngressPath path : paths) {
- if (path.getPath() == null) {
- continue;
- }
-
- OperatorEnum operator;
- if ("ImplementationSpecific".equals(path.getPathType())) {
- operator = OperatorEnum.MATCH;
- } else if ("Prefix".equals(path.getPathType())) {
- operator = OperatorEnum.STARTS_WITH;
- } else if ("Exact".equals(path.getPathType())) {
- operator = OperatorEnum.EQ;
- } else {
- LOG.info("Invalid path type, set it with match
operator");
- operator = OperatorEnum.MATCH;
- }
-
- ConditionData pathCondition = new ConditionData();
- pathCondition.setOperator(operator.getAlias());
- pathCondition.setParamType(ParamTypeEnum.URI.getName());
- pathCondition.setParamValue(path.getPath());
- List<ConditionData> conditionList = new ArrayList<>(2);
- if (hostCondition != null) {
- conditionList.add(hostCondition);
- }
- conditionList.add(pathCondition);
-
- SelectorData selectorData = SelectorData.builder()
-
.pluginId(String.valueOf(PluginEnum.DIVIDE.getCode()))
- .pluginName(PluginEnum.DIVIDE.getName())
- .name(path.getPath())
- .matchMode(MatchModeEnum.AND.getCode())
- .type(SelectorTypeEnum.CUSTOM_FLOW.getCode())
- .enabled(true)
- .logged(false)
- .continued(true)
- .conditionList(conditionList).build();
- List<DivideUpstream> upstreamList =
parseUpstream(path.getBackend(), namespace);
- if (upstreamList.isEmpty()) {
- upstreamList = defaultUpstream;
- }
-
selectorData.setHandle(GsonUtils.getInstance().toJson(upstreamList));
-
- DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- if (annotations != null) {
-
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
-
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
-
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
-
divideRuleHandle.setHeaderMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.HEADER_MAX_SIZE_ANNOTATION_KEY,
"10240")));
-
divideRuleHandle.setRequestMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.REQUEST_MAX_SIZE_ANNOTATION_KEY,
"102400")));
- }
- RuleData ruleData = RuleData.builder()
- .name(path.getPath())
- .pluginName(PluginEnum.DIVIDE.getName())
- .matchMode(MatchModeEnum.AND.getCode())
- .conditionDataList(conditionList)
-
.handle(GsonUtils.getInstance().toJson(divideRuleHandle))
- .loged(false)
- .enabled(true).build();
-
- res.add(Pair.of(selectorData, ruleData));
- }
- }
- }
- return res;
- }
-
- private String parsePort(final V1IngressServiceBackend service) {
- if (service.getPort() != null) {
- if (service.getPort().getNumber() != null &&
service.getPort().getNumber() > 0) {
- return String.valueOf(service.getPort().getNumber());
- } else if (service.getPort().getName() != null &&
!"".equals(service.getPort().getName().trim())) {
- return service.getPort().getName().trim();
- }
- }
- return null;
- }
-
- private List<DivideUpstream> parseUpstream(final V1IngressBackend backend,
final String namespace) {
- List<DivideUpstream> upstreamList = new ArrayList<>();
- if (backend != null && backend.getService() != null &&
backend.getService().getName() != null) {
- String serviceName = backend.getService().getName();
- // shenyu routes directly to the container
- V1Endpoints v1Endpoints =
endpointsLister.namespace(namespace).get(serviceName);
- List<V1EndpointSubset> subsets = v1Endpoints.getSubsets();
- if (subsets == null || subsets.isEmpty()) {
- LOG.info("Endpoints {} do not have subsets", serviceName);
- } else {
- for (V1EndpointSubset subset : subsets) {
- List<V1EndpointAddress> addresses = subset.getAddresses();
- if (addresses == null || addresses.isEmpty()) {
- continue;
- }
- for (V1EndpointAddress address : addresses) {
- String upstreamIp = address.getIp();
- String defaultPort = parsePort(backend.getService());
- if (defaultPort != null) {
- DivideUpstream upstream = new DivideUpstream();
- upstream.setUpstreamUrl(upstreamIp + ":" +
defaultPort);
- upstream.setWeight(100);
- // TODO support config protocol in annotation
- upstream.setProtocol("http://");
- upstream.setWarmup(0);
- upstream.setStatus(true);
- upstream.setUpstreamHost("");
- upstreamList.add(upstream);
- }
- }
- }
- }
- }
- return upstreamList;
- }
-
- private Pair<SelectorData, RuleData> getDefaultRouteConfig(final
List<DivideUpstream> divideUpstream, final Map<String, String> annotations) {
- final ConditionData conditionData = new ConditionData();
- conditionData.setParamName("default");
- conditionData.setParamType(ParamTypeEnum.URI.getName());
- conditionData.setOperator(OperatorEnum.PATH_PATTERN.getAlias());
- conditionData.setParamValue("/**");
-
- final SelectorData selectorData = SelectorData.builder()
- .name("default-selector")
- .sort(Integer.MAX_VALUE)
- .conditionList(Collections.singletonList(conditionData))
- .handle(GsonUtils.getInstance().toJson(divideUpstream))
- .enabled(true)
- .id("1")
- .pluginName(PluginEnum.DIVIDE.getName())
- .pluginId(String.valueOf(PluginEnum.DIVIDE.getCode()))
- .logged(false)
- .continued(true)
- .matchMode(MatchModeEnum.AND.getCode())
- .type(SelectorTypeEnum.FULL_FLOW.getCode()).build();
-
- DivideRuleHandle divideRuleHandle = new DivideRuleHandle();
- // TODO need an annotation parsing common way
- if (annotations != null) {
-
divideRuleHandle.setLoadBalance(annotations.getOrDefault(IngressConstants.LOADBALANCER_ANNOTATION_KEY,
LoadBalanceEnum.RANDOM.getName()));
-
divideRuleHandle.setRetry(Integer.parseInt(annotations.getOrDefault(IngressConstants.RETRY_ANNOTATION_KEY,
"3")));
-
divideRuleHandle.setTimeout(Long.parseLong(annotations.getOrDefault(IngressConstants.TIMEOUT_ANNOTATION_KEY,
"3000")));
-
divideRuleHandle.setHeaderMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.HEADER_MAX_SIZE_ANNOTATION_KEY,
"10240")));
-
divideRuleHandle.setRequestMaxSize(Long.parseLong(annotations.getOrDefault(IngressConstants.REQUEST_MAX_SIZE_ANNOTATION_KEY,
"102400")));
- }
- final RuleData ruleData = RuleData.builder()
- .selectorId("1")
- .pluginName(PluginEnum.DIVIDE.getName())
- .name("default-rule")
- .matchMode(MatchModeEnum.AND.getCode())
- .conditionDataList(Collections.singletonList(conditionData))
- .handle(GsonUtils.getInstance().toJson(divideRuleHandle))
- .loged(false)
- .enabled(true)
- .sort(Integer.MAX_VALUE).build();
-
- return Pair.of(selectorData, ruleData);
}
}
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/reconciler/IngressReconciler.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/reconciler/IngressReconciler.java
index 792275d98..8ee10acec 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/reconciler/IngressReconciler.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/reconciler/IngressReconciler.java
@@ -26,12 +26,13 @@ import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1HTTPIngressPath;
import io.kubernetes.client.openapi.models.V1Ingress;
+import io.kubernetes.client.openapi.models.V1IngressBuilder;
import io.kubernetes.client.openapi.models.V1IngressRule;
import io.kubernetes.client.openapi.models.V1Secret;
-import io.kubernetes.client.openapi.models.V1IngressBuilder;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shenyu.common.config.ssl.ShenyuSniAsyncMapping;
import org.apache.shenyu.common.config.ssl.SslCrtAndKeyStream;
+import org.apache.shenyu.common.dto.MetaData;
import org.apache.shenyu.common.dto.PluginData;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
@@ -41,6 +42,7 @@ import org.apache.shenyu.k8s.cache.IngressCache;
import org.apache.shenyu.k8s.cache.IngressSecretCache;
import org.apache.shenyu.k8s.cache.IngressSelectorCache;
import org.apache.shenyu.k8s.cache.ServiceIngressCache;
+import org.apache.shenyu.k8s.common.IngressConfiguration;
import org.apache.shenyu.k8s.common.IngressConstants;
import org.apache.shenyu.k8s.common.ShenyuMemoryConfig;
import org.apache.shenyu.k8s.parser.IngressParser;
@@ -49,13 +51,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
-import java.util.ArrayList;
-import java.util.HashSet;
import java.util.Optional;
+import java.util.Set;
/**
* The Reconciler of Ingress.
@@ -65,7 +67,7 @@ public class IngressReconciler implements Reconciler {
private static final Logger LOG =
LoggerFactory.getLogger(IngressReconciler.class);
// ingressName serviceName selectorData ruleData
- private static Pair<Pair<String, String>, Pair<SelectorData, RuleData>>
globalDefaultBackend;
+ private static Pair<Pair<String, String>, IngressConfiguration>
globalDefaultBackend;
private final Lister<V1Ingress> ingressLister;
@@ -90,11 +92,11 @@ public class IngressReconciler implements Reconciler {
* @param apiClient apiClient
*/
public IngressReconciler(final SharedIndexInformer<V1Ingress>
ingressInformer,
- final SharedIndexInformer<V1Secret> secretInformer,
- final ShenyuCacheRepository shenyuCacheRepository,
- final ShenyuSniAsyncMapping shenyuSniAsyncMapping,
- final IngressParser ingressParser,
- final ApiClient apiClient) {
+ final SharedIndexInformer<V1Secret>
secretInformer,
+ final ShenyuCacheRepository shenyuCacheRepository,
+ final ShenyuSniAsyncMapping shenyuSniAsyncMapping,
+ final IngressParser ingressParser,
+ final ApiClient apiClient) {
this.ingressLister = new Lister<>(ingressInformer.getIndexer());
this.secretLister = new Lister<>(secretInformer.getIndexer());
this.shenyuCacheRepository = shenyuCacheRepository;
@@ -177,9 +179,19 @@ public class IngressReconciler implements Reconciler {
}
private void doDeleteConfigByIngress(final Request request, final
V1Ingress oldIngress) {
- List<String> selectorList =
deleteSelectorByIngressName(request.getNamespace(), request.getName(),
PluginEnum.DIVIDE.getName());
+ List<String> selectorList = new ArrayList<>();
+ if
(Objects.equals(oldIngress.getMetadata().getAnnotations().get(IngressConstants.PLUGIN_DUBBO_ENABLED),
"true")) {
+ selectorList = deleteSelectorByIngressName(request.getNamespace(),
request.getName(), PluginEnum.DUBBO.getName(),
+
oldIngress.getMetadata().getAnnotations().get(IngressConstants.PLUGIN_DUBBO_CONTEXT_PATH));
+ } else {
+ selectorList = deleteSelectorByIngressName(request.getNamespace(),
request.getName(), PluginEnum.DIVIDE.getName(), "");
+ }
if (Objects.nonNull(selectorList) && !selectorList.isEmpty()) {
- IngressSelectorCache.getInstance().remove(request.getNamespace(),
request.getName(), PluginEnum.DIVIDE.getName());
+ if
(Objects.equals(oldIngress.getMetadata().getAnnotations().get(IngressConstants.PLUGIN_DUBBO_ENABLED),
"true")) {
+
IngressSelectorCache.getInstance().remove(request.getNamespace(),
request.getName(), PluginEnum.DUBBO.getName());
+ } else {
+
IngressSelectorCache.getInstance().remove(request.getNamespace(),
request.getName(), PluginEnum.DIVIDE.getName());
+ }
}
List<Pair<String, String>> serviceList =
parseServiceFromIngress(oldIngress);
Objects.requireNonNull(serviceList).forEach(pair -> {
@@ -198,54 +210,64 @@ public class IngressReconciler implements Reconciler {
private void initPlugins(final ShenyuCacheRepository
shenyuCacheRepository) {
//GLOBAL
PluginData globalPlugin = PluginData.builder()
- .id(String.valueOf(PluginEnum.GLOBAL.getCode()))
- .name(PluginEnum.GLOBAL.getName())
- .config("")
- .role(PluginRoleEnum.SYS.getName())
- .enabled(true)
- .sort(PluginEnum.GLOBAL.getCode())
- .build();
+ .id(String.valueOf(PluginEnum.GLOBAL.getCode()))
+ .name(PluginEnum.GLOBAL.getName())
+ .config("")
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.GLOBAL.getCode())
+ .build();
shenyuCacheRepository.saveOrUpdatePluginData(globalPlugin);
//uri
PluginData uriPlugin = PluginData.builder()
- .id(String.valueOf(PluginEnum.URI.getCode()))
- .name(PluginEnum.URI.getName())
- .config("")
- .role(PluginRoleEnum.SYS.getName())
- .enabled(true)
- .sort(PluginEnum.URI.getCode())
- .build();
+ .id(String.valueOf(PluginEnum.URI.getCode()))
+ .name(PluginEnum.URI.getName())
+ .config("")
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.URI.getCode())
+ .build();
shenyuCacheRepository.saveOrUpdatePluginData(uriPlugin);
//nettyHttpClient
PluginData webclientPlugin = PluginData.builder()
- .id(String.valueOf(PluginEnum.NETTY_HTTP_CLIENT.getCode()))
- .config("")
- .name(PluginEnum.NETTY_HTTP_CLIENT.getName())
- .role(PluginRoleEnum.SYS.getName())
- .enabled(true)
- .sort(PluginEnum.NETTY_HTTP_CLIENT.getCode())
- .build();
+ .id(String.valueOf(PluginEnum.NETTY_HTTP_CLIENT.getCode()))
+ .config("")
+ .name(PluginEnum.NETTY_HTTP_CLIENT.getName())
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.NETTY_HTTP_CLIENT.getCode())
+ .build();
shenyuCacheRepository.saveOrUpdatePluginData(webclientPlugin);
//divide
PluginData dividePlugin = PluginData.builder()
- .id(String.valueOf(PluginEnum.DIVIDE.getCode()))
- .name(PluginEnum.DIVIDE.getName())
- .config("{multiSelectorHandle: 1, multiRuleHandle:0}")
- .role(PluginRoleEnum.SYS.getName())
- .enabled(true)
- .sort(PluginEnum.DIVIDE.getCode())
- .build();
+ .id(String.valueOf(PluginEnum.DIVIDE.getCode()))
+ .name(PluginEnum.DIVIDE.getName())
+ .config("{multiSelectorHandle: 1, multiRuleHandle:0}")
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.DIVIDE.getCode())
+ .build();
shenyuCacheRepository.saveOrUpdatePluginData(dividePlugin);
//GeneralContextPlugin
PluginData generalContextPlugin = PluginData.builder()
- .id(String.valueOf(PluginEnum.GENERAL_CONTEXT.getCode()))
- .config("")
- .name(PluginEnum.GENERAL_CONTEXT.getName())
- .role(PluginRoleEnum.SYS.getName())
- .enabled(true)
- .sort(PluginEnum.GENERAL_CONTEXT.getCode())
- .build();
+ .id(String.valueOf(PluginEnum.GENERAL_CONTEXT.getCode()))
+ .config("")
+ .name(PluginEnum.GENERAL_CONTEXT.getName())
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.GENERAL_CONTEXT.getCode())
+ .build();
shenyuCacheRepository.saveOrUpdatePluginData(generalContextPlugin);
+ //duubo
+ PluginData dubboPlugin = PluginData.builder()
+ .id(String.valueOf(PluginEnum.DUBBO.getCode()))
+ .name(PluginEnum.DUBBO.getName())
+ .config("")
+ .role(PluginRoleEnum.SYS.getName())
+ .enabled(true)
+ .sort(PluginEnum.DUBBO.getCode())
+ .build();
+ shenyuCacheRepository.saveOrUpdatePluginData(dubboPlugin);
}
/**
@@ -258,7 +280,7 @@ public class IngressReconciler implements Reconciler {
if (Objects.nonNull(v1Ingress.getMetadata())) {
Map<String, String> annotations =
v1Ingress.getMetadata().getAnnotations();
if (Objects.nonNull(annotations)
- &&
Objects.nonNull(annotations.get(IngressConstants.K8S_INGRESS_CLASS_ANNOTATION_KEY)))
{
+ &&
Objects.nonNull(annotations.get(IngressConstants.K8S_INGRESS_CLASS_ANNOTATION_KEY)))
{
return
IngressConstants.SHENYU_INGRESS_CLASS.equals(annotations.get(IngressConstants.K8S_INGRESS_CLASS_ANNOTATION_KEY));
} else {
return Objects.nonNull(v1Ingress.getSpec()) &&
IngressConstants.SHENYU_INGRESS_CLASS.equals(v1Ingress.getSpec().getIngressClassName());
@@ -269,7 +291,7 @@ public class IngressReconciler implements Reconciler {
}
private List<String> deleteSelectorByIngressName(final String namespace,
final String name,
- final String pluginName) {
+ final String pluginName,
final String path) {
final List<String> selectorList =
IngressSelectorCache.getInstance().get(namespace, name, pluginName);
if (Objects.nonNull(selectorList) && !selectorList.isEmpty()) {
for (String selectorId : selectorList) {
@@ -278,6 +300,10 @@ public class IngressReconciler implements Reconciler {
List<String> ruleIdList = new ArrayList<>();
ruleList.forEach(rule -> ruleIdList.add(rule.getId()));
for (String id : ruleIdList) {
+ MetaData metaData =
shenyuCacheRepository.findMetaData(path);
+ if (Objects.nonNull(metaData)) {
+ shenyuCacheRepository.deleteMetaData(metaData);
+ }
shenyuCacheRepository.deleteRuleData(pluginName,
selectorId, id);
}
shenyuCacheRepository.deleteSelectorData(pluginName,
selectorId);
@@ -339,45 +365,54 @@ public class IngressReconciler implements Reconciler {
private void addNewIngressConfigToShenyu(final V1Ingress v1Ingress, final
CoreV1Api apiClient) throws IOException {
V1Ingress ingressCopy = new V1IngressBuilder(v1Ingress).build();
ShenyuMemoryConfig shenyuMemoryConfig =
ingressParser.parse(ingressCopy, apiClient);
+ String pluginName =
Objects.equals(ingressCopy.getMetadata().getAnnotations().get(IngressConstants.PLUGIN_DUBBO_ENABLED),
"true")
+ ? PluginEnum.DUBBO.getName() : PluginEnum.DIVIDE.getName();
if (Objects.nonNull(shenyuMemoryConfig)) {
- List<Pair<SelectorData, RuleData>> routeConfigList =
shenyuMemoryConfig.getRouteConfigList();
- List<SslCrtAndKeyStream> tlsConfigList =
shenyuMemoryConfig.getTlsConfigList();
-
- if (Objects.nonNull(routeConfigList)) {
- routeConfigList.forEach(routeConfig -> {
- SelectorData selectorData = routeConfig.getLeft();
- RuleData ruleData = routeConfig.getRight();
- if (Objects.nonNull(selectorData)) {
-
selectorData.setId(IngressSelectorCache.getInstance().generateSelectorId());
- selectorData.setSort(100);
-
shenyuCacheRepository.saveOrUpdateSelectorData(selectorData);
- if (Objects.nonNull(ruleData)) {
- ruleData.setId(selectorData.getId());
- ruleData.setSelectorId(selectorData.getId());
- ruleData.setSort(100);
-
shenyuCacheRepository.saveOrUpdateRuleData(ruleData);
-
IngressSelectorCache.getInstance().put(Objects.requireNonNull(v1Ingress.getMetadata()).getNamespace(),
- v1Ingress.getMetadata().getName(),
PluginEnum.DIVIDE.getName(), selectorData.getId());
- } else {
-
shenyuCacheRepository.deleteSelectorData(selectorData.getPluginName(),
selectorData.getId());
- }
- }
- });
+ List<IngressConfiguration> routeConfigList =
shenyuMemoryConfig.getRouteConfigList();
+ if (Objects.isNull(routeConfigList)) {
+ return;
}
+ routeConfigList.forEach(routeConfig -> {
+ SelectorData selectorData = routeConfig.getSelectorData();
+ if (Objects.isNull(selectorData)) {
+ return;
+ }
+
selectorData.setId(IngressSelectorCache.getInstance().generateSelectorId());
+ selectorData.setSort(100);
+ shenyuCacheRepository.saveOrUpdateSelectorData(selectorData);
+ RuleData ruleData = routeConfig.getRuleData();
+ if (Objects.isNull(ruleData)) {
+
shenyuCacheRepository.deleteSelectorData(selectorData.getPluginName(),
selectorData.getId());
+ return;
+ }
+
+ ruleData.setId(selectorData.getId());
+ ruleData.setSelectorId(selectorData.getId());
+ ruleData.setSort(100);
+ shenyuCacheRepository.saveOrUpdateRuleData(ruleData);
+ IngressSelectorCache.getInstance().put(
+
Objects.requireNonNull(v1Ingress.getMetadata()).getNamespace(),
+ v1Ingress.getMetadata().getName(), pluginName,
selectorData.getId());
+ MetaData metaData = routeConfig.getMetaData();
+ if (Objects.nonNull(metaData)) {
+ metaData.setId(ruleData.getId());
+ shenyuCacheRepository.saveOrUpdateMetaData(metaData);
+ }
+ });
if (Objects.nonNull(shenyuMemoryConfig.getGlobalDefaultBackend()))
{
synchronized (IngressReconciler.class) {
if (globalDefaultBackend == null) {
// Add a default backend
-
shenyuCacheRepository.saveOrUpdateSelectorData(shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getLeft());
-
shenyuCacheRepository.saveOrUpdateRuleData(shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getRight());
+
shenyuCacheRepository.saveOrUpdateSelectorData(shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getSelectorData());
+
shenyuCacheRepository.saveOrUpdateRuleData(shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getRuleData());
globalDefaultBackend =
shenyuMemoryConfig.getGlobalDefaultBackend();
IngressSelectorCache.getInstance().put(Objects.requireNonNull(v1Ingress.getMetadata()).getNamespace(),
- v1Ingress.getMetadata().getName(),
PluginEnum.DIVIDE.getName(),
shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getLeft().getId());
+ v1Ingress.getMetadata().getName(), pluginName,
shenyuMemoryConfig.getGlobalDefaultBackend().getRight().getSelectorData().getId());
}
}
}
-
+ List<SslCrtAndKeyStream> tlsConfigList =
shenyuMemoryConfig.getTlsConfigList();
if (Objects.nonNull(tlsConfigList)) {
final String namespace =
Objects.requireNonNull(v1Ingress.getMetadata()).getNamespace();
final String ingressName = v1Ingress.getMetadata().getName();
diff --git
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/repository/ShenyuCacheRepository.java
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/repository/ShenyuCacheRepository.java
index d5c7ac456..d2b5023a4 100644
---
a/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/repository/ShenyuCacheRepository.java
+++
b/shenyu-kubernetes-controller/src/main/java/org/apache/shenyu/k8s/repository/ShenyuCacheRepository.java
@@ -17,10 +17,13 @@
package org.apache.shenyu.k8s.repository;
+import org.apache.shenyu.common.dto.MetaData;
import org.apache.shenyu.common.dto.PluginData;
import org.apache.shenyu.common.dto.RuleData;
import org.apache.shenyu.common.dto.SelectorData;
import org.apache.shenyu.plugin.base.cache.BaseDataCache;
+import org.apache.shenyu.plugin.base.cache.CommonMetaDataSubscriber;
+import org.apache.shenyu.plugin.base.cache.MetaDataCache;
import org.apache.shenyu.sync.data.api.PluginDataSubscriber;
import java.util.List;
@@ -37,13 +40,16 @@ public class ShenyuCacheRepository {
private final PluginDataSubscriber subscriber;
+ private final CommonMetaDataSubscriber metaDataSubscriber;
+
/**
* Shenyu Cache Repository Constructor.
*
* @param subscriber PluginDataSubscriber
*/
- public ShenyuCacheRepository(final PluginDataSubscriber subscriber) {
+ public ShenyuCacheRepository(final PluginDataSubscriber subscriber, final
CommonMetaDataSubscriber metaDataSubscriber) {
this.subscriber = subscriber;
+ this.metaDataSubscriber = metaDataSubscriber;
}
/**
@@ -132,4 +138,29 @@ public class ShenyuCacheRepository {
public void deleteRuleData(final String pluginName, final String
selectorId, final String ruleId) {
subscriber.unRuleSubscribe(RuleData.builder().pluginName(pluginName).selectorId(selectorId).id(ruleId).build());
}
+
+ /**
+ * Find MetaData by path.
+ * @param path path
+ * @return MetaData
+ */
+ public MetaData findMetaData(final String path) {
+ return MetaDataCache.getInstance().obtain(path);
+ }
+
+ /**
+ * Save or update MetaData by MetaData.
+ * @param metaData MetaData
+ */
+ public void saveOrUpdateMetaData(final MetaData metaData) {
+ metaDataSubscriber.onSubscribe(metaData);
+ }
+
+ /**
+ * Delete MetaData by MetaData.
+ * @param metaData MetaData
+ */
+ public void deleteMetaData(final MetaData metaData) {
+ metaDataSubscriber.unSubscribe(metaData);
+ }
}
diff --git
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-k8s/src/main/java/org/apache/shenyu/springboot/starter/k8s/IngressControllerConfiguration.java
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-k8s/src/main/java/org/apache/shenyu/springboot/starter/k8s/IngressControllerConfiguration.java
index e54a42638..f151322fd 100644
---
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-k8s/src/main/java/org/apache/shenyu/springboot/starter/k8s/IngressControllerConfiguration.java
+++
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-k8s/src/main/java/org/apache/shenyu/springboot/starter/k8s/IngressControllerConfiguration.java
@@ -42,6 +42,7 @@ import org.apache.shenyu.k8s.parser.IngressParser;
import org.apache.shenyu.k8s.reconciler.EndpointsReconciler;
import org.apache.shenyu.k8s.reconciler.IngressReconciler;
import org.apache.shenyu.k8s.repository.ShenyuCacheRepository;
+import org.apache.shenyu.plugin.base.cache.CommonMetaDataSubscriber;
import org.apache.shenyu.sync.data.api.PluginDataSubscriber;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -157,12 +158,13 @@ public class IngressControllerConfiguration {
/**
* ShenyuCacheRepository.
*
- * @param subscriber PluginDataSubscriber
+ * @param pluginDataSubscriber PluginDataSubscriber
+ * @param metaDataSubscriber CommonMetaDataSubscriber
* @return ShenyuCacheRepository
*/
@Bean
- public ShenyuCacheRepository shenyuCacheRepository(final
PluginDataSubscriber subscriber) {
- return new ShenyuCacheRepository(subscriber);
+ public ShenyuCacheRepository shenyuCacheRepository(final
PluginDataSubscriber pluginDataSubscriber, final CommonMetaDataSubscriber
metaDataSubscriber) {
+ return new ShenyuCacheRepository(pluginDataSubscriber,
metaDataSubscriber);
}
/**