Skip to content

Commit 19c473f

Browse files
authored
fix: webpage e2e test (#982)
1 parent 3608c15 commit 19c473f

File tree

12 files changed

+251
-52
lines changed

12 files changed

+251
-52
lines changed

.github/workflows/e2e-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
sample_dir:
1717
- "sample-operators/mysql-schema"
1818
- "sample-operators/tomcat-operator"
19+
- "sample-operators/webpage"
1920
runs-on: ubuntu-latest
2021
steps:
2122
- name: Checkout

operator-framework-junit5/src/main/java/io/javaoperatorsdk/operator/junit/E2EOperatorExtension.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Locale;
1111
import java.util.Objects;
1212
import java.util.concurrent.TimeUnit;
13+
import java.util.function.Consumer;
1314

1415
import org.junit.jupiter.api.extension.ExtensionContext;
1516
import org.slf4j.Logger;
@@ -70,7 +71,7 @@ protected void before(ExtensionContext context) {
7071
}
7172
}
7273

73-
LOGGER.debug("Deploying the operator into Kubernetes");
74+
LOGGER.debug("Deploying the operator into Kubernetes. Target namespace: {}", namespace);
7475
operatorDeployment.forEach(hm -> {
7576
hm.getMetadata().setNamespace(namespace);
7677
if (hm.getKind().toLowerCase(Locale.ROOT).equals("clusterrolebinding")) {
@@ -88,6 +89,7 @@ protected void before(ExtensionContext context) {
8889
kubernetesClient
8990
.resourceList(operatorDeployment)
9091
.waitUntilReady(operatorDeploymentTimeout.toMillis(), TimeUnit.MILLISECONDS);
92+
LOGGER.debug("Operator resources deployed.");
9193
}
9294

9395
@Override
@@ -110,6 +112,13 @@ public Builder withDeploymentTimeout(Duration value) {
110112
return this;
111113
}
112114

115+
public Builder withOperatorDeployment(List<HasMetadata> hm,
116+
Consumer<List<HasMetadata>> modifications) {
117+
modifications.accept(hm);
118+
operatorDeployment.addAll(hm);
119+
return this;
120+
}
121+
113122
public Builder withOperatorDeployment(List<HasMetadata> hm) {
114123
operatorDeployment.addAll(hm);
115124
return this;

sample-operators/webpage/k8s/operator.yaml

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,27 @@
11
apiVersion: v1
2-
kind: Namespace
3-
metadata:
4-
name: webserver-operator
5-
6-
---
7-
apiVersion: v1
82
kind: ServiceAccount
93
metadata:
10-
name: webserver-operator
11-
namespace: webserver-operator
4+
name: webpage-operator
125

136
---
147
apiVersion: apps/v1
158
kind: Deployment
169
metadata:
17-
name: webserver-operator
18-
namespace: webserver-operator
10+
name: webpage-operator
1911
spec:
2012
selector:
2113
matchLabels:
22-
app: webserver-operator
14+
app: webpage-operator
2315
replicas: 1
2416
template:
2517
metadata:
2618
labels:
27-
app: webserver-operator
19+
app: webpage-operator
2820
spec:
29-
serviceAccountName: webserver-operator
21+
serviceAccountName: webpage-operator
3022
containers:
3123
- name: operator
32-
image: webserver-operator
24+
image: webpage-operator
3325
imagePullPolicy: Never
3426
ports:
3527
- containerPort: 80
@@ -53,18 +45,17 @@ metadata:
5345
name: operator-admin
5446
subjects:
5547
- kind: ServiceAccount
56-
name: webserver-operator
57-
namespace: webserver-operator
48+
name: webpage-operator
5849
roleRef:
5950
kind: ClusterRole
60-
name: webserver-operator
51+
name: webpage-operator
6152
apiGroup: ""
6253

6354
---
6455
apiVersion: rbac.authorization.k8s.io/v1
6556
kind: ClusterRole
6657
metadata:
67-
name: webserver-operator
58+
name: webpage-operator
6859
rules:
6960
- apiGroups:
7061
- ""

sample-operators/webpage/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@
4545
<artifactId>awaitility</artifactId>
4646
<scope>compile</scope>
4747
</dependency>
48+
<dependency>
49+
<groupId>io.javaoperatorsdk</groupId>
50+
<artifactId>operator-framework-junit-5</artifactId>
51+
<version>${project.version}</version>
52+
<scope>test</scope>
53+
</dependency>
4854
</dependencies>
4955
<build>
5056
<plugins>
@@ -57,7 +63,7 @@
5763
<image>gcr.io/distroless/java:11</image>
5864
</from>
5965
<to>
60-
<image>webserver-operator</image>
66+
<image>webpage-operator</image>
6167
</to>
6268
</configuration>
6369
</plugin>

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package io.javaoperatorsdk.operator.sample;
22

33
import java.io.IOException;
4-
import java.util.Arrays;
54

65
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
@@ -18,16 +17,18 @@
1817
import io.javaoperatorsdk.operator.config.runtime.DefaultConfigurationService;
1918

2019
public class WebPageOperator {
21-
20+
public static final String WEBPAGE_RECONCILER_ENV = "WEBPAGE_RECONCILER";
21+
public static final String WEBPAGE_RECONCILER_ENV_VALUE = "classic";
2222
private static final Logger log = LoggerFactory.getLogger(WebPageOperator.class);
2323

24+
2425
public static void main(String[] args) throws IOException {
2526
log.info("WebServer Operator starting!");
2627

2728
Config config = new ConfigBuilder().withNamespace(null).build();
2829
KubernetesClient client = new DefaultKubernetesClient(config);
2930
Operator operator = new Operator(client, DefaultConfigurationService.instance());
30-
if (Arrays.stream(args).anyMatch(arg -> arg.equals("--classic"))) {
31+
if (WEBPAGE_RECONCILER_ENV_VALUE.equals(System.getenv(WEBPAGE_RECONCILER_ENV))) {
3132
operator.register(new WebPageReconciler(client));
3233
} else {
3334
operator.register(new WebPageReconcilerDependentResources(client));

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconciler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public UpdateControl<WebPage> reconcile(WebPage webPage, Context context) {
111111
private WebPageStatus createStatus(String configMapName) {
112112
WebPageStatus status = new WebPageStatus();
113113
status.setHtmlConfigMap(configMapName);
114-
status.setAreWeGood("Yes!");
114+
status.setAreWeGood(true);
115115
status.setErrorMessage(null);
116116
return status;
117117
}
@@ -191,7 +191,7 @@ private ConfigMap makeDesiredHtmlConfigMap(String ns, String configMapName, WebP
191191
return configMap;
192192
}
193193

194-
private Map<String, String> lowLevelLabel() {
194+
public static Map<String, String> lowLevelLabel() {
195195
Map<String, String> labels = new HashMap<>();
196196
labels.put(LOW_LEVEL_LABEL_KEY, "true");
197197
return labels;

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageReconcilerDependentResources.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public UpdateControl<WebPage> reconcile(WebPage webPage, Context context) {
6969
private WebPageStatus createStatus(String configMapName) {
7070
WebPageStatus status = new WebPageStatus();
7171
status.setHtmlConfigMap(configMapName);
72-
status.setAreWeGood("Yes!");
72+
status.setAreWeGood(true);
7373
status.setErrorMessage(null);
7474
return status;
7575
}
@@ -148,16 +148,16 @@ protected Class<Service> resourceType() {
148148
.setLabelSelector(DEPENDENT_RESOURCE_LABEL_SELECTOR));
149149
}
150150

151-
private static String configMapName(WebPage nginx) {
151+
public static String configMapName(WebPage nginx) {
152152
return nginx.getMetadata().getName() + "-html";
153153
}
154154

155-
private static String deploymentName(WebPage nginx) {
155+
public static String deploymentName(WebPage nginx) {
156156
return nginx.getMetadata().getName();
157157
}
158158

159-
private static String serviceName(WebPage nginx) {
160-
return nginx.getMetadata().getName();
159+
public static String serviceName(WebPage webPage) {
160+
return webPage.getMetadata().getName();
161161
}
162162

163163
private class ConfigMapDependentResource

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageStatus.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public class WebPageStatus extends ObservedGenerationAwareStatus {
66

77
private String htmlConfigMap;
88

9-
private String areWeGood;
9+
private Boolean areWeGood;
1010

1111
private String errorMessage;
1212

@@ -18,11 +18,11 @@ public void setHtmlConfigMap(String htmlConfigMap) {
1818
this.htmlConfigMap = htmlConfigMap;
1919
}
2020

21-
public String getAreWeGood() {
21+
public Boolean getAreWeGood() {
2222
return areWeGood;
2323
}
2424

25-
public void setAreWeGood(String areWeGood) {
25+
public void setAreWeGood(Boolean areWeGood) {
2626
this.areWeGood = areWeGood;
2727
}
2828

sample-operators/webpage/src/main/resources/io/javaoperatorsdk/operator/sample/ingress.yaml

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import java.io.IOException;
4+
import java.net.URI;
5+
import java.net.URISyntaxException;
6+
import java.net.http.HttpClient;
7+
import java.net.http.HttpRequest;
8+
import java.net.http.HttpResponse;
9+
import java.time.Duration;
10+
import java.util.Objects;
11+
12+
import org.junit.jupiter.api.Test;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
16+
import io.fabric8.kubernetes.api.model.ObjectMeta;
17+
import io.fabric8.kubernetes.api.model.apps.Deployment;
18+
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
19+
import io.fabric8.kubernetes.client.KubernetesClient;
20+
import io.fabric8.kubernetes.client.LocalPortForward;
21+
import io.javaoperatorsdk.operator.junit.AbstractOperatorExtension;
22+
23+
import static io.javaoperatorsdk.operator.sample.WebPageReconcilerDependentResources.serviceName;
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
import static org.awaitility.Awaitility.await;
26+
27+
public abstract class WebPageOperatorAbstractTest {
28+
29+
static final Logger log = LoggerFactory.getLogger(WebPageOperatorDependentResourcesE2E.class);
30+
31+
static final KubernetesClient client = new DefaultKubernetesClient();
32+
public static final String TEST_PAGE = "test-page";
33+
34+
boolean isLocal() {
35+
String deployment = System.getProperty("test.deployment");
36+
boolean remote = (deployment != null && deployment.equals("remote"));
37+
log.info("Running the operator " + (remote ? "remote" : "locally"));
38+
return !remote;
39+
}
40+
41+
@Test
42+
void testAddingWebPage() {
43+
44+
var webPage = createWebPage();
45+
operator().create(WebPage.class, webPage);
46+
47+
await()
48+
.atMost(Duration.ofSeconds(20))
49+
.pollInterval(Duration.ofSeconds(1))
50+
.until(
51+
() -> {
52+
var actual = operator().get(WebPage.class, TEST_PAGE);
53+
var deployment = operator().get(Deployment.class,
54+
WebPageReconcilerDependentResources.deploymentName(webPage));
55+
56+
return Boolean.TRUE.equals(actual.getStatus().getAreWeGood())
57+
&& Objects.equals(deployment.getSpec().getReplicas(),
58+
deployment.getStatus().getReadyReplicas());
59+
});
60+
61+
String response = httpGetForWebPage(webPage);
62+
assertThat(response).contains("<title>Hello Operator World</title>");
63+
}
64+
65+
String httpGetForWebPage(WebPage webPage) {
66+
LocalPortForward portForward = null;
67+
try {
68+
portForward =
69+
client.services().inNamespace(webPage.getMetadata().getNamespace())
70+
.withName(serviceName(webPage)).portForward(80);
71+
HttpClient httpClient =
72+
HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();
73+
HttpRequest request =
74+
HttpRequest.newBuilder().GET()
75+
.uri(new URI("http://localhost:" + portForward.getLocalPort())).build();
76+
return httpClient.send(request, HttpResponse.BodyHandlers.ofString()).body();
77+
} catch (URISyntaxException | IOException | InterruptedException e) {
78+
throw new IllegalStateException(e);
79+
} finally {
80+
if (portForward != null) {
81+
try {
82+
portForward.close();
83+
} catch (IOException e) {
84+
log.error("Port forward close error.", e);
85+
}
86+
}
87+
}
88+
}
89+
90+
WebPage createWebPage() {
91+
WebPage webPage = new WebPage();
92+
webPage.setMetadata(new ObjectMeta());
93+
webPage.getMetadata().setName(TEST_PAGE);
94+
webPage.getMetadata().setNamespace(operator().getNamespace());
95+
webPage.setSpec(new WebPageSpec());
96+
webPage
97+
.getSpec()
98+
.setHtml(
99+
"<html>\n"
100+
+ " <head>\n"
101+
+ " <title>Hello Operator World</title>\n"
102+
+ " </head>\n"
103+
+ " <body>\n"
104+
+ " Hello World! \n"
105+
+ " </body>\n"
106+
+ " </html>");
107+
108+
return webPage;
109+
}
110+
111+
abstract AbstractOperatorExtension operator();
112+
113+
}

0 commit comments

Comments
 (0)