Skip to content

Commit c392542

Browse files
committed
Merge branch 'next' into mermaid-in-docs
# Conflicts: # docs/documentation/dependent-resources.md
2 parents 165288e + 76650a5 commit c392542

File tree

21 files changed

+378
-276
lines changed

21 files changed

+378
-276
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/ConfigurationService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ default Config getClientConfiguration() {
7777
* @return {@code true} if CRDs should be checked (default), {@code false} otherwise
7878
*/
7979
default boolean checkCRDAndValidateLocalModel() {
80-
return true;
80+
return false;
8181
}
8282

8383
int DEFAULT_RECONCILIATION_THREADS_NUMBER = 5;

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/Utils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static boolean isValidateCustomResourcesEnvVarSet() {
6464
}
6565

6666
public static boolean shouldCheckCRDAndValidateLocalModel() {
67-
return getBooleanFromSystemPropsOrDefault(CHECK_CRD_ENV_KEY, true);
67+
return getBooleanFromSystemPropsOrDefault(CHECK_CRD_ENV_KEY, false);
6868
}
6969

7070
public static boolean debugThreadPool() {

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/reconciler/dependent/managed/KubernetesClientAware.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44

55
public interface KubernetesClientAware {
66
void setKubernetesClient(KubernetesClient kubernetesClient);
7+
8+
KubernetesClient getKubernetesClient();
79
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/Controller.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.LinkedList;
44
import java.util.List;
5+
import java.util.Optional;
56
import java.util.stream.Collectors;
67

78
import org.slf4j.Logger;
@@ -54,13 +55,17 @@ public class Controller<P extends HasMetadata> implements Reconciler<P>, Cleaner
5455
private final boolean contextInitializer;
5556
private final boolean hasDeleterDependents;
5657
private final boolean isCleaner;
58+
private final Metrics metrics;
59+
5760

5861
public Controller(Reconciler<P> reconciler,
5962
ControllerConfiguration<P> configuration,
6063
KubernetesClient kubernetesClient) {
6164
this.reconciler = reconciler;
6265
this.configuration = configuration;
6366
this.kubernetesClient = kubernetesClient;
67+
this.metrics = Optional.ofNullable(ConfigurationServiceProvider.instance().getMetrics())
68+
.orElse(Metrics.NOOP);
6469
contextInitializer = reconciler instanceof ContextInitializer;
6570

6671
eventSourceManager = new EventSourceManager<>(this);
@@ -105,9 +110,8 @@ private void initContextIfNeeded(P resource, Context<P> context) {
105110

106111
@Override
107112
public DeleteControl cleanup(P resource, Context<P> context) {
108-
initContextIfNeeded(resource, context);
109113
try {
110-
return metrics()
114+
return metrics
111115
.timeControllerExecution(
112116
new ControllerExecution<>() {
113117
@Override
@@ -127,6 +131,7 @@ public String successTypeName(DeleteControl deleteControl) {
127131

128132
@Override
129133
public DeleteControl execute() {
134+
initContextIfNeeded(resource, context);
130135
if (hasDeleterDependents) {
131136
dependents.stream()
132137
.filter(d -> d instanceof Deleter)
@@ -147,8 +152,7 @@ public DeleteControl execute() {
147152

148153
@Override
149154
public UpdateControl<P> reconcile(P resource, Context<P> context) throws Exception {
150-
initContextIfNeeded(resource, context);
151-
return metrics().timeControllerExecution(
155+
return metrics.timeControllerExecution(
152156
new ControllerExecution<>() {
153157
@Override
154158
public String name() {
@@ -174,18 +178,13 @@ public String successTypeName(UpdateControl<P> result) {
174178

175179
@Override
176180
public UpdateControl<P> execute() throws Exception {
181+
initContextIfNeeded(resource, context);
177182
dependents.forEach(dependent -> dependent.reconcile(resource, context));
178183
return reconciler.reconcile(resource, context);
179184
}
180185
});
181186
}
182187

183-
184-
private Metrics metrics() {
185-
final var metrics = ConfigurationServiceProvider.instance().getMetrics();
186-
return metrics != null ? metrics : Metrics.NOOP;
187-
}
188-
189188
@Override
190189
public List<EventSource> prepareEventSources(EventSourceContext<P> context) {
191190
List<EventSource> sources = new LinkedList<>();

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/dependent/kubernetes/KubernetesDependentResource.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ public void setKubernetesClient(KubernetesClient kubernetesClient) {
156156
this.client = kubernetesClient;
157157
}
158158

159+
@Override
160+
public KubernetesClient getKubernetesClient() {
161+
return client;
162+
}
163+
159164
@Override
160165
protected R desired(P primary, Context<P> context) {
161166
return super.desired(primary, context);

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/ConfigurationServiceProviderTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ void shouldProvideTheSetInstanceIfProvided() {
3535
@Test
3636
void shouldBePossibleToOverrideConfigOnce() {
3737
final var config = new AbstractConfigurationService(null);
38-
assertTrue(config.checkCRDAndValidateLocalModel());
38+
assertFalse(config.checkCRDAndValidateLocalModel());
3939

4040
ConfigurationServiceProvider.set(config);
4141
var instance = ConfigurationServiceProvider.instance();
4242
assertEquals(config, instance);
4343

44-
ConfigurationServiceProvider.overrideCurrent(o -> o.checkingCRDAndValidateLocalModel(false));
44+
ConfigurationServiceProvider.overrideCurrent(o -> o.checkingCRDAndValidateLocalModel(true));
4545
instance = ConfigurationServiceProvider.instance();
4646
assertNotEquals(config, instance);
47-
assertFalse(instance.checkCRDAndValidateLocalModel());
47+
assertTrue(instance.checkCRDAndValidateLocalModel());
4848

4949
assertThrows(IllegalStateException.class,
5050
() -> ConfigurationServiceProvider.overrideCurrent(o -> o.withCloseClientOnStop(false)));

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/api/config/UtilsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
class UtilsTest {
2121

2222
@Test
23-
void shouldCheckCRDAndValidateLocalModelByDefault() {
24-
assertTrue(Utils.shouldCheckCRDAndValidateLocalModel());
23+
void shouldNotCheckCRDAndValidateLocalModelByDefault() {
24+
assertFalse(Utils.shouldCheckCRDAndValidateLocalModel());
2525
}
2626

2727
@Test

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/processing/ControllerTest.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import org.junit.jupiter.api.Test;
44

55
import io.fabric8.kubernetes.api.model.Secret;
6-
import io.javaoperatorsdk.operator.MissingCRDException;
76
import io.javaoperatorsdk.operator.MockKubernetesClient;
87
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
98
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
@@ -12,7 +11,6 @@
1211
import io.javaoperatorsdk.operator.sample.simple.TestCustomResource;
1312

1413
import static org.assertj.core.api.Assertions.assertThat;
15-
import static org.junit.jupiter.api.Assertions.assertThrows;
1614
import static org.mockito.Mockito.*;
1715

1816
@SuppressWarnings("unchecked")
@@ -47,19 +45,6 @@ void crdShouldNotBeCheckedForCustomResourcesIfDisabled() {
4745
}
4846
}
4947

50-
@Test
51-
void crdShouldBeCheckedForCustomResourcesByDefault() {
52-
ConfigurationServiceProvider.reset();
53-
final var client = MockKubernetesClient.client(TestCustomResource.class);
54-
when(configuration.getResourceClass()).thenReturn(TestCustomResource.class);
55-
56-
final var controller = new Controller<TestCustomResource>(reconciler, configuration, client);
57-
// since we're not really connected to a cluster and the CRD wouldn't be deployed anyway, we
58-
// expect a MissingCRDException to be thrown
59-
assertThrows(MissingCRDException.class, controller::start);
60-
verify(client, times(1)).apiextensions();
61-
}
62-
6348
@Test
6449
void usesFinalizerIfThereIfReconcilerImplementsCleaner() {
6550
Reconciler reconciler = mock(Reconciler.class, withSettings().extraInterfaces(Cleaner.class));

sample-operators/webpage/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<version>3.0.0-SNAPSHOT</version>
1111
</parent>
1212

13-
<artifactId>webpage</artifactId>
13+
<artifactId>sample-webpage-operator</artifactId>
1414
<name>Operator SDK - Samples - WebPage</name>
1515
<description>Provisions an nginx Webserver based on a CRD with give html</description>
1616
<packaging>jar</packaging>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import io.fabric8.kubernetes.api.model.ConfigMap;
10+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
11+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
12+
import io.javaoperatorsdk.operator.api.reconciler.Context;
13+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;
14+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
15+
import io.javaoperatorsdk.operator.processing.event.ResourceID;
16+
import io.javaoperatorsdk.operator.processing.event.source.PrimaryToSecondaryMapper;
17+
18+
import static io.javaoperatorsdk.operator.sample.Utils.configMapName;
19+
import static io.javaoperatorsdk.operator.sample.Utils.deploymentName;
20+
21+
// this annotation only activates when using managed dependents and is not otherwise needed
22+
@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
23+
class ConfigMapDependentResource extends CRUKubernetesDependentResource<ConfigMap, WebPage>
24+
implements PrimaryToSecondaryMapper<WebPage> {
25+
26+
private static final Logger log = LoggerFactory.getLogger(ConfigMapDependentResource.class);
27+
28+
public ConfigMapDependentResource() {
29+
super(ConfigMap.class);
30+
}
31+
32+
@Override
33+
protected ConfigMap desired(WebPage webPage, Context<WebPage> context) {
34+
Map<String, String> data = new HashMap<>();
35+
data.put("index.html", webPage.getSpec().getHtml());
36+
return new ConfigMapBuilder()
37+
.withMetadata(
38+
new ObjectMetaBuilder()
39+
.withName(configMapName(webPage))
40+
.withNamespace(webPage.getMetadata().getNamespace())
41+
.build())
42+
.withData(data)
43+
.build();
44+
}
45+
46+
@Override
47+
public ConfigMap update(ConfigMap actual, ConfigMap target, WebPage primary,
48+
Context<WebPage> context) {
49+
var res = super.update(actual, target, primary, context);
50+
var ns = actual.getMetadata().getNamespace();
51+
log.info("Restarting pods because HTML has changed in {}",
52+
ns);
53+
getKubernetesClient()
54+
.pods()
55+
.inNamespace(ns)
56+
.withLabel("app", deploymentName(primary))
57+
.delete();
58+
return res;
59+
}
60+
61+
@Override
62+
public ResourceID associatedSecondaryID(WebPage primary) {
63+
return new ResourceID(configMapName(primary), primary.getMetadata().getNamespace());
64+
}
65+
}
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.ConfigMapVolumeSourceBuilder;
4+
import io.fabric8.kubernetes.api.model.apps.Deployment;
5+
import io.javaoperatorsdk.operator.api.reconciler.Context;
6+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
7+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
8+
9+
import static io.javaoperatorsdk.operator.ReconcilerUtils.loadYaml;
10+
import static io.javaoperatorsdk.operator.sample.Utils.configMapName;
11+
import static io.javaoperatorsdk.operator.sample.Utils.deploymentName;
12+
13+
// this annotation only activates when using managed dependents and is not otherwise needed
14+
@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
15+
class DeploymentDependentResource extends CRUDKubernetesDependentResource<Deployment, WebPage> {
16+
17+
public DeploymentDependentResource() {
18+
super(Deployment.class);
19+
}
20+
21+
@Override
22+
protected Deployment desired(WebPage webPage, Context<WebPage> context) {
23+
var deploymentName = deploymentName(webPage);
24+
Deployment deployment = loadYaml(Deployment.class, getClass(), "deployment.yaml");
25+
deployment.getMetadata().setName(deploymentName);
26+
deployment.getMetadata().setNamespace(webPage.getMetadata().getNamespace());
27+
deployment.getSpec().getSelector().getMatchLabels().put("app", deploymentName);
28+
29+
deployment
30+
.getSpec()
31+
.getTemplate()
32+
.getMetadata()
33+
.getLabels()
34+
.put("app", deploymentName);
35+
deployment
36+
.getSpec()
37+
.getTemplate()
38+
.getSpec()
39+
.getVolumes()
40+
.get(0)
41+
.setConfigMap(
42+
new ConfigMapVolumeSourceBuilder().withName(configMapName(webPage)).build());
43+
return deployment;
44+
}
45+
}

sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/ErrorSimulationException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package io.javaoperatorsdk.operator.sample;
22

3-
public class ErrorSimulationException extends RuntimeException {
3+
public class ErrorSimulationException extends Exception {
44

55
public ErrorSimulationException(String message) {
66
super(message);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import io.fabric8.kubernetes.api.model.Service;
7+
import io.javaoperatorsdk.operator.api.reconciler.Context;
8+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
9+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
10+
11+
import static io.javaoperatorsdk.operator.ReconcilerUtils.loadYaml;
12+
import static io.javaoperatorsdk.operator.sample.Utils.deploymentName;
13+
import static io.javaoperatorsdk.operator.sample.Utils.serviceName;
14+
15+
// this annotation only activates when using managed dependents and is not otherwise needed
16+
@KubernetesDependent(labelSelector = WebPageManagedDependentsReconciler.SELECTOR)
17+
class ServiceDependentResource extends CRUDKubernetesDependentResource<Service, WebPage> {
18+
19+
public ServiceDependentResource() {
20+
super(Service.class);
21+
}
22+
23+
@Override
24+
protected Service desired(WebPage webPage, Context<WebPage> context) {
25+
Service service = loadYaml(Service.class, getClass(), "service.yaml");
26+
service.getMetadata().setName(serviceName(webPage));
27+
service.getMetadata().setNamespace(webPage.getMetadata().getNamespace());
28+
Map<String, String> labels = new HashMap<>();
29+
labels.put("app", deploymentName(webPage));
30+
service.getSpec().setSelector(labels);
31+
return service;
32+
}
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package io.javaoperatorsdk.operator.sample;
2+
3+
import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusUpdateControl;
4+
5+
public class Utils {
6+
7+
private Utils() {}
8+
9+
static WebPageStatus createStatus(String configMapName) {
10+
WebPageStatus status = new WebPageStatus();
11+
status.setHtmlConfigMap(configMapName);
12+
status.setAreWeGood(true);
13+
status.setErrorMessage(null);
14+
return status;
15+
}
16+
17+
static String configMapName(WebPage nginx) {
18+
return nginx.getMetadata().getName() + "-html";
19+
}
20+
21+
static String deploymentName(WebPage nginx) {
22+
return nginx.getMetadata().getName();
23+
}
24+
25+
static String serviceName(WebPage webPage) {
26+
return webPage.getMetadata().getName();
27+
}
28+
29+
static ErrorStatusUpdateControl<WebPage> handleError(WebPage resource, Exception e) {
30+
resource.getStatus().setErrorMessage("Error: " + e.getMessage());
31+
return ErrorStatusUpdateControl.updateStatus(resource);
32+
}
33+
34+
static void simulateErrorIfRequested(WebPage webPage) throws ErrorSimulationException {
35+
if (webPage.getSpec().getHtml().contains("error")) {
36+
// special case just to showcase error if doing a demo
37+
throw new ErrorSimulationException("Simulating error");
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)