This is an automated email from the ASF dual-hosted git repository. marat pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push: new 7d84fe5d Add basic integration and e2e tests, env setup (#682) 7d84fe5d is described below commit 7d84fe5d21cc08e617267f8009a22c6123563769 Author: Dmitry Volodin <dmvo...@gmail.com> AuthorDate: Thu Mar 23 02:22:25 2023 +0300 Add basic integration and e2e tests, env setup (#682) * Add basic integration and e2e tests, env setup * Fix RBAC and optimize tests running * Fix actions script * Fix docker exec command --- .github/workflows/operator.yml | 19 ++ .github/workflows/vscode.yml | 2 +- karavan-operator/Makefile | 13 +- karavan-operator/pom.xml | 53 +++++- .../camel/karavan/operator/KaravanReconciler.java | 4 +- .../karavan/operator/resource/KaravanRole.java | 3 +- .../camel/karavan/operator/spec/KaravanSpec.java | 12 ++ .../karavan/operator/KaravanReconcilerE2E.java | 146 +++++++++++++++ .../karavan/operator/KaravanReconcilerTest.java | 65 +++++++ .../src/test/resources/application.properties | 3 + .../src/test/resources/kubernetes/kubernetes.yaml | 202 +++++++++++++++++++++ .../src/test/resources/kubernetes/pipelines.yaml | 40 ++++ .../src/test/resources/kubernetes/tasks.yaml | 73 ++++++++ 13 files changed, 629 insertions(+), 6 deletions(-) diff --git a/.github/workflows/operator.yml b/.github/workflows/operator.yml index 4f35a47b..c235653e 100644 --- a/.github/workflows/operator.yml +++ b/.github/workflows/operator.yml @@ -6,6 +6,7 @@ on: workflow_dispatch: pull_request: branches: [ main ] + paths: ['karavan-operator/**'] env: REGISTRY: ghcr.io @@ -38,6 +39,24 @@ jobs: key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-maven- + - name: Kubernetes KinD Cluster + uses: container-tools/kind-action@v2 + with: + version: v0.17.0 + node_image: "kindest/node:v1.24.7" + registry: false + + - name: Test operator + run: | + mvn test -f karavan-operator -Pintegration-tests + + - name: Test operator (end-to-end) + run: | + cd karavan-operator + make test-deploy-kind + mvn test -Pend-to-end-tests + make test-undeploy-kind + # Build Karavan operator - name: Build operator run: | diff --git a/.github/workflows/vscode.yml b/.github/workflows/vscode.yml index f0be3e8f..2b90b49e 100644 --- a/.github/workflows/vscode.yml +++ b/.github/workflows/vscode.yml @@ -1,4 +1,4 @@ -name: vscode xtension +name: vscode extension on: push: diff --git a/karavan-operator/Makefile b/karavan-operator/Makefile index ac3df03f..d1897f0e 100644 --- a/karavan-operator/Makefile +++ b/karavan-operator/Makefile @@ -55,7 +55,7 @@ help: ## Display this help. ##@ Build docker-build: ## Build docker image with the manager. - mvn package -Dquarkus.container-image.build=true -Dquarkus.container-image.image=${IMG} + mvn clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.image=${IMG} docker-push: ## Push docker image with the manager. mvn package -Dquarkus.container-image.push=true -Dquarkus.container-image.image=${IMG} @@ -74,6 +74,17 @@ deploy: ## Deploy controller to the K8s cluster specified in ~/.kube/config. undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. kubectl delete -f target/kubernetes/kubernetes.yml +##@ Test + +test-deploy-kind: docker-build install ## Build and deploy controller for tests to the default KinD cluster. + kind load docker-image ${IMG} + kubectl apply -f src/test/resources/kubernetes/kubernetes.yaml + kubectl wait deployment camel-karavan-operator -n camel-karavan-operator --for condition=Available=True --timeout=120s + +test-undeploy-kind: install ## Undeploy controller from the test default KinD cluster. + kubectl delete -f src/test/resources/kubernetes/kubernetes.yaml + docker exec $(shell kind get clusters | head -1)-control-plane crictl rmi ${IMG} + ##@ Bundle .PHONY: bundle bundle: ## Generate bundle manifests and metadata, then validate generated files. diff --git a/karavan-operator/pom.xml b/karavan-operator/pom.xml index b7f5eebd..5bdd3e77 100644 --- a/karavan-operator/pom.xml +++ b/karavan-operator/pom.xml @@ -10,6 +10,7 @@ <packaging>jar</packaging> <properties> <compiler-plugin.version>3.8.1</compiler-plugin.version> + <surefire-plugin.version>3.0.0-M9</surefire-plugin.version> <maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> @@ -54,6 +55,10 @@ <groupId>io.quarkiverse.operatorsdk</groupId> <artifactId>quarkus-operator-sdk-bundle-generator</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-container-image-jib</artifactId> + </dependency> <!-- This dependency is needed only to ensure proper building order so that this module is build after the bundle generator extension --> <dependency> <groupId>io.quarkiverse.operatorsdk</groupId> @@ -65,6 +70,11 @@ <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.awaitility</groupId> + <artifactId>awaitility</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> @@ -96,6 +106,47 @@ <quarkus.package.type>native</quarkus.package.type> </properties> </profile> + <profile> + <id>end-to-end-tests</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire-plugin.version}</version> + <configuration> + <includes> + <include>**/*E2E.java</include> + </includes> + <excludes> + <exclude>**/*Test.java</exclude> + <exclude>**/*IT.java</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>integration-tests</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>${surefire-plugin.version}</version> + <configuration> + <includes> + <include>**/*Test.java</include> + <include>**/*IT.java</include> + </includes> + <excludes> + <exclude>**/*E2E.java</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </build> + </profile> </profiles> - </project> diff --git a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java index 93e2333c..f1adc6f5 100644 --- a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java +++ b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java @@ -70,7 +70,7 @@ public class KaravanReconciler implements Reconciler<Karavan>, EventSourceInitia static final Logger log = LoggerFactory.getLogger(KaravanReconciler.class); private boolean isOpenShift; - private boolean initTektonInstalled; + private final boolean initTektonInstalled; private KubernetesClient client; private Workflow<Karavan> workflow; private KaravanServiceAccount karavanServiceAccount; @@ -172,7 +172,7 @@ public class KaravanReconciler implements Reconciler<Karavan>, EventSourceInitia return EventSourceInitializer.nameEventSources(list.toArray(new EventSource[list.size()])); } - private List<CRUDKubernetesDependentResource> getResources(){ + private List<CRUDKubernetesDependentResource> getResources() { List<CRUDKubernetesDependentResource> list = new ArrayList<>(Arrays.asList( karavanServiceAccount, karavanRole, karavanRoleBinding, karavanRoleBindingView, karavanPvcData, karavanPvcM2Cache, karavanPvcJbang, diff --git a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/resource/KaravanRole.java b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/resource/KaravanRole.java index 8bf2c52f..40985977 100644 --- a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/resource/KaravanRole.java +++ b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/resource/KaravanRole.java @@ -43,7 +43,8 @@ public class KaravanRole extends CRUDKubernetesDependentResource<Role, Karavan> new PolicyRuleBuilder().withApiGroups("").withResources("secrets", "configmaps").withVerbs("get", "list").build(), new PolicyRuleBuilder().withApiGroups("").withResources("persistentvolumes", "persistentvolumeclaims").withVerbs("get", "list", "watch").build(), new PolicyRuleBuilder().withApiGroups("tekton.dev").withResources("pipelineruns").withVerbs("*").build(), - new PolicyRuleBuilder().withApiGroups("").withResources("pods", "services", "routes", "replicationcontrollers").withVerbs("*").build(), + new PolicyRuleBuilder().withApiGroups("").withResources("pods", "services", "replicationcontrollers").withVerbs("*").build(), + new PolicyRuleBuilder().withApiGroups("route.openshift.io").withResources( "routes").withVerbs("*").build(), new PolicyRuleBuilder().withApiGroups("apps").withResources("deployments").withVerbs("*").build() ) .build(); diff --git a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/spec/KaravanSpec.java b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/spec/KaravanSpec.java index 6ea24684..44c1d83f 100644 --- a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/spec/KaravanSpec.java +++ b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/spec/KaravanSpec.java @@ -25,6 +25,18 @@ public class KaravanSpec { private int nodePort; private String gitPullInterval; + public KaravanSpec() { + } + + public KaravanSpec(int instances, String auth, String environment, String runtimes, int nodePort, String gitPullInterval) { + this.instances = instances; + this.auth = auth; + this.environment = environment; + this.runtimes = runtimes; + this.nodePort = nodePort; + this.gitPullInterval = gitPullInterval; + } + public int getInstances() { return instances; } diff --git a/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerE2E.java b/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerE2E.java new file mode 100644 index 00000000..577e90ca --- /dev/null +++ b/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerE2E.java @@ -0,0 +1,146 @@ +package org.apache.camel.karavan.operator; + +import io.fabric8.kubernetes.api.model.*; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.rbac.Role; +import io.fabric8.kubernetes.api.model.rbac.RoleBinding; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.openshift.api.model.Route; +import io.fabric8.tekton.pipeline.v1beta1.Pipeline; +import io.fabric8.tekton.pipeline.v1beta1.Task; +import org.apache.camel.karavan.operator.spec.Karavan; +import org.apache.camel.karavan.operator.spec.KaravanSpec; +import org.apache.camel.karavan.operator.spec.KaravanStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; + + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static org.awaitility.Awaitility.await; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.jupiter.api.Assertions.*; + +public class KaravanReconcilerE2E { + private static final String DEFAULT_NAMESPACE = "default"; + + KubernetesClient client; + + @BeforeEach + void createKubernetesClient() { + client = new KubernetesClientBuilder().build(); + } + private Karavan buildKaravan() { + var karavan = new Karavan(); + karavan.setMetadata(new ObjectMetaBuilder().withName("karavan").withNamespace(DEFAULT_NAMESPACE).build()); + karavan.setSpec(new KaravanSpec(1, "public", "demo", "quarkus,spring-boot", 30668, "10s")); + + return karavan; + } + + private class Obj { + Class<? extends HasMetadata> type; + String name; + + public Obj(Class<? extends HasMetadata> type, String name) { + this.type = type; + this.name = name; + } + } + + private List<Obj> getResources() { + var array = new ArrayList<>(Arrays.asList( + new Obj(Deployment.class, "karavan"), + new Obj(Service.class, "karavan"), + new Obj(ServiceAccount.class, "karavan"), + new Obj(Role.class, "karavan"), + new Obj(RoleBinding.class, "karavan"), + new Obj(RoleBinding.class, "karavan-view"), + new Obj(PersistentVolumeClaim.class, "karavan-data"), + new Obj(PersistentVolumeClaim.class, "karavan-m2-cache"), + new Obj(PersistentVolumeClaim.class, "karavan-jbang-cache") + )); + if (Utils.isOpenShift(client)) { + array.add(new Obj(Route.class, "karavan")); + } + return array; + } + + private List<Obj> getTektonResources() { + var array = new ArrayList<>(Arrays.asList( + new Obj(Task.class, "karavan-task-dev-quarkus"), + new Obj(Task.class, "karavan-task-dev-spring-boot"), + new Obj(Pipeline.class, "karavan-pipeline-dev-quarkus"), + new Obj(Pipeline.class, "karavan-pipeline-dev-spring-boot"), + new Obj(ServiceAccount.class, "pipeline"), + new Obj(Role.class, "deployer"), + new Obj(RoleBinding.class, "pipeline-deployer") + )); + if (Utils.isOpenShift(client)) { + array.add(new Obj(Route.class, "karavan")); + } + return array; + } + + private void deleteKaravan(Karavan karavan) { + client.resources(Karavan.class).inNamespace(DEFAULT_NAMESPACE).withName(karavan.getMetadata().getName()).delete(); + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + getResources().forEach(c -> assertNull(client.resources(c.type).inNamespace(DEFAULT_NAMESPACE).withName(c.name).get())); + }); + } + + @Test + @Order(1) + void basicOperatorTest() { + var karavan = buildKaravan(); + client.resource(karavan).create(); + + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + Karavan updatedKaravan = client.resources(Karavan.class).inNamespace(DEFAULT_NAMESPACE).withName("karavan").get(); + assertThat(updatedKaravan.getStatus(), is(notNullValue())); + assertThat(updatedKaravan.getStatus().getState(), is(KaravanStatus.State.READY)); + }); + + getResources().forEach(c -> assertNotNull(client.resources(c.type).inNamespace(DEFAULT_NAMESPACE).withName(c.name).get())); + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + var deployment = client.resources(Deployment.class).inNamespace(DEFAULT_NAMESPACE).withName("karavan").get(); + assertNotNull(deployment); + assertEquals(deployment.getSpec().getReplicas(), deployment.getStatus().getAvailableReplicas()); + }); + + deleteKaravan(karavan); + } + + @Test + @Order(2) + void installTektonTest() throws FileNotFoundException { + var karavan = buildKaravan(); + client.resource(karavan).create(); + + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + Karavan updatedKaravan = client.resources(Karavan.class).inNamespace(DEFAULT_NAMESPACE).withName("karavan").get(); + assertThat(updatedKaravan.getStatus(), is(notNullValue())); + assertThat(updatedKaravan.getStatus().getState(), is(KaravanStatus.State.READY)); + }); + + client.resource(new FileInputStream("src/test/resources/kubernetes/pipelines.yaml")).create(); + client.resource(new FileInputStream("src/test/resources/kubernetes/tasks.yaml")).create(); + + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + getTektonResources().forEach(c -> assertNotNull(client.resources(c.type).inNamespace(DEFAULT_NAMESPACE).withName(c.name).get())); + }); + + deleteKaravan(karavan); + client.resource(new FileInputStream("src/test/resources/kubernetes/pipelines.yaml")).delete(); + client.resource(new FileInputStream("src/test/resources/kubernetes/tasks.yaml")).delete(); + } +} diff --git a/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerTest.java b/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerTest.java new file mode 100644 index 00000000..c407f0fb --- /dev/null +++ b/karavan-operator/src/test/java/org/apache/camel/karavan/operator/KaravanReconcilerTest.java @@ -0,0 +1,65 @@ +package org.apache.camel.karavan.operator; + +import io.fabric8.kubernetes.api.model.Namespace; +import io.fabric8.kubernetes.api.model.NamespaceBuilder; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.javaoperatorsdk.operator.Operator; +import io.quarkus.test.junit.QuarkusTest; +import org.apache.camel.karavan.operator.spec.Karavan; +import org.apache.camel.karavan.operator.spec.KaravanSpec; +import org.apache.camel.karavan.operator.spec.KaravanStatus; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import javax.inject.Inject; + +import static org.awaitility.Awaitility.await; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.CoreMatchers.is; +import static java.util.concurrent.TimeUnit.MINUTES; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; + +@QuarkusTest +public class KaravanReconcilerTest { + private static final String KARAVAN_OPERATOR_TEST_NAMESPACE = "karavan-operator-test"; + + @Inject + Operator operator; + + @Inject + KubernetesClient client; + + @BeforeAll + static void initNamespace() { + new KubernetesClientBuilder().build().resource(new NamespaceBuilder().withNewMetadata().withName(KARAVAN_OPERATOR_TEST_NAMESPACE).endMetadata().build()).create(); + } + + @AfterAll + static void cleanupNamespace() { + var client = new KubernetesClientBuilder().build(); + client.resources(Namespace.class).withName(KARAVAN_OPERATOR_TEST_NAMESPACE).delete(); + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> assertNull(client.resources(Namespace.class).withName(KARAVAN_OPERATOR_TEST_NAMESPACE).get())); + } + + @Test + void basicReconcile() { + var karavan = new Karavan(); + karavan.setMetadata(new ObjectMetaBuilder().withName("karavan").withNamespace(KARAVAN_OPERATOR_TEST_NAMESPACE).build()); + karavan.setSpec(new KaravanSpec(1, "public", "demo", "quarkus,spring-boot", 30668, "10s")); + + operator.start(); + client.resource(karavan).create(); + + await().atMost(5, MINUTES).ignoreExceptions().untilAsserted(() -> { + Karavan updatedKaravan = client.resources(Karavan.class).inNamespace(KARAVAN_OPERATOR_TEST_NAMESPACE).withName("karavan").get(); + assertThat(updatedKaravan.getStatus(), is(notNullValue())); + assertThat(updatedKaravan.getStatus().getState(), is(KaravanStatus.State.READY)); + }); + + operator.stop(); + } +} diff --git a/karavan-operator/src/test/resources/application.properties b/karavan-operator/src/test/resources/application.properties new file mode 100644 index 00000000..87034dc2 --- /dev/null +++ b/karavan-operator/src/test/resources/application.properties @@ -0,0 +1,3 @@ +# Predefined designtime namespace for operator testing in Kubernetes cluster +quarkus.operator-sdk.namespaces=karavan-operator-test + diff --git a/karavan-operator/src/test/resources/kubernetes/kubernetes.yaml b/karavan-operator/src/test/resources/kubernetes/kubernetes.yaml new file mode 100644 index 00000000..4163d8fd --- /dev/null +++ b/karavan-operator/src/test/resources/kubernetes/kubernetes.yaml @@ -0,0 +1,202 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: camel-karavan-operator +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: camel-karavan-operator + name: camel-karavan-operator + namespace: camel-karavan-operator +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: camel-karavan-operator + template: + metadata: + labels: + app.kubernetes.io/name: camel-karavan-operator + namespace: camel-karavan-operator + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + image: controller:latest + imagePullPolicy: Never + livenessProbe: + failureThreshold: 3 + httpGet: + path: /q/health/live + port: http + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 10 + name: camel-karavan-operator + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /q/health/ready + port: http + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 10 + resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 250m + memory: 256Mi + restartPolicy: Always + serviceAccountName: camel-karavan-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: camel-karavan-operator-cluster-role + namespace: camel-karavan-operator +rules: + - apiGroups: + - camel.apache.org + resources: + - karavans + - karavans/status + - karavans/finalizers + verbs: + - "*" + - apiGroups: + - apps + resources: + - deployments + verbs: + - "*" + - apiGroups: + - route.openshift.io + resources: + - routes + - routes/custom-host + verbs: + - "*" + - apiGroups: + - "" + resources: + - pods + - serviceaccounts + - deployments + - services + - persistentvolumes + - persistentvolumeclaims + - replicationcontrollers + verbs: + - "*" + - apiGroups: + - tekton.dev + resources: + - pipelinetasks + - pipelines + - pipelineruns + - tasks + verbs: + - "*" + - apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings + - clusterroles + verbs: + - "*" + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - "*" + - apiGroups: + - networking.k8s.io + resources: + - customresourcedefinitions + - customresourcedefinitions/status + verbs: + - get + - list + - apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - "*" + - apiGroups: + - policy + resources: + - poddisruptionbudgets + - poddisruptionbudgets/status + verbs: + - "*" +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: camel-karavan-operator + name: camel-karavan-operator + namespace: camel-karavan-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: camel-karavan-operator-cluser-role-binding-view + namespace: camel-karavan-operator +roleRef: + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io + name: view +subjects: + - kind: ServiceAccount + name: camel-karavan-operator + namespace: camel-karavan-operator +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: camel-karavan-operator + name: camel-karavan-operator + namespace: camel-karavan-operator +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 8080 + selector: + app.kubernetes.io/name: camel-karavan-operator + type: ClusterIP +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: camel-karavan-operator-cluster-role-binding +roleRef: + kind: ClusterRole + apiGroup: rbac.authorization.k8s.io + name: camel-karavan-operator-cluster-role +subjects: + - kind: ServiceAccount + name: camel-karavan-operator + namespace: camel-karavan-operator diff --git a/karavan-operator/src/test/resources/kubernetes/pipelines.yaml b/karavan-operator/src/test/resources/kubernetes/pipelines.yaml new file mode 100644 index 00000000..bab0d843 --- /dev/null +++ b/karavan-operator/src/test/resources/kubernetes/pipelines.yaml @@ -0,0 +1,40 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines + pipeline.tekton.dev/release: devel + version: devel + name: pipelines.tekton.dev +spec: + group: tekton.dev + names: + categories: + - tekton + - tekton-pipelines + kind: Pipeline + listKind: PipelineList + plural: pipelines + singular: pipeline + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + served: true + storage: true + subresources: + status: {} + - name: v1 + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + served: true + storage: false + subresources: + status: {} + diff --git a/karavan-operator/src/test/resources/kubernetes/tasks.yaml b/karavan-operator/src/test/resources/kubernetes/tasks.yaml new file mode 100644 index 00000000..58f97a2a --- /dev/null +++ b/karavan-operator/src/test/resources/kubernetes/tasks.yaml @@ -0,0 +1,73 @@ +# Copyright 2019 The Tekton Authors +# +# 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 +# +# https://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: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: tasks.tekton.dev + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines + pipeline.tekton.dev/release: "devel" + version: "devel" +spec: + group: tekton.dev + preserveUnknownFields: false + versions: + - name: v1beta1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + # One can use x-kubernetes-preserve-unknown-fields: true + # at the root of the schema (and inside any properties, additionalProperties) + # to get the traditional CRD behaviour that nothing is pruned, despite + # setting spec.preserveUnknownProperties: false. + # + # See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/ + # See issue: https://github.com/knative/serving/issues/912 + x-kubernetes-preserve-unknown-fields: true + # Opt into the status subresource so metadata.generation + # starts to increment + subresources: + status: {} + - name: v1 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + # TODO(#1461): Add OpenAPIV3 schema + # OpenAPIV3 schema allows Kubernetes to perform validation on the schema fields + # and use the schema in tooling such as `kubectl explain`. + # Using "x-kubernetes-preserve-unknown-fields: true" + # at the root of the schema (or within it) allows arbitrary fields. + # We currently perform our own validation separately. + # See https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema + # for more info. + x-kubernetes-preserve-unknown-fields: true + # Opt into the status subresource so metadata.generation + # starts to increment + subresources: + status: {} + names: + kind: Task + plural: tasks + singular: task + categories: + - tekton + - tekton-pipelines + scope: Namespaced +