Skip to content

Commit e757fa4

Browse files
committed
refactor: TomcatReconciler now uses dependent resources support
1 parent e2a553a commit e757fa4

File tree

2 files changed

+76
-98
lines changed

2 files changed

+76
-98
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import io.fabric8.kubernetes.api.model.ObjectMeta;
4+
import io.fabric8.kubernetes.api.model.apps.Deployment;
5+
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
6+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Builder;
7+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater;
8+
9+
public class DeploymentDependentResource
10+
implements Builder<Deployment, Tomcat>, Updater<Deployment, Tomcat> {
11+
12+
@Override
13+
public Deployment buildFor(Tomcat tomcat) {
14+
Deployment deployment = TomcatReconciler.loadYaml(Deployment.class, "deployment.yaml");
15+
final ObjectMeta tomcatMetadata = tomcat.getMetadata();
16+
final String tomcatName = tomcatMetadata.getName();
17+
return new DeploymentBuilder(deployment)
18+
.editMetadata()
19+
.addToLabels("app", tomcatName)
20+
.withName(tomcatName)
21+
.withNamespace(tomcatMetadata.getNamespace())
22+
.addToLabels("app.kubernetes.io/part-of", tomcatName)
23+
.addToLabels("app.kubernetes.io/managed-by", "tomcat-operator")
24+
.endMetadata()
25+
.editSpec()
26+
.withReplicas(tomcat.getSpec().getReplicas())
27+
// set tomcat version
28+
.editTemplate()
29+
// make sure label selector matches label (which has to be matched by service selector too)
30+
.editMetadata().addToLabels("app", tomcatName).endMetadata()
31+
.editSpec()
32+
.editFirstContainer().withImage("tomcat:" + tomcat.getSpec().getVersion()).endContainer()
33+
.endSpec()
34+
.endTemplate()
35+
.endSpec()
36+
.build();
37+
}
38+
39+
@Override
40+
public Deployment update(Deployment fetched, Tomcat tomcat) {
41+
return new DeploymentBuilder(fetched).editSpec().editTemplate().editSpec().editFirstContainer()
42+
.withImage("tomcat:" + tomcat.getSpec().getVersion())
43+
.endContainer().endSpec().endTemplate().endSpec().build();
44+
}
45+
}

sample-operators/tomcat-operator/src/main/java/io/javaoperatorsdk/operator/sample/TomcatReconciler.java

Lines changed: 31 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,49 @@
77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
99

10-
import io.fabric8.kubernetes.api.model.OwnerReference;
10+
import io.fabric8.kubernetes.api.model.ObjectMeta;
1111
import io.fabric8.kubernetes.api.model.Service;
12+
import io.fabric8.kubernetes.api.model.ServiceBuilder;
1213
import io.fabric8.kubernetes.api.model.apps.Deployment;
1314
import io.fabric8.kubernetes.api.model.apps.DeploymentStatus;
1415
import io.fabric8.kubernetes.client.KubernetesClient;
15-
import io.fabric8.kubernetes.client.informers.SharedIndexInformer;
1616
import io.fabric8.kubernetes.client.utils.Serialization;
17-
import io.javaoperatorsdk.operator.api.config.Cloner;
1817
import io.javaoperatorsdk.operator.api.reconciler.Context;
1918
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
20-
import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
2119
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
2220
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
23-
import io.javaoperatorsdk.operator.processing.event.source.EventSourceRegistry;
24-
import io.javaoperatorsdk.operator.processing.event.source.InformerEventSource;
25-
import io.javaoperatorsdk.operator.processing.event.source.Mappers;
21+
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResourceConfiguration;
22+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Updater;
2623

2724
import static io.javaoperatorsdk.operator.api.reconciler.Constants.NO_FINALIZER;
2825

2926
/**
3027
* Runs a specified number of Tomcat app server Pods. It uses a Deployment to create the Pods. Also
3128
* creates a Service over which the Pods can be accessed.
3229
*/
33-
@ControllerConfiguration(finalizerName = NO_FINALIZER)
34-
public class TomcatReconciler implements Reconciler<Tomcat>, EventSourceInitializer<Tomcat> {
30+
@ControllerConfiguration(
31+
finalizerName = NO_FINALIZER,
32+
labelSelector = "app.kubernetes.io/managed-by=tomcat-operator",
33+
dependents = {
34+
@DependentResourceConfiguration(resourceType = Deployment.class,
35+
updatable = true, builder = DeploymentDependentResource.class,
36+
updater = DeploymentDependentResource.class),
37+
@DependentResourceConfiguration(resourceType = Service.class, creatable = false,
38+
updatable = true)
39+
})
40+
public class TomcatReconciler implements Reconciler<Tomcat>, Updater<Service, Tomcat> {
3541

3642
private final Logger log = LoggerFactory.getLogger(getClass());
3743

3844
private final KubernetesClient kubernetesClient;
3945

40-
private volatile InformerEventSource<Deployment, Tomcat> informerEventSource;
41-
4246
public TomcatReconciler(KubernetesClient client) {
4347
this.kubernetesClient = client;
4448
}
4549

4650
@Override
47-
public void prepareEventSources(EventSourceRegistry<Tomcat> eventSourceRegistry, Cloner cloner) {
48-
SharedIndexInformer<Deployment> deploymentInformer =
49-
kubernetesClient.apps().deployments().inAnyNamespace()
50-
.withLabel("app.kubernetes.io/managed-by", "tomcat-operator")
51-
.runnableInformer(0);
52-
53-
this.informerEventSource =
54-
new InformerEventSource<>(deploymentInformer, Mappers.fromOwnerReference(), cloner);
55-
eventSourceRegistry.registerEventSource(this.informerEventSource);
56-
}
57-
58-
@Override
59-
public UpdateControl<Tomcat> reconcile(Tomcat tomcat, Context context) {
60-
createOrUpdateDeployment(tomcat);
61-
createOrUpdateService(tomcat);
62-
63-
Deployment deployment = informerEventSource.getAssociated(tomcat);
51+
public UpdateControl<Tomcat> reconcile(Tomcat tomcat, Context<Tomcat> context) {
52+
Deployment deployment = context.getSecondaryResource(Deployment.class);
6453

6554
if (deployment != null) {
6655
Tomcat updatedTomcat =
@@ -85,78 +74,22 @@ private Tomcat updateTomcatStatus(Tomcat tomcat, Deployment deployment) {
8574
return tomcat;
8675
}
8776

88-
private void createOrUpdateDeployment(Tomcat tomcat) {
89-
String ns = tomcat.getMetadata().getNamespace();
90-
Deployment existingDeployment =
91-
kubernetesClient
92-
.apps()
93-
.deployments()
94-
.inNamespace(ns)
95-
.withName(tomcat.getMetadata().getName())
96-
.get();
97-
if (existingDeployment == null) {
98-
Deployment deployment = loadYaml(Deployment.class, "deployment.yaml");
99-
deployment.getMetadata().setName(tomcat.getMetadata().getName());
100-
deployment.getMetadata().setNamespace(ns);
101-
deployment.getMetadata().getLabels().put("app.kubernetes.io/part-of",
102-
tomcat.getMetadata().getName());
103-
deployment.getMetadata().getLabels().put("app.kubernetes.io/managed-by", "tomcat-operator");
104-
// set tomcat version
105-
deployment
106-
.getSpec()
107-
.getTemplate()
108-
.getSpec()
109-
.getContainers()
110-
.get(0)
111-
.setImage("tomcat:" + tomcat.getSpec().getVersion());
112-
deployment.getSpec().setReplicas(tomcat.getSpec().getReplicas());
113-
114-
// make sure label selector matches label (which has to be matched by service selector too)
115-
deployment
116-
.getSpec()
117-
.getTemplate()
118-
.getMetadata()
119-
.getLabels()
120-
.put("app", tomcat.getMetadata().getName());
121-
deployment
122-
.getSpec()
123-
.getSelector()
124-
.getMatchLabels()
125-
.put("app", tomcat.getMetadata().getName());
126-
127-
OwnerReference ownerReference = deployment.getMetadata().getOwnerReferences().get(0);
128-
ownerReference.setName(tomcat.getMetadata().getName());
129-
ownerReference.setUid(tomcat.getMetadata().getUid());
130-
131-
log.info("Creating or updating Deployment {} in {}", deployment.getMetadata().getName(), ns);
132-
kubernetesClient.apps().deployments().inNamespace(ns).create(deployment);
133-
} else {
134-
existingDeployment
135-
.getSpec()
136-
.getTemplate()
137-
.getSpec()
138-
.getContainers()
139-
.get(0)
140-
.setImage("tomcat:" + tomcat.getSpec().getVersion());
141-
existingDeployment.getSpec().setReplicas(tomcat.getSpec().getReplicas());
142-
kubernetesClient.apps().deployments().inNamespace(ns).createOrReplace(existingDeployment);
143-
}
144-
}
145-
146-
private void createOrUpdateService(Tomcat tomcat) {
147-
Service service = loadYaml(Service.class, "service.yaml");
148-
service.getMetadata().setName(tomcat.getMetadata().getName());
149-
String ns = tomcat.getMetadata().getNamespace();
150-
service.getMetadata().setNamespace(ns);
151-
service.getMetadata().getOwnerReferences().get(0).setName(tomcat.getMetadata().getName());
152-
service.getMetadata().getOwnerReferences().get(0).setUid(tomcat.getMetadata().getUid());
153-
service.getSpec().getSelector().put("app", tomcat.getMetadata().getName());
154-
log.info("Creating or updating Service {} in {}", service.getMetadata().getName(), ns);
155-
kubernetesClient.services().inNamespace(ns).createOrReplace(service);
77+
@Override
78+
public Service update(Service fetched, Tomcat tomcat) {
79+
final ObjectMeta tomcatMetadata = tomcat.getMetadata();
80+
return new ServiceBuilder(loadYaml(Service.class, "service.yaml"))
81+
.editMetadata()
82+
.withName(tomcatMetadata.getName())
83+
.withNamespace(tomcatMetadata.getNamespace())
84+
.endMetadata()
85+
.editSpec()
86+
.addToSelector("app", tomcatMetadata.getName())
87+
.endSpec()
88+
.build();
15689
}
15790

158-
private <T> T loadYaml(Class<T> clazz, String yaml) {
159-
try (InputStream is = getClass().getResourceAsStream(yaml)) {
91+
static <T> T loadYaml(Class<T> clazz, String yaml) {
92+
try (InputStream is = TomcatReconciler.class.getResourceAsStream(yaml)) {
16093
return Serialization.unmarshal(is, clazz);
16194
} catch (IOException ex) {
16295
throw new IllegalStateException("Cannot find yaml on classpath: " + yaml);

0 commit comments

Comments
 (0)