Skip to content

feat: handle clustered resource on secondary to primary mapper init #2321

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 1 commit into from
Mar 27, 2024
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 @@ -103,21 +103,22 @@ static boolean getBooleanFromSystemPropsOrDefault(String propertyName, boolean d
return defaultValue;
} else {
property = property.trim().toLowerCase();
switch (property) {
case "true":
return true;
case "false":
return false;
default:
return defaultValue;
}
return switch (property) {
case "true" -> true;
case "false" -> false;
default -> defaultValue;
};
}
}

public static Class<?> getFirstTypeArgumentFromExtendedClass(Class<?> clazz) {
return getTypeArgumentFromExtendedClassByIndex(clazz, 0);
}

public static Class<?> getTypeArgumentFromExtendedClassByIndex(Class<?> clazz, int index) {
try {
Type type = clazz.getGenericSuperclass();
return (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
return (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[index];
} catch (Exception e) {
throw new RuntimeException(GENERIC_PARAMETER_TYPE_ERROR_PREFIX
+ clazz.getSimpleName()
Expand Down Expand Up @@ -186,27 +187,31 @@ private static Optional<? extends Class<?>> extractType(Class<?> clazz,

public static Class<?> getFirstTypeArgumentFromSuperClassOrInterface(Class<?> clazz,
Class<?> expectedImplementedInterface) {
return getTypeArgumentFromSuperClassOrInterfaceByIndex(clazz, expectedImplementedInterface, 0);
}

public static Class<?> getTypeArgumentFromSuperClassOrInterfaceByIndex(Class<?> clazz,
Class<?> expectedImplementedInterface, int index) {
// first check super class if it exists
try {
final Class<?> superclass = clazz.getSuperclass();
if (!superclass.equals(Object.class)) {
try {
return getFirstTypeArgumentFromExtendedClass(clazz);
return getTypeArgumentFromExtendedClassByIndex(clazz, index);
} catch (Exception e) {
// try interfaces
try {
return getFirstTypeArgumentFromInterface(clazz, expectedImplementedInterface);
return getTypeArgumentFromInterfaceByIndex(clazz, expectedImplementedInterface, index);
} catch (Exception ex) {
// try on the parent
return getFirstTypeArgumentFromSuperClassOrInterface(superclass,
expectedImplementedInterface);
return getTypeArgumentFromSuperClassOrInterfaceByIndex(superclass,
expectedImplementedInterface, index);
}
}
}
return getFirstTypeArgumentFromInterface(clazz, expectedImplementedInterface);
return getTypeArgumentFromInterfaceByIndex(clazz, expectedImplementedInterface, index);
} catch (Exception e) {
throw new OperatorException(
GENERIC_PARAMETER_TYPE_ERROR_PREFIX + clazz.getSimpleName(), e);
throw new OperatorException(GENERIC_PARAMETER_TYPE_ERROR_PREFIX + clazz.getSimpleName(), e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.api.config.Utils;
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
import io.javaoperatorsdk.operator.processing.GroupVersionKind;

public class GenericKubernetesDependentResource<P extends HasMetadata>
extends KubernetesDependentResource<GenericKubernetesResource, P> {

private GroupVersionKind groupVersionKind;
private final GroupVersionKind groupVersionKind;

public GenericKubernetesDependentResource(GroupVersionKind groupVersionKind) {
super(GenericKubernetesResource.class);
Expand All @@ -19,6 +20,13 @@ protected InformerConfiguration.InformerConfigurationBuilder<GenericKubernetesRe
return InformerConfiguration.from(groupVersionKind);
}

@SuppressWarnings("unchecked")
@Override
protected Class<P> getPrimaryResourceType() {
return (Class<P>) Utils.getFirstTypeArgumentFromExtendedClass(getClass());
}

@SuppressWarnings("unused")
public GroupVersionKind getGroupVersionKind() {
return groupVersionKind;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import org.slf4j.LoggerFactory;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.javaoperatorsdk.operator.OperatorException;
import io.javaoperatorsdk.operator.ReconcilerUtils;
import io.javaoperatorsdk.operator.api.config.Utils;
import io.javaoperatorsdk.operator.api.config.dependent.Configured;
import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Constants;
Expand All @@ -36,28 +38,36 @@ public abstract class KubernetesDependentResource<R extends HasMetadata, P exten
implements DependentResourceConfigurator<KubernetesDependentResourceConfig<R>> {

private static final Logger log = LoggerFactory.getLogger(KubernetesDependentResource.class);
private final ResourceUpdaterMatcher<R> updaterMatcher;
private final boolean garbageCollected = this instanceof GarbageCollected;
private final boolean usingCustomResourceUpdateMatcher = this instanceof ResourceUpdaterMatcher;
@SuppressWarnings("unchecked")
private final ResourceUpdaterMatcher<R> updaterMatcher = usingCustomResourceUpdateMatcher
? (ResourceUpdaterMatcher<R>) this
: GenericResourceUpdaterMatcher.updaterMatcherFor(resourceType());
private final boolean clustered;
private KubernetesDependentResourceConfig<R> kubernetesDependentResourceConfig;

private final boolean usingCustomResourceUpdateMatcher;

@SuppressWarnings("unchecked")
public KubernetesDependentResource(Class<R> resourceType) {
this(resourceType, null);
}

@SuppressWarnings("unchecked")
public KubernetesDependentResource(Class<R> resourceType, String name) {
super(resourceType, name);
final var primaryResourceType = getPrimaryResourceType();
clustered = !Namespaced.class.isAssignableFrom(primaryResourceType);
}

usingCustomResourceUpdateMatcher = this instanceof ResourceUpdaterMatcher;
updaterMatcher = usingCustomResourceUpdateMatcher
? (ResourceUpdaterMatcher<R>) this
: GenericResourceUpdaterMatcher.updaterMatcherFor(resourceType);
protected KubernetesDependentResource(Class<R> resourceType, String name,
boolean primaryIsClustered) {
super(resourceType, name);
clustered = primaryIsClustered;
}

@SuppressWarnings("unchecked")
protected Class<P> getPrimaryResourceType() {
return (Class<P>) Utils.getTypeArgumentFromExtendedClassByIndex(getClass(), 1);
}

@Override
public void configureWith(KubernetesDependentResourceConfig<R> config) {
this.kubernetesDependentResourceConfig = config;
Expand Down Expand Up @@ -89,7 +99,7 @@ private SecondaryToPrimaryMapper<R> getSecondaryToPrimaryMapper() {
if (this instanceof SecondaryToPrimaryMapper) {
return (SecondaryToPrimaryMapper<R>) this;
} else if (garbageCollected) {
return Mappers.fromOwnerReferences(false);
return Mappers.fromOwnerReferences(clustered);
} else if (useNonOwnerRefBasedSecondaryToPrimaryMapping()) {
return Mappers.fromDefaultAnnotations();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public TestDependent(String name) {
super(ConfigMap.class, name);
}

@Override
protected Class<TestCustomResource> getPrimaryResourceType() {
return TestCustomResource.class;
}

@Override
public ReconcileResult<ConfigMap> reconcile(TestCustomResource primary,
Context<TestCustomResource> context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,24 @@ public ConfigMapDeleterBulkDependentResource() {
super(ConfigMap.class);
}

@Override
protected Class<BulkDependentTestCustomResource> getPrimaryResourceType() {
return BulkDependentTestCustomResource.class;
}

@Override
public Map<String, ConfigMap> desiredResources(BulkDependentTestCustomResource primary,
Context<BulkDependentTestCustomResource> context) {
var number = primary.getSpec().getNumberOfResources();
Map<String, ConfigMap> res = new HashMap<>();
for (int i = 0; i < number; i++) {
var key = Integer.toString(i);
res.put(key, desired(primary, key, context));
res.put(key, desired(primary, key));
}
return res;
}

public ConfigMap desired(BulkDependentTestCustomResource primary, String key,
Context<BulkDependentTestCustomResource> context) {
public ConfigMap desired(BulkDependentTestCustomResource primary, String key) {
ConfigMap configMap = new ConfigMap();
configMap.setMetadata(new ObjectMetaBuilder()
.withName(primary.getMetadata().getName() + INDEX_DELIMITER + key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public BaseDependentResource(Class<R> resourceType, String component) {
this.component = component;
}

@Override
protected Class<ComplexDependentCustomResource> getPrimaryResourceType() {
return ComplexDependentCustomResource.class;
}

protected String name(ComplexDependentCustomResource primary) {
return String.format("%s-%s", component, primary.getSpec().getProjectId());
}
Expand Down
Loading