mirror of
https://github.com/openshift/openshift-docs.git
synced 2026-02-05 21:46:22 +01:00
162 lines
6.0 KiB
Plaintext
162 lines
6.0 KiB
Plaintext
// Module included in the following assemblies:
|
|
//
|
|
// * operators/operator_sdk/java/osdk-java-tutorial.adoc
|
|
|
|
:_mod-docs-content-type: PROCEDURE
|
|
[id="osdk-java-implement-controller_{context}"]
|
|
= Implementing the controller
|
|
|
|
After creating a new API and controller, you can implement the controller logic.
|
|
|
|
.Procedure
|
|
|
|
. Append the following dependency to the `pom.xml` file:
|
|
+
|
|
[source,xml]
|
|
----
|
|
<dependency>
|
|
<groupId>commons-collections</groupId>
|
|
<artifactId>commons-collections</artifactId>
|
|
<version>3.2.2</version>
|
|
</dependency>
|
|
----
|
|
|
|
. For this example, replace the generated controller file `MemcachedReconciler.java` with following example implementation:
|
|
+
|
|
.Example `MemcachedReconciler.java`
|
|
[%collapsible]
|
|
====
|
|
[source,java]
|
|
----
|
|
package com.example;
|
|
|
|
import io.fabric8.kubernetes.client.KubernetesClient;
|
|
import io.javaoperatorsdk.operator.api.reconciler.Context;
|
|
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
|
|
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
|
|
import io.fabric8.kubernetes.api.model.ContainerBuilder;
|
|
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
|
|
import io.fabric8.kubernetes.api.model.LabelSelectorBuilder;
|
|
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
|
|
import io.fabric8.kubernetes.api.model.OwnerReferenceBuilder;
|
|
import io.fabric8.kubernetes.api.model.Pod;
|
|
import io.fabric8.kubernetes.api.model.PodSpecBuilder;
|
|
import io.fabric8.kubernetes.api.model.PodTemplateSpecBuilder;
|
|
import io.fabric8.kubernetes.api.model.apps.Deployment;
|
|
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
|
|
import io.fabric8.kubernetes.api.model.apps.DeploymentSpecBuilder;
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class MemcachedReconciler implements Reconciler<Memcached> {
|
|
private final KubernetesClient client;
|
|
|
|
public MemcachedReconciler(KubernetesClient client) {
|
|
this.client = client;
|
|
}
|
|
|
|
// TODO Fill in the rest of the reconciler
|
|
|
|
@Override
|
|
public UpdateControl<Memcached> reconcile(
|
|
Memcached resource, Context context) {
|
|
// TODO: fill in logic
|
|
Deployment deployment = client.apps()
|
|
.deployments()
|
|
.inNamespace(resource.getMetadata().getNamespace())
|
|
.withName(resource.getMetadata().getName())
|
|
.get();
|
|
|
|
if (deployment == null) {
|
|
Deployment newDeployment = createMemcachedDeployment(resource);
|
|
client.apps().deployments().create(newDeployment);
|
|
return UpdateControl.noUpdate();
|
|
}
|
|
|
|
int currentReplicas = deployment.getSpec().getReplicas();
|
|
int requiredReplicas = resource.getSpec().getSize();
|
|
|
|
if (currentReplicas != requiredReplicas) {
|
|
deployment.getSpec().setReplicas(requiredReplicas);
|
|
client.apps().deployments().createOrReplace(deployment);
|
|
return UpdateControl.noUpdate();
|
|
}
|
|
|
|
List<Pod> pods = client.pods()
|
|
.inNamespace(resource.getMetadata().getNamespace())
|
|
.withLabels(labelsForMemcached(resource))
|
|
.list()
|
|
.getItems();
|
|
|
|
List<String> podNames =
|
|
pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList());
|
|
|
|
|
|
if (resource.getStatus() == null
|
|
|| !CollectionUtils.isEqualCollection(podNames, resource.getStatus().getNodes())) {
|
|
if (resource.getStatus() == null) resource.setStatus(new MemcachedStatus());
|
|
resource.getStatus().setNodes(podNames);
|
|
return UpdateControl.updateResource(resource);
|
|
}
|
|
|
|
return UpdateControl.noUpdate();
|
|
}
|
|
|
|
private Map<String, String> labelsForMemcached(Memcached m) {
|
|
Map<String, String> labels = new HashMap<>();
|
|
labels.put("app", "memcached");
|
|
labels.put("memcached_cr", m.getMetadata().getName());
|
|
return labels;
|
|
}
|
|
|
|
private Deployment createMemcachedDeployment(Memcached m) {
|
|
Deployment deployment = new DeploymentBuilder()
|
|
.withMetadata(
|
|
new ObjectMetaBuilder()
|
|
.withName(m.getMetadata().getName())
|
|
.withNamespace(m.getMetadata().getNamespace())
|
|
.build())
|
|
.withSpec(
|
|
new DeploymentSpecBuilder()
|
|
.withReplicas(m.getSpec().getSize())
|
|
.withSelector(
|
|
new LabelSelectorBuilder().withMatchLabels(labelsForMemcached(m)).build())
|
|
.withTemplate(
|
|
new PodTemplateSpecBuilder()
|
|
.withMetadata(
|
|
new ObjectMetaBuilder().withLabels(labelsForMemcached(m)).build())
|
|
.withSpec(
|
|
new PodSpecBuilder()
|
|
.withContainers(
|
|
new ContainerBuilder()
|
|
.withImage("memcached:1.4.36-alpine")
|
|
.withName("memcached")
|
|
.withCommand("memcached", "-m=64", "-o", "modern", "-v")
|
|
.withPorts(
|
|
new ContainerPortBuilder()
|
|
.withContainerPort(11211)
|
|
.withName("memcached")
|
|
.build())
|
|
.build())
|
|
.build())
|
|
.build())
|
|
.build())
|
|
.build();
|
|
deployment.addOwnerReference(m);
|
|
return deployment;
|
|
}
|
|
}
|
|
----
|
|
====
|
|
+
|
|
The example controller runs the following reconciliation logic for each `Memcached` custom resource (CR):
|
|
+
|
|
--
|
|
* Creates a Memcached deployment if it does not exist.
|
|
* Ensures that the deployment size matches the size specified by the `Memcached` CR spec.
|
|
* Updates the `Memcached` CR status with the names of the `memcached` pods.
|
|
--
|