Skip to content

Commit 3b5eec2

Browse files
committed
integration test (wip)
1 parent 0260dfb commit 3b5eec2

File tree

9 files changed

+249
-0
lines changed

9 files changed

+249
-0
lines changed

operator-framework/src/main/java/io/javaoperatorsdk/operator/api/UpdateControl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ public static <T extends CustomResource> UpdateControl<T> updateStatusSubResourc
2727
return new UpdateControl<>(customResource, true, false);
2828
}
2929

30+
/**
31+
* As a results of this there will be two call to K8S API. First the custom resource will be
32+
* updates then the status sub-resource.
33+
*/
3034
public static <T extends CustomResource>
3135
UpdateControl<T> updateCustomResourceAndStatusSubResource(T customResource) {
3236
return new UpdateControl<>(customResource, true, true);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ public KubernetesClient getK8sClient() {
183183
return crOperations;
184184
}
185185

186+
public CustomResource getCustomResource(String name) {
187+
return getCrOperations().inNamespace(TEST_NAMESPACE).withName(name).get();
188+
}
189+
186190
public Operator getOperator() {
187191
return operator;
188192
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ public static TestCustomResource testCustomResource(String uid) {
3131
resource.getSpec().setValue("test-value");
3232
return resource;
3333
}
34+
35+
public static void waitXms(int x) {
36+
try {
37+
Thread.sleep(x);
38+
} catch (InterruptedException e) {
39+
throw new IllegalStateException(e);
40+
}
41+
}
3442
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
4+
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
5+
import io.fabric8.kubernetes.client.KubernetesClient;
6+
import io.javaoperatorsdk.operator.doubleupdate.subresource.DoubleUpdateTestCustomResource;
7+
import io.javaoperatorsdk.operator.doubleupdate.subresource.DoubleUpdateTestCustomResourceController;
8+
import io.javaoperatorsdk.operator.doubleupdate.subresource.DoubleUpdateTestCustomResourceSpec;
9+
import io.javaoperatorsdk.operator.doubleupdate.subresource.DoubleUpdateTestCustomResourceStatus;
10+
import io.javaoperatorsdk.operator.sample.subresource.SubResourceTestCustomResourceStatus;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.TestInstance;
14+
15+
import java.util.concurrent.TimeUnit;
16+
17+
import static io.javaoperatorsdk.operator.IntegrationTestSupport.TEST_NAMESPACE;
18+
import static io.javaoperatorsdk.operator.TestUtils.waitXms;
19+
import static io.javaoperatorsdk.operator.doubleupdate.subresource.DoubleUpdateTestCustomResourceController.TEST_ANNOTATION;
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.awaitility.Awaitility.await;
22+
23+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
24+
public class UpdatingResAndSubResIT {
25+
26+
private IntegrationTestSupport integrationTestSupport = new IntegrationTestSupport();
27+
28+
@BeforeEach
29+
public void initAndCleanup() {
30+
KubernetesClient k8sClient = new DefaultKubernetesClient();
31+
integrationTestSupport.initialize(
32+
k8sClient, new DoubleUpdateTestCustomResourceController(), "doubleupdate-test-crd.yaml");
33+
integrationTestSupport.cleanup();
34+
}
35+
36+
@Test
37+
public void updatesSubResourceStatus() {
38+
integrationTestSupport.teardownIfSuccess(
39+
() -> {
40+
DoubleUpdateTestCustomResource resource = createTestCustomResource("1");
41+
integrationTestSupport.getCrOperations().inNamespace(TEST_NAMESPACE).create(resource);
42+
43+
awaitStatusUpdated(resource.getMetadata().getName());
44+
// wait for sure, there are no more events
45+
waitXms(200);
46+
47+
DoubleUpdateTestCustomResource customResource =
48+
(DoubleUpdateTestCustomResource)
49+
integrationTestSupport.getCustomResource(resource.getMetadata().getName());
50+
assertThat(integrationTestSupport.numberOfControllerExecutions()).isEqualTo(1);
51+
assertThat(customResource.getStatus())
52+
.isEqualTo(DoubleUpdateTestCustomResourceStatus.State.SUCCESS);
53+
assertThat(customResource.getMetadata().getAnnotations().get(TEST_ANNOTATION))
54+
.isNotNull();
55+
});
56+
}
57+
58+
void awaitStatusUpdated(String name) {
59+
await("cr status updated")
60+
.atMost(5, TimeUnit.SECONDS)
61+
.untilAsserted(
62+
() -> {
63+
DoubleUpdateTestCustomResource cr =
64+
(DoubleUpdateTestCustomResource)
65+
integrationTestSupport
66+
.getCrOperations()
67+
.inNamespace(TEST_NAMESPACE)
68+
.withName(name)
69+
.get();
70+
assertThat(cr.getMetadata().getFinalizers()).hasSize(1);
71+
assertThat(cr).isNotNull();
72+
assertThat(cr.getStatus()).isNotNull();
73+
assertThat(cr.getStatus().getState())
74+
.isEqualTo(SubResourceTestCustomResourceStatus.State.SUCCESS);
75+
});
76+
}
77+
78+
public DoubleUpdateTestCustomResource createTestCustomResource(String id) {
79+
DoubleUpdateTestCustomResource resource = new DoubleUpdateTestCustomResource();
80+
resource.setMetadata(
81+
new ObjectMetaBuilder()
82+
.withName("doubleupdateresource-" + id)
83+
.withNamespace(TEST_NAMESPACE)
84+
.build());
85+
resource.setKind("DoubleUpdateSample");
86+
resource.setSpec(new DoubleUpdateTestCustomResourceSpec());
87+
resource.getSpec().setValue(id);
88+
return resource;
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package io.javaoperatorsdk.operator.doubleupdate.subresource;
2+
3+
import io.fabric8.kubernetes.client.CustomResource;
4+
5+
public class DoubleUpdateTestCustomResource extends CustomResource {
6+
7+
private DoubleUpdateTestCustomResourceSpec spec;
8+
9+
private DoubleUpdateTestCustomResourceStatus status;
10+
11+
public DoubleUpdateTestCustomResourceSpec getSpec() {
12+
return spec;
13+
}
14+
15+
public void setSpec(DoubleUpdateTestCustomResourceSpec spec) {
16+
this.spec = spec;
17+
}
18+
19+
public DoubleUpdateTestCustomResourceStatus getStatus() {
20+
return status;
21+
}
22+
23+
public void setStatus(DoubleUpdateTestCustomResourceStatus status) {
24+
this.status = status;
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return "TestCustomResource{"
30+
+ "spec="
31+
+ spec
32+
+ ", status="
33+
+ status
34+
+ ", extendedFrom="
35+
+ super.toString()
36+
+ '}';
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package io.javaoperatorsdk.operator.doubleupdate.subresource;
2+
3+
import io.javaoperatorsdk.operator.TestExecutionInfoProvider;
4+
import io.javaoperatorsdk.operator.api.*;
5+
6+
import java.util.HashMap;
7+
import java.util.concurrent.atomic.AtomicInteger;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
@Controller(crdName = DoubleUpdateTestCustomResourceController.CRD_NAME)
12+
public class DoubleUpdateTestCustomResourceController
13+
implements ResourceController<DoubleUpdateTestCustomResource>, TestExecutionInfoProvider {
14+
15+
public static final String CRD_NAME = "doubleupdatesamples.sample.javaoperatorsdk";
16+
private static final Logger log =
17+
LoggerFactory.getLogger(DoubleUpdateTestCustomResourceController.class);
18+
public static final String TEST_ANNOTATION = "TestAnnotation";
19+
public static final String TEST_ANNOTATION_VALUE = "TestAnnotationValue";
20+
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
21+
22+
@Override
23+
public DeleteControl deleteResource(
24+
DoubleUpdateTestCustomResource resource, Context<DoubleUpdateTestCustomResource> context) {
25+
return DeleteControl.DEFAULT_DELETE;
26+
}
27+
28+
@Override
29+
public UpdateControl<DoubleUpdateTestCustomResource> createOrUpdateResource(
30+
DoubleUpdateTestCustomResource resource, Context<DoubleUpdateTestCustomResource> context) {
31+
numberOfExecutions.addAndGet(1);
32+
33+
log.info("Value: " + resource.getSpec().getValue());
34+
35+
resource.getMetadata().setAnnotations(new HashMap<>());
36+
resource.getMetadata().getAnnotations().put(TEST_ANNOTATION, TEST_ANNOTATION_VALUE);
37+
ensureStatusExists(resource);
38+
resource.getStatus().setState(DoubleUpdateTestCustomResourceStatus.State.SUCCESS);
39+
40+
return UpdateControl.updateCustomResourceAndStatusSubResource(resource);
41+
}
42+
43+
private void ensureStatusExists(DoubleUpdateTestCustomResource resource) {
44+
DoubleUpdateTestCustomResourceStatus status = resource.getStatus();
45+
if (status == null) {
46+
status = new DoubleUpdateTestCustomResourceStatus();
47+
resource.setStatus(status);
48+
}
49+
}
50+
51+
public int getNumberOfExecutions() {
52+
return numberOfExecutions.get();
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.doubleupdate.subresource;
2+
3+
public class DoubleUpdateTestCustomResourceSpec {
4+
5+
private String value;
6+
7+
public String getValue() {
8+
return value;
9+
}
10+
11+
public DoubleUpdateTestCustomResourceSpec setValue(String value) {
12+
this.value = value;
13+
return this;
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.javaoperatorsdk.operator.doubleupdate.subresource;
2+
3+
public class DoubleUpdateTestCustomResourceStatus {
4+
5+
private State state;
6+
7+
public State getState() {
8+
return state;
9+
}
10+
11+
public DoubleUpdateTestCustomResourceStatus setState(State state) {
12+
this.state = state;
13+
return this;
14+
}
15+
16+
public enum State {
17+
SUCCESS,
18+
ERROR
19+
}
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: doubleupdatesamples.sample.javaoperatorsdk
5+
spec:
6+
group: sample.javaoperatorsdk
7+
version: v1
8+
subresources:
9+
status: {}
10+
scope: Namespaced
11+
names:
12+
plural: doubleupdatesamples
13+
singular: doubleupdatesample
14+
kind: DoubleUpdateSample
15+
shortNames:
16+
- ss

0 commit comments

Comments
 (0)