Skip to content

Commit 340c772

Browse files
authored
Merge pull request #267 from java-operator-sdk/spring-boot-test-module
Spring boot test module
2 parents a4d5507 + 68e5469 commit 340c772

File tree

9 files changed

+271
-71
lines changed

9 files changed

+271
-71
lines changed

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,28 @@ public class Application {
204204
}
205205
}
206206
```
207+
208+
#### Spring Boot test support
209+
210+
Adding the following dependency would let you mock the operator for the
211+
tests where loading the spring container is necessary,
212+
but it doesn't need real access to a Kubernetes cluster.
213+
214+
```xml
215+
<dependency>
216+
<groupId>io.javaoperatorsdk</groupId>
217+
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
218+
<version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for latest version}</version>
219+
</dependency>
220+
```
221+
222+
Mock the operator:
223+
```java
224+
@SpringBootTest
225+
@EnableMockOperator
226+
public class SpringBootStarterSampleApplicationTest {
227+
228+
@Test
229+
void contextLoads() {}
230+
}
231+
```
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>io.javaoperatorsdk</groupId>
8+
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
9+
10+
<parent>
11+
<groupId>io.javaoperatorsdk</groupId>
12+
<artifactId>java-operator-sdk</artifactId>
13+
<version>1.6.2-SNAPSHOT</version>
14+
</parent>
15+
16+
<properties>
17+
<java.version>11</java.version>
18+
<maven.compiler.source>11</maven.compiler.source>
19+
<maven.compiler.target>11</maven.compiler.target>
20+
</properties>
21+
22+
<dependencyManagement>
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.springframework.boot</groupId>
26+
<artifactId>spring-boot-dependencies</artifactId>
27+
<version>2.3.4.RELEASE</version>
28+
<type>pom</type>
29+
<scope>import</scope>
30+
</dependency>
31+
</dependencies>
32+
</dependencyManagement>
33+
34+
<dependencies>
35+
<dependency>
36+
<groupId>io.fabric8</groupId>
37+
<artifactId>kubernetes-server-mock</artifactId>
38+
<version>4.12.0</version>
39+
</dependency>
40+
41+
<dependency>
42+
<groupId>org.springframework.boot</groupId>
43+
<artifactId>spring-boot-starter</artifactId>
44+
</dependency>
45+
<dependency>
46+
<groupId>io.javaoperatorsdk</groupId>
47+
<artifactId>operator-framework</artifactId>
48+
<version>${project.version}</version>
49+
</dependency>
50+
<dependency>
51+
<groupId>io.fabric8</groupId>
52+
<artifactId>kubernetes-server-mock</artifactId>
53+
<version>4.12.0</version>
54+
</dependency>
55+
</dependencies>
56+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.javaoperatorsdk.operator.springboot.starter.test;
2+
3+
import java.lang.annotation.Retention;
4+
import java.lang.annotation.RetentionPolicy;
5+
import org.springframework.context.annotation.Import;
6+
7+
@Retention(RetentionPolicy.RUNTIME)
8+
@Import(TestConfiguration.class)
9+
public @interface EnableMockOperator {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.javaoperatorsdk.operator.springboot.starter.test;
2+
3+
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
4+
import io.fabric8.kubernetes.client.KubernetesClient;
5+
import io.fabric8.kubernetes.client.server.mock.KubernetesCrudDispatcher;
6+
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
7+
import io.fabric8.kubernetes.client.utils.Serialization;
8+
import io.fabric8.mockwebserver.Context;
9+
import java.io.FileInputStream;
10+
import java.io.FileNotFoundException;
11+
import java.util.Collections;
12+
import java.util.HashMap;
13+
import java.util.List;
14+
import okhttp3.mockwebserver.MockWebServer;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
import org.springframework.beans.factory.annotation.Value;
18+
import org.springframework.context.annotation.Bean;
19+
import org.springframework.context.annotation.Configuration;
20+
import org.springframework.util.ResourceUtils;
21+
22+
@Configuration
23+
public class TestConfiguration {
24+
25+
private static final Logger log = LoggerFactory.getLogger(TestConfiguration.class);
26+
27+
@Value("${io.javaoperatorsdk.test.crdPaths}")
28+
private List<String> crdPaths;
29+
30+
@Bean
31+
public KubernetesMockServer k8sMockServer() {
32+
final var server =
33+
new KubernetesMockServer(
34+
new Context(),
35+
new MockWebServer(),
36+
new HashMap<>(),
37+
new KubernetesCrudDispatcher(Collections.emptyList()),
38+
true);
39+
server.init();
40+
return server;
41+
}
42+
43+
@Bean
44+
public KubernetesClient kubernetesClient(KubernetesMockServer server) {
45+
final var client = server.createClient();
46+
47+
crdPaths.forEach(
48+
crdPath -> {
49+
CustomResourceDefinition crd = null;
50+
try {
51+
crd = Serialization.unmarshal(new FileInputStream(ResourceUtils.getFile(crdPath)));
52+
} catch (FileNotFoundException e) {
53+
log.warn("CRD with path {} not found!", crdPath);
54+
e.printStackTrace();
55+
return;
56+
}
57+
58+
client.apiextensions().v1().customResourceDefinitions().create(crd);
59+
});
60+
61+
return client;
62+
}
63+
}

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<module>operator-framework</module>
4646
<module>operator-framework-quarkus-extension</module>
4747
<module>operator-framework-spring-boot-starter</module>
48+
<module>operator-framework-spring-boot-starter-test</module>
4849
<module>samples</module>
4950
</modules>
5051

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,88 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4-
<modelVersion>4.0.0</modelVersion>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
56

6-
<parent>
7-
<groupId>io.javaoperatorsdk</groupId>
8-
<artifactId>java-operator-sdk-samples</artifactId>
9-
<version>1.6.2-SNAPSHOT</version>
10-
</parent>
117

12-
<artifactId>operator-framework-samples-spring-boot-auto-configuration</artifactId>
13-
<name>Operator SDK - Samples - Spring Boot - Auto Config</name>
14-
<description>Sample usage with Spring Boot</description>
15-
<packaging>jar</packaging>
8+
<parent>
9+
<groupId>io.javaoperatorsdk</groupId>
10+
<artifactId>java-operator-sdk-samples</artifactId>
11+
<version>1.6.2-SNAPSHOT</version>
12+
</parent>
1613

17-
<properties>
18-
<java.version>11</java.version>
19-
<maven.compiler.source>11</maven.compiler.source>
20-
<maven.compiler.target>11</maven.compiler.target>
21-
</properties>
14+
<artifactId>operator-framework-samples-spring-boot-auto-configuration</artifactId>
15+
<name>Operator SDK - Samples - Spring Boot - Auto Config</name>
16+
<description>Sample usage with Spring Boot</description>
17+
<packaging>jar</packaging>
2218

19+
<properties>
20+
<java.version>11</java.version>
21+
<maven.compiler.source>11</maven.compiler.source>
22+
<maven.compiler.target>11</maven.compiler.target>
23+
</properties>
24+
25+
<dependencies>
26+
<dependency>
27+
<groupId>io.javaoperatorsdk</groupId>
28+
<artifactId>operator-framework-samples-common</artifactId>
29+
<version>${project.version}</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>io.javaoperatorsdk</groupId>
33+
<artifactId>operator-framework-spring-boot-starter</artifactId>
34+
<version>${project.version}</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter-test</artifactId>
39+
<scope>test</scope>
40+
<exclusions>
41+
<exclusion>
42+
<groupId>org.junit.vintage</groupId>
43+
<artifactId>junit-vintage-engine</artifactId>
44+
</exclusion>
45+
<exclusion>
46+
<groupId>org.springframework.boot</groupId>
47+
<artifactId>spring-boot-starter-logging</artifactId>
48+
</exclusion>
49+
<exclusion>
50+
<groupId>org.skyscreamer</groupId>
51+
<artifactId>jsonassert</artifactId>
52+
</exclusion>
53+
</exclusions>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.springframework.boot</groupId>
57+
<artifactId>spring-boot-starter-log4j2</artifactId>
58+
</dependency>
59+
60+
<dependency>
61+
<groupId>io.javaoperatorsdk</groupId>
62+
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
63+
<version>${project.version}</version>
64+
</dependency>
65+
</dependencies>
66+
67+
<dependencyManagement>
2368
<dependencies>
24-
<dependency>
25-
<groupId>io.javaoperatorsdk</groupId>
26-
<artifactId>operator-framework-samples-common</artifactId>
27-
<version>${project.version}</version>
28-
</dependency>
29-
<dependency>
30-
<groupId>io.javaoperatorsdk</groupId>
31-
<artifactId>operator-framework-spring-boot-starter</artifactId>
32-
<version>${project.version}</version>
33-
</dependency>
34-
<dependency>
35-
<groupId>org.springframework.boot</groupId>
36-
<artifactId>spring-boot-starter-test</artifactId>
37-
<scope>test</scope>
38-
<exclusions>
39-
<exclusion>
40-
<groupId>org.junit.vintage</groupId>
41-
<artifactId>junit-vintage-engine</artifactId>
42-
</exclusion>
43-
<exclusion>
44-
<groupId>org.springframework.boot</groupId>
45-
<artifactId>spring-boot-starter-logging</artifactId>
46-
</exclusion>
47-
<exclusion>
48-
<groupId>org.skyscreamer</groupId>
49-
<artifactId>jsonassert</artifactId>
50-
</exclusion>
51-
</exclusions>
52-
</dependency>
53-
<dependency>
54-
<groupId>org.springframework.boot</groupId>
55-
<artifactId>spring-boot-starter-log4j2</artifactId>
56-
</dependency>
69+
<dependency>
70+
<groupId>org.springframework.boot</groupId>
71+
<artifactId>spring-boot-dependencies</artifactId>
72+
<version>2.3.4.RELEASE</version>
73+
<type>pom</type>
74+
<scope>import</scope>
75+
</dependency>
5776
</dependencies>
77+
</dependencyManagement>
5878

59-
<dependencyManagement>
60-
<dependencies>
61-
<dependency>
62-
<groupId>org.springframework.boot</groupId>
63-
<artifactId>spring-boot-dependencies</artifactId>
64-
<version>2.3.4.RELEASE</version>
65-
<type>pom</type>
66-
<scope>import</scope>
67-
</dependency>
68-
</dependencies>
69-
</dependencyManagement>
70-
71-
<build>
72-
<plugins>
73-
<plugin>
74-
<groupId>org.springframework.boot</groupId>
75-
<artifactId>spring-boot-maven-plugin</artifactId>
76-
<version>2.3.4.RELEASE</version>
77-
</plugin>
78-
</plugins>
79-
</build>
79+
<build>
80+
<plugins>
81+
<plugin>
82+
<groupId>org.springframework.boot</groupId>
83+
<artifactId>spring-boot-maven-plugin</artifactId>
84+
<version>2.3.4.RELEASE</version>
85+
</plugin>
86+
</plugins>
87+
</build>
8088
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import io.javaoperatorsdk.operator.springboot.starter.test.EnableMockOperator;
4+
import org.junit.jupiter.api.Test;
5+
import org.springframework.boot.test.context.SpringBootTest;
6+
7+
@SpringBootTest
8+
@EnableMockOperator
9+
public class SpringBootStarterSampleApplicationTest {
10+
11+
@Test
12+
void contextLoads() {}
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
io.javaoperatorsdk:
2+
controllers:
3+
customservicecontroller:
4+
retry:
5+
maxAttempts: 3
6+
7+
test:
8+
crdPaths: classpath:test-crd.yaml
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: customservices.sample.javaoperatorsdk
5+
spec:
6+
group: sample.javaoperatorsdk
7+
versions:
8+
- name: v1
9+
served: true
10+
storage: true
11+
scope: Namespaced
12+
names:
13+
plural: customservices
14+
singular: customservice
15+
kind: CustomService
16+
shortNames:
17+
- cs

0 commit comments

Comments
 (0)