Skip to content
Closed
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
4 changes: 2 additions & 2 deletions bootstrapper-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>bootstrapper</artifactId>
Expand All @@ -32,7 +32,7 @@

<properties>
<maven-plugin-annotations.version>3.15.2</maven-plugin-annotations.version>
<maven-plugin-api.version>3.9.16</maven-plugin-api.version>
<maven-plugin-api.version>3.9.15</maven-plugin-api.version>
<templating-maven-plugin.version>3.1.0</templating-maven-plugin.version>
<maven-plugin-plugin.version>3.15.2</maven-plugin-plugin.version>
</properties>
Expand Down
2 changes: 1 addition & 1 deletion caffeine-bounded-cache-support/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>caffeine-bounded-cache-support</artifactId>
Expand Down
3 changes: 3 additions & 0 deletions docs/content/en/docs/documentation/error-handling-retries.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ these features:

2. In case an exception is thrown, a retry is initiated. However, if an event is received
meanwhile, it will be reconciled instantly, and this execution won't count as a retry attempt.
If that event-triggered reconciliation also fails inside the current retry window, the
existing retry deadline is preserved rather than reset — the failure does not advance the
retry counter unless the original deadline is imminent.
3. If the retry limit is reached (so no more automatic retry would happen), but a new event
received, the reconciliation will still happen, but won't reset the retry, and will still be
marked as the last attempt in the retry info. The point (1) still holds - thus successful reconciliation will reset the retry - but no retry will happen in case of an error.
Expand Down
8 changes: 8 additions & 0 deletions docs/content/en/docs/documentation/eventing.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ rare corner cases. Returning an empty set means that the mapper considered the s
resource event as irrelevant and the SDK will thus not trigger a reconciliation of the primary
resource in that situation.

On an update event, the SDK calls `toPrimaryResourceIDs` for **both the old and the new version**
of the secondary resource. This way it can reconcile not only the primaries that the secondary
currently maps to, but also those it previously mapped to and no longer does. So when a reference
changes — including when only a subset of the referenced primaries changes — both the newly
referenced and the dropped primaries are reconciled, and a dropped primary can revert to its
default state. Because the mapper can be invoked for an older version of a resource, keep your
implementation a pure function of the resource passed to it.

Adding a `SecondaryToPrimaryMapper` is typically sufficient when there is a one-to-many relationship
between primary and secondary resources. The secondary resources can be mapped to its primary
owner, and this is enough information to also get these secondary resources from the `Context`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ All controller-level keys are prefixed with `josdk.controller.<controller-name>.
| `josdk.controller.<name>.finalizer` | `String` | Finalizer string added to managed resources |
| `josdk.controller.<name>.generation-aware` | `Boolean` | Skip reconciliation when the resource generation has not changed |
| `josdk.controller.<name>.label-selector` | `String` | Label selector to filter watched resources |
| `josdk.controller.<name>.shard-selector` | `String` | Shard selector to filter watched resources for sharding across operator replicas |
| `josdk.controller.<name>.max-reconciliation-interval` | `Duration` | Maximum interval between reconciliations even without events |
| `josdk.controller.<name>.field-manager` | `String` | Field manager name used for SSA operations |
| `josdk.controller.<name>.trigger-reconciler-on-all-events` | `Boolean` | Trigger reconciliation on every event, not only meaningful changes |
Expand All @@ -333,6 +334,7 @@ All controller-level keys are prefixed with `josdk.controller.<controller-name>.
| Key | Type | Description |
|---|---|---|
| `josdk.controller.<name>.informer.label-selector` | `String` | Label selector for the primary resource informer (alias for `label-selector`) |
| `josdk.controller.<name>.informer.shard-selector` | `String` | Shard selector for the primary resource informer (alias for `shard-selector`) |
| `josdk.controller.<name>.informer.list-limit` | `Long` | Page size for paginated informer list requests; omit for no pagination |

#### Retry
Expand Down
2 changes: 1 addition & 1 deletion micrometer-support/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>micrometer-support</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion migration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>migration</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion operator-framework-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<groupId>io.javaoperatorsdk</groupId>
<artifactId>operator-framework-bom</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Operator SDK - Bill of Materials</name>
<description>Java SDK for implementing Kubernetes operators</description>
Expand Down
2 changes: 1 addition & 1 deletion operator-framework-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.javaoperatorsdk</groupId>
<artifactId>java-operator-sdk</artifactId>
<version>5.3.6-SNAPSHOT</version>
<version>999-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ private <P extends HasMetadata> ResolvedControllerConfiguration<P> controllerCon
var triggerReconcilerOnAllEvents =
annotation != null && annotation.triggerReconcilerOnAllEvents();

var defaultFilters = annotation == null || annotation.defaultFilters();

InformerConfiguration<P> informerConfig =
InformerConfiguration.builder(resourceClass)
.initFromAnnotation(annotation != null ? annotation.informer() : null, context)
Expand All @@ -341,7 +343,8 @@ private <P extends HasMetadata> ResolvedControllerConfiguration<P> controllerCon
dependentFieldManager,
this,
informerConfig,
triggerReconcilerOnAllEvents);
triggerReconcilerOnAllEvents,
defaultFilters);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,8 @@ default boolean triggerReconcilerOnAllEvent() {
default boolean triggerReconcilerOnAllEvents() {
return false;
}

default boolean isDefaultFilters() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class ControllerConfigurationOverrider<R extends HasMetadata> {
private Map<DependentResourceSpec, Object> configurations;
private final InformerConfiguration<R>.Builder config;
private boolean triggerReconcilerOnAllEvents;
private boolean defaultFilters;

private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
this.finalizer = original.getFinalizerName();
Expand All @@ -59,6 +60,7 @@ private ControllerConfigurationOverrider(ControllerConfiguration<R> original) {
this.name = original.getName();
this.fieldManager = original.fieldManager();
this.triggerReconcilerOnAllEvents = original.triggerReconcilerOnAllEvents();
this.defaultFilters = original.isDefaultFilters();
}

public ControllerConfigurationOverrider<R> withFinalizer(String finalizer) {
Expand Down Expand Up @@ -134,6 +136,11 @@ public ControllerConfigurationOverrider<R> withLabelSelector(String labelSelecto
return this;
}

public ControllerConfigurationOverrider<R> withShardSelector(String shardSelector) {
config.withShardSelector(shardSelector);
return this;
}

public ControllerConfigurationOverrider<R> withReconciliationMaxInterval(
Duration reconciliationMaxInterval) {
this.reconciliationMaxInterval = reconciliationMaxInterval;
Expand Down Expand Up @@ -186,6 +193,11 @@ public ControllerConfigurationOverrider<R> withTriggerReconcilerOnAllEvents(
return this;
}

public ControllerConfigurationOverrider<R> withDefaultFilters(boolean defaultFilters) {
this.defaultFilters = defaultFilters;
return this;
}

/**
* Sets a max page size limit when starting the informer. This will result in pagination while
* populating the cache. This means that longer lists will take multiple requests to fetch. See
Expand Down Expand Up @@ -231,6 +243,7 @@ public ControllerConfiguration<R> build() {
original.getConfigurationService(),
config.buildForController(),
triggerReconcilerOnAllEvents,
defaultFilters,
original.getWorkflowSpec().orElse(null));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class ResolvedControllerConfiguration<P extends HasMetadata>
private final ConfigurationService configurationService;
private final String fieldManager;
private final boolean triggerReconcilerOnAllEvents;
private final boolean defaultFilters;
private WorkflowSpec workflowSpec;

public ResolvedControllerConfiguration(ControllerConfiguration<P> other) {
Expand All @@ -61,6 +62,7 @@ public ResolvedControllerConfiguration(ControllerConfiguration<P> other) {
other.getConfigurationService(),
other.getInformerConfig(),
other.triggerReconcilerOnAllEvents(),
other.isDefaultFilters(),
other.getWorkflowSpec().orElse(null));
}

Expand All @@ -77,6 +79,7 @@ public ResolvedControllerConfiguration(
ConfigurationService configurationService,
InformerConfiguration<P> informerConfig,
boolean triggerReconcilerOnAllEvents,
boolean defaultFilters,
WorkflowSpec workflowSpec) {
this(
name,
Expand All @@ -90,7 +93,8 @@ public ResolvedControllerConfiguration(
fieldManager,
configurationService,
informerConfig,
triggerReconcilerOnAllEvents);
triggerReconcilerOnAllEvents,
defaultFilters);
setWorkflowSpec(workflowSpec);
}

Expand All @@ -106,7 +110,8 @@ protected ResolvedControllerConfiguration(
String fieldManager,
ConfigurationService configurationService,
InformerConfiguration<P> informerConfig,
boolean triggerReconcilerOnAllEvents) {
boolean triggerReconcilerOnAllEvents,
boolean defaultFilters) {
this.informerConfig = informerConfig;
this.configurationService = configurationService;
this.name = ControllerConfiguration.ensureValidName(name, associatedReconcilerClassName);
Expand All @@ -120,6 +125,7 @@ protected ResolvedControllerConfiguration(
ControllerConfiguration.ensureValidFinalizerName(finalizer, getResourceTypeName());
this.fieldManager = fieldManager;
this.triggerReconcilerOnAllEvents = triggerReconcilerOnAllEvents;
this.defaultFilters = defaultFilters;
}

protected ResolvedControllerConfiguration(
Expand All @@ -139,7 +145,8 @@ protected ResolvedControllerConfiguration(
null,
configurationService,
InformerConfiguration.builder(resourceClass).buildForController(),
false);
false,
true);
}

@Override
Expand Down Expand Up @@ -234,4 +241,9 @@ public String fieldManager() {
public boolean triggerReconcilerOnAllEvents() {
return triggerReconcilerOnAllEvents;
}

@Override
public boolean isDefaultFilters() {
return defaultFilters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@
*/
String labelSelector() default NO_VALUE_SET;

/**
* Optional shard selector used to restrict the set of resources the associated informer will act
* upon to a single shard, typically when the same workload is split across several operator
* instances. Just like {@link #labelSelector()} it is expressed as a label selector and can be
* made of multiple comma separated requirements that act as a logical AND operator. When both a
* label selector and a shard selector are set, the resulting informer only watches resources
* matching both (the two selectors are combined with a logical AND).
*
* @return the shard selector
*/
String shardSelector() default NO_VALUE_SET;

/**
* Optional {@link OnAddFilter} to filter add events sent to the associated informer
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class InformerConfiguration<R extends HasMetadata> {
private Set<String> namespaces;
private Boolean followControllerNamespaceChanges;
private String labelSelector;
private String shardSelector;
private OnAddFilter<? super R> onAddFilter;
private OnUpdateFilter<? super R> onUpdateFilter;
private OnDeleteFilter<? super R> onDeleteFilter;
Expand All @@ -62,6 +63,7 @@ protected InformerConfiguration(
Set<String> namespaces,
boolean followControllerNamespaceChanges,
String labelSelector,
String shardSelector,
OnAddFilter<? super R> onAddFilter,
OnUpdateFilter<? super R> onUpdateFilter,
OnDeleteFilter<? super R> onDeleteFilter,
Expand All @@ -77,6 +79,7 @@ protected InformerConfiguration(
this.namespaces = namespaces;
this.followControllerNamespaceChanges = followControllerNamespaceChanges;
this.labelSelector = labelSelector;
this.shardSelector = shardSelector;
this.onAddFilter = onAddFilter;
this.onUpdateFilter = onUpdateFilter;
this.onDeleteFilter = onDeleteFilter;
Expand Down Expand Up @@ -113,6 +116,7 @@ public static <R extends HasMetadata> InformerConfiguration<R>.Builder builder(
original.namespaces,
original.followControllerNamespaceChanges,
original.labelSelector,
original.shardSelector,
original.onAddFilter,
original.onUpdateFilter,
original.onDeleteFilter,
Expand All @@ -125,11 +129,6 @@ public static <R extends HasMetadata> InformerConfiguration<R>.Builder builder(
.builder;
}

public static String ensureValidLabelSelector(String labelSelector) {
// might want to implement validation here?
return labelSelector;
}

public static boolean allNamespacesWatched(Set<String> namespaces) {
failIfNotValid(namespaces);
return DEFAULT_NAMESPACES_SET.equals(namespaces);
Expand Down Expand Up @@ -251,6 +250,20 @@ public String getLabelSelector() {
return labelSelector;
}

/**
* Retrieves the shard selector that is used, in addition to the {@link #getLabelSelector() label
* selector}, to restrict which resources are actually watched by the associated informer.
* Typically used to assign a subset (shard) of the resources to a given operator instance. It is
* expressed using the same syntax as a label selector. See the official documentation on the <a
* href="https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/">topic</a> for
* more details on syntax.
*
* @return the shard selector filtering watched resources
*/
public String getShardSelector() {
return shardSelector;
}

public OnAddFilter<? super R> getOnAddFilter() {
return onAddFilter;
}
Expand Down Expand Up @@ -353,6 +366,11 @@ public InformerConfiguration<R>.Builder initFromAnnotation(
var labelSelector = Constants.NO_VALUE_SET.equals(fromAnnotation) ? null : fromAnnotation;
withLabelSelector(labelSelector);

final var shardFromAnnotation = informerConfig.shardSelector();
var shardSelector =
Constants.NO_VALUE_SET.equals(shardFromAnnotation) ? null : shardFromAnnotation;
withShardSelector(shardSelector);

withOnAddFilter(
Utils.instantiate(informerConfig.onAddFilter(), OnAddFilter.class, context));

Expand Down Expand Up @@ -442,7 +460,12 @@ public Builder withFollowControllerNamespacesChanges(boolean followChanges) {
}

public Builder withLabelSelector(String labelSelector) {
InformerConfiguration.this.labelSelector = ensureValidLabelSelector(labelSelector);
InformerConfiguration.this.labelSelector = labelSelector;
return this;
}

public Builder withShardSelector(String shardSelector) {
InformerConfiguration.this.shardSelector = shardSelector;
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ public Builder<R> withLabelSelector(String labelSelector) {
return this;
}

public Builder<R> withShardSelector(String shardSelector) {
config.withShardSelector(shardSelector);
return this;
}

public Builder<R> withOnAddFilter(OnAddFilter<? super R> onAddFilter) {
config.withOnAddFilter(onAddFilter);
return this;
Expand Down Expand Up @@ -308,6 +313,7 @@ public void updateFrom(InformerConfiguration<R> informerConfig) {
.withFollowControllerNamespacesChanges(
informerConfig.getFollowControllerNamespaceChanges())
.withLabelSelector(informerConfig.getLabelSelector())
.withShardSelector(informerConfig.getShardSelector())
.withItemStore(informerConfig.getItemStore())
.withOnAddFilter(informerConfig.getOnAddFilter())
.withOnUpdateFilter(informerConfig.getOnUpdateFilter())
Expand Down
Loading
Loading