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);
}
}