All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkiverse.operatorsdk.it.OperatorSDKResource Maven / Gradle / Ivy

There is a newer version: 6.9.1
Show newest version
package io.quarkiverse.operatorsdk.it;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;

import com.fasterxml.jackson.annotation.JsonProperty;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
import io.javaoperatorsdk.operator.api.config.Version;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceConfigurationResolver;
import io.javaoperatorsdk.operator.api.config.dependent.DependentResourceSpec;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependentResourceConfig;
import io.javaoperatorsdk.operator.processing.dependent.workflow.ManagedWorkflow;
import io.javaoperatorsdk.operator.processing.event.rate.RateLimiter;
import io.javaoperatorsdk.operator.processing.retry.Retry;
import io.quarkiverse.operatorsdk.runtime.QuarkusConfigurationService;
import io.quarkiverse.operatorsdk.runtime.QuarkusControllerConfiguration;
import io.quarkus.runtime.annotations.RegisterForReflection;

@SuppressWarnings("unused")
@Path("/operator")
public class OperatorSDKResource {

    @Inject
    Instance> controllers;
    @Inject
    QuarkusConfigurationService configurationService;

    @GET
    @Path("config")
    public JSONConfiguration config() {
        return new JSONConfiguration(configurationService);
    }

    @GET
    @Path("{name}")
    public boolean exists(@PathParam("name") String name) {
        return configurationService.getKnownReconcilerNames().contains(name);
    }

    @GET
    @Path("controllers")
    @Produces("application/json")
    public Set getControllerNames() {
        return config().getKnownControllerNames();
    }

    @GET
    @Path("{name}/config")
    public JSONControllerConfiguration getConfig(@PathParam("name") String name) {
        return getControllerConfigurationByName(name)
                .map(JSONControllerConfiguration::new)
                .orElse(null);
    }

    private Optional> getControllerConfigurationByName(
            String name) {
        return controllers.stream()
                .map(c -> configurationService.getConfigurationFor(c))
                .filter(c -> c.getName().equals(name))
                .findFirst();
    }

    @GET
    @Path("{name}/workflow")
    public JSONWorkflow getWorkflow(@PathParam("name") String name) {
        return new JSONWorkflow(configurationService.workflowByName(name));
    }

    @GET
    @Path("{name}/dependents/{dependent}")
    public JSONKubernetesResourceConfig getDependentConfig(@PathParam("name") String name,
            @PathParam("dependent") String dependent) {
        final var dr = configurationService.getDependentByName(name, dependent);
        if (dr == null) {
            return null;
        }
        final var config = dr.getDependentResourceConfig();
        if (config instanceof KubernetesDependentResourceConfig) {
            return new JSONKubernetesResourceConfig((KubernetesDependentResourceConfig) config);
        }
        return null;
    }

    static class JSONConfiguration {
        private final QuarkusConfigurationService conf;

        public JSONConfiguration(QuarkusConfigurationService conf) {
            this.conf = conf;
        }

        public Set getKnownControllerNames() {
            return conf.getKnownReconcilerNames();
        }

        public Version getVersion() {
            return conf.getVersion();
        }

        @JsonProperty("validate")
        public boolean validate() {
            return conf.checkCRDAndValidateLocalModel();
        }

        @JsonProperty("maxThreads")
        public int concurrentReconciliationThreads() {
            return conf.concurrentReconciliationThreads();
        }

        @JsonProperty("timeout")
        public int timeout() {
            return conf.getTerminationTimeoutSeconds();
        }

        @JsonProperty("applyCRDs")
        public boolean apply() {
            return conf.getCRDGenerationInfo().isApplyCRDs();
        }

        @JsonProperty("metrics")
        public String metrics() {
            return conf.getMetrics().getClass().getName();
        }

        @JsonProperty("registryBound")
        public boolean registryBound() {
            final var metrics = conf.getMetrics();
            return metrics instanceof TestMetrics && ((TestMetrics) metrics).isRegistryBound();
        }

        @JsonProperty("leaderConfig")
        public String leaderConfig() {
            return conf.getLeaderElectionConfiguration().map(lec -> lec.getClass().getName()).orElse(null);
        }

        @JsonProperty("useSSA")
        public boolean useSSA() {
            return conf.ssaBasedCreateUpdateMatchForDependentResources();
        }
    }

    static class JSONControllerConfiguration {

        private final ControllerConfiguration conf;

        public JSONControllerConfiguration(ControllerConfiguration conf) {
            this.conf = conf;
        }

        public String getName() {
            return conf.getName();
        }

        @JsonProperty("crdName")
        public String getCRDName() {
            return conf.getResourceTypeName();
        }

        public String getFinalizer() {
            return conf.getFinalizerName();
        }

        public boolean isGenerationAware() {
            return conf.isGenerationAware();
        }

        public String getCustomResourceClass() {
            return conf.getResourceClass().getCanonicalName();
        }

        public String getAssociatedControllerClassName() {
            return conf.getAssociatedReconcilerClassName();
        }

        public String[] getNamespaces() {
            return conf.getNamespaces().toArray(new String[0]);
        }

        @JsonProperty("watchAllNamespaces")
        public boolean watchAllNamespaces() {
            return conf.watchAllNamespaces();
        }

        @JsonProperty("watchCurrentNamespace")
        public boolean watchCurrentNamespace() {
            return conf.watchCurrentNamespace();
        }

        public RetryConfiguration getRetryConfiguration() {
            return conf.getRetryConfiguration();
        }

        public Retry getRetry() {
            return conf.getRetry();
        }

        public String getLabelSelector() {
            return conf.getLabelSelector();
        }

        public List getDependents() {
            final var dependents = conf.getDependentResources();
            final var result = new ArrayList(dependents.size());
            return dependents.stream()
                    .map(spec -> new JSONDependentResourceSpec(spec, conf))
                    .collect(Collectors.toList());
        }

        @JsonProperty("maxReconciliationIntervalSeconds")
        public long maxReconciliationIntervalSeconds() {
            return conf.maxReconciliationInterval().map(Duration::getSeconds).orElseThrow();
        }

        @SuppressWarnings("rawtypes")
        public RateLimiter getRateLimiter() {
            return conf.getRateLimiter();
        }
    }

    static class JSONDependentResourceSpec {
        private final DependentResourceSpec spec;
        private final ControllerConfiguration conf;

        JSONDependentResourceSpec(DependentResourceSpec spec, ControllerConfiguration conf) {
            this.spec = spec;
            this.conf = conf;
        }

        public String getDependentClass() {
            return spec.getDependentResourceClass().getCanonicalName();
        }

        public Object getDependentConfig() {
            final var c = DependentResourceConfigurationResolver.configurationFor(spec, conf);
            if (c instanceof KubernetesDependentResourceConfig) {
                return new JSONKubernetesResourceConfig((KubernetesDependentResourceConfig) c);
            } else {
                return c;
            }
        }

        public String getName() {
            return spec.getName();
        }
    }

    // needed for native tests, see https://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection
    @RegisterForReflection
    static class JSONKubernetesResourceConfig {

        private final KubernetesDependentResourceConfig config;

        JSONKubernetesResourceConfig(KubernetesDependentResourceConfig config) {
            this.config = config;
        }

        public String getOnAddFilter() {
            return Optional.ofNullable(config.onAddFilter())
                    .map(f -> f.getClass().getCanonicalName())
                    .orElse(null);
        }

        public String getResourceDiscriminator() {
            return Optional.ofNullable(config.getResourceDiscriminator())
                    .map(f -> f.getClass().getCanonicalName())
                    .orElse(null);
        }

        public String getLabelSelector() {
            return config.labelSelector();
        }
    }

    static class JSONWorkflow {
        private final ManagedWorkflow workflow;

        @SuppressWarnings("rawtypes")
        JSONWorkflow(ManagedWorkflow workflow) {
            this.workflow = workflow;
        }

        public boolean isCleaner() {
            return workflow.hasCleaner();
        }

        public boolean isEmpty() {
            return workflow.isEmpty();
        }

        public Map getDependents() {
            return workflow.getOrderedSpecs().stream()
                    .collect(Collectors.toMap(DependentResourceSpec::getName, JSONDRSpec::new));
        }
    }

    @SuppressWarnings("rawtypes")
    static class JSONDRSpec {
        private final DependentResourceSpec spec;

        JSONDRSpec(DependentResourceSpec spec) {
            this.spec = spec;
        }

        public String getType() {
            return spec.getDependentResourceClass().getName();
        }

        public String getReadyCondition() {
            final var readyCondition = spec.getReadyCondition();
            return readyCondition == null ? null : readyCondition.getClass().getName();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy