Skip to content

Commit 9abcb37

Browse files
authored
feat: sample of how to do unmodifiable part of dependent (operator-framework#1746)
1 parent 2879d48 commit 9abcb37

File tree

5 files changed

+162
-0
lines changed

5 files changed

+162
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.extension.RegisterExtension;
5+
6+
import io.fabric8.kubernetes.api.model.ConfigMap;
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
9+
import io.javaoperatorsdk.operator.sample.unmodifiabledependentpart.UnmodifiableDependentPartCustomResource;
10+
import io.javaoperatorsdk.operator.sample.unmodifiabledependentpart.UnmodifiableDependentPartReconciler;
11+
import io.javaoperatorsdk.operator.sample.unmodifiabledependentpart.UnmodifiableDependentPartSpec;
12+
13+
import static io.javaoperatorsdk.operator.sample.unmodifiabledependentpart.UnmodifiablePartConfigMapDependent.ACTUAL_DATA_KEY;
14+
import static io.javaoperatorsdk.operator.sample.unmodifiabledependentpart.UnmodifiablePartConfigMapDependent.UNMODIFIABLE_INITIAL_DATA_KEY;
15+
import static org.assertj.core.api.Assertions.assertThat;
16+
import static org.awaitility.Awaitility.await;
17+
18+
public class UnmodifiableDependentPartIT {
19+
20+
public static final String TEST_RESOURCE_NAME = "test1";
21+
public static final String INITIAL_DATA = "initialData";
22+
public static final String UPDATED_DATA = "updatedData";
23+
24+
@RegisterExtension
25+
LocallyRunOperatorExtension operator =
26+
LocallyRunOperatorExtension.builder()
27+
.withReconciler(UnmodifiableDependentPartReconciler.class)
28+
.build();
29+
30+
@Test
31+
void partConfigMapDataUnmodifiable() {
32+
var resource = operator.create(testResource());
33+
34+
await().untilAsserted(() -> {
35+
var cm = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
36+
assertThat(cm).isNotNull();
37+
assertThat(cm.getData()).containsEntry(UNMODIFIABLE_INITIAL_DATA_KEY, INITIAL_DATA);
38+
assertThat(cm.getData()).containsEntry(ACTUAL_DATA_KEY, INITIAL_DATA);
39+
});
40+
41+
resource.getSpec().setData(UPDATED_DATA);
42+
operator.replace(resource);
43+
44+
await().untilAsserted(() -> {
45+
var cm = operator.get(ConfigMap.class, TEST_RESOURCE_NAME);
46+
assertThat(cm).isNotNull();
47+
assertThat(cm.getData()).containsEntry(UNMODIFIABLE_INITIAL_DATA_KEY, INITIAL_DATA);
48+
assertThat(cm.getData()).containsEntry(ACTUAL_DATA_KEY, UPDATED_DATA);
49+
});
50+
}
51+
52+
53+
UnmodifiableDependentPartCustomResource testResource() {
54+
var res = new UnmodifiableDependentPartCustomResource();
55+
res.setMetadata(new ObjectMetaBuilder()
56+
.withName(TEST_RESOURCE_NAME)
57+
.build());
58+
res.setSpec(new UnmodifiableDependentPartSpec());
59+
res.getSpec().setData(INITIAL_DATA);
60+
return res;
61+
}
62+
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.javaoperatorsdk.operator.sample.unmodifiabledependentpart;
2+
3+
import io.fabric8.kubernetes.api.model.Namespaced;
4+
import io.fabric8.kubernetes.client.CustomResource;
5+
import io.fabric8.kubernetes.model.annotation.Group;
6+
import io.fabric8.kubernetes.model.annotation.ShortNames;
7+
import io.fabric8.kubernetes.model.annotation.Version;
8+
9+
@Group("sample.javaoperatorsdk")
10+
@Version("v1")
11+
@ShortNames("udp")
12+
public class UnmodifiableDependentPartCustomResource
13+
extends CustomResource<UnmodifiableDependentPartSpec, Void>
14+
implements Namespaced {
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package io.javaoperatorsdk.operator.sample.unmodifiabledependentpart;
2+
3+
import java.util.concurrent.atomic.AtomicInteger;
4+
5+
import io.javaoperatorsdk.operator.api.reconciler.Context;
6+
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
7+
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
8+
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
9+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
10+
11+
@ControllerConfiguration(dependents = {@Dependent(type = UnmodifiablePartConfigMapDependent.class)})
12+
public class UnmodifiableDependentPartReconciler
13+
implements Reconciler<UnmodifiableDependentPartCustomResource> {
14+
15+
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
16+
17+
@Override
18+
public UpdateControl<UnmodifiableDependentPartCustomResource> reconcile(
19+
UnmodifiableDependentPartCustomResource resource,
20+
Context<UnmodifiableDependentPartCustomResource> context)
21+
throws InterruptedException {
22+
numberOfExecutions.addAndGet(1);
23+
return UpdateControl.noUpdate();
24+
}
25+
26+
public int getNumberOfExecutions() {
27+
return numberOfExecutions.get();
28+
}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.sample.unmodifiabledependentpart;
2+
3+
public class UnmodifiableDependentPartSpec {
4+
5+
private String data;
6+
7+
public String getData() {
8+
return data;
9+
}
10+
11+
public UnmodifiableDependentPartSpec setData(String data) {
12+
this.data = data;
13+
return this;
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.javaoperatorsdk.operator.sample.unmodifiabledependentpart;
2+
3+
import java.util.Map;
4+
5+
import io.fabric8.kubernetes.api.model.ConfigMap;
6+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.javaoperatorsdk.operator.api.reconciler.Context;
9+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
10+
11+
public class UnmodifiablePartConfigMapDependent
12+
extends CRUDKubernetesDependentResource<ConfigMap, UnmodifiableDependentPartCustomResource> {
13+
14+
public static final String UNMODIFIABLE_INITIAL_DATA_KEY = "initialDataKey";
15+
public static final String ACTUAL_DATA_KEY = "actualDataKey";
16+
17+
public UnmodifiablePartConfigMapDependent() {
18+
super(ConfigMap.class);
19+
}
20+
21+
@Override
22+
protected ConfigMap desired(UnmodifiableDependentPartCustomResource primary,
23+
Context<UnmodifiableDependentPartCustomResource> context) {
24+
var actual = getSecondaryResource(primary, context);
25+
ConfigMap res = new ConfigMapBuilder()
26+
.withMetadata(new ObjectMetaBuilder()
27+
.withName(primary.getMetadata().getName())
28+
.withNamespace(primary.getMetadata().getNamespace())
29+
.build())
30+
.build();
31+
res.setData(Map.of(ACTUAL_DATA_KEY, primary.getSpec().getData(),
32+
// setting the old data if available
33+
UNMODIFIABLE_INITIAL_DATA_KEY,
34+
actual.map(cm -> cm.getData().get(UNMODIFIABLE_INITIAL_DATA_KEY))
35+
.orElse(primary.getSpec().getData())));
36+
return res;
37+
}
38+
}

0 commit comments

Comments
 (0)