use of org.entando.kubernetes.fluentspi.TestResource in project entando-k8s-controller-coordinator by entando-k8s.
the class DefaultSimpleKubernetesClientTest method shouldUpdateStatusOfOpaqueCustomResource.
@Test
@Description("Should track phase updates on the status of opaque custom resources and in Kubernetes events")
void shouldUpdateStatusOfOpaqueCustomResource() throws IOException {
ValueHolder<TestResource> testResource = new ValueHolder<>();
step("Given I have created an instance of the CustomResourceDefinition TestResource", () -> {
testResource.set(createTestResource(new TestResource().withNames(MY_APP_NAMESPACE_1, MY_APP).withSpec(new BasicDeploymentSpecBuilder().withReplicas(1).build())));
attachResource("TestResource", testResource.get());
});
SerializedEntandoResource serializedEntandoResource = objectMapper.readValue(objectMapper.writeValueAsBytes(testResource.get()), SerializedEntandoResource.class);
step("And it is represented in an opaque format using the SerializedEntandoResource class", () -> {
serializedEntandoResource.setDefinition(CustomResourceDefinitionContext.fromCustomResourceType(TestResource.class));
attachResource("Opaque Resource", serializedEntandoResource);
});
step("When I update its phase to 'successful'", () -> getMyClient().updatePhase(serializedEntandoResource, EntandoDeploymentPhase.SUCCESSFUL));
step("Then the updated status reflects on the TestResource", () -> {
final TestResource actual = getFabric8Client().customResources(TestResource.class).inNamespace(MY_APP_NAMESPACE_1).withName(MY_APP).get();
assertThat(actual.getStatus().getPhase()).isEqualTo(EntandoDeploymentPhase.SUCCESSFUL);
attachResource("TestResource", actual);
});
step("And a PHASE_CHANGE event has been issued to Kubernetes", () -> {
final List<Event> events = getMyClient().listEventsFor(testResource.get());
attachResources("Events", events);
assertThat(events).allMatch(event -> event.getInvolvedObject().getName().equals(testResource.get().getMetadata().getName()));
assertThat(events).anyMatch(event -> event.getAction().equals("PHASE_CHANGE"));
});
}
use of org.entando.kubernetes.fluentspi.TestResource in project entando-k8s-controller-coordinator by entando-k8s.
the class LivenessTests method shouldCreateControllerPodPointingToResource.
@Test
@Description("Should create a controller pod that points to the newly created resource")
void shouldCreateControllerPodPointingToResource() {
System.setProperty(EntandoOperatorSpiConfigProperty.ENTANDO_CONTROLLER_POD_NAME.getJvmSystemProperty(), "my-pod");
step("Given the Coordinator observes its own namespace", () -> {
System.setProperty(EntandoOperatorConfigProperty.ENTANDO_NAMESPACES_TO_OBSERVE.getJvmSystemProperty(), clientDouble.getNamespace());
coordinator.onStartup(new StartupEvent());
});
ValueHolder<SerializedEntandoResource> testResource = new ValueHolder<>();
step("And I have created a new TestResource resource", () -> {
final TestResource r = new TestResource().withNames(clientDouble.getNamespace(), "test-keycloak").withSpec(new BasicDeploymentSpecBuilder().withDbms(DbmsVendor.EMBEDDED).build());
r.getMetadata().setGeneration(1L);
testResource.set(clientDouble.createOrPatchEntandoResource(CoordinatorTestUtils.toSerializedResource(r)));
attachment("TestResource", objectMapper.writeValueAsString(testResource.get()));
});
final File file = Paths.get("/tmp/EntandoControllerCoordinator.ready").toFile();
clientDouble.getCluster().getResourceProcessor().getAllWatchers().forEach(watcher -> {
Liveness.alive();
step(format("When the watcher %s is closed", watcher.getClass().getSimpleName()), () -> {
watcher.onClose(new WatcherException("Closed"));
});
step("Then the liveness probe will fail", () -> {
assertThat(file).doesNotExist();
});
});
}
use of org.entando.kubernetes.fluentspi.TestResource in project entando-k8s-controller-coordinator by entando-k8s.
the class ControllerCoordinatorAdapterTestBase method prepareCrds.
@BeforeAll
static void prepareCrds() {
try (final DefaultKubernetesClient c = new DefaultKubernetesClient()) {
registerCrdResource(c, "testresources.test.org.crd.yaml");
registerCrdResource(c, "mycrds.test.org.crd.yaml");
await().atMost(20, TimeUnit.SECONDS).ignoreExceptions().until(() -> {
if (c.namespaces().withName(MY_APP_NAMESPACE_1).fromServer().get() == null) {
TestFixturePreparation.createNamespace(c, MY_APP_NAMESPACE_1);
}
// Wait for the API to be 100% available
final TestResource testResource1 = c.customResources(TestResource.class).inNamespace(new TestResource().withNames(MY_APP_NAMESPACE_1, "my-app").getMetadata().getNamespace()).createOrReplace(new TestResource().withNames(MY_APP_NAMESPACE_1, "my-app"));
c.secrets().inNamespace(testResource1.getMetadata().getNamespace()).create(SecretUtils.buildSecret(testResource1, "dummy", "koos", "asdfasdf"));
c.customResources(TestResource.class).inNamespace(testResource1.getMetadata().getNamespace()).delete(testResource1);
return true;
});
}
}
use of org.entando.kubernetes.fluentspi.TestResource in project entando-k8s-controller-coordinator by entando-k8s.
the class ControllerCoordinatorProcessingCriteriaTest method testGenerationObservedIsCurrentButForceInstructed.
@Test
@Description("Resource modification events should be processed when using the annotation 'entando.org/processing-instruction=force' even " + "when the 'generation' property on the metadata of the resource is the same as the 'observedGeneration' property on" + " its status")
void testGenerationObservedIsCurrentButForceInstructed() {
step("Given the Coordinator observes this namespace", () -> System.setProperty(EntandoOperatorConfigProperty.ENTANDO_NAMESPACES_TO_OBSERVE.getJvmSystemProperty(), OBSERVED_NAMESPACE));
final ValueHolder<SerializedEntandoResource> testResource = new ValueHolder<>();
step("And I have created an TestResource resource with the 'force' processing instruction", () -> {
testResource.set(createTestResource(10L, Collections.singletonMap(AnnotationNames.PROCESSING_INSTRUCTION.getName(), "force")));
attachment("TestResource", objectMapper.writeValueAsString(testResource.get()));
});
step("And the generation in the metadata is the same as the observedGeneration in the status", () -> {
// NB This step assumes that the ClientDouble is holding this exact instance of the resource when the ControllerCoordinator
// starts
testResource.get().getStatus().updateDeploymentPhase(EntandoDeploymentPhase.STARTED, 10L);
attachment("TestResource", objectMapper.writeValueAsString(testResource.get()));
});
step("When I start the ControllerCoordinator", () -> coordinator.onStartup(new StartupEvent()));
step("Then a new pod gets created", () -> {
coordinator.getObserver(CustomResourceDefinitionContext.fromCustomResourceType(TestResource.class)).shutDownAndWait(1, SECONDS);
await().ignoreExceptions().atMost(3, TimeUnit.SECONDS).until(() -> {
final Map<String, String> labels = labelsFromResource(testResource.get());
return clientDouble.loadPod(CONTROLLER_NAMESPACE, labels) != null;
});
});
step("And the 'force' processing instruction has been removed to avoid recursive processing", () -> {
final SerializedEntandoResource latestKeycloakServer = clientDouble.load(TestResource.class, testResource.get().getMetadata().getNamespace(), testResource.get().getMetadata().getName());
assertThat(CoordinatorUtils.resolveProcessingInstruction(latestKeycloakServer)).isEqualTo(OperatorProcessingInstruction.NONE);
attachment("TestResource", objectMapper.writeValueAsString(testResource.get()));
});
step("And the forced event was logged", () -> {
final Optional<String> logEntry = LogInterceptor.getLogEntries().stream().filter(s -> s.contains("has been forced")).findFirst();
assertThat(logEntry).isPresent();
});
}
use of org.entando.kubernetes.fluentspi.TestResource in project entando-k8s-controller-coordinator by entando-k8s.
the class ControllerCoordinatorProcessingCriteriaTest method testIgnoredWhenOwnedByResourceOfInterest.
@Test
@Description("Resources should be ignored when they are owned by other resources of interest")
void testIgnoredWhenOwnedByResourceOfInterest() {
step("Given the Coordinator observes this namespace", () -> System.setProperty(EntandoOperatorConfigProperty.ENTANDO_NAMESPACES_TO_OBSERVE.getJvmSystemProperty(), OBSERVED_NAMESPACE));
ValueHolder<SerializedEntandoResource> owningResource = new ValueHolder<>();
step("And I have created another resource of interest, a ProvidedCapability", () -> {
owningResource.set(clientDouble.createOrPatchEntandoResource(CoordinatorTestUtils.toSerializedResource(new ProvidedCapabilityBuilder().withNewMetadata().withName("my-capability").withNamespace(OBSERVED_NAMESPACE).endMetadata().withNewSpec().withCapability(StandardCapability.DBMS).endSpec().build())));
attachment("CapabilityResource", objectMapper.writeValueAsString(owningResource.get()));
});
ValueHolder<SerializedEntandoResource> testResource = new ValueHolder<>();
step("And I have created an TestResource resource that is owned by another resource of interest", () -> {
testResource.set(createTestResource(1L, Collections.emptyMap()));
testResource.get().getMetadata().getOwnerReferences().add(ResourceUtils.buildOwnerReference(owningResource.get()));
clientDouble.createOrPatchEntandoResource(testResource.get());
});
step("when I start the ControllerCoordinator", () -> coordinator.onStartup(new StartupEvent()));
step("Then a new pod gets created for the owning resource", () -> {
await().ignoreExceptions().atMost(10, SECONDS).until(() -> clientDouble.loadPod(CONTROLLER_NAMESPACE, labelsFromResource(owningResource.get())) != null);
attachment("Controller Pod", objectMapper.writeValueAsString(clientDouble.loadPod(CONTROLLER_NAMESPACE, labelsFromResource(owningResource.get()))));
});
step("Then no new pod gets created for the owned resource", () -> {
assertThat(clientDouble.loadPod(CONTROLLER_NAMESPACE, labelsFromResource(testResource.get()))).isNull();
});
step("And the ignored event was logged", () -> {
final Optional<String> logEntry = LogInterceptor.getLogEntries().stream().filter(s -> s.contains("is ignored because it is not a top level resource")).findFirst();
assertThat(logEntry).isPresent();
});
}
Aggregations