diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java index 8b70d81dd9..5001fb2864 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppDeploymentResource.java @@ -30,17 +30,13 @@ import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_APP_CONTAINER_NAME; import static io.apicurio.registry.operator.resource.LabelDiscriminators.AppDeploymentDiscriminator; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_APP; import static io.apicurio.registry.operator.resource.ResourceKey.APP_DEPLOYMENT_KEY; import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_SERVICE_KEY; import static io.apicurio.registry.operator.utils.Mapper.toYAML; import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_APP, - resourceDiscriminator = AppDeploymentDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = AppDeploymentDiscriminator.class) public class AppDeploymentResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(AppDeploymentResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppIngressResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppIngressResource.java index f322bb9943..727bf40590 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppIngressResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppIngressResource.java @@ -16,10 +16,7 @@ import static io.apicurio.registry.operator.utils.IngressUtils.withIngressRule; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_APP, - resourceDiscriminator = AppIngressDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = AppIngressDiscriminator.class) public class AppIngressResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(AppIngressResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java index edbd0d6c33..d0be4ada00 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/app/AppServiceResource.java @@ -8,15 +8,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.apicurio.registry.operator.resource.LabelDiscriminators.*; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_APP; +import static io.apicurio.registry.operator.resource.LabelDiscriminators.AppServiceDiscriminator; import static io.apicurio.registry.operator.resource.ResourceKey.APP_SERVICE_KEY; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_APP, - resourceDiscriminator = AppServiceDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = AppServiceDiscriminator.class) public class AppServiceResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(AppServiceResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIDeploymentResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIDeploymentResource.java index 645a0c1e73..854cdbaf76 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIDeploymentResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIDeploymentResource.java @@ -16,7 +16,6 @@ import java.util.LinkedHashMap; import static io.apicurio.registry.operator.api.v1.ContainerNames.STUDIO_UI_CONTAINER_NAME; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_STUDIO_UI; import static io.apicurio.registry.operator.resource.ResourceKey.*; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.addEnvVar; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromDeployment; @@ -24,10 +23,7 @@ import static io.apicurio.registry.operator.utils.Mapper.toYAML; import static java.util.Optional.ofNullable; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_STUDIO_UI, - resourceDiscriminator = StudioUIDeploymentDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = StudioUIDeploymentDiscriminator.class) public class StudioUIDeploymentResource extends CRUDKubernetesDependentResource { diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIIngressResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIIngressResource.java index c947d14a12..f9162936fa 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIIngressResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIIngressResource.java @@ -10,16 +10,13 @@ import org.slf4j.LoggerFactory; import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_STUDIO_UI; -import static io.apicurio.registry.operator.resource.ResourceKey.*; +import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_INGRESS_KEY; import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_SERVICE_KEY; import static io.apicurio.registry.operator.utils.IngressUtils.getHost; import static io.apicurio.registry.operator.utils.IngressUtils.withIngressRule; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_STUDIO_UI, - resourceDiscriminator = StudioUIIngressDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = StudioUIIngressDiscriminator.class) public class StudioUIIngressResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(StudioUIIngressResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIServiceResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIServiceResource.java index ae3ed66b93..b34f4658ed 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIServiceResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/studioui/StudioUIServiceResource.java @@ -9,14 +9,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_STUDIO_UI; import static io.apicurio.registry.operator.resource.ResourceKey.STUDIO_UI_SERVICE_KEY; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_STUDIO_UI, - resourceDiscriminator = StudioUIServiceDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = StudioUIServiceDiscriminator.class) public class StudioUIServiceResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(StudioUIServiceResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIDeploymentResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIDeploymentResource.java index 18f325a8eb..fb1ca16f81 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIDeploymentResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIDeploymentResource.java @@ -16,7 +16,6 @@ import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_UI_CONTAINER_NAME; import static io.apicurio.registry.operator.resource.LabelDiscriminators.UIDeploymentDiscriminator; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_UI; import static io.apicurio.registry.operator.resource.ResourceKey.*; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.addEnvVar; import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromDeployment; @@ -24,10 +23,7 @@ import static io.apicurio.registry.operator.utils.Mapper.toYAML; import static java.util.Optional.ofNullable; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_UI, - resourceDiscriminator = UIDeploymentDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = UIDeploymentDiscriminator.class) public class UIDeploymentResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(UIDeploymentResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIIngressResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIIngressResource.java index 69d4ee1f3a..776d96c4a5 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIIngressResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIIngressResource.java @@ -16,10 +16,7 @@ import static io.apicurio.registry.operator.utils.IngressUtils.withIngressRule; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_UI, - resourceDiscriminator = UIIngressDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = UIIngressDiscriminator.class) public class UIIngressResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(UIIngressResource.class); diff --git a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIServiceResource.java b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIServiceResource.java index d20cac406c..2b330c36c3 100644 --- a/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIServiceResource.java +++ b/operator/controller/src/main/java/io/apicurio/registry/operator/resource/ui/UIServiceResource.java @@ -8,15 +8,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.apicurio.registry.operator.resource.LabelDiscriminators.*; -import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_UI; +import static io.apicurio.registry.operator.resource.LabelDiscriminators.UIServiceDiscriminator; import static io.apicurio.registry.operator.resource.ResourceKey.UI_SERVICE_KEY; import static io.apicurio.registry.operator.utils.Mapper.toYAML; -@KubernetesDependent( - labelSelector = "app.kubernetes.io/name=apicurio-registry,app.kubernetes.io/component=" + COMPONENT_UI, - resourceDiscriminator = UIServiceDiscriminator.class -) +@KubernetesDependent(resourceDiscriminator = UIServiceDiscriminator.class) public class UIServiceResource extends CRUDKubernetesDependentResource { private static final Logger log = LoggerFactory.getLogger(UIServiceResource.class); diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/ITBase.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/ITBase.java index d3f2c2b48e..2d476ecfcf 100644 --- a/operator/controller/src/test/java/io/apicurio/registry/operator/it/ITBase.java +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/ITBase.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.api.model.ConfigMapBuilder; import io.fabric8.kubernetes.api.model.HasMetadata; import io.fabric8.kubernetes.api.model.NamespaceBuilder; +import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.ConfigBuilder; @@ -14,6 +15,7 @@ import io.fabric8.kubernetes.client.utils.Serialization; import io.javaoperatorsdk.operator.Operator; import io.javaoperatorsdk.operator.api.reconciler.Reconciler; +import io.javaoperatorsdk.operator.processing.event.ResourceID; import io.quarkiverse.operatorsdk.runtime.QuarkusConfigurationService; import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.spi.CDI; @@ -24,12 +26,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -56,6 +59,7 @@ public enum OperatorDeployment { protected static Instance> reconcilers; protected static QuarkusConfigurationService configuration; protected static KubernetesClient client; + protected static PodLogManager podLogManager; protected static PortForwardManager portForwardManager; protected static IngressManager ingressManager; protected static String deploymentTarget; @@ -81,9 +85,11 @@ public static void before() throws Exception { portForwardManager = new PortForwardManager(client, namespace); ingressManager = new IngressManager(client, namespace); + podLogManager = new PodLogManager(client); if (operatorDeployment == OperatorDeployment.remote) { createTestResources(); + startOperatorLogs(); } else { createOperator(); registerReconcilers(); @@ -178,6 +184,21 @@ private static void createTestResources() throws Exception { }); } + private static void startOperatorLogs() { + List operatorPods = new ArrayList<>(); + await().ignoreExceptions().untilAsserted(() -> { + operatorPods.clear(); + operatorPods.addAll(client.pods() + .withLabels(Map.of( + "app.kubernetes.io/name", "apicurio-registry-operator", + "app.kubernetes.io/component", "operator", + "app.kubernetes.io/part-of", "apicurio-registry")) + .list().getItems()); + assertThat(operatorPods).hasSize(1); + }); + podLogManager.startPodLog(ResourceID.fromResource(operatorPods.get(0))); + } + private static void cleanTestResources() throws Exception { if (cleanup) { log.info("Deleting generated resources from Namespace {}", namespace); @@ -261,7 +282,7 @@ static void createNamespace(KubernetesClient client, String namespace) { } static String calculateNamespace() { - return ("apicurio-registry-operator-test-" + UUID.randomUUID()).substring(0, 63); + return "test-" + UUID.randomUUID().toString().substring(0, 7); } static void setDefaultAwaitilityTimings() { @@ -306,7 +327,7 @@ public static void after() throws Exception { } else { cleanTestResources(); } - + podLogManager.stopAndWait(); if (cleanup) { log.info("Deleting namespace : {}", namespace); assertThat(client.namespaces().withName(namespace).delete()).isNotNull(); diff --git a/operator/controller/src/test/java/io/apicurio/registry/operator/it/PodLogManager.java b/operator/controller/src/test/java/io/apicurio/registry/operator/it/PodLogManager.java new file mode 100644 index 0000000000..97c27141f3 --- /dev/null +++ b/operator/controller/src/test/java/io/apicurio/registry/operator/it/PodLogManager.java @@ -0,0 +1,79 @@ +package io.apicurio.registry.operator.it; + +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.dsl.LogWatch; +import io.javaoperatorsdk.operator.processing.event.ResourceID; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.time.Duration; +import java.time.Instant; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +public class PodLogManager { + + private static final Logger log = LoggerFactory.getLogger(PodLogManager.class); + + private final KubernetesClient k8sClient; + + private final Map activePodLogMap = new ConcurrentHashMap<>(); + + public PodLogManager(KubernetesClient k8sClient) { + this.k8sClient = k8sClient; + } + + private String getNamespace(ResourceID id) { + return id.getNamespace().orElse("default"); + } + + public void startPodLog(ResourceID podID) { + k8sClient.pods().inNamespace(getNamespace(podID)).withName(podID.getName()).waitUntilReady(60, + SECONDS); + new Thread(() -> { + StringBuilder chunk = new StringBuilder(); + try ( + LogWatch logWatch = k8sClient.pods().inNamespace(getNamespace(podID)).withName(podID.getName()).watchLog(); + BufferedReader reader = new BufferedReader(new InputStreamReader(logWatch.getOutput())) + ) { + AtomicBoolean stop = new AtomicBoolean(false); + log.debug("START LOG of pod {}/{}", getNamespace(podID), podID.getName()); + activePodLogMap.put(podID, stop); + var lastWriteAt = Instant.now(); + while (!stop.get()) { + var line = reader.readLine(); + if (line != null) { + chunk.append(getNamespace(podID)).append("/").append(podID.getName()).append(" >>> ") + .append(line).append("\n"); + if (lastWriteAt.plus(Duration.ofSeconds(5)).isBefore(Instant.now())) { + log.debug("LOG of pod {}/{}:\n{}", getNamespace(podID), podID.getName(), chunk); + chunk.setLength(0); + lastWriteAt = Instant.now(); + } + } else { + stop.set(true); + } + } + } catch (Exception ex) { + log.error("Error while reading logs of pod {}/{}", getNamespace(podID), podID.getName(), ex); + } finally { + if (chunk.length() > 0) { + log.debug("LOG of pod {}/{}:\n{}", getNamespace(podID), podID.getName(), chunk); + } + log.debug("END LOG of pod {}/{}", getNamespace(podID), podID.getName()); + activePodLogMap.remove(podID); + } + }).start(); + } + + public void stopAndWait() { + activePodLogMap.values().forEach(stop -> stop.set(true)); + await().until(activePodLogMap::isEmpty); + } +}