Skip to content

feat: integration test for cross reference dependent resource #1203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -36,7 +36,7 @@ void overridingNSShouldPreserveUntouchedDependents() {
// override the NS
final var namespace = "some-ns";
final var externalDRName =
DependentResource.defaultNameFor(NamedDependentReconciler.ExternalDependendResource.class);
DependentResource.defaultNameFor(NamedDependentReconciler.ExternalDependentResource.class);
final var stringConfig = "some String configuration";
configuration = ControllerConfigurationOverrider.override(configuration)
.settingNamespace(namespace)
Expand All @@ -54,7 +54,7 @@ void overridingNSShouldPreserveUntouchedDependents() {

@ControllerConfiguration(dependents = {
@Dependent(type = NamedDependentReconciler.NamedDependentResource.class),
@Dependent(type = NamedDependentReconciler.ExternalDependendResource.class)
@Dependent(type = NamedDependentReconciler.ExternalDependentResource.class)
})
private static class NamedDependentReconciler implements Reconciler<ConfigMap> {

Expand All @@ -72,7 +72,7 @@ public NamedDependentResource() {
}
}

private static class ExternalDependendResource implements DependentResource<Object, ConfigMap> {
private static class ExternalDependentResource implements DependentResource<Object, ConfigMap> {

@Override
public ReconcileResult<Object> reconcile(ConfigMap primary, Context<ConfigMap> context) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.javaoperatorsdk.operator;

import java.time.Duration;

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.fabric8.kubernetes.api.model.Secret;
import io.javaoperatorsdk.operator.junit.LocalOperatorExtension;
import io.javaoperatorsdk.operator.sample.dependentresourcecrossref.DependentResourceCrossRefReconciler;
import io.javaoperatorsdk.operator.sample.dependentresourcecrossref.DependentResourceCrossRefResource;

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

class DependentResourceCrossRefIT {

public static final String TEST_RESOURCE_NAME = "test";
public static final int EXECUTION_NUMBER = 500;

@RegisterExtension
LocalOperatorExtension operator =
LocalOperatorExtension.builder()
.withReconciler(new DependentResourceCrossRefReconciler())
.build();

@Test
void dependentResourceCanReferenceEachOther() {
for (int i = 0; i < EXECUTION_NUMBER; i++) {
operator.create(DependentResourceCrossRefResource.class, testResource(i));
}
await()
.pollDelay(Duration.ofMillis(150))
.untilAsserted(
() -> {
assertThat(operator
.getReconcilerOfType(DependentResourceCrossRefReconciler.class)
.isErrorHappened()).isFalse();
for (int i = 0; i < EXECUTION_NUMBER; i++) {
assertThat(operator.get(ConfigMap.class, TEST_RESOURCE_NAME + i)).isNotNull();
assertThat(operator.get(Secret.class, TEST_RESOURCE_NAME + i)).isNotNull();
}
});
}

DependentResourceCrossRefResource testResource(int n) {
var res = new DependentResourceCrossRefResource();
res.setMetadata(new ObjectMetaBuilder().withName(TEST_RESOURCE_NAME + n).build());
return res;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package io.javaoperatorsdk.operator.sample.dependentresourcecrossref;

import java.util.ArrayList;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Secret;
import io.javaoperatorsdk.operator.api.reconciler.*;
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUKubernetesDependentResource;

@ControllerConfiguration(dependents = {
@Dependent(type = DependentResourceCrossRefReconciler.SecretDependentResource.class),
@Dependent(type = DependentResourceCrossRefReconciler.ConfigMapDependentResource.class)})
public class DependentResourceCrossRefReconciler
implements Reconciler<DependentResourceCrossRefResource>,
ErrorStatusHandler<DependentResourceCrossRefResource> {

private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
private volatile boolean errorHappened = false;

@Override
public UpdateControl<DependentResourceCrossRefResource> reconcile(
DependentResourceCrossRefResource resource,
Context<DependentResourceCrossRefResource> context) {
numberOfExecutions.addAndGet(1);
return UpdateControl.noUpdate();
}

public int getNumberOfExecutions() {
return numberOfExecutions.get();
}

@Override
public ErrorStatusUpdateControl<DependentResourceCrossRefResource> updateErrorStatus(
DependentResourceCrossRefResource resource,
Context<DependentResourceCrossRefResource> context, Exception e) {
errorHappened = true;
return ErrorStatusUpdateControl.noStatusUpdate();
}

public boolean isErrorHappened() {
return errorHappened;
}

public static class SecretDependentResource extends
CRUKubernetesDependentResource<Secret, DependentResourceCrossRefResource> {

public SecretDependentResource() {
super(Secret.class);
}

@Override
protected Secret desired(DependentResourceCrossRefResource primary,
Context<DependentResourceCrossRefResource> context) {
Secret secret = new Secret();
secret.setMetadata(new ObjectMetaBuilder()
.withName(primary.getMetadata().getName())
.withNamespace(primary.getMetadata().getNamespace())
.build());
secret.setData(Map.of("key", Base64.getEncoder().encodeToString("secretData".getBytes())));
return secret;
}
}

public static class ConfigMapDependentResource extends
CRUKubernetesDependentResource<ConfigMap, DependentResourceCrossRefResource> {


public ConfigMapDependentResource() {
super(ConfigMap.class);
}

@Override
protected ConfigMap desired(DependentResourceCrossRefResource primary,
Context<DependentResourceCrossRefResource> context) {
var secret = context.getSecondaryResource(Secret.class);
if (secret.isEmpty()) {
throw new IllegalStateException("Secret is empty");
}
ConfigMap configMap = new ConfigMap();
configMap.setMetadata(new ObjectMetaBuilder()
.withName(primary.getMetadata().getName())
.withNamespace(primary.getMetadata().getNamespace())
.build());
configMap
.setData(Map.of("secretKey", new ArrayList<>(secret.get().getData().keySet()).get(0)));
return configMap;
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.javaoperatorsdk.operator.sample.dependentresourcecrossref;

import io.fabric8.kubernetes.api.model.Namespaced;
import io.fabric8.kubernetes.client.CustomResource;
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Kind;
import io.fabric8.kubernetes.model.annotation.ShortNames;
import io.fabric8.kubernetes.model.annotation.Version;

@Group("sample.javaoperatorsdk")
@Version("v1")
@Kind("MaxIntervalTestCustomResource")
@ShortNames("mit")
public class DependentResourceCrossRefResource
extends CustomResource<Void, DependentResourceCrossRefResourceStatus>
implements Namespaced {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.javaoperatorsdk.operator.sample.dependentresourcecrossref;

public class DependentResourceCrossRefResourceStatus {

}