Skip to content

Commit

Permalink
Merge pull request #15 from srl-labs/ssh-treeViewBtn
Browse files Browse the repository at this point in the history
Add buttons next to Containers
  • Loading branch information
FloSch62 authored Jan 25, 2025
2 parents c73ee70 + 6814788 commit d549922
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 47 deletions.
26 changes: 22 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,18 @@
},
{
"command": "containerlab.node.attachShell",
"title": "Attach shell"
"title": "Attach shell",
"icon": "$(terminal)"
},
{
"command": "containerlab.node.ssh",
"title": "Connect to SSH"
"title": "Connect to SSH",
"icon": "$(remote)"
},
{
"command": "containerlab.showLogs",
"title": "View logs"
"title": "View logs",
"icon": "$(list-unordered)"
}
],
"menus": {
Expand All @@ -160,7 +163,7 @@
{
"when": "resourceFilename =~ /\\.clab\\.(yml|yaml)$/",
"command": "containerlab.lab.graph",
"group": "navigation@1"
"group": "navigation@0"
}
],
"editor/title/run": [
Expand Down Expand Up @@ -276,6 +279,21 @@
"when": "viewItem == containerlabContainer",
"group": "nodeNavigation@3"
},
{
"command": "containerlab.node.attachShell",
"when": "viewItem == containerlabContainer",
"group": "inline@1"
},
{
"command": "containerlab.node.ssh",
"when": "viewItem == containerlabContainer",
"group": "inline@2"
},
{
"command": "containerlab.showLogs",
"when": "viewItem == containerlabContainer",
"group": "inline@0"
},
{
"command": "containerlab.node.attachShell",
"when": "viewItem == containerlabContainer",
Expand Down
4 changes: 2 additions & 2 deletions src/commands/clabCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ export class ClabCommand extends cmd.Command {
private node: ContainerlabNode;
private action: string;

constructor(action: string, node: ContainerlabNode, spinnerMsg?: cmd.SpinnerMsg, useTerminal?: boolean, terminalName?: string) {4
constructor(action: string, node: ContainerlabNode, spinnerMsg?: cmd.SpinnerMsg, useTerminal?: boolean, terminalName?: string) {4;
const options: cmd.CmdOptions = {
command: "containerlab",
useSpinner: useTerminal ? false : true,
spinnerMsg: spinnerMsg,
terminalName: terminalName,
}
};
super(options);

this.action = action;
Expand Down
19 changes: 10 additions & 9 deletions src/commands/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import { outputChannel } from '../extension';
export function execCommandInTerminal(command: string, terminalName: string) {
let terminal: vscode.Terminal | undefined;
for (const term of vscode.window.terminals) {
if (term.name.match(terminalName)) {
if (term.name === terminalName) {
terminal = term;
// Send Ctrl+C to stop any previous command
term.sendText("\x03");
// Send Ctrl+C & enter to stop any previous command
term.sendText("\x03\r");
break;
}
}
if (!terminal) {
terminal = vscode.window.createTerminal({ name: terminalName });
}

terminal.sendText(command);
terminal.show();
}
Expand Down Expand Up @@ -79,12 +80,12 @@ export class Command {
this.useSpinner = options.useSpinner;

if(this.useSpinner) {
if(options.terminalName) throw new Error("useSpinner is true. terminalName should NOT be defined.");
if(!options.spinnerMsg) throw new Error("useSpinner is true, but spinnerMsg is undefined.");
if(options.terminalName) {throw new Error("useSpinner is true. terminalName should NOT be defined.");}
if(!options.spinnerMsg) {throw new Error("useSpinner is true, but spinnerMsg is undefined.");}
this.spinnerMsg = options.spinnerMsg;
}
else {
if(!options.terminalName) throw new Error("UseSpinner is false. terminalName must be defined.")
if(!options.terminalName) {throw new Error("UseSpinner is false. terminalName must be defined.");}
this.terminalName = options.terminalName;
}

Expand All @@ -95,9 +96,9 @@ export class Command {
protected execute(args?: string[]) {
let cmd: string[] = [];

if(this.useSudo) cmd.push("sudo");
if(this.useSudo) {cmd.push("sudo");}
cmd.push(this.command);
if(args) cmd.push(...args);
if(args) {cmd.push(...args);}

outputChannel.appendLine(`[${this.command}] Running: ${cmd.join(" ")}`);

Expand All @@ -120,7 +121,7 @@ export class Command {
},
async (progress, token) => {
return new Promise<void>((resolve, reject) => {
console.log(`xxx: ${cmd[1]}`)
console.log(`xxx: ${cmd[1]}`);
const child = spawn(cmd[0], cmd.slice(1));

// If user clicks Cancel, kill the child process
Expand Down
2 changes: 1 addition & 1 deletion src/commands/copyLabPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ export function copyLabPath(node: ContainerlabNode) {
const labName = node.details?.labName ? node.details?.labName : utils.getRelativeFolderPath(labPath);

vscode.env.clipboard.writeText(labPath).then(() => {
vscode.window.showInformationMessage(`Copied file path of ${labName} to clipboard.`)
vscode.window.showInformationMessage(`Copied file path of ${labName} to clipboard.`);
});
}
2 changes: 1 addition & 1 deletion src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function deploySpecificFile() {
filters: {
yaml: ["yaml", "yml"]
},
}
};

vscode.window.showOpenDialog(opts).then(uri => {
if (!uri || !uri.length) {
Expand Down
6 changes: 3 additions & 3 deletions src/commands/dockerCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import * as cmd from './command';
export class DockerCommand extends cmd.Command {
private action: string;

constructor(action: string, spinnerMsg?: cmd.SpinnerMsg) {4
constructor(action: string, spinnerMsg?: cmd.SpinnerMsg) {4;
const options: cmd.CmdOptions = {
command: "docker",
useSpinner: true,
spinnerMsg: spinnerMsg,
}
};
super(options);

this.action = action;
Expand All @@ -21,7 +21,7 @@ export class DockerCommand extends cmd.Command {
public run(containerID: string) {

// Build the command
const cmd = [this.action, containerID]
const cmd = [this.action, containerID];

this.execute(cmd);
}
Expand Down
2 changes: 1 addition & 1 deletion src/commands/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function graphDrawIO(node: ContainerlabNode) {
progressMsg: "Generating DrawIO graph...",
successMsg: "DrawIO Graph Completed!",
failMsg: "Graph (draw.io) Failed",
}
};

const graphCmd = new ClabCommand("graph", node, spinnerMessages);

Expand Down
24 changes: 12 additions & 12 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export * from "./command"
export * from "./deploy"
export * from "./destroy"
export * from "./redeploy"
export * from "./openLabFile"
export * from "./startNode"
export * from "./stopNode"
export * from "./attachShell"
export * from "./ssh"
export * from "./showLogs"
export * from "./graph"
export * from "./copyLabPath"
export * from "./command";
export * from "./deploy";
export * from "./destroy";
export * from "./redeploy";
export * from "./openLabFile";
export * from "./startNode";
export * from "./stopNode";
export * from "./attachShell";
export * from "./ssh";
export * from "./showLogs";
export * from "./graph";
export * from "./copyLabPath";
10 changes: 5 additions & 5 deletions src/commands/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ export function sshToNode(node: ContainerlabNode) {

let sshTarget: string | undefined;

if(node.details?.hostname) sshTarget = node.details?.hostname;
else if(node.details?.v6Addr) sshTarget = node.details?.hostname;
else if(node.details?.v4Addr) sshTarget = node.details?.v4Addr;
else if(node.details?.containerId) sshTarget = node.details?.containerId;
else return vscode.window.showErrorMessage("No target to connect to container");
if(node.details?.hostname) {sshTarget = node.details?.hostname;}
else if(node.details?.v6Addr) {sshTarget = node.details?.hostname;}
else if(node.details?.v4Addr) {sshTarget = node.details?.v4Addr;}
else if(node.details?.containerId) {sshTarget = node.details?.containerId;}
else {return vscode.window.showErrorMessage("No target to connect to container");}

// Pull the default SSH user from settings
const config = vscode.workspace.getConfiguration("containerlab");
Expand Down
2 changes: 1 addition & 1 deletion src/commands/startNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function startNode(node: ContainerlabNode) {
progressMsg: `Starting node ${containerId}...`,
successMsg: `Node '${containerId}' started successfully`,
failMsg: `Could not start node '${containerId}'`
}
};

const startCmd = new DockerCommand("start", spinnerMessages);
startCmd.run(containerId);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/stopNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function stopNode(node: ContainerlabNode) {
progressMsg: `Stopping node ${containerId}...`,
successMsg: `Node '${containerId}' stopped successfully`,
failMsg: `Could not stop node '${containerId}'`
}
};

const startCmd = new DockerCommand("stop", spinnerMessages);
startCmd.run(containerId);
Expand Down
12 changes: 6 additions & 6 deletions src/containerlabTreeDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ export class ContainerlabTreeDataProvider implements vscode.TreeDataProvider<Con
const containerNodes = containers.map((ctr: any) => {
let v4Addr, v6Addr: string | undefined;

if (ctr.ipv4_address) v4Addr = ctr.ipv4_address.split('/')[0];
if (ctr.ipv6_address) v6Addr = ctr.ipv6_address.split('/')[0];
if (ctr.ipv4_address) {v4Addr = ctr.ipv4_address.split('/')[0];}
if (ctr.ipv6_address) {v6Addr = ctr.ipv6_address.split('/')[0];}

const label = `${ctr.name} (${ctr.state})`;

Expand All @@ -177,10 +177,10 @@ export class ContainerlabTreeDataProvider implements vscode.TreeDataProvider<Con
},
"containerlabContainer",
);
node.tooltip = `Container: ${ctr.name}\nID: ${ctr.container_id}\nState: ${ctr.state}`;
node.tooltip = `Container: ${ctr.name}\nID: ${ctr.container_id}\nState: ${ctr.state}\nIPv4: ${v4Addr}\nIPv6: ${v6Addr}`;

if (ctr.state === 'running') node.iconPath = new vscode.ThemeIcon('circle-filled', new vscode.ThemeColor('testing.iconPassed'));
else node.iconPath = new vscode.ThemeIcon('circle-filled', new vscode.ThemeColor('testing.iconFailed'));
if (ctr.state === 'running') {node.iconPath = new vscode.ThemeIcon('circle-filled', new vscode.ThemeColor('testing.iconPassed'));}
else {node.iconPath = new vscode.ThemeIcon('circle-filled', new vscode.ThemeColor('testing.iconFailed'));}

return node;
});
Expand All @@ -191,7 +191,7 @@ export class ContainerlabTreeDataProvider implements vscode.TreeDataProvider<Con
}

private async findLocalClabFiles(): Promise<string[]> {
if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) return [];
if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) {return [];}

const patterns = ['**/*.clab.yml', '**/*.clab.yaml'];
const exclude = '**/node_modules/**';
Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function stripFileName(path: string): string {
}

export function getRelativeFolderPath(targetPath: string): string {
const workspacePath = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.path : ""
const workspacePath = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.path : "";
return path.relative(workspacePath, targetPath);
}

Expand Down

0 comments on commit d549922

Please sign in to comment.