Skip to content

Commit 74454ea

Browse files
metacosmcsviri
andauthored
refactor: make it easier to initialize mapper & cloner in subclasses (#1403)
* feat: use fabric8 client json mapper by default (#1382) Also remove constants to avoid mismatched configurations * refactor: make it easier to initialize mapper & cloner in subclasses Co-authored-by: Attila Mészáros <[email protected]>
1 parent c1dfd91 commit 74454ea

File tree

5 files changed

+66
-31
lines changed

5 files changed

+66
-31
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java

+39
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,40 @@
99
import io.javaoperatorsdk.operator.ReconcilerUtils;
1010
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
1111

12+
import com.fasterxml.jackson.databind.ObjectMapper;
13+
1214
@SuppressWarnings("rawtypes")
1315
public class AbstractConfigurationService implements ConfigurationService {
1416
private final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();
1517
private final Version version;
18+
private Cloner cloner;
19+
private ObjectMapper mapper;
1620

1721
public AbstractConfigurationService(Version version) {
22+
this(version, null, null);
23+
}
24+
25+
public AbstractConfigurationService(Version version, Cloner cloner) {
26+
this(version, cloner, null);
27+
}
28+
29+
public AbstractConfigurationService(Version version, Cloner cloner, ObjectMapper mapper) {
1830
this.version = version;
31+
init(cloner, mapper);
32+
}
33+
34+
/**
35+
* Subclasses can call this method to more easily initialize the {@link Cloner} and
36+
* {@link ObjectMapper} associated with this ConfigurationService implementation. This is useful
37+
* in situations where the cloner depends on a mapper that might require additional configuration
38+
* steps before it's ready to be used.
39+
*
40+
* @param cloner the {@link Cloner} instance to be used
41+
* @param mapper the {@link ObjectMapper} instance to be used
42+
*/
43+
protected void init(Cloner cloner, ObjectMapper mapper) {
44+
this.cloner = cloner != null ? cloner : ConfigurationService.super.getResourceCloner();
45+
this.mapper = mapper != null ? mapper : ConfigurationService.super.getObjectMapper();
1946
}
2047

2148
protected <R extends HasMetadata> void register(ControllerConfiguration<R> config) {
@@ -77,10 +104,12 @@ protected <R extends HasMetadata> String keyFor(Reconciler<R> reconciler) {
77104
return ReconcilerUtils.getNameFor(reconciler);
78105
}
79106

107+
@SuppressWarnings("unused")
80108
protected ControllerConfiguration getFor(String reconcilerName) {
81109
return configurations.get(reconcilerName);
82110
}
83111

112+
@SuppressWarnings("unused")
84113
protected Stream<ControllerConfiguration> controllerConfigurations() {
85114
return configurations.values().stream();
86115
}
@@ -94,4 +123,14 @@ public Set<String> getKnownReconcilerNames() {
94123
public Version getVersion() {
95124
return version;
96125
}
126+
127+
@Override
128+
public Cloner getResourceCloner() {
129+
return cloner;
130+
}
131+
132+
@Override
133+
public ObjectMapper getObjectMapper() {
134+
return mapper;
135+
}
97136
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import io.fabric8.kubernetes.api.model.HasMetadata;
77
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
88

9+
import com.fasterxml.jackson.databind.ObjectMapper;
10+
911
public class BaseConfigurationService extends AbstractConfigurationService {
1012

1113
private static final String LOGGER_NAME = "Default ConfigurationService implementation";
@@ -15,6 +17,10 @@ public BaseConfigurationService(Version version) {
1517
super(version);
1618
}
1719

20+
public BaseConfigurationService(Version version, Cloner cloner, ObjectMapper mapper) {
21+
super(version, cloner, mapper);
22+
}
23+
1824
public BaseConfigurationService() {
1925
this(Utils.loadFromProperties());
2026
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java

+18-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.fabric8.kubernetes.api.model.HasMetadata;
88
import io.fabric8.kubernetes.client.Config;
99
import io.fabric8.kubernetes.client.CustomResource;
10+
import io.fabric8.kubernetes.client.utils.Serialization;
1011
import io.javaoperatorsdk.operator.api.monitoring.Metrics;
1112
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
1213
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceFactory;
@@ -17,20 +18,6 @@
1718
/** An interface from which to retrieve configuration information. */
1819
public interface ConfigurationService {
1920

20-
ObjectMapper OBJECT_MAPPER = new ObjectMapper();
21-
22-
Cloner DEFAULT_CLONER = new Cloner() {
23-
@SuppressWarnings("unchecked")
24-
@Override
25-
public HasMetadata clone(HasMetadata object) {
26-
try {
27-
return OBJECT_MAPPER.readValue(OBJECT_MAPPER.writeValueAsString(object), object.getClass());
28-
} catch (JsonProcessingException e) {
29-
throw new IllegalStateException(e);
30-
}
31-
}
32-
};
33-
3421
/**
3522
* Retrieves the configuration associated with the specified reconciler
3623
*
@@ -93,12 +80,25 @@ default int concurrentReconciliationThreads() {
9380
}
9481

9582
/**
96-
* Used to clone custom resources.
83+
* Used to clone custom resources. It is strongly suggested that implementors override this method
84+
* since the default implementation creates a new {@link Cloner} instance each time this method is
85+
* called.
9786
*
98-
* @return the ObjectMapper to use
87+
* @return the configured {@link Cloner}
9988
*/
10089
default Cloner getResourceCloner() {
101-
return DEFAULT_CLONER;
90+
return new Cloner() {
91+
@SuppressWarnings("unchecked")
92+
@Override
93+
public HasMetadata clone(HasMetadata object) {
94+
try {
95+
final var mapper = getObjectMapper();
96+
return mapper.readValue(mapper.writeValueAsString(object), object.getClass());
97+
} catch (JsonProcessingException e) {
98+
throw new IllegalStateException(e);
99+
}
100+
}
101+
};
102102
}
103103

104104
int DEFAULT_TERMINATION_TIMEOUT_SECONDS = 10;
@@ -126,7 +126,7 @@ default boolean closeClientOnStop() {
126126
}
127127

128128
default ObjectMapper getObjectMapper() {
129-
return OBJECT_MAPPER;
129+
return Serialization.jsonMapper();
130130
}
131131

132132
default DependentResourceFactory dependentResourceFactory() {

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceOverrider.java

+1-11
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public ConfigurationServiceOverrider withObjectMapper(ObjectMapper objectMapper)
8181
}
8282

8383
public ConfigurationService build() {
84-
return new BaseConfigurationService(original.getVersion()) {
84+
return new BaseConfigurationService(original.getVersion(), cloner, objectMapper) {
8585
@Override
8686
public Set<String> getKnownReconcilerNames() {
8787
return original.getKnownReconcilerNames();
@@ -102,11 +102,6 @@ public int concurrentReconciliationThreads() {
102102
return threadNumber;
103103
}
104104

105-
@Override
106-
public Cloner getResourceCloner() {
107-
return cloner;
108-
}
109-
110105
@Override
111106
public int getTerminationTimeoutSeconds() {
112107
return timeoutSeconds;
@@ -130,11 +125,6 @@ public ExecutorService getExecutorService() {
130125
return super.getExecutorService();
131126
}
132127
}
133-
134-
@Override
135-
public ObjectMapper getObjectMapper() {
136-
return objectMapper;
137-
}
138128
};
139129
}
140130

operator-framework/src/test/java/io/javaoperatorsdk/operator/StandaloneDependentResourceIT.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import io.fabric8.kubernetes.api.model.ObjectMeta;
99
import io.fabric8.kubernetes.api.model.apps.Deployment;
10-
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
10+
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
1111
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
1212
import io.javaoperatorsdk.operator.sample.standalonedependent.StandaloneDependentTestCustomResource;
1313
import io.javaoperatorsdk.operator.sample.standalonedependent.StandaloneDependentTestCustomResourceSpec;
@@ -52,7 +52,7 @@ void executeUpdateForTestingCacheUpdateForGetResource() {
5252

5353
awaitForDeploymentReadyReplicas(1);
5454

55-
var clonedCr = ConfigurationService.DEFAULT_CLONER.clone(createdCR);
55+
var clonedCr = ConfigurationServiceProvider.instance().getResourceCloner().clone(createdCR);
5656
clonedCr.getSpec().setReplicaCount(2);
5757
operator.replace(StandaloneDependentTestCustomResource.class, clonedCr);
5858

0 commit comments

Comments
 (0)