From d4edad5b3164d0b7aabeda1fc9bd7c6c9ab0dd25 Mon Sep 17 00:00:00 2001 From: Andrea Peruffo Date: Thu, 22 Jun 2023 15:59:02 +0100 Subject: [PATCH] Initial Chaos Test integration for SharedInformers --- .github/workflows/e2e-httpclient-tests.yml | 46 ++++ chaos-tests/Readme.md | 58 +++++ chaos-tests/pom.xml | 225 ++++++++++++++++++ .../java/io/fabric8/it/CheckerCommand.java | 133 +++++++++++ .../java/io/fabric8/it/ControlCommand.java | 123 ++++++++++ .../main/resources/simplelogger.properties | 17 ++ chaos-tests/src/test/java/ChaosIT.java | 161 +++++++++++++ .../src/test/resources/checker-infra.yaml | 50 ++++ .../src/test/resources/checker-pod.yaml | 29 +++ .../src/test/resources/control-infra.yaml | 50 ++++ .../src/test/resources/control-pod.yaml | 27 +++ .../src/test/resources/network-delay.yaml | 29 +++ .../src/test/resources/network-duplicate.yaml | 30 +++ .../src/test/resources/network-loss.yaml | 30 +++ java-generator/cli/pom.xml | 5 - pom.xml | 7 + 16 files changed, 1015 insertions(+), 5 deletions(-) create mode 100644 chaos-tests/Readme.md create mode 100644 chaos-tests/pom.xml create mode 100644 chaos-tests/src/main/java/io/fabric8/it/CheckerCommand.java create mode 100644 chaos-tests/src/main/java/io/fabric8/it/ControlCommand.java create mode 100644 chaos-tests/src/main/resources/simplelogger.properties create mode 100644 chaos-tests/src/test/java/ChaosIT.java create mode 100644 chaos-tests/src/test/resources/checker-infra.yaml create mode 100644 chaos-tests/src/test/resources/checker-pod.yaml create mode 100644 chaos-tests/src/test/resources/control-infra.yaml create mode 100644 chaos-tests/src/test/resources/control-pod.yaml create mode 100644 chaos-tests/src/test/resources/network-delay.yaml create mode 100644 chaos-tests/src/test/resources/network-duplicate.yaml create mode 100644 chaos-tests/src/test/resources/network-loss.yaml diff --git a/.github/workflows/e2e-httpclient-tests.yml b/.github/workflows/e2e-httpclient-tests.yml index 82f6c1bf410..632dab2400f 100644 --- a/.github/workflows/e2e-httpclient-tests.yml +++ b/.github/workflows/e2e-httpclient-tests.yml @@ -84,3 +84,49 @@ jobs: - name: Run Integration Tests run: | ./mvnw ${MAVEN_ARGS} -P"httpclient-${{ matrix.httpclient }}" -Pitests -pl $IT_MODULE verify + + chaos-tests: + name: K8S Chaos Test + runs-on: ubuntu-latest + if: github.repository == 'fabric8io/kubernetes-client' + strategy: + fail-fast: false + matrix: + kubernetes: [v1.25.0] + java-version: [11,17] + http-client: [okhttp,jdk,jetty,vertx] + chaos-test: ["network-delay.yaml", "network-loss.yaml", "network-duplicate.yaml"] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Minikube-Kubernetes + uses: manusa/actions-setup-minikube@v2.7.2 + with: + minikube version: v1.28.0 + kubernetes version: ${{ matrix.kubernetes }} + github token: ${{ secrets.GITHUB_TOKEN }} + start args: '--force' + - name: Setup Kubectl + uses: azure/setup-kubectl@v3 + with: + version: ${{ matrix.kubernetes }} + - name: Setup Java ${{ matrix.java-version }} + uses: actions/setup-java@v3 + with: + java-version: "${{ matrix.java-version }}" + distribution: "temurin" + cache: maven + - name: Install Chaos Mesh + run: | + curl -sSL https://mirrors.chaos-mesh.org/v2.6.0/install.sh | bash + kubectl wait --for=condition=Ready pods --all-namespaces --all --timeout=600s + - name: Build the Support apps containers + run: | + # eval $(minikube -p minikube docker-env) -> check if needed in CI + ./mvnw ${MAVEN_ARGS} -U -Pitests -P"httpclient-${{ matrix.http-client }}" -Pchecker clean package k8s:build -pl chaos-tests -DskipTests + ./mvnw ${MAVEN_ARGS} -U -Pitests -P"httpclient-${{ matrix.http-client }}" -Pcontrol clean package k8s:build -pl chaos-tests -DskipTests + - name: Run Chaos Tests + env: + CHAOS_TEST: ${{ matrix.chaos-test }} + run: | + ./mvnw ${MAVEN_ARGS} -Pitests verify -pl chaos-tests diff --git a/chaos-tests/Readme.md b/chaos-tests/Readme.md new file mode 100644 index 00000000000..4887531c4d3 --- /dev/null +++ b/chaos-tests/Readme.md @@ -0,0 +1,58 @@ +# Chaos Mesh tests for Kubernetes Client SharedInformer + +This module will run automated Chaos Tests for the SharedInformers + +### Setup + +Start minikube, e.g.: + +```bash +minikube start --driver=docker --memory 8192 --cpus 3 +``` + +Install ChaosMesh on minikube: + +```bash +curl -sSL https://mirrors.chaos-mesh.org/v2.6.0/install.sh | bash +``` + +Wait for the pods to be all ready: + +```bash +kubectl wait --for=condition=Ready pods -n chaos-mesh --all --timeout=600s +``` + +Build the control and checker Docker images in the minikube docker-env: + +```bash +eval $(minikube -p minikube docker-env) +mvn -Pitests -Phttpclient-jdk -Pchecker clean package k8s:build -pl chaos-tests -DskipTests +mvn -Pitests -Phttpclient-jdk -Pcontrol clean package k8s:build -pl chaos-tests -DskipTests +``` + +and finally run the test: + +```bash +mvn -Pitests verify -pl chaos-tests +``` + +### Glossary + +- checker: run the SharedInformer to get notifications over the shared resource +- control: apply timely changes to the shared resource + +## What's going on? + +As of today this is the main flow of the tests(please double-check the implementation if this documentation is not accurate anymore): + +- Starts a "Checker" application(as a Pod in a cluster) which starts a SharedInformer on a ConfigMap +- Starts a "Control" application(as a Pod in the cluster) which keeps incrementing a counter stored in the previously mentioned ConfigMap +- The "Checker" is waiting for the number to reach a specific value N +- The "Control" keeps incrementing the counter up to the same number N +- We start a Chaos Experiment targeting the "Checker" app, in this setup, we are using 3 different Network disruption scenarios +- The Chaos Experiment lasts for 12 minutes +- After the Experiment is finished we do expect that the "Checker" app SharedInformer recovers and eventually reaches the target N +- Eventually, both the 2 Control and Checker Pods should be in a Successful state + +We are testing the resiliency of the WebSocket communication used under the cover by the SharedInformers and we guarantee that they do recover appropriately when something happens. +We guarantee that we don't have regressions and this tests can be used as a gate for other HTTP client implementations. diff --git a/chaos-tests/pom.xml b/chaos-tests/pom.xml new file mode 100644 index 00000000000..67c9661f4c5 --- /dev/null +++ b/chaos-tests/pom.xml @@ -0,0 +1,225 @@ + + + + 4.0.0 + + kubernetes-client-project + io.fabric8 + 6.8-SNAPSHOT + + + chaos-tests + jar + Fabric8 :: Chaos Tests + + + 1.13.1 + 4.7.4 + + + + + sonatype-snapshots + https://oss.sonatype.org/content/repositories/snapshots + false + true + + + + + + + info.picocli + picocli + ${picocli.version} + + + + io.fabric8 + kubernetes-client + + + io.fabric8 + kubernetes-httpclient-okhttp + + + + + io.fabric8 + kubernetes-httpclient-okhttp + test + + + + org.slf4j + slf4j-simple + compile + + + + io.fabric8 + kubernetes-junit-jupiter + test + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + org.awaitility + awaitility + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + + + + + + + + + + + + + + + + + + + + TLSv1.2,TLSv1.1,TLSv1 + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + + org.eclipse.jkube + kubernetes-maven-plugin + ${jkube.version} + + + + chaos-test-${app-name}:latest + + openjdk:latest + java -jar /maven/${project.artifactId}-${project.version}.jar + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ${main-class} + + + + + + + + + + + httpclient-okhttp + + + io.fabric8 + kubernetes-httpclient-okhttp + + + + + httpclient-jdk + + + io.fabric8 + kubernetes-httpclient-jdk + + + + + httpclient-vertx + + + io.fabric8 + kubernetes-httpclient-vertx + + + + + httpclient-jetty + + + io.fabric8 + kubernetes-httpclient-jetty + + + + + + + checker + + checker + io.fabric8.it.CheckerCommand + + + + control + + control + io.fabric8.it.ControlCommand + + + + + diff --git a/chaos-tests/src/main/java/io/fabric8/it/CheckerCommand.java b/chaos-tests/src/main/java/io/fabric8/it/CheckerCommand.java new file mode 100644 index 00000000000..78dee736f76 --- /dev/null +++ b/chaos-tests/src/main/java/io/fabric8/it/CheckerCommand.java @@ -0,0 +1,133 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * 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.fabric8.it; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.informers.ResourceEventHandler; +import io.fabric8.kubernetes.client.informers.SharedIndexInformer; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +@Command(name = "checker", mixinStandardHelpOptions = true) +public class CheckerCommand implements Runnable { + + @CommandLine.Option(names = { + "--num" }, paramLabel = "", defaultValue = "10", description = "The number to be reached to quit successfully") + int num; + + @CommandLine.Option(names = { + "--namespace" }, paramLabel = "", defaultValue = "default", description = "The namespace where the configMap will be created") + String namespace; + + @CommandLine.Option(names = { + "--labelkey" }, paramLabel = "", defaultValue = "chaos", description = "The label key to match") + String labelKey; + + @CommandLine.Option(names = { + "--labelvalue" }, paramLabel = "", defaultValue = "test", description = "The label value to match") + String labelValue; + + private static final String COUNTER = "counter"; + + private int extractValue(ConfigMap configMap) { + return Integer.parseInt(configMap.getData().get(COUNTER)); + } + + @Override + public void run() { + System.out.println("Running Checker App"); + KubernetesClient client = new KubernetesClientBuilder().build(); + + CountDownLatch latch = new CountDownLatch(1); + AtomicInteger counter = new AtomicInteger(); + + ResourceEventHandler handler = new ResourceEventHandler() { + @Override + public void onAdd(ConfigMap configMap) { + System.out.println("Ready to start"); + int initialCount = extractValue(configMap); + if (initialCount == 0) { + System.out.println("Counter is 0"); + counter.set(0); + } else { + throw new RuntimeException("Counter is NOT ZERO at the start! Found value: " + initialCount); + } + } + + @Override + public void onUpdate(ConfigMap oldConfigMap, ConfigMap newConfigMap) { + int currentValue = extractValue(newConfigMap); + if (counter.compareAndSet(currentValue - 1, currentValue)) { + System.out.println("Update received, and it's in the correct order, counter: " + currentValue); + } else { + if (currentValue > counter.get()) { + System.out.println("Update received, NOT in the correct order but compatible: " + currentValue); + counter.set(currentValue); + } else { + throw new RuntimeException("Update received in an incorrect order: " + currentValue); + } + } + + if (currentValue == num) { + System.out.println("Last update received!"); + } else if (currentValue > num) { + throw new RuntimeException("Current value is > than the expected value, " + currentValue); + } + } + + @Override + public void onDelete(ConfigMap configMap, boolean deletedFinalStateUnknown) { + if (counter.compareAndSet(num, 0)) { + System.out.println("Experiment should successfully end"); + latch.countDown(); + } else { + throw new RuntimeException("Expected " + num + " but reached " + counter.get()); + } + } + }; + + Map labels = new HashMap<>(); + labels.put(labelKey, labelValue); + Map data = new HashMap<>(); + data.put("counter", Integer.toString(0)); + + SharedIndexInformer configMapInformer = client.configMaps().inNamespace(namespace) + .withLabel(labelKey, labelValue).inform(handler); + configMapInformer.start(); + + try { + latch.await(30, TimeUnit.MINUTES); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + System.out.println("Terminating successfully!"); + System.exit(0); + } + + public static void main(String[] args) { + int exitCode = new CommandLine(new CheckerCommand()).execute(args); + System.exit(exitCode); + } + +} diff --git a/chaos-tests/src/main/java/io/fabric8/it/ControlCommand.java b/chaos-tests/src/main/java/io/fabric8/it/ControlCommand.java new file mode 100644 index 00000000000..234b38374e0 --- /dev/null +++ b/chaos-tests/src/main/java/io/fabric8/it/ControlCommand.java @@ -0,0 +1,123 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * 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.fabric8.it; + +import io.fabric8.kubernetes.api.model.ConfigMap; +import io.fabric8.kubernetes.api.model.ConfigMapBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +import java.util.HashMap; +import java.util.Map; + +@Command(name = "control", mixinStandardHelpOptions = true) +public class ControlCommand implements Runnable { + + @CommandLine.Option(names = { + "--num" }, paramLabel = "", defaultValue = "10", description = "The number to be reached to quit successfully") + int num; + + @CommandLine.Option(names = { + "--namespace" }, paramLabel = "", defaultValue = "default", description = "The namespace where the configMap will be created") + String namespace; + + @CommandLine.Option(names = { + "--labelkey" }, paramLabel = "", defaultValue = "chaos", description = "The label key to match") + String labelKey; + + @CommandLine.Option(names = { + "--labelvalue" }, paramLabel = "", defaultValue = "test", description = "The label value to match") + String labelValue; + + @CommandLine.Option(names = { + "--delay" }, paramLabel = "", defaultValue = "1000", description = "The delay between each number increase") + int delay; + + private static final String COUNTER = "counter"; + + private int extractValue(ConfigMap configMap) { + return Integer.parseInt(configMap.getData().get(COUNTER)); + } + + @Override + public void run() { + System.out.println("Running Control App"); + KubernetesClient client = new KubernetesClientBuilder().build(); + + Map labels = new HashMap<>(); + labels.put(labelKey, labelValue); + Map data = new HashMap<>(); + data.put("counter", Integer.toString(0)); + ConfigMap defaultConfigMap = new ConfigMapBuilder() + .withNewMetadata() + .withName("chaos-test") + .withNamespace(namespace) + .withLabels(labels) + .endMetadata() + .withData(data) + .build(); + + if (client.resource(defaultConfigMap).inNamespace(namespace).get() != null) { + System.out.println("ConfigMap detected removing it before starting"); + client.resource(defaultConfigMap).inNamespace(namespace).delete(); + } + client.resource(defaultConfigMap).inNamespace(namespace).create(); + + while (true) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + ConfigMap currentConfigMap = client.resource(defaultConfigMap).inNamespace(namespace).get(); + + if (currentConfigMap == null) { + throw new RuntimeException("Cannot find the configMap!"); + } else { + int counter = extractValue(currentConfigMap); + System.out.println("going to increment the value, current: " + counter); + + if (counter == num) { + System.out.println("I'm done here!"); + break; + } else if (counter > num) { + throw new RuntimeException("Something went wrong!"); + } else { + currentConfigMap.getData().put(COUNTER, Integer.toString(counter + 1)); + client.resource(currentConfigMap).inNamespace(namespace).createOrReplace(); + System.out.println("Counter incremented"); + } + } + } + + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + System.out.println("Finished! deleting the ConfigMap"); + client.resource(defaultConfigMap).inNamespace(namespace).delete(); + } + + public static void main(String[] args) { + int exitCode = new CommandLine(new ControlCommand()).execute(args); + System.exit(exitCode); + } + +} diff --git a/chaos-tests/src/main/resources/simplelogger.properties b/chaos-tests/src/main/resources/simplelogger.properties new file mode 100644 index 00000000000..dc71c5f9639 --- /dev/null +++ b/chaos-tests/src/main/resources/simplelogger.properties @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +org.slf4j.simpleLogger.defaultLogLevel=debug diff --git a/chaos-tests/src/test/java/ChaosIT.java b/chaos-tests/src/test/java/ChaosIT.java new file mode 100644 index 00000000000..4ca373924dd --- /dev/null +++ b/chaos-tests/src/test/java/ChaosIT.java @@ -0,0 +1,161 @@ + +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * 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. + */ +import io.fabric8.junit.jupiter.api.KubernetesTest; +import io.fabric8.junit.jupiter.api.LoadKubernetesManifests; +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.Version; +import io.fabric8.kubernetes.client.dsl.NamespaceableResource; +import io.fabric8.kubernetes.client.dsl.PodResource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@KubernetesTest +@LoadKubernetesManifests(value = { "checker-infra.yaml", "control-infra.yaml" }) +public class ChaosIT { + protected Logger logger = LoggerFactory.getLogger(getClass().getName()); + + KubernetesClient client; + + String checkerImage = Optional.ofNullable(System.getenv("CHECKER_IMAGE")).orElse("chaos-test-checker:latest"); + String controlImage = Optional.ofNullable(System.getenv("CONTROL_IMAGE")).orElse("chaos-test-control:latest"); + String chaosTest = Optional.ofNullable(System.getenv("CHAOS_TEST")).orElse("network-delay.yaml"); + + @BeforeEach + void beforeEach() throws Exception { + logger.info("BeforeEach execution"); + // this needs to be executed before the pods are started + client.configMaps().inNamespace(client.getNamespace()).withName("chaos-test").delete(); + } + + @AfterEach + void afterEach() throws Exception { + logger.info("AfterEach execution"); + + try { + String checkerLogs = checkerSelector().getLog(); + logger.info("*** Checker Logs ***\n" + checkerLogs); + logger.info("******"); + } catch (Exception e) { + // ignore + } + + try { + String controlLogs = controlSelector().getLog(); + logger.info("*** Control Logs ***\n" + controlLogs); + logger.info("******"); + } catch (Exception e) { + // ignore + } + } + + private static final int TOTAL_COUNT = 1 * 60 * 20; // 1 count each second, for 20 minutes + + private static void setArgs(Pod pod, String namespace) { + List command = pod.getSpec().getContainers().get(0).getCommand(); + command.add("java"); + command.add("-jar"); + command.add("/maven/chaos-tests-" + Version.clientVersion() + ".jar"); + command.add("--namespace"); + command.add(namespace); + command.add("--num"); + command.add(Integer.toString(TOTAL_COUNT)); + pod.getSpec().getContainers().get(0).setCommand(command); + } + + private static void setImage(Pod pod, String image) { + pod.getSpec().getContainers().get(0).setImage(image); + } + + private PodResource checkerSelector() { + return client.pods().inNamespace(client.getNamespace()).withName("checker"); + } + + private PodResource controlSelector() { + return client.pods().inNamespace(client.getNamespace()).withName("checker"); + } + + @Test + void test() throws IOException { + logger.warn("Running test with chaos settings from: " + chaosTest); + logger.warn("Using checker image: " + checkerImage); + logger.warn("Using control image: " + controlImage); + + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("checker-pod.yaml")) { + Stream> resources = client.load(is).resources(); + resources + .filter(r -> r.item().getKind().equals("Pod")) + .forEach(r -> { + if (checkerImage != null) { + setImage(((Pod) r.item()), checkerImage); + } + setArgs(((Pod) r.item()), client.getNamespace()); + r.inNamespace(client.getNamespace()).create(); + }); + } + await().pollInterval(1, TimeUnit.SECONDS).ignoreExceptions().atMost(1, TimeUnit.MINUTES).until(() -> { + assertEquals("Running", checkerSelector().get().getStatus().getPhase()); + return true; + }); + + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("control-pod.yaml")) { + Stream> resources = client.load(is).resources(); + resources + .filter(r -> r.item().getKind().equals("Pod")) + .forEach(r -> { + if (controlImage != null) { + setImage(((Pod) r.item()), controlImage); + } + setArgs(((Pod) r.item()), client.getNamespace()); + r.inNamespace(client.getNamespace()).create(); + }); + } + await().pollInterval(1, TimeUnit.SECONDS).ignoreExceptions().atMost(1, TimeUnit.MINUTES).until(() -> { + assertTrue(checkerSelector().getLog().contains("Update received, and it's in the correct order, counter: 1")); + return true; + }); + + try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(chaosTest)) { + client.load(is).inNamespace(client.getNamespace()).createOrReplace(); + } + + await().pollInterval(10, TimeUnit.SECONDS).ignoreExceptions().atMost(30, TimeUnit.MINUTES).until(() -> { + logger.info("Checking status"); + logger.info("checker: " + checkerSelector().get().getStatus().getPhase()); + logger.info("control: " + controlSelector().get().getStatus().getPhase()); + assertEquals("Succeeded", checkerSelector().get().getStatus().getPhase()); + assertEquals("Succeeded", controlSelector().get().getStatus().getPhase()); + return true; + }); + } + +} diff --git a/chaos-tests/src/test/resources/checker-infra.yaml b/chaos-tests/src/test/resources/checker-infra.yaml new file mode 100644 index 00000000000..c9ba751b979 --- /dev/null +++ b/chaos-tests/src/test/resources/checker-infra.yaml @@ -0,0 +1,50 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: chaos-test-checker-sa +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: configMaps-checker-reader +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: + - get + - list + - watch + - patch + - update + - create + - delete + - post +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: configMaps-checker-reader-binding +roleRef: + kind: Role + apiGroup: rbac.authorization.k8s.io + name: configMaps-checker-reader +subjects: + - kind: ServiceAccount + name: chaos-test-checker-sa diff --git a/chaos-tests/src/test/resources/checker-pod.yaml b/chaos-tests/src/test/resources/checker-pod.yaml new file mode 100644 index 00000000000..932333f47e3 --- /dev/null +++ b/chaos-tests/src/test/resources/checker-pod.yaml @@ -0,0 +1,29 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +apiVersion: v1 +kind: Pod +metadata: + name: checker + labels: + app: checker +spec: + containers: + - name: checker + image: docker.io/andreatp/fabric8-it-checker-app:latest + imagePullPolicy: IfNotPresent + restartPolicy: Never + serviceAccountName: chaos-test-checker-sa diff --git a/chaos-tests/src/test/resources/control-infra.yaml b/chaos-tests/src/test/resources/control-infra.yaml new file mode 100644 index 00000000000..d77a23c472b --- /dev/null +++ b/chaos-tests/src/test/resources/control-infra.yaml @@ -0,0 +1,50 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: chaos-test-control-sa +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: configMaps-control-reader +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: + - get + - list + - watch + - patch + - update + - create + - delete + - post +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: configMaps-control-reader-binding +roleRef: + kind: Role + apiGroup: rbac.authorization.k8s.io + name: configMaps-control-reader +subjects: + - kind: ServiceAccount + name: chaos-test-control-sa diff --git a/chaos-tests/src/test/resources/control-pod.yaml b/chaos-tests/src/test/resources/control-pod.yaml new file mode 100644 index 00000000000..6fbc8eeae9c --- /dev/null +++ b/chaos-tests/src/test/resources/control-pod.yaml @@ -0,0 +1,27 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +apiVersion: v1 +kind: Pod +metadata: + name: control +spec: + containers: + - name: control + image: docker.io/andreatp/fabric8-it-control-app:latest + imagePullPolicy: IfNotPresent + restartPolicy: Never + serviceAccountName: chaos-test-control-sa diff --git a/chaos-tests/src/test/resources/network-delay.yaml b/chaos-tests/src/test/resources/network-delay.yaml new file mode 100644 index 00000000000..281ee4dd2dd --- /dev/null +++ b/chaos-tests/src/test/resources/network-delay.yaml @@ -0,0 +1,29 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: network-delay +spec: + action: delay + mode: all + selector: + labelSelectors: + 'app': 'checker' + delay: + latency: '60s' + duration: '12m' diff --git a/chaos-tests/src/test/resources/network-duplicate.yaml b/chaos-tests/src/test/resources/network-duplicate.yaml new file mode 100644 index 00000000000..14e5c575def --- /dev/null +++ b/chaos-tests/src/test/resources/network-duplicate.yaml @@ -0,0 +1,30 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: network-delay +spec: + action: duplicate + mode: all + selector: + labelSelectors: + 'app': 'checker' + duplicate: + duplicate: '100' + correlation: '50' + duration: '12m' diff --git a/chaos-tests/src/test/resources/network-loss.yaml b/chaos-tests/src/test/resources/network-loss.yaml new file mode 100644 index 00000000000..cc2a559f2f0 --- /dev/null +++ b/chaos-tests/src/test/resources/network-loss.yaml @@ -0,0 +1,30 @@ +# +# Copyright (C) 2015 Red Hat, Inc. +# +# 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. +# + +apiVersion: chaos-mesh.org/v1alpha1 +kind: NetworkChaos +metadata: + name: network-loss +spec: + action: loss + mode: all + selector: + labelSelectors: + 'app': 'checker' + loss: + loss: '100' + correlation: '50' + duration: '12m' diff --git a/java-generator/cli/pom.xml b/java-generator/cli/pom.xml index 815ebad84e5..fe21003da97 100644 --- a/java-generator/cli/pom.xml +++ b/java-generator/cli/pom.xml @@ -29,10 +29,6 @@ java-generator-cli Fabric8 :: Java generator :: CLI - - 4.7.5 - - io.fabric8 @@ -43,7 +39,6 @@ info.picocli picocli - ${picocli.version} diff --git a/pom.xml b/pom.xml index a79c872d444..d7b795e4e66 100644 --- a/pom.xml +++ b/pom.xml @@ -132,6 +132,7 @@ 32.1.2-jre 1.12.0 1.2.1 + 4.7.4 1.0.0 @@ -804,6 +805,11 @@ + + info.picocli + picocli + ${picocli.version} + @@ -1316,6 +1322,7 @@ itests kubernetes-itests + chaos-tests