Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: start debug session from task (#470) #495

Merged
merged 3 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2021 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc.
******************************************************************************/
package com.redhat.devtools.intellij.tektoncd.actions.debug;
lstocchi marked this conversation as resolved.
Show resolved Hide resolved

import com.redhat.devtools.intellij.tektoncd.actions.StartAction;
import com.redhat.devtools.intellij.tektoncd.tkn.Tkn;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Input;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Output;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Workspace;
import com.redhat.devtools.intellij.tektoncd.tree.ClusterTaskNode;
import com.redhat.devtools.intellij.tektoncd.tree.ParentableNode;
import com.redhat.devtools.intellij.tektoncd.tree.TaskNode;
import com.redhat.devtools.intellij.tektoncd.utils.DebugHelper;
import com.redhat.devtools.intellij.tektoncd.utils.DeployHelper;
import com.redhat.devtools.intellij.tektoncd.utils.YAMLBuilder;
import com.redhat.devtools.intellij.tektoncd.utils.model.actions.StartResourceModel;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

import static com.redhat.devtools.intellij.tektoncd.Constants.KIND_CLUSTERTASK;
import static com.redhat.devtools.intellij.tektoncd.Constants.KIND_TASK;
import static com.redhat.devtools.intellij.tektoncd.utils.Utils.isActiveTektonVersionOlder;

public class DebugTaskAction extends StartAction {

public DebugTaskAction() {
super(TaskNode.class, ClusterTaskNode.class);
}

@Override
protected String doStart(Tkn tkncli, String namespace, StartResourceModel model) throws IOException {
String runAsYAML = createRun(tkncli, namespace, model);
if (runAsYAML == null) {
throw new IOException("Unable to debug task" + model.getName());
}
runAsYAML = YAMLBuilder.addBreakPointToResource(runAsYAML);
String runName = DeployHelper.saveResource(runAsYAML, namespace, tkncli);
DebugHelper.doDebugTaskRun(tkncli, namespace, runName);
return null;
}

private String createRun(Tkn tkncli, String namespace, StartResourceModel model) throws IOException {
String serviceAccount = model.getServiceAccount();
Map<String, Input> params = model.getParams().stream().collect(Collectors.toMap(Input::name, param -> param));
Map<String, Workspace> workspaces = model.getWorkspaces();
Map<String, String> inputResources = model.getInputResources().stream().collect(Collectors.toMap(Input::name, Input::value));
Map<String, String> outputResources = model.getOutputResources().stream().collect(Collectors.toMap(Output::name, Output::value));
String runPrefixName = model.getRunPrefixName();
String run = null;
if (model.getKind().equalsIgnoreCase(KIND_TASK)) {
run = tkncli.createRunFromTask(namespace, model.getName(), params, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
} else if (model.getKind().equalsIgnoreCase(KIND_CLUSTERTASK)) {
run = tkncli.createRunFromClusterTask(namespace, model.getName(), params, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
}
return run;
}

@Override
public boolean isVisible(Object selected) {
Object element = getElement(selected);
if (element instanceof TaskNode
|| element instanceof ClusterTaskNode) {
Tkn tkn = ((ParentableNode)element).getRoot().getTkn();
return isActiveTektonVersionOlder(tkn.getTektonVersion(), "0.26.0") &&
tkn.isTektonAlphaFeatureEnabled();
}
return false;
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/redhat/devtools/intellij/tektoncd/tkn/Tkn.java
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,22 @@ public interface Tkn {
*/
String startTask(String namespace, String task, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException;

/**
* Preview the TaskRun without running it
*
* @param namespace the namespace of the task
* @param task the task that has to be run
* @param parameters the parameters to start task
* @param inputResources the input resources to start task
* @param outputResources the output resources to start task
* @param serviceAccount the service account to use when running the task
* @param workspaces the workspaces to start the task
* @param runPrefixName the name to use as a prefix for the taskrun
* @throws IOException if communication errored
* @return TaskRun
*/
String createRunFromTask(String namespace, String task, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException;

/**
* Start the execution of a task
*
Expand All @@ -521,6 +537,22 @@ public interface Tkn {
*/
String startClusterTask(String namespace, String clusterTask, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException;

/**
* Preview the ClusterTaskRun without running it
*
* @param namespace the namespace where to run the clusterTask, useful to retrieve the input/output resources
* @param clusterTask the task that has to be run
* @param parameters the parameters to start task
* @param inputResources the input resources to start task
* @param outputResources the output resources to start task
* @param serviceAccount the service account to use when running the task
* @param workspaces the workspaces to start the task
* @param runPrefixName the name to use as a prefix for the taskrun
* @throws IOException if communication errored
* @return ClusterTaskRun
*/
String createRunFromClusterTask(String namespace, String clusterTask, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException;

/**
* Re-run the task using last taskrun values
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,11 +654,23 @@ public String startTask(String namespace, String task, Map<String, Input> parame
return startTaskAndGetRunName(args, parameters, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
}

@Override
public String createRunFromTask(String namespace, String task, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException {
List<String> args = new ArrayList<>(Arrays.asList("task", "start", task, "-n", namespace, "--dry-run"));
return startTask(args, parameters, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
}

public String startClusterTask(String namespace, String clusterTask, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException {
List<String> args = new ArrayList<>(Arrays.asList("clustertask", "start", clusterTask, "-n", namespace)); // -n is used to retreive input/output resources
return startTaskAndGetRunName(args, parameters, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
}

@Override
public String createRunFromClusterTask(String namespace, String clusterTask, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException {
List<String> args = new ArrayList<>(Arrays.asList("clustertask", "start", clusterTask, "-n", namespace, "--dry-run")); // -n is used to retreive input/output resources
return startTask(args, parameters, inputResources, outputResources, serviceAccount, workspaces, runPrefixName);
}

private String startTask(List<String> args, Map<String, Input> parameters, Map<String, String> inputResources, Map<String, String> outputResources, String serviceAccount, Map<String, Workspace> workspaces, String runPrefixName) throws IOException {
if (!serviceAccount.isEmpty()) {
args.add(FLAG_SERVICEACCOUNT + "=" + serviceAccount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.redhat.devtools.intellij.common.utils.YAMLHelper;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Input;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Output;
import com.redhat.devtools.intellij.tektoncd.tkn.component.field.Workspace;
Expand Down Expand Up @@ -374,6 +375,13 @@ private static ObjectNode createTaskRunSpec(String name, List<Input> params, Lis
return specNode;
}

public static String addBreakPointToResource(String resourceAsYAML) throws IOException {
ObjectNode run = YAMLBuilder.convertToObjectNode(resourceAsYAML);
ObjectNode breakpoint = YAMLBuilder.createBreakpointSection();
((ObjectNode)run.get("spec")).set("debug", breakpoint);
return YAMLHelper.JSONToYAML(run);
}

public static ObjectNode createTriggerTemplate(String name, String apiVersion, List<String> params, List<ObjectNode> runs) {
ObjectNode rootNode = YAML_MAPPER.createObjectNode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@

import com.google.common.base.Strings;
import com.redhat.devtools.intellij.common.utils.YAMLHelper;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

import static com.redhat.devtools.intellij.tektoncd.Constants.KIND_CLUSTERTASK;

Expand All @@ -37,7 +37,7 @@ public ConfigurationModel(String configuration) {
try {
this.name = YAMLHelper.getStringValueFromYAML(configuration, new String[] {"metadata", "name"});
this.kind = YAMLHelper.getStringValueFromYAML(configuration, new String[] {"kind"});
if (!this.kind.equalsIgnoreCase(KIND_CLUSTERTASK)) {
if (!KIND_CLUSTERTASK.equalsIgnoreCase(this.kind)) {
this.namespace = YAMLHelper.getStringValueFromYAML(configuration, new String[]{"metadata", "namespace"});
}
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void init(String configuration) {
errorMessage += " * Kind field is missing or its value is not valid.\n";
isValid = false;
}
if (Strings.isNullOrEmpty(namespace) && !kind.equalsIgnoreCase(KIND_CLUSTERTASK)) {
if (Strings.isNullOrEmpty(namespace) && !KIND_CLUSTERTASK.equalsIgnoreCase(kind)) {
errorMessage += " * Namespace field is missing or its value is not valid.\n";
isValid = false;
}
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
<action id="com.redhat.devtools.intellij.tektoncd.actions.StartAction" class="com.redhat.devtools.intellij.tektoncd.actions.StartAction" text="Start"/>
<action id="com.redhat.devtools.intellij.tektoncd.actions.MirrorStartAction" class="com.redhat.devtools.intellij.tektoncd.actions.MirrorStartAction" text="Mirror Start"/>
<action id="com.redhat.devtools.intellij.tektoncd.actions.StartLastRunAction" class="com.redhat.devtools.intellij.tektoncd.actions.StartLastRunAction" text="Start Last Run"/>
<action id="com.redhat.devtools.intellij.tektoncd.actions.debug.DebugTaskAction" class="com.redhat.devtools.intellij.tektoncd.actions.debug.DebugTaskAction" text="Start in Debug Mode" />
<action id="com.redhat.devtools.intellij.tektoncd.actions.debug.DebugTaskRunAction" class="com.redhat.devtools.intellij.tektoncd.actions.debug.DebugTaskRunAction" text="Start in Debug Mode"/>
<action id="com.redhat.devtools.intellij.tektoncd.actions.debug.ConnectDebugTaskRunAction" class="com.redhat.devtools.intellij.tektoncd.actions.debug.ConnectDebugTaskRunAction" text="Open Debug Panel"/>
<action id="com.redhat.devtools.intellij.tektoncd.actions.task.FindTaskRefAction" class="com.redhat.devtools.intellij.tektoncd.actions.task.FindTaskRefAction" text="Find Usages" />
Expand Down