diff --git a/.github/actions/common/xds-service/action.yml b/.github/actions/common/xds-service/action.yml new file mode 100644 index 0000000000..cd4084f974 --- /dev/null +++ b/.github/actions/common/xds-service/action.yml @@ -0,0 +1,51 @@ +name: "xDS Service Common Test" +description: "Auto common test for xds service" +runs: + using: composite + steps: + - name: start minikube + uses: medyagh/setup-minikube@latest + id: minikube + with: + minikube-version: 1.31.2 + driver: docker + container-runtime: docker + - name: Delay for 10 seconds to ready k8s + shell: bash + run: sleep 10s + - name: check k8s + shell: bash + run: | + kubectl cluster-info + kubectl get pods -n kube-system + echo "k8s version:" $(kubectl version) + - name: deploy istio + shell: bash + run: | + curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.21.4 sh - + istio-1.21.4/bin/istioctl install -f sermant-integration-tests/xds-service-test/script/istio-operator.yaml --skip-confirmation + - name: Delay for 10 seconds to ready istio + shell: bash + run: | + sleep 10s + kubectl get pods -n istio-system + - name: Set up JDK ${{ env.javaVersion }} + uses: actions/setup-java@v3 + with: + java-version: ${{ env.javaVersion }} + distribution: 'adopt' + cache: maven + - name: get cached agent + uses: actions/cache@v3 + with: + path: sermant-agent-*/ + key: ${{ runner.os }}-agent-${{ github.run_id }} + - name: remove xds service product + shell: bash + run: | + rm -rf sermant-integration-tests/xds-service-test/product + - name: get cached xds service package + uses: actions/cache@v3 + with: + path: sermant-integration-tests/xds-service-test/product/ + key: ${{ runner.os }}-xds-service-product-${{ github.run_id }} \ No newline at end of file diff --git a/.github/actions/scenarios/xds-service/xds-service-discovery/client-envoy/action.yml b/.github/actions/scenarios/xds-service/xds-service-discovery/client-envoy/action.yml new file mode 100644 index 0000000000..4b55487216 --- /dev/null +++ b/.github/actions/scenarios/xds-service/xds-service-discovery/client-envoy/action.yml @@ -0,0 +1,59 @@ +name: "xDS Service Discovery Test with Client Using Envoy" +description: "Auto test for xds service discovery with Client Using Envoy" +runs: + using: composite + steps: + - name: build docker image + shell: bash + run: | + cd sermant-integration-tests/xds-service-test/product/spring-server/ + minikube image build -t spring-server:1.0.0 . + cd ../spring-client/ + minikube image build -t spring-client:1.0.0 . + eval $(minikube docker-env) + docker images + - name: start spring-client using envoy + shell: bash + run: | + kubectl label namespace default istio-injection=enabled + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-close.yaml + kubectl wait --for=condition=ready pod -l app=spring-client --timeout=10s + kubectl port-forward svc/spring-client 8080:8080 & + kubectl label namespace default istio-injection- + - name: Wait for spring-client pod to be ready + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + sleep 5s + - name: test one server + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ONE_SERVER_INSTANCE_ENVOY --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: stop spring-server + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml + sleep 3s + - name: test the number of spring-server instances changes from 1 to 0 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ZERO_SERVER_INSTANCE_ENVOY --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: restart spring-server + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + sleep 10s + - name: test the number of spring-server instances changes from 0 to 1 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ONE_SERVER_INSTANCE_ENVOY --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: close all service + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-close.yaml + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml \ No newline at end of file diff --git a/.github/actions/scenarios/xds-service/xds-service-discovery/sermant-only/action.yml b/.github/actions/scenarios/xds-service/xds-service-discovery/sermant-only/action.yml new file mode 100644 index 0000000000..80907206bb --- /dev/null +++ b/.github/actions/scenarios/xds-service/xds-service-discovery/sermant-only/action.yml @@ -0,0 +1,84 @@ +name: "xDS Service Discovery Test" +description: "Auto test for xds service discovery" +runs: + using: composite + steps: + - name: build docker image + shell: bash + run: | + cd sermant-integration-tests/xds-service-test/product/spring-server/ + minikube image build -t spring-server:1.0.0 . + cd ../spring-client/ + minikube image build -t spring-client:1.0.0 . + eval $(minikube docker-env) + docker images + - name: start spring-client and spring-server + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml + - name: Wait for spring-client pod to be ready + shell: bash + run: | + kubectl wait --for=condition=ready pod -l app=spring-client --timeout=10s + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + kubectl port-forward svc/spring-client 8080:8080 & + - name: test one server + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ONE_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: stop spring-server + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml + sleep 3s + - name: test the number of spring-server instances changes from 1 to 0 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ZERO_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: start spring-server with 2 replicas + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + sleep 2s + - name: test the number of spring-server instances changes from 0 to 2 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_TWO_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: create istio token + shell: bash + run: | + kubectl create serviceaccount istio-test + TOKEN=$(kubectl create token istio-test --duration=1h --audience=istio-ca) + kubectl create secret generic istio-test-secret \ + --from-literal=token=${TOKEN} \ + --type="istio.io/key-and-cert" \ + -n default + - name: restart spring-client and sermant xds service use security mode + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml + sleep 5s + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-subscribe-secure.yaml + kubectl wait --for=condition=ready pod -l app=spring-client --timeout=10s + pkill -f "kubectl port-forward svc/spring-client" + kubectl port-forward svc/spring-client 8080:8080 & + - name: test sermant xds service use security mode + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=SECRET --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: test subscribe to get service instance + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_SUBSCRIBE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: close all service + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-subscribe-secure.yaml + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml \ No newline at end of file diff --git a/.github/actions/scenarios/xds-service/xds-service-discovery/server-envoy/action.yml b/.github/actions/scenarios/xds-service/xds-service-discovery/server-envoy/action.yml new file mode 100644 index 0000000000..8f20cd411b --- /dev/null +++ b/.github/actions/scenarios/xds-service/xds-service-discovery/server-envoy/action.yml @@ -0,0 +1,58 @@ +name: "xDS Service Discovery Test with Server Using Envoy" +description: "Auto test for xds service discovery with server using envoy" +runs: + using: composite + steps: + - name: build docker image + shell: bash + run: | + cd sermant-integration-tests/xds-service-test/product/spring-server/ + minikube image build -t spring-server:1.0.0 . + cd ../spring-client/ + minikube image build -t spring-client:1.0.0 . + eval $(minikube docker-env) + docker images + - name: start spring-client + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml + kubectl wait --for=condition=ready pod -l app=spring-client --timeout=10s + kubectl port-forward svc/spring-client 8080:8080 & + - name: start spring-server with envoy + shell: bash + run: | + kubectl label namespace default istio-injection=enabled + sleep 5s + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + - name: test one server + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ONE_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: stop spring-server + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml + sleep 3s + - name: test the number of spring-server instances changes from 1 to 0 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_ZERO_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: start spring-server with 2 replicas + shell: bash + run: | + kubectl apply -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml + kubectl wait --for=condition=ready pod -l app=spring-server --timeout=10s + sleep 2s + - name: test the number of spring-server instances changes from 0 to 2 + shell: bash + run: | + mvn test -Dxds.service.integration.test.type=DISCOVERY_TWO_SERVER_INSTANCE --file \ + sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml + - name: close all service + shell: bash + run: | + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml + kubectl delete -f sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml \ No newline at end of file diff --git a/.github/workflows/xds_service_test.yml b/.github/workflows/xds_service_test.yml new file mode 100644 index 0000000000..b57404e41a --- /dev/null +++ b/.github/workflows/xds_service_test.yml @@ -0,0 +1,88 @@ +name: xds integration test +on: + push: + pull_request: + branches: + - '*' + paths: + - 'sermant-agentcore/**' + - 'sermant-integration-tests/xds-service-test/**' + - '.github/workflows/xds_service_test.yml' + - '.github/actions/common/xds-service/**' + - '.github/actions/scenarios/xds-service/**' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ github.head_ref }} + cancel-in-progress: true +jobs: + build-agent-and-cache: + name: build agent and cache + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'adopt' + cache: maven + - name: cache agent + uses: actions/cache@v3 + with: + path: sermant-agent-*/ + key: ${{ runner.os }}-agent-${{ github.run_id }} + - name: cache xds service package + uses: actions/cache@v3 + with: + path: sermant-integration-tests/xds-service-test/product/ + key: ${{ runner.os }}-xds-service-product-${{ github.run_id }} + - name: package agent + run: | + sed -i '/sermant-backend/d' pom.xml + sed -i '/sermant-injector/d' pom.xml + mvn package -DskipTests -Ptest --file pom.xml + cp -r sermant-integration-tests/xds-service-test/product/spring-client/agent sermant-integration-tests/xds-service-test/product/spring-server/ + test-for-xds-service-discovery-onlysermant: + name: Test for xds service discovery with only sermant + runs-on: ubuntu-latest + needs: [build-agent-and-cache] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 100 + - name: set java version to environment + run: | + echo "javaVersion=8" >> $GITHUB_ENV + - name: xds common operation + uses: ./.github/actions/common/xds-service + - name: xds service discovery + uses: ./.github/actions/scenarios/xds-service/xds-service-discovery/sermant-only + test-for-xds-service-discovery-with-server-envoy: + name: Test for xds service discovery with spring-server using envoy + runs-on: ubuntu-latest + needs: [build-agent-and-cache] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 100 + - name: set java version to environment + run: | + echo "javaVersion=8" >> $GITHUB_ENV + - name: xds common operation + uses: ./.github/actions/common/xds-service + - name: xds service discovery + uses: ./.github/actions/scenarios/xds-service/xds-service-discovery/server-envoy + test-for-xds-service-discovery-with-client-envoy: + name: Test for xds service discovery with spring-client using enovy + runs-on: ubuntu-latest + needs: [build-agent-and-cache] + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 100 + - name: set java version to environment + run: | + echo "javaVersion=8" >> $GITHUB_ENV + - name: xds common operation + uses: ./.github/actions/common/xds-service + - name: xds service discovery + uses: ./.github/actions/scenarios/xds-service/xds-service-discovery/client-envoy \ No newline at end of file diff --git a/sermant-agentcore/sermant-agentcore-config/config/test/config.properties b/sermant-agentcore/sermant-agentcore-config/config/test/config.properties index 65c47396b7..0e66f48135 100644 --- a/sermant-agentcore/sermant-agentcore-config/config/test/config.properties +++ b/sermant-agentcore/sermant-agentcore-config/config/test/config.properties @@ -34,6 +34,8 @@ agent.service.inject.enable=true agent.service.dynamic.config.enable=true # HTTP server switch agent.service.httpserver.enable=false +# xDS service switch +agent.service.xds.service.enable=false #============================= Event configuration =============================# # Event switch event.enable=false @@ -91,6 +93,13 @@ gateway.nettyPort=6888 #gateway.initReconnectInternalTime=5 # Specify retreat algorithm maximum connection interval (s) #gateway.maxReconnectInternalTime=180 +#=============================xds configuration===============================# +# istiod control plane address, security.enable=false with 15010 port, and security.enable=true with 15012 port +xds.config.control.plane.address=istiod.istio-system.svc:15010 +# Whether to use secure communication with the control plane +xds.config.security.enable=false +# service account token used for secure communication with the control plane +xds.config.service.account.token.path=/var/run/secrets/kubernetes.io/serviceaccount/token #=============================Metadata===============================# # Service name for host service instance service.meta.service=default diff --git a/sermant-integration-tests/pom.xml b/sermant-integration-tests/pom.xml index 361afad2a3..2883cd1e41 100644 --- a/sermant-integration-tests/pom.xml +++ b/sermant-integration-tests/pom.xml @@ -1,19 +1,4 @@ - @@ -35,5 +20,6 @@ tag-transmission-test mq-consume-prohibition-test database-write-prohibition-test + xds-service-test diff --git a/sermant-integration-tests/xds-service-test/config/plugins.yaml b/sermant-integration-tests/xds-service-test/config/plugins.yaml new file mode 100644 index 0000000000..fa3c76d3b1 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/config/plugins.yaml @@ -0,0 +1,2 @@ +plugins: + - xds-service-discovery \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/pom.xml b/sermant-integration-tests/xds-service-test/pom.xml new file mode 100644 index 0000000000..8ebebb3432 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/pom.xml @@ -0,0 +1,26 @@ + + + + sermant-integration-tests + io.sermant.integration + 1.0.0 + + 4.0.0 + + xds-service-test + pom + + + 8 + 8 + 2.7.17 + + + + spring-client + spring-server + xds-service-discovery + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/product/spring-client/Dockerfile b/sermant-integration-tests/xds-service-test/product/spring-client/Dockerfile new file mode 100644 index 0000000000..a8610d97cd --- /dev/null +++ b/sermant-integration-tests/xds-service-test/product/spring-client/Dockerfile @@ -0,0 +1,7 @@ +FROM openjdk:8 +WORKDIR /home +COPY agent/ /home/agent +COPY spring-client.jar /home/spring-client.jar +COPY start.sh /home +RUN chmod -R 777 /home +ENTRYPOINT ["sh", "/home/start.sh"] diff --git a/sermant-integration-tests/xds-service-test/product/spring-client/start.sh b/sermant-integration-tests/xds-service-test/product/spring-client/start.sh new file mode 100644 index 0000000000..2cde5e71e1 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/product/spring-client/start.sh @@ -0,0 +1 @@ +exec java -jar /home/spring-client.jar diff --git a/sermant-integration-tests/xds-service-test/product/spring-server/Dockerfile b/sermant-integration-tests/xds-service-test/product/spring-server/Dockerfile new file mode 100644 index 0000000000..36e3064789 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/product/spring-server/Dockerfile @@ -0,0 +1,7 @@ +FROM openjdk:8 +WORKDIR /home +COPY agent/ /home/agent +COPY spring-server.jar /home/spring-server.jar +COPY start.sh /home +RUN chmod -R 777 /home +ENTRYPOINT ["sh", "/home/start.sh"] diff --git a/sermant-integration-tests/xds-service-test/product/spring-server/start.sh b/sermant-integration-tests/xds-service-test/product/spring-server/start.sh new file mode 100644 index 0000000000..9203dd1c8d --- /dev/null +++ b/sermant-integration-tests/xds-service-test/product/spring-server/start.sh @@ -0,0 +1 @@ +exec java -jar /home/spring-server.jar diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-close.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-close.yaml new file mode 100644 index 0000000000..e02cbc040c --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-close.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-client +spec: + replicas: 1 + selector: + matchLabels: + app: spring-client + template: + metadata: + labels: + app: spring-client + spec: + containers: + - name: spring-client + image: spring-client:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + env: + - name: agent_service_dynamic_config_enable + value: "false" + - name: agent_service_xds_service_enable + value: "false" + - name: agent_config_ignoredPrefixes + value: "ignore" + - name: xds_service_discovery_enabled + value: "false" + - name: JAVA_TOOL_OPTIONS + value: "-javaagent:/home/agent/sermant-agent.jar" + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-client +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-client \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml new file mode 100644 index 0000000000..ada30345f5 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-open.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-client +spec: + replicas: 1 + selector: + matchLabels: + app: spring-client + template: + metadata: + labels: + app: spring-client + spec: + containers: + - name: spring-client + image: spring-client:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + env: + - name: agent_service_dynamic_config_enable + value: "false" + - name: agent_service_xds_service_enable + value: "true" + - name: agent_config_ignoredPrefixes + value: "ignore" + - name: JAVA_TOOL_OPTIONS + value: "-javaagent:/home/agent/sermant-agent.jar" + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-client +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-client \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-subscribe-secure.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-subscribe-secure.yaml new file mode 100644 index 0000000000..c875a20d79 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-client-sermant-xds-subscribe-secure.yaml @@ -0,0 +1,63 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-client +spec: + replicas: 1 + selector: + matchLabels: + app: spring-client + template: + metadata: + labels: + app: spring-client + spec: + containers: + - name: spring-client + image: spring-client:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + volumeMounts: + - name: token-volume + mountPath: /var/run/secrets/tokens + readOnly: true + env: + - name: agent_service_dynamic_config_enable + value: "false" + - name: agent_service_xds_service_enable + value: "true" + - name: agent_config_ignoredPrefixes + value: "ignore" + - name: xds_service_discovery_upstreamServiceName + value: "spring-server" + - name: xds_service_discovery_type + value: "subscribe" + - name: xds_config_control_plane_address + value: "istiod.istio-system.svc:15012" + - name: xds_config_security_enable + value: "true" + - name: xds_config_service_account_token_path + value: "/var/run/secrets/tokens/token" + - name: JAVA_TOOL_OPTIONS + value: "-javaagent:/home/agent/sermant-agent.jar" + volumes: + - name: token-volume + secret: + secretName: istio-test-secret + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-client +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-client \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml new file mode 100644 index 0000000000..df6eeb1b67 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-server-2-replicas.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-server +spec: + replicas: 2 + selector: + matchLabels: + app: spring-server + template: + metadata: + labels: + app: spring-server + spec: + containers: + - name: spring-server + image: spring-server:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-server +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-server \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml new file mode 100644 index 0000000000..e10869ad20 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-server-sermant-xds-open.yaml @@ -0,0 +1,39 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-server +spec: + replicas: 1 + selector: + matchLabels: + app: spring-server + template: + metadata: + labels: + app: spring-server + spec: + containers: + - name: spring-server + image: spring-server:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + env: + - name: JAVA_TOOL_OPTIONS + value: "-javaagent:/home/agent/sermant-agent.jar" + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-server +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-server \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml b/sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml new file mode 100644 index 0000000000..952e0f5483 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/discovery/spring-server.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spring-server +spec: + replicas: 1 + selector: + matchLabels: + app: spring-server + template: + metadata: + labels: + app: spring-server + spec: + containers: + - name: spring-server + image: spring-server:1.0.0 + imagePullPolicy: Never + ports: + - containerPort: 8080 + imagePullSecrets: + - name: default-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: spring-server +spec: + type: ClusterIP + ports: + - port: 8080 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: spring-server \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/script/istio-operator.yaml b/sermant-integration-tests/xds-service-test/script/istio-operator.yaml new file mode 100644 index 0000000000..008ca8fbfc --- /dev/null +++ b/sermant-integration-tests/xds-service-test/script/istio-operator.yaml @@ -0,0 +1,36 @@ +apiVersion: install.istio.io/v1alpha1 +kind: IstioOperator +spec: + profile: default + components: + ingressGateways: + - name: istio-ingressgateway + enabled: true + k8s: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + pilot: + enabled: true + k8s: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + values: + global: + proxy: + resources: + limits: + cpu: 1000m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/spring-client/pom.xml b/sermant-integration-tests/xds-service-test/spring-client/pom.xml new file mode 100644 index 0000000000..7abc5e5cfd --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-client/pom.xml @@ -0,0 +1,80 @@ + + + + xds-service-test + io.sermant.integration + 1.0.0 + + 4.0.0 + + spring-client + + + 8 + 8 + 4.5.13 + + + + + org.springframework.boot + spring-boot-starter-web + ${spring.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.version} + + io.sermant.demo.spring.client.SpringClientApplication + spring-client + ${pom.basedir}/../product/spring-client + + + + + repackage + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + false + + + agent-clean + clean + + clean + + + + + ${pom.basedir}/../product/spring-client + + spring-client.jar + + + + + + + + + + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientApplication.java b/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientApplication.java new file mode 100644 index 0000000000..79119502da --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientApplication.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.demo.spring.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * SpringClientApplication + * + * @author daizhenyu + * @since 2024-07-02 + **/ +@SpringBootApplication +public class SpringClientApplication { + /** + * main + * + * @param args args + */ + public static void main(String[] args) { + SpringApplication.run(SpringClientApplication.class, args); + } +} diff --git a/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientController.java b/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientController.java new file mode 100644 index 0000000000..b5f6579c78 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-client/src/main/java/io/sermant/demo/spring/client/SpringClientController.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.demo.spring.client; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +/** + * controller + * + * @author daizhenyu + * @since 2024-07-02 + **/ +@RestController +public class SpringClientController { + private static final String HELLO_METHOD_PATH = "/hello"; + + private static final int SUCCESS_CODE = 200; + + private static final int MAX_TOTAL = 200; + + private static final int MAX_PER_ROUTE = 20; + + private static final int CONNECT_TIMEOUT = 200; + + private static final int SOCKET_TIMEOUT = 200; + + private static final int RETRY_COUNT = 3; + + private static CloseableHttpClient httpClient; + + static { + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); + connectionManager.setMaxTotal(MAX_TOTAL); + connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE); + + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(CONNECT_TIMEOUT) + .setSocketTimeout(SOCKET_TIMEOUT) + .build(); + + httpClient = HttpClients.custom() + .setConnectionManager(connectionManager) + .setDefaultRequestConfig(requestConfig) + .setRetryHandler(new DefaultHttpRequestRetryHandler(RETRY_COUNT, true)) + .build(); + } + + /** + * call upstream service + * + * @param address address + * @return result + */ + @RequestMapping("hello") + public String hello(String address) { + StringBuilder urlBuilder = new StringBuilder(); + urlBuilder.append("http://"); + urlBuilder.append(address); + urlBuilder.append(HELLO_METHOD_PATH); + return httpGet(urlBuilder.toString()); + } + + private String httpGet(String url) { + HttpGet httpGet = new HttpGet(url); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + if (response.getStatusLine().getStatusCode() == SUCCESS_CODE) { + return EntityUtils.toString(response.getEntity()); + } + return ""; + } catch (IOException e) { + return ""; + } + } +} diff --git a/sermant-integration-tests/xds-service-test/spring-server/pom.xml b/sermant-integration-tests/xds-service-test/spring-server/pom.xml new file mode 100644 index 0000000000..07385222ba --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-server/pom.xml @@ -0,0 +1,74 @@ + + + + xds-service-test + io.sermant.integration + 1.0.0 + + 4.0.0 + + spring-server + + + 8 + 8 + + + + + org.springframework.boot + spring-boot-starter-web + ${spring.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.version} + + io.sermant.demo.spring.server.SpringServerApplication + spring-server + ${pom.basedir}/../product/spring-server + + + + + repackage + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + false + + + agent-clean + clean + + clean + + + + + ${pom.basedir}/../product/spring-server + + spring-server.jar + + + + + + + + + + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerApplication.java b/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerApplication.java new file mode 100644 index 0000000000..2be2bc65af --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerApplication.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.demo.spring.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * SpringServerApplication + * + * @author daizhenyu + * @since 2024-07-02 + **/ +@SpringBootApplication +public class SpringServerApplication { + /** + * main + * + * @param args args + */ + public static void main(String[] args) { + SpringApplication.run(SpringServerApplication.class, args); + } +} diff --git a/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerController.java b/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerController.java new file mode 100644 index 0000000000..2f2f37303d --- /dev/null +++ b/sermant-integration-tests/xds-service-test/spring-server/src/main/java/io/sermant/demo/spring/server/SpringServerController.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.demo.spring.server; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * controller + * + * @author daizhenyu + * @since 2024-07-02 + **/ +@RestController +public class SpringServerController { + /** + * say hello + * + * @return result + */ + @RequestMapping("hello") + public String sayHello() { + return "hello"; + } +} diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/config/config.yaml b/sermant-integration-tests/xds-service-test/xds-service-discovery/config/config.yaml new file mode 100644 index 0000000000..f7f8e2922b --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/config/config.yaml @@ -0,0 +1,4 @@ +xds.service.discovery: + enabled: true + upstreamServiceName: spring-server + type: get \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/pom.xml b/sermant-integration-tests/xds-service-test/xds-service-discovery/pom.xml new file mode 100644 index 0000000000..9bf2005a07 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/pom.xml @@ -0,0 +1,256 @@ + + + + xds-service-test + io.sermant.integration + 1.0.0 + + 4.0.0 + + xds-service-discovery + pom + + + ${pom.basedir}/../product/spring-client + xds-service-discovery + ${output.basedir}/agent/pluginPackage + undefined + ${package.plugin.dir}/${package.plugin.name}/${package.plugin.type} + ${project.version} + ${pom.basedir}/../../../sermant-agent-${project.version}/agent + ${package.plugin.dir}/${package.plugin.name}/config + ${pom.basedir}/../config + ../config + 8 + 8 + + + + + io.sermant + sermant-agentcore-core + provided + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + false + + + copy-config + package + + copy-resources + + + ${output.basedir}/agent/config + true + + + ${sermant.source.dir}/config + + bootstrap.properties + config.properties + logback.xml + + + + ${sermant.plugins.config.dir} + + plugins.yaml + + + + + + + copy-common + package + + copy-resources + + + ${output.basedir}/agent/common + true + + + ${sermant.source.dir}/common + + * + + + + + + + copy-core + package + + copy-resources + + + ${output.basedir}/agent/core + true + + + ${sermant.source.dir}/core + + * + + + + + + + copy-god + package + + copy-resources + + + ${output.basedir}/agent/god + true + + + ${sermant.source.dir}/god + + * + + + + + + + copy-implement + package + + copy-resources + + + ${output.basedir}/agent/implement + true + + + ${sermant.source.dir}/implement + + * + + + + + + + copy-agent + package + + copy-resources + + + ${output.basedir}/agent + true + + + ${sermant.source.dir} + + sermant-agent.jar + + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + false + + + agent-clean + clean + + clean + + + + + ${output.basedir}/agent + + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ${package.plugin.name} + ${package.plugin.version} + + + + + + org.apache.maven.plugins + maven-resources-plugin + + + package + + copy-resources + + + ${config.output.dir} + true + + + ${plugin.config.dir} + + config.yaml + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + ${package.output.dir}/${project.artifactId}-${project.version}.jar + + + + + + + + + + + xds-service-discovery-plugin + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/pom.xml b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/pom.xml new file mode 100644 index 0000000000..fd926cdedf --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/pom.xml @@ -0,0 +1,47 @@ + + + + xds-service-discovery + io.sermant.integration + 1.0.0 + + + 4.0.0 + xds-service-discovery-plugin + + + ${pom.basedir}/../../product/spring-client + xds-service-discovery + plugin + false + 8 + 8 + + + + + io.sermant + sermant-agentcore-core + ${project.version} + provided + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateConfig.java b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateConfig.java new file mode 100644 index 0000000000..c5651a5e85 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateConfig.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.xds.service.discovery; + +import io.sermant.core.config.common.ConfigFieldKey; +import io.sermant.core.config.common.ConfigTypeKey; +import io.sermant.core.plugin.config.PluginConfig; + +/** + * config + * + * @author daizhenyu + * @since 2024-07-02 + **/ +@ConfigTypeKey("xds.service.discovery") +public class TemplateConfig implements PluginConfig { + @ConfigFieldKey("upstreamServiceName") + private String upstreamServiceName; + + @ConfigFieldKey("type") + private String type; + + @ConfigFieldKey("enabled") + private boolean enabled; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getUpstreamServiceName() { + return upstreamServiceName; + } + + public void setUpstreamServiceName(String upstreamServiceName) { + this.upstreamServiceName = upstreamServiceName; + } +} diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateDeclarer.java b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateDeclarer.java new file mode 100644 index 0000000000..a0833b5a5b --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateDeclarer.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.xds.service.discovery; + +import io.sermant.core.plugin.agent.declarer.AbstractPluginDeclarer; +import io.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import io.sermant.core.plugin.agent.matcher.ClassMatcher; +import io.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * template bytecode enhancement declarer + * + * @author daizhnyu + * @since 2024-07-05 + */ +public class TemplateDeclarer extends AbstractPluginDeclarer { + @Override + public ClassMatcher getClassMatcher() { + // Matches the class to be intercepted by fully qualified name + return ClassMatcher.nameEquals("io.sermant.demo.spring.client.SpringClientController"); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + // matches the method to be intercepted by name + InterceptDeclarer.build(MethodMatcher.nameEquals("hello"), new TemplateInterceptor()) + }; + } + + @Override + public boolean isEnabled() { + return super.isEnabled(); + } +} diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateInterceptor.java b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateInterceptor.java new file mode 100644 index 0000000000..6c2916ae72 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/java/io/sermant/xds/service/discovery/TemplateInterceptor.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.xds.service.discovery; + +import io.sermant.core.plugin.agent.entity.ExecuteContext; +import io.sermant.core.plugin.agent.interceptor.Interceptor; +import io.sermant.core.plugin.config.PluginConfigManager; +import io.sermant.core.service.ServiceManager; +import io.sermant.core.service.xds.XdsCoreService; +import io.sermant.core.service.xds.XdsServiceDiscovery; +import io.sermant.core.service.xds.entity.ServiceInstance; +import io.sermant.core.service.xds.listener.XdsServiceDiscoveryListener; +import io.sermant.core.utils.CollectionUtils; + +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * interceptor + * + * @author daizhenyu + * @since 2024-07-05 + **/ +public class TemplateInterceptor implements Interceptor { + private final XdsServiceDiscovery xdsServiceDiscovery; + + private final TemplateConfig templateConfig; + + private List instanceList = new ArrayList<>(); + + private SecureRandom secureRandom = new SecureRandom(); + + /** + * constructor + */ + public TemplateInterceptor() { + xdsServiceDiscovery = ServiceManager.getService(XdsCoreService.class) + .getXdsServiceDiscovery(); + templateConfig = PluginConfigManager.getPluginConfig(TemplateConfig.class); + if (templateConfig.getType().equals("subscribe")) { + xdsServiceDiscovery.subscribeServiceInstance(templateConfig.getUpstreamServiceName(), + new XdsServiceDiscoveryListener() { + @Override + public void process(Set instances) { + instanceList = new ArrayList<>(instances); + } + }); + } + } + + @Override + public ExecuteContext before(ExecuteContext context) { + if (!templateConfig.isEnabled()) { + return context; + } + if (templateConfig.getType().equals("get")) { + instanceList = new ArrayList<>(xdsServiceDiscovery + .getServiceInstance(templateConfig.getUpstreamServiceName())); + } + + context.setLocalFieldValue("serviceCount", instanceList.size()); + if (CollectionUtils.isEmpty(instanceList)) { + return context; + } + int randomIndex = secureRandom.nextInt(instanceList.size()); + ServiceInstance instance = instanceList.get(randomIndex); + Object[] arguments = context.getArguments(); + arguments[0] = buildUrl(instance); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + if (!templateConfig.isEnabled()) { + return context; + } + String oldResult = (String) context.getResult(); + context.changeResult(oldResult + "-" + context.getLocalFieldValue("serviceCount")); + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + return context; + } + + private String buildUrl(ServiceInstance instance) { + StringBuilder builder = new StringBuilder(); + builder.append(instance.getHost()); + builder.append(":"); + builder.append(instance.getPort()); + return builder.toString(); + } +} diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.agent.declarer.PluginDeclarer new file mode 100644 index 0000000000..2631c72a90 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -0,0 +1,16 @@ +# +# Copyright (C) 2024-2024 Sermant Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +io.sermant.xds.service.discovery.TemplateDeclarer \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.config.PluginConfig b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.config.PluginConfig new file mode 100644 index 0000000000..3ff82c5e7b --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-discovery/xds-service-discovery-plugin/src/main/resources/META-INF/services/io.sermant.core.plugin.config.PluginConfig @@ -0,0 +1,16 @@ +# +# Copyright (C) 2024-2024 Sermant Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +io.sermant.xds.service.discovery.TemplateConfig \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml b/sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml new file mode 100644 index 0000000000..2eb5d5770b --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-integration-test/pom.xml @@ -0,0 +1,69 @@ + + + + xds-service-test + io.sermant.integration + 1.0.0 + + 4.0.0 + + xds-service-integration-test + + + 8 + 8 + 4.5.13 + 1.2 + 3.0.0 + + + + + org.junit.jupiter + junit-jupiter + test + + + org.apache.httpcomponents + httpclient + ${httpclient4x.version} + test + + + ch.qos.logback + logback-core + test + + + ch.qos.logback + logback-classic + test + + + org.slf4j + slf4j-api + test + + + commons-logging + commons-logging + ${commons-log.version} + test + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + + + + \ No newline at end of file diff --git a/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/discovery/XdsServiceDiscoveryTest.java b/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/discovery/XdsServiceDiscoveryTest.java new file mode 100644 index 0000000000..05bdd4efa3 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/discovery/XdsServiceDiscoveryTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.xds.service.discovery; + +import io.sermant.xds.service.utils.HttpRequestUtils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; + +/** + * xDS service discovery test + * + * @author daizhenyu + * @since 2024-07-15 + **/ +public class XdsServiceDiscoveryTest { + /** + * one server instance + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = "DISCOVERY_ONE_SERVER_INSTANCE") + public void testDiscoveryWithOneServerInstance() { + String[] resultStrings = splitResult(HttpRequestUtils.doGet("http://127.0.0.1:8080/hello")); + Assertions.assertEquals(2, resultStrings.length, "The returned result format is incorrect."); + Assertions.assertEquals("hello", resultStrings[0]); + Assertions.assertEquals("1", resultStrings[1]); + } + + /** + * zero server instance + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = "DISCOVERY_ZERO_SERVER_INSTANCE") + public void testDiscoveryWithZeroServerInstance() { + String[] resultStrings = splitResult(HttpRequestUtils.doGet("http://127.0.0.1:8080/hello")); + Assertions.assertEquals(2, resultStrings.length, "The returned result format is incorrect."); + Assertions.assertEquals("0", resultStrings[1]); + } + + /** + * two server instance + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = "DISCOVERY_TWO_SERVER_INSTANCE") + public void testDiscoveryWithTwoServerInstance() { + String[] resultStrings = splitResult(HttpRequestUtils.doGet("http://127.0.0.1:8080/hello")); + Assertions.assertEquals(2, resultStrings.length, "The returned result format is incorrect."); + Assertions.assertEquals("hello", resultStrings[0]); + Assertions.assertEquals("2", resultStrings[1]); + } + + /** + * secret + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = "SECRET") + public void testDiscoveryWithSecret() { + String[] resultStrings = splitResult(HttpRequestUtils.doGet("http://127.0.0.1:8080/hello")); + Assertions.assertEquals(2, resultStrings.length, "The returned result format is incorrect."); + Assertions.assertEquals("hello", resultStrings[0]); + Assertions.assertEquals("2", resultStrings[1]); + } + + /** + * subscribe to get service instance + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = "DISCOVERY_SUBSCRIBE") + public void testDiscoveryWithSubscribe() { + String[] resultStrings = splitResult(HttpRequestUtils.doGet("http://127.0.0.1:8080/hello")); + Assertions.assertEquals(2, resultStrings.length, "The returned result format is incorrect."); + Assertions.assertEquals("hello", resultStrings[0]); + Assertions.assertEquals("2", resultStrings[1]); + } + + /** + * one server instance with client using envoy + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = + "DISCOVERY_ONE_SERVER_INSTANCE_ENVOY") + public void testDiscoveryWithClientUsingEnvoyAndOneInstance() { + Assertions.assertEquals("hello", HttpRequestUtils.doGet("http://127.0.0.1:8080/hello?address=spring-server" + + ".default.svc.cluster.local:8080")); + } + + /** + * zero server instance with client using envoy + */ + @Test + @EnabledIfSystemProperty(named = "xds.service.integration.test.type", matches = + "DISCOVERY_ZERO_SERVER_INSTANCE_ENVOY") + public void testDiscoveryWithClientUsingEnvoyAndZeroInstance() { + Assertions.assertEquals("", HttpRequestUtils.doGet("http://127.0.0.1:8080/hello?address=spring-server" + + ".default.svc.cluster.local:8080")); + } + + private String[] splitResult(String result) { + Assertions.assertNotNull(result, "The returned result is null."); + return result.split("-"); + } +} diff --git a/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/utils/HttpRequestUtils.java b/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/utils/HttpRequestUtils.java new file mode 100644 index 0000000000..a36bdf5547 --- /dev/null +++ b/sermant-integration-tests/xds-service-test/xds-service-integration-test/src/test/java/io/sermant/xds/service/utils/HttpRequestUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024-2024 Sermant Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.sermant.xds.service.utils; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * http utils + * + * @author daizhenyu + * @since 2024-01-08 + **/ +public class HttpRequestUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(HttpRequestUtils.class); + + private static final int SUCCESS_CODE = 200; + + private HttpRequestUtils() { + } + + /** + * http get + * + * @param url http url + * @return response body + */ + public static String doGet(String url) { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + RequestConfig requestConfig = RequestConfig.custom() + .build(); + HttpGet httpGet = new HttpGet(url); + httpGet.setConfig(requestConfig); + try (CloseableHttpResponse response = httpClient.execute(httpGet)) { + if (response.getStatusLine().getStatusCode() == SUCCESS_CODE) { + return EntityUtils.toString(response.getEntity()); + } + LOGGER.info("Request error, the message is: {}", EntityUtils.toString(response.getEntity())); + return ""; + } + } catch (IOException e) { + LOGGER.info("Request exception, the message is: {}", e.getMessage()); + return ""; + } + } +}