diff --git a/.github/workflows/e2e-k8s.yml b/.github/workflows/e2e-k8s.yml index 4a4c657e6805..7a2e5950344c 100644 --- a/.github/workflows/e2e-k8s.yml +++ b/.github/workflows/e2e-k8s.yml @@ -201,6 +201,8 @@ jobs: strategy: matrix: include: + - case: shenyu-e2e-case-http + script: e2e-http-sync - case: shenyu-e2e-case-spring-cloud script: e2e-springcloud-sync - case: shenyu-e2e-case-apache-dubbo diff --git a/shenyu-e2e/shenyu-e2e-case/pom.xml b/shenyu-e2e/shenyu-e2e-case/pom.xml index 602c78feac50..56b996301026 100644 --- a/shenyu-e2e/shenyu-e2e-case/pom.xml +++ b/shenyu-e2e/shenyu-e2e-case/pom.xml @@ -30,6 +30,7 @@ shenyu-e2e-case-storage + shenyu-e2e-case-http shenyu-e2e-case-spring-cloud shenyu-e2e-case-alibaba-dubbo shenyu-e2e-case-apache-dubbo diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/script/e2e-http-sync.sh b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/script/e2e-http-sync.sh new file mode 100644 index 000000000000..35904130a2a1 --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/script/e2e-http-sync.sh @@ -0,0 +1,78 @@ +#!/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. +# + +docker save shenyu-examples-http:latest | sudo k3s ctr images import - + +# init kubernetes for mysql +SHENYU_TESTCASE_DIR=$(dirname "$(dirname "$(dirname "$(dirname "$0")")")") +bash "${SHENYU_TESTCASE_DIR}"/k8s/script/storage/storage_init_mysql.sh + +# init register center +CUR_PATH=$(readlink -f "$(dirname "$0")") +PRGDIR=$(dirname "$CUR_PATH") +kubectl apply -f "${SHENYU_TESTCASE_DIR}"/k8s/sync/shenyu-cm.yml + +# init shenyu sync +SYNC_ARRAY=("websocket" "http" "zookeeper" "etcd") +#SYNC_ARRAY=("websocket" "nacos") +MIDDLEWARE_SYNC_ARRAY=("zookeeper" "etcd" "nacos") +for sync in ${SYNC_ARRAY[@]}; do + echo -e "------------------\n" + kubectl apply -f "$SHENYU_TESTCASE_DIR"/k8s/shenyu-mysql.yml + sleep 30s + echo "[Start ${sync} synchronous] create shenyu-admin-${sync}.yml shenyu-bootstrap-${sync}.yml shenyu-examples-springcloud.yml" + # shellcheck disable=SC2199 + # shellcheck disable=SC2076 + # shellcheck disable=SC2154 + if [[ "${MIDDLEWARE_SYNC_ARRAY[@]}" =~ "${sync}" ]]; then + kubectl apply -f "${SHENYU_TESTCASE_DIR}"/k8s/shenyu-"${sync}".yml + sleep 10s + fi + kubectl apply -f "${SHENYU_TESTCASE_DIR}"/k8s/sync/shenyu-admin-"${sync}".yml + sh "$SHENYU_TESTCASE_DIR"/k8s/script/healthcheck.sh http://localhost:31095/actuator/health + kubectl apply -f "${SHENYU_TESTCASE_DIR}"/k8s/sync/shenyu-bootstrap-"${sync}".yml + sh "$SHENYU_TESTCASE_DIR"/k8s/script/healthcheck.sh http://localhost:31195/actuator/health + kubectl apply -f "${PRGDIR}"/shenyu-examples-http.yml + sh "$SHENYU_TESTCASE_DIR"/k8s/script/healthcheck.sh http://localhost:31189/grpc/actuator/health + sleep 10s + kubectl get pod -o wide + + ## run e2e-test + ./mvnw -B -f ./shenyu-e2e/pom.xml -pl shenyu-e2e-case/shenyu-e2e-case-grpc -am test + # shellcheck disable=SC2181 + if (($?)); then + echo "${sync}-sync-e2e-test failed" + echo "shenyu-admin log:" + echo "------------------" + kubectl logs "$(kubectl get pod -o wide | grep shenyu-admin | awk '{print $1}')" + echo "shenyu-bootstrap log:" + echo "------------------" + kubectl logs "$(kubectl get pod -o wide | grep shenyu-bootstrap | awk '{print $1}')" + exit 1 + fi + kubectl delete -f "${SHENYU_TESTCASE_DIR}"/k8s/shenyu-mysql.yml + kubectl delete -f "${SHENYU_TESTCASE_DIR}"/k8s/sync/shenyu-admin-"${sync}".yml + kubectl delete -f "${SHENYU_TESTCASE_DIR}"/k8s/sync/shenyu-bootstrap-"${sync}".yml + kubectl delete -f "${PRGDIR}"/shenyu-examples-grpc.yml + # shellcheck disable=SC2199 + # shellcheck disable=SC2076 + if [[ "${MIDDLEWARE_SYNC_ARRAY[@]}" =~ "${sync}" ]]; then + kubectl delete -f "${SHENYU_TESTCASE_DIR}"/k8s/shenyu-"${sync}".yml + fi + echo "[Remove ${sync} synchronous] delete shenyu-admin-${sync}.yml shenyu-bootstrap-${sync}.yml shenyu-examples-springcloud.yml" +done diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/shenyu-examples-http.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/shenyu-examples-http.yml new file mode 100644 index 000000000000..c96ceea19ccd --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/k8s/shenyu-examples-http.yml @@ -0,0 +1,70 @@ +# 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-http + labels: + app: shenyu-examples-http +spec: + replicas: 1 + selector: + matchLabels: + app: shenyu-examples-http + strategy: {} + template: + metadata: + labels: + app: shenyu-examples-http + spec: + containers: + - image: shenyu-examples-http + name: shenyu-examples-http + 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-http + labels: + app: shenyu-examples-http +spec: + selector: + app: shenyu-examples-http + type: NodePort + ports: + - name: "8189" + port: 8189 + targetPort: 8189 + nodePort: 31189 +status: + loadBalancer: {} diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml new file mode 100644 index 000000000000..f326c8600958 --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml @@ -0,0 +1,28 @@ + + + + + org.apache.shenyu + shenyu-e2e-case + 0.0.1-SNAPSHOT + + 4.0.0 + shenyu-e2e-case-http + diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DataSynTest.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DataSynTest.java new file mode 100644 index 000000000000..14bf9da4f239 --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DataSynTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.e2e.testcase.http; + +import org.apache.shenyu.e2e.client.WaitDataSync; +import org.apache.shenyu.e2e.client.admin.AdminClient; +import org.apache.shenyu.e2e.client.gateway.GatewayClient; +import org.apache.shenyu.e2e.engine.annotation.ShenYuTest; +import org.apache.shenyu.e2e.enums.ServiceTypeEnum; +import org.junit.jupiter.api.Test; + +/** + * Testing the correctness of etcd data synchronization method. + */ +@ShenYuTest(environments = { + @ShenYuTest.Environment( + serviceName = "shenyu-e2e-admin", + service = @ShenYuTest.ServiceConfigure(moduleName = "shenyu-e2e", + baseUrl = "http://localhost:31095", + type = ServiceTypeEnum.SHENYU_ADMIN, + parameters = { + @ShenYuTest.Parameter(key = "username", value = "admin"), + @ShenYuTest.Parameter(key = "password", value = "123456") + } + ) + ), + @ShenYuTest.Environment( + serviceName = "shenyu-e2e-gateway", + service = @ShenYuTest.ServiceConfigure(moduleName = "shenyu-e2e", + baseUrl = "http://localhost:31195", + type = ServiceTypeEnum.SHENYU_GATEWAY + ) + ) +}) +public class DataSynTest { + + @Test + void testDataSyn(final AdminClient adminClient, final GatewayClient gatewayClient) throws Exception { + adminClient.login(); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllSelectors, gatewayClient::getSelectorCache, adminClient); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllMetaData, gatewayClient::getMetaDataCache, adminClient); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllRules, gatewayClient::getRuleCache, adminClient); + } +} diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginCases.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginCases.java new file mode 100644 index 000000000000..09d5aa8334c3 --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginCases.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.e2e.testcase.http; + +import com.google.common.collect.Lists; +import org.apache.shenyu.e2e.engine.scenario.ShenYuScenarioProvider; +import org.apache.shenyu.e2e.engine.scenario.specification.ScenarioSpec; +import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuBeforeEachSpec; +import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuCaseSpec; +import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuScenarioSpec; + +import java.util.List; +import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.exists; + +public class DividePluginCases implements ShenYuScenarioProvider { + @Override + public List get() { + return Lists.newArrayList( + testDivideHello() + ); + } + + private ShenYuScenarioSpec testDivideHello() { + return ShenYuScenarioSpec.builder() + .name("single-divide uri =]") + .beforeEachSpec(ShenYuBeforeEachSpec.builder() + .checker(exists("/http/shenyu/client/hello")) + .build()) + .caseSpec(ShenYuCaseSpec.builder() + .addExists("/http/shenyu/client/hello") + .addNotExists("/http/shenyu/client/hello/222/111") + .build()) + .build(); + } +} diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginTest.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginTest.java new file mode 100644 index 000000000000..8d810e8da609 --- /dev/null +++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/http/DividePluginTest.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.e2e.testcase.http; + +import org.apache.shenyu.e2e.client.WaitDataSync; +import org.apache.shenyu.e2e.client.admin.AdminClient; +import org.apache.shenyu.e2e.client.gateway.GatewayClient; +import org.apache.shenyu.e2e.engine.annotation.ShenYuScenario; +import org.apache.shenyu.e2e.engine.annotation.ShenYuTest; +import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec; +import org.apache.shenyu.e2e.enums.ServiceTypeEnum; +import org.junit.jupiter.api.BeforeAll; + +@ShenYuTest(environments = { + @ShenYuTest.Environment( + serviceName = "shenyu-e2e-admin", + service = @ShenYuTest.ServiceConfigure(moduleName = "shenyu-e2e", + baseUrl = "http://localhost:31095", + type = ServiceTypeEnum.SHENYU_ADMIN, + parameters = { + @ShenYuTest.Parameter(key = "username", value = "admin"), + @ShenYuTest.Parameter(key = "password", value = "123456") + } + ) + ), + @ShenYuTest.Environment( + serviceName = "shenyu-e2e-gateway", + service = @ShenYuTest.ServiceConfigure(moduleName = "shenyu-e2e", + baseUrl = "http://localhost:31195", + type = ServiceTypeEnum.SHENYU_GATEWAY + ) + ) +}) +public class DividePluginTest { + + @BeforeAll + void setup(final AdminClient adminClient, final GatewayClient gatewayClient) throws Exception { + adminClient.login(); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllSelectors, gatewayClient::getSelectorCache, adminClient); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllMetaData, gatewayClient::getMetaDataCache, adminClient); + WaitDataSync.waitAdmin2GatewayDataSyncEquals(adminClient::listAllRules, gatewayClient::getRuleCache, adminClient); + } + + @ShenYuScenario(provider = DividePluginCases.class) + void testDivide(final GatewayClient gateway, final CaseSpec spec) { + spec.getVerifiers().forEach(verifier -> verifier.verify(gateway.getHttpRequesterSupplier().get())); + } +}