Skip to content

Commit 3f25e2f

Browse files
committed
integration test for generation aware scheduling
1 parent 344a922 commit 3f25e2f

File tree

4 files changed

+93
-45
lines changed

4 files changed

+93
-45
lines changed

operator-framework/src/test/java/com/github/containersolutions/operator/ConcurrencyIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void cleanup() {
3838
}
3939

4040
@Test
41-
public void manyResourcesGetCreatedUpdatedAndDeleted() throws Exception {
41+
public void manyResourcesGetCreatedUpdatedAndDeleted() {
4242
integrationTest.teardownIfSuccess(() -> {
4343
log.info("Adding new resources.");
4444
for (int i = 0; i < NUMBER_OF_RESOURCES_CREATED; i++) {

operator-framework/src/test/java/com/github/containersolutions/operator/ControllerExecutionIT.java

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import com.github.containersolutions.operator.sample.TestCustomResourceSpec;
55
import io.fabric8.kubernetes.api.model.ConfigMap;
66
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
7-
import org.junit.jupiter.api.BeforeAll;
8-
import org.junit.jupiter.api.BeforeEach;
97
import org.junit.jupiter.api.Test;
108
import org.junit.jupiter.api.TestInstance;
119
import org.slf4j.Logger;
@@ -15,7 +13,6 @@
1513

1614
import static com.github.containersolutions.operator.IntegrationTestSupport.TEST_NAMESPACE;
1715
import static org.assertj.core.api.Assertions.assertThat;
18-
import static org.assertj.core.api.Assertions.fail;
1916
import static org.awaitility.Awaitility.await;
2017

2118
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -24,51 +21,69 @@ public class ControllerExecutionIT {
2421
private final static Logger log = LoggerFactory.getLogger(ControllerExecutionIT.class);
2522
private IntegrationTestSupport integrationTestSupport = new IntegrationTestSupport();
2623

27-
@BeforeAll
28-
public void setup() {
29-
integrationTestSupport.initialize();
30-
}
31-
32-
@BeforeEach
33-
public void cleanup() {
24+
public void initAndCleanup(boolean controllerStatusUpdate) {
25+
integrationTestSupport.initialize(controllerStatusUpdate);
3426
integrationTestSupport.cleanup();
3527
}
3628

3729
@Test
38-
public void configMapGetsCreatedForTestCustomResource() throws Exception {
30+
public void configMapGetsCreatedForTestCustomResource() {
31+
initAndCleanup(true);
3932
integrationTestSupport.teardownIfSuccess(() -> {
40-
TestCustomResource resource = new TestCustomResource();
41-
resource.setMetadata(new ObjectMetaBuilder()
42-
.withName("test-custom-resource")
43-
.withNamespace(TEST_NAMESPACE)
44-
.build());
45-
resource.setKind("CustomService");
46-
resource.setSpec(new TestCustomResourceSpec());
47-
resource.getSpec().setConfigMapName("test-config-map");
48-
resource.getSpec().setKey("test-key");
49-
resource.getSpec().setValue("test-value");
33+
TestCustomResource resource = testCustomResource();
34+
5035
integrationTestSupport.getCrOperations().inNamespace(TEST_NAMESPACE).create(resource);
5136

52-
await("configmap created").atMost(5, TimeUnit.SECONDS)
53-
.untilAsserted(() -> {
54-
ConfigMap configMap = integrationTestSupport.getK8sClient().configMaps().inNamespace(TEST_NAMESPACE)
55-
.withName("test-config-map").get();
56-
assertThat(configMap).isNotNull();
57-
assertThat(configMap.getData().get("test-key")).isEqualTo("test-value");
58-
});
59-
await("cr status updated").atMost(5, TimeUnit.SECONDS)
60-
.untilAsserted(() -> {
61-
TestCustomResource cr = integrationTestSupport.getCrOperations().inNamespace(TEST_NAMESPACE).withName("test-custom-resource").get();
62-
assertThat(cr).isNotNull();
63-
assertThat(cr.getStatus()).isNotNull();
64-
assertThat(cr.getStatus().getConfigMapStatus()).isEqualTo("ConfigMap Ready");
65-
});
37+
awaitResourcesCreatedOrUpdated();
38+
awaitStatusUpdated();
6639
});
6740
}
6841

6942
@Test
7043
public void eventIsSkippedChangedOnMetadataOnlyUpdate() {
71-
fail("TODO");
44+
initAndCleanup(false);
45+
integrationTestSupport.teardownIfSuccess(() -> {
46+
TestCustomResource resource = testCustomResource();
47+
48+
integrationTestSupport.getCrOperations().inNamespace(TEST_NAMESPACE).create(resource);
49+
50+
awaitResourcesCreatedOrUpdated();
51+
assertThat(integrationTestSupport.numberOfControllerExecutions()).isEqualTo(1);
52+
});
53+
}
54+
55+
void awaitResourcesCreatedOrUpdated() {
56+
await("configmap created").atMost(5, TimeUnit.SECONDS)
57+
.untilAsserted(() -> {
58+
ConfigMap configMap = integrationTestSupport.getK8sClient().configMaps().inNamespace(TEST_NAMESPACE)
59+
.withName("test-config-map").get();
60+
assertThat(configMap).isNotNull();
61+
assertThat(configMap.getData().get("test-key")).isEqualTo("test-value");
62+
});
63+
}
64+
65+
void awaitStatusUpdated() {
66+
await("cr status updated").atMost(5, TimeUnit.SECONDS)
67+
.untilAsserted(() -> {
68+
TestCustomResource cr = integrationTestSupport.getCrOperations().inNamespace(TEST_NAMESPACE).withName("test-custom-resource").get();
69+
assertThat(cr).isNotNull();
70+
assertThat(cr.getStatus()).isNotNull();
71+
assertThat(cr.getStatus().getConfigMapStatus()).isEqualTo("ConfigMap Ready");
72+
});
73+
}
74+
75+
private TestCustomResource testCustomResource() {
76+
TestCustomResource resource = new TestCustomResource();
77+
resource.setMetadata(new ObjectMetaBuilder()
78+
.withName("test-custom-resource")
79+
.withNamespace(TEST_NAMESPACE)
80+
.build());
81+
resource.setKind("CustomService");
82+
resource.setSpec(new TestCustomResourceSpec());
83+
resource.getSpec().setConfigMapName("test-config-map");
84+
resource.getSpec().setKey("test-key");
85+
resource.getSpec().setValue("test-value");
86+
return resource;
7287
}
7388

7489
}

operator-framework/src/test/java/com/github/containersolutions/operator/IntegrationTestSupport.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.containersolutions.operator;
22

3-
import com.github.containersolutions.operator.api.ResourceController;
43
import com.github.containersolutions.operator.sample.TestCustomResource;
54
import com.github.containersolutions.operator.sample.TestCustomResourceController;
65
import com.github.containersolutions.operator.sample.TestCustomResourceSpec;
@@ -35,17 +34,21 @@ public class IntegrationTestSupport {
3534
private MixedOperation<TestCustomResource, CustomResourceList, CustomResourceDoneable,
3635
Resource<TestCustomResource, CustomResourceDoneable>> crOperations;
3736
private Operator operator;
38-
37+
private TestCustomResourceController controller;
3938

4039
public void initialize() {
40+
initialize(true);
41+
}
42+
43+
public void initialize(boolean updateStatus) {
4144
k8sClient = new DefaultKubernetesClient();
4245

4346
log.info("Initializing integration test in namespace {}", TEST_NAMESPACE);
4447

4548
CustomResourceDefinition crd = loadYaml(CustomResourceDefinition.class, "test-crd.yaml");
4649
k8sClient.customResourceDefinitions().createOrReplace(crd);
4750

48-
ResourceController<TestCustomResource> controller = new TestCustomResourceController(k8sClient);
51+
controller = new TestCustomResourceController(k8sClient, updateStatus);
4952
Class doneableClass = getCustomResourceDoneableClass(controller);
5053
crOperations = k8sClient.customResources(crd, TestCustomResource.class, CustomResourceList.class, doneableClass);
5154
crOperations.inNamespace(TEST_NAMESPACE).delete(crOperations.list().getItems());
@@ -94,7 +97,7 @@ public void cleanup() {
9497
* @param test The code of the actual test.
9598
* @throws Exception if the test threw an exception.
9699
*/
97-
public void teardownIfSuccess(TestRun test) throws Exception {
100+
public void teardownIfSuccess(TestRun test) {
98101
try {
99102
test.run();
100103

@@ -105,11 +108,17 @@ public void teardownIfSuccess(TestRun test) throws Exception {
105108
}
106109
await("namespace deleted").atMost(30, TimeUnit.SECONDS)
107110
.until(() -> k8sClient.namespaces().withName(TEST_NAMESPACE).get() == null);
111+
} catch (Exception e) {
112+
throw new IllegalStateException(e);
108113
} finally {
109114
k8sClient.close();
110115
}
111116
}
112117

118+
public int numberOfControllerExecutions() {
119+
return controller.getNumberOfExecutions();
120+
}
121+
113122
private <T> T loadYaml(Class<T> clazz, String yaml) {
114123
try (InputStream is = getClass().getResourceAsStream(yaml)) {
115124
return Serialization.unmarshal(is, clazz);

operator-framework/src/test/java/com/github/containersolutions/operator/sample/TestCustomResourceController.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
import org.slf4j.Logger;
1010
import org.slf4j.LoggerFactory;
1111

12+
import java.time.LocalDateTime;
1213
import java.util.HashMap;
1314
import java.util.Map;
1415
import java.util.Optional;
16+
import java.util.concurrent.atomic.AtomicInteger;
1517

1618
@Controller(
1719
crdName = TestCustomResourceController.CRD_NAME,
@@ -23,9 +25,16 @@ public class TestCustomResourceController implements ResourceController<TestCust
2325
public static final String CRD_NAME = "customservices.sample.javaoperatorsdk";
2426

2527
private final KubernetesClient kubernetesClient;
28+
private final boolean updateStatus;
29+
private AtomicInteger numberOfExecutions = new AtomicInteger(0);
2630

2731
public TestCustomResourceController(KubernetesClient kubernetesClient) {
32+
this(kubernetesClient, true);
33+
}
34+
35+
public TestCustomResourceController(KubernetesClient kubernetesClient, boolean updateStatus) {
2836
this.kubernetesClient = kubernetesClient;
37+
this.updateStatus = updateStatus;
2938
}
3039

3140
@Override
@@ -38,6 +47,7 @@ public boolean deleteResource(TestCustomResource resource) {
3847

3948
@Override
4049
public Optional<TestCustomResource> createOrUpdateResource(TestCustomResource resource) {
50+
numberOfExecutions.addAndGet(1);
4151
ConfigMap existingConfigMap = kubernetesClient
4252
.configMaps().inNamespace(resource.getMetadata().getNamespace())
4353
.withName(resource.getSpec().getConfigMapName()).get();
@@ -60,17 +70,31 @@ public Optional<TestCustomResource> createOrUpdateResource(TestCustomResource re
6070
kubernetesClient.configMaps().inNamespace(resource.getMetadata().getNamespace())
6171
.createOrReplace(newConfigMap);
6272
}
63-
64-
if (resource.getStatus() == null) {
65-
resource.setStatus(new TestCustomResourceStatus());
73+
if (updateStatus) {
74+
if (resource.getStatus() == null) {
75+
resource.setStatus(new TestCustomResourceStatus());
76+
}
77+
resource.getStatus().setConfigMapStatus("ConfigMap Ready");
6678
}
67-
resource.getStatus().setConfigMapStatus("ConfigMap Ready");
79+
addOrUpdateAnnotation(resource);
6880
return Optional.of(resource);
6981
}
7082

83+
// for testing purposes we change metadata
84+
private void addOrUpdateAnnotation(TestCustomResource resource) {
85+
if (resource.getMetadata().getAnnotations() == null) {
86+
resource.getMetadata().setAnnotations(new HashMap<>());
87+
}
88+
resource.getMetadata().getAnnotations().put("testAnnotation", LocalDateTime.now().toString());
89+
}
90+
7191
private Map<String, String> configMapData(TestCustomResource resource) {
7292
Map<String, String> data = new HashMap<>();
7393
data.put(resource.getSpec().getKey(), resource.getSpec().getValue());
7494
return data;
7595
}
96+
97+
public int getNumberOfExecutions() {
98+
return numberOfExecutions.get();
99+
}
76100
}

0 commit comments

Comments
 (0)