diff --git a/pom.xml b/pom.xml index e521084..d564811 100644 --- a/pom.xml +++ b/pom.xml @@ -17,11 +17,11 @@ 3.5.2 java-operator-sdk https://sonarcloud.io - 6.13.1 - 3.8.3 + 7.1.0 + 3.19.0 24.1.2 5.11.0 - 6.6.8 + 7.1.0 3.27.3 2.43.0 @@ -46,6 +46,12 @@ + + + io.javaoperatorsdk + operator-framework-core + 5.0.4 + io.quarkiverse.operatorsdk quarkus-operator-sdk diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/Utils.java b/src/main/java/io/javaoperatorsdk/operator/glue/Utils.java index 5311c49..399e92d 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/Utils.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/Utils.java @@ -66,7 +66,7 @@ public static Map getRelatedResources(Glue gl var es = (InformerEventSource) context .eventSourceRetriever() - .getResourceEventSourceFor(GenericKubernetesResource.class, gvk.toString()); + .getEventSourceFor(GenericKubernetesResource.class, gvk.toString()); var namespace = relatedResourceSpec.isClusterScoped() ? null : relatedResourceSpec.getNamespace() == null ? glue.getMetadata().getNamespace() @@ -135,13 +135,6 @@ public static String getKindFromTemplate(String resourceTemplate) { return getPropertyValueFromTemplate(resourceTemplate, "kind"); } - public static Set leafResourceNames(Glue glue) { - Set result = new HashSet<>(); - glue.getSpec().getChildResources().forEach(r -> result.add(r.getName())); - glue.getSpec().getChildResources().forEach(r -> r.getDependsOn().forEach(result::remove)); - return result; - } - private static Optional getOptionalPropertyValueFromTemplate(String resourceTemplate, String property) { var finalProp = property + ":"; diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/AbstractStatus.java b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/AbstractStatus.java index 5744ef4..22f9824 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/AbstractStatus.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/AbstractStatus.java @@ -1,8 +1,8 @@ package io.javaoperatorsdk.operator.glue.customresource; -import io.javaoperatorsdk.operator.api.ObservedGenerationAwareStatus; +public class AbstractStatus { -public class AbstractStatus extends ObservedGenerationAwareStatus { + private Long observedGeneration = null; private String errorMessage; @@ -14,4 +14,11 @@ public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } + public Long getObservedGeneration() { + return observedGeneration; + } + + public void setObservedGeneration(Long observedGeneration) { + this.observedGeneration = observedGeneration; + } } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperator.java b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperator.java index c8dd269..f938802 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperator.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperator.java @@ -10,6 +10,6 @@ @Version("v1beta1") @ShortNames("go") public class GlueOperator - extends CustomResource + extends CustomResource implements Namespaced { } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/ResourceFlowOperatorStatus.java b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperatorStatus.java similarity index 68% rename from src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/ResourceFlowOperatorStatus.java rename to src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperatorStatus.java index 5ad0174..b15e535 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/ResourceFlowOperatorStatus.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/customresource/operator/GlueOperatorStatus.java @@ -2,7 +2,7 @@ import io.javaoperatorsdk.operator.glue.customresource.AbstractStatus; -public class ResourceFlowOperatorStatus extends AbstractStatus { +public class GlueOperatorStatus extends AbstractStatus { } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GCGenericDependentResource.java b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GCGenericDependentResource.java index 9dbf369..4d5e0ec 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GCGenericDependentResource.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GCGenericDependentResource.java @@ -10,13 +10,16 @@ public class GCGenericDependentResource extends GenericDependentResource implements GarbageCollected { public GCGenericDependentResource(GenericTemplateHandler genericTemplateHandler, - GenericKubernetesResource desired, String name, + GenericKubernetesResource desired, String name, String resourceName, String namespace, boolean clusterScoped, Matcher matcher) { - super(genericTemplateHandler, desired, name, clusterScoped, matcher); + super(genericTemplateHandler, desired, name, resourceName, namespace, clusterScoped, matcher); } public GCGenericDependentResource(GenericTemplateHandler genericTemplateHandler, - String desiredTemplate, String name, boolean clusterScoped, Matcher matcher) { - super(genericTemplateHandler, desiredTemplate, name, clusterScoped, matcher); + String desiredTemplate, String name, String resourceName, String namespace, + boolean clusterScoped, + Matcher matcher) { + super(genericTemplateHandler, desiredTemplate, name, resourceName, namespace, clusterScoped, + matcher); } } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericBulkDependentResource.java b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericBulkDependentResource.java index a98dbd9..bbea509 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericBulkDependentResource.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericBulkDependentResource.java @@ -22,7 +22,7 @@ public GenericBulkDependentResource(GenericTemplateHandler genericTemplateHandle String desiredTemplate, String name, boolean clusterScoped, Matcher matcher) { - super(genericTemplateHandler, desiredTemplate, name, clusterScoped, matcher); + super(genericTemplateHandler, desiredTemplate, name, null, null, clusterScoped, matcher); } @Override diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericDependentResource.java b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericDependentResource.java index a111aac..0457b56 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericDependentResource.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericDependentResource.java @@ -1,5 +1,12 @@ package io.javaoperatorsdk.operator.glue.dependent; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.fabric8.kubernetes.api.model.GenericKubernetesResource; import io.fabric8.kubernetes.client.utils.Serialization; import io.javaoperatorsdk.operator.api.reconciler.Context; @@ -20,33 +27,41 @@ public class GenericDependentResource Updater, Creator { + private static final Logger log = LoggerFactory.getLogger(GenericDependentResource.class); + protected final GenericKubernetesResource desired; protected final String desiredTemplate; - protected final String name; + // resource name might be templated + protected final String resourceName; + protected final String namespace; protected final boolean clusterScoped; protected final Matcher matcher; protected final GenericTemplateHandler genericTemplateHandler; public GenericDependentResource(GenericTemplateHandler genericTemplateHandler, - GenericKubernetesResource desired, String name, + GenericKubernetesResource desired, String name, String resourceName, String namespace, boolean clusterScoped, Matcher matcher) { - super(new GroupVersionKind(desired.getApiVersion(), desired.getKind())); + super(new GroupVersionKind(desired.getApiVersion(), desired.getKind()), name); this.desired = desired; + this.namespace = namespace; this.matcher = matcher; this.desiredTemplate = null; - this.name = name; + this.resourceName = resourceName; this.clusterScoped = clusterScoped; this.genericTemplateHandler = genericTemplateHandler; } public GenericDependentResource(GenericTemplateHandler genericTemplateHandler, - String desiredTemplate, String name, boolean clusterScoped, Matcher matcher) { + String desiredTemplate, String name, String resourceName, String namespace, + boolean clusterScoped, + Matcher matcher) { super(new GroupVersionKind(Utils.getApiVersionFromTemplate(desiredTemplate), - Utils.getKindFromTemplate(desiredTemplate))); + Utils.getKindFromTemplate(desiredTemplate)), name); this.genericTemplateHandler = genericTemplateHandler; - this.name = name; + this.resourceName = resourceName; this.desiredTemplate = desiredTemplate; + this.namespace = namespace; this.matcher = matcher; this.desired = null; this.clusterScoped = clusterScoped; @@ -84,4 +99,38 @@ public Result match(GenericKubernetesResource actualR return Result.nonComputed(false); } } + + @Override + protected Optional selectTargetSecondaryResource( + Set secondaryResources, + Glue primary, + Context context) { + + var allSecondaryResources = context.getSecondaryResources(GenericKubernetesResource.class); + if (log.isDebugEnabled()) { + log.debug("All secondary resources for DR: {}, resources: {}", name, + allSecondaryResources.stream() + .map(r -> "{ Name: %s; Namespace: %s }".formatted(r.getMetadata().getName(), + r.getMetadata().getNamespace())) + .toList()); + } + var res = allSecondaryResources + .stream() + .filter(r -> r.getKind().equals(getGroupVersionKind().getKind()) && + r.getApiVersion().equals(getGroupVersionKind().apiVersion()) && + r.getMetadata().getName().equals(resourceName) && + (namespace == null || Objects.equals(namespace, r.getMetadata().getNamespace()))) + .toList(); + + if (res.size() > 1) { + throw new IllegalStateException("Multiple resources found for gvk: " + getGroupVersionKind() + + " name:" + name + + " namespace:" + namespace); + } else if (res.size() == 1) { + return Optional.of(res.get(0)); + } else { + return Optional.empty(); + } + } + } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericResourceDiscriminator.java b/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericResourceDiscriminator.java deleted file mode 100644 index e351183..0000000 --- a/src/main/java/io/javaoperatorsdk/operator/glue/dependent/GenericResourceDiscriminator.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.javaoperatorsdk.operator.glue.dependent; - -import java.util.Objects; -import java.util.Optional; - -import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.javaoperatorsdk.operator.api.reconciler.Context; -import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator; -import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; -import io.javaoperatorsdk.operator.processing.GroupVersionKind; - -public class GenericResourceDiscriminator - implements ResourceDiscriminator { - - private final GroupVersionKind groupVersionKind; - private final String name; - private final String namespace; - - public GenericResourceDiscriminator(GroupVersionKind groupVersionKind, String name, - String namespace) { - this.groupVersionKind = groupVersionKind; - this.name = name; - this.namespace = namespace; - } - - @Override - public Optional distinguish(Class resource, - Glue primary, - Context context) { - var res = context.getSecondaryResources(GenericKubernetesResource.class) - .stream() - .filter(r -> r.getKind().equals(groupVersionKind.getKind()) && - r.getApiVersion().equals(groupVersionKind.apiVersion()) && - r.getMetadata().getName().equals(name) && - (namespace == null || Objects.equals(namespace, r.getMetadata().getNamespace()))) - .toList(); - - if (res.size() > 1) { - throw new IllegalStateException("Multiple resources found for gvk: " + groupVersionKind - + " name:" + name - + " namespace:" + namespace); - } else if (res.size() == 1) { - return Optional.of(res.get(0)); - } else { - return Optional.empty(); - } - } -} diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndErrorHandler.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndStatusHandler.java similarity index 62% rename from src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndErrorHandler.java rename to src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndStatusHandler.java index 43cf57d..fc611f9 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndErrorHandler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/ValidationAndStatusHandler.java @@ -11,20 +11,25 @@ import io.fabric8.kubernetes.client.CustomResource; import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusUpdateControl; +import io.javaoperatorsdk.operator.api.reconciler.UpdateControl; import io.javaoperatorsdk.operator.glue.GlueException; import io.javaoperatorsdk.operator.glue.customresource.AbstractStatus; import io.javaoperatorsdk.operator.glue.customresource.glue.DependentResourceSpec; +import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; import io.javaoperatorsdk.operator.glue.customresource.glue.GlueSpec; +import io.javaoperatorsdk.operator.glue.customresource.glue.GlueStatus; import io.javaoperatorsdk.operator.glue.customresource.glue.RelatedResourceSpec; +import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperator; +import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperatorStatus; import jakarta.inject.Singleton; @Singleton -public class ValidationAndErrorHandler { +public class ValidationAndStatusHandler { public static final int MAX_MESSAGE_SIZE = 150; - private static final Logger log = LoggerFactory.getLogger(ValidationAndErrorHandler.class); + private static final Logger log = LoggerFactory.getLogger(ValidationAndStatusHandler.class); public static final String NON_UNIQUE_NAMES_FOUND_PREFIX = "Non unique names found: "; @@ -34,18 +39,58 @@ public class ValidationAndErrorHandler { log.error("Error during reconciliation of resource. Name: {} namespace: {}, Kind: {}", resource.getMetadata().getName(), resource.getMetadata().getNamespace(), resource.getKind(), e); - if (e instanceof ValidationAndErrorHandler.NonUniqueNameException ex) { + if (e instanceof ValidationAndStatusHandler.NonUniqueNameException ex) { resource.getStatus() .setErrorMessage(NON_UNIQUE_NAMES_FOUND_PREFIX + String.join(",", ex.getDuplicates())); - return ErrorStatusUpdateControl.updateStatus(resource).withNoRetry(); + return ErrorStatusUpdateControl.patchStatus(resource).withNoRetry(); } else { var message = e.getMessage(); + if (message == null) { + message = e.getClass().getName(); + } if (message.length() > MAX_MESSAGE_SIZE) { message = message.substring(0, MAX_MESSAGE_SIZE) + "..."; } resource.getStatus().setErrorMessage("Error: " + message); - return ErrorStatusUpdateControl.updateStatus(resource); + return ErrorStatusUpdateControl.patchStatus(resource); + } + } + + public UpdateControl handleStatusUpdate(GlueOperator primary) { + if (primary.getStatus() == null) { + primary.setStatus(new GlueOperatorStatus()); + } + return handleGenericStatusUpdate(primary); + } + + public UpdateControl handleStatusUpdate(Glue primary) { + if (primary.getStatus() == null) { + primary.setStatus(new GlueStatus()); + } + return handleGenericStatusUpdate(primary); + } + + private > UpdateControl handleGenericStatusUpdate( + T primary) { + boolean patch = false; + + if (primary.getStatus().getErrorMessage() != null) { + patch = true; + primary.getStatus().setErrorMessage(null); + } + if (!primary.getMetadata().getGeneration() + .equals(primary.getStatus().getObservedGeneration())) { + patch = true; + primary.getStatus().setObservedGeneration(primary.getMetadata().getGeneration()); } + + if (patch) { + primary.getMetadata().setResourceVersion(null); + return UpdateControl.patchStatus(primary); + } else { + return UpdateControl.noUpdate(); + } + } public void checkIfValidGlueSpec(GlueSpec glueSpec) { diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java index d3cb5c9..1dd2e47 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/GlueReconciler.java @@ -24,11 +24,10 @@ import io.javaoperatorsdk.operator.glue.dependent.GCGenericBulkDependentResource; import io.javaoperatorsdk.operator.glue.dependent.GCGenericDependentResource; import io.javaoperatorsdk.operator.glue.dependent.GenericDependentResource; -import io.javaoperatorsdk.operator.glue.dependent.GenericResourceDiscriminator; -import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; +import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndStatusHandler; import io.javaoperatorsdk.operator.glue.reconciler.operator.GlueOperatorReconciler; import io.javaoperatorsdk.operator.glue.templating.GenericTemplateHandler; -import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource; +import io.javaoperatorsdk.operator.processing.GroupVersionKind; import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition; import io.javaoperatorsdk.operator.processing.dependent.workflow.KubernetesResourceDeletedCondition; import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowBuilder; @@ -38,17 +37,17 @@ import static io.javaoperatorsdk.operator.glue.reconciler.operator.GlueOperatorReconciler.PARENT_RELATED_RESOURCE_NAME; @ControllerConfiguration(name = GlueReconciler.GLUE_RECONCILER_NAME) -public class GlueReconciler implements Reconciler, Cleaner, ErrorStatusHandler { +public class GlueReconciler implements Reconciler, Cleaner { private static final Logger log = LoggerFactory.getLogger(GlueReconciler.class); public static final String DEPENDENT_NAME_ANNOTATION_KEY = - "io.javaoperatorsdk.operator.resourceflow/name"; + "io.javaoperatorsdk.operator.glue/resource-name"; public static final String PARENT_GLUE_FINALIZER_PREFIX = - "io.javaoperatorsdk.operator.resourceflow.glue/"; + "io.javaoperatorsdk.operator.glue/"; public static final String GLUE_RECONCILER_NAME = "glue"; - private final ValidationAndErrorHandler validationAndErrorHandler; + private final ValidationAndStatusHandler validationAndStatusHandler; private final InformerRegister informerRegister; private final KubernetesResourceDeletedCondition deletePostCondition = @@ -56,10 +55,10 @@ public class GlueReconciler implements Reconciler, Cleaner, ErrorSta private final GenericTemplateHandler genericTemplateHandler; - public GlueReconciler(ValidationAndErrorHandler validationAndErrorHandler, + public GlueReconciler(ValidationAndStatusHandler validationAndStatusHandler, InformerRegister informerRegister, GenericTemplateHandler genericTemplateHandler) { - this.validationAndErrorHandler = validationAndErrorHandler; + this.validationAndStatusHandler = validationAndStatusHandler; this.informerRegister = informerRegister; this.genericTemplateHandler = genericTemplateHandler; } @@ -80,7 +79,7 @@ public UpdateControl reconcile(Glue primary, log.debug("Reconciling glue. name: {} namespace: {}", primary.getMetadata().getName(), primary.getMetadata().getNamespace()); - validationAndErrorHandler.checkIfValidGlueSpec(primary.getSpec()); + validationAndStatusHandler.checkIfValidGlueSpec(primary.getSpec()); registerRelatedResourceInformers(context, primary); if (deletedGlueIfParentMarkedForDeletion(context, primary)) { @@ -93,23 +92,33 @@ public UpdateControl reconcile(Glue primary, informerRegister.deRegisterInformerOnResourceFlowChange(context, primary); result.throwAggregateExceptionIfErrorsPresent(); patchRelatedResourcesStatus(context, primary); - return removeErrorMessageFromGlueStatusIfPresent(primary); + return validationAndStatusHandler.handleStatusUpdate(primary); } @Override public DeleteControl cleanup(Glue primary, Context context) { + log.debug("Cleanup for Glue. Name: {} namespace: {}", primary.getMetadata().getName(), + primary.getMetadata().getNamespace()); + + registerRelatedResourceInformers(context, primary); var actualWorkflow = buildWorkflowAndRegisterInformers(primary, context); var result = actualWorkflow.cleanup(primary, context); result.throwAggregateExceptionIfErrorsPresent(); - if (!result.allPostConditionsMet()) { + var deletableResourceCount = actualWorkflow.getDependentResourcesByName() + .entrySet().stream().filter(e -> e.getValue().isDeletable()).count(); + + // add this logic to josdk with deleted dependents + if (!result.allPostConditionsMet() || result.getDeleteCalledOnDependents() + .size() < deletableResourceCount) { return DeleteControl.noFinalizerRemoval(); } else { removeFinalizerForParent(primary, context); - actualWorkflow.getDependentResourcesByNameWithoutActivationCondition().forEach((n, dr) -> { + actualWorkflow.getDependentResourcesWithoutActivationCondition().forEach(dr -> { var genericDependentResource = (GenericDependentResource) dr; - informerRegister.deRegisterInformer(genericDependentResource.getGroupVersionKind(), + informerRegister.deRegisterInformer( + genericDependentResource.getGroupVersionKind(), primary, context); }); informerRegister.deRegisterInformerForRelatedResources(primary, context); @@ -124,7 +133,7 @@ public ErrorStatusUpdateControl updateErrorStatus(Glue resource, Context context, Glue primary) { @@ -137,21 +146,10 @@ private boolean deletedGlueIfParentMarkedForDeletion(Context context, Glue } } - private UpdateControl removeErrorMessageFromGlueStatusIfPresent(Glue primary) { - if (primary.getStatus() != null && primary.getStatus().getErrorMessage() != null) { - primary.getStatus().setErrorMessage(null); - primary.getMetadata().setResourceVersion(null); - return UpdateControl.patchStatus(primary); - } else { - return UpdateControl.noUpdate(); - } - } - private void registerRelatedResourceInformers(Context context, Glue glue) { - glue.getSpec().getRelatedResources().forEach(r -> { - informerRegister.registerInformerForRelatedResource(context, glue, r); - }); + glue.getSpec().getRelatedResources() + .forEach(r -> informerRegister.registerInformerForRelatedResource(context, glue, r)); } // todo test @@ -177,12 +175,10 @@ private void cleanupRemovedResourcesFromWorkflow(Context context, private io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow buildWorkflowAndRegisterInformers( Glue primary, Context context) { var builder = new WorkflowBuilder(); - Set leafDependentNames = Utils.leafResourceNames(primary); Map genericDependentResourceMap = new HashMap<>(); primary.getSpec().getChildResources().forEach(spec -> createAndAddDependentToWorkflow(primary, - context, spec, genericDependentResourceMap, builder, - leafDependentNames.contains(spec.getName()))); + context, spec, genericDependentResourceMap, builder)); return builder.build(); } @@ -190,7 +186,7 @@ private io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow private void createAndAddDependentToWorkflow(Glue primary, Context context, DependentResourceSpec spec, Map genericDependentResourceMap, - WorkflowBuilder builder, boolean leafDependent) { + WorkflowBuilder builder) { // todo test processing ns not as template // todo test processing ns as template @@ -200,37 +196,36 @@ private void createAndAddDependentToWorkflow(Glue primary, Context context var resourceInSameNamespaceAsPrimary = targetNamespace.map(n -> n.trim().equals(primary.getMetadata().getNamespace().trim())) .orElse(true); - - var dr = createDependentResource(spec, leafDependent, resourceInSameNamespaceAsPrimary); - var gvk = dr.getGroupVersionKind(); - - if (!(dr instanceof BulkDependentResource)) { - dr.setResourceDiscriminator(new GenericResourceDiscriminator(dr.getGroupVersionKind(), - genericTemplateHandler.processTemplate(Utils.getName(spec), primary, false, context), - targetNamespace.orElse(null))); + String name = null; + if (!Boolean.TRUE.equals(spec.getBulk())) { + name = genericTemplateHandler.processTemplate(Utils.getName(spec), primary, false, context); } - + var dr = createDependentResource(name, spec, resourceInSameNamespaceAsPrimary, + targetNamespace.orElse(null)); + GroupVersionKind gvk = dr.getGroupVersionKind(); var es = informerRegister.registerInformer(context, gvk, primary); - dr.configureWith(es); + dr.setEventSource(es); - builder.addDependentResource(dr); - spec.getDependsOn().forEach(s -> builder.dependsOn(genericDependentResourceMap.get(s))); - // if a resources does not depend on another there is no reason to add cleanup condition + var nodeBuilder = builder.addDependentResourceAndConfigure(dr); + spec.getDependsOn().forEach(s -> nodeBuilder.dependsOn(genericDependentResourceMap.get(s))); + // if resources do not depend on another, there is no reason to add cleanup condition if (!spec.getDependsOn().isEmpty()) { - builder.withDeletePostcondition(deletePostCondition); + nodeBuilder.withDeletePostcondition(deletePostCondition); } genericDependentResourceMap.put(spec.getName(), dr); Optional.ofNullable(spec.getReadyPostCondition()) - .ifPresent(c -> builder.withReadyPostcondition(toCondition(c))); + .ifPresent(c -> nodeBuilder.withReadyPostcondition(toCondition(c))); Optional.ofNullable(spec.getCondition()) - .ifPresent(c -> builder.withReconcilePrecondition(toCondition(c))); + .ifPresent(c -> nodeBuilder.withReconcilePrecondition(toCondition(c))); + } - private GenericDependentResource createDependentResource(DependentResourceSpec spec, - boolean leafDependent, Boolean resourceInSameNamespaceAsPrimary) { + private GenericDependentResource createDependentResource(String resourceName, + DependentResourceSpec spec, Boolean resourceInSameNamespaceAsPrimary, String namespace) { - if (leafDependent && resourceInSameNamespaceAsPrimary && !spec.isClusterScoped()) { + if (spec.getDependsOn().isEmpty() && + resourceInSameNamespaceAsPrimary && !spec.isClusterScoped()) { return spec.getResourceTemplate() != null ? spec.getBulk() ? new GCGenericBulkDependentResource(genericTemplateHandler, @@ -238,18 +233,20 @@ private GenericDependentResource createDependentResource(DependentResourceSpec s spec.getName(), spec.isClusterScoped(), spec.getMatcher()) : new GCGenericDependentResource(genericTemplateHandler, spec.getResourceTemplate(), - spec.getName(), + spec.getName(), resourceName, namespace, spec.isClusterScoped(), spec.getMatcher()) : new GCGenericDependentResource(genericTemplateHandler, spec.getResource(), - spec.getName(), + spec.getName(), resourceName, namespace, spec.isClusterScoped(), spec.getMatcher()); } else { return spec.getResourceTemplate() != null ? new GenericDependentResource(genericTemplateHandler, - spec.getResourceTemplate(), spec.getName(), spec.isClusterScoped(), + spec.getResourceTemplate(), spec.getName(), resourceName, namespace, + spec.isClusterScoped(), spec.getMatcher()) : new GenericDependentResource(genericTemplateHandler, - spec.getResource(), spec.getName(), spec.isClusterScoped(), spec.getMatcher()); + spec.getResource(), spec.getName(), resourceName, namespace, spec.isClusterScoped(), + spec.getMatcher()); } } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerProducer.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerProducer.java index 405db6e..4b7a957 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerProducer.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerProducer.java @@ -2,7 +2,7 @@ import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; @@ -15,7 +15,7 @@ public class InformerProducer { public InformerEventSource createInformer( - InformerConfiguration configuration, + InformerEventSourceConfiguration configuration, Context context) { return new InformerEventSource<>(configuration, context.eventSourceRetriever().eventSourceContextForDynamicRegistration()); diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegister.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegister.java index 02a6fdf..dae2fcf 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegister.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegister.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import io.fabric8.kubernetes.api.model.GenericKubernetesResource; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.Context; import io.javaoperatorsdk.operator.glue.ControllerConfig; import io.javaoperatorsdk.operator.glue.Utils; @@ -94,8 +94,10 @@ public InformerEventSource registerInformer( markEventSource(gvk, glue); } - var configBuilder = InformerConfiguration.from(gvk) - .withSecondaryToPrimaryMapper(mapper); + var configBuilder = InformerEventSourceConfiguration.from(gvk, Glue.class) + .withSecondaryToPrimaryMapper(mapper) + .withName(gvk.toString()); + configBuilder.withName(gvk.toString()); labelSelectorForGVK(gvk).ifPresent(ls -> { log.debug("Registering label selector: {} for informer for gvk: {}", ls, gvk); configBuilder.withLabelSelector(ls); @@ -103,10 +105,14 @@ public InformerEventSource registerInformer( var newInformer = informerProducer.createInformer(configBuilder.build(), context); - return (InformerEventSource) context + var resultInformer = (InformerEventSource) context .eventSourceRetriever() - .dynamicallyRegisterEventSource(gvk.toString(), newInformer); - + .dynamicallyRegisterEventSource(newInformer); + if (log.isDebugEnabled()) { + log.debug("Registering informer for gvk: {} actually registered: {}", gvk, + resultInformer == newInformer); + } + return resultInformer; } public synchronized void deRegisterInformer(GroupVersionKind groupVersionKind, diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/RelatedAndOwnedResourceSecondaryToPrimaryMapper.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/RelatedAndOwnedResourceSecondaryToPrimaryMapper.java index 5f722b5..4a9d299 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/RelatedAndOwnedResourceSecondaryToPrimaryMapper.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/glue/RelatedAndOwnedResourceSecondaryToPrimaryMapper.java @@ -6,7 +6,11 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import io.fabric8.kubernetes.api.model.GenericKubernetesResource; +import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper; import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; @@ -14,13 +18,16 @@ public class RelatedAndOwnedResourceSecondaryToPrimaryMapper implements SecondaryToPrimaryMapper { + private static final Logger log = + LoggerFactory.getLogger(RelatedAndOwnedResourceSecondaryToPrimaryMapper.class); + private final Map> secondaryToPrimaryMap = new ConcurrentHashMap<>(); @Override public Set toPrimaryResourceIDs(GenericKubernetesResource resource) { // based on if GC or non GC dependent it can have different mapping - var res = Mappers.fromOwnerReferences(false).toPrimaryResourceIDs(resource); - res.addAll(Mappers.fromDefaultAnnotations().toPrimaryResourceIDs(resource)); + var res = Mappers.fromOwnerReferences(Glue.class, false).toPrimaryResourceIDs(resource); + res.addAll(Mappers.fromDefaultAnnotations(Glue.class).toPrimaryResourceIDs(resource)); // related resource mapping var idMapped = secondaryToPrimaryMap.get( @@ -28,6 +35,9 @@ public Set toPrimaryResourceIDs(GenericKubernetesResource resource) if (idMapped != null) { res.addAll(idMapped); } + log.debug("Resource name: {}, namespace: {}, kind: {}, resourceIds: {}", + resource.getMetadata().getName(), + resource.getMetadata().getNamespace(), resource.getKind(), res); return res; } diff --git a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java index d1943a0..ab6ac97 100644 --- a/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java +++ b/src/main/java/io/javaoperatorsdk/operator/glue/reconciler/operator/GlueOperatorReconciler.java @@ -10,7 +10,7 @@ import io.fabric8.kubernetes.api.model.ObjectMeta; import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.client.utils.KubernetesResourceUtil; -import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; +import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration; import io.javaoperatorsdk.operator.api.reconciler.*; import io.javaoperatorsdk.operator.glue.ControllerConfig; import io.javaoperatorsdk.operator.glue.GlueException; @@ -19,12 +19,13 @@ import io.javaoperatorsdk.operator.glue.customresource.glue.RelatedResourceSpec; import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperator; import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperatorSpec; +import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperatorStatus; import io.javaoperatorsdk.operator.glue.customresource.operator.Parent; -import io.javaoperatorsdk.operator.glue.customresource.operator.ResourceFlowOperatorStatus; -import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; +import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndStatusHandler; import io.javaoperatorsdk.operator.glue.reconciler.glue.GlueReconciler; import io.javaoperatorsdk.operator.glue.templating.GenericTemplateHandler; import io.javaoperatorsdk.operator.processing.GroupVersionKind; +import io.javaoperatorsdk.operator.processing.event.NoEventSourceForClassException; import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.javaoperatorsdk.operator.processing.event.source.EventSource; import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; @@ -33,8 +34,8 @@ @ControllerConfiguration(name = GlueOperatorReconciler.GLUE_OPERATOR_RECONCILER_NAME) public class GlueOperatorReconciler - implements Reconciler, EventSourceInitializer, - Cleaner, ErrorStatusHandler { + implements Reconciler, + Cleaner { private static final Logger log = LoggerFactory.getLogger(GlueOperatorReconciler.class); @@ -48,7 +49,7 @@ public class GlueOperatorReconciler Optional glueLabelSelector; private final ControllerConfig controllerConfig; - private final ValidationAndErrorHandler validationAndErrorHandler; + private final ValidationAndStatusHandler validationAndErrorHandler; private final GenericTemplateHandler genericTemplateHandler; private Map defaultGlueLabels; @@ -56,10 +57,10 @@ public class GlueOperatorReconciler private InformerEventSource glueEventSource; public GlueOperatorReconciler(ControllerConfig controllerConfig, - ValidationAndErrorHandler validationAndErrorHandler, + ValidationAndStatusHandler validationAndStatusHandler, GenericTemplateHandler genericTemplateHandler) { this.controllerConfig = controllerConfig; - this.validationAndErrorHandler = validationAndErrorHandler; + this.validationAndErrorHandler = validationAndStatusHandler; this.genericTemplateHandler = genericTemplateHandler; } @@ -95,7 +96,7 @@ public UpdateControl reconcile(GlueOperator glueOperator, } }); - return UpdateControl.noUpdate(); + return validationAndErrorHandler.handleStatusUpdate(glueOperator); } private Glue createGlue(GenericKubernetesResource targetParentResource, @@ -177,11 +178,11 @@ private InformerEventSource getOrRegist try { es = (InformerEventSource) context .eventSourceRetriever() - .getResourceEventSourceFor(GenericKubernetesResource.class, gvk.toString()); + .getEventSourceFor(GenericKubernetesResource.class, gvk.toString()); es.start(); - } catch (IllegalArgumentException e) { - var configBuilder = InformerConfiguration.from(gvk, - context.eventSourceRetriever().eventSourceContextForDynamicRegistration()) + } catch (NoEventSourceForClassException | IllegalArgumentException e) { + var configBuilder = InformerEventSourceConfiguration.from(gvk, GlueOperator.class) + .withName(gvk.toString()) .withSecondaryToPrimaryMapper( resource -> Set.of(ResourceID.fromResource(glueOperator))); @@ -191,27 +192,28 @@ private InformerEventSource getOrRegist es = new InformerEventSource<>(configBuilder.build(), context.eventSourceRetriever().eventSourceContextForDynamicRegistration()); - context.eventSourceRetriever().dynamicallyRegisterEventSource(gvk.toString(), es); + context.eventSourceRetriever().dynamicallyRegisterEventSource(es); } return es; } @Override - public Map prepareEventSources( + public List> prepareEventSources( EventSourceContext eventSourceContext) { glueEventSource = new InformerEventSource<>( - InformerConfiguration.from(Glue.class, eventSourceContext) + InformerEventSourceConfiguration.from(Glue.class, GlueOperator.class) + .withName("GlueEventSource") .withLabelSelector(FOR_GLUE_OPERATOR_LABEL_KEY + "=" + FOR_GLUE_OPERATOR_LABEL_VALUE) .build(), eventSourceContext); - return EventSourceInitializer.nameEventSources(glueEventSource); + return List.of(glueEventSource); } @Override public ErrorStatusUpdateControl updateErrorStatus(GlueOperator resource, Context context, Exception e) { if (resource.getStatus() == null) { - resource.setStatus(new ResourceFlowOperatorStatus()); + resource.setStatus(new GlueOperatorStatus()); } return validationAndErrorHandler.updateStatusErrorMessage(e, resource); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a501d72..c9ca4d7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,3 +11,4 @@ quarkus.container-image.labels."org.opencontainers.image.source"=https://github. quarkus.container-image.labels."org.opencontainers.image.documentation"=https://github.com/java-operator-sdk/kubernetes-glue-operator?tab=readme-ov-file#documentation # Generate apply-able cluster role bindings quarkus.kubernetes.namespace=default +quarkus.operator-sdk.enable-ssa=false \ No newline at end of file diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/GlueOperatorTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/GlueOperatorTest.java index e1febf8..db0fa03 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/GlueOperatorTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/GlueOperatorTest.java @@ -18,7 +18,7 @@ import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperator; import io.javaoperatorsdk.operator.glue.customresource.operator.GlueOperatorSpec; import io.javaoperatorsdk.operator.glue.customresource.operator.Parent; -import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; +import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndStatusHandler; import io.javaoperatorsdk.operator.glue.reconciler.operator.GlueOperatorReconciler; import io.quarkus.test.junit.QuarkusTest; @@ -162,7 +162,7 @@ void nonUniqueNameTest() { assertThat(actual.getStatus()).isNotNull(); assertThat(actual.getStatus().getErrorMessage()) - .startsWith(ValidationAndErrorHandler.NON_UNIQUE_NAMES_FOUND_PREFIX); + .startsWith(ValidationAndStatusHandler.NON_UNIQUE_NAMES_FOUND_PREFIX); }); } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java index cdd3515..6564439 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/GlueTest.java @@ -19,7 +19,7 @@ import io.javaoperatorsdk.operator.glue.customresource.TestCustomResource; import io.javaoperatorsdk.operator.glue.customresource.glue.DependentResourceSpec; import io.javaoperatorsdk.operator.glue.customresource.glue.Glue; -import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndErrorHandler; +import io.javaoperatorsdk.operator.glue.reconciler.ValidationAndStatusHandler; import io.quarkus.test.junit.QuarkusTest; import static io.javaoperatorsdk.operator.glue.TestUtils.INITIAL_RECONCILE_WAIT_TIMEOUT; @@ -38,7 +38,7 @@ void simpleTemplating() { TestUtils.loadGlue("/glue/Templating.yaml"); glue = create(glue); - await().untilAsserted(() -> { + await().timeout(Duration.ofHours(1)).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "templconfigmap1"); var cm2 = get(ConfigMap.class, "templconfigmap2"); assertThat(cm1).isNotNull(); @@ -60,7 +60,7 @@ void simpleTemplating() { delete(glue); - await().timeout(Duration.ofSeconds(30)).untilAsserted(() -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "templconfigmap1"); var cm2 = get(ConfigMap.class, "templconfigmap2"); assertThat(cm1).isNull(); @@ -99,7 +99,7 @@ void crossReferenceResource() { delete(glue); - await().untilAsserted(() -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "cm-1"); var cm2 = get(ConfigMap.class, "cm-2"); assertThat(cm1).isNull(); @@ -136,7 +136,7 @@ void javaScriptCondition() { delete(glue); - await().timeout(Duration.ofSeconds(GC_TIMEOUT_SEC)).untilAsserted(() -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "configmap1"); var cm2 = get(ConfigMap.class, "configmap2"); assertThat(cm1).isNull(); @@ -159,7 +159,7 @@ void stringTemplate() { delete(glue); - await().untilAsserted(() -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "templconfigmap1"); var cm2 = get(ConfigMap.class, "templconfigmap2"); assertThat(cm1).isNull(); @@ -188,7 +188,7 @@ void simpleConcurrencyTest() { })); glueList.forEach(this::delete); - await().untilAsserted(() -> IntStream.range(0, num).forEach(index -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> IntStream.range(0, num).forEach(index -> { var w = get(Glue.class, "concurrencysample" + index); assertThat(w).isNull(); })); @@ -224,7 +224,7 @@ void changingWorkflow() { glue.getMetadata().setResourceVersion(null); delete(glue); - await().untilAsserted(() -> { + await().timeout(GC_TIMEOUT).untilAsserted(() -> { var cm1 = get(ConfigMap.class, "configmap1"); var s = get(Secret.class, "secret1"); assertThat(cm1).isNull(); @@ -241,7 +241,7 @@ void nonUniqueNameResultsInErrorMessageOnStatus() { assertThat(actualGlue.getStatus()).isNotNull(); Assertions.assertThat(actualGlue.getStatus().getErrorMessage()) - .startsWith(ValidationAndErrorHandler.NON_UNIQUE_NAMES_FOUND_PREFIX); + .startsWith(ValidationAndStatusHandler.NON_UNIQUE_NAMES_FOUND_PREFIX); }); } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java b/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java index 67228e8..bdc69d4 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/TestBase.java @@ -24,7 +24,8 @@ public class TestBase { - public static final int GC_TIMEOUT_SEC = 45; + public static final int GC_TIMEOUT_SEC = 120; + public static final Duration GC_TIMEOUT = Duration.ofSeconds(GC_TIMEOUT_SEC); @Inject protected KubernetesClient client; diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegisterTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegisterTest.java index 009bd6d..a9fca1f 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegisterTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/reconciler/glue/InformerRegisterTest.java @@ -38,7 +38,7 @@ void registersInformerWithLabelSelectorIfConfigured() { register.registerInformer(mockContext, gvk, testGlue()); verify(informerProducer).createInformer(argThat(c -> { - assertThat(c.getLabelSelector()).isEqualTo(LABEL_SELECTOR); + assertThat(c.getInformerConfig().getLabelSelector()).isEqualTo(LABEL_SELECTOR); return true; }), any()); } diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java index c4763ba..4631639 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageE2E.java @@ -52,7 +52,7 @@ void testWebPageCRUDOperations() { createdWebPage.getMetadata().setResourceVersion(null); createdWebPage.getSpec().setExposed(true); - createdWebPage = client.resource(createdWebPage).update(); + createdWebPage = client.resource(createdWebPage).patch(); await().untilAsserted(() -> { var ingress = client.resources(Ingress.class).withName(webPage.getMetadata().getName()).get(); diff --git a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java index ebe61f9..5da148a 100644 --- a/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java +++ b/src/test/java/io/javaoperatorsdk/operator/glue/sample/webpage/WebPageSampleTest.java @@ -1,6 +1,7 @@ package io.javaoperatorsdk.operator.glue.sample.webpage; + import org.junit.jupiter.api.Test; import io.fabric8.kubernetes.api.model.ConfigMap; @@ -15,7 +16,7 @@ import static org.awaitility.Awaitility.await; @QuarkusTest -public class WebPageSampleTest extends TestBase { +class WebPageSampleTest extends TestBase { @Test void webPageCRUD() {