diff --git a/core/pom.xml b/core/pom.xml index 37f541d2..0c344cfc 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -108,5 +108,10 @@ com.github.java-json-tools json-patch + + io.fabric8 + crd-generator-apt + test + diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionController.java b/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionController.java deleted file mode 100644 index ad3263b6..00000000 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionController.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.javaoperatorsdk.admissioncontroller; - -import io.fabric8.kubernetes.api.model.KubernetesResource; -import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; -import io.javaoperatorsdk.admissioncontroller.mutation.DefaultRequestMutator; -import io.javaoperatorsdk.admissioncontroller.mutation.Mutator; -import io.javaoperatorsdk.admissioncontroller.validation.DefaultRequestValidator; -import io.javaoperatorsdk.admissioncontroller.validation.Validator; - -public class AdmissionController { - - private final RequestHandler requestHandler; - - public AdmissionController(Mutator mutator) { - this(new DefaultRequestMutator<>(mutator)); - } - - public AdmissionController(Validator mutator) { - this(new DefaultRequestValidator<>(mutator)); - } - - public AdmissionController(RequestHandler requestHandler) { - this.requestHandler = requestHandler; - } - - public AdmissionReview handle(AdmissionReview admissionReview) { - var response = requestHandler.handle(admissionReview.getRequest()); - AdmissionReview responseAdmissionReview = new AdmissionReview(); - responseAdmissionReview.setResponse(response); - response.setUid(admissionReview.getRequest().getUid()); - return responseAdmissionReview; - } - -} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionController.java new file mode 100644 index 00000000..a0a500d3 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionController.java @@ -0,0 +1,34 @@ +package io.javaoperatorsdk.webhook.admission; + +import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; +import io.javaoperatorsdk.webhook.admission.mutation.DefaultAdmissionRequestMutator; +import io.javaoperatorsdk.webhook.admission.mutation.Mutator; +import io.javaoperatorsdk.webhook.admission.validation.DefaultAdmissionRequestValidator; +import io.javaoperatorsdk.webhook.admission.validation.Validator; + +public class AdmissionController { + + private final AdmissionRequestHandler admissionRequestHandler; + + public AdmissionController(Mutator mutator) { + this(new DefaultAdmissionRequestMutator<>(mutator)); + } + + public AdmissionController(Validator mutator) { + this(new DefaultAdmissionRequestValidator<>(mutator)); + } + + public AdmissionController(AdmissionRequestHandler admissionRequestHandler) { + this.admissionRequestHandler = admissionRequestHandler; + } + + public AdmissionReview handle(AdmissionReview admissionReview) { + var response = admissionRequestHandler.handle(admissionReview.getRequest()); + AdmissionReview responseAdmissionReview = new AdmissionReview(); + responseAdmissionReview.setResponse(response); + response.setUid(admissionReview.getRequest().getUid()); + return responseAdmissionReview; + } + +} diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerException.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerException.java similarity index 92% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerException.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerException.java index 0960923e..685b9c67 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerException.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerException.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; public class AdmissionControllerException extends RuntimeException { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/RequestHandler.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionRequestHandler.java similarity index 70% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/RequestHandler.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionRequestHandler.java index d967d266..bddbf991 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/RequestHandler.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionRequestHandler.java @@ -1,9 +1,9 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -public interface RequestHandler { +public interface AdmissionRequestHandler { AdmissionResponse handle(AdmissionRequest admissionRequest); diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionUtils.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionUtils.java similarity index 92% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionUtils.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionUtils.java index 7acd1d24..c1259790 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AdmissionUtils.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AdmissionUtils.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -13,7 +13,9 @@ public class AdmissionUtils { public static final String JSON_PATCH = "JSONPatch"; - private final static ObjectMapper mapper = new ObjectMapper(); + private static final ObjectMapper mapper = new ObjectMapper(); + + private AdmissionUtils() {} public static AdmissionResponse notAllowedExceptionToAdmissionResponse( NotAllowedException notAllowedException) { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionController.java similarity index 57% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionController.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionController.java index 01cd16d7..373469f3 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionController.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionController.java @@ -1,27 +1,27 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import java.util.concurrent.CompletionStage; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; -import io.javaoperatorsdk.admissioncontroller.mutation.AsyncDefaultRequestMutator; -import io.javaoperatorsdk.admissioncontroller.mutation.AsyncMutator; -import io.javaoperatorsdk.admissioncontroller.validation.AsyncDefaultRequestValidator; -import io.javaoperatorsdk.admissioncontroller.validation.Validator; +import io.javaoperatorsdk.webhook.admission.mutation.AsyncDefaultAdmissionRequestMutator; +import io.javaoperatorsdk.webhook.admission.mutation.AsyncMutator; +import io.javaoperatorsdk.webhook.admission.validation.AsyncDefaultAdmissionRequestValidator; +import io.javaoperatorsdk.webhook.admission.validation.Validator; public class AsyncAdmissionController { - private final AsyncRequestHandler requestHandler; + private final AsyncAdmissionRequestHandler requestHandler; public AsyncAdmissionController(AsyncMutator mutator) { - this(new AsyncDefaultRequestMutator<>(mutator)); + this(new AsyncDefaultAdmissionRequestMutator<>(mutator)); } public AsyncAdmissionController(Validator validator) { - this(new AsyncDefaultRequestValidator<>(validator)); + this(new AsyncDefaultAdmissionRequestValidator<>(validator)); } - public AsyncAdmissionController(AsyncRequestHandler requestHandler) { + public AsyncAdmissionController(AsyncAdmissionRequestHandler requestHandler) { this.requestHandler = requestHandler; } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncRequestHandler.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionRequestHandler.java similarity index 74% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncRequestHandler.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionRequestHandler.java index 9582f1dc..ab99106f 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/AsyncRequestHandler.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionRequestHandler.java @@ -1,11 +1,11 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import java.util.concurrent.CompletionStage; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -public interface AsyncRequestHandler { +public interface AsyncAdmissionRequestHandler { CompletionStage handle(AdmissionRequest admissionRequest); diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/NotAllowedException.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/NotAllowedException.java similarity index 83% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/NotAllowedException.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/NotAllowedException.java index f1f61bf2..ece3cecf 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/NotAllowedException.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/NotAllowedException.java @@ -1,12 +1,13 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import io.fabric8.kubernetes.api.model.Status; public class NotAllowedException extends AdmissionControllerException { - private Status status = new Status(); + private final Status status; public NotAllowedException() { + status = new Status(); status.setCode(403); } @@ -27,34 +28,40 @@ public NotAllowedException(String message, Throwable cause, boolean enableSuppre public NotAllowedException(String message) { super(message); + this.status = new Status(); this.status.setMessage(message); this.status.setCode(403); } public NotAllowedException(int code) { + this.status = new Status(); this.status.setCode(code); } public NotAllowedException(String message, int code) { super(message); + this.status = new Status(); this.status.setCode(code); this.status.setMessage(message); } public NotAllowedException(String message, Throwable cause, int code) { super(message, cause); + this.status = new Status(); this.status.setCode(code); this.status.setMessage(message); } public NotAllowedException(Throwable cause, int code) { super(cause); + this.status = new Status(); this.status.setCode(code); } public NotAllowedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int code) { super(message, cause, enableSuppression, writableStackTrace); + this.status = new Status(); status.setCode(code); } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/Operation.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/Operation.java similarity index 55% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/Operation.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/Operation.java index a9d8e871..fb8a0e5d 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/Operation.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/Operation.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; public enum Operation { CREATE, UPDATE, DELETE, CONNECT diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncDefaultRequestMutator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncDefaultAdmissionRequestMutator.java similarity index 58% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncDefaultRequestMutator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncDefaultAdmissionRequestMutator.java index 7aeec740..a64185a0 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncDefaultRequestMutator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncDefaultAdmissionRequestMutator.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.mutation; +package io.javaoperatorsdk.webhook.admission.mutation; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -6,24 +6,27 @@ import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -import io.javaoperatorsdk.admissioncontroller.*; -import io.javaoperatorsdk.admissioncontroller.clone.Cloner; -import io.javaoperatorsdk.admissioncontroller.clone.ObjectMapperCloner; +import io.javaoperatorsdk.webhook.admission.AdmissionUtils; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionRequestHandler; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; +import io.javaoperatorsdk.webhook.clone.Cloner; +import io.javaoperatorsdk.webhook.clone.ObjectMapperCloner; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.admissionResponseFromMutation; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.getTargetResource; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.admissionResponseFromMutation; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource; -public class AsyncDefaultRequestMutator - implements AsyncRequestHandler { +public class AsyncDefaultAdmissionRequestMutator + implements AsyncAdmissionRequestHandler { private final AsyncMutator mutator; private final Cloner cloner; - public AsyncDefaultRequestMutator(AsyncMutator mutator) { + public AsyncDefaultAdmissionRequestMutator(AsyncMutator mutator) { this(mutator, new ObjectMapperCloner<>()); } - public AsyncDefaultRequestMutator(AsyncMutator mutator, Cloner cloner) { + public AsyncDefaultAdmissionRequestMutator(AsyncMutator mutator, Cloner cloner) { this.mutator = mutator; this.cloner = cloner; } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncMutator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncMutator.java similarity index 59% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncMutator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncMutator.java index b6bf5b31..2df8a5b0 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/AsyncMutator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/AsyncMutator.java @@ -1,10 +1,10 @@ -package io.javaoperatorsdk.admissioncontroller.mutation; +package io.javaoperatorsdk.webhook.admission.mutation; import java.util.concurrent.CompletionStage; import io.fabric8.kubernetes.api.model.KubernetesResource; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.Operation; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; public interface AsyncMutator { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/DefaultRequestMutator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/DefaultAdmissionRequestMutator.java similarity index 55% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/DefaultRequestMutator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/DefaultAdmissionRequestMutator.java index 7f65e80d..8b5287aa 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/DefaultRequestMutator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/DefaultAdmissionRequestMutator.java @@ -1,28 +1,29 @@ -package io.javaoperatorsdk.admissioncontroller.mutation; +package io.javaoperatorsdk.webhook.admission.mutation; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -import io.javaoperatorsdk.admissioncontroller.AdmissionUtils; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.Operation; -import io.javaoperatorsdk.admissioncontroller.RequestHandler; -import io.javaoperatorsdk.admissioncontroller.clone.Cloner; -import io.javaoperatorsdk.admissioncontroller.clone.ObjectMapperCloner; +import io.javaoperatorsdk.webhook.admission.AdmissionRequestHandler; +import io.javaoperatorsdk.webhook.admission.AdmissionUtils; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; +import io.javaoperatorsdk.webhook.clone.Cloner; +import io.javaoperatorsdk.webhook.clone.ObjectMapperCloner; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.admissionResponseFromMutation; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.getTargetResource; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.admissionResponseFromMutation; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource; -public class DefaultRequestMutator implements RequestHandler { +public class DefaultAdmissionRequestMutator + implements AdmissionRequestHandler { private final Mutator mutator; private final Cloner cloner; - public DefaultRequestMutator(Mutator mutator) { + public DefaultAdmissionRequestMutator(Mutator mutator) { this(mutator, new ObjectMapperCloner<>()); } - public DefaultRequestMutator(Mutator mutator, Cloner cloner) { + public DefaultAdmissionRequestMutator(Mutator mutator, Cloner cloner) { this.mutator = mutator; this.cloner = cloner; } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/Mutator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/Mutator.java similarity index 51% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/Mutator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/Mutator.java index 8826ab66..481361f1 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/mutation/Mutator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/mutation/Mutator.java @@ -1,8 +1,8 @@ -package io.javaoperatorsdk.admissioncontroller.mutation; +package io.javaoperatorsdk.webhook.admission.mutation; import io.fabric8.kubernetes.api.model.KubernetesResource; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.Operation; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; public interface Mutator { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/AsyncDefaultRequestValidator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/AsyncDefaultAdmissionRequestValidator.java similarity index 72% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/AsyncDefaultRequestValidator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/AsyncDefaultAdmissionRequestValidator.java index f2635e42..a838dc9f 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/AsyncDefaultRequestValidator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/AsyncDefaultAdmissionRequestValidator.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.validation; +package io.javaoperatorsdk.webhook.admission.validation; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -7,16 +7,19 @@ import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -import io.javaoperatorsdk.admissioncontroller.*; +import io.javaoperatorsdk.webhook.admission.AdmissionUtils; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionRequestHandler; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.getTargetResource; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource; -public class AsyncDefaultRequestValidator - implements AsyncRequestHandler { +public class AsyncDefaultAdmissionRequestValidator + implements AsyncAdmissionRequestHandler { private final Validator validator; - public AsyncDefaultRequestValidator(Validator validator) { + public AsyncDefaultAdmissionRequestValidator(Validator validator) { this.validator = validator; } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/DefaultRequestValidator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/DefaultAdmissionRequestValidator.java similarity index 64% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/DefaultRequestValidator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/DefaultAdmissionRequestValidator.java index 29c1889d..4b810efc 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/DefaultRequestValidator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/DefaultAdmissionRequestValidator.java @@ -1,20 +1,21 @@ -package io.javaoperatorsdk.admissioncontroller.validation; +package io.javaoperatorsdk.webhook.admission.validation; import io.fabric8.kubernetes.api.model.KubernetesResource; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponse; -import io.javaoperatorsdk.admissioncontroller.AdmissionUtils; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.Operation; -import io.javaoperatorsdk.admissioncontroller.RequestHandler; +import io.javaoperatorsdk.webhook.admission.AdmissionRequestHandler; +import io.javaoperatorsdk.webhook.admission.AdmissionUtils; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; -import static io.javaoperatorsdk.admissioncontroller.AdmissionUtils.getTargetResource; +import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource; -public class DefaultRequestValidator implements RequestHandler { +public class DefaultAdmissionRequestValidator + implements AdmissionRequestHandler { private final Validator validator; - public DefaultRequestValidator(Validator validator) { + public DefaultAdmissionRequestValidator(Validator validator) { this.validator = validator; } diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/Validator.java b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/Validator.java similarity index 52% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/Validator.java rename to core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/Validator.java index 99622ee3..9dc8de45 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/validation/Validator.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/admission/validation/Validator.java @@ -1,8 +1,8 @@ -package io.javaoperatorsdk.admissioncontroller.validation; +package io.javaoperatorsdk.webhook.admission.validation; import io.fabric8.kubernetes.api.model.KubernetesResource; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.Operation; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.Operation; public interface Validator { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/Cloner.java b/core/src/main/java/io/javaoperatorsdk/webhook/clone/Cloner.java similarity index 84% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/Cloner.java rename to core/src/main/java/io/javaoperatorsdk/webhook/clone/Cloner.java index 956ee4e6..1f1a74a7 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/Cloner.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/clone/Cloner.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.clone; +package io.javaoperatorsdk.webhook.clone; public interface Cloner { diff --git a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/ObjectMapperCloner.java b/core/src/main/java/io/javaoperatorsdk/webhook/clone/ObjectMapperCloner.java similarity index 66% rename from core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/ObjectMapperCloner.java rename to core/src/main/java/io/javaoperatorsdk/webhook/clone/ObjectMapperCloner.java index f39141d9..5a993f9f 100644 --- a/core/src/main/java/io/javaoperatorsdk/admissioncontroller/clone/ObjectMapperCloner.java +++ b/core/src/main/java/io/javaoperatorsdk/webhook/clone/ObjectMapperCloner.java @@ -1,11 +1,11 @@ -package io.javaoperatorsdk.admissioncontroller.clone; +package io.javaoperatorsdk.webhook.clone; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; public class ObjectMapperCloner implements Cloner { - private final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private final ObjectMapper objectMapper = new ObjectMapper(); @Override public T clone(T object) { @@ -13,7 +13,7 @@ public T clone(T object) { return null; } try { - return (T) OBJECT_MAPPER.readValue(OBJECT_MAPPER.writeValueAsString(object), + return (T) objectMapper.readValue(objectMapper.writeValueAsString(object), object.getClass()); } catch (JsonProcessingException e) { throw new IllegalStateException(e); diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java new file mode 100644 index 00000000..ff1d5004 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java @@ -0,0 +1,81 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; + +import static io.javaoperatorsdk.webhook.conversion.Commons.*; + +public class AsyncConversionController implements AsyncConversionRequestHandler { + + private static final Logger log = LoggerFactory.getLogger(ConversionController.class); + + @SuppressWarnings("rawtypes") + private final Map mappers = new HashMap<>(); + + public void registerMapper(AsyncMapper mapper) { + String version = mapper.getClass().getDeclaredAnnotation(TargetVersion.class).value(); + if (mappers.get(version) != null) { + throw new IllegalStateException(MAPPER_ALREADY_REGISTERED_FOR_VERSION_MESSAGE + version); + } + mappers.put(version, mapper); + } + + @Override + public CompletionStage handle(ConversionReview conversionReview) { + try { + return convertObjects( + conversionReview.getRequest().getObjects(), + Utils.versionOfApiVersion(conversionReview.getRequest().getDesiredAPIVersion())) + .thenApply(convertedObjects -> createResponse(convertedObjects, conversionReview)); + } catch (MissingConversionMapperException e) { + log.error("Error in conversion hook. UID: {}", + conversionReview.getRequest().getUid(), e); + return CompletableFuture.completedStage(createErrorResponse(e, conversionReview)); + } + + } + + @SuppressWarnings("unchecked") + private CompletionStage> convertObjects(List objects, + String targetVersion) { + CompletableFuture[] completableFutures = new CompletableFuture[objects.size()]; + for (int i = 0; i < objects.size(); i++) { + completableFutures[i] = mapObject(objects.get(i), targetVersion); + } + return CompletableFuture.allOf(completableFutures).thenApply(r -> { + List result = new ArrayList<>(completableFutures.length); + for (CompletableFuture cf : completableFutures) { + result.add(cf.join()); + } + return result; + }); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private CompletableFuture mapObject(HasMetadata resource, String targetVersion) { + String sourceVersion = Utils.versionOfApiVersion(resource.getApiVersion()); + AsyncMapper sourceToHubMapper = mappers.get(sourceVersion); + if (sourceToHubMapper == null) { + throwMissingMapperForVersion(sourceVersion); + } + AsyncMapper hubToTarget = mappers.get(targetVersion); + if (hubToTarget == null) { + throwMissingMapperForVersion(targetVersion); + } + return sourceToHubMapper.toHub(resource) + .thenApply(r -> hubToTarget.fromHub(r).toCompletableFuture().join()) + .toCompletableFuture(); + + } + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionRequestHandler.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionRequestHandler.java new file mode 100644 index 00000000..fe12e086 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionRequestHandler.java @@ -0,0 +1,11 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.concurrent.CompletionStage; + +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; + +public interface AsyncConversionRequestHandler { + + CompletionStage handle(ConversionReview conversionReview); + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncMapper.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncMapper.java new file mode 100644 index 00000000..1ce3539e --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncMapper.java @@ -0,0 +1,13 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.concurrent.CompletionStage; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +public interface AsyncMapper { + + CompletionStage toHub(R resource); + + CompletionStage fromHub(HUB hub); + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Commons.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Commons.java new file mode 100644 index 00000000..d1433956 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Commons.java @@ -0,0 +1,45 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.List; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.Status; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionResponse; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; + +public class Commons { + + public static final String FAILED_STATUS_MESSAGE = "Failed"; + public static final String MAPPER_ALREADY_REGISTERED_FOR_VERSION_MESSAGE = + "Mapper already registered for version: "; + + public static ConversionReview createResponse(List convertedObjects, + ConversionReview conversionReview) { + ConversionReview result = new ConversionReview(); + var response = new ConversionResponse(); + response.setResult(new Status()); + response.getResult().setStatus("Success"); + response.setUid(conversionReview.getRequest().getUid()); + response.setConvertedObjects(convertedObjects); + result.setResponse(response); + return result; + } + + public static ConversionReview createErrorResponse(Exception e, + ConversionReview conversionReview) { + ConversionReview result = new ConversionReview(); + var response = new ConversionResponse(); + response.setUid(conversionReview.getRequest().getUid()); + response.setResult(new Status()); + response.getResult().setStatus(FAILED_STATUS_MESSAGE); + response.getResult().setMessage(e.getMessage()); + result.setResponse(response); + return result; + } + + public static void throwMissingMapperForVersion(String version) { + throw new MissingConversionMapperException( + "Missing mapper from version: " + version); + } + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java new file mode 100644 index 00000000..4c98f83c --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java @@ -0,0 +1,65 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; + +import static io.javaoperatorsdk.webhook.conversion.Commons.*; + +public class ConversionController implements ConversionRequestHandler { + + private static final Logger log = LoggerFactory.getLogger(ConversionController.class); + + + @SuppressWarnings("rawtypes") + private final Map mappers = new HashMap<>(); + + public void registerMapper(Mapper mapper) { + String version = mapper.getClass().getDeclaredAnnotation(TargetVersion.class).value(); + if (mappers.get(version) != null) { + throw new IllegalStateException(MAPPER_ALREADY_REGISTERED_FOR_VERSION_MESSAGE + version); + } + mappers.put(version, mapper); + } + + @Override + public ConversionReview handle(ConversionReview conversionReview) { + try { + List convertedObjects = + convertObjects(conversionReview.getRequest().getObjects(), + Utils.versionOfApiVersion(conversionReview.getRequest().getDesiredAPIVersion())); + return createResponse(convertedObjects, conversionReview); + } catch (MissingConversionMapperException e) { + log.error("Error in conversion hook. UID: {}", conversionReview.getRequest().getUid(), e); + return createErrorResponse(e, conversionReview); + } + } + + @SuppressWarnings("unchecked") + private List convertObjects(List objects, String targetVersion) { + return objects.stream().map(r -> mapObject(r, targetVersion)) + .collect(Collectors.toList()); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private HasMetadata mapObject(HasMetadata resource, String targetVersion) { + String sourceVersion = Utils.versionOfApiVersion(resource.getApiVersion()); + var sourceToHubMapper = mappers.get(sourceVersion); + if (sourceToHubMapper == null) { + throwMissingMapperForVersion(sourceVersion); + } + var hubToTarget = mappers.get(targetVersion); + if (hubToTarget == null) { + throwMissingMapperForVersion(targetVersion); + } + return hubToTarget.fromHub(sourceToHubMapper.toHub(resource)); + } + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionException.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionException.java new file mode 100644 index 00000000..61a0a3fc --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionException.java @@ -0,0 +1,23 @@ +package io.javaoperatorsdk.webhook.conversion; + +public class ConversionException extends RuntimeException { + + public ConversionException() {} + + public ConversionException(String message) { + super(message); + } + + public ConversionException(String message, Throwable cause) { + super(message, cause); + } + + public ConversionException(Throwable cause) { + super(cause); + } + + public ConversionException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionRequestHandler.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionRequestHandler.java new file mode 100644 index 00000000..1e22cdb1 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionRequestHandler.java @@ -0,0 +1,9 @@ +package io.javaoperatorsdk.webhook.conversion; + +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; + +public interface ConversionRequestHandler { + + ConversionReview handle(ConversionReview admissionRequest); + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Mapper.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Mapper.java new file mode 100644 index 00000000..d88f2696 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Mapper.java @@ -0,0 +1,11 @@ +package io.javaoperatorsdk.webhook.conversion; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +public interface Mapper { + + HUB toHub(R resource); + + R fromHub(HUB hub); + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/MissingConversionMapperException.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/MissingConversionMapperException.java new file mode 100644 index 00000000..009bd059 --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/MissingConversionMapperException.java @@ -0,0 +1,10 @@ +package io.javaoperatorsdk.webhook.conversion; + +public class MissingConversionMapperException extends ConversionException { + + public MissingConversionMapperException() {} + + public MissingConversionMapperException(String message) { + super(message); + } +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/TargetVersion.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/TargetVersion.java new file mode 100644 index 00000000..3521290f --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/TargetVersion.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface TargetVersion { + + /** + * The target version of the resource this mapper supports. Example values: "v1","v1beta1". This + * is not the full API Version just the version suffix, for example only the "v1" of api version: + * "apiextensions.k8s.io/v1" + **/ + String value(); + +} diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java new file mode 100644 index 00000000..7f16d81e --- /dev/null +++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.webhook.conversion; + +public class Utils { + + private Utils() {} + + /** + * @param apiVersion like "apiextensions.k8s.io/v1" + * @return version suffix; "v1" from the example above + */ + public static String versionOfApiVersion(String apiVersion) { + var lastDelimiter = apiVersion.lastIndexOf("/"); + return apiVersion.substring(lastDelimiter + 1); + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerTest.java b/core/src/test/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerTest.java deleted file mode 100644 index b3f0da20..00000000 --- a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/AdmissionControllerTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.javaoperatorsdk.admissioncontroller; - -import org.junit.jupiter.api.Test; - -import io.fabric8.kubernetes.api.model.HasMetadata; - -import static io.javaoperatorsdk.admissioncontroller.Commons.*; - -class AdmissionControllerTest { - - @Test - void validatesResource() { - AdmissionController admissionController = - new AdmissionController<>((resource, operation) -> { - if (resource.getMetadata().getLabels().get(Commons.LABEL_KEY) == null) { - throw new NotAllowedException(MISSING_REQUIRED_LABEL); - } - }); - var inputAdmissionReview = createTestAdmissionReview(); - - var response = admissionController.handle(inputAdmissionReview); - - assertValidation(response, inputAdmissionReview.getRequest().getUid()); - } - - @Test - void mutatesResource() { - AdmissionController admissionController = - new AdmissionController<>((resource, operation) -> { - resource.getMetadata().getLabels().putIfAbsent(Commons.LABEL_KEY, LABEL_TEST_VALUE); - return resource; - }); - var inputAdmissionReview = createTestAdmissionReview(); - - var response = admissionController.handle(inputAdmissionReview); - - assertMutation(response); - } -} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerTest.java new file mode 100644 index 00000000..1026f3b4 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionControllerTest.java @@ -0,0 +1,34 @@ +package io.javaoperatorsdk.webhook.admission; + +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.api.model.HasMetadata; + +import static io.javaoperatorsdk.webhook.admission.AdmissionTestSupport.*; + +class AdmissionControllerTest { + + AdmissionTestSupport admissionTestSupport = new AdmissionTestSupport(); + + @Test + void validatesResource() { + AdmissionController admissionController = + new AdmissionController<>((resource, operation) -> { + if (resource.getMetadata().getLabels().get(AdmissionTestSupport.LABEL_KEY) == null) { + throw new NotAllowedException(MISSING_REQUIRED_LABEL); + } + }); + admissionTestSupport.validatesResource(admissionController::handle); + } + + @Test + void mutatesResource() { + AdmissionController admissionController = + new AdmissionController<>((resource, operation) -> { + resource.getMetadata().getLabels().putIfAbsent(AdmissionTestSupport.LABEL_KEY, + LABEL_TEST_VALUE); + return resource; + }); + admissionTestSupport.mutatesResource(admissionController::handle); + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/Commons.java b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionTestSupport.java similarity index 73% rename from core/src/test/java/io/javaoperatorsdk/admissioncontroller/Commons.java rename to core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionTestSupport.java index baacb40b..31b33e06 100644 --- a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/Commons.java +++ b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AdmissionTestSupport.java @@ -1,9 +1,10 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import java.io.IOException; import java.io.InputStream; import java.util.Base64; import java.util.UUID; +import java.util.function.Function; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; @@ -12,7 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat; -public class Commons { +public class AdmissionTestSupport { public static final String LABEL_KEY = "app.kubernetes.io/name"; public static final String MISSING_REQUIRED_LABEL = "Missing required label."; @@ -25,7 +26,7 @@ public static AdmissionReview createTestAdmissionReview() { request.setOperation(Operation.CREATE.name()); request.setUid(UUID.randomUUID().toString()); Deployment deployment = null; - try (InputStream is = Commons.class.getResourceAsStream("deployment.yaml")) { + try (InputStream is = AdmissionTestSupport.class.getResourceAsStream("deployment.yaml")) { deployment = Serialization.unmarshal(is, Deployment.class); request.setObject(deployment); } catch (IOException e) { @@ -34,21 +35,31 @@ public static AdmissionReview createTestAdmissionReview() { return admissionReview; } - public static void assertMutation(AdmissionReview admissionReview) { - assertThat(admissionReview.getResponse().getAllowed()).isTrue(); - String patch = new String(Base64.getDecoder().decode(admissionReview.getResponse().getPatch())); - assertThat(patch) - .isEqualTo( - "[{\"op\":\"add\",\"path\":\"/metadata/labels/app.kubernetes.io~1name\",\"value\":\"mutation-test\"}]"); - } - public static void assertValidation(AdmissionReview admissionReview, String requestUid) { + + void validatesResource(Function function) { + var inputAdmissionReview = createTestAdmissionReview(); + + var admissionReview = function.apply(inputAdmissionReview); + assertThat(admissionReview.getResponse().getUid()) - .isEqualTo(requestUid); + .isEqualTo(inputAdmissionReview.getRequest().getUid()); assertThat(admissionReview.getResponse().getStatus().getCode()).isEqualTo(403); assertThat(admissionReview.getResponse().getStatus().getMessage()) .isEqualTo(MISSING_REQUIRED_LABEL); assertThat(admissionReview.getResponse().getAllowed()).isFalse(); } + void mutatesResource(Function function) { + var inputAdmissionReview = createTestAdmissionReview(); + + var admissionReview = function.apply(inputAdmissionReview); + + assertThat(admissionReview.getResponse().getAllowed()).isTrue(); + String patch = new String(Base64.getDecoder().decode(admissionReview.getResponse().getPatch())); + assertThat(patch) + .isEqualTo( + "[{\"op\":\"add\",\"path\":\"/metadata/labels/app.kubernetes.io~1name\",\"value\":\"mutation-test\"}]"); + } + } diff --git a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionControllerTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionControllerTest.java similarity index 57% rename from core/src/test/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionControllerTest.java rename to core/src/test/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionControllerTest.java index 9591894f..646d60d2 100644 --- a/core/src/test/java/io/javaoperatorsdk/admissioncontroller/AsyncAdmissionControllerTest.java +++ b/core/src/test/java/io/javaoperatorsdk/webhook/admission/AsyncAdmissionControllerTest.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller; +package io.javaoperatorsdk.webhook.admission; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -6,13 +6,14 @@ import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.HasMetadata; -import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; -import io.javaoperatorsdk.admissioncontroller.mutation.AsyncMutator; +import io.javaoperatorsdk.webhook.admission.mutation.AsyncMutator; -import static io.javaoperatorsdk.admissioncontroller.Commons.*; +import static io.javaoperatorsdk.webhook.admission.AdmissionTestSupport.*; class AsyncAdmissionControllerTest { + AdmissionTestSupport admissionTestSupport = new AdmissionTestSupport(); + @Test void validatesResource() throws ExecutionException, InterruptedException { AsyncAdmissionController admissionController = @@ -21,12 +22,12 @@ void validatesResource() throws ExecutionException, InterruptedException { throw new NotAllowedException(MISSING_REQUIRED_LABEL); } }); - var inputAdmissionReview = createTestAdmissionReview(); - CompletableFuture response = - (CompletableFuture) admissionController.handle(inputAdmissionReview); - assertValidation(response.get(), inputAdmissionReview.getRequest().getUid()); + admissionTestSupport + .validatesResource(res -> admissionController.handle(res).toCompletableFuture().join()); + + } @Test @@ -37,12 +38,9 @@ void mutatesResource() throws ExecutionException, InterruptedException { resource.getMetadata().getLabels().putIfAbsent(LABEL_KEY, LABEL_TEST_VALUE); return resource; })); - var inputAdmissionReview = createTestAdmissionReview(); - - CompletableFuture response = - (CompletableFuture) admissionController.handle(inputAdmissionReview); - assertMutation(response.get()); + admissionTestSupport + .mutatesResource(res -> admissionController.handle(res).toCompletableFuture().join()); } } diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionControllerTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionControllerTest.java new file mode 100644 index 00000000..4365e496 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionControllerTest.java @@ -0,0 +1,53 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.concurrent.ExecutionException; +import java.util.function.Function; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionResponse; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; +import io.javaoperatorsdk.webhook.conversion.mapper.*; + +class AsyncConversionControllerTest { + + ConversionTestSupport conversionTestSupport = new ConversionTestSupport(); + AsyncConversionController controller = new AsyncConversionController(); + + @BeforeEach + void setup() { + controller.registerMapper(new AsyncV1Mapper()); + controller.registerMapper(new AsyncV2Mapper()); + controller.registerMapper(new AsyncV3Mapper()); + } + + @Test + void handlesSimpleConversion() { + conversionTestSupport.handlesSimpleConversion(getConversionReviewConversionResponseFunction()); + } + + + @Test + void convertsVariousVersionsInSingleRequest() { + conversionTestSupport + .convertsVariousVersionsInSingleRequest(getConversionReviewConversionResponseFunction()); + } + + @Test + void errorResponseOnMissingMapper() { + conversionTestSupport + .errorResponseOnMissingMapper(getConversionReviewConversionResponseFunction()); + } + + private Function getConversionReviewConversionResponseFunction() { + return request -> { + try { + return controller.handle(request).toCompletableFuture().get().getResponse(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }; + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionControllerTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionControllerTest.java new file mode 100644 index 00000000..f040218a --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionControllerTest.java @@ -0,0 +1,47 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.function.Function; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionResponse; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; +import io.javaoperatorsdk.webhook.conversion.mapper.CustomResourceV1Mapper; +import io.javaoperatorsdk.webhook.conversion.mapper.CustomResourceV2Mapper; +import io.javaoperatorsdk.webhook.conversion.mapper.CustomResourceV3Mapper; + +public class ConversionControllerTest { + + ConversionTestSupport conversionTestSupport = new ConversionTestSupport(); + ConversionController controller = new ConversionController(); + + @BeforeEach + void setup() { + controller.registerMapper(new CustomResourceV1Mapper()); + controller.registerMapper(new CustomResourceV2Mapper()); + controller.registerMapper(new CustomResourceV3Mapper()); + } + + @Test + void handlesSimpleConversion() { + conversionTestSupport.handlesSimpleConversion(getConversionReviewConversionResponseFunction()); + } + + @Test + void convertsVariousVersionsInSingleRequest() { + conversionTestSupport + .convertsVariousVersionsInSingleRequest(getConversionReviewConversionResponseFunction()); + } + + @Test + void errorResponseOnMissingMapper() { + conversionTestSupport + .errorResponseOnMissingMapper(getConversionReviewConversionResponseFunction()); + } + + private Function getConversionReviewConversionResponseFunction() { + return request -> controller.handle(request).getResponse(); + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionTestSupport.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionTestSupport.java new file mode 100644 index 00000000..ee2a3b46 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/ConversionTestSupport.java @@ -0,0 +1,111 @@ +package io.javaoperatorsdk.webhook.conversion; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; + +import io.fabric8.kubernetes.api.model.HasMetadata; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionRequest; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionResponse; +import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview; +import io.javaoperatorsdk.webhook.conversion.crd.*; + +import static io.javaoperatorsdk.webhook.conversion.Commons.FAILED_STATUS_MESSAGE; +import static org.assertj.core.api.Assertions.assertThat; + +public class ConversionTestSupport { + + public static final String DEFAULT_ADDITIONAL_VALUE = "defaultAdditionalValue"; + public static final String DEFAULT_THIRD_VALUE = "defaultThirdValue"; + public static final String V1 = "v1"; + public static final String V2 = "v2"; + public static final String V3 = "v3"; + public static final int VALUE = 1; + public static final String V1_NAME = "v1name"; + public static final String V2_NAME = "v2name"; + public static final String V3_NAME = "v3name"; + public static final String API_GROUP = "sample.javaoperatorsdk"; + + void handlesSimpleConversion(Function func) { + var request = createRequest(V2, v1resource()); + + var response = func.apply(request); + + assertThat(response.getConvertedObjects()).hasSize(1); + assertThat(response.getUid()).isEqualTo(request.getRequest().getUid()); + CustomResourceV2 convertedObject = (CustomResourceV2) response.getConvertedObjects().get(0); + assertThat(convertedObject.getMetadata()).isEqualTo(v1resource().getMetadata()); + assertThat(convertedObject.getSpec().getAdditionalValue()).isEqualTo(DEFAULT_ADDITIONAL_VALUE); + assertThat(convertedObject.getSpec().getValue()).isEqualTo(String.valueOf(VALUE)); + } + + void convertsVariousVersionsInSingleRequest(Function func) { + var request = createRequest(V3, v1resource(), v2resource(), v3resource()); + + var response = func.apply(request); + + assertThat(response.getConvertedObjects()).hasSize(3); + List namesInOrder = response.getConvertedObjects().stream() + .map(r -> r.getMetadata().getName()).collect(Collectors.toList()); + assertThat(namesInOrder).containsExactly(V1_NAME, V2_NAME, V3_NAME); + assertThat(response.getConvertedObjects()).allMatch(r -> r instanceof CustomResourceV3); + } + + void errorResponseOnMissingMapper(Function func) { + var request = createRequest("v4", v1resource()); + + var response = func.apply(request); + + assertThat(response.getUid()).isEqualTo(request.getRequest().getUid()); + assertThat(response.getResult().getStatus()).isEqualTo(FAILED_STATUS_MESSAGE); + assertThat(response.getResult().getMessage()).contains("Missing", "v4"); + } + + public static ConversionReview createRequest(String targetVersion, HasMetadata... resources) { + ConversionReview review = new ConversionReview(); + ConversionRequest request = new ConversionRequest(); + request.setDesiredAPIVersion(API_GROUP + "/" + targetVersion); + request.setUid(UUID.randomUUID().toString()); + request.setObjects(Arrays.asList(resources)); + review.setRequest(request); + return review; + } + + public static CustomResourceV1 v1resource() { + var r = new CustomResourceV1(); + r.setMetadata(new ObjectMetaBuilder() + .withName(V1_NAME).withNamespace("default") + .build()); + r.setSpec(new CustomResourceV1Spec()); + r.getSpec().setValue(VALUE); + return r; + } + + public static CustomResourceV2 v2resource() { + var r = new CustomResourceV2(); + r.setMetadata(new ObjectMetaBuilder() + .withName(V2_NAME).withNamespace("default") + .build()); + r.setSpec(new CustomResourceV2Spec()); + r.getSpec().setValue("2"); + r.getSpec().setAdditionalValue("additionalValueV2"); + return r; + } + + public static CustomResourceV3 v3resource() { + var r = new CustomResourceV3(); + r.setMetadata(new ObjectMetaBuilder() + .withName(V3_NAME).withNamespace("default") + .build()); + r.setSpec(new CustomResourceV3Spec()); + r.getSpec().setValue("3"); + r.getSpec().setAdditionalValue("additionalValueV3"); + r.getSpec().setThirdValue("thirdValue"); + return r; + } + + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java new file mode 100644 index 00000000..6229d126 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.webhook.conversion; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class UtilsTest { + + @Test + void getsVersionFromApiVersion() { + assertThat(Utils.versionOfApiVersion("apiextensions.k8s.io/v1")).isEqualTo("v1"); + assertThat(Utils.versionOfApiVersion("extensions/v1beta1")).isEqualTo("v1beta1"); + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java new file mode 100644 index 00000000..ea003ef6 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java @@ -0,0 +1,20 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Kind; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version("v1") +@Kind("MultiVersionCustomResource") +@ShortNames("mv1") +public class CustomResourceV1 + extends + CustomResource + implements Namespaced { + + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Spec.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Spec.java new file mode 100644 index 00000000..7ffc65d8 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Spec.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV1Spec { + + private int value; + + public int getValue() { + return value; + } + + public CustomResourceV1Spec setValue(int value) { + this.value = value; + return this; + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Status.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Status.java new file mode 100644 index 00000000..64237de7 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1Status.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV1Status { + + private int value1; + + public int getValue1() { + return value1; + } + + public CustomResourceV1Status setValue1(int value1) { + this.value1 = value1; + return this; + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java new file mode 100644 index 00000000..0f357f92 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Kind; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version(value = "v2", storage = false) +@Kind("MultiVersionCustomResource") +@ShortNames("mv2") +public class CustomResourceV2 + extends + CustomResource + implements Namespaced { + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Spec.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Spec.java new file mode 100644 index 00000000..efe1137a --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Spec.java @@ -0,0 +1,26 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV2Spec { + + private String value; + + private String additionalValue; + + public String getValue() { + return value; + } + + public CustomResourceV2Spec setValue(String value) { + this.value = value; + return this; + } + + public String getAdditionalValue() { + return additionalValue; + } + + public CustomResourceV2Spec setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + return this; + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Status.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Status.java new file mode 100644 index 00000000..72b66388 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2Status.java @@ -0,0 +1,16 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV2Status { + + private int value1; + + public int getValue1() { + return value1; + } + + public CustomResourceV2Status setValue1(int value1) { + this.value1 = value1; + return this; + } + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java new file mode 100644 index 00000000..2916fb8f --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +import io.fabric8.kubernetes.api.model.Namespaced; +import io.fabric8.kubernetes.client.CustomResource; +import io.fabric8.kubernetes.model.annotation.Group; +import io.fabric8.kubernetes.model.annotation.Kind; +import io.fabric8.kubernetes.model.annotation.ShortNames; +import io.fabric8.kubernetes.model.annotation.Version; + +@Group("sample.javaoperatorsdk") +@Version(value = "v3", storage = false) +@Kind("MultiVersionCustomResource") +@ShortNames("mv3") +public class CustomResourceV3 + extends + CustomResource + implements Namespaced { + +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Spec.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Spec.java new file mode 100644 index 00000000..acbdfda1 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Spec.java @@ -0,0 +1,37 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV3Spec { + + private String value; + + private String additionalValue; + + private String thirdValue; + + public String getValue() { + return value; + } + + public CustomResourceV3Spec setValue(String value) { + this.value = value; + return this; + } + + public String getAdditionalValue() { + return additionalValue; + } + + public CustomResourceV3Spec setAdditionalValue(String additionalValue) { + this.additionalValue = additionalValue; + return this; + } + + public String getThirdValue() { + return thirdValue; + } + + public CustomResourceV3Spec setThirdValue(String thirdValue) { + this.thirdValue = thirdValue; + return this; + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Status.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Status.java new file mode 100644 index 00000000..e3c857e3 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3Status.java @@ -0,0 +1,15 @@ +package io.javaoperatorsdk.webhook.conversion.crd; + +public class CustomResourceV3Status { + + private int value1; + + public int getValue1() { + return value1; + } + + public CustomResourceV3Status setValue1(int value1) { + this.value1 = value1; + return this; + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV1Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV1Mapper.java new file mode 100644 index 00000000..c2c4f700 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV1Mapper.java @@ -0,0 +1,25 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import io.javaoperatorsdk.webhook.conversion.AsyncMapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV1; +import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV3; + +@TargetVersion("v1") +public class AsyncV1Mapper implements AsyncMapper { + + CustomResourceV1Mapper mapper = new CustomResourceV1Mapper(); + + @Override + public CompletionStage toHub(CustomResourceV1 resource) { + return CompletableFuture.completedStage(mapper.toHub(resource)); + } + + @Override + public CompletionStage fromHub(CustomResourceV3 customResourceV3) { + return CompletableFuture.completedStage(mapper.fromHub(customResourceV3)); + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV2Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV2Mapper.java new file mode 100644 index 00000000..a8ca2a8f --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV2Mapper.java @@ -0,0 +1,25 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import io.javaoperatorsdk.webhook.conversion.AsyncMapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV2; +import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV3; + +@TargetVersion("v2") +public class AsyncV2Mapper implements AsyncMapper { + + CustomResourceV2Mapper mapper = new CustomResourceV2Mapper(); + + @Override + public CompletionStage toHub(CustomResourceV2 resource) { + return CompletableFuture.completedStage(mapper.toHub(resource)); + } + + @Override + public CompletionStage fromHub(CustomResourceV3 customResourceV3) { + return CompletableFuture.completedStage(mapper.fromHub(customResourceV3)); + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV3Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV3Mapper.java new file mode 100644 index 00000000..332ad1c5 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/AsyncV3Mapper.java @@ -0,0 +1,24 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +import io.javaoperatorsdk.webhook.conversion.AsyncMapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV3; + +@TargetVersion("v3") +public class AsyncV3Mapper implements AsyncMapper { + + CustomResourceV3Mapper mapper = new CustomResourceV3Mapper(); + + @Override + public CompletionStage toHub(CustomResourceV3 resource) { + return CompletableFuture.completedStage(mapper.toHub(resource)); + } + + @Override + public CompletionStage fromHub(CustomResourceV3 customResourceV3) { + return CompletableFuture.completedStage(mapper.fromHub(customResourceV3)); + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV1Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV1Mapper.java new file mode 100644 index 00000000..16ff7c21 --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV1Mapper.java @@ -0,0 +1,41 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import io.javaoperatorsdk.webhook.conversion.Mapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.*; + +import static io.javaoperatorsdk.webhook.conversion.ConversionTestSupport.DEFAULT_ADDITIONAL_VALUE; +import static io.javaoperatorsdk.webhook.conversion.ConversionTestSupport.DEFAULT_THIRD_VALUE; + +@TargetVersion("v1") +public class CustomResourceV1Mapper implements Mapper { + + @Override + public CustomResourceV3 toHub(CustomResourceV1 resource) { + CustomResourceV3 hub = new CustomResourceV3(); + hub.setMetadata(resource.getMetadata()); + var spec = new CustomResourceV3Spec(); + spec.setValue(Integer.toString(resource.getSpec().getValue())); + spec.setAdditionalValue(DEFAULT_ADDITIONAL_VALUE); + spec.setThirdValue(DEFAULT_THIRD_VALUE); + hub.setSpec(spec); + if (resource.getStatus() != null) { + hub.setStatus(new CustomResourceV3Status()); + hub.getStatus().setValue1(resource.getStatus().getValue1()); + } + return hub; + } + + @Override + public CustomResourceV1 fromHub(CustomResourceV3 hub) { + CustomResourceV1 resource = new CustomResourceV1(); + resource.setMetadata(hub.getMetadata()); + resource.setSpec(new CustomResourceV1Spec()); + resource.getSpec().setValue(Integer.parseInt(hub.getSpec().getValue())); + if (resource.getStatus() != null) { + resource.setStatus(new CustomResourceV1Status()); + resource.getStatus().setValue1(hub.getStatus().getValue1()); + } + return resource; + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV2Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV2Mapper.java new file mode 100644 index 00000000..f4bb700c --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV2Mapper.java @@ -0,0 +1,42 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import io.javaoperatorsdk.webhook.conversion.Mapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.*; + +import static io.javaoperatorsdk.webhook.conversion.ConversionTestSupport.DEFAULT_ADDITIONAL_VALUE; +import static io.javaoperatorsdk.webhook.conversion.ConversionTestSupport.DEFAULT_THIRD_VALUE; + +@TargetVersion("v2") +public class CustomResourceV2Mapper implements Mapper { + + @Override + public CustomResourceV3 toHub(CustomResourceV2 resource) { + CustomResourceV3 hub = new CustomResourceV3(); + hub.setMetadata(resource.getMetadata()); + var spec = new CustomResourceV3Spec(); + spec.setValue(resource.getSpec().getValue()); + spec.setAdditionalValue(DEFAULT_ADDITIONAL_VALUE); + spec.setThirdValue(DEFAULT_THIRD_VALUE); + hub.setSpec(spec); + if (resource.getStatus() != null) { + hub.setStatus(new CustomResourceV3Status()); + hub.getStatus().setValue1(resource.getStatus().getValue1()); + } + return hub; + } + + @Override + public CustomResourceV2 fromHub(CustomResourceV3 hub) { + CustomResourceV2 resource = new CustomResourceV2(); + resource.setMetadata(hub.getMetadata()); + resource.setSpec(new CustomResourceV2Spec()); + resource.getSpec().setValue(hub.getSpec().getValue()); + resource.getSpec().setAdditionalValue(hub.getSpec().getAdditionalValue()); + if (resource.getStatus() != null) { + resource.setStatus(new CustomResourceV2Status()); + resource.getStatus().setValue1(hub.getStatus().getValue1()); + } + return resource; + } +} diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV3Mapper.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV3Mapper.java new file mode 100644 index 00000000..963812db --- /dev/null +++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/mapper/CustomResourceV3Mapper.java @@ -0,0 +1,19 @@ +package io.javaoperatorsdk.webhook.conversion.mapper; + +import io.javaoperatorsdk.webhook.conversion.Mapper; +import io.javaoperatorsdk.webhook.conversion.TargetVersion; +import io.javaoperatorsdk.webhook.conversion.crd.*; + +@TargetVersion("v3") +public class CustomResourceV3Mapper implements Mapper { + + @Override + public CustomResourceV3 toHub(CustomResourceV3 resource) { + return resource; + } + + @Override + public CustomResourceV3 fromHub(CustomResourceV3 hub) { + return hub; + } +} diff --git a/core/src/test/resources/io/javaoperatorsdk/admissioncontroller/deployment.yaml b/core/src/test/resources/io/javaoperatorsdk/webhook/admission/deployment.yaml similarity index 100% rename from core/src/test/resources/io/javaoperatorsdk/admissioncontroller/deployment.yaml rename to core/src/test/resources/io/javaoperatorsdk/webhook/admission/deployment.yaml diff --git a/pom.xml b/pom.xml index 412c40a4..d9eba037 100644 --- a/pom.xml +++ b/pom.xml @@ -40,7 +40,7 @@ https://sonarcloud.io 5.8.2 - 5.10.1 + 5.12.2 1.7.32 2.17.1 4.1.0 diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml index a6952857..869374c0 100644 --- a/samples/quarkus/pom.xml +++ b/samples/quarkus/pom.xml @@ -7,7 +7,7 @@ admission-controller-framework-samples 0.2.1-SNAPSHOT - io.javaoperatorsdk.admissioncontroller.sample + webhook.sample quarkus-sample Admission Controller Framework - Samples - Quarkus diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionControllerConfig.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java similarity index 88% rename from samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionControllerConfig.java rename to samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java index 88b14138..7bf370b2 100644 --- a/samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionControllerConfig.java +++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.quarkus; +package io.javaoperatorsdk.webhook.admission.sample.quarkus; import java.util.concurrent.CompletableFuture; @@ -7,12 +7,12 @@ import javax.inject.Singleton; import io.fabric8.kubernetes.api.model.Pod; -import io.javaoperatorsdk.admissioncontroller.AdmissionController; -import io.javaoperatorsdk.admissioncontroller.AsyncAdmissionController; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.mutation.AsyncMutator; -import io.javaoperatorsdk.admissioncontroller.mutation.Mutator; -import io.javaoperatorsdk.admissioncontroller.validation.Validator; +import io.javaoperatorsdk.webhook.admission.AdmissionController; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.mutation.AsyncMutator; +import io.javaoperatorsdk.webhook.admission.mutation.Mutator; +import io.javaoperatorsdk.webhook.admission.validation.Validator; @Dependent public class AdmissionControllerConfig { diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpoint.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java similarity index 78% rename from samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpoint.java rename to samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java index c32935ab..d544cb00 100644 --- a/samples/quarkus/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpoint.java +++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.quarkus; +package io.javaoperatorsdk.webhook.admission.sample.quarkus; import javax.inject.Inject; import javax.inject.Named; @@ -7,12 +7,10 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; -import io.javaoperatorsdk.admissioncontroller.AdmissionController; -import io.javaoperatorsdk.admissioncontroller.AsyncAdmissionController; +import io.javaoperatorsdk.webhook.admission.AdmissionController; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import io.smallrye.mutiny.Uni; -import static io.javaoperatorsdk.admissioncontroller.sample.quarkus.AdmissionControllerConfig.*; - @Path("/") public class AdmissionEndpoint { @@ -36,14 +34,14 @@ public class AdmissionEndpoint { @Inject public AdmissionEndpoint( - @Named(MUTATING_CONTROLLER) AdmissionController mutationController, - @Named(VALIDATING_CONTROLLER) AdmissionController validationController, - @Named(ERROR_MUTATING_CONTROLLER) AdmissionController errorMutationController, - @Named(ERROR_VALIDATING_CONTROLLER) AdmissionController errorValidationController, - @Named(ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController asyncMutationController, - @Named(ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController asyncValidationController, - @Named(ERROR_ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController errorAsyncMutationController, - @Named(ERROR_ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController errorAsyncValidationController) { + @Named(AdmissionControllerConfig.MUTATING_CONTROLLER) AdmissionController mutationController, + @Named(AdmissionControllerConfig.VALIDATING_CONTROLLER) AdmissionController validationController, + @Named(AdmissionControllerConfig.ERROR_MUTATING_CONTROLLER) AdmissionController errorMutationController, + @Named(AdmissionControllerConfig.ERROR_VALIDATING_CONTROLLER) AdmissionController errorValidationController, + @Named(AdmissionControllerConfig.ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController asyncMutationController, + @Named(AdmissionControllerConfig.ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController asyncValidationController, + @Named(AdmissionControllerConfig.ERROR_ASYNC_MUTATING_CONTROLLER) AsyncAdmissionController errorAsyncMutationController, + @Named(AdmissionControllerConfig.ERROR_ASYNC_VALIDATING_CONTROLLER) AsyncAdmissionController errorAsyncValidationController) { this.mutationController = mutationController; this.validationController = validationController; this.errorMutationController = errorMutationController; diff --git a/samples/quarkus/src/main/resources/META-INF/resources/index.html b/samples/quarkus/src/main/resources/META-INF/resources/index.html index 79ba34e6..efa5eea2 100644 --- a/samples/quarkus/src/main/resources/META-INF/resources/index.html +++ b/samples/quarkus/src/main/resources/META-INF/resources/index.html @@ -143,7 +143,7 @@

RESTEasy JAX-RS

Application

    -
  • GroupId: io.javaoperatorsdk.admissioncontroller.sample
  • +
  • GroupId: webhook.sample
  • ArtifactId: quarkus-sample
  • Version: 1.0.0-SNAPSHOT
  • Quarkus Version: 2.5.4.Final
  • diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpointTest.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java similarity index 81% rename from samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpointTest.java rename to samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java index ca9b1c51..9d32bd13 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/AdmissionEndpointTest.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.quarkus; +package io.javaoperatorsdk.webhook.admission.sample.quarkus; import java.io.IOException; import java.io.InputStream; @@ -10,7 +10,6 @@ import io.quarkus.test.junit.QuarkusTest; import io.restassured.http.ContentType; -import static io.javaoperatorsdk.admissioncontroller.sample.quarkus.AdmissionEndpoint.*; import static io.restassured.RestAssured.given; import static org.hamcrest.CoreMatchers.is; @@ -24,42 +23,42 @@ class AdmissionEndpointTest { @Test void mutates() { - testMutate(MUTATE_PATH); + testMutate(AdmissionEndpoint.MUTATE_PATH); } @Test void validates() { - testValidate(VALIDATE_PATH); + testValidate(AdmissionEndpoint.VALIDATE_PATH); } @Test void errorMutates() { - testServerErrorOnPath(ERROR_MUTATE_PATH); + testServerErrorOnPath(AdmissionEndpoint.ERROR_MUTATE_PATH); } @Test void errorValidates() { - testServerErrorOnPath(ERROR_VALIDATE_PATH); + testServerErrorOnPath(AdmissionEndpoint.ERROR_VALIDATE_PATH); } @Test void asyncMutates() { - testMutate(ASYNC_MUTATE_PATH); + testMutate(AdmissionEndpoint.ASYNC_MUTATE_PATH); } @Test void asyncValidates() { - testValidate(ASYNC_VALIDATE_PATH); + testValidate(AdmissionEndpoint.ASYNC_VALIDATE_PATH); } @Test void errorAsyncValidation() { - testServerErrorOnPath(ERROR_ASYNC_VALIDATE_PATH); + testServerErrorOnPath(AdmissionEndpoint.ERROR_ASYNC_VALIDATE_PATH); } @Test void errorAsyncMutation() { - testServerErrorOnPath(ERROR_ASYNC_MUTATE_PATH); + testServerErrorOnPath(AdmissionEndpoint.ERROR_ASYNC_MUTATE_PATH); } private void testServerErrorOnPath(String path) { diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/NativeAdmissionEndpointIT.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java similarity index 74% rename from samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/NativeAdmissionEndpointIT.java rename to samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java index dca389e2..80970f09 100644 --- a/samples/quarkus/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/quarkus/NativeAdmissionEndpointIT.java +++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.quarkus; +package io.javaoperatorsdk.webhook.admission.sample.quarkus; import io.quarkus.test.junit.NativeImageTest; diff --git a/samples/spring-boot/pom.xml b/samples/spring-boot/pom.xml index 79c01b82..6b6113d1 100644 --- a/samples/spring-boot/pom.xml +++ b/samples/spring-boot/pom.xml @@ -8,7 +8,7 @@ 0.2.1-SNAPSHOT - io.javaoperatorsdk.admissioncontroller.sample + webhook.sample spring-boot-sample 0.2.1-SNAPSHOT Admission Controller Framework - Samples - Spring Boot diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpoint.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java similarity index 95% rename from samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpoint.java rename to samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java index 42289545..a3c7d24d 100644 --- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpoint.java +++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.springboot; +package io.javaoperatorsdk.webhook.sample.springboot; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -9,8 +9,8 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview; -import io.javaoperatorsdk.admissioncontroller.AdmissionController; -import io.javaoperatorsdk.admissioncontroller.AsyncAdmissionController; +import io.javaoperatorsdk.webhook.admission.AdmissionController; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; import reactor.core.publisher.Mono; diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/Config.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java similarity index 84% rename from samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/Config.java rename to samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java index cf6c57a6..ccc754b1 100644 --- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/Config.java +++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.springboot; +package io.javaoperatorsdk.webhook.sample.springboot; import java.util.concurrent.CompletableFuture; @@ -6,12 +6,12 @@ import org.springframework.context.annotation.Configuration; import io.fabric8.kubernetes.api.model.Pod; -import io.javaoperatorsdk.admissioncontroller.AdmissionController; -import io.javaoperatorsdk.admissioncontroller.AsyncAdmissionController; -import io.javaoperatorsdk.admissioncontroller.NotAllowedException; -import io.javaoperatorsdk.admissioncontroller.mutation.AsyncMutator; -import io.javaoperatorsdk.admissioncontroller.mutation.Mutator; -import io.javaoperatorsdk.admissioncontroller.validation.Validator; +import io.javaoperatorsdk.webhook.admission.AdmissionController; +import io.javaoperatorsdk.webhook.admission.AsyncAdmissionController; +import io.javaoperatorsdk.webhook.admission.NotAllowedException; +import io.javaoperatorsdk.webhook.admission.mutation.AsyncMutator; +import io.javaoperatorsdk.webhook.admission.mutation.Mutator; +import io.javaoperatorsdk.webhook.admission.validation.Validator; @Configuration public class Config { diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplication.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/SpringBootSampleApplication.java similarity index 82% rename from samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplication.java rename to samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/SpringBootSampleApplication.java index 22f14c0b..6341bec3 100644 --- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplication.java +++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/SpringBootSampleApplication.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.springboot; +package io.javaoperatorsdk.webhook.sample.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplicationTests.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplicationTests.java deleted file mode 100644 index 18298be6..00000000 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/SpringBootSampleApplicationTests.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.javaoperatorsdk.admissioncontroller.sample.springboot; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SpringBootSampleApplicationTests { - - @Test - void contextLoads() {} - -} diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpointTest.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java similarity index 94% rename from samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpointTest.java rename to samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java index 52d2b903..1f7f983b 100644 --- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/admissioncontroller/sample/springboot/AdmissionEndpointTest.java +++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java @@ -1,4 +1,4 @@ -package io.javaoperatorsdk.admissioncontroller.sample.springboot; +package io.javaoperatorsdk.webhook.sample.springboot; import java.io.IOException; import java.nio.file.Files; @@ -15,7 +15,7 @@ import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; -import static io.javaoperatorsdk.admissioncontroller.sample.springboot.AdmissionEndpoint.*; +import static io.javaoperatorsdk.webhook.sample.springboot.AdmissionEndpoint.*; @Import(Config.class) @WebFluxTest(AdmissionEndpoint.class)