You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/03/31 18:58:17 UTC

[camel-karavan] branch main updated: Implements #662

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 6ca6a390 Implements #662
6ca6a390 is described below

commit 6ca6a3907c3c9adf12c36d0a6af350e8d422765a
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Mar 31 14:58:04 2023 -0400

    Implements #662
---
 .../camel/karavan/api/KubernetesResource.java      | 10 ++++-
 .../camel/karavan/service/KubernetesService.java   | 45 ++++++++++++++--------
 karavan-app/src/main/webui/src/api/KaravanApi.tsx  | 11 ++++++
 .../src/main/webui/src/projects/ProjectInfo.tsx    | 12 +++++-
 .../src/main/webui/src/projects/ProjectPage.tsx    |  8 +++-
 5 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
index d2fc2988..60733747 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
@@ -57,7 +57,6 @@ public class KubernetesResource {
     @ConfigProperty(name = "karavan.environment")
     String environment;
 
-
     private static final Logger LOGGER = Logger.getLogger(KubernetesResource.class.getName());
 
     @POST
@@ -86,6 +85,15 @@ public class KubernetesResource {
         return Response.ok(kubernetesService.getPipelineRunLog(name, kubernetesService.getNamespace())).build();
     }
 
+    @DELETE
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Path("/pipelinerun/{env}/{name}")
+    public Response stopPipelineRun(@PathParam("env") String env, @PathParam("name") String name) throws Exception {
+        kubernetesService.stopPipelineRun(name, kubernetesService.getNamespace());
+        return Response.ok().build();
+    }
+
     @GET
     @Produces(MediaType.APPLICATION_JSON)
     @Path("/container/log/{env}/{name}")
diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
index 99b6e135..99ee99d7 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
@@ -37,8 +37,7 @@ import io.fabric8.tekton.pipeline.v1beta1.PipelineRun;
 import io.fabric8.tekton.pipeline.v1beta1.PipelineRunBuilder;
 import io.fabric8.tekton.pipeline.v1beta1.PipelineRunSpec;
 import io.fabric8.tekton.pipeline.v1beta1.PipelineRunSpecBuilder;
-import io.fabric8.tekton.pipeline.v1beta1.PipelineRunStatus;
-import io.fabric8.tekton.pipeline.v1beta1.PipelineRunStatusBuilder;
+import io.fabric8.tekton.pipeline.v1beta1.TaskRun;
 import io.fabric8.tekton.pipeline.v1beta1.WorkspaceBindingBuilder;
 import io.quarkus.vertx.ConsumeEvent;
 import io.vertx.mutiny.core.eventbus.EventBus;
@@ -79,6 +78,7 @@ public class KubernetesService {
 
     @Produces
     public KubernetesClient kubernetesClient() {
+        System.setProperty("kubeconfig", "/Users/mgubaidu/projects/oss/camel-karavan/karavan-app/karavan-kubeconfig.yaml");
         return new DefaultKubernetesClient();
     }
 
@@ -103,9 +103,9 @@ public class KubernetesService {
 
     @ConsumeEvent(value = START_INFORMERS, blocking = true)
     void startInformers(String data) {
-        LOGGER.info("Start Kubernetes Informers");
         try {
             stopInformers(null);
+            LOGGER.info("Starting Kubernetes Informers");
             String runtimeLabel = getRuntimeLabel();
 
             SharedIndexInformer<Deployment> deploymentInformer = kubernetesClient().apps().deployments().inNamespace(getNamespace()).withLabel(runtimeLabel, "camel").inform();
@@ -123,7 +123,7 @@ public class KubernetesService {
             SharedIndexInformer<Pod> podRunInformer = kubernetesClient().pods().inNamespace(getNamespace()).withLabel(runtimeLabel, "camel").inform();
             podRunInformer.addEventHandlerWithResyncPeriod(new PodEventHandler(infinispanService, this),30 * 1000L);
             informers.add(podRunInformer);
-
+            LOGGER.info("Started Kubernetes Informers");
         } catch (Exception e) {
             LOGGER.error("Error starting informers: " + e.getMessage());
         }
@@ -180,6 +180,10 @@ public class KubernetesService {
         return tektonClient().v1beta1().pipelineRuns().inNamespace(namespace).withName(pipelineRuneName).get();
     }
 
+    public List<TaskRun> getTaskRuns(String pipelineRuneName, String namespace) {
+        return tektonClient().v1beta1().taskRuns().inNamespace(namespace).withLabel("tekton.dev/pipelineRun", pipelineRuneName).list().getItems();
+    }
+
     public String getContainerLog(String podName, String namespace) {
         String logText = kubernetesClient().pods().inNamespace(namespace).withName(podName).getLog(true);
         return logText;
@@ -202,16 +206,15 @@ public class KubernetesService {
 
     public List<PipelineRunLog> getPipelineRunLog(String pipelineRuneName, String namespace) {
         List<PipelineRunLog> result = new ArrayList<>(1);
-        PipelineRun pipelineRun = getPipelineRun(pipelineRuneName, namespace);
-        pipelineRun.getStatus().getTaskRuns().forEach((s, pipelineRunTaskRunStatus) -> {
-            String podName = pipelineRunTaskRunStatus.getStatus().getPodName();
+        getTaskRuns(pipelineRuneName, namespace).forEach(taskRun -> {
+            String podName = taskRun.getStatus().getPodName();
             StringBuilder log = new StringBuilder();
-            pipelineRunTaskRunStatus.getStatus().getSteps().forEach(stepState -> {
+            taskRun.getStatus().getSteps().forEach(stepState -> {
                 String logText = kubernetesClient().pods().inNamespace(namespace).withName(podName).inContainer(stepState.getContainer()).getLog(true);
                 log.append(stepState.getContainer()).append(System.lineSeparator());
                 log.append(logText).append(System.lineSeparator());
             });
-            result.add(new PipelineRunLog(s, log.toString()));
+            result.add(new PipelineRunLog(taskRun.getMetadata().getName(), log.toString()));
         });
         return result;
     }
@@ -228,17 +231,29 @@ public class KubernetesService {
         try {
             LOGGER.info("Stop PipelineRun: " + pipelineRunName + " in the namespace: " + namespace);
 
-            PipelineRun run = tektonClient().v1beta1().pipelineRuns().inNamespace(namespace).withName(pipelineRunName).get();
-            run.getSpec().setStatus("CancelledRunFinally");
+            getTaskRuns(pipelineRunName, namespace).forEach(taskRun -> {
+                taskRun.getStatus().setConditions(getCancelConditions("TaskRunCancelled"));
+                tektonClient().v1beta1().taskRuns().inNamespace(namespace).resource(taskRun).replaceStatus();
+            });
 
-            tektonClient().v1beta1().pipelineRuns().inNamespace(namespace)
-                    .resource(run)
-                    .lockResourceVersion(run.getMetadata().getResourceVersion())
-                    .replaceStatus();
+            PipelineRun run = tektonClient().v1beta1().pipelineRuns().inNamespace(namespace).withName(pipelineRunName).get();
+            run.getStatus().setConditions(getCancelConditions("CancelledRunFinally"));
+            tektonClient().v1beta1().pipelineRuns().inNamespace(namespace).resource(run).replaceStatus();
         } catch (Exception ex) {
             LOGGER.error(ex.getMessage());
         }
     }
+
+    private List<Condition> getCancelConditions(String reason){
+        List<Condition> cancelConditions = new ArrayList<>();
+        Condition taskRunCancelCondition = new Condition();
+        taskRunCancelCondition.setType("Succeeded");
+        taskRunCancelCondition.setStatus("False");
+        taskRunCancelCondition.setReason(reason);
+        taskRunCancelCondition.setMessage("Cancelled successfully.");
+        cancelConditions.add(taskRunCancelCondition);
+        return cancelConditions;
+    }
     
     public void rolloutDeployment(String name, String namespace) {
         try {
diff --git a/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 25bf64f4..b456a556 100644
--- a/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -320,6 +320,17 @@ export class KaravanApi {
         });
     }
 
+    static async stopPipelineRun(environment: string, pipelineRunName: string, after: (res: AxiosResponse<any>) => void) {
+        instance.delete('/api/kubernetes/pipelinerun/' + environment + "/" + pipelineRunName)
+            .then(res => {
+                if (res.status === 200) {
+                    after(res.data);
+                }
+            }).catch(err => {
+            console.log(err);
+        });
+    }
+
     static async getContainerLog(environment: string, name: string, after: (res: AxiosResponse<string>) => void) {
         instance.get('/api/kubernetes/container/log/' + environment + "/" + name)
             .then(res => {
diff --git a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
index 658278f3..f0fc0189 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectInfo.tsx
@@ -25,7 +25,7 @@ interface Props {
     needCommit: boolean,
     files: ProjectFile[],
     showLog: (type: 'container' | 'pipeline', name: string, environment: string) => void
-    deleteEntity: (type: 'pod' | 'deployment', name: string, environment: string) => void
+    deleteEntity: (type: 'pod' | 'deployment' | 'pipelinerun', name: string, environment: string) => void
 }
 
 interface State {
@@ -38,7 +38,7 @@ interface State {
     isBuilding: boolean,
     isRolling: boolean,
     showDeleteConfirmation: boolean,
-    deleteEntity?: 'pod' | 'deployment',
+    deleteEntity?: 'pod' | 'deployment' | 'pipelinerun',
     deleteEntityName?: string,
     deleteEntityEnv?: string,
     environment: string,
@@ -345,6 +345,14 @@ export class ProjectInfo extends React.Component<Props, State> {
                                         {pipeline}
                                     </Button>
                                     : "No pipeline"}
+                                {isRunning && <Tooltip content={"Stop PipelineRun"}>
+                                    <Button icon={<DeleteIcon/>} variant="link" onClick={e => this.setState({
+                                        showDeleteConfirmation: true,
+                                        deleteEntity: "pipelinerun",
+                                        deleteEntityEnv: env,
+                                        deleteEntityName: pipeline
+                                    })}></Button>
+                                </Tooltip>}
                             </Label>
                             {pipeline && showTime && lastPipelineRunTime !== undefined && <Label icon={<ClockIcon/>} color={color}>{lastPipelineRunTime + "s"}</Label>}
                         </LabelGroup>
diff --git a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
index 2278cabb..afced74a 100644
--- a/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webui/src/projects/ProjectPage.tsx
@@ -320,7 +320,7 @@ export class ProjectPage extends React.Component<Props, State> {
 
     }
 
-    deleteEntity = (type: 'pod' | 'deployment', name: string, environment: string) => {
+    deleteEntity = (type: 'pod' | 'deployment' | 'pipelinerun', name: string, environment: string) => {
         switch (type) {
             case "deployment":
                 KaravanApi.deleteDeployment(environment, name, (res: any) => {
@@ -334,6 +334,12 @@ export class ProjectPage extends React.Component<Props, State> {
                         this.onRefresh();
                 });
                 break;
+            case "pipelinerun":
+                KaravanApi.stopPipelineRun(environment, name, (res: any) => {
+                    if (Array.isArray(res) && Array.from(res).length > 0)
+                        this.onRefresh();
+                });
+                break;
         }
     }