wiki.getshifting.com

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


vscodetasks

VS Code Tasks

Summary: I've been using VSCode for years now and I keep on finding new options to improve my productivity using the tool. On this page I'll show you how I use VSCode tasks to automate small scripts that I use on a daily basis.
Date: 2 January 2025

The tasks below are used on a Windows 11 machine. Powershell is the main shell, so by default the tasks are executed in a Powershell terminal.

What are VSCode Tasks

Tasks are mainly used in VSCode to help developers to automate their workflow. You can use tasks to run scripts, compile code, run tests, etc. I found them also very useful to automate small scripts that you use as a sysadmin. On this page I'll show you how to manage tasks, use different shells and overall how to improve your productivity.

How to create a task

To create a task, you need to create a file called 'tasks.json' in the '.vscode' folder in the root of your project. Here is an example of a 'tasks.json' file:

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Login to Azure",
            "type": "shell",
            "command": [
                "Write-Host 'Start login to Azure' -ForegroundColor Green;",
                "az login;"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "dependsOrder": "sequence",
            "problemMatcher": []
        }
    ]
}

This is just one task and on it's own not that useful. But you can add multiple tasks to the 'tasks' array. You can also add a 'group' to group tasks together.

Group tasks

If you need specific tasks to run in order you can create multiple tasks and a group to define the order.

Example: Start a connection to a Azure Jumpbox through a Bastion

In the example below I'm using tasks to start multiple browsers and setup a connection to a kubernetes cluster:

  • The first is a group because it has a 'dependsOn' property that refers to the other tasks. The other tasks are executed in sequence.
  • The second one uses a powershell script (see below) to login to Azure.
    • As you can see in the script, you can use any normal powershell command. I especially like to use scripts if I need to provide instructions to myself (or others, as these are set in a git repository).
  • The third one uses the Azure CLI in a powershell to setup a tunnel to a Bastion in Azure.
  • The fourth one starts Chrome with a specific URL. Note that I use a different browser from my default one so I can use multiple azure identities without having to use incognito/private mode.
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "Connect to Dev",
            "detail": "Starts chrome for PIM groups; login to azure; setup the connection to the Bastion in the dev spoke.",
            "dependsOrder": "sequence",
            "dependsOn": [
                "Chrome PIM Groups",
                "Prepare Bastion",
                "Bastion Tunnel to Dev"
            ],
            "problemMatcher": []
        },
        {
            "label": "Prepare Bastion",
            "type": "shell",
            "command": [
                "./.vscode/tasks/bastion-prepare.ps1;"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "dependsOrder": "sequence",
            "problemMatcher": []
        },
        {
            "label": "Bastion Tunnel to Dev",
            "type": "shell",
            "command": [
                "Write-Host 'Start tunnel to DEVELOPMENT' -ForegroundColor Green;",
                "az network bastion tunnel --name bas-001 --resource-group rg-bastion --target-resource-id /subscriptions/aa123456-a123-a123-a123-abcd12345678/resourceGroups/rg-cluster/providers/Microsoft.Compute/virtualMachines/vm-jumpbox --resource-port 22 --port 50022;"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "new"
            },
            "dependsOrder": "sequence",
            "problemMatcher": []
        },
        {
            "label": "Chrome PIM Groups",
            "type": "shell",
            "windows": {
                "command": "start"
            },
            "osx": {
                "command": "open"
            },
            "args": [
                "C:\\Program Files\\Google\\Chrome\\Application\\chrome 'https://portal.azure.com/?feature.msaljs=true#view/Microsoft_Azure_PIMCommon/ActivationMenuBlade/~/aadgroup/provider/aadgroup'"
            ],
            "problemMatcher": []
        }
    ]
}

This is the powershell script that I use to login to Azure:

Write-Host "Make sure you have activated the correct PIM group: https://portal.azure.com/#view/Microsoft_Azure_PIMCommon/ActivationMenuBlade/~/aadgroup"
Write-Host "Login to azure (use 'az logout' in case of problems)"
# Using az login because Connect-AzAccount opens login dialog in the background
# Connect-AzAccount -SubscriptionId aa123456-a123-a123-a123-abcd12345678
az login
Write-Host "Set subscription to hub subscription which has the bastion"
Set-AzContext -Subscription aa123456-a123-a123-a123-abcd12345678 | Out-Null
az account set --subscription aa123456-a123-a123-a123-abcd12345678
# Remove the known hosts file, these are environment specific
$daysToKeepKnownHosts = 28
$limit = (Get-Date).AddDays(-$daysToKeepKnownHosts)
$knownHostsPath = 'C:\Users\sjoer\.ssh'
$knownHostsFile = 'known_hosts'
Write-Host "Rename and remove known_hosts file: $knownHostsPath\$knownHostsFile"
if (Test-Path $knownHostsPath\$knownHostsFile){
    Get-ChildItem $knownHostsPath\$knownHostsFile | Rename-Item -NewName { $_.BaseName + (Get-Date -Format "yyyyMMdd-HHmm") + $_.Extension } -Verbose
    Get-ChildItem $knownHostsPath | Where-Object { ($_.CreationTime -lt $limit) -AND ($_.Name -like "$knownHostsFile*") } | Remove-Item -Force -Verbose
} else {
    Write-Host "The file $knownHostsPath\$knownHostsFile does not exist."
}
$subscription = Get-AzContext
Write-Host "Done, you are now in $($subscription.Subscription.Name). Use one of the other tasks to continue." -foregroundcolor green
Write-Host "Subscription Name: $($subscription.Subscription.Name)" -foregroundcolor green
Write-Host "Subscription Id  : $($subscription.Subscription.Id)" -foregroundcolor green
Write-Host "Tenant Name      : $($subscription.Tenant.Name)" -foregroundcolor green
Write-Host "Tenant Id        : $($subscription.Tenant.Id)" -foregroundcolor green
 
Write-Host "Once the tunnel is open, you can connect to the jumpbox and K8S in VS Code:"
Write-Host "Jumpbox    : In VS Code, open the Remote Explorer extension from the activity bar"
Write-Host "               -> SSH Targets -> Open 127.0.0.1 (linux) in a new window"
Write-Host "K8S cluster: In VS Code, from the just new opened window,"
Write-Host "               open the Kubernetes extension (might need to be installed for ssh:127.0.0.1) from the activity bar"
Write-Host "               -> Set Kubeconfig -> Select kubeconfig from /home/azadmin/.kube/config"

Example: Start a connection to a AKS K8S Cluster

This is another example of a group task to connect to a Argo CD pod in a Kubernetes cluster:

  • The first is a group because it has a 'dependsOn' property that refers to the other tasks. The other tasks are executed in sequence.
  • The second one uses the Azure CLI to login to Azure and get the AKS credentials.
  • The third one uses the Azure CLI to setup a port forward to the Argo CD pod. It also displays the Argo CD user and password from a kubernetes secret.
  • The fourth one starts a tab to connect to the Argo CD web interface which is now available through the port forward.
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "Connect to ArgoCD",
            "detail": "Login to azure; Connect to k8s; Setup port forwarding for argoCD; Start browser.",
            "dependsOrder": "sequence",
            "dependsOn": [
                "Connect K8S",
                "Open ArgoCD",
                "Port Forward to ArgoCD"
            ],
            "problemMatcher": []
        },
        {
            "label": "Connect K8S",
            "type": "shell",
            "command": [
                "echo 'Login to azure';",
                "az logout;",
                "az login;",
                "echo 'Set the subscription';",
                "az account set --subscription aa123456-a123-a123-a123-abcd12345678;",
                "az account show;",
                "echo 'Get AKS credentials';",
                "az aks get-credentials --resource-group rg-cluster --name aks-cluster --overwrite-existing;",
                "echo 'Use kubelogin plugin for authentication';",
                "kubelogin convert-kubeconfig -l azurecli;",
                "echo 'You can now close this and continue using the K8S plugin to connect to k8s or start a new terminal to work on the commandline.'"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "new",
                "showReuseMessage": true,
                "clear": true
            },
            "dependsOrder": "sequence",
            "problemMatcher": []
        },
        {
            "label": "Port Forward to ArgoCD",
            "type": "shell",
            "command": [
                "Write-Host 'ArgoCD User: admin';",
                "kubectl get secret argocd-initial-admin-secret --namespace ops -o json | ConvertFrom-Json | select -ExpandProperty data | % { $_.PSObject.Properties | % { $_.Name + [System.Environment]::NewLine + [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($_.Value)) + [System.Environment]::NewLine + [System.Environment]::NewLine } };",
                "Write-Host 'ArgoCD Port: 8080';",
                "kubectl port-forward deployment/argo-cd-argocd-server 8080 --namespace ops"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "new",
                "showReuseMessage": true,
                "clear": true
            },
            "dependsOrder": "sequence",
            "problemMatcher": []
        },
        {
            "label": "Open ArgoCD",
            "type": "shell",
            "windows": {
                "command": "start"
            },
            "osx": {
                "command": "open"
            },
            "args": [
                "http://localhost:8080"
            ],
            "problemMatcher": []
        }
    ]
}

A task using the Git Bash shell

If you're using git on Windows you might want to use the Git Bash shell, which is automatically installed with git. You can use the following task to run a script in the Git Bash shell:

Note that using all options listed below are very important. Each one is necessary to make the task work. Using git-bash.exe directly will start the git bash in it's own window and not in the terminal of VSCode. Using the -c option allows to start the bash script and the -l option starts the bash shell as a login shell.
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "AKS - Delete all jobs",
            "type": "shell",
            "command": [
                ".vscode/tasks/delete-k8s-jobs.sh"
            ],
            "options": {
                "shell": {
                    "executable": "C:\\Program Files\\Git\\git-cmd.exe",
                    "args": [
                        "--command=usr/bin/bash.exe",
                        "-l",
                        "-c"
                    ]
                }
            },
            "isBackground": true,
            "problemMatcher": [],
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "new",
                "showReuseMessage": true
            }
        }
    ]
}

This is the script that is started by the task:

# Delete all jobs starting with shift in a namespace
export NAMESPACE=shiftops
echo "Deleting all jobs in namespace $NAMESPACE"
# Check
kubectl get jobs -n $NAMESPACE -o name | grep shift-
# Delete all the jobs
kubectl get jobs -n $NAMESPACE -o name | grep shift- |
while read job; do
    # Note that the output specified the type so no need for 'delete job', just 'delete' is enough
    kubectl delete $job -n $NAMESPACE
done

Starting tasks

When you're in the editor you can start a task by pressing ctrl + shift + p and then type 'Run Task'. You can now select the task you want to run.

If you have a lot of tasks I'd use the VSCode extension 'iulian-radu-at.vscode-tasks-sidebar' to show the tasks in the sidebar. This makes it easier to start a task.

vscodetasks.txt · Last modified: by 127.0.0.1