Can I create an Azure DevOps varIable group from azure cli and pass it some value?

7/16/2019

I have declared the following Variable group in Azure DevOps.

KUBERNETES_CLUSTER = myAksCluster
RESOURCE_GROUP = myResourceGroup

enter image description here

In the Release pipeline process, I want to create a Public Static IP address in order to assigned to some application in myAksCluster.

Via Azure cli commands I am creating the Static IP address of this way via az cli bash small script. We can assume here that I already have created the kubernetes cluster

#!/usr/bin/env bash

KUBERNETES_CLUSTER=myAksCluster
RESOURCE_GROUP=myResourceGroup

# Getting the name of the node resource group. -o tsv is to get the value without " "
NODE_RESOURCE_GROUP=$(az aks show --resource-group $RESOURCE_GROUP --name $KUBERNETES_CLUSTER --query nodeResourceGroup -o tsv)
echo "Node Resource Group:" $NODE_RESOURCE_GROUP

# Creating Public Static IP
PUBLIC_IP_NAME=DevelopmentStaticIp
az network public-ip create --resource-group $NODE_RESOURCE_GROUP --name $PUBLIC_IP_NAME --allocation-method static

# Query the ip
PUBLIC_IP_ADDRESS=$(az network public-ip list --resource-group $NODE_RESOURCE_GROUP --query [1].ipAddress --output tsv)
# Output 
# I want to use the value of PUBLIC_IP_ADDRESS variable in Azure DevOps variable  groups of the release pipeline

If I execute az network public-ip list ... command I get my public Ip address.

⟩ az network public-ip list --resource-group $NODE_RESOURCE_GROUP --query [1].ipAddress -o tsv
10.x.x.x

I want to use that PUBLIC_IP_ADDRESS value to assign it to a new Azure DevOps variable groups in my release, but doing all this process from a CLI task or Azure Cli task like part of the release pipeline process.

The idea is when my previous az cli bash small script to be executed in the release pipeline, I have a new variable in my ReleaseDev azure variable groups of this way:

enter image description here

And after that, I can use PUBLIC_STATIC_IP_ADDRESS which will be an azure devops variable like arguments to the application which will use that IP value inside my kubernetes cluster.

I have been checking some information and maybe I could create an Azure CLI task in my release pipeline to execute the az cli bash small script which is creating the public static ip address of this way: enter image description here

But is finally at the end when I get the public ip address value, that I don't know how to create from this Azure CLI task (my script) the variable PUBLIC_STATIC_IP_ADDRESS with its respective value that I got here.

Can I use an Azure CLI task from the release pipeline to get this small workflow? I have been checking somethings like this recommendation but is not clear for me

how to create an Az variable group with some value passed from my release pipeline? Is Azure CLI release pipeline task, the proper task for do that?

UPDATE

I am following the approach suugested by Lu Mike, so I have created a Powershell task and executing the following script in Inline type/mode:

# Connect-AzAccount
Install-Module -Name Az -AllowClobber -Force 

@{KUBERNETES_CLUSTER = "$KUBERNETES_CLUSTER"}
@{RESOURCE_GROUP = "$RESOURCE_GROUP"}

@{NODE_RESOURCE_GROUP="$(az aks show --resource-group $RESOURCE_GROUP --name $KUBERNETES_CLUSTER --query nodeResourceGroup -o tsv)"}
# echo "Node Resource Group:" $NODE_RESOURCE_GROUP

@{PUBLIC_IP_NAME="Zcrm365DevelopmentStaticIpAddress"}
az network public-ip create --resource-group $NODE_RESOURCE_GROUP --name $PUBLIC_IP_NAME --allocation-method static

@{PUBLIC_IP_ADDRESS="$(az network public-ip list --resource-group $NODE_RESOURCE_GROUP --query [1].ipAddress --output tsv)"}
echo "##vso[task.setvaraible variable=ipAddress;]%PUBLIC_IP_ADDRESS%"

$orgUrl="https://dev.azure.com/my-org/"

$projectName = "ZCRM365"

##########################################################################
$personalToken = $PAT # "<your PAT>" 
# I am creating a varaible environment inside the power shell task and reference it here.
##########################################################################

$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalToken)"))
$header = @{authorization = "Basic $token"}

$projectsUrl = "$($orgUrl)/$($projectName)/_apis/distributedtask/variablegroups/1?api-version=5.0-preview.1"

$requestBody = @{
    "variables" = @{
        "PUBLIC_STATIC_IP_ADDRESS" = @{
            "value" = "$PUBLIC_IP_ADDRESS"
        }
    }
    "@type" = "Vsts"
    "name" = "ReleaseVariablesDev"
    "description" = "Updated variable group"
} | ConvertTo-Json

Invoke-RestMethod -Uri $projectsUrl -Method Put -ContentType "application/json" -Headers $header -Body $requestBody
Invoke-RestMethod -Uri $projectsUrl -Method Put -ContentType "application/json" -Headers $header -Body $requestBody

IMPORTANT

As you can see, in this process I am mixing az cli commands and powershell language in this task. I am not sure if it is good. By the way I am using a Linux Agent.

I had to include -Force flag to the Install-Module -Name Az -AllowClobber -Force command to install azure powershell module


My output is the following:

2019-07-19T06:01:29.6372873Z Name                           Value
2019-07-19T06:01:29.6373433Z ----                           -----
2019-07-19T06:01:29.6373706Z KUBERNETES_CLUSTER             
2019-07-19T06:01:29.6373856Z RESOURCE_GROUP                 
2019-07-19T06:01:38.0177665Z ERROR: az aks show: error: argument --resource-group/-g: expected one argument
2019-07-19T06:01:38.0469751Z usage: az aks show [-h] [--verbose] [--debug]
2019-07-19T06:01:38.0470669Z                    [--output {json,jsonc,table,tsv,yaml,none}]
2019-07-19T06:01:38.0471442Z                    [--query JMESPATH] --resource-group RESOURCE_GROUP_NAME
2019-07-19T06:01:38.0472050Z                    --name NAME [--subscription _SUBSCRIPTION]
2019-07-19T06:01:38.1381959Z NODE_RESOURCE_GROUP            
2019-07-19T06:01:38.1382691Z PUBLIC_IP_NAME                 Zcrm365DevelopmentStaticIpAddress
2019-07-19T06:01:39.5094672Z ERROR: az network public-ip create: error: argument --resource-group/-g: expected one argument
2019-07-19T06:01:39.5231190Z usage: az network public-ip create [-h] [--verbose] [--debug]
2019-07-19T06:01:39.5232152Z                                    [--output {json,jsonc,table,tsv,yaml,none}]
2019-07-19T06:01:39.5232671Z                                    [--query JMESPATH] --resource-group
2019-07-19T06:01:39.5233234Z                                    RESOURCE_GROUP_NAME --name NAME
2019-07-19T06:01:39.5233957Z                                    [--location LOCATION]
2019-07-19T06:01:39.5234866Z                                    [--tags [TAGS [TAGS ...]]]
2019-07-19T06:01:39.5235731Z                                    [--allocation-method {Static,Dynamic}]
2019-07-19T06:01:39.5236428Z                                    [--dns-name DNS_NAME]
2019-07-19T06:01:39.5236795Z                                    [--idle-timeout IDLE_TIMEOUT]
2019-07-19T06:01:39.5237070Z                                    [--reverse-fqdn REVERSE_FQDN]
2019-07-19T06:01:39.5240483Z                                    [--version {IPv4,IPv6}]
2019-07-19T06:01:39.5250084Z                                    [--sku {Basic,Standard}] [--zone {1,2,3}]
2019-07-19T06:01:39.5250439Z                                    [--ip-tags IP_TAGS [IP_TAGS ...]]
2019-07-19T06:01:39.5251048Z                                    [--public-ip-prefix PUBLIC_IP_PREFIX]
2019-07-19T06:01:39.5251594Z                                    [--subscription _SUBSCRIPTION]
2019-07-19T06:01:40.4262896Z ERROR: az network public-ip list: error: argument --resource-group/-g: expected one argument
2019-07-19T06:01:40.4381683Z usage: az network public-ip list [-h] [--verbose] [--debug]
2019-07-19T06:01:40.4382086Z                                  [--output {json,jsonc,table,tsv,yaml,none}]
2019-07-19T06:01:40.4382346Z                                  [--query JMESPATH]
2019-07-19T06:01:40.4382668Z                                  [--resource-group RESOURCE_GROUP_NAME]
2019-07-19T06:01:40.4382931Z                                  [--subscription _SUBSCRIPTION]
2019-07-19T06:01:40.5103276Z PUBLIC_IP_ADDRESS              
2019-07-19T06:01:40.5133644Z ##[error]Unable to process command '##vso[task.setvaraible variable=ipAddress;]%PUBLIC_IP_ADDRESS%' successfully. Please reference documentation (http://go.microsoft.com/fwlink/?LinkId=817296)
2019-07-19T06:01:40.5147351Z ##[error]##vso[task.setvaraible] is not a recognized command for Task command extension. Please reference documentation (http://go.microsoft.com/fwlink/?LinkId=817296)

And maybe that is why I have some problem to execute az commands

Power shell and its respective azure task are new for me, and I am not sure about how can I get along of this process.

-- bgarcial
azure-aks
azure-devops
bash
kubernetes

2 Answers

7/17/2019

You can try to invoke REST API(Variablegroups - Update) to add or update the variable group in the script. Please refer to following script.

$orgUrl = "https://dev.azure.com/<your organization >"
$projectName = "<your project>"
$personalToken = "<your PAT>"

$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalToken)"))
$header = @{authorization = "Basic $token"}

$projectsUrl = "$($orgUrl)/$($projectName)/_apis/distributedtask/variablegroups/1?api-version=5.0-preview.1"

$requestBody = @{
  "variables" = @{
    "PUBLIC_STATIC_IP_ADDRESS" = @{
      "value" = "<the static ip you got>"
    }
  }
  "@type" = "Vsts"
  "name" = "<your variable group name>"
  "description" = "Updated variable group"
} | ConvertTo-Json

Invoke-RestMethod -Uri $projectsUrl -Method Put -ContentType "application/json" -Headers $header -Body $requestBody

Then, you will find the varaible in the group.

enter image description here

UPDATE:

You can use AZ commands directly as powershell script, since after you installed Az module for powershell, Az commands support powershell and bash. Please refer to following script.

$KUBERNETES_CLUSTER = "KUBERNETES_CLUSTER"
$RESOURCE_GROUP = "RESOURCE_GROUP"
$PUBLIC_IP_ADDRESS

$PUBLIC_IP_NAME="Zcrm365DevelopmentStaticIpAddress"
$NODE_RESOURCE_GROUP = az aks show --resource-group $RESOURCE_GROUP --name $KUBERNETES_CLUSTER --query nodeResourceGroup -o tsv | az network public-ip create --resource-group --name $PUBLIC_IP_NAME --allocation-method static

az network public-ip create --resource-group $NODE_RESOURCE_GROUP --name $PUBLIC_IP_NAME --allocation-method static

$PUBLIC_IP_ADDRESS = az network public-ip list --resource-group $NODE_RESOURCE_GROUP --query [1].ipAddress --output tsv

echo "##vso[task.setvaraible variable=ipAddress;]$PUBLIC_IP_ADDRESS"

$orgUrl="https://dev.azure.com/<org>/"

....

Please refer to following links to learn the usage of az commands in powershell.

https://docs.microsoft.com/en-us/azure/storage/common/storage-auth-aad-script

Azure CLI vs Powershell?

-- Lu Mike
Source: StackOverflow

7/17/2019

You can use the Rest API as Lu Mike mentioned to update the variable group, or you can install the Shared variable updater extension that do it for you.

But the important thing is, you need to set a variable in the Azure CLI task that you can use it in the second task (either it's Rest API task or the Shared variable updater task). so you need to add this line to your script:

echo "##vso[task.setvaraible variable=ipAddress;]%PUBLIC_IP_ADDRESS%"

Now in the next tasks you can use the variable $(ipAddress) that contains the ip value:

enter image description here

-- Shayki Abramczyk
Source: StackOverflow