Skip to content

Commit 755c404

Browse files
committed
Annotation config + controller IT
Signed-off-by: Attila Mészáros <[email protected]>
1 parent 2d43aff commit 755c404

File tree

5 files changed

+122
-2
lines changed

5 files changed

+122
-2
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.javaoperatorsdk.operator.api.config.informer;
2+
3+
public @interface Field {
4+
5+
String field();
6+
7+
String value();
8+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,10 @@
113113
* the informer cache.
114114
*/
115115
long informerListLimit() default NO_LONG_VALUE_SET;
116+
117+
/** Field selector for informer, for matching field with the value: field=value; */
118+
Field[] withFields() default {};
119+
120+
/** Negated field selector for informer, for Non-matching field with the value: field!=value; */
121+
Field[] withoutFields() default {};
116122
}

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

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

33
import java.util.AbstractMap;
44
import java.util.ArrayList;
5+
import java.util.Arrays;
56
import java.util.Collection;
67
import java.util.Collections;
78
import java.util.HashMap;
@@ -55,7 +56,9 @@ protected InformerConfiguration(
5556
OnDeleteFilter<? super R> onDeleteFilter,
5657
GenericFilter<? super R> genericFilter,
5758
ItemStore<R> itemStore,
58-
Long informerListLimit) {
59+
Long informerListLimit,
60+
Map<String, String> withFields,
61+
List<AbstractMap.SimpleEntry<String, String>> withoutFields) {
5962
this(resourceClass);
6063
this.name = name;
6164
this.namespaces = namespaces;
@@ -67,6 +70,8 @@ protected InformerConfiguration(
6770
this.genericFilter = genericFilter;
6871
this.itemStore = itemStore;
6972
this.informerListLimit = informerListLimit;
73+
this.withFields = withFields;
74+
this.withoutFields = withoutFields;
7075
}
7176

7277
private InformerConfiguration(Class<R> resourceClass) {
@@ -100,7 +105,9 @@ public static <R extends HasMetadata> InformerConfiguration<R>.Builder builder(
100105
original.onDeleteFilter,
101106
original.genericFilter,
102107
original.itemStore,
103-
original.informerListLimit)
108+
original.informerListLimit,
109+
original.withFields,
110+
original.withoutFields)
104111
.builder;
105112
}
106113

@@ -344,6 +351,10 @@ public InformerConfiguration<R>.Builder initFromAnnotation(
344351
final var informerListLimit =
345352
informerListLimitValue == Constants.NO_LONG_VALUE_SET ? null : informerListLimitValue;
346353
withInformerListLimit(informerListLimit);
354+
355+
Arrays.stream(informerConfig.withFields()).forEach(f -> withField(f.field(), f.value()));
356+
Arrays.stream(informerConfig.withoutFields())
357+
.forEach(f -> withoutField(f.field(), f.value()));
347358
}
348359
return this;
349360
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.javaoperatorsdk.operator.baseapi.fieldselector;
2+
3+
import java.time.Duration;
4+
import java.util.Map;
5+
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.RegisterExtension;
8+
9+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
10+
import io.fabric8.kubernetes.api.model.SecretBuilder;
11+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
12+
13+
import static io.javaoperatorsdk.operator.baseapi.fieldselector.FieldSelectorTestReconciler.MY_SECRET_TYPE;
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
import static org.awaitility.Awaitility.await;
16+
17+
class FieldSelectorIT {
18+
19+
public static final String TEST_1 = "test1";
20+
public static final String TEST_2 = "test2";
21+
22+
@RegisterExtension
23+
LocallyRunOperatorExtension extension =
24+
LocallyRunOperatorExtension.builder()
25+
.withReconciler(new FieldSelectorTestReconciler())
26+
.build();
27+
28+
@Test
29+
void filtersCustomResourceByLabel() {
30+
31+
extension.create(
32+
new SecretBuilder()
33+
.withMetadata(new ObjectMetaBuilder().withName(TEST_1).build())
34+
.withStringData(Map.of("key1", "value1"))
35+
.withType(MY_SECRET_TYPE)
36+
.build());
37+
38+
extension.create(
39+
new SecretBuilder()
40+
.withMetadata(new ObjectMetaBuilder().withName(TEST_2).build())
41+
.withStringData(Map.of("key2", "value2"))
42+
.build());
43+
44+
await()
45+
.pollDelay(Duration.ofMillis(150))
46+
.untilAsserted(
47+
() -> {
48+
var r = extension.getReconcilerOfType(FieldSelectorTestReconciler.class);
49+
assertThat(r.getReconciledSecrets()).containsExactly(TEST_1);
50+
});
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.javaoperatorsdk.operator.baseapi.fieldselector;
2+
3+
import java.util.Collections;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
8+
import io.fabric8.kubernetes.api.model.Secret;
9+
import io.javaoperatorsdk.operator.api.config.informer.Field;
10+
import io.javaoperatorsdk.operator.api.config.informer.Informer;
11+
import io.javaoperatorsdk.operator.api.reconciler.Context;
12+
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
13+
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
14+
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
15+
import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider;
16+
17+
@ControllerConfiguration(
18+
informer =
19+
@Informer(
20+
withFields =
21+
@Field(field = "type", value = FieldSelectorTestReconciler.MY_SECRET_TYPE)))
22+
public class FieldSelectorTestReconciler implements Reconciler<Secret>, TestExecutionInfoProvider {
23+
24+
public static final String MY_SECRET_TYPE = "my-secret-type";
25+
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
26+
27+
private Set<String> reconciledSecrets = Collections.synchronizedSet(new HashSet<>());
28+
29+
@Override
30+
public UpdateControl<Secret> reconcile(Secret resource, Context<Secret> context) {
31+
reconciledSecrets.add(resource.getMetadata().getName());
32+
numberOfExecutions.addAndGet(1);
33+
return UpdateControl.noUpdate();
34+
}
35+
36+
public int getNumberOfExecutions() {
37+
return numberOfExecutions.get();
38+
}
39+
40+
public Set<String> getReconciledSecrets() {
41+
return reconciledSecrets;
42+
}
43+
}

0 commit comments

Comments
 (0)