Skip to content
Draft

wip #3001

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.javaoperatorsdk.operator.processing;

import io.fabric8.kubernetes.api.model.HasMetadata;
import io.javaoperatorsdk.operator.MockKubernetesClient;
import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
import io.javaoperatorsdk.operator.api.config.MockControllerConfiguration;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MockController {
public static <P extends HasMetadata> Controller<P> mockController(Class<P> primaryClass) {
Reconciler<P> reconciler = mock(Reconciler.class);
final var conf = MockControllerConfiguration.forResource(primaryClass);
final var configurationService = new BaseConfigurationService();
when(conf.getConfigurationService()).thenReturn(configurationService);
return new Controller<>(reconciler, conf, MockKubernetesClient.client(primaryClass));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.javaoperatorsdk.operator.dependent.desiredonce;

import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;

@Group("io.josdk")
@Version("v1")
public class DesiredOnce extends CustomResource<DesiredOnceSpec, Void> {
static final String KEY = "key";
static final String VALUE = "value";

public DesiredOnce() {}

public DesiredOnce(String value) {
this.spec = new DesiredOnceSpec(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.javaoperatorsdk.operator.dependent.desiredonce;

import java.util.Map;

import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
import io.javaoperatorsdk.operator.api.config.informer.Informer;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;

@KubernetesDependent(informer = @Informer(labelSelector = "desiredonce=true"))
public class DesiredOnceDependent extends CRUDKubernetesDependentResource<ConfigMap, DesiredOnce> {
private boolean desiredAlreadyCalled;

@Override
protected ConfigMap desired(DesiredOnce primary, Context<DesiredOnce> context) {
if (desiredAlreadyCalled) {
throw new IllegalStateException("desired should have only been called once");
}
desiredAlreadyCalled = true;
return new ConfigMapBuilder()
.editOrNewMetadata()
.withName(getName(primary))
.withNamespace(primary.getMetadata().getNamespace())
.withLabels(Map.of("desiredonce", "true"))
.endMetadata()
.addToData(DesiredOnce.KEY, primary.getSpec().value())
.build();
}

static String getName(DesiredOnce primary) {
return primary.getMetadata().getName() + "cm";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.javaoperatorsdk.operator.dependent.desiredonce;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;

import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

class DesiredOnceIT {

@RegisterExtension
LocallyRunOperatorExtension operator =
LocallyRunOperatorExtension.builder().withReconciler(DesiredOnceReconciler.class).build();

@Test
public void checkThatDesiredIsOnlyCalledOncePerReconciliation() {
var resource = operator.create(testResource());

await()
.untilAsserted(
() -> {
var cm = operator.get(ConfigMap.class, DesiredOnceDependent.getName(resource));
assertThat(cm).isNotNull();
assertThat(cm.getData().get(DesiredOnce.KEY)).isEqualTo(DesiredOnce.VALUE);
});
}

private DesiredOnce testResource() {
var res = new DesiredOnce(DesiredOnce.VALUE);
res.setMetadata(
new ObjectMetaBuilder().withName("test").withNamespace(operator.getNamespace()).build());
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.javaoperatorsdk.operator.dependent.desiredonce;

import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
import io.javaoperatorsdk.operator.api.reconciler.Workflow;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;

@Workflow(dependents = @Dependent(type = DesiredOnceDependent.class))
public class DesiredOnceReconciler implements Reconciler<DesiredOnce> {
@Override
public UpdateControl<DesiredOnce> reconcile(DesiredOnce resource, Context<DesiredOnce> context)
throws Exception {
return UpdateControl.noUpdate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.javaoperatorsdk.operator.dependent.desiredonce;

public record DesiredOnceSpec(String value) {}
Loading