|
| 1 | +package io.javaoperatorsdk.operator.api.reconciler.dependent; |
| 2 | + |
| 3 | +import java.util.Optional; |
| 4 | + |
| 5 | +import org.slf4j.Logger; |
| 6 | +import org.slf4j.LoggerFactory; |
| 7 | + |
| 8 | +import io.fabric8.kubernetes.api.model.HasMetadata; |
| 9 | +import io.fabric8.kubernetes.client.KubernetesClient; |
| 10 | +import io.javaoperatorsdk.operator.ReconcilerUtils; |
| 11 | +import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration; |
| 12 | +import io.javaoperatorsdk.operator.api.reconciler.Context; |
| 13 | +import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext; |
| 14 | +import io.javaoperatorsdk.operator.processing.event.ResourceID; |
| 15 | +import io.javaoperatorsdk.operator.processing.event.source.AssociatedSecondaryResourceIdentifier; |
| 16 | +import io.javaoperatorsdk.operator.processing.event.source.EventSource; |
| 17 | +import io.javaoperatorsdk.operator.processing.event.source.PrimaryResourcesRetriever; |
| 18 | +import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource; |
| 19 | +import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers; |
| 20 | + |
| 21 | +public abstract class KubernetesDependentResource<R extends HasMetadata, P extends HasMetadata> |
| 22 | +extends AbstractDependentResource<R, P> { |
| 23 | + |
| 24 | +private static final Logger log = LoggerFactory.getLogger(KubernetesDependentResource.class); |
| 25 | + |
| 26 | +protected KubernetesClient client; |
| 27 | +private boolean explicitDelete = false; |
| 28 | +private boolean owned = true; |
| 29 | +private InformerEventSource<R, P> informerEventSource; |
| 30 | + |
| 31 | +public KubernetesDependentResource() { |
| 32 | +this(null); |
| 33 | +} |
| 34 | + |
| 35 | +public KubernetesDependentResource(KubernetesClient client) { |
| 36 | +this.client = client; |
| 37 | +} |
| 38 | + |
| 39 | +protected void beforeCreateOrUpdate(R desired, P primary) { |
| 40 | +if (owned) { |
| 41 | +desired.addOwnerReference(primary); |
| 42 | +} |
| 43 | +} |
| 44 | + |
| 45 | +@Override |
| 46 | +protected boolean match(R actual, R target, Context context) { |
| 47 | +return ReconcilerUtils.specsEqual(actual, target); |
| 48 | +} |
| 49 | + |
| 50 | +@SuppressWarnings("unchecked") |
| 51 | +@Override |
| 52 | +protected R create(R target, P primary, Context context) { |
| 53 | +log.debug("Creating target resource with type: " + |
| 54 | +"{}, with id: {}", target.getClass(), ResourceID.fromResource(target)); |
| 55 | +beforeCreateOrUpdate(target, primary); |
| 56 | +Class<R> targetClass = (Class<R>) target.getClass(); |
| 57 | +return client.resources(targetClass).inNamespace(target.getMetadata().getNamespace()) |
| 58 | +.create(target); |
| 59 | +} |
| 60 | + |
| 61 | +@SuppressWarnings("unchecked") |
| 62 | +@Override |
| 63 | +protected R update(R actual, R target, P primary, Context context) { |
| 64 | +log.debug("Updating target resource with type: {}, with id: {}", target.getClass(), |
| 65 | +ResourceID.fromResource(target)); |
| 66 | +beforeCreateOrUpdate(target, primary); |
| 67 | +Class<R> targetClass = (Class<R>) target.getClass(); |
| 68 | +return client.resources(targetClass).inNamespace(target.getMetadata().getNamespace()) |
| 69 | +.replace(target); |
| 70 | +} |
| 71 | + |
| 72 | +@SuppressWarnings({"unchecked", "rawtypes"}) |
| 73 | +@Override |
| 74 | +public Optional<EventSource> eventSource(EventSourceContext<P> context) { |
| 75 | +if (informerEventSource != null) { |
| 76 | +return Optional.of(informerEventSource); |
| 77 | +} |
| 78 | +var informerConfig = initInformerConfiguration(context); |
| 79 | +informerEventSource = new InformerEventSource(informerConfig, context); |
| 80 | +return Optional.of(informerEventSource); |
| 81 | +} |
| 82 | + |
| 83 | +@SuppressWarnings("unchecked") |
| 84 | +private InformerConfiguration<R, P> initInformerConfiguration(EventSourceContext<P> context) { |
| 85 | +PrimaryResourcesRetriever<R> associatedPrimaries = |
| 86 | +(this instanceof PrimaryResourcesRetriever) ? (PrimaryResourcesRetriever<R>) this |
| 87 | +: getDefaultPrimaryResourcesRetriever(); |
| 88 | + |
| 89 | +AssociatedSecondaryResourceIdentifier<P> associatedSecondary = |
| 90 | +(this instanceof AssociatedSecondaryResourceIdentifier) |
| 91 | +? (AssociatedSecondaryResourceIdentifier<P>) this |
| 92 | +: getDefaultAssociatedSecondaryResourceIdentifier(); |
| 93 | + |
| 94 | +return InformerConfiguration.from(context, resourceType()) |
| 95 | +.withPrimaryResourcesRetriever(associatedPrimaries) |
| 96 | +.withAssociatedSecondaryResourceIdentifier(associatedSecondary) |
| 97 | +.build(); |
| 98 | +} |
| 99 | + |
| 100 | +protected AssociatedSecondaryResourceIdentifier<P> getDefaultAssociatedSecondaryResourceIdentifier() { |
| 101 | +return ResourceID::fromResource; |
| 102 | +} |
| 103 | + |
| 104 | +protected PrimaryResourcesRetriever<R> getDefaultPrimaryResourcesRetriever() { |
| 105 | +return Mappers.fromOwnerReference(); |
| 106 | +} |
| 107 | + |
| 108 | +public KubernetesDependentResource<R, P> setInformerEventSource( |
| 109 | +InformerEventSource<R, P> informerEventSource) { |
| 110 | +this.informerEventSource = informerEventSource; |
| 111 | +return this; |
| 112 | +} |
| 113 | + |
| 114 | +@Override |
| 115 | +public void delete(P primary, Context context) { |
| 116 | +if (explicitDelete) { |
| 117 | +var resource = getResource(primary); |
| 118 | +resource.ifPresent(r -> client.resource(r).delete()); |
| 119 | +} |
| 120 | +} |
| 121 | + |
| 122 | +@Override |
| 123 | +public Optional<R> getResource(P primaryResource) { |
| 124 | +return informerEventSource.getAssociated(primaryResource); |
| 125 | +} |
| 126 | + |
| 127 | +public KubernetesDependentResource<R, P> setClient(KubernetesClient client) { |
| 128 | +this.client = client; |
| 129 | +return this; |
| 130 | +} |
| 131 | + |
| 132 | + |
| 133 | +public KubernetesDependentResource<R, P> setExplicitDelete(boolean explicitDelete) { |
| 134 | +this.explicitDelete = explicitDelete; |
| 135 | +return this; |
| 136 | +} |
| 137 | + |
| 138 | +public boolean isExplicitDelete() { |
| 139 | +return explicitDelete; |
| 140 | +} |
| 141 | + |
| 142 | +public boolean isOwned() { |
| 143 | +return owned; |
| 144 | +} |
| 145 | + |
| 146 | +public KubernetesDependentResource<R, P> setOwned(boolean owned) { |
| 147 | +this.owned = owned; |
| 148 | +return this; |
| 149 | +} |
| 150 | +} |
0 commit comments