Search in sources :

Example 1 with AdmissionReview

use of io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview in project kubernetes-client by fabric8io.

the class AdmissionReviewTest method testJacksonParsingWithUpdateOptions.

@Test
@DisplayName("Should be able to deserialize from AdmissionRequest option set to UpdateOption")
void testJacksonParsingWithUpdateOptions() {
    InputStream jsonStream = getClass().getResourceAsStream("/admissionreview-withupdateoptions.json");
    AdmissionReview admissionReview = Serialization.unmarshal(jsonStream, AdmissionReview.class);
    assertEquals("UPDATE", admissionReview.getRequest().getOperation());
    assertRequest(admissionReview);
}
Also used : InputStream(java.io.InputStream) AdmissionReview(io.fabric8.kubernetes.api.model.admission.v1beta1.AdmissionReview) Test(org.junit.jupiter.api.Test) DisplayName(org.junit.jupiter.api.DisplayName)

Example 2 with AdmissionReview

use of io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview in project kubernetes-client by fabric8io.

the class AdmissionReviewTest method testJacksonParsingWithPathOptions.

@Test
@DisplayName("Should be able to deserialize from AdmissionRequest option set to PatchOption")
void testJacksonParsingWithPathOptions() {
    InputStream jsonStream = getClass().getResourceAsStream("/admissionreview-withpatchoptions.json");
    AdmissionReview admissionReview = Serialization.unmarshal(jsonStream, AdmissionReview.class);
    assertEquals("PATCH", admissionReview.getRequest().getOperation());
    assertRequest(admissionReview);
}
Also used : InputStream(java.io.InputStream) AdmissionReview(io.fabric8.kubernetes.api.model.admission.v1beta1.AdmissionReview) Test(org.junit.jupiter.api.Test) DisplayName(org.junit.jupiter.api.DisplayName)

Example 3 with AdmissionReview

use of io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview in project xp-operator by enonic.

the class TestApi method runTest.

@SuppressWarnings("unchecked")
private void runTest(File file) {
    try {
        TestFile test = mapper.readValue(file, TestFile.class);
        if (test.disabled()) {
            return;
        }
        AdmissionReview review = mutationApi.validate(test.admissionRequest());
        List<Patch> patch = null;
        if (review.getResponse().getPatch() != null) {
            String patchDecoded = new String(BaseEncoding.base64().decode(review.getResponse().getPatch()));
            patch = mapper.readValue(patchDecoded, new TypeReference<List<Patch>>() {
            });
            review = applyPatch(patch, review);
        }
        review = admissionApi.validate(review);
        Assertions.assertEquals(test.assertException(), review.getResponse().getStatus().getMessage(), "Exception does not match");
        if (review.getResponse().getStatus().getMessage() == null) {
            Assertions.assertEquals(mapper.writeValueAsString(test.assertResult()), mapper.writeValueAsString(review.getRequest().getObject()), "Result does not match");
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
Also used : TypeReference(com.fasterxml.jackson.core.type.TypeReference) IOException(java.io.IOException) Patch(com.enonic.kubernetes.operator.api.mutation.Patch) AdmissionReview(io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview)

Example 4 with AdmissionReview

use of io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview in project xp-operator by enonic.

the class BaseAdmissionApi method handle.

protected AdmissionReview handle(AdmissionReview admissionReview) throws JsonProcessingException {
    String apiName = this.getClass().getSimpleName();
    cfgIfBool("operator.api.debug", () -> {
        try {
            log.info(String.format("%s Request: %s", apiName, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(admissionReview)));
        } catch (JsonProcessingException e) {
        // Ignore
        }
    });
    HasMetadata obj = getObject(admissionReview);
    String type = String.format("%s/%s", obj.getApiVersion(), obj.getKind());
    log.debug(String.format("%s called with type %s", apiName, type));
    Consumer<R> func = functionMap.get(obj.getClass());
    String error = null;
    if (func == null) {
        error = String.format("%s cannot handle resources of type %s", apiName, type);
    }
    R apiObject = null;
    if (error == null && !deleteEvent(admissionReview)) {
        try {
            apiObject = createApiObject(admissionReview);
            Objects.requireNonNull(func).accept(apiObject);
        } catch (Throwable e) {
            error = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
        }
    }
    AdmissionResponseBuilder builder = new AdmissionResponseBuilder().withUid(admissionReview.getRequest().getUid()).withAllowed(error == null);
    StatusBuilder statusBuilder = new StatusBuilder();
    if (error != null) {
        statusBuilder.withMessage(error);
        log.warn(String.format("%s failed for %s %s in NS %s: %s", apiName, obj.getKind(), obj.getMetadata().getName(), obj.getMetadata().getNamespace(), error));
    } else if (apiObject != null) {
        postRequestHook(apiObject, builder);
    }
    builder.withStatus(statusBuilder.build());
    admissionReview.setResponse(builder.build());
    cfgIfBool("operator.api.debug", () -> {
        try {
            log.info(String.format("%s Response: %s", apiName, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(admissionReview)));
        } catch (JsonProcessingException e) {
        // Ignore
        }
    });
    return admissionReview;
}
Also used : HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) StatusBuilder(io.fabric8.kubernetes.api.model.StatusBuilder) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) AdmissionResponseBuilder(io.fabric8.kubernetes.api.model.admission.v1.AdmissionResponseBuilder)

Example 5 with AdmissionReview

use of io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview in project xp-operator by enonic.

the class AdmissionApi method xp7deployment.

private void xp7deployment(AdmissionReview admissionReview) {
    AdmissionOperation op = getOperation(admissionReview);
    Xp7Deployment newDeployment = (Xp7Deployment) admissionReview.getRequest().getObject();
    if (op != AdmissionOperation.DELETE) {
        // Check spec
        Preconditions.checkState(newDeployment.getSpec() != null, "'spec' cannot be null");
        Preconditions.checkState(newDeployment.getSpec().getEnabled() != null, "'spec.enabled' cannot be null");
        Preconditions.checkState(newDeployment.getSpec().getXpVersion() != null, "'spec.xpVersion' cannot be null");
        Preconditions.checkState(newDeployment.getSpec().getXp7DeploymentSpecNodesSharedDisks() != null, "'spec.nodesSharedDisks' cannot be null");
        Preconditions.checkState(newDeployment.getSpec().getXp7DeploymentSpecNodeGroups() != null, "'spec.nodeGroups' cannot be null");
        // Check status
        Preconditions.checkState(newDeployment.getStatus() != null, "'status' cannot be null");
        Preconditions.checkState(newDeployment.getStatus().getMessage() != null, "'status.message' cannot be null");
        Preconditions.checkState(newDeployment.getStatus().getState() != null, "'status.state' cannot be null");
        Preconditions.checkState(newDeployment.getStatus().getXp7DeploymentStatusFields() != null, "'status.fields' cannot be null");
        Preconditions.checkState(newDeployment.getStatus().getXp7DeploymentStatusFields().getXp7DeploymentStatusFieldsPods() != null, "'status.fields.pods' cannot be null");
        // Check node groups
        int nrOfMasterNodes = 0;
        int i = 0;
        for (Xp7DeploymentSpecNodeGroup ng : newDeployment.getSpec().getXp7DeploymentSpecNodeGroups()) {
            Preconditions.checkState(ng.getName() != null, "'spec.nodeGroups[" + i + "].name' cannot be null");
            Preconditions.checkState(!ng.getName().equals(cfgStr("operator.charts.values.allNodesKey")), "'spec.nodeGroups[" + i + "].name' cannot be " + cfgStr("operator.charts.values.allNodesKey"));
            dns1123("spec.nodeGroups[" + i + "].name", ng.getName());
            Preconditions.checkState(ng.getData() != null, "'spec.nodeGroups[" + i + "].data' cannot be null");
            Preconditions.checkState(ng.getMaster() != null, "'spec.nodeGroups[" + i + "].master' cannot be null");
            Preconditions.checkState(ng.getReplicas() != null, "'spec.nodeGroups[" + i + "].replicas' cannot be null");
            Preconditions.checkState(ng.getReplicas() >= 0, "'spec.nodeGroups[" + i + "].replicas' has to be >= 0");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupEnvironment() != null, "'spec.nodeGroups[" + i + "].env' cannot be null");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources() != null, "'spec.nodeGroups[" + i + "].resources' cannot be null");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources().getCpu() != null, "'spec.nodeGroups[" + i + "].resources.cpu' cannot be null");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources().getMemory() != null, "'spec.nodeGroups[" + i + "].resources.memory' cannot be null");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources().getMemory().contains("Mi") || ng.getXp7DeploymentSpecNodeGroupResources().getMemory().contains("Gi"), "'spec.nodeGroups[" + i + "].resources.memory' can only be defined with Gi or Mi");
            Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources().getXp7DeploymentSpecNodeGroupDisks() != null, "'spec.nodeGroups[" + i + "].resources.disks' cannot be null");
            // Check disks
            if (ng.getData()) {
                Preconditions.checkState(ng.getXp7DeploymentSpecNodeGroupResources().getXp7DeploymentSpecNodeGroupDisks().stream().anyMatch(d -> d.getName().equals("index")), "nodes with data=true must have disk 'index' defined");
            }
            if (ng.getMaster()) {
                nrOfMasterNodes += ng.getReplicas();
            }
            i++;
        }
        // Check replicas
        Preconditions.checkState(nrOfMasterNodes > 0, "some nodeGroups must have master=true");
        Preconditions.checkState(nrOfMasterNodes % 2 == 1, "number of master nodes has to be an odd number");
    }
    // Strict label and name validation
    cfgIfBool("operator.deployment.xp.labels.strictValidation", () -> {
        Preconditions.checkState(newDeployment.getMetadata() != null, "'metadata' cannot be null");
        Preconditions.checkState(newDeployment.getMetadata().getLabels() != null, "'metadata.labels' cannot be null");
        String cloud = newDeployment.getMetadata().getLabels().get(cfgStr("operator.deployment.xp.labels.cloud"));
        String solution = newDeployment.getMetadata().getLabels().get(cfgStr("operator.deployment.xp.labels.solution"));
        String environment = newDeployment.getMetadata().getLabels().get(cfgStr("operator.deployment.xp.labels.environment"));
        String service = newDeployment.getMetadata().getLabels().get(cfgStr("operator.deployment.xp.labels.service"));
        Preconditions.checkState(cloud != null, String.format("'metadata.labels.%s' cannot be null", cfgStr("operator.deployment.xp.labels.cloud")));
        Preconditions.checkState(solution != null, String.format("'metadata.labels.%s' cannot be null", cfgStr("operator.deployment.xp.labels.solution")));
        Preconditions.checkState(environment != null, String.format("'metadata.labels.%s' cannot be null", cfgStr("operator.deployment.xp.labels.environment")));
        Preconditions.checkState(service != null, String.format("'metadata.labels.%s' cannot be null", cfgStr("operator.deployment.xp.labels.service")));
        String name = String.format("%s-%s-%s-%s", cloud, solution, environment, service);
        Preconditions.checkState(newDeployment.getMetadata().getName().equals(name), String.format("Xp7Deployment name must be equal to <Cloud>-<Solution>-<Environment>-<Service> according to labels, i.e: '%s'", name));
    });
    if (op == AdmissionOperation.CREATE) {
        Optional<Xp7Deployment> xp7Deployments = getXp7Deployment(admissionReview.getRequest().getObject());
        Preconditions.checkState(xp7Deployments.isEmpty(), "There is already an Xp7Deployment in NS '%s'", newDeployment.getMetadata().getNamespace());
        // Assert version is > 7.7.X, if we cant parse version, just let it go
        ComparableVersion currentVersion = new ComparableVersion("7.7.0");
        try {
            if (newDeployment.getSpec().getXpVersion().startsWith("7.")) {
                currentVersion = new ComparableVersion(newDeployment.getSpec().getXpVersion());
            } else if (newDeployment.getSpec().getXpVersion().startsWith("enonic/xp:7.")) {
                String pattern = "^enonic\\/xp:([0-9]+\\.[0-9]+\\.[0-9]+)";
                Matcher m = Pattern.compile(pattern).matcher(newDeployment.getSpec().getXpVersion());
                if (m.find()) {
                    currentVersion = new ComparableVersion(m.group(1));
                }
            }
        } catch (Exception e) {
        // Just ignore
        }
        Preconditions.checkState(currentVersion.compareTo(new ComparableVersion("7.6.100")) > 0, "Operator only supports XP version 7.7 and higher");
    }
}
Also used : AdmissionOperation(com.enonic.kubernetes.operator.api.AdmissionOperation) Mapping(com.enonic.kubernetes.operator.ingress.Mapping) Xp7App(com.enonic.kubernetes.client.v1.xp7app.Xp7App) Produces(javax.ws.rs.Produces) Predicates.inNodeGroupAllOr(com.enonic.kubernetes.kubernetes.Predicates.inNodeGroupAllOr) HTTPIngressPath(io.fabric8.kubernetes.api.model.networking.v1.HTTPIngressPath) Xp7Config(com.enonic.kubernetes.client.v1.xp7config.Xp7Config) Path(javax.ws.rs.Path) Xp7DeploymentSpecNodeGroup(com.enonic.kubernetes.client.v1.xp7deployment.Xp7DeploymentSpecNodeGroup) BaseAdmissionApi(com.enonic.kubernetes.operator.api.BaseAdmissionApi) HashSet(java.util.HashSet) Matcher(java.util.regex.Matcher) Xp7Deployment(com.enonic.kubernetes.client.v1.xp7deployment.Xp7Deployment) Consumes(javax.ws.rs.Consumes) Configuration.cfgStr(com.enonic.kubernetes.common.Configuration.cfgStr) ComparableVersion(org.apache.maven.artifact.versioning.ComparableVersion) Configuration.cfgIfBool(com.enonic.kubernetes.common.Configuration.cfgIfBool) Domain(com.enonic.kubernetes.client.v1.domain.Domain) Predicates.matchAnnotationPrefix(com.enonic.kubernetes.kubernetes.Predicates.matchAnnotationPrefix) POST(javax.ws.rs.POST) Predicates.inSameNamespaceAs(com.enonic.kubernetes.kubernetes.Predicates.inSameNamespaceAs) Predicates.fieldEquals(com.enonic.kubernetes.kubernetes.Predicates.fieldEquals) OperatorXp7ConfigSync.getAnnotationMappings(com.enonic.kubernetes.operator.ingress.OperatorXp7ConfigSync.getAnnotationMappings) Collection(java.util.Collection) Predicates.withName(com.enonic.kubernetes.kubernetes.Predicates.withName) Set(java.util.Set) Validator.dns1123(com.enonic.kubernetes.common.Validator.dns1123) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) Predicates.isBeingBackupRestored(com.enonic.kubernetes.kubernetes.Predicates.isBeingBackupRestored) HasMetadata(io.fabric8.kubernetes.api.model.HasMetadata) Collectors(java.util.stream.Collectors) Validator(com.enonic.kubernetes.common.Validator) List(java.util.List) AdmissionReview(io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview) Ingress(io.fabric8.kubernetes.api.model.networking.v1.Ingress) Optional(java.util.Optional) Preconditions(com.google.common.base.Preconditions) ApplicationScoped(javax.enterprise.context.ApplicationScoped) Pattern(java.util.regex.Pattern) AdmissionOperation(com.enonic.kubernetes.operator.api.AdmissionOperation) Collections(java.util.Collections) Xp7Deployment(com.enonic.kubernetes.client.v1.xp7deployment.Xp7Deployment) Matcher(java.util.regex.Matcher) ComparableVersion(org.apache.maven.artifact.versioning.ComparableVersion) Xp7DeploymentSpecNodeGroup(com.enonic.kubernetes.client.v1.xp7deployment.Xp7DeploymentSpecNodeGroup) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException)

Aggregations

AdmissionReview (io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview)11 InputStream (java.io.InputStream)6 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)5 HasMetadata (io.fabric8.kubernetes.api.model.HasMetadata)5 Domain (com.enonic.kubernetes.client.v1.domain.Domain)4 Xp7App (com.enonic.kubernetes.client.v1.xp7app.Xp7App)4 Xp7Config (com.enonic.kubernetes.client.v1.xp7config.Xp7Config)4 Xp7Deployment (com.enonic.kubernetes.client.v1.xp7deployment.Xp7Deployment)4 Xp7DeploymentSpecNodeGroup (com.enonic.kubernetes.client.v1.xp7deployment.Xp7DeploymentSpecNodeGroup)4 Configuration.cfgIfBool (com.enonic.kubernetes.common.Configuration.cfgIfBool)4 Configuration.cfgStr (com.enonic.kubernetes.common.Configuration.cfgStr)4 Validator (com.enonic.kubernetes.common.Validator)4 Validator.dns1123 (com.enonic.kubernetes.common.Validator.dns1123)4 Predicates.fieldEquals (com.enonic.kubernetes.kubernetes.Predicates.fieldEquals)4 Predicates.inNodeGroupAllOr (com.enonic.kubernetes.kubernetes.Predicates.inNodeGroupAllOr)4 Predicates.inSameNamespaceAs (com.enonic.kubernetes.kubernetes.Predicates.inSameNamespaceAs)4 Predicates.isBeingBackupRestored (com.enonic.kubernetes.kubernetes.Predicates.isBeingBackupRestored)4 Predicates.matchAnnotationPrefix (com.enonic.kubernetes.kubernetes.Predicates.matchAnnotationPrefix)4 Predicates.withName (com.enonic.kubernetes.kubernetes.Predicates.withName)4 AdmissionOperation (com.enonic.kubernetes.operator.api.AdmissionOperation)4