From 97ba06f9d8a027261306621813d6702a96f0e25d Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 8 Dec 2022 12:16:28 +0100 Subject: [PATCH 01/21] feat: E2E improvements --- .../src/main/resources/application.properties | 0 .../spring-boot/src/main/resources/kubernetes/common.yml | 8 -------- 2 files changed, 8 deletions(-) rename samples/{spring-boot => commons}/src/main/resources/application.properties (100%) delete mode 100644 samples/spring-boot/src/main/resources/kubernetes/common.yml diff --git a/samples/spring-boot/src/main/resources/application.properties b/samples/commons/src/main/resources/application.properties similarity index 100% rename from samples/spring-boot/src/main/resources/application.properties rename to samples/commons/src/main/resources/application.properties diff --git a/samples/spring-boot/src/main/resources/kubernetes/common.yml b/samples/spring-boot/src/main/resources/kubernetes/common.yml deleted file mode 100644 index 3c76a673..00000000 --- a/samples/spring-boot/src/main/resources/kubernetes/common.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: pkcs12-pass -data: - password: c3VwZXJzZWNyZXQ= -type: Opaque From 490be20ce20379c26f921acdcb4175a0402f9877 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 8 Dec 2022 12:26:20 +0100 Subject: [PATCH 02/21] put back application properties --- .../src/main/resources/application.properties | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/{commons => spring-boot}/src/main/resources/application.properties (100%) diff --git a/samples/commons/src/main/resources/application.properties b/samples/spring-boot/src/main/resources/application.properties similarity index 100% rename from samples/commons/src/main/resources/application.properties rename to samples/spring-boot/src/main/resources/application.properties From 636d4db87e42c575557c61cdedfc1b53c7bcaf0f Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 8 Dec 2022 13:07:39 +0100 Subject: [PATCH 03/21] put back common yaml --- pom.xml | 5 ++++ samples/quarkus/pom.xml | 12 ++++++++ .../src/main/resources/application.properties | 29 +++++++++++++++++++ .../src/main/resources/kubernetes/common.yaml | 8 +++++ 4 files changed, 54 insertions(+) create mode 100644 samples/spring-boot/src/main/resources/kubernetes/common.yaml diff --git a/pom.xml b/pom.xml index 0386f69e..25454665 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,11 @@ certmanager-annotations ${dekorate.version} + + io.dekorate + kubernetes-annotations + ${dekorate.version} + io.dekorate jib-annotations diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index b4b97203..303809e5 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -69,6 +69,18 @@ org.jboss.resteasy resteasy-jackson2-provider + + io.dekorate + kubernetes-annotations + + + io.dekorate + certmanager-annotations + + + io.dekorate + jib-annotations + io.javaoperatorsdk.admissioncontroller.sample sample-commons diff --git a/samples/quarkus/src/main/resources/application.properties b/samples/quarkus/src/main/resources/application.properties index e69de29b..696325d9 100644 --- a/samples/quarkus/src/main/resources/application.properties +++ b/samples/quarkus/src/main/resources/application.properties @@ -0,0 +1,29 @@ +server.port=443 +server.ssl.enabled=true +server.ssl.key-store-type=PKCS12 +## Container +dekorate.jib.from=openjdk:11 +## To include the keystore secret +dekorate.options.input-path=kubernetes + +## To generate the Certificate and the Issuer resources +dekorate.certificate.secret-name=tls-secret +dekorate.certificate.dnsNames=quarkus-sample.test.svc,localhost +dekorate.certificate.self-signed.enabled=true +dekorate.certificate.subject.organizations=Dekorate,Community +dekorate.certificate.duration=2160h0m0s +dekorate.certificate.renewBefore=360h0m0s +dekorate.certificate.privateKey.algorithm=RSA +dekorate.certificate.privateKey.encoding=PKCS8 +dekorate.certificate.privateKey.size=2048 +dekorate.certificate.keystores.pkcs12.create=true +dekorate.certificate.keystores.pkcs12.passwordSecretRef.name=pkcs12-pass +dekorate.certificate.keystores.pkcs12.passwordSecretRef.key=password +dekorate.certificate.usages=server auth,client auth + +## To configure the application for using the generated Certificate and Issuer resources +dekorate.kubernetes.env-vars[0].name=SERVER_SSL_KEY_STORE +dekorate.kubernetes.env-vars[0].value=/etc/certs/keystore.p12 +dekorate.kubernetes.env-vars[1].name=SERVER_SSL_KEY_STORE_PASSWORD +dekorate.kubernetes.env-vars[1].secret=pkcs12-pass +dekorate.kubernetes.env-vars[1].value=password \ No newline at end of file diff --git a/samples/spring-boot/src/main/resources/kubernetes/common.yaml b/samples/spring-boot/src/main/resources/kubernetes/common.yaml new file mode 100644 index 00000000..336ec2fe --- /dev/null +++ b/samples/spring-boot/src/main/resources/kubernetes/common.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: pkcs12-pass +data: + password: c3VwZXJzZWNyZXQ= +type: Opaque \ No newline at end of file From e9f1478e296905147cadd4113eaff19ecc561d27 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 8 Dec 2022 13:18:10 +0100 Subject: [PATCH 04/21] wip --- samples/quarkus/pom.xml | 4 ++++ samples/quarkus/src/main/resources/kubernetes/common.yaml | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 samples/quarkus/src/main/resources/kubernetes/common.yaml diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index 303809e5..5519a4f0 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -69,6 +69,10 @@ org.jboss.resteasy resteasy-jackson2-provider + + io.quarkus + quarkus-kubernetes + io.dekorate kubernetes-annotations diff --git a/samples/quarkus/src/main/resources/kubernetes/common.yaml b/samples/quarkus/src/main/resources/kubernetes/common.yaml new file mode 100644 index 00000000..336ec2fe --- /dev/null +++ b/samples/quarkus/src/main/resources/kubernetes/common.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: pkcs12-pass +data: + password: c3VwZXJzZWNyZXQ= +type: Opaque \ No newline at end of file From cd540944b05d5a11f75b77af1a2bd1760f3bd67e Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 8 Dec 2022 14:02:38 +0100 Subject: [PATCH 05/21] issue with cert manager quarkus --- samples/quarkus/pom.xml | 13 +++------- .../src/main/resources/application.properties | 26 +++++++++---------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index 5519a4f0..3caa77fe 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -74,16 +74,9 @@ quarkus-kubernetes - io.dekorate - kubernetes-annotations - - - io.dekorate - certmanager-annotations - - - io.dekorate - jib-annotations + io.quarkiverse.certmanager + quarkus-certmanager + 0.0.2 io.javaoperatorsdk.admissioncontroller.sample diff --git a/samples/quarkus/src/main/resources/application.properties b/samples/quarkus/src/main/resources/application.properties index 696325d9..e707b53c 100644 --- a/samples/quarkus/src/main/resources/application.properties +++ b/samples/quarkus/src/main/resources/application.properties @@ -7,19 +7,19 @@ dekorate.jib.from=openjdk:11 dekorate.options.input-path=kubernetes ## To generate the Certificate and the Issuer resources -dekorate.certificate.secret-name=tls-secret -dekorate.certificate.dnsNames=quarkus-sample.test.svc,localhost -dekorate.certificate.self-signed.enabled=true -dekorate.certificate.subject.organizations=Dekorate,Community -dekorate.certificate.duration=2160h0m0s -dekorate.certificate.renewBefore=360h0m0s -dekorate.certificate.privateKey.algorithm=RSA -dekorate.certificate.privateKey.encoding=PKCS8 -dekorate.certificate.privateKey.size=2048 -dekorate.certificate.keystores.pkcs12.create=true -dekorate.certificate.keystores.pkcs12.passwordSecretRef.name=pkcs12-pass -dekorate.certificate.keystores.pkcs12.passwordSecretRef.key=password -dekorate.certificate.usages=server auth,client auth +quarkus.certificate.secret-name=tls-secret +quarkus.certificate.dns-names=quarkus-sample.test.svc,localhost +quarkus.certificate.self-signed.enabled=true +quarkus.certificate.subject.organizations=Dekorate,Community +quarkus.certificate.duration=2160h0m0s +quarkus.certificate.renewBefore=360h0m0s +quarkus.certificate.privateKey.algorithm=RSA +quarkus.certificate.privateKey.encoding=PKCS8 +quarkus.certificate.privateKey.size=2048 +quarkus.certificate.keystores.pkcs12.create=true +quarkus.certificate.keystores.pkcs12.password-secret-ref.name=pkcs12-pass +quarkus.certificate.keystores.pkcs12.password-secret-ref.key=password +quarkus.certificate.usages=server auth,client auth ## To configure the application for using the generated Certificate and Issuer resources dekorate.kubernetes.env-vars[0].name=SERVER_SSL_KEY_STORE From 9f815593b91b0cfeb3cc7b915263b55b807be02a Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 13 Dec 2022 10:11:30 +0100 Subject: [PATCH 06/21] fix generated resources --- samples/quarkus/src/main/resources/application.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/quarkus/src/main/resources/application.properties b/samples/quarkus/src/main/resources/application.properties index e707b53c..53f20ada 100644 --- a/samples/quarkus/src/main/resources/application.properties +++ b/samples/quarkus/src/main/resources/application.properties @@ -13,9 +13,9 @@ quarkus.certificate.self-signed.enabled=true quarkus.certificate.subject.organizations=Dekorate,Community quarkus.certificate.duration=2160h0m0s quarkus.certificate.renewBefore=360h0m0s -quarkus.certificate.privateKey.algorithm=RSA -quarkus.certificate.privateKey.encoding=PKCS8 -quarkus.certificate.privateKey.size=2048 +quarkus.certificate.private-key.algorithm=RSA +quarkus.certificate.private-key.encoding=PKCS8 +quarkus.certificate.private-key.size=2048 quarkus.certificate.keystores.pkcs12.create=true quarkus.certificate.keystores.pkcs12.password-secret-ref.name=pkcs12-pass quarkus.certificate.keystores.pkcs12.password-secret-ref.key=password From 6be9bdc11843ded448a6215e0cf2f54761c88570 Mon Sep 17 00:00:00 2001 From: csviri Date: Tue, 13 Dec 2022 17:13:45 +0100 Subject: [PATCH 07/21] wip --- samples/quarkus/pom.xml | 18 +++++---- .../common.yaml => kubernetes/common.yml} | 0 .../src/main/resources/application.properties | 18 ++------- .../admission/AdmissionControllerE2E.java | 37 +++++++++++++++++++ 4 files changed, 52 insertions(+), 21 deletions(-) rename samples/quarkus/src/main/{resources/kubernetes/common.yaml => kubernetes/common.yml} (100%) create mode 100644 samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index 3caa77fe..ea567eb9 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -46,8 +46,8 @@ ${project.version} - io.fabric8 kubernetes-client + io.fabric8 @@ -55,6 +55,10 @@ io.quarkus quarkus-kubernetes-client + + io.quarkus + quarkus-container-image-jib + io.quarkus quarkus-junit5 @@ -82,12 +86,12 @@ io.javaoperatorsdk.admissioncontroller.sample sample-commons ${project.version} - - - io.fabric8 - kubernetes-client - - + + + kubernetes-client + io.fabric8 + + diff --git a/samples/quarkus/src/main/resources/kubernetes/common.yaml b/samples/quarkus/src/main/kubernetes/common.yml similarity index 100% rename from samples/quarkus/src/main/resources/kubernetes/common.yaml rename to samples/quarkus/src/main/kubernetes/common.yml diff --git a/samples/quarkus/src/main/resources/application.properties b/samples/quarkus/src/main/resources/application.properties index 53f20ada..0713c783 100644 --- a/samples/quarkus/src/main/resources/application.properties +++ b/samples/quarkus/src/main/resources/application.properties @@ -1,10 +1,6 @@ -server.port=443 -server.ssl.enabled=true -server.ssl.key-store-type=PKCS12 -## Container -dekorate.jib.from=openjdk:11 -## To include the keystore secret -dekorate.options.input-path=kubernetes +quarkus.http.port=443 + +quarkus.kubernetes.image-pull-policy=IfNotPresent ## To generate the Certificate and the Issuer resources quarkus.certificate.secret-name=tls-secret @@ -12,7 +8,7 @@ quarkus.certificate.dns-names=quarkus-sample.test.svc,localhost quarkus.certificate.self-signed.enabled=true quarkus.certificate.subject.organizations=Dekorate,Community quarkus.certificate.duration=2160h0m0s -quarkus.certificate.renewBefore=360h0m0s +quarkus.certificate.renew-before=360h0m0s quarkus.certificate.private-key.algorithm=RSA quarkus.certificate.private-key.encoding=PKCS8 quarkus.certificate.private-key.size=2048 @@ -21,9 +17,3 @@ quarkus.certificate.keystores.pkcs12.password-secret-ref.name=pkcs12-pass quarkus.certificate.keystores.pkcs12.password-secret-ref.key=password quarkus.certificate.usages=server auth,client auth -## To configure the application for using the generated Certificate and Issuer resources -dekorate.kubernetes.env-vars[0].name=SERVER_SSL_KEY_STORE -dekorate.kubernetes.env-vars[0].value=/etc/certs/keystore.p12 -dekorate.kubernetes.env-vars[1].name=SERVER_SSL_KEY_STORE_PASSWORD -dekorate.kubernetes.env-vars[1].secret=pkcs12-pass -dekorate.kubernetes.env-vars[1].value=password \ No newline at end of file diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java new file mode 100644 index 00000000..0ae50794 --- /dev/null +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -0,0 +1,37 @@ +package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; + +@Disabled +class AdmissionControllerE2E { + + @BeforeAll + static void deployService() throws IOException { + try (KubernetesClient client = new KubernetesClientBuilder().build(); + FileInputStream fileInputStream = new FileInputStream("target/kubernetes.yml"); + InputStream certManager = + new URL( + "https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml") + .openStream();) { + client.resourceList(client.load(fileInputStream).get()).createOrReplace(); + } + } + + @Test + void testValidationHook() { + + + } + + +} From 11241c851daeedea59d534d8acac4046630d6033 Mon Sep 17 00:00:00 2001 From: csviri Date: Wed, 14 Dec 2022 11:32:32 +0100 Subject: [PATCH 08/21] refactor to use ingress in tests instead of pods --- delme.yaml | 18 ++++ .../sample/commons/AdmissionControllers.java | 33 +++--- .../src/main/resources/admission-request.json | 102 +++++------------- .../k8s/mutating-webhook-configuration.yml | 22 ++++ .../k8s/validating-webhook-configuration.yml | 22 ++++ .../admission/AdmissionControllerConfig.java | 10 +- .../quarkus/admission/AdmissionEndpoint.java | 18 ++-- .../admission/AdditionalAdmissionConfig.java | 10 +- .../AdmissionAdditionalTestEndpoint.java | 18 ++-- .../admission/AdmissionControllerE2E.java | 50 ++++++++- .../admission/AdmissionEndpointTest.java | 2 +- .../k8s/mutating-webhook-configuration.yml | 2 +- .../k8s/validating-webhook-configuration.yml | 2 +- .../springboot/admission/AdmissionConfig.java | 10 +- .../admission/AdmissionEndpoint.java | 18 ++-- .../admission/AdditionalAdmissionConfig.java | 10 +- .../AdmissionAdditionalTestEndpoint.java | 18 ++-- .../admission/AdmissionEndpointTest.java | 2 +- 18 files changed, 210 insertions(+), 157 deletions(-) create mode 100644 delme.yaml create mode 100644 samples/quarkus/k8s/mutating-webhook-configuration.yml create mode 100644 samples/quarkus/k8s/validating-webhook-configuration.yml diff --git a/delme.yaml b/delme.yaml new file mode 100644 index 00000000..a96a21e4 --- /dev/null +++ b/delme.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: minimal-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx-example + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 \ No newline at end of file diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java index d062a3dc..b8d7c07c 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java @@ -3,7 +3,7 @@ import java.util.HashMap; import java.util.concurrent.CompletableFuture; -import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.javaoperatorsdk.webhook.admission.NotAllowedException; @@ -15,18 +15,19 @@ public class AdmissionControllers { public static final String ERROR_MESSAGE = "Some error happened"; public static final String APP_NAME_LABEL_KEY = "app.kubernetes.io/name"; + public static final String ANOTHER_LABEL_TO_ADD = "app.kubernetes.io/id"; - public static AdmissionController mutatingController() { + public static AdmissionController mutatingController() { return new AdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null) { resource.getMetadata().setLabels(new HashMap<>()); } - resource.getMetadata().getLabels().putIfAbsent(APP_NAME_LABEL_KEY, "mutation-test"); + resource.getMetadata().getLabels().putIfAbsent(ANOTHER_LABEL_TO_ADD, "mutation-test"); return resource; }); } - public static AdmissionController validatingController() { + public static AdmissionController validatingController() { return new AdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null || resource.getMetadata().getLabels().get(APP_NAME_LABEL_KEY) == null) { @@ -35,18 +36,18 @@ public static AdmissionController validatingController() { }); } - public static AsyncAdmissionController asyncMutatingController() { + public static AsyncAdmissionController asyncMutatingController() { return new AsyncAdmissionController<>( - (AsyncMutator) (resource, operation) -> CompletableFuture.supplyAsync(() -> { + (AsyncMutator) (resource, operation) -> CompletableFuture.supplyAsync(() -> { if (resource.getMetadata().getLabels() == null) { resource.getMetadata().setLabels(new HashMap<>()); } - resource.getMetadata().getLabels().putIfAbsent(APP_NAME_LABEL_KEY, "mutation-test"); + resource.getMetadata().getLabels().putIfAbsent(ANOTHER_LABEL_TO_ADD, "mutation-test"); return resource; })); } - public static AsyncAdmissionController asyncValidatingController() { + public static AsyncAdmissionController asyncValidatingController() { return new AsyncAdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null || resource.getMetadata().getLabels().get(APP_NAME_LABEL_KEY) == null) { @@ -56,26 +57,26 @@ public static AsyncAdmissionController asyncValidatingController() { } - public static AdmissionController errorMutatingController() { - return new AdmissionController<>((Validator) (resource, operation) -> { + public static AdmissionController errorMutatingController() { + return new AdmissionController<>((Validator) (resource, operation) -> { throw new IllegalStateException(ERROR_MESSAGE); }); } - public static AdmissionController errorValidatingController() { - return new AdmissionController<>((Mutator) (resource, operation) -> { + public static AdmissionController errorValidatingController() { + return new AdmissionController<>((Mutator) (resource, operation) -> { throw new IllegalStateException(ERROR_MESSAGE); }); } - public static AsyncAdmissionController errorAsyncMutatingController() { - return new AsyncAdmissionController<>((AsyncMutator) (resource, operation) -> { + public static AsyncAdmissionController errorAsyncMutatingController() { + return new AsyncAdmissionController<>((AsyncMutator) (resource, operation) -> { throw new IllegalStateException(ERROR_MESSAGE); }); } - public static AsyncAdmissionController errorAsyncValidatingController() { - return new AsyncAdmissionController<>((Validator) (resource, operation) -> { + public static AsyncAdmissionController errorAsyncValidatingController() { + return new AsyncAdmissionController<>((Validator) (resource, operation) -> { throw new IllegalStateException(ERROR_MESSAGE); }); } diff --git a/samples/commons/src/main/resources/admission-request.json b/samples/commons/src/main/resources/admission-request.json index 072f583a..244f1f76 100644 --- a/samples/commons/src/main/resources/admission-request.json +++ b/samples/commons/src/main/resources/admission-request.json @@ -25,91 +25,37 @@ ] }, "object": { - "apiVersion": "v1", - "kind": "Pod", + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", "metadata": { - "generateName": "nginx-deployment-6c54bd5869-", - "creationTimestamp": null, - "labels": { - "app": "nginx", - "pod-template-hash": "2710681425" - }, + "name": "minimal-ingress", "annotations": { - "openshift.io/scc": "restricted" - }, - "ownerReferences": [ - { - "apiVersion": "extensions/v1beta1", - "kind": "ReplicaSet", - "name": "nginx-deployment-6c54bd5869", - "uid": "16c2b355-5f5d-11e8-ac91-36e6bb280816", - "controller": true, - "blockOwnerDeletion": true - } - ] + "nginx.ingress.kubernetes.io/rewrite-target": "/" + } }, "spec": { - "volumes": [ - { - "name": "default-token-tq5lq", - "secret": { - "secretName": "default-token-tq5lq" - } - } - ], - "containers": [ + "ingressClassName": "nginx-example", + "rules": [ { - "name": "nginx", - "image": "nginx:1.7.9", - "ports": [ - { - "containerPort": 80, - "protocol": "TCP" - } - ], - "resources": {}, - "volumeMounts": [ - { - "name": "default-token-tq5lq", - "readOnly": true, - "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" - } - ], - "terminationMessagePath": "/dev/termination-log", - "terminationMessagePolicy": "File", - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { - "drop": [ - "KILL", - "MKNOD", - "SETGID", - "SETUID" - ] - }, - "runAsUser": 1000080000 + "http": { + "paths": [ + { + "path": "/testpath", + "pathType": "Prefix", + "backend": { + "service": { + "name": "test", + "port": { + "number": 80 + } + } + } + } + ] } } - ], - "restartPolicy": "Always", - "terminationGracePeriodSeconds": 30, - "dnsPolicy": "ClusterFirst", - "serviceAccountName": "default", - "serviceAccount": "default", - "securityContext": { - "seLinuxOptions": { - "level": "s0:c9,c4" - }, - "fsGroup": 1000080000 - }, - "imagePullSecrets": [ - { - "name": "default-dockercfg-kksdv" - } - ], - "schedulerName": "default-scheduler" - }, - "status": {} + ] + } }, "oldObject": null } diff --git a/samples/quarkus/k8s/mutating-webhook-configuration.yml b/samples/quarkus/k8s/mutating-webhook-configuration.yml new file mode 100644 index 00000000..252e1f38 --- /dev/null +++ b/samples/quarkus/k8s/mutating-webhook-configuration.yml @@ -0,0 +1,22 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: "pod-mutating.quarkus.example.com" + annotations: + cert-manager.io/inject-ca-from: test/spring-boot-sample +webhooks: + - name: "pod-mutating.quarkus.example.com" + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE"] + resources: ["ingresses"] + scope: "Namespaced" + clientConfig: + service: + namespace: "default" + name: "quarkus-sample" + path: "/mutate" + admissionReviewVersions: ["v1"] + sideEffects: None + timeoutSeconds: 5 \ No newline at end of file diff --git a/samples/quarkus/k8s/validating-webhook-configuration.yml b/samples/quarkus/k8s/validating-webhook-configuration.yml new file mode 100644 index 00000000..9dbe5c76 --- /dev/null +++ b/samples/quarkus/k8s/validating-webhook-configuration.yml @@ -0,0 +1,22 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: "pod-policy.quarkus.example.com" + annotations: + cert-manager.io/inject-ca-from: test/spring-boot-sample +webhooks: + - name: "pod-policy.quarkus.example.com" + rules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE"] + resources: ["ingresses"] + scope: "Namespaced" + clientConfig: + service: + namespace: "default" + name: "quarkus-sample" + path: "/validate" + admissionReviewVersions: ["v1"] + sideEffects: None + timeoutSeconds: 5 \ No newline at end of file diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java index 28b09f0d..8fec52b1 100644 --- a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java +++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java @@ -3,7 +3,7 @@ import javax.inject.Named; import javax.inject.Singleton; -import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers; @@ -17,25 +17,25 @@ public class AdmissionControllerConfig { @Singleton @Named(MUTATING_CONTROLLER) - public AdmissionController mutatingController() { + public AdmissionController mutatingController() { return AdmissionControllers.mutatingController(); } @Singleton @Named(VALIDATING_CONTROLLER) - public AdmissionController validatingController() { + public AdmissionController validatingController() { return AdmissionControllers.validatingController(); } @Singleton @Named(ASYNC_MUTATING_CONTROLLER) - public AsyncAdmissionController asyncMutatingController() { + public AsyncAdmissionController asyncMutatingController() { return AdmissionControllers.asyncMutatingController(); } @Singleton @Named(ASYNC_VALIDATING_CONTROLLER) - public AsyncAdmissionController asyncValidatingController() { + public AsyncAdmissionController asyncValidatingController() { return AdmissionControllers.asyncValidatingController(); } } diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java index 7ad6cef4..4f98da38 100644 --- a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java +++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java @@ -5,8 +5,8 @@ import javax.ws.rs.*; import javax.ws.rs.core.MediaType; -import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.smallrye.mutiny.Uni; @@ -19,17 +19,17 @@ public class AdmissionEndpoint { public static final String ASYNC_MUTATE_PATH = "async-mutate"; public static final String ASYNC_VALIDATE_PATH = "async-validate"; - private final AdmissionController mutationController; - private final AdmissionController validationController; - private final AsyncAdmissionController asyncMutationController; - private final AsyncAdmissionController asyncValidationController; + private final AdmissionController mutationController; + private final AdmissionController validationController; + private final AsyncAdmissionController asyncMutationController; + private final AsyncAdmissionController asyncValidationController; @Inject public AdmissionEndpoint( - @Named(AdmissionControllerConfig.MUTATING_CONTROLLER) AdmissionController mutationController, - @Named(AdmissionControllerConfig.VALIDATING_CONTROLLER) AdmissionController validationController, - @Named(AdmissionControllerConfig.ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController asyncMutationController, - @Named(AdmissionControllerConfig.ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController asyncValidationController) { + @Named(AdmissionControllerConfig.MUTATING_CONTROLLER) AdmissionController mutationController, + @Named(AdmissionControllerConfig.VALIDATING_CONTROLLER) AdmissionController validationController, + @Named(AdmissionControllerConfig.ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController asyncMutationController, + @Named(AdmissionControllerConfig.ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController asyncValidationController) { this.mutationController = mutationController; this.validationController = validationController; this.asyncMutationController = asyncMutationController; diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdditionalAdmissionConfig.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdditionalAdmissionConfig.java index c3c16ddb..5969c4d3 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdditionalAdmissionConfig.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdditionalAdmissionConfig.java @@ -3,7 +3,7 @@ import javax.inject.Named; import javax.inject.Singleton; -import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers; @@ -17,25 +17,25 @@ public class AdditionalAdmissionConfig { @Singleton @Named(ERROR_MUTATING_CONTROLLER) - public AdmissionController errorMutatingController() { + public AdmissionController errorMutatingController() { return AdmissionControllers.errorMutatingController(); } @Singleton @Named(ERROR_VALIDATING_CONTROLLER) - public AdmissionController errorValidatingController() { + public AdmissionController errorValidatingController() { return AdmissionControllers.errorValidatingController(); } @Singleton @Named(ERROR_ASYNC_MUTATING_CONTROLLER) - public AsyncAdmissionController errorAsyncMutatingController() { + public AsyncAdmissionController errorAsyncMutatingController() { return AdmissionControllers.errorAsyncMutatingController(); } @Singleton @Named(ERROR_ASYNC_VALIDATING_CONTROLLER) - public AsyncAdmissionController errorAsyncValidatingController() { + public AsyncAdmissionController errorAsyncValidatingController() { return AdmissionControllers.errorAsyncValidatingController(); } } diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionAdditionalTestEndpoint.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionAdditionalTestEndpoint.java index fac1f02d..2b005243 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionAdditionalTestEndpoint.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionAdditionalTestEndpoint.java @@ -8,8 +8,8 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.smallrye.mutiny.Uni; @@ -22,17 +22,17 @@ public class AdmissionAdditionalTestEndpoint { public static final String ERROR_MUTATE_PATH = "error-mutate"; public static final String ERROR_VALIDATE_PATH = "error-validate"; - private final AdmissionController errorMutationController; - private final AdmissionController errorValidationController; - private final AsyncAdmissionController errorAsyncMutationController; - private final AsyncAdmissionController errorAsyncValidationController; + private final AdmissionController errorMutationController; + private final AdmissionController errorValidationController; + private final AsyncAdmissionController errorAsyncMutationController; + private final AsyncAdmissionController errorAsyncValidationController; @Inject public AdmissionAdditionalTestEndpoint( - @Named(AdditionalAdmissionConfig.ERROR_MUTATING_CONTROLLER) AdmissionController errorMutationController, - @Named(AdditionalAdmissionConfig.ERROR_VALIDATING_CONTROLLER) AdmissionController errorValidationController, - @Named(AdditionalAdmissionConfig.ERROR_ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController errorAsyncMutationController, - @Named(AdditionalAdmissionConfig.ERROR_ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController errorAsyncValidationController) { + @Named(AdditionalAdmissionConfig.ERROR_MUTATING_CONTROLLER) AdmissionController errorMutationController, + @Named(AdditionalAdmissionConfig.ERROR_VALIDATING_CONTROLLER) AdmissionController errorValidationController, + @Named(AdditionalAdmissionConfig.ERROR_ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController errorAsyncMutationController, + @Named(AdditionalAdmissionConfig.ERROR_ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController errorAsyncValidationController) { this.errorMutationController = errorMutationController; this.errorValidationController = errorValidationController; this.errorAsyncMutationController = errorAsyncMutationController; diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index 0ae50794..ebf29b50 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -4,34 +4,78 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import io.fabric8.kubernetes.api.model.networking.v1.*; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; @Disabled class AdmissionControllerE2E { + private KubernetesClient client = new KubernetesClientBuilder().build(); + @BeforeAll static void deployService() throws IOException { try (KubernetesClient client = new KubernetesClientBuilder().build(); - FileInputStream fileInputStream = new FileInputStream("target/kubernetes.yml"); InputStream certManager = new URL( "https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml") - .openStream();) { - client.resourceList(client.load(fileInputStream).get()).createOrReplace(); + .openStream()) { + applyAndWait(client, certManager); + applyAndWait(client, "target/kubernetes/kubernetes.yml"); + applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); + applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); } } @Test void testValidationHook() { + var res = client.network().v1().ingresses().resource(ingress("validate-test")).create(); + } + private Ingress ingress(String name) { + return new IngressBuilder() + .withNewMetadata() + .withName(name) + .endMetadata() + .withSpec(new IngressSpecBuilder() + .withIngressClassName("sample") + .withRules(new IngressRuleBuilder() + .withHttp(new HTTPIngressRuleValueBuilder() + .withPaths(new HTTPIngressPathBuilder() + .withPath("/test") + .withBackend(new IngressBackendBuilder() + .withService(new IngressServiceBackendBuilder() + .withName("service") + .withPort(new ServiceBackendPortBuilder() + .withNumber(80) + .build()) + .build()) + .build()) + .build()) + .build()) + .build()) + .build()) + .build(); + } + public static void applyAndWait(KubernetesClient client, String path) { + try (FileInputStream fileInputStream = new FileInputStream(path)) { + applyAndWait(client, fileInputStream); + } catch (IOException e) { + throw new IllegalStateException(e); + } } + public static void applyAndWait(KubernetesClient client, InputStream is) { + var resources = client.load(is).get(); + client.resourceList(resources).createOrReplace(); + client.resourceList(resources).waitUntilReady(2, TimeUnit.MINUTES); + } } diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java index d9d0c5b5..9a9047df 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java @@ -18,7 +18,7 @@ class AdmissionEndpointTest { public static final String MUTATION_RESPONSE = - "{\"apiVersion\":\"admission.k8s.io/v1\",\"kind\":\"AdmissionReview\",\"response\":{\"allowed\":true,\"patch\":\"W3sib3AiOiJhZGQiLCJwYXRoIjoiL21ldGFkYXRhL2xhYmVscy9hcHAua3ViZXJuZXRlcy5pb34xbmFtZSIsInZhbHVlIjoibXV0YXRpb24tdGVzdCJ9XQ==\",\"patchType\":\"JSONPatch\",\"uid\":\"0df28fbd-5f5f-11e8-bc74-36e6bb280816\"}}"; + "{\"apiVersion\":\"admission.k8s.io/v1\",\"kind\":\"AdmissionReview\",\"response\":{\"allowed\":true,\"patch\":\"W3sib3AiOiJhZGQiLCJwYXRoIjoiL21ldGFkYXRhL2xhYmVscyIsInZhbHVlIjp7ImFwcC5rdWJlcm5ldGVzLmlvL2lkIjoibXV0YXRpb24tdGVzdCJ9fV0=\",\"patchType\":\"JSONPatch\",\"uid\":\"0df28fbd-5f5f-11e8-bc74-36e6bb280816\"}}"; public static final String VALIDATE_RESPONSE = "{\"apiVersion\":\"admission.k8s.io/v1\",\"kind\":\"AdmissionReview\",\"response\":{\"allowed\":false,\"status\":{\"apiVersion\":\"v1\",\"kind\":\"Status\",\"code\":403,\"message\":\"Missing label: app.kubernetes.io/name\"},\"uid\":\"0df28fbd-5f5f-11e8-bc74-36e6bb280816\"}}"; diff --git a/samples/spring-boot/k8s/mutating-webhook-configuration.yml b/samples/spring-boot/k8s/mutating-webhook-configuration.yml index fc424d06..9870c54f 100644 --- a/samples/spring-boot/k8s/mutating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/mutating-webhook-configuration.yml @@ -10,7 +10,7 @@ webhooks: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE"] - resources: ["pods"] + resources: ["ingresses"] scope: "Namespaced" clientConfig: service: diff --git a/samples/spring-boot/k8s/validating-webhook-configuration.yml b/samples/spring-boot/k8s/validating-webhook-configuration.yml index dac1c42a..3316fb4a 100644 --- a/samples/spring-boot/k8s/validating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/validating-webhook-configuration.yml @@ -10,7 +10,7 @@ webhooks: - apiGroups: [""] apiVersions: ["v1"] operations: ["CREATE"] - resources: ["pods"] + resources: ["ingresses"] scope: "Namespaced" clientConfig: service: diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java index 42b2f094..9e6d91ba 100644 --- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java +++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java @@ -3,7 +3,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers; @@ -12,22 +12,22 @@ public class AdmissionConfig { @Bean - public AdmissionController mutatingController() { + public AdmissionController mutatingController() { return AdmissionControllers.mutatingController(); } @Bean - public AdmissionController validatingController() { + public AdmissionController validatingController() { return AdmissionControllers.validatingController(); } @Bean - public AsyncAdmissionController asyncMutatingController() { + public AsyncAdmissionController asyncMutatingController() { return AdmissionControllers.asyncMutatingController(); } @Bean - public AsyncAdmissionController asyncValidatingController() { + public AsyncAdmissionController asyncValidatingController() { return AdmissionControllers.asyncValidatingController(); } } diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java index 5e5b7b2a..ebdbfef1 100644 --- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java +++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java @@ -7,8 +7,8 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; -import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; @@ -22,17 +22,17 @@ public class AdmissionEndpoint { public static final String ASYNC_MUTATE_PATH = "async-mutate"; public static final String ASYNC_VALIDATE_PATH = "async-validate"; - private final AdmissionController mutatingController; - private final AdmissionController validatingController; - private final AsyncAdmissionController asyncMutatingController; - private final AsyncAdmissionController asyncValidatingController; + private final AdmissionController mutatingController; + private final AdmissionController validatingController; + private final AsyncAdmissionController asyncMutatingController; + private final AsyncAdmissionController asyncValidatingController; @Autowired public AdmissionEndpoint( - @Qualifier("mutatingController") AdmissionController mutationController, - @Qualifier("validatingController") AdmissionController validatingController, - @Qualifier("asyncMutatingController") AsyncAdmissionController asyncMutatingController, - @Qualifier("asyncValidatingController") AsyncAdmissionController asyncValidatingController) { + @Qualifier("mutatingController") AdmissionController mutationController, + @Qualifier("validatingController") AdmissionController validatingController, + @Qualifier("asyncMutatingController") AsyncAdmissionController asyncMutatingController, + @Qualifier("asyncValidatingController") AsyncAdmissionController asyncValidatingController) { this.mutatingController = mutationController; this.validatingController = validatingController; this.asyncMutatingController = asyncMutatingController; diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdditionalAdmissionConfig.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdditionalAdmissionConfig.java index 7bc198ec..6e20545a 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdditionalAdmissionConfig.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdditionalAdmissionConfig.java @@ -3,7 +3,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers; @@ -12,22 +12,22 @@ public class AdditionalAdmissionConfig { @Bean - public AdmissionController errorMutatingController() { + public AdmissionController errorMutatingController() { return AdmissionControllers.errorMutatingController(); } @Bean - public AdmissionController errorValidatingController() { + public AdmissionController errorValidatingController() { return AdmissionControllers.errorValidatingController(); } @Bean - public AsyncAdmissionController errorAsyncMutatingController() { + public AsyncAdmissionController errorAsyncMutatingController() { return AdmissionControllers.errorAsyncMutatingController(); } @Bean - public AsyncAdmissionController errorAsyncValidatingController() { + public AsyncAdmissionController errorAsyncValidatingController() { return AdmissionControllers.errorAsyncValidatingController(); } } diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionAdditionalTestEndpoint.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionAdditionalTestEndpoint.java index 0b2ba6eb..172e7ff8 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionAdditionalTestEndpoint.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionAdditionalTestEndpoint.java @@ -7,8 +7,8 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; -import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; +import io.fabric8.kubernetes.api.model.networking.v1.Ingress; import io.javaoperatorsdk.webhook.admission.AdmissionController; import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; @@ -22,17 +22,17 @@ public class AdmissionAdditionalTestEndpoint { public static final String ERROR_ASYNC_MUTATE_PATH = "error-async-mutate"; public static final String ERROR_ASYNC_VALIDATE_PATH = "error-async-validate"; - private final AdmissionController errorMutatingController; - private final AdmissionController errorValidatingController; - private final AsyncAdmissionController errorAsyncMutatingController; - private final AsyncAdmissionController errorAsyncValidatingController; + private final AdmissionController errorMutatingController; + private final AdmissionController errorValidatingController; + private final AsyncAdmissionController errorAsyncMutatingController; + private final AsyncAdmissionController errorAsyncValidatingController; @Autowired public AdmissionAdditionalTestEndpoint( - @Qualifier("errorMutatingController") AdmissionController errorMutatingController, - @Qualifier("errorValidatingController") AdmissionController errorValidatingController, - @Qualifier("errorAsyncMutatingController") AsyncAdmissionController errorAsyncMutatingController, - @Qualifier("errorAsyncValidatingController") AsyncAdmissionController errorAsyncValidatingController) { + @Qualifier("errorMutatingController") AdmissionController errorMutatingController, + @Qualifier("errorValidatingController") AdmissionController errorValidatingController, + @Qualifier("errorAsyncMutatingController") AsyncAdmissionController errorAsyncMutatingController, + @Qualifier("errorAsyncValidatingController") AsyncAdmissionController errorAsyncValidatingController) { this.errorMutatingController = errorMutatingController; this.errorValidatingController = errorValidatingController; this.errorAsyncMutatingController = errorAsyncMutatingController; diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java index 505d27e3..07fcd378 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java @@ -77,7 +77,7 @@ public void testMutate(String path) { .body(request()) .exchange() .expectStatus().isOk().expectBody().json( - "{\"apiVersion\":\"admission.k8s.io/v1\",\"kind\":\"AdmissionReview\",\"response\":{\"allowed\":true,\"patch\":\"W3sib3AiOiJhZGQiLCJwYXRoIjoiL21ldGFkYXRhL2xhYmVscy9hcHAua3ViZXJuZXRlcy5pb34xbmFtZSIsInZhbHVlIjoibXV0YXRpb24tdGVzdCJ9XQ==\",\"patchType\":\"JSONPatch\",\"uid\":\"0df28fbd-5f5f-11e8-bc74-36e6bb280816\"}}"); + "{\"apiVersion\":\"admission.k8s.io/v1\",\"kind\":\"AdmissionReview\",\"response\":{\"allowed\":true,\"patch\":\"W3sib3AiOiJhZGQiLCJwYXRoIjoiL21ldGFkYXRhL2xhYmVscyIsInZhbHVlIjp7ImFwcC5rdWJlcm5ldGVzLmlvL2lkIjoibXV0YXRpb24tdGVzdCJ9fV0=\",\"patchType\":\"JSONPatch\",\"uid\":\"0df28fbd-5f5f-11e8-bc74-36e6bb280816\"}}"); } public void testValidate(String path) { From e2193c0f3ac422e03a0147948813075b835db1c6 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 11:18:11 +0100 Subject: [PATCH 09/21] wip --- .github/workflows/pr.yml | 3 +- delme.yaml | 1 + .../sample/commons/AdmissionControllers.java | 16 +-- .../webhook/sample/commons/Utils.java | 61 ++++++++++ samples/manual-test.http | 104 +++++------------- .../k8s/mutating-webhook-configuration.yml | 11 +- .../k8s/validating-webhook-configuration.yml | 11 +- samples/quarkus/pom.xml | 9 ++ .../src/main/resources/application.properties | 7 +- .../admission/AdmissionControllerE2E.java | 67 ++++------- .../k8s/mutating-webhook-configuration.yml | 8 +- .../k8s/validating-webhook-configuration.yml | 8 +- samples/spring-boot/pom.xml | 2 +- .../src/main/resources/application.properties | 4 +- .../admission/AdmissionControllerE2E.java | 61 ++++++++++ 15 files changed, 218 insertions(+), 155 deletions(-) create mode 100644 samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java create mode 100644 samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 89729ae3..5c70406e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -68,7 +68,8 @@ jobs: kubectl config set-context --current --namespace=test # Generate manifests and image - cd samples/spring-boot + cd samples/spring-boot + # ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -Ddekorate.jib.group=test -DskipTests ./mvnw ${MAVEN_ARGS} clean install -Ddekorate.jib.registry=$KIND_REGISTRY -Ddekorate.jib.group=tests -Ddekorate.jib.version=latest -Ddekorate.jib.autoPushEnabled=true -DskipTests # Install manifests diff --git a/delme.yaml b/delme.yaml index a96a21e4..d4f7252a 100644 --- a/delme.yaml +++ b/delme.yaml @@ -1,3 +1,4 @@ +# TODO del this apiVersion: networking.k8s.io/v1 kind: Ingress metadata: diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java index b8d7c07c..c4a70e7b 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/AdmissionControllers.java @@ -14,15 +14,15 @@ public class AdmissionControllers { public static final String ERROR_MESSAGE = "Some error happened"; - public static final String APP_NAME_LABEL_KEY = "app.kubernetes.io/name"; - public static final String ANOTHER_LABEL_TO_ADD = "app.kubernetes.io/id"; + public static final String VALIDATION_TARGET_LABEL = "app.kubernetes.io/name"; + public static final String MUTATION_TARGET_LABEL = "app.kubernetes.io/id"; public static AdmissionController mutatingController() { return new AdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null) { resource.getMetadata().setLabels(new HashMap<>()); } - resource.getMetadata().getLabels().putIfAbsent(ANOTHER_LABEL_TO_ADD, "mutation-test"); + resource.getMetadata().getLabels().putIfAbsent(MUTATION_TARGET_LABEL, "mutation-test"); return resource; }); } @@ -30,8 +30,8 @@ public static AdmissionController mutatingController() { public static AdmissionController validatingController() { return new AdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null - || resource.getMetadata().getLabels().get(APP_NAME_LABEL_KEY) == null) { - throw new NotAllowedException("Missing label: " + APP_NAME_LABEL_KEY); + || resource.getMetadata().getLabels().get(VALIDATION_TARGET_LABEL) == null) { + throw new NotAllowedException("Missing label: " + VALIDATION_TARGET_LABEL); } }); } @@ -42,7 +42,7 @@ public static AsyncAdmissionController asyncMutatingController() { if (resource.getMetadata().getLabels() == null) { resource.getMetadata().setLabels(new HashMap<>()); } - resource.getMetadata().getLabels().putIfAbsent(ANOTHER_LABEL_TO_ADD, "mutation-test"); + resource.getMetadata().getLabels().putIfAbsent(MUTATION_TARGET_LABEL, "mutation-test"); return resource; })); } @@ -50,8 +50,8 @@ public static AsyncAdmissionController asyncMutatingController() { public static AsyncAdmissionController asyncValidatingController() { return new AsyncAdmissionController<>((resource, operation) -> { if (resource.getMetadata().getLabels() == null - || resource.getMetadata().getLabels().get(APP_NAME_LABEL_KEY) == null) { - throw new NotAllowedException("Missing label: " + APP_NAME_LABEL_KEY); + || resource.getMetadata().getLabels().get(VALIDATION_TARGET_LABEL) == null) { + throw new NotAllowedException("Missing label: " + VALIDATION_TARGET_LABEL); } }); } diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java new file mode 100644 index 00000000..d601e3e9 --- /dev/null +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java @@ -0,0 +1,61 @@ +package io.javaoperatorsdk.webhook.sample.commons; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import io.fabric8.kubernetes.api.model.networking.v1.*; +import io.fabric8.kubernetes.client.KubernetesClient; + +import static io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers.VALIDATION_TARGET_LABEL; + +public class Utils { + + public static void applyAndWait(KubernetesClient client, String path) { + try (FileInputStream fileInputStream = new FileInputStream(path)) { + applyAndWait(client, fileInputStream); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public static void applyAndWait(KubernetesClient client, InputStream is) { + var resources = client.load(is).get(); + client.resourceList(resources).createOrReplace(); + client.resourceList(resources).waitUntilReady(3, TimeUnit.MINUTES); + } + + public static void addRequiredLabels(Ingress ingress) { + ingress.getMetadata().setLabels(Map.of(VALIDATION_TARGET_LABEL, "val")); + } + + public static Ingress testIngress(String name) { + return new IngressBuilder() + .withNewMetadata() + .withName(name) + .endMetadata() + .withSpec(new IngressSpecBuilder() + .withIngressClassName("sample") + .withRules(new IngressRuleBuilder() + .withHttp(new HTTPIngressRuleValueBuilder() + .withPaths(new HTTPIngressPathBuilder() + .withPath("/test") + .withPathType("Prefix") + .withBackend(new IngressBackendBuilder() + .withService(new IngressServiceBackendBuilder() + .withName("service") + .withPort(new ServiceBackendPortBuilder() + .withNumber(80) + .build()) + .build()) + .build()) + .build()) + .build()) + .build()) + .build()) + .build(); + } + +} diff --git a/samples/manual-test.http b/samples/manual-test.http index d34c53bd..1f7482ef 100644 --- a/samples/manual-test.http +++ b/samples/manual-test.http @@ -1,4 +1,4 @@ -POST http://localhost:8080/mutate HTTP/1.1 +POST http://192.168.49.2:31599/validate HTTP/1.1 Content-Type: application/json { @@ -28,91 +28,37 @@ Content-Type: application/json ] }, "object": { - "apiVersion": "v1", - "kind": "Pod", + "apiVersion": "networking.k8s.io/v1", + "kind": "Ingress", "metadata": { - "generateName": "nginx-deployment-6c54bd5869-", - "creationTimestamp": null, - "labels": { - "app": "nginx", - "pod-template-hash": "2710681425" - }, + "name": "minimal-ingress", "annotations": { - "openshift.io/scc": "restricted" - }, - "ownerReferences": [ - { - "apiVersion": "extensions/v1beta1", - "kind": "ReplicaSet", - "name": "nginx-deployment-6c54bd5869", - "uid": "16c2b355-5f5d-11e8-ac91-36e6bb280816", - "controller": true, - "blockOwnerDeletion": true - } - ] + "nginx.ingress.kubernetes.io/rewrite-target": "/" + } }, "spec": { - "volumes": [ - { - "name": "default-token-tq5lq", - "secret": { - "secretName": "default-token-tq5lq" - } - } - ], - "containers": [ + "ingressClassName": "nginx-example", + "rules": [ { - "name": "nginx", - "image": "nginx:1.7.9", - "ports": [ - { - "containerPort": 80, - "protocol": "TCP" - } - ], - "resources": {}, - "volumeMounts": [ - { - "name": "default-token-tq5lq", - "readOnly": true, - "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount" - } - ], - "terminationMessagePath": "/dev/termination-log", - "terminationMessagePolicy": "File", - "imagePullPolicy": "IfNotPresent", - "securityContext": { - "capabilities": { - "drop": [ - "KILL", - "MKNOD", - "SETGID", - "SETUID" - ] - }, - "runAsUser": 1000080000 + "http": { + "paths": [ + { + "path": "/testpath", + "pathType": "Prefix", + "backend": { + "service": { + "name": "test", + "port": { + "number": 80 + } + } + } + } + ] } } - ], - "restartPolicy": "Always", - "terminationGracePeriodSeconds": 30, - "dnsPolicy": "ClusterFirst", - "serviceAccountName": "default", - "serviceAccount": "default", - "securityContext": { - "seLinuxOptions": { - "level": "s0:c9,c4" - }, - "fsGroup": 1000080000 - }, - "imagePullSecrets": [ - { - "name": "default-dockercfg-kksdv" - } - ], - "schedulerName": "default-scheduler" - }, - "status": {} + ] + } }, "oldObject": null } diff --git a/samples/quarkus/k8s/mutating-webhook-configuration.yml b/samples/quarkus/k8s/mutating-webhook-configuration.yml index 252e1f38..5ba8a6d9 100644 --- a/samples/quarkus/k8s/mutating-webhook-configuration.yml +++ b/samples/quarkus/k8s/mutating-webhook-configuration.yml @@ -1,15 +1,15 @@ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: - name: "pod-mutating.quarkus.example.com" + name: "mutating.quarkus.example.com" annotations: - cert-manager.io/inject-ca-from: test/spring-boot-sample + cert-manager.io/inject-ca-from: default/quarkus-sample webhooks: - - name: "pod-mutating.quarkus.example.com" + - name: "mutating.quarkus.example.com" rules: - - apiGroups: [""] + - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] - operations: ["CREATE"] + operations: ["*"] resources: ["ingresses"] scope: "Namespaced" clientConfig: @@ -17,6 +17,7 @@ webhooks: namespace: "default" name: "quarkus-sample" path: "/mutate" + port: 443 admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 \ No newline at end of file diff --git a/samples/quarkus/k8s/validating-webhook-configuration.yml b/samples/quarkus/k8s/validating-webhook-configuration.yml index 9dbe5c76..6474e024 100644 --- a/samples/quarkus/k8s/validating-webhook-configuration.yml +++ b/samples/quarkus/k8s/validating-webhook-configuration.yml @@ -1,15 +1,15 @@ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - name: "pod-policy.quarkus.example.com" + name: "validating.quarkus.example.com" annotations: - cert-manager.io/inject-ca-from: test/spring-boot-sample + cert-manager.io/inject-ca-from: default/quarkus-sample webhooks: - - name: "pod-policy.quarkus.example.com" + - name: "validating.quarkus.example.com" rules: - - apiGroups: [""] + - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] - operations: ["CREATE"] + operations: ["*"] resources: ["ingresses"] scope: "Namespaced" clientConfig: @@ -17,6 +17,7 @@ webhooks: namespace: "default" name: "quarkus-sample" path: "/validate" + port: 443 admissionReviewVersions: ["v1"] sideEffects: None timeoutSeconds: 5 \ No newline at end of file diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index ea567eb9..46e19439 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -55,6 +55,15 @@ io.quarkus quarkus-kubernetes-client + + io.quarkus + quarkus-minikube + + + org.assertj + assertj-core + test + io.quarkus quarkus-container-image-jib diff --git a/samples/quarkus/src/main/resources/application.properties b/samples/quarkus/src/main/resources/application.properties index 0713c783..add08155 100644 --- a/samples/quarkus/src/main/resources/application.properties +++ b/samples/quarkus/src/main/resources/application.properties @@ -1,10 +1,13 @@ -quarkus.http.port=443 +#quarkus.http.insecure-requests=disabled +quarkus.http.port=80 +quarkus.http.ssl-port=443 quarkus.kubernetes.image-pull-policy=IfNotPresent +quarkus.kubernetes.ports."tls".container-port=443 ## To generate the Certificate and the Issuer resources quarkus.certificate.secret-name=tls-secret -quarkus.certificate.dns-names=quarkus-sample.test.svc,localhost +quarkus.certificate.dns-names=quarkus-sample.default.svc,localhost quarkus.certificate.self-signed.enabled=true quarkus.certificate.subject.organizations=Dekorate,Community quarkus.certificate.duration=2160h0m0s diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index ebf29b50..72053a9e 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -1,20 +1,22 @@ package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.networking.v1.*; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.KubernetesClientException; + +import static io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers.MUTATION_TARGET_LABEL; +import static io.javaoperatorsdk.webhook.sample.commons.Utils.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; -@Disabled class AdmissionControllerE2E { private KubernetesClient client = new KubernetesClientBuilder().build(); @@ -27,55 +29,32 @@ static void deployService() throws IOException { "https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml") .openStream()) { applyAndWait(client, certManager); - applyAndWait(client, "target/kubernetes/kubernetes.yml"); - applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); + // applyAndWait(client, "target/kubernetes/minikube.yml"); + applyAndWait(client, "k8s/validating-webhook-configuration.yml"); applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); } } @Test - void testValidationHook() { - var res = client.network().v1().ingresses().resource(ingress("validate-test")).create(); + void validationHook() { + var ingressWithLabel = testIngress("normal-add-test"); + addRequiredLabels(ingressWithLabel); + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res).isNotNull(); + + assertThrows(KubernetesClientException.class, + () -> client.network().v1().ingresses().resource(testIngress("validate-test")) + .createOrReplace()); } - private Ingress ingress(String name) { - return new IngressBuilder() - .withNewMetadata() - .withName(name) - .endMetadata() - .withSpec(new IngressSpecBuilder() - .withIngressClassName("sample") - .withRules(new IngressRuleBuilder() - .withHttp(new HTTPIngressRuleValueBuilder() - .withPaths(new HTTPIngressPathBuilder() - .withPath("/test") - .withBackend(new IngressBackendBuilder() - .withService(new IngressServiceBackendBuilder() - .withName("service") - .withPort(new ServiceBackendPortBuilder() - .withNumber(80) - .build()) - .build()) - .build()) - .build()) - .build()) - .build()) - .build()) - .build(); - } + @Test + void mutationHook() { + var ingressWithLabel = testIngress("mutation-test"); + addRequiredLabels(ingressWithLabel); - public static void applyAndWait(KubernetesClient client, String path) { - try (FileInputStream fileInputStream = new FileInputStream(path)) { - applyAndWait(client, fileInputStream); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); - public static void applyAndWait(KubernetesClient client, InputStream is) { - var resources = client.load(is).get(); - client.resourceList(resources).createOrReplace(); - client.resourceList(resources).waitUntilReady(2, TimeUnit.MINUTES); + assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); } } diff --git a/samples/spring-boot/k8s/mutating-webhook-configuration.yml b/samples/spring-boot/k8s/mutating-webhook-configuration.yml index 9870c54f..dba2afa1 100644 --- a/samples/spring-boot/k8s/mutating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/mutating-webhook-configuration.yml @@ -3,18 +3,18 @@ kind: MutatingWebhookConfiguration metadata: name: "pod-mutating.spring-boot.example.com" annotations: - cert-manager.io/inject-ca-from: test/spring-boot-sample + cert-manager.io/inject-ca-from: default/spring-boot-sample webhooks: - name: "pod-mutating.spring-boot.example.com" rules: - - apiGroups: [""] + - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] - operations: ["CREATE"] + operations: ["*"] resources: ["ingresses"] scope: "Namespaced" clientConfig: service: - namespace: "test" + namespace: "default" name: "spring-boot-sample" path: "/mutate" admissionReviewVersions: ["v1"] diff --git a/samples/spring-boot/k8s/validating-webhook-configuration.yml b/samples/spring-boot/k8s/validating-webhook-configuration.yml index 3316fb4a..1251bfd3 100644 --- a/samples/spring-boot/k8s/validating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/validating-webhook-configuration.yml @@ -3,18 +3,18 @@ kind: ValidatingWebhookConfiguration metadata: name: "pod-policy.spring-boot.example.com" annotations: - cert-manager.io/inject-ca-from: test/spring-boot-sample + cert-manager.io/inject-ca-from: default/spring-boot-sample webhooks: - name: "pod-policy.spring-boot.example.com" rules: - - apiGroups: [""] + - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] - operations: ["CREATE"] + operations: ["*"] resources: ["ingresses"] scope: "Namespaced" clientConfig: service: - namespace: "test" + namespace: "default" name: "spring-boot-sample" path: "/validate" admissionReviewVersions: ["v1"] diff --git a/samples/spring-boot/pom.xml b/samples/spring-boot/pom.xml index c94aea0a..03a2ba7b 100644 --- a/samples/spring-boot/pom.xml +++ b/samples/spring-boot/pom.xml @@ -89,7 +89,7 @@ gcr.io/distroless/java:11 - spring-boot-sample + test/spring-boot-sample:${project.version} diff --git a/samples/spring-boot/src/main/resources/application.properties b/samples/spring-boot/src/main/resources/application.properties index 9bc6156a..9587382a 100644 --- a/samples/spring-boot/src/main/resources/application.properties +++ b/samples/spring-boot/src/main/resources/application.properties @@ -5,10 +5,10 @@ server.ssl.key-store-type=PKCS12 dekorate.jib.from=openjdk:11 ## To include the keystore secret dekorate.options.input-path=kubernetes - +dekorate.jib.group=test ## To generate the Certificate and the Issuer resources dekorate.certificate.secret-name=tls-secret -dekorate.certificate.dnsNames=spring-boot-sample.test.svc,localhost +dekorate.certificate.dnsNames=spring-boot-sample.default.svc,localhost dekorate.certificate.self-signed.enabled=true dekorate.certificate.subject.organizations=Dekorate,Community dekorate.certificate.duration=2160h0m0s diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java new file mode 100644 index 00000000..580ca00e --- /dev/null +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java @@ -0,0 +1,61 @@ +package io.javaoperatorsdk.webhook.sample.springboot.admission; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.api.model.networking.v1.*; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.KubernetesClientException; + +import static io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers.MUTATION_TARGET_LABEL; +import static io.javaoperatorsdk.webhook.sample.commons.Utils.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AdmissionControllerE2E { + + private KubernetesClient client = new KubernetesClientBuilder().build(); + + @BeforeAll + static void deployService() throws IOException { + try (KubernetesClient client = new KubernetesClientBuilder().build(); + InputStream certManager = + new URL( + "https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml") + .openStream()) { + applyAndWait(client, certManager); + applyAndWait(client, "target/classes/META-INF/dekorate/kubernetes.yml"); + applyAndWait(client, "k8s/validating-webhook-configuration.yml"); + applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); + } + } + + @Test + void validationHook() { + var ingressWithLabel = testIngress("normal-add-test"); + addRequiredLabels(ingressWithLabel); + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res).isNotNull(); + + assertThrows(KubernetesClientException.class, + () -> client.network().v1().ingresses().resource(testIngress("validate-test")) + .createOrReplace()); + } + + @Test + void mutationHook() { + var ingressWithLabel = testIngress("mutation-test"); + addRequiredLabels(ingressWithLabel); + + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + + assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); + } + + +} From 420541c900fddbaa3630c5da273b8549a4c8b02a Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 13:24:52 +0100 Subject: [PATCH 10/21] e2e test improvemets --- .github/workflows/master-snapshot-release.yml | 2 +- .github/workflows/pr.yml | 59 ++++--------------- .../webhook/sample/commons/Utils.java | 2 + samples/quarkus/pom.xml | 6 ++ .../admission/AdmissionControllerE2E.java | 17 +++--- .../k8s/mutating-webhook-configuration.yml | 4 +- .../k8s/validating-webhook-configuration.yml | 4 +- samples/spring-boot/pom.xml | 6 ++ .../admission/AdmissionControllerE2E.java | 20 ++++--- 9 files changed, 51 insertions(+), 69 deletions(-) diff --git a/.github/workflows/master-snapshot-release.yml b/.github/workflows/master-snapshot-release.yml index 67d63ef2..566a3d6b 100644 --- a/.github/workflows/master-snapshot-release.yml +++ b/.github/workflows/master-snapshot-release.yml @@ -27,7 +27,7 @@ jobs: cache: 'maven' - name: Run unit tests run: ./mvnw ${MAVEN_ARGS} -B test --file pom.xml - - name: Run integration tests + - name: Package run: ./mvnw ${MAVEN_ARGS} -B package --file pom.xml release-snapshot: runs-on: ubuntu-latest diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 5c70406e..65c1f32c 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -31,7 +31,7 @@ jobs: ./mvnw ${MAVEN_ARGS} impsort:check --file pom.xml - name: Run unit tests run: ./mvnw ${MAVEN_ARGS} -B test --file pom.xml - spring-boot-integration-test: + spring-boot-e2e-tests: runs-on: ubuntu-latest needs: build strategy: @@ -46,20 +46,14 @@ jobs: distribution: ${{ matrix.distribution }} java-version: ${{ matrix.java }} cache: 'maven' - - name: Build - run: ./mvnw ${MAVEN_ARGS} clean install -DskipTests - - name: Kubernetes KinD Cluster - uses: container-tools/kind-action@v1 + - name: Setup Minikube-Kubernetes + uses: manusa/actions-setup-minikube@v2.7.1 with: - version: v0.11.1 - registry: true - - name: Install Cert-Manager - run: | - OS=$(go env GOOS); ARCH=$(go env GOARCH); curl -sSL -o kubectl-cert-manager.tar.gz https://github.com/cert-manager/cert-manager/releases/download/v1.7.2/kubectl-cert_manager-$OS-$ARCH.tar.gz - tar xzf kubectl-cert-manager.tar.gz - sudo mv kubectl-cert_manager /usr/local/bin - kubectl cert-manager x install - - name: Run Integration Test + minikube version: v1.25.2 + kubernetes version: v1.23.6 + github token: ${{ secrets.GITHUB_TOKEN }} + driver: docker + - name: Run E2E Test run: | set -x @@ -69,37 +63,6 @@ jobs: # Generate manifests and image cd samples/spring-boot - # ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -Ddekorate.jib.group=test -DskipTests - ./mvnw ${MAVEN_ARGS} clean install -Ddekorate.jib.registry=$KIND_REGISTRY -Ddekorate.jib.group=tests -Ddekorate.jib.version=latest -Ddekorate.jib.autoPushEnabled=true -DskipTests - - # Install manifests - kubectl apply -f target/classes/META-INF/dekorate/kubernetes.yml - - # Wait until the service is started - kubectl wait --for=condition=available --timeout=600s deployment/spring-boot-sample - - # First test: verify validating webhook works - ## Install webhook - kubectl apply -f k8s/validating-webhook-configuration.yml - - ## Wait some time to let Cert-Manager to inject issuers - sleep 10 - - ## Test Pod with missing label: it should fail - K8S_MESSAGE=$(kubectl apply -f k8s/create-pod-with-missing-label-example.yml 2>&1 || true) - if [[ $K8S_MESSAGE != *"Missing label"* ]]; then - echo "The validation webhook didn't work. Message: $K8S_MESSAGE" - exit 1 - fi - - # Second test: verify mutating webhook works - ## Install webhook - kubectl apply -f k8s/mutating-webhook-configuration.yml - - ## Test the same Pod can now be installed because the mutating webhook adds the missing label - kubectl apply -f k8s/create-pod-with-missing-label-example.yml - K8S_MESSAGE=`kubectl get pod pod-with-missing-label -o yaml | grep app.kubernetes.io/name` - if [[ $K8S_MESSAGE != *"mutation-test"* ]]; then - echo "The mutating webhook didn't work. Message: $K8S_MESSAGE" - exit 1 - fi \ No newline at end of file + ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -DskipTests + ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests + diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java index d601e3e9..35ee7bf7 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java @@ -13,6 +13,8 @@ public class Utils { + public static final int SPIN_UP_GRACE_PERIOD = 10; + public static void applyAndWait(KubernetesClient client, String path) { try (FileInputStream fileInputStream = new FileInputStream(path)) { applyAndWait(client, fileInputStream); diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index 46e19439..591af2b6 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -102,6 +102,12 @@ + + org.awaitility + awaitility + ${awaitility.version} + test + diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index 72053a9e..9ad65e97 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.time.Duration; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -15,6 +16,7 @@ import static io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers.MUTATION_TARGET_LABEL; import static io.javaoperatorsdk.webhook.sample.commons.Utils.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertThrows; class AdmissionControllerE2E { @@ -39,9 +41,10 @@ static void deployService() throws IOException { void validationHook() { var ingressWithLabel = testIngress("normal-add-test"); addRequiredLabels(ingressWithLabel); - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); - assertThat(res).isNotNull(); - + await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res).isNotNull(); + }); assertThrows(KubernetesClientException.class, () -> client.network().v1().ingresses().resource(testIngress("validate-test")) .createOrReplace()); @@ -51,10 +54,10 @@ void validationHook() { void mutationHook() { var ingressWithLabel = testIngress("mutation-test"); addRequiredLabels(ingressWithLabel); - - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); - - assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); + await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); + }); } } diff --git a/samples/spring-boot/k8s/mutating-webhook-configuration.yml b/samples/spring-boot/k8s/mutating-webhook-configuration.yml index dba2afa1..a1ce2122 100644 --- a/samples/spring-boot/k8s/mutating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/mutating-webhook-configuration.yml @@ -1,11 +1,11 @@ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: - name: "pod-mutating.spring-boot.example.com" + name: "mutating.spring-boot.example.com" annotations: cert-manager.io/inject-ca-from: default/spring-boot-sample webhooks: - - name: "pod-mutating.spring-boot.example.com" + - name: "mutating.spring-boot.example.com" rules: - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] diff --git a/samples/spring-boot/k8s/validating-webhook-configuration.yml b/samples/spring-boot/k8s/validating-webhook-configuration.yml index 1251bfd3..1c899f4a 100644 --- a/samples/spring-boot/k8s/validating-webhook-configuration.yml +++ b/samples/spring-boot/k8s/validating-webhook-configuration.yml @@ -1,11 +1,11 @@ apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - name: "pod-policy.spring-boot.example.com" + name: "validating.spring-boot.example.com" annotations: cert-manager.io/inject-ca-from: default/spring-boot-sample webhooks: - - name: "pod-policy.spring-boot.example.com" + - name: "validating.spring-boot.example.com" rules: - apiGroups: ["networking.k8s.io"] apiVersions: ["v1"] diff --git a/samples/spring-boot/pom.xml b/samples/spring-boot/pom.xml index 03a2ba7b..2364a341 100644 --- a/samples/spring-boot/pom.xml +++ b/samples/spring-boot/pom.xml @@ -76,6 +76,12 @@ assertj-core test + + org.awaitility + awaitility + ${awaitility.version} + test + diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java index 580ca00e..8c1f5306 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.time.Duration; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -15,6 +16,7 @@ import static io.javaoperatorsdk.webhook.sample.commons.AdmissionControllers.MUTATION_TARGET_LABEL; import static io.javaoperatorsdk.webhook.sample.commons.Utils.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; import static org.junit.jupiter.api.Assertions.assertThrows; class AdmissionControllerE2E { @@ -22,7 +24,7 @@ class AdmissionControllerE2E { private KubernetesClient client = new KubernetesClientBuilder().build(); @BeforeAll - static void deployService() throws IOException { + static void deployService() throws IOException, InterruptedException { try (KubernetesClient client = new KubernetesClientBuilder().build(); InputStream certManager = new URL( @@ -39,9 +41,10 @@ static void deployService() throws IOException { void validationHook() { var ingressWithLabel = testIngress("normal-add-test"); addRequiredLabels(ingressWithLabel); - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); - assertThat(res).isNotNull(); - + await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res).isNotNull(); + }); assertThrows(KubernetesClientException.class, () -> client.network().v1().ingresses().resource(testIngress("validate-test")) .createOrReplace()); @@ -51,11 +54,10 @@ void validationHook() { void mutationHook() { var ingressWithLabel = testIngress("mutation-test"); addRequiredLabels(ingressWithLabel); - - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); - - assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); + await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { + var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); + }); } - } From dacbd7ad5a95120245ccd031935284457aa9da17 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 13:26:22 +0100 Subject: [PATCH 11/21] wip --- .github/workflows/pr.yml | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 65c1f32c..0ec2f235 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -55,14 +55,36 @@ jobs: driver: docker - name: Run E2E Test run: | - set -x - - # Create namespace - kubectl create namespace test - kubectl config set-context --current --namespace=test - - # Generate manifests and image + set -x cd samples/spring-boot ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests + quarkus-e2e-tests: + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + java: [ 11 ] + distribution: [ temurin ] + steps: + - uses: actions/checkout@v2 + - name: Set up Java and Maven + uses: actions/setup-java@v2 + with: + distribution: ${{ matrix.distribution }} + java-version: ${{ matrix.java }} + cache: 'maven' + - name: Setup Minikube-Kubernetes + uses: manusa/actions-setup-minikube@v2.7.1 + with: + minikube version: v1.25.2 + kubernetes version: v1.23.6 + github token: ${{ secrets.GITHUB_TOKEN }} + driver: docker + - name: Run E2E Test + run: | + set -x + cd samples/quarkus + ./mvnw install -Dquarkus.container-image.build=true -DskipTests + ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file From 9967e9dd96043d9166ddbb58293ea3b98a59ed40 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 13:31:19 +0100 Subject: [PATCH 12/21] fix --- .github/workflows/pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0ec2f235..403a3fac 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -55,9 +55,9 @@ jobs: driver: docker - name: Run E2E Test run: | - set -x - cd samples/spring-boot + set -x ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -DskipTests + cd samples/spring-boot ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests quarkus-e2e-tests: @@ -84,7 +84,7 @@ jobs: driver: docker - name: Run E2E Test run: | - set -x - cd samples/quarkus + set -x ./mvnw install -Dquarkus.container-image.build=true -DskipTests + cd samples/quarkus ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file From 699173f2e9b33efe6339c7de2910d16e49f7fd94 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 13:38:50 +0100 Subject: [PATCH 13/21] fix --- .github/workflows/pr.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 403a3fac..9ac63ff6 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -56,8 +56,9 @@ jobs: - name: Run E2E Test run: | set -x - ./mvnw ${MAVEN_ARGS} clean install jib:dockerBuild -DskipTests + ./mvnw ${MAVEN_ARGS} clean install -DskipTests cd samples/spring-boot + ./mvnw ${MAVEN_ARGS} jib:dockerBuild -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests quarkus-e2e-tests: @@ -85,6 +86,7 @@ jobs: - name: Run E2E Test run: | set -x - ./mvnw install -Dquarkus.container-image.build=true -DskipTests + ./mvnw install -DskipTests cd samples/quarkus + ./mvnw install -Dquarkus.container-image.build=true -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file From 36ce3504bef3cba989105bcbb6c8cbb743614fd2 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 13:45:00 +0100 Subject: [PATCH 14/21] wip --- .github/workflows/pr.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 9ac63ff6..b998fda4 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -57,7 +57,8 @@ jobs: run: | set -x ./mvnw ${MAVEN_ARGS} clean install -DskipTests - cd samples/spring-boot + cd samples/spring-boot + pwd ./mvnw ${MAVEN_ARGS} jib:dockerBuild -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests @@ -86,7 +87,7 @@ jobs: - name: Run E2E Test run: | set -x - ./mvnw install -DskipTests + ./mvnw clean install -DskipTests cd samples/quarkus ./mvnw install -Dquarkus.container-image.build=true -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file From 1bffe8d9bbc10305461d4b4369c96f74ff4c10fe Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 14:02:28 +0100 Subject: [PATCH 15/21] fixes --- delme.yaml | 2 ++ .../webhook/sample/commons/Utils.java | 2 +- .../admission/AdmissionControllerE2E.java | 20 ++++++++++++++----- .../admission/AdmissionControllerE2E.java | 14 +++++++++++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/delme.yaml b/delme.yaml index d4f7252a..a3e33f63 100644 --- a/delme.yaml +++ b/delme.yaml @@ -5,6 +5,8 @@ metadata: name: minimal-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / + labels: + app.kubernetes.io/name: "app" spec: ingressClassName: nginx-example rules: diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java index 35ee7bf7..7a6c825b 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java @@ -13,7 +13,7 @@ public class Utils { - public static final int SPIN_UP_GRACE_PERIOD = 10; + public static final int SPIN_UP_GRACE_PERIOD = 120; public static void applyAndWait(KubernetesClient client, String path) { try (FileInputStream fileInputStream = new FileInputStream(path)) { diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index 9ad65e97..9057e0e9 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -42,12 +42,17 @@ void validationHook() { var ingressWithLabel = testIngress("normal-add-test"); addRequiredLabels(ingressWithLabel); await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + Ingress res = null; + try { + // this can be since coredns in minikube can take some time + res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + } catch (KubernetesClientException e) { + } assertThat(res).isNotNull(); }); assertThrows(KubernetesClientException.class, - () -> client.network().v1().ingresses().resource(testIngress("validate-test")) - .createOrReplace()); + () -> client.network().v1().ingresses().resource(testIngress("validate-test")) + .createOrReplace()); } @Test @@ -55,9 +60,14 @@ void mutationHook() { var ingressWithLabel = testIngress("mutation-test"); addRequiredLabels(ingressWithLabel); await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + Ingress res = null; + try { + // this can be since coredns in minikube can take some time + res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + } catch (KubernetesClientException e) { + } + assertThat(res).isNotNull(); assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); }); } - } diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java index 8c1f5306..910183be 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java @@ -42,7 +42,12 @@ void validationHook() { var ingressWithLabel = testIngress("normal-add-test"); addRequiredLabels(ingressWithLabel); await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + Ingress res = null; + try { + // this can be since coredns in minikube can take some time + res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + } catch (KubernetesClientException e) { + } assertThat(res).isNotNull(); }); assertThrows(KubernetesClientException.class, @@ -55,7 +60,12 @@ void mutationHook() { var ingressWithLabel = testIngress("mutation-test"); addRequiredLabels(ingressWithLabel); await().atMost(Duration.ofSeconds(SPIN_UP_GRACE_PERIOD)).untilAsserted(() -> { - var res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + Ingress res = null; + try { + res = client.network().v1().ingresses().resource(ingressWithLabel).createOrReplace(); + } catch (KubernetesClientException e) { + } + assertThat(res).isNotNull(); assertThat(res.getMetadata().getLabels()).containsKey(MUTATION_TARGET_LABEL); }); } From ee66cf315e51b1d5f4b7b51a467011d0a840750d Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 14:10:39 +0100 Subject: [PATCH 16/21] format --- .../sample/quarkus/admission/AdmissionControllerE2E.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index 9057e0e9..08c1ca33 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -51,8 +51,8 @@ void validationHook() { assertThat(res).isNotNull(); }); assertThrows(KubernetesClientException.class, - () -> client.network().v1().ingresses().resource(testIngress("validate-test")) - .createOrReplace()); + () -> client.network().v1().ingresses().resource(testIngress("validate-test")) + .createOrReplace()); } @Test From e4c85daa7f6997b86f17a06754440b4171a463db Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 14:30:28 +0100 Subject: [PATCH 17/21] check --- .github/workflows/pr.yml | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index b998fda4..a0e1b5df 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -62,32 +62,32 @@ jobs: ./mvnw ${MAVEN_ARGS} jib:dockerBuild -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests - quarkus-e2e-tests: - runs-on: ubuntu-latest - needs: build - strategy: - matrix: - java: [ 11 ] - distribution: [ temurin ] - steps: - - uses: actions/checkout@v2 - - name: Set up Java and Maven - uses: actions/setup-java@v2 - with: - distribution: ${{ matrix.distribution }} - java-version: ${{ matrix.java }} - cache: 'maven' - - name: Setup Minikube-Kubernetes - uses: manusa/actions-setup-minikube@v2.7.1 - with: - minikube version: v1.25.2 - kubernetes version: v1.23.6 - github token: ${{ secrets.GITHUB_TOKEN }} - driver: docker - - name: Run E2E Test - run: | - set -x - ./mvnw clean install -DskipTests - cd samples/quarkus - ./mvnw install -Dquarkus.container-image.build=true -DskipTests - ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file +# quarkus-e2e-tests: +# runs-on: ubuntu-latest +# needs: build +# strategy: +# matrix: +# java: [ 11 ] +# distribution: [ temurin ] +# steps: +# - uses: actions/checkout@v2 +# - name: Set up Java and Maven +# uses: actions/setup-java@v2 +# with: +# distribution: ${{ matrix.distribution }} +# java-version: ${{ matrix.java }} +# cache: 'maven' +# - name: Setup Minikube-Kubernetes +# uses: manusa/actions-setup-minikube@v2.7.1 +# with: +# minikube version: v1.25.2 +# kubernetes version: v1.23.6 +# github token: ${{ secrets.GITHUB_TOKEN }} +# driver: docker +# - name: Run E2E Test +# run: | +# set -x +# ./mvnw clean install -DskipTests +# cd samples/quarkus +# ./mvnw install -Dquarkus.container-image.build=true -DskipTests +# ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file From c839522c79f829ee86f182c62e5f77ea145bba48 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 14:46:35 +0100 Subject: [PATCH 18/21] wip --- .../java/io/javaoperatorsdk/webhook/sample/commons/Utils.java | 2 +- .../sample/springboot/admission/AdmissionControllerE2E.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java index 7a6c825b..251c207d 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java @@ -26,7 +26,7 @@ public static void applyAndWait(KubernetesClient client, String path) { public static void applyAndWait(KubernetesClient client, InputStream is) { var resources = client.load(is).get(); client.resourceList(resources).createOrReplace(); - client.resourceList(resources).waitUntilReady(3, TimeUnit.MINUTES); + client.resourceList(resources).waitUntilReady(5, TimeUnit.MINUTES); } public static void addRequiredLabels(Ingress ingress) { diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java index 910183be..6c08d2cc 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionControllerE2E.java @@ -24,7 +24,7 @@ class AdmissionControllerE2E { private KubernetesClient client = new KubernetesClientBuilder().build(); @BeforeAll - static void deployService() throws IOException, InterruptedException { + static void deployService() throws IOException { try (KubernetesClient client = new KubernetesClientBuilder().build(); InputStream certManager = new URL( From b64d14eda02c331e6fbfb9ff9dfff88ec3e4b709 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 15:02:05 +0100 Subject: [PATCH 19/21] wip --- .github/workflows/pr.yml | 58 +++++++++---------- .../admission/AdmissionControllerE2E.java | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index a0e1b5df..027665e3 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -62,32 +62,32 @@ jobs: ./mvnw ${MAVEN_ARGS} jib:dockerBuild -DskipTests ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests -# quarkus-e2e-tests: -# runs-on: ubuntu-latest -# needs: build -# strategy: -# matrix: -# java: [ 11 ] -# distribution: [ temurin ] -# steps: -# - uses: actions/checkout@v2 -# - name: Set up Java and Maven -# uses: actions/setup-java@v2 -# with: -# distribution: ${{ matrix.distribution }} -# java-version: ${{ matrix.java }} -# cache: 'maven' -# - name: Setup Minikube-Kubernetes -# uses: manusa/actions-setup-minikube@v2.7.1 -# with: -# minikube version: v1.25.2 -# kubernetes version: v1.23.6 -# github token: ${{ secrets.GITHUB_TOKEN }} -# driver: docker -# - name: Run E2E Test -# run: | -# set -x -# ./mvnw clean install -DskipTests -# cd samples/quarkus -# ./mvnw install -Dquarkus.container-image.build=true -DskipTests -# ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file + quarkus-e2e-tests: + runs-on: ubuntu-latest + needs: build + strategy: + matrix: + java: [ 11 ] + distribution: [ temurin ] + steps: + - uses: actions/checkout@v2 + - name: Set up Java and Maven + uses: actions/setup-java@v2 + with: + distribution: ${{ matrix.distribution }} + java-version: ${{ matrix.java }} + cache: 'maven' + - name: Setup Minikube-Kubernetes + uses: manusa/actions-setup-minikube@v2.7.1 + with: + minikube version: v1.25.2 + kubernetes version: v1.23.6 + github token: ${{ secrets.GITHUB_TOKEN }} + driver: docker + - name: Run E2E Test + run: | + set -x + ./mvnw clean install -DskipTests + cd samples/quarkus + ./mvnw install -Dquarkus.container-image.build=true -DskipTests + ./mvnw ${MAVEN_ARGS} test -Pend-to-end-tests \ No newline at end of file diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java index 08c1ca33..2c93fa10 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerE2E.java @@ -31,7 +31,7 @@ static void deployService() throws IOException { "https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.yaml") .openStream()) { applyAndWait(client, certManager); - // applyAndWait(client, "target/kubernetes/minikube.yml"); + applyAndWait(client, "target/kubernetes/minikube.yml"); applyAndWait(client, "k8s/validating-webhook-configuration.yml"); applyAndWait(client, "k8s/mutating-webhook-configuration.yml"); } From 0396a894461334a7e01c7e8dd92245b114854b40 Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 15:16:21 +0100 Subject: [PATCH 20/21] eval --- .github/workflows/pr.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 027665e3..a703cc67 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -56,6 +56,7 @@ jobs: - name: Run E2E Test run: | set -x + eval $(minikube -p minikube docker-env) ./mvnw ${MAVEN_ARGS} clean install -DskipTests cd samples/spring-boot pwd @@ -87,6 +88,7 @@ jobs: - name: Run E2E Test run: | set -x + eval $(minikube -p minikube docker-env) ./mvnw clean install -DskipTests cd samples/quarkus ./mvnw install -Dquarkus.container-image.build=true -DskipTests From 693a6bd61668f8f3310095c5119696a32ff5410d Mon Sep 17 00:00:00 2001 From: csviri Date: Thu, 15 Dec 2022 15:24:04 +0100 Subject: [PATCH 21/21] wip --- .../java/io/javaoperatorsdk/webhook/sample/commons/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java index 251c207d..7a6c825b 100644 --- a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java +++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/Utils.java @@ -26,7 +26,7 @@ public static void applyAndWait(KubernetesClient client, String path) { public static void applyAndWait(KubernetesClient client, InputStream is) { var resources = client.load(is).get(); client.resourceList(resources).createOrReplace(); - client.resourceList(resources).waitUntilReady(5, TimeUnit.MINUTES); + client.resourceList(resources).waitUntilReady(3, TimeUnit.MINUTES); } public static void addRequiredLabels(Ingress ingress) {