Local-exec using powershell not executing commands - terraform

Having some issues when trying to run Powershell commands through a null-resource 'local-exec". I’m trying to run a PowerShell command with some additional parameters:
provisioner “local-exec” {
interpreter = [“PowerShell”, “-Command”]
command = <<EOT
$ResourceGroupName = '"${module.rg.resource_group.name}"'
$FunctionAppName = '"${var.function_apps[each.key].name}"'
$SubscriptionId = '"${var.subscriptions.id}"'
# Option 1 - does nothing
Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId
# Option 2 - does nothing
(Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId)
# Option 3 - shows the correct cmd line with correctly expanded variables but does not execute the command
"Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId"
# Option 4 - when I hardcode the values it works
Get-AzFunctionApp -ResourceGroupName "real_rg_name" -Name "real_rg_appname" -SubscriptionId real_subscr_id
EOT
}
Only when I hardcode the values the Az command executes.

I tested the same with something like below :
provider "azurerm" {
features{}
}
data "azurerm_resource_group" "example"{
name = "ansumantest"
}
variable "function_apps" {
default = ["ansumantestfunc1","ansumantestfunc2"]
}
variable "Subscription" {
default = "948d4068-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
resource "null_resource" "example2" {
count = length(var.function_apps)
provisioner "local-exec" {
command = <<Settings
$ResourceGroupName = "${data.azurerm_resource_group.example.name}"
$FunctionAppName = "${var.function_apps[count.index]}"
$SubscriptionId = "${var.Subscription}"
Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId
Settings
interpreter = ["PowerShell", "-Command"]
}
}
Output:
Note :
I am using Terraform v1.1.0 on windows_amd64
provider registry.terraform.io/hashicorp/azurerm v2.90.0
provider registry.terraform.io/hashicorp/null v3.1.0

Related

Setup and deploy Azure function using PowerShell

I try to setup and deploy Azure Function by using PowerShell script based on this topic: Setup Azure Function from PowerShell
My script looks like this:
#=============Defining All Variables=========
$location = 'Central US'
$resourceGroupName = 'MyResourceGroup'
$subscriptionId = 'MysubscriptionId'
$functionAppName = 'MyfunctionAppName'
$appServicePlanName = 'ASP-test-8b50'
$tier = 'Dynamic'
$archivePath = 'd:\TestAzureFunc.zip'
Connect-AzAccount
#========Creating Azure Resource Group========
$resourceGroup = Get-AzResourceGroup | Where-Object { $_.ResourceGroupName -eq $resourceGroupName }
if ($resourceGroup -eq $null)
{
New-AzResourceGroup -Name $resourceGroupName -Location $location -force
}
#selecting default azure subscription by name
Select-AzSubscription -SubscriptionID $subscriptionId
Set-AzContext $subscriptionId
#========Creating App Service Plan============
New-AzAppServicePlan -ResourceGroupName $resourceGroupName -Name $appServicePlanName -Location $location -Tier $tier
$functionAppSettings = #{
ServerFarmId="/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Web/serverfarms/$appServicePlanName";
alwaysOn=$True;
}
#========Creating Azure Function========
$functionAppResource = Get-AzResource | Where-Object { $_.ResourceName -eq $functionAppName -And $_.ResourceType -eq "Microsoft.Web/Sites" }
if ($functionAppResource -eq $null)
{
New-AzResource -ResourceType 'Microsoft.Web/Sites' -ResourceName $functionAppName -kind 'functionapp' -Location $location -ResourceGroupName $resourceGroupName -Properties $functionAppSettings -force
}
#========Defining Azure Function Settings========
$AppSettings =#{}
$AppSettings =#{'FUNCTIONS_EXTENSION_VERSION' = '~2';
'FUNCTIONS_WORKER_RUNTIME' = 'dotnet';}
Set-AzWebApp -Name $functionAppName -ResourceGroupName $resourceGroupName -AppSettings $AppSettings
#========Deploy Azure Function from zip========
Publish-AzWebapp -ResourceGroupName $resourceGroupName -Name $functionAppName -ArchivePath $archivePath
The script works without errors. Resource group and Function App created as needed. But the list of functions of the Function App is empty.
Function details here:
My intuition tells me that I've forgotten something. But I don't know what.
Could you advise me on how to deploy my Azure function properly?
One of the workaround you can follow ,
Looking at your script we need to ensure that we are providing function app configuration as below cmdlts the link you followed:-
$AzFunctionAppSettings = #{
APPINSIGHTS_INSTRUMENTATIONKEY = $AppInsightsKey;
AzureWebJobsDashboard = $AzFunctionAppStorageAccountConnectionString;
AzureWebJobsStorage = $AzFunctionAppStorageAccountConnectionString;
FUNCTIONS_EXTENSION_VERSION = "~4";
FUNCTIONS_WORKER_RUNTIME = "dotnet";
}
And also make sure that the storage account connection string you provided in the function is same as here providing.
And then you can navigate to Kudu API to check the wwwroot folder is exist or not.
For more information please refer the below links:-
SO THREAD|Powershell command Publish-AzWebApp not publishing apllication
BLOG|How to Deploy Azure Function Apps With Powershell.

Deploying multiple scripts with CustomScriptExtension on an Azure Windows VM

I'm trying to deploy multiple PowerShell scripts to an Azure Windows VM by using the CustomScriptExtension.
The scripts are independent from each other so the order of their deployment doesn't matter. Also the scripts are in same blob container.
I have already a working template as below for installing one script at the moment:
$resourceGroup = "myResourceGroup"
$vmName = "myVM"
$location = "easteurope"
$storageAcctName = "myStorageAcct"
$storageKey = $env:ARM_ACCESS_KEY
$fileUri = #("https://xxxxx.blob.core.windows.net/xxxx/01-installTools.ps1")
$protectedSettings = #{"storageAccountName" = $storageAcctName; "storageAccountKey" = $storageKey};
$settings = #{"fileUris" = $fileUri;"commandToExecute" ="powershell -ExecutionPolicy Unrestricted -File 01-installTools.ps1"};
#run command
Set-AzVMExtension -ResourceGroupName $resourceGroup `
-Location $location `
-ExtensionName "IIS" `
-VMName $vmName `
-Publisher "Microsoft.Compute" `
-ExtensionType "CustomScriptExtension" `
-TypeHandlerVersion "1.8" `
-Settings $settings `
-ProtectedSettings $protectedSettings;
Also is it possible to use 2 CustomScriptExtensions?
I get a TypeHandlerVersion error if i try to do that.

Local-exec using powershell throws Cannot index into a null array

Had some help in getting PowerShell command to run in Terraform local-exec See here for code. Just hit the next hurdle as that I can now run various 'get-az' commands with parameters but if I want to run
Update-AzFunctionAppSetting -ResourceGroupName "MyResourceGroup" -Name "MyFunctionApp" -SubscriptionId "MySubscriptionId" -AppSetting #{"testmw" = "2"}
it throws an error:
Update-AzFunctionAppSetting : Cannot index into a null array.
Please use the below code as per your requirement :
provider "azurerm" {
features{}
}
data "azurerm_resource_group" "example"{
name = "ansumantest"
}
variable "function_apps" {
default = ["ansumanfunc1","ansumanfunc2"]
}
variable "Subscription" {
default = "SubID"
}
resource "null_resource" "example2" {
count = length(var.function_apps)
provisioner "local-exec" {
command = <<Settings
$ResourceGroupName = "${data.azurerm_resource_group.example.name}"
$FunctionAppName = "${var.function_apps[count.index]}"
$SubscriptionId = "${var.Subscription}"
Get-AzFunctionApp -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionId
Update-AzFunctionAppSetting -ResourceGroupName $ResourceGroupName -Name $FunctionAppName -SubscriptionId $SubscriptionID -AppSetting #{"testmw" = "2"}
Settings
interpreter = ["PowerShell", "-Command"]
}
}
Output:

Powershell Loop with two variables

I am looking for a way to pipe many (100 paired variables) items into this powershell script. Each single command has two variables ResourceGroup and AccountName. I can build an array, but not sure how to get the script to execute the paired variables.
EDIT: Would there be any way to import these variables from CSV , or pull them directly.
$rgName = "<resource-group>"
$accountName = "<storage-account>"
$location = "<location>"
# Create a storage account with MinimumTlsVersion set to TLS 1.1.
New-AzStorageAccount -ResourceGroupName $rgName `
-AccountName $accountName `
-Location $location `
-SkuName Standard_GRS `
-MinimumTlsVersion TLS1_1
# Read the MinimumTlsVersion property.
(Get-AzStorageAccount -ResourceGroupName $rgName -Name $accountName).MinimumTlsVersion
# Update the MinimumTlsVersion version for the storage account to TLS 1.2.
Set-AzStorageAccount -ResourceGroupName $rgName `
-AccountName $accountName `
-MinimumTlsVersion TLS1_2
# Read the MinimumTlsVersion property.
(Get-AzStorageAccount -ResourceGroupName $rgName -Name $accountName).MinimumTlsVersion
If you want to group variables together, you could use an array of System.Management.Automation.PSCustomObject, then iterate this array and run your code:
param (
[Parameter(Mandatory = $true)]
[PSCustomObject[]]
$StorageAccountData
)
foreach ($obj in $StorageAccountData) {
$rgName = $obj.ResourceGroupName
$accountName = $obj.AccountName
$location = $obj.Location
# Create a storage account with MinimumTlsVersion set to TLS 1.1.
New-AzStorageAccount -ResourceGroupName $rgName `
-AccountName $accountName `
-Location $location `
-SkuName Standard_GRS `
-MinimumTlsVersion TLS1_1
# Read the MinimumTlsVersion property.
(Get-AzStorageAccount `
-ResourceGroupName $rgName `
-Name $accountName).MinimumTlsVersion
# Update the MinimumTlsVersion version for the storage account to TLS 1.2.
Set-AzStorageAccount `
-ResourceGroupName $rgName `
-AccountName $accountName `
-MinimumTlsVersion TLS1_2
# Read the MinimumTlsVersion property.
(Get-AzStorageAccount `
-ResourceGroupName $rgName `
-Name $accountName).MinimumTlsVersion
}
Then you could run this script like so:
PS C:\Users\user> $storageAccountData = #(
>> [PSCustomObject]#{
>> ResourceGroupName = 'storageRG'
>> AccountName = 'storage1'
>> Location = 'australiaeast'
>> }
>> [PSCustomObject]#{
>> ResourceGroupName = 'storageRG'
>> AccountName = 'storage2'
>> Location = 'australiaeast'
>> }
>> )
PS C:\Users\user> script.ps1 -StorageAccountData $storageAccountData
If you want to pipe this into the script, you can create a function and use ValueFromPipeline:
function MyFunction {
[CmdletBinding()]
param (
[Parameter(
Mandatory = $true,
ValueFromPipeline = $true
)]
[PSCustomObject[]]
$StorageAccountData
)
# rest of your code
}
Then pass the array of PSCustomObject down then pipeline to this function with $storageAccountData | MyFunction. Make sure to dot source the script to load the function into your preferred scope before calling the function.
Update
If you wanted to read from a CSV file(e.g. storage-accounts.csv):
AccountName,ResourceGroupName,Location
storage1,storageRG,australiaeast
storage2,storageRG,australiaeast
You just need use Import-Csv:
$storageAccountData = Import-Csv -Path .\storage-accounts.csv
foreach ($obj in $storageAccountData) {
# rest of your code
}

Custome Linux VM Extension on Azure

Ttrying to run .sh script via custome script extension via set-azvmextension but nither its througing an error nor output gettting generated on linux vm.
$resourceGroupName = "abc-RG"
$storageAccountName = "abcdiag"
$containerName = "public"
$location = "Central India"
$vmName = "abclinux2"
$extensionName = "vm_rwq"
$deploymentScript = "dd.sh"
$destintionPath = "/tmp/"
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{"fileUris" = "[https://abcdiag.blob.core.windows.net/public/dd.sh]"; "commandToExecute" = "sh dd.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName >>
If you want to use Azure Custom Script Extension Version 1 with Linux virtual machines, the publisher should be Microsoft.OSTCExtensions and the type should be CustomScriptForLinux. For more details, please refer to the document
For example
$resourceGroupName = ""
$storageAccountName = ""
$location = ""
$vmName = ""
$extensionName = "vm_rwq"
$fileUri = #("https://jimtestperfdiag516.blob.core.windows.net/test/config-music.sh")
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName "test" -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{'fileUris' =$fileUri; "commandToExecute" = "./config-music.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName -Name $extensionName -Publisher "Microsoft.OSTCExtensions" -Type "CustomScriptForLinux" -TypeHandlerVersion "1.5" -Settings $Settings -ProtectedSettings $ProtectedSettings
Update
According to my research, Azure Custom Script Extension Version 1 does not support Red Hat operating System VM. For more details, please refer to the document
So if you want to install Custom Script Extension on Red Hat VM, we should use the new version: version 2. For further information, please refer to the article. Besides, if you want to use script to install the extension on Azure Linux VM, Azure CLI is a better way.
az vm extension set \
--resource-group myResourceGroup \
--vm-name myVM \
--name customScript \
--publisher Microsoft.Azure.Extensions \
--settings ./script-config.json \
--protected-settings ./protected-config.json
But, if you still want to use PowerShell, please refer to the following script
$resourceGroupName = ""
$storageAccountName = ""
$location = ""
$vmName = ""
$extensionName = "vm_rwq"
$fileUri = #("https://jimtestperfdiag516.blob.core.windows.net/test/config-music.sh")
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName "test" -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{'fileUris' =$fileUri; "commandToExecute" = "./config-music.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName -Name $extensionName `
-Publisher "Microsoft.Azure.Extensions" -Type "CustomScript" `
-TypeHandlerVersion "2.1" -Settings $Settings -ProtectedSettings $ProtectedSettings

Resources