|
3 | 3 | 
|
4 | 4 | [](https://discord.com/channels/723455000604573736)
|
5 | 5 |
|
6 |
| -Build Kubernetes Operators in Java without hassle. Inspired |
7 |
| -by [operator-sdk](https://github.com/operator-framework/operator-sdk). |
| 6 | +#Build Kubernetes Operators in Java Without Hassle |
8 | 7 |
|
9 |
| -Our webpage with documentation is getting better every day: https://javaoperatorsdk.io/ |
| 8 | +## Documentation |
10 | 9 |
|
11 |
| -**!! NOTE the main branch now contains source code for v2, which is under development, for actual |
12 |
| -version see [v1 branch](https://github.com/java-operator-sdk/java-operator-sdk/tree/v1) !!** |
| 10 | +Documentation can be found on the **[JOSDK WebSite](https://javaoperatorsdk.io/)**. |
13 | 11 |
|
14 |
| -Table of Contents |
15 |
| -========== |
| 12 | +It's getting better every day! :) |
16 | 13 |
|
17 |
| -1. [Features](#Features) |
18 |
| -1. [Why build your own Operator?](#Why-build-your-own-Operator) |
19 |
| -1. [Roadmap and Release Notes](#Roadmap-and-Release-Notes) |
20 |
| -1. [Join us on Discord!](#Join-us-on-Discord) |
21 |
| -1. [Usage](#Usage) |
| 14 | +## Contact us |
22 | 15 |
|
23 |
| -## Features |
| 16 | +Join us on [Discord](https://discord.gg/DacEhAy) or feel free to ask any question on |
| 17 | +[Kubernetes Slack Operator Channel](https://kubernetes.slack.com/archives/CAW0GV7A5) |
| 18 | + |
| 19 | +## How to Contribute |
| 20 | + |
| 21 | +See the [contribution](https://javaoperatorsdk.io/docs/contributing) guide on the website. |
| 22 | + |
| 23 | +## What is Java Operator SDK |
| 24 | + |
| 25 | +Java Operator SDK is a higher level framework and related tooling to support writing Kubernetes Operators in Java. |
| 26 | +It makes it use to utilize best practices and patters of an Operator development. Features include: |
24 | 27 |
|
25 | 28 | * Framework for handling Kubernetes API events
|
26 | 29 | * Automatic registration of Custom Resource watches
|
27 | 30 | * Retry action on failure
|
28 | 31 | * Smart event scheduling (only handle the latest event for the same resource)
|
29 | 32 | * Handling Observed Generations automatically
|
30 |
| -* for all see [features](https://javaoperatorsdk.io/docs/features) section on the webpage |
31 |
| - |
32 |
| -Check out |
33 |
| -this [blog post](https://csviri.medium.com/deep-dive-building-a-kubernetes-operator-sdk-for-java-developers-5008218822cb) |
34 |
| -about the non-trivial yet common problems needed to be solved for every operator. In case you are interested how to |
35 |
| -handle more complex scenarios take a look |
36 |
| -on [event sources](https://csviri.medium.com/java-operator-sdk-introduction-to-event-sources-a1aab5af4b7b) |
37 |
| -. |
38 |
| - |
39 |
| -## Why build your own Operator? |
40 |
| - |
41 |
| -* Infrastructure automation using the power and flexibility of Java. |
42 |
| - See [blog post](https://blog.container-solutions.com/cloud-native-java-infrastructure-automation-with-kubernetes-operators) |
43 |
| - . |
44 |
| -* Provisioning of complex applications - avoiding Helm chart hell |
45 |
| -* Integration with Cloud services - e.g. Secret stores |
46 |
| -* Safer deployment of applications - only expose cluster to users by Custom Resources |
47 |
| - |
48 |
| -#### Overview of the 1.9.0 changes |
49 |
| - |
50 |
| -- The Spring Boot starters have been moved to their own repositories and are now found at: |
51 |
| - - https://github.com/java-operator-sdk/operator-framework-spring-boot-starter |
52 |
| - - https://github.com/java-operator-sdk/operator-framework-spring-boot-starter-test |
53 |
| -- Updated Fabric8 client to version 5.4.0 |
54 |
| -- It is now possible to configure the controllers to not automatically add finalizers to resources. See the `Controller` |
55 |
| - annotation documentation for more details. |
56 |
| -- Added the possibility to configure how many seconds the SDK will wait before terminating reconciliation threads when a |
57 |
| - shut down is requested |
58 |
| - |
59 |
| -#### Overview of the 1.8.0 changes |
60 |
| - |
61 |
| -- The quarkus extension has been moved to the quarkiverse and is now found at |
62 |
| - https://github.com/quarkiverse/quarkus-operator-sdk |
63 |
| - |
64 |
| -##### Overview of the 1.7.0 changes |
65 |
| - |
66 |
| -- `Doneable` classes have been removed along with all the involved complexity |
67 |
| -- `Controller` annotation has been simplified: the `crdName` field has been removed as that value is computed from the |
68 |
| - associated custom resource implementation |
69 |
| -- Custom Resource implementation classes now need to be annotated with `Group` and `Version` |
70 |
| - annotations so that they can be identified properly. Optionally, they can also be annotated with |
71 |
| - `Kind` (if the name of the implementation class doesn't match the desired kind) and `Plural` if the plural version |
72 |
| - cannot be automatically computed (or the default computed version doesn't match your expectations). |
73 |
| -- The `CustomResource` class that needs to be extended is now parameterized with spec and status types, so you can have |
74 |
| - an empty default implementation that does what you'd expect. If you don't need a status, using `Void` for the |
75 |
| - associated type should work. |
76 |
| -- Custom Resources that are namespace-scoped need to implement the `Namespaced` interface so that the client can |
77 |
| - generate the proper URLs. This means, in particular, that `CustomResource` |
78 |
| - implementations that do **not** implement `Namespaced` are considered cluster-scoped. As a consequence, |
79 |
| - the `isClusterScoped` method/field has been removed from the appropriate classes (`Controller` annotation, in |
80 |
| - particular) as this is now inferred from the `CustomResource` |
81 |
| - type associated with your `Controller`. |
82 |
| - |
83 |
| -Many of these changes might not be immediately apparent but will result in `404` errors when connecting to the cluster. |
84 |
| -Please check that the Custom Resource implementations are properly annotated and that the value corresponds to your CRD |
85 |
| -manifest. If the namespace appear to be missing in your request URL, don't forget that namespace-scoped Custom Resources |
86 |
| -need to implement the `Namescaped` interface. |
87 |
| - |
88 |
| -## Join us on Discord! |
89 |
| - |
90 |
| -[Discord Invite Link](https://discord.gg/DacEhAy) |
91 |
| - |
92 |
| -## Usage |
93 |
| - |
94 |
| -We have several simple Operators under the [smoke-test-samples](smoke-test-samples) directory: |
95 |
| - |
96 |
| -* *pure-java*: Minimal Operator implementation which only parses the Custom Resource and prints to stdout. Implemented |
97 |
| - with and without Spring Boot support. The two samples share the common module. |
98 |
| -* *spring-boot-plain*: Sample showing integration with Spring Boot. |
99 |
| - |
100 |
| -There are also more complete samples in the standalone [sample-operators](sample-operators): |
101 |
| - |
102 |
| -* *webserver*: Simple example creating an NGINX webserver from a Custom Resource containing HTML code. |
103 |
| -* *mysql-schema*: Operator managing schemas in a MySQL database. |
104 |
| -* *tomcat*: Operator with two controllers, managing Tomcat instances and Webapps for these. |
105 |
| - |
106 |
| -Add [dependency](https://search.maven.org/search?q=a:operator-framework) to your project with Maven: |
107 |
| - |
108 |
| -```xml |
109 |
| - |
110 |
| -<dependency> |
111 |
| - <groupId>io.javaoperatorsdk</groupId> |
112 |
| - <artifactId>operator-framework</artifactId> |
113 |
| - <version>{see https://search.maven.org/search?q=a:operator-framework for latest version}</version> |
114 |
| -</dependency> |
115 |
| -``` |
116 |
| - |
117 |
| -Or alternatively with Gradle, which also requires declaring the SDK as an annotation processor to generate the mappings |
118 |
| -between controllers and custom resource classes: |
119 |
| - |
120 |
| -```groovy |
121 |
| -dependencies { |
122 |
| - implementation "io.javaoperatorsdk:operator-framework:${javaOperatorVersion}" |
123 |
| - annotationProcessor "io.javaoperatorsdk:operator-framework:${javaOperatorVersion}" |
124 |
| -} |
125 |
| -``` |
126 |
| - |
127 |
| -Once you've added the dependency, define a main method initializing the Operator and registering a controller. |
128 |
| - |
129 |
| -```java |
130 |
| -public class Runner { |
131 |
| - |
132 |
| - public static void main(String[] args) { |
133 |
| - Operator operator = new Operator(DefaultConfigurationService.instance()); |
134 |
| - operator.register(new WebPageReconciler()); |
135 |
| - operator.start(); |
136 |
| - } |
137 |
| -} |
138 |
| -``` |
139 |
| - |
140 |
| -The Controller implements the business logic and describes all the classes needed to handle the CRD. |
141 |
| - |
142 |
| -```java |
143 |
| - |
144 |
| -@ControllerConfiguration |
145 |
| -public class WebPageReconciler implements Reconciler<WebPage> { |
146 |
| - |
147 |
| - // Return the changed resource, so it gets updated. See javadoc for details. |
148 |
| - @Override |
149 |
| - public UpdateControl<WebPage> reconcile(WebPage resource, |
150 |
| - Context context) { |
151 |
| - // ... your logic ... |
152 |
| - return UpdateControl.updateStatus(resource); |
153 |
| - } |
154 |
| -} |
155 |
| -``` |
156 |
| - |
157 |
| -A sample custom resource POJO representation |
158 |
| - |
159 |
| -```java |
160 |
| - |
161 |
| -@Group("sample.javaoperatorsdk") |
162 |
| -@Version("v1") |
163 |
| -public class WebPage extends CustomResource<WebPageSpec, WebPageStatus> implements |
164 |
| - Namespaced { |
165 |
| - |
166 |
| -} |
167 |
| - |
168 |
| -public class WebPageSpec { |
169 |
| - |
170 |
| - private String html; |
171 |
| - |
172 |
| - public String getHtml() { |
173 |
| - return html; |
174 |
| - } |
175 |
| - |
176 |
| - public void setHtml(String html) { |
177 |
| - this.html = html; |
178 |
| - } |
179 |
| -} |
180 |
| -``` |
181 |
| - |
182 |
| -### Deactivating CustomResource implementations validation |
183 |
| - |
184 |
| -The operator will, by default, query the deployed CRDs to check that the `CustomResource` |
185 |
| -implementations match what is known to the cluster. This requires an additional query to the cluster and, sometimes, |
186 |
| -elevated privileges for the operator to be able to read the CRDs from the cluster. This validation is mostly meant to |
187 |
| -help users new to operator development get started and avoid common mistakes. Advanced users or production deployments |
188 |
| -might want to skip this step. This is done by setting the `CHECK_CRD_ENV_KEY` environment variable to `false`. |
189 |
| - |
190 |
| -### Automatic generation of CRDs |
191 |
| - |
192 |
| -To automatically generate CRD manifests from your annotated Custom Resource classes, you only need to add the following |
193 |
| -dependencies to your project: |
194 |
| - |
195 |
| -```xml |
196 |
| - |
197 |
| -<dependency> |
198 |
| - <groupId>io.fabric8</groupId> |
199 |
| - <artifactId>crd-generator-apt</artifactId> |
200 |
| - <scope>provided</scope> |
201 |
| -</dependency> |
202 |
| -``` |
203 |
| - |
204 |
| -The CRD will be generated in `target/classes/META-INF/fabric8` (or in `target/test-classes/META-INF/fabric8`, if you use |
205 |
| -the `test` scope) with the CRD name suffixed by the generated spec version. For example, a CR using |
206 |
| -the `java-operator-sdk.io` group with a `mycrs` plural form will result in 2 files: |
207 |
| - |
208 |
| -- `mycrs.java-operator-sdk.io-v1.yml` |
209 |
| -- `mycrs.java-operator-sdk.io-v1beta1.yml` |
210 |
| - |
211 |
| -**NOTE:** |
212 |
| -> Quarkus users using the `quarkus-operator-sdk` extension do not need to add any extra dependency to get their CRD generated as this is handled by the extension itself. |
213 |
| -
|
214 |
| -### Quarkus |
215 |
| - |
216 |
| -A [Quarkus](https://quarkus.io) extension is also provided to ease the development of Quarkus-based operators. |
217 |
| - |
218 |
| -Add [this dependency](https://search.maven.org/search?q=a:quarkus-operator-sdk) |
219 |
| -to your project: |
220 |
| - |
221 |
| -```xml |
222 |
| - |
223 |
| -<dependency> |
224 |
| - <groupId>io.quarkiverse.operatorsdk</groupId> |
225 |
| - <artifactId>quarkus-operator-sdk</artifactId> |
226 |
| - <version>{see https://search.maven.org/search?q=a:quarkus-operator-sdk for latest version} |
227 |
| - </version> |
228 |
| -</dependency> |
229 |
| -``` |
230 |
| - |
231 |
| -Create an Application, Quarkus will automatically create and inject a `KubernetesClient` ( |
232 |
| -or `OpenShiftClient`), `Operator`, `ConfigurationService` and `ResourceController` instances that your application can |
233 |
| -use. Below, you can see the minimal code you need to write to get your operator and controllers up and running: |
234 |
| - |
235 |
| -```java |
236 |
| - |
237 |
| -@QuarkusMain |
238 |
| -public class QuarkusOperator implements QuarkusApplication { |
239 |
| - |
240 |
| - @Inject |
241 |
| - Operator operator; |
242 |
| - |
243 |
| - public static void main(String... args) { |
244 |
| - Quarkus.run(QuarkusOperator.class, args); |
245 |
| - } |
246 |
| - |
247 |
| - @Override |
248 |
| - public int run(String... args) throws Exception { |
249 |
| - operator.start(); |
250 |
| - Quarkus.waitForExit(); |
251 |
| - return 0; |
252 |
| - } |
253 |
| -} |
254 |
| -``` |
255 |
| - |
256 |
| -### Spring Boot |
257 |
| - |
258 |
| -You can also let Spring Boot wire your application together and automatically register the controllers. |
259 |
| - |
260 |
| -Add [this dependency](https://search.maven.org/search?q=a:operator-framework-spring-boot-starter) to your project: |
261 |
| - |
262 |
| -```xml |
263 |
| - |
264 |
| -<dependency> |
265 |
| - <groupId>io.javaoperatorsdk</groupId> |
266 |
| - <artifactId>operator-framework-spring-boot-starter</artifactId> |
267 |
| - <version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for |
268 |
| - latest version} |
269 |
| - </version> |
270 |
| -</dependency> |
271 |
| -``` |
272 |
| - |
273 |
| -Create an Application |
274 |
| - |
275 |
| -```java |
276 |
| - |
277 |
| -@SpringBootApplication |
278 |
| -public class Application { |
279 |
| - |
280 |
| - public static void main(String[] args) { |
281 |
| - SpringApplication.run(Application.class, args); |
282 |
| - } |
283 |
| -} |
284 |
| -``` |
285 |
| - |
286 |
| -#### Spring Boot test support |
| 33 | +* Support For Intelligent Error Handling |
287 | 34 |
|
288 |
| -Adding the following dependency would let you mock the operator for the tests where loading the spring container is |
289 |
| -necessary, but it doesn't need real access to a Kubernetes cluster. |
| 35 | +For all features and their usage see the [related section on the website](https://javaoperatorsdk.io/docs/features). |
290 | 36 |
|
291 |
| -```xml |
| 37 | +## Related Projects |
292 | 38 |
|
293 |
| -<dependency> |
294 |
| - <groupId>io.javaoperatorsdk</groupId> |
295 |
| - <artifactId>operator-framework-spring-boot-starter-test</artifactId> |
296 |
| - <version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for |
297 |
| - latest version} |
298 |
| - </version> |
299 |
| -</dependency> |
300 |
| -``` |
| 39 | +Operator SDK plugin: https://github.com/operator-framework/java-operator-plugins |
301 | 40 |
|
302 |
| -Mock the operator: |
| 41 | +Quarkus Extension: https://github.com/quarkiverse/quarkus-operator-sdk |
303 | 42 |
|
304 |
| -```java |
305 | 43 |
|
306 |
| -@SpringBootTest |
307 |
| -@EnableMockOperator |
308 |
| -public class SpringBootStarterSampleApplicationTest { |
309 | 44 |
|
310 |
| - @Test |
311 |
| - void contextLoads() { |
312 |
| - } |
313 |
| -} |
314 |
| -``` |
0 commit comments