This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new c4c25187 Operator should deploy Task and Pipelines if Tekton installed 
after Karavan (#673)
c4c25187 is described below

commit c4c25187731dc93961ec3771efdc149b6a588fef
Author: Dmitry Volodin <[email protected]>
AuthorDate: Mon Mar 13 18:08:38 2023 +0300

    Operator should deploy Task and Pipelines if Tekton installed after Karavan 
(#673)
---
 .../camel/karavan/operator/KaravanReconciler.java  | 64 ++++------------------
 .../org/apache/camel/karavan/operator/Utils.java   |  9 +--
 .../operator/watcher/TektonCrdEventHandler.java    | 40 +++++++++-----
 .../watcher/TektonSubscriptionEventHandler.java    | 26 ++++-----
 4 files changed, 54 insertions(+), 85 deletions(-)

diff --git 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java
 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java
index e383aa6f..93e2333c 100644
--- 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java
+++ 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/KaravanReconciler.java
@@ -17,8 +17,9 @@
 package org.apache.camel.karavan.operator;
 
 import io.fabric8.kubernetes.client.KubernetesClient;
-import io.fabric8.kubernetes.client.informers.SharedIndexInformer;
 import io.fabric8.openshift.client.OpenShiftClient;
+import io.fabric8.tekton.pipeline.v1beta1.Pipeline;
+import io.fabric8.tekton.pipeline.v1beta1.Task;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
@@ -31,7 +32,6 @@ import 
io.javaoperatorsdk.operator.processing.dependent.workflow.Workflow;
 import 
io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult;
 import 
io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowBuilder;
 import io.javaoperatorsdk.operator.processing.event.source.EventSource;
-import io.quarkus.runtime.Quarkus;
 import org.apache.camel.karavan.operator.resource.KaravanDeployment;
 import org.apache.camel.karavan.operator.resource.KaravanPvcData;
 import org.apache.camel.karavan.operator.resource.KaravanPvcJbang;
@@ -70,10 +70,9 @@ public class KaravanReconciler implements 
Reconciler<Karavan>, EventSourceInitia
     static final Logger log = LoggerFactory.getLogger(KaravanReconciler.class);
 
     private boolean isOpenShift;
+    private boolean initTektonInstalled;
     private KubernetesClient client;
-    private SharedIndexInformer informer;
     private Workflow<Karavan> workflow;
-
     private KaravanServiceAccount karavanServiceAccount;
     private KaravanRole karavanRole;
     private KaravanRoleBinding karavanRoleBinding;
@@ -96,6 +95,7 @@ public class KaravanReconciler implements 
Reconciler<Karavan>, EventSourceInitia
     public KaravanReconciler(KubernetesClient client) {
         this.client = client;
         this.isOpenShift = Utils.isOpenShift(client);
+        this.initTektonInstalled = Utils.isTektonInstalled(client);
         initDependentResources();
         createWorkflow();
         addSubscriptionWatcher();
@@ -105,32 +105,32 @@ public class KaravanReconciler implements 
Reconciler<Karavan>, EventSourceInitia
     public UpdateControl<Karavan> reconcile(Karavan karavan, Context<Karavan> 
context) throws Exception {
         final var name = karavan.getMetadata().getName();
         final var namespace = karavan.getMetadata().getNamespace();
+        log.info("--- Starting Karavan '{}' reconcile at '{}' namespace ---", 
name, namespace);
+
         WorkflowReconcileResult result = workflow.reconcile(karavan, context);
         if (result.allDependentResourcesReady()) {
-            log.info("Karavan is exposed and ready to be used at '{}' 
namespace", namespace);
+            log.info("Karavan '{}' is exposed and ready to be used at '{}' 
namespace", name, namespace);
             karavan.setStatus(new KaravanStatus(KaravanStatus.State.READY));
             return UpdateControl.updateStatus(karavan);
         } else {
             final var duration = Duration.ofSeconds(5);
-            log.info("Karavan is not ready yet, rescheduling reconciliation 
after {}s", name, duration.toSeconds());
+            log.info("Karavan '{}' is not ready yet, rescheduling 
reconciliation after {}s", name, duration.toSeconds());
             return UpdateControl.<Karavan>noUpdate().rescheduleAfter(duration);
         }
     }
 
     private void addSubscriptionWatcher() {
         if (this.isOpenShift) {
-            this.informer = 
client.adapt(OpenShiftClient.class).operatorHub().subscriptions().inform(new 
TektonSubscriptionEventHandler(this), 30 * 1000L);
-        } else {
-            this.informer = 
client.apiextensions().v1().customResourceDefinitions().inform(new 
TektonCrdEventHandler(this), 30 * 1000L);
+            
client.adapt(OpenShiftClient.class).operatorHub().subscriptions().inform(new 
TektonSubscriptionEventHandler(initTektonInstalled), 30 * 1000L);
         }
+        client.apiextensions().v1().customResourceDefinitions().inform(new 
TektonCrdEventHandler(Pipeline::new, initTektonInstalled), 30 * 1000L);
+        client.apiextensions().v1().customResourceDefinitions().inform(new 
TektonCrdEventHandler(Task::new, initTektonInstalled), 30 * 1000L);
     }
 
     private void createWorkflow() {
         log.info("Creating workflow in " + (isOpenShift ? "Openshift" : 
"Kubernetes"));
         WorkflowBuilder workflowBuilder = new WorkflowBuilder<Karavan>();
-        getResources().forEach(dr -> {
-            workflowBuilder.addDependentResource(dr);
-        });
+        getResources().forEach(workflowBuilder::addDependentResource);
         this.workflow = workflowBuilder.build();
     }
 
@@ -166,46 +166,6 @@ public class KaravanReconciler implements 
Reconciler<Karavan>, EventSourceInitia
         });
     }
 
-    public void addTektonResources() {
-        log.info("Recreate workflow with Tekton resources");
-        if (karavanTektonTaskQuarkus == null) {
-            karavanTektonTaskQuarkus = new KaravanTektonTask(isOpenShift, 
CamelRuntime.Type.QUARKUS);
-            karavanTektonTaskQuarkus.setKubernetesClient(client);
-            karavanTektonTaskQuarkus.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (karavanTektonTaskSpringBoot == null) {
-            karavanTektonTaskSpringBoot = new KaravanTektonTask(isOpenShift, 
CamelRuntime.Type.SPRING_BOOT);
-            karavanTektonTaskSpringBoot.setKubernetesClient(client);
-            karavanTektonTaskSpringBoot.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (karavanTektonPipelineQuarkus == null) {
-            karavanTektonPipelineQuarkus = new 
KaravanTektonPipeline(CamelRuntime.Type.QUARKUS);
-            karavanTektonPipelineQuarkus.setKubernetesClient(client);
-            karavanTektonPipelineQuarkus.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (karavanTektonPipelineSpringboot == null) {
-            karavanTektonPipelineSpringboot = new 
KaravanTektonPipeline(CamelRuntime.Type.SPRING_BOOT);
-            karavanTektonPipelineSpringboot.setKubernetesClient(client);
-            karavanTektonPipelineSpringboot.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (pipelineServiceAccount == null) {
-            pipelineServiceAccount = new PipelineServiceAccount();
-            pipelineServiceAccount.setKubernetesClient(client);
-            pipelineServiceAccount.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (pipelineRoleDeployer == null) {
-            pipelineRoleDeployer = new PipelineRoleDeployer();
-            pipelineRoleDeployer.setKubernetesClient(client);
-            pipelineRoleDeployer.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        if (pipelineRoleBinding == null) {
-            pipelineRoleBinding = new PipelineRoleBinding();
-            pipelineRoleBinding.setKubernetesClient(client);
-            pipelineRoleBinding.configureWith(new 
KubernetesDependentResourceConfig());
-        }
-        createWorkflow();
-    }
-
     @Override
     public Map<String, EventSource> 
prepareEventSources(EventSourceContext<Karavan> context) {
         List<EventSource> list = getResources().stream().map(crd -> 
crd.initEventSource(context)).collect(Collectors.toList());
diff --git 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/Utils.java 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/Utils.java
index 990ac2eb..b6cb7aa4 100644
--- 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/Utils.java
+++ 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/Utils.java
@@ -27,6 +27,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 public class Utils {
+    private static final Pipeline pipeline = new Pipeline();
+    private static final Task task = new Task();
 
     public static Map<String, String> getLabels(String name, Map<String, 
String> labels) {
         Map<String, String> result = new HashMap<>(Map.of(
@@ -40,8 +42,6 @@ public class Utils {
     }
 
     public static boolean isTektonInstalled(KubernetesClient client) {
-        Pipeline pipeline = new Pipeline();
-        Task task = new Task();
         APIResourceList kinds = 
client.getApiResources(pipeline.getApiVersion());
         if (kinds != null && kinds.getResources().stream().anyMatch(res -> 
res.getKind().equalsIgnoreCase(pipeline.getKind())) &&
                 kinds.getResources().stream().anyMatch(res -> 
res.getKind().equalsIgnoreCase(task.getKind()))) {
@@ -57,9 +57,6 @@ public class Utils {
     }
 
     public static boolean isOpenShift(KubernetesClient client) {
-        if (client.isAdaptable(OpenShiftClient.class)) {
-            return true;
-        }
-        return false;
+        return client.adapt(OpenShiftClient.class).isSupported();
     }
 }
diff --git 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonCrdEventHandler.java
 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonCrdEventHandler.java
index 9983c146..3e598ff1 100644
--- 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonCrdEventHandler.java
+++ 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonCrdEventHandler.java
@@ -16,36 +16,48 @@
  */
 package org.apache.camel.karavan.operator.watcher;
 
+import io.fabric8.kubernetes.api.model.HasMetadata;
 import 
io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
+import 
io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinitionSpec;
+import io.fabric8.kubernetes.client.KubernetesClient;
 import io.fabric8.kubernetes.client.informers.ResourceEventHandler;
-import org.apache.camel.karavan.operator.KaravanReconciler;
+import io.quarkus.runtime.Quarkus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class TektonCrdEventHandler implements 
ResourceEventHandler<CustomResourceDefinition> {
+import java.util.Objects;
+import java.util.function.Supplier;
 
-    private static final String NAME = "pipelines.tekton.dev";
+public class TektonCrdEventHandler<T extends HasMetadata> implements 
ResourceEventHandler<CustomResourceDefinition> {
+    static final Logger log = 
LoggerFactory.getLogger(TektonCrdEventHandler.class);
 
-    private KaravanReconciler karavanReconciler;
+    private final Supplier<? extends T> obj;
 
-    public TektonCrdEventHandler(KaravanReconciler karavanReconciler) {
-        this.karavanReconciler = karavanReconciler;
+    private boolean initTektonInstalled;
+
+    public TektonCrdEventHandler(Supplier<? extends T> obj, boolean 
initTektonInstalled) {
+        this.obj = Objects.requireNonNull(obj);
+        this.initTektonInstalled = initTektonInstalled;
     }
 
     @Override
     public void onAdd(CustomResourceDefinition crd) {
-        if (crd.getMetadata().getName().contains(NAME)) {
-            karavanReconciler.addTektonResources();
+        if (!initTektonInstalled && isTektonCustomResource(crd.getSpec())) {
+            // This is hack while OJSDK doesn't support dynamic EventSource 
reload.
+            // Just restart whole Quarkus application.
+            log.info("Restarting Karavan operator as Tekton resources have 
been installed...");
+            Quarkus.asyncExit();
         }
     }
 
     @Override
-    public void onUpdate(CustomResourceDefinition crd1, 
CustomResourceDefinition crd2) {
-        if (crd2.getMetadata().getName().contains(NAME)) {
-            karavanReconciler.addTektonResources();
-        }
-    }
+    public void onUpdate(CustomResourceDefinition oldCrd, 
CustomResourceDefinition newCrd) {}
 
     @Override
-    public void onDelete(CustomResourceDefinition obj, boolean 
deletedFinalStateUnknown) {
+    public void onDelete(CustomResourceDefinition obj, boolean 
deletedFinalStateUnknown) {}
 
+    private boolean isTektonCustomResource(CustomResourceDefinitionSpec spec) {
+        return spec.getVersions().stream().anyMatch(ver -> (spec.getGroup() + 
"/" + ver.getName() + "/" + spec.getNames().getKind())
+                .equalsIgnoreCase(obj.get().getApiVersion() + "/" + 
obj.get().getKind()));
     }
 }
diff --git 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonSubscriptionEventHandler.java
 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonSubscriptionEventHandler.java
index c468f929..8037e24b 100644
--- 
a/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonSubscriptionEventHandler.java
+++ 
b/karavan-operator/src/main/java/org/apache/camel/karavan/operator/watcher/TektonSubscriptionEventHandler.java
@@ -16,36 +16,36 @@
  */
 package org.apache.camel.karavan.operator.watcher;
 
+import io.fabric8.kubernetes.client.KubernetesClient;
 import io.fabric8.kubernetes.client.informers.ResourceEventHandler;
 import io.fabric8.openshift.api.model.operatorhub.v1alpha1.Subscription;
-import org.apache.camel.karavan.operator.KaravanReconciler;
+import io.fabric8.openshift.api.model.operatorhub.v1alpha1.SubscriptionSpec;
+import io.quarkus.runtime.Quarkus;
 
 public class TektonSubscriptionEventHandler implements 
ResourceEventHandler<Subscription> {
 
-    private static final String NAME = "openshift-pipelines-operator";
+    private static final String OPENSHIFT_TEKTON_SUBSCRIPTION_NAME = 
"openshift-pipelines-operator";
 
-    private KaravanReconciler karavanReconciler;
+    private boolean initTektonInstalled;
 
-    public TektonSubscriptionEventHandler(KaravanReconciler karavanReconciler) 
{
-        this.karavanReconciler = karavanReconciler;
+    public TektonSubscriptionEventHandler(boolean initTektonInstalled) {
+        this.initTektonInstalled = initTektonInstalled;
     }
 
     @Override
     public void onAdd(Subscription subscription) {
-        if (subscription.getMetadata().getName().contains(NAME)) {
-            karavanReconciler.addTektonResources();
+        if (!initTektonInstalled && 
isTektonSubscription(subscription.getSpec())) {
+            Quarkus.asyncExit();
         }
     }
 
     @Override
-    public void onUpdate(Subscription oldSubscription, Subscription 
newSubscription) {
-        if (newSubscription.getMetadata().getName().contains(NAME)) {
-            karavanReconciler.addTektonResources();
-        }
-    }
+    public void onUpdate(Subscription oldSubscription, Subscription 
newSubscription) {}
 
     @Override
-    public void onDelete(Subscription obj, boolean deletedFinalStateUnknown) {
+    public void onDelete(Subscription obj, boolean deletedFinalStateUnknown) {}
 
+    private boolean isTektonSubscription(SubscriptionSpec spec) {
+        return spec.getName().contains(OPENSHIFT_TEKTON_SUBSCRIPTION_NAME);
     }
 }

Reply via email to