Skip to content

Commit 580523c

Browse files
committed
docs
1 parent ec37025 commit 580523c

File tree

7 files changed

+79
-8
lines changed

7 files changed

+79
-8
lines changed

docs/documentation/features.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,67 @@ following attributes are available in most parts of reconciliation logic and dur
458458

459459
For more information about MDC see this [link](https://www.baeldung.com/mdc-in-log4j-2-logback).
460460

461+
## Dynamically Adjusting Target Namespaces
462+
463+
A controller can be configured to watch a set of namespaces (not only a single namespace or the whole cluster).
464+
The framework supports to dynamically change the list of these namespaces while the operator is running.
465+
When a reconciler is registered the
466+
[`RegisteredController`](https://github.com/java-operator-sdk/java-operator-sdk/blob/ec37025a15046d8f409c77616110024bf32c3416/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/RegisteredController.java#L5-L5)
467+
is returned, which provides the related methods. These namespaces are meant to be changed when the operator is already
468+
running.
469+
470+
In a real life scenario usually the list of the target namespaces configured in `ConfigMap` or other input,
471+
this part however is out of the scope of the framework. So in case you want to use a `ConfigMap` and react to change
472+
of it, registering an Informer and calling the `RegisteredController` is up to the developer to implement.
473+
474+
```java
475+
476+
public static void main(String[] args) throws IOException {
477+
KubernetesClient client = new DefaultKubernetesClient();
478+
Operator operator = new Operator(client);
479+
RegisteredController registeredController = operator.register(new WebPageReconciler(client));
480+
operator.installShutdownHook();
481+
operator.start();
482+
483+
// call registeredController further while operator is running
484+
}
485+
486+
```
487+
488+
If a target namespaces change for a controller, it might be desirable to change the target namespaces of registered
489+
`InformerEventSource`-s. In order to express this, the InformerEventSource needs to be configured to
490+
`followControllerNamespaceChanges`, this the related method in `InformerConfiguration` should return `true`:
491+
492+
```java
493+
494+
@ControllerConfiguration
495+
public class MyReconciler
496+
implements Reconciler<TestCustomResource>, EventSourceInitializer<TestCustomResource>{
497+
498+
@Override
499+
public Map<String, EventSource> prepareEventSources(
500+
EventSourceContext<ChangeNamespaceTestCustomResource> context) {
501+
502+
InformerEventSource<ConfigMap, TestCustomResource> configMapES =
503+
new InformerEventSource<>(InformerConfiguration.from(ConfigMap.class)
504+
.setAndFollowControllerNamespaceChanges(context)
505+
.build(), context);
506+
507+
return EventSourceInitializer.nameEventSources(configMapES);
508+
}
509+
510+
}
511+
```
512+
513+
As seen in the above code snippet, the informer will have the initial namespaces inherited from controller, but
514+
also will adjust the target namespaces if it changes for the controller.
515+
516+
See also the [integration test](https://github.com/java-operator-sdk/java-operator-sdk/blob/ec37025a15046d8f409c77616110024bf32c3416/operator-framework/src/test/java/io/javaoperatorsdk/operator/sample/changenamespace/ChangeNamespaceTestReconciler.java)
517+
for this feature.
518+
461519
## Monitoring with Micrometer
462520

463-
## Automatic generation of CRDs
521+
## Automatic Generation of CRDs
464522

465523
Note that this is feature of [Fabric8 Kubernetes Client](https://github.com/fabric8io/kubernetes-client) not the JOSDK.
466524
But it's worth to mention here.

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/RegisteredController.java

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

55
public interface RegisteredController {
66

7+
/**
8+
* If the controller and possibly registered
9+
* {@link io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource}
10+
* watches a set of namespaces this set can be adjusted dynamically, this when the operator is
11+
* running.
12+
*
13+
* @param namespaces target namespaces to watch
14+
*/
715
void changeNamespaces(Set<String> namespaces);
816

917
void changeNamespaces(String... namespaces);

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected DefaultInformerConfiguration(String labelSelector,
3232
Mappers.fromOwnerReference());
3333
}
3434

35-
public boolean isInheritControllerNamespacesOnChange() {
35+
public boolean followControllerNamespaceChanges() {
3636
return followControllerNamespaceChanges;
3737
}
3838

@@ -42,7 +42,13 @@ public SecondaryToPrimaryMapper<R> getSecondaryToPrimaryMapper() {
4242

4343
}
4444

45-
boolean isInheritControllerNamespacesOnChange();
45+
/**
46+
* Used in case the watched namespaces are changed dynamically, thus when operator is running (See
47+
* {@link io.javaoperatorsdk.operator.RegisteredController}). If true, changing the target
48+
* namespaces of a controller would result to change target namespaces for the
49+
* InformerEventSource.
50+
*/
51+
boolean followControllerNamespaceChanges();
4652

4753
SecondaryToPrimaryMapper<R> getSecondaryToPrimaryMapper();
4854

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public void changeNamespaces(Set<String> namespaces) {
149149
getRegisteredEventSources().forEach(es -> {
150150
if (es instanceof InformerEventSource) {
151151
InformerEventSource ies = (InformerEventSource) es;
152-
if (ies.getConfiguration().isInheritControllerNamespacesOnChange()) {
152+
if (ies.getConfiguration().followControllerNamespaceChanges()) {
153153
ies.changeNamespaces(namespaces);
154154
}
155155
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerEventSource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ public synchronized void cleanupOnCreateOrUpdateEventFiltering(ResourceID resour
268268

269269
@Override
270270
public void changeNamespaces(Set<String> namespaces) {
271-
if (!configuration.isInheritControllerNamespacesOnChange()) {
271+
if (!configuration.followControllerNamespaceChanges()) {
272272
throw new IllegalStateException(
273273
"InformerEventSource is not configured to change inherit namespaces.");
274274
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/source/informer/InformerManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public class InformerManager<T extends HasMetadata, C extends ResourceConfigurat
3737
private C configuration;
3838
private MixedOperation<T, KubernetesResourceList<T>, Resource<T>> client;
3939
private ResourceEventHandler<T> eventHandler;
40-
private Map<String, Function<T, List<String>>> indexers = new HashMap<>();
40+
private final Map<String, Function<T, List<String>>> indexers = new HashMap<>();
4141

4242
@Override
4343
public void start() throws OperatorException {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
@SuppressWarnings({"rawtypes", "unchecked"})
2929
class EventSourceManagerTest {
3030

31-
private final EventProcessor eventProcessor = mock(EventProcessor.class);
3231
private final EventSourceManager eventSourceManager = initManager();
3332

3433
@Test
@@ -151,7 +150,7 @@ void changesNamespacesOnControllerAndInformerEventSources() {
151150
var manager = new EventSourceManager(controller, eventSources);
152151

153152
InformerConfiguration informerConfigurationMock = mock(InformerConfiguration.class);
154-
when(informerConfigurationMock.isInheritControllerNamespacesOnChange()).thenReturn(true);
153+
when(informerConfigurationMock.followControllerNamespaceChanges()).thenReturn(true);
155154
InformerEventSource informerEventSource = mock(InformerEventSource.class);
156155
when(informerEventSource.resourceType()).thenReturn(TestCustomResource.class);
157156
when(informerEventSource.getConfiguration()).thenReturn(informerConfigurationMock);

0 commit comments

Comments
 (0)