Unable to deploy Azure ARM with parameters using az cli from powershell script - azure

Trying simple deployment with parameters from a PS script:
$prefix = "xxx"
$location = "switzerlandnorth"
az deployment group create `
--name $timestamp `
--resource-group $resourceGroupName `
--mode incremental `
--verbose `
--template-file .\src\ops\scripts\arm.json `
--parameters "{ `"location`": { `"value`": `"$location`" },`"projectPrefix`": { `"value`": `"$prefix`" } }"
Response with error:
Unable to parse parameter: { location: { value: switzerlandnorth }, projectPrefix: { value: xxx } }
Running from a PS1 script.

As we can see in the error that it is unable to parse the parameters. The correct way to pass the parameters to the az deployment group create command is:
az deployment group create `
--name $timestamp `
--resource-group $resourceGroupName `
--mode "incremental" `
--verbose `
--template-file ".\src\ops\scripts\arm.json" `
--parameters '{ \"location\": { \"value\": \"switzerlandnorth\" },\"projectPrefix\": { \"value\": \"xxx\" } }'
Update:
If you want to pass the PowerShell variables in the Parameters you can do something like below -
$location = "switzerlandnorth"
$projectPrefix = "xxx"
$params = '{ \"location\": { \"value\": \" ' + $location + '\" },\"projectPrefix\": { \"value\": \"' + $projectprefix + '\" } }'
az deployment group create `
--name $timestamp `
--resource-group $resourceGroupName `
--mode "incremental" `
--verbose `
--template-file ".\src\ops\scripts\arm.json" `
--parameters $params
Hope this helps!

Another way you can think of this is using objects/hashtables in PS and then converting to JSON, e.g.
$param = #{
location = "switzerlandnorth"
prefix = "foo"
}
$paramJSON = ($param | ConvertTo-Json -Depth 30 -Compress).Replace('"', '\"') # escape quotes in order to pass the command via pwsh.exe
az deployment group create -g $resourceGroupName--template-file "azuredeploy.json" -p $paramJson
This is a similar example:
https://gist.github.com/bmoore-msft/d578c815f319af7eb20d9d97df9bf657

I'll throw in my two cents here because previous answers are slim on what we are actually doing here. In short the az deployment group create command wants the --parameters argument to be a double serialized JSON string {scoff}. In order to create a value that can be handled by az deployment group create we would need to do something like this:
$stupidlyFormattedParam = #{
someAppSetting1 = #{ value = "setting 1" }
someAppSetting2 = #{ value = "setting 2" }
} | ConvertTo-Json -Compress -Depth 10 | ConvertTo-Json
az deployment group create --name someName--resource-group someGroup --parameters $stupidlyFormattedParam --template-file .\someFile.json

Related

AzureRM `New-AzureRmResource` works but `az resource create doesn't`

i've been tasked with migrating some PowerShell scripts from AzureRM to azure cli. We have some deep resources that get set on App Services to enable complex logging.
This AzureRM script works fine. Even the Get-AzureRmResouce call works, but the azure cli does not and even the REST api call does not. I get a Resource not found error.
this code works:
New-AzureRmResource -ResourceGroupName $ResourceGroupName `
-ResourceName ($AppName + "/AntMDS/" + $SettingName) `
-ResourceType "Microsoft.Web/serverfarms/firstPartyApps/settings" `
-Properties $SettingProperties `
-ApiVersion 2015-08-01 -Force | Out-Null
this code does not:
$temp = New-TemporaryFile
$SettingProperties | ConvertTo-Json | Out-File $temp.FullName
$result = az resource create --resource-group $ResourceGroupName `
--name "$AppName/AntMDS/$SettingName" `
--resource-type "Microsoft.Web/serverfarms/firstPartyApps/settings" `
--properties "#$($temp.FullName)" `
--api-version "2015-08-01" `
| ConvertFrom-Json
if(-not $result) {
throw "Unable to create resource: ""$AppName/AntMDS/$SettingName"" on group $ResourceGroupName"
}
Remove-Item $temp
says "Resource not found"

How to import a specification into a versionset of Azure APIM using Azure-CLI

I'm trying to update an existing version in a versionset inside an Azure API Management service with a new specification using Azure CLI.
I know it does support importing it as an API without a versionset:
az apim api import `
--path "/as" `
--resource-group "myResourceGroup" `
--service-name "test-apim" `
--api-id "test-apim" `
--specification-format "OpenApiJson" `
--specification-path "..\swagger.json"
And I also know that you can use the Azure Powershell modules to fetch a version set and use this to upload a new specification:
$apiMgmtContext = New-AzApiManagementContext `
-ResourceGroupName "myResourceGroup" `
-ServiceName "test-apim"
$versionSet = Get-AzApiManagementApiVersionSet -Context $apiMgmtContext |
Where-Object { $_.DisplayName -eq "my-version-set" } |
Sort-Object -Property ApiVersionSetId -Descending |
Select-Object -first 1
Import-AzApiManagementApi `
-Context $apiMgmtContext `
-ApiVersionSetId $versionSet.ApiVersionSetId `
-ServiceUrl "http" `
-SpecificationFormat "OpenApiJson" `
-SpecificationPath "..\swagger.json" `
-Path "/as" `
-ApiId "test-apim"
But does anyone know if this can be done with the az cli as the powershell modules will eventually become obsolete?
Looking at the documentation, it supports version set.
You need to use the parameter --api-version-set-id:
az apim api import `
--path "/as" `
--resource-group "myResourceGroup" `
--service-name "test-apim" `
--api-id "test-apim" `
--specification-format "OpenApiJson" `
--specification-path "..\swagger.json" `
--api-version-set-id "my-version-set-id"
Also there is no indication that Az Powershell will become obsolete for the moment.

creating AKS cluster with managed identity and associated with an acr by az cli script error

I am new to power-shell scripts and I tried to run below script that will create an AKS-cluster with managed identity also associated with an ACR . But it was giving an error at "managed identity" line..
Param(
[parameter(Mandatory = $false)]
[string]$subscriptionName = "azure-subcription",
[parameter(Mandatory = $false)]
[string]$resourceGroupName = "demoRG",
[parameter(Mandatory = $false)]
[string]$resourceGroupLocaltion = "East US 2",
[parameter(Mandatory = $false)]
[string]$clusterName = "nginxCluster",
[parameter(Mandatory = $false)]
[int16]$workerNodeCount = 3,
[parameter(Mandatory = $false)]
[string]$kubernetesVersion = "1.19.3",
[parameter(Mandatory = $false)]
[string]$acrRegistryName = "ngAcrRegistrydemo"
)
# Set Azure subscription name
Write-Host "Setting Azure subscription to $subscriptionName" -ForegroundColor Yellow
az account set --subscription=$subscriptionName
$aksRgExists = az group exists --name $resourceGroupName
Write-Host "$resourceGroupName exists : $aksRgExists"
if ($aksRgExists -eq $false) {
# Create resource group name
Write-Host "Creating resource group $resourceGroupName in region $resourceGroupLocaltion" -ForegroundColor Yellow
az group create `
--name=$resourceGroupName `
--location=$resourceGroupLocaltion `
--output=jsonc
}
$aks = az aks show `
--name $clusterName `
--resource-group $resourceGroupName `
--query name | ConvertFrom-Json
$aksCLusterExists = $aks.Length -gt 0
if ($aksCLusterExists -eq $false) {
# Create AKS cluster
Write-Host "Creating AKS cluster $clusterName with resource group $resourceGroupName in region $resourceGroupLocaltion" -ForegroundColor Yellow
az aks create `
--resource-group=$resourceGroupName `
--name=$clusterName `
--node-count=$workerNodeCount `
--enable-managed-identity `
--output=jsonc `
--kubernetes-version=$kubernetesVersion `
--aks-custom-headers="CustomizedUbuntu=aks-ubuntu-1804,ContainerRuntime=containerd" `
--attach-acr=$acrRegistryName
}
# Get credentials for newly created cluster
Write-Host "Getting credentials for cluster $clusterName" -ForegroundColor Yellow
az aks get-credentials `
--resource-group=$resourceGroupName `
--name=$clusterName `
--overwrite-existing
Write-Host "Successfully created cluster $clusterName with $workerNodeCount node(s)" -ForegroundColor Green
Write-Host "Creating cluster role binding for Kubernetes dashboard" -ForegroundColor Green
# kubectl create clusterrolebinding kubernetes-dashboard `
# -n kube-system `
# --clusterrole=cluster-admin `
# --serviceaccount=kube-system:kubernetes-dashboard
Error Msg is coming like as "az: error: unrecognized arguments: --enable-managed-identity".
Please help or give suggestions on how to enable managed identity also associated with AKS-clusters.
Many Thanks,
First, there is no parameter --aks-custom-headers of the CLI command az aks create, and the other two-parameter --enable-managed-identity and --attach-acr. You can try it again without the character =, just append the value behind the parameters:
az aks create `
--resource-group $resourceGroupName `
--name $clusterName `
--node-count $workerNodeCount `
--enable-managed-identity `
--kubernetes-version $kubernetesVersion `
--attach-acr $acrRegistryName
You can take a look at the command az aks create. In addition, that's managed identity, not the service principal, so you need to use the command az identity list to get the identity of the AKS in the node group and you can get the node group through CLI command like below:
az aks show -g aksGroup -n aksCluster --query nodeResourceGroup
I updated Azure CLI (version 2.15.1 or later) by using below
https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-windows?tabs=azure-powershell
and executed aks creation ps-script as above and it working perfectly .
AKS-infrastructure are created .
Many Thanks..

chaining az calls in a powershell script

I'm trying to build a script that sets up my Azure environment, but passing information from one call to the next is proving to be tricky. I'm not sure how to treat the data returned as an object.
# az network public-ip create output (truncated)
#{
# "publicIp": {
# "ipAddress": "1.1.1.1",
# }
#}
$staticIpCreate = (az network public-ip create --resource-group mygroup --name myipname --allocation-method static | ConvertFrom-Json)
$staticIp = ($staticIpCreate | Select-Object ipAddress)
Write-Host "Static Ip :$($staticIp)"
You do not need to combine them, here is PowerShell command to achieve the samething
$PIP = New-AzureRmPublicIpAddress -AllocationMethod Static -ResourceGroupName DDemo -Location Westus2 -Name DDemoIPTest
Write-Host "Static IP:" $PIP.IpAddress
Image
from jessehouwing's comment
Write-Debug "////// static ip"
$staticIpCreate = az network public-ip create --resource-group mygroup --name myipname --allocation-method static | ConvertFrom-Json
$staticIp = $staticIpCreate.publicIp.ipAddress
Write-Host "Static Ip :$($staticIp)"

Why does certain Azure CLI commands require az login

In our VSTS release pipeline we want to call a powershell script that adds a function key for one of my Azure Functions (using the Key Management rest API).
I've created a script based on this article:
https://www.markheath.net/post/managing-azure-function-keys
Param(
[string] [Parameter(Mandatory=$true)] $ResourceGroup,
[string] [Parameter(Mandatory=$true)] $AppName,
[string] [Parameter(Mandatory=$true)] $FunctionName,
[string] [Parameter(Mandatory=$true)] $KeyName,
[string] [Parameter(Mandatory=$true)] $KeyValue
)
function getAuthenticationToken([string]$appName, [string]$resourceGroup)
{
$user = az webapp deployment list-publishing-profiles -n $appName -g $resourceGroup `
--query "[?publishMethod=='MSDeploy'].userName" -o tsv
$pass = az webapp deployment list-publishing-profiles -n $appName -g $resourceGroup `
--query "[?publishMethod=='MSDeploy'].userPWD" -o tsv
$pair = "$($user):$($pass)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$jwt = Invoke-RestMethod -Uri "https://$appName.scm.azurewebsites.net/api/functions/admin/token" -Headers #{Authorization=("Basic {0}" -f $encodedCreds)} -Method GET
return $jwt
}
function setFunctionKey([string]$appName, [string]$functionName, [string] $keyName, [string]$keyValue, [string]$jwt)
{
$body = (#{
"name" = $keyName
"value" = $keyValue
} | ConvertTo-Json)
#Setting the SecurityProtocol is a workaround for calling Azure APIs, I think?
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Invoke-RestMethod -Uri "https://$appName.azurewebsites.net/admin/functions/$functionName/keys/$keyName/" `
-Headers #{Authorization=("Bearer $jwt")} `
-Method PUT `
-ContentType "application/json" `
-Body $body
} catch {
$_.Exception | Format-List -Force
}
}
$jwt = getAuthenticationToken $AppName $ResourceGroup
setFunctionKey $AppName $FunctionName $KeyName $KeyValue $jwt
Write-Host "Specified key '$KeyName' has been added to $FunctionName"
Works locally, but when running it VSTS it gets and error when calling
$user = az webapp deployment list-publishing-profiles -n $appName -g $resourceGroup `
--query "[?publishMethod=='MSDeploy'].userName" -o tsv
with the message:
ERROR: Please run 'az login' to setup account.
We have other azure cli calls that works, ex: az cosmosdb database, so I guess our Service Principle connections are in place. What could be the issue here?
Seems like we had an old powershell version containing a bug that keeps the old service connection authentication context when you create a new service connection authentication, which I did in this case.
So we updated powershell on our build agents and we got things going!
From the document that you posted above, there is something you could miss.
The first step is that we need to get the credentials to call the Kudu
API. If you're authenticated with the Azure CLI, you can do that by
calling the az webapp deployment list-publishing-profiles command and
extracting the userName and userPWD for MSDeploy. You need to provide
the function app name and resource group name.
It seems that you should authenticate the Azure CLI before you use them.

Resources