Skip to content

Docs for v2 #715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 110 additions & 124 deletions README.md

Large diffs are not rendered by default.

133 changes: 82 additions & 51 deletions docs/documentation/features.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/documentation/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ permalink: /docs/getting-started
## Introduction & Resources on Operators

Operators are easy and simple way to manage resource on Kubernetes clusters but
also outside of the cluster. The goal of this SDK is to allow writing operators in Java by
also outside the cluster. The goal of this SDK is to allow writing operators in Java by
providing a nice API and handling common issues regarding the operators on framework level.

For an introduction, what is an operator see this [blog post](https://blog.container-solutions.com/kubernetes-operators-explained).
Expand Down
176 changes: 84 additions & 92 deletions docs/documentation/use-samples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ layout: docs
permalink: /docs/using-samples
---


# How to use sample Operators

We have several sample Operators under the [samples](https://github.com/java-operator-sdk/java-operator-sdk/tree/master/samples) directory:
We have several sample Operators under
the [samples](https://github.com/java-operator-sdk/java-operator-sdk/tree/master/smoke-test-samples) directory:

* *pure-java*: Minimal Operator implementation which only parses the Custom Resource and prints to
stdout. Implemented with and without Spring Boot support. The two samples share the common module.
* *pure-java*: Minimal Operator implementation which only parses the Custom Resource and prints to stdout. Implemented
with and without Spring Boot support. The two samples share the common module.
* *spring-boot-plain*: Sample showing integration with Spring Boot.

There are also more samples in the
standalone [samples repo](https://github.com/java-operator-sdk/samples):
There are also more samples in the standalone [samples repo](https://github.com/java-operator-sdk/samples):

* *webserver*: Simple example creating an NGINX webserver from a Custom Resource containing HTML
code.
* *webserver*: Simple example creating an NGINX webserver from a Custom Resource containing HTML code.
* *mysql-schema*: Operator managing schemas in a MySQL database.
* *tomcat*: Operator with two controllers, managing Tomcat instances and Webapps for these.

Expand All @@ -27,14 +25,14 @@ Add [dependency](https://search.maven.org/search?q=a:operator-framework) to your
```xml

<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework for latest version}</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework for latest version}</version>
</dependency>
```

Or alternatively with Gradle, which also requires declaring the SDK as an annotation processor to
generate the mappings between controllers and custom resource classes:
Or alternatively with Gradle, which also requires declaring the SDK as an annotation processor to generate the mappings
between controllers and custom resource classes:

```groovy
dependencies {
Expand All @@ -43,16 +41,16 @@ dependencies {
}
```

Once you've added the dependency, define a main method initializing the Operator and registering a
controller.
Once you've added the dependency, define a main method initializing the Operator and registering a controller.

```java
public class Runner {

public static void main(String[] args) {
Operator operator = new Operator(DefaultConfigurationService.instance());
operator.register(new WebServerController());
}
public static void main(String[] args) {
Operator operator = new Operator(DefaultConfigurationService.instance());
operator.register(new WebServerController());
operator.start();
}
}
```

Expand All @@ -61,15 +59,15 @@ The Controller implements the business logic and describes all the classes neede
```java

@Controller
public class WebServerController implements ResourceController<WebServer> {

// Return the changed resource, so it gets updated. See javadoc for details.
@Override
public UpdateControl<CustomService> createOrUpdateResource(CustomService resource,
Context<WebServer> context) {
// ... your logic ...
return UpdateControl.updateStatusSubResource(resource);
}
public class WebServerController implements Reconciler<WebServer> {

// Return the changed resource, so it gets updated. See javadoc for details.
@Override
public UpdateControl<CustomService> reconcile(CustomService resource,
Context context) {
// ... your logic ...
return UpdateControl.updateStatus(resource);
}
}
```

Expand All @@ -80,51 +78,49 @@ A sample custom resource POJO representation
@Group("sample.javaoperatorsdk")
@Version("v1")
public class WebServer extends CustomResource<WebServerSpec, WebServerStatus> implements
Namespaced {
Namespaced {

}

public class WebServerSpec {

private String html;
private String html;

public String getHtml() {
return html;
}
public String getHtml() {
return html;
}

public void setHtml(String html) {
this.html = html;
}
public void setHtml(String html) {
this.html = html;
}
}
```

### Deactivating CustomResource implementations validation

The operator will, by default, query the deployed CRDs to check that the `CustomResource`
implementations match what is known to the cluster. This requires an additional query to the cluster
and, sometimes, elevated privileges for the operator to be able to read the CRDs from the cluster.
This validation is mostly meant to help users new to operator development get started and avoid
common mistakes. Advanced users or production deployments might want to skip this step. This is done
by setting the `CHECK_CRD_ENV_KEY` environment variable to `false`.
implementations match what is known to the cluster. This requires an additional query to the cluster and, sometimes,
elevated privileges for the operator to be able to read the CRDs from the cluster. This validation is mostly meant to
help users new to operator development get started and avoid common mistakes. Advanced users or production deployments
might want to skip this step. This is done by setting the `CHECK_CRD_ENV_KEY` environment variable to `false`.

### Automatic generation of CRDs

To automatically generate CRD manifests from your annotated Custom Resource classes, you only need
to add the following dependencies to your project:
To automatically generate CRD manifests from your annotated Custom Resource classes, you only need to add the following
dependencies to your project:

```xml

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>crd-generator-apt</artifactId>
<scope>provided</scope>
<groupId>io.fabric8</groupId>
<artifactId>crd-generator-apt</artifactId>
<scope>provided</scope>
</dependency>
```

The CRD will be generated in `target/classes/META-INF/fabric8` (or
in `target/test-classes/META-INF/fabric8`, if you use the `test` scope) with the CRD name suffixed
by the generated spec version. For example, a CR using the `java-operator-sdk.io` group with
a `mycrs` plural form will result in 2 files:
The CRD will be generated in `target/classes/META-INF/fabric8` (or in `target/test-classes/META-INF/fabric8`, if you use
the `test` scope) with the CRD name suffixed by the generated spec version. For example, a CR using
the `java-operator-sdk.io` group with a `mycrs` plural form will result in 2 files:

- `mycrs.java-operator-sdk.io-v1.yml`
- `mycrs.java-operator-sdk.io-v1beta1.yml`
Expand All @@ -134,64 +130,60 @@ a `mycrs` plural form will result in 2 files:

### Quarkus

A [Quarkus](https://quarkus.io) extension is also provided to ease the development of Quarkus-based
operators.
A [Quarkus](https://quarkus.io) extension is also provided to ease the development of Quarkus-based operators.

Add [this dependency](https://search.maven.org/search?q=a:quarkus-operator-sdk)
to your project:

```xml

<dependency>
<groupId>io.quarkiverse.operatorsdk</groupId>
<artifactId>quarkus-operator-sdk</artifactId>
<version>{see https://search.maven.org/search?q=a:quarkus-operator-sdk for latest version}
</version>
<groupId>io.quarkiverse.operatorsdk</groupId>
<artifactId>quarkus-operator-sdk</artifactId>
<version>{see https://search.maven.org/search?q=a:quarkus-operator-sdk for latest version}
</version>
</dependency>
```

Create an Application, Quarkus will automatically create and inject a `KubernetesClient` (
or `OpenShiftClient`), `Operator`, `ConfigurationService` and `ResourceController` instances that
your application can use. Below, you can see the minimal code you need to write to get your operator
and controllers up and running:
or `OpenShiftClient`), `Operator`, `ConfigurationService` and `ResourceController` instances that your application can
use. Below, you can see the minimal code you need to write to get your operator and controllers up and running:

```java

@QuarkusMain
public class QuarkusOperator implements QuarkusApplication {

@Inject
Operator operator;
@Inject
Operator operator;

public static void main(String... args) {
Quarkus.run(QuarkusOperator.class, args);
}
public static void main(String... args) {
Quarkus.run(QuarkusOperator.class, args);
}

@Override
public int run(String... args) throws Exception {
operator.start();
Quarkus.waitForExit();
return 0;
}
@Override
public int run(String... args) throws Exception {
operator.start();
Quarkus.waitForExit();
return 0;
}
}
```

### Spring Boot

You can also let Spring Boot wire your application together and automatically register the
controllers.
You can also let Spring Boot wire your application together and automatically register the controllers.

Add [this dependency](https://search.maven.org/search?q=a:operator-framework-spring-boot-starter) to
your project:
Add [this dependency](https://search.maven.org/search?q=a:operator-framework-spring-boot-starter) to your project:

```xml

<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for
latest version}
</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for
latest version}
</version>
</dependency>
```

Expand All @@ -202,25 +194,25 @@ Create an Application
@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```

#### Spring Boot test support

Adding the following dependency would let you mock the operator for the tests where loading the
spring container is necessary, but it doesn't need real access to a Kubernetes cluster.
Adding the following dependency would let you mock the operator for the tests where loading the spring container is
necessary, but it doesn't need real access to a Kubernetes cluster.

```xml

<dependency>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for
latest version}
</version>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-spring-boot-starter-test</artifactId>
<version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for
latest version}
</version>
</dependency>
```

Expand All @@ -232,8 +224,8 @@ Mock the operator:
@EnableMockOperator
public class SpringBootStarterSampleApplicationTest {

@Test
void contextLoads() {
}
@Test
void contextLoads() {
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ public interface ErrorStatusHandler<T extends HasMetadata> {
* when the last reconciliation retry attempt is failed on the Reconciler. In that case the
* updateErrorStatus is called automatically.
* <p>
* The result of the method call is used to make a status sub-resource update on the custom
* resource. This is always a sub-resource update request, so no update on custom resource itself
* (like spec of metadata) happens. Note that this update request will also produce an event, and
* will result in a reconciliation if the controller is not generation aware.
* The result of the method call is used to make a status update on the custom resource. This is
* always a sub-resource update request, so no update on custom resource itself (like spec of
* metadata) happens. Note that this update request will also produce an event, and will result in
* a reconciliation if the controller is not generation aware.
* <p>
* Note that the scope of this feature is only the reconcile method of the reconciler, since there
* should not be updates on custom resource after it is marked for deletion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
public interface EventSourceInitializer<T extends HasMetadata> {

/**
* In this typically you might want to register event sources. But can access
* CustomResourceEventSource, what might be handy for some edge cases.
* Reconciler can implement this interface typically to register event sources. But can access
* CustomResourceEventSource, what might be useful for some edge cases.
*
* @param eventSourceRegistry the {@link EventSourceRegistry} where event sources can be
* registered.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package io.javaoperatorsdk.operator.api.reconciler;

public interface RetryInfo {

/**
* @return current retry attempt count. 0 if the current execution is not a retry.
*/
int getAttemptCount();

/**
* @return true, if the current attempt is the last one in regard to the retry limit
* configuration.
*/
boolean isLastAttempt();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ private UpdateControl(
this.updateResource = updateResource;
}

/**
* Creates an update control instance that instructs the framework to do an update on resource
* itself, not on the status. Note that usually as a results of a reconciliation should be a
* status update not an update to the resource itself.
*/
public static <T extends HasMetadata> UpdateControl<T> updateResource(T customResource) {
return new UpdateControl<>(customResource, false, true);
}
Expand All @@ -31,7 +36,7 @@ public static <T extends HasMetadata> UpdateControl<T> updateStatus(
/**
* As a results of this there will be two call to K8S API. First the custom resource will be
* updates then the status sub-resource.
*
*
* @param <T> resource type
* @param customResource - custom resource to use in both API calls
* @return UpdateControl instance
Expand Down