Skip to content

Support for passing old resource to validator #330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import io.javaoperatorsdk.webhook.admission.Operation;

import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.allowedAdmissionResponse;
import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource;
import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.notAllowedExceptionToAdmissionResponse;

public class AsyncDefaultAdmissionRequestValidator<T extends KubernetesResource>
Expand All @@ -28,9 +27,11 @@ public AsyncDefaultAdmissionRequestValidator(Validator<T> validator) {
@SuppressWarnings("unchecked")
public CompletionStage<AdmissionResponse> handle(AdmissionRequest admissionRequest) {
var operation = Operation.valueOf(admissionRequest.getOperation());
var originalResource = (T) getTargetResource(admissionRequest, operation);
var originalResource = (T) admissionRequest.getObject();
var oldResource = (T) admissionRequest.getOldObject();
var asyncValidate =
CompletableFuture.runAsync(() -> validator.validate(originalResource, operation));
CompletableFuture
.runAsync(() -> validator.validate(originalResource, oldResource, operation));
return asyncValidate
.thenApply(v -> allowedAdmissionResponse())
.exceptionally(e -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import io.javaoperatorsdk.webhook.admission.Operation;

import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.allowedAdmissionResponse;
import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.getTargetResource;
import static io.javaoperatorsdk.webhook.admission.AdmissionUtils.notAllowedExceptionToAdmissionResponse;

public class DefaultAdmissionRequestValidator<T extends KubernetesResource>
Expand All @@ -24,9 +23,10 @@ public DefaultAdmissionRequestValidator(Validator<T> validator) {
@SuppressWarnings("unchecked")
public AdmissionResponse handle(AdmissionRequest admissionRequest) {
var operation = Operation.valueOf(admissionRequest.getOperation());
var originalResource = (T) getTargetResource(admissionRequest, operation);
var originalResource = (T) admissionRequest.getObject();
var oldResource = (T) admissionRequest.getOldObject();
try {
validator.validate(originalResource, operation);
validator.validate(originalResource, oldResource, operation);
return allowedAdmissionResponse();
} catch (NotAllowedException e) {
return notAllowedExceptionToAdmissionResponse(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@

public interface Validator<T extends KubernetesResource> {

void validate(T resource, Operation operation) throws NotAllowedException;
void validate(T resource, T oldResource, Operation operation) throws NotAllowedException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ class AdmissionControllerTest {

@Test
void validatesResource() {
var admissionController = new AdmissionController<HasMetadata>((resource, operation) -> {
});
var admissionController =
new AdmissionController<HasMetadata>((resource, oldResource, operation) -> {
});
admissionTestSupport.validatesResource(admissionController::handle);
}

@Test
void validatesResource_whenNotAllowedException() {
var admissionController =
new AdmissionController<>((Validator<HasMetadata>) (resource, operation) -> {
new AdmissionController<>((Validator<HasMetadata>) (resource, oldResource, operation) -> {
throw new NotAllowedException(MISSING_REQUIRED_LABEL);
});
admissionTestSupport.notAllowedException(admissionController::handle);
Expand All @@ -32,7 +33,7 @@ void validatesResource_whenNotAllowedException() {
@Test
void validatesResource_whenOtherException() {
var admissionController =
new AdmissionController<>((Validator<HasMetadata>) (resource, operation) -> {
new AdmissionController<>((Validator<HasMetadata>) (resource, oldResource, operation) -> {
throw new IllegalArgumentException("Invalid resource");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ class AsyncAdmissionControllerTest {

@Test
void validatesResource() {
var admissionController = new AsyncAdmissionController<HasMetadata>((resource, operation) -> {
});
var admissionController =
new AsyncAdmissionController<HasMetadata>((resource, oldResource, operation) -> {
});

admissionTestSupport
.validatesResource(res -> admissionController.handle(res).toCompletableFuture().join());
Expand All @@ -30,9 +31,10 @@ void validatesResource() {
@Test
void validatesResource_whenNotAllowedException() {
var admissionController =
new AsyncAdmissionController<>((Validator<HasMetadata>) (resource, operation) -> {
throw new NotAllowedException(MISSING_REQUIRED_LABEL);
});
new AsyncAdmissionController<>(
(Validator<HasMetadata>) (resource, oldResource, operation) -> {
throw new NotAllowedException(MISSING_REQUIRED_LABEL);
});

admissionTestSupport
.notAllowedException(res -> admissionController.handle(res).toCompletableFuture().join());
Expand All @@ -41,9 +43,10 @@ void validatesResource_whenNotAllowedException() {
@Test
void validatesResource_whenOtherException() {
var admissionController =
new AsyncAdmissionController<>((Validator<HasMetadata>) (resource, operation) -> {
throw new IllegalArgumentException("Invalid resource");
});
new AsyncAdmissionController<>(
(Validator<HasMetadata>) (resource, oldResource, operation) -> {
throw new IllegalArgumentException("Invalid resource");
});

admissionTestSupport.assertThatThrownBy(
res -> admissionController.handle(res).toCompletableFuture()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static AsyncAdmissionController<Ingress> asyncValidatingController() {
}

public static AdmissionController<Ingress> errorMutatingController() {
return new AdmissionController<>((Validator<Ingress>) (resource, operation) -> {
return new AdmissionController<>((Validator<Ingress>) (resource, oldResource, operation) -> {
throw new IllegalStateException(ERROR_MESSAGE);
});
}
Expand All @@ -54,9 +54,10 @@ public static AsyncAdmissionController<Ingress> errorAsyncMutatingController() {
}

public static AsyncAdmissionController<Ingress> errorAsyncValidatingController() {
return new AsyncAdmissionController<>((Validator<Ingress>) (resource, operation) -> {
throw new IllegalStateException(ERROR_MESSAGE);
});
return new AsyncAdmissionController<>(
(Validator<Ingress>) (resource, oldResource, operation) -> {
throw new IllegalStateException(ERROR_MESSAGE);
});
}

private static class IngressMutator implements Mutator<Ingress> {
Expand All @@ -72,11 +73,20 @@ public Ingress mutate(Ingress resource, Operation operation) throws NotAllowedEx

private static class IngressValidator implements Validator<Ingress> {
@Override
public void validate(Ingress resource, Operation operation) throws NotAllowedException {
public void validate(Ingress resource, Ingress oldResource, Operation operation)
throws NotAllowedException {
if (operation.equals(Operation.DELETE)) {
return;
}
if (resource.getMetadata().getLabels() == null
|| resource.getMetadata().getLabels().get(VALIDATION_TARGET_LABEL) == null) {
throw new NotAllowedException("Missing label: " + VALIDATION_TARGET_LABEL);
}
if (operation.equals(Operation.UPDATE)
&& !resource.getSpec().getIngressClassName()
.equals(oldResource.getSpec().getIngressClassName())) {
throw new NotAllowedException("IngressClassName cannot be changed");
}
}
}
}
Loading