Passing Terraform output to Powershell task in Azure Devosps - azure

In Azure DevOps we have the follwing YAML pipeline which is applying Terraform configuration from a CmdLine task.
The Output task should return the ObjectId of a Data Factory after it is deployed by Terraform.
I would like to use that ObjectId and pass it to the next Azure Powershell Task as a parameter so I can add that Id as member to an AzureADGroup.
How can I use the output from the step called 'Terraform output' in the next Powershell Task?
- task: CmdLine#2
displayName: Terraform Apply
enabled: False
inputs:
script: terraform apply -auto-approve -input=false tfplan
workingDirectory: infrastructure/tf_scripts/dev
- task: CmdLine#2
displayName: Terraform output
enabled: False
inputs:
script: |
terraform output adf_objectid
workingDirectory: infrastructure/tf_scripts/dev
- task: AzurePowerShell#4
displayName: 'Azure PowerShell script: InlineScript'
inputs:
azureSubscription: 'a6cb1cd3-8d5e-4db6-8af5-bcb66492d5cc'
ScriptType: 'InlineScript'
Inline: |
$spn=(terraform output adf_objectid)
Connect-AzureAD -AadAccessToken $aadToken -AccountId $context.Account.Id -TenantId $context.tenant.id -MsAccessToken $graphToken
Add-AzureADGroupMember -ObjectId xxxxx-xxxxx-xxxxx -RefObjectId $spn
workingDirectory: wd/scripts/dev
azurePowerShellVersion: 'LatestVersion'

Passing Terraform output to Powershell task in Azure Devosps
You could try to use the the Logging Command to set the adf_objectid as an azure devops pipeline variable:
echo ##vso[task.setvariable variable=spn]$(terraform output adf_objectid)
Check the similar thread for some details.

Related

unable to pass parameter from azure Devops yaml to PowerShell

parameters:
- name: AzureSubscription
default: 'abc'
- name: BlobName
type: string
default: ""
stages:
- stage: MyStage
displayName: 'My Stage'
variables:
- name: sas
jobs:
- job: ABC
displayName: ABC
steps:
- task: AzureCLI#2
displayName: 'XYZ'
inputs:
azureSubscription: ${{ parameters.AzureSubscription }}
scriptType: pscore
arguments:
scriptLocation: inlineScript
inlineScript: |
$sas=az storage account generate-sas --account-key "mykey" --account-name "abc" --expiry (Get-Date).AddHours(100).ToString("yyyy-MM-dTH:mZ") --https-only --permissions rw --resource-types sco --services b
Write-Host "My Token: " $sas
- task: PowerShell#2
inputs:
targetType: 'filepath'
filePath: $(System.DefaultWorkingDirectory)/psscript.ps1
arguments: >
-Token "????"
-BlobName "${{parameters.BlobName}}"
displayName: 'some work'
In this Azure Devops yaml, i have created 2 tasks. AzureCLI#2 and PowerShell#2
In AzureCLI#2 i get value in $sas varaible. Write-Host confirms that, but $sas does not get passes as parameter to PowerShell#2 powershell file as parameter.
"${{parameters.BlobName}}" is working fine. In powershell i am able to read that value.
How to pass sas variable value?
Tried
-Token $sas # not worked
-Token "${{sas}}" # not worked
Different tasks in Azure Pipeline don't share a common runspace that would allow them to preserve or pass on variables.
For this reason Azure Pipelines offers special logging commands that allow to take string output from a task to update an Azure Pipeline environment variable that can be used in subsequent tasks: Set variables in scripts (Microsoft Docs).
In your case you would use a logging command like this to make your sas token available to the next task:
Write-Host "##vso[task.setvariable variable=sas]$sas"
In the argument of your subsequent task (within the same job) use the variable syntax of Azure Pipelines:
-Token '$(sas)'

Execute simple SQL query though Azure Devops CICD pipeline

I am new to Azure Devops and CICD pipeline. I have been tasked to create a CICD pipeline to execute a SQL query from Azure Devops CI/CD pipeline. How do I do that? Any suggestion would be helpful.
SQL queries can be ran via the ADO tasks
Something like:
variables:
AzureSubscription: '<Azure service connection>'
ServerName: '<Database server name>'
DatabaseName: '<Database name>'
AdminUser: '<SQL user name>'
AdminPassword: '<SQL user password>'
SQLFile: '<Location of SQL file in $(Build.SourcesDirectory)>'
steps:
- task: AzurePowerShell#2
displayName: Azure PowerShell script: FilePath
inputs:
azureSubscription: '$(AzureSubscription)'
ScriptPath: '$(Build.SourcesDirectory)\scripts\SetAzureFirewallRule.ps1'
ScriptArguments: '$(ServerName)'
azurePowerShellVersion: LatestVersion
- task: CmdLine#1
displayName: Run Sqlcmd
inputs:
filename: Sqlcmd
arguments: '-S $(ServerName) -U $(AdminUser) -P $(AdminPassword) -d $(DatabaseName) -i $(SQLFile)'
- task: AzurePowerShell#2
displayName: Azure PowerShell script: FilePath
inputs:
azureSubscription: '$(AzureSubscription)'
ScriptPath: '$(Build.SourcesDirectory)\scripts\RemoveAzureFirewallRule.ps1'
ScriptArguments: '$(ServerName)'
azurePowerShellVersion: LatestVersion
Note the extra steps is to remove the firewall if you are utilizing firewall rules

I cannot work out why this Azure CLI wont work in my Azure Pipeline

I keep getting the following problem in my pipeline when passing a runtime variable into the following two CLI commands.
az webapp create --resource-group $(RG) --plan $(azureSubscription) --name "%APPNAME%"'
az webapp config appsettings set --name "%APPNAME%"' --resource-group $(RG) --settings '/home/vsts/work/1/s/studentsettings.json' --subscription $(azureSubscription)
This is the Error:
/home/vsts/work/_temp/azureclitaskscript1617264397722.sh: line 1: syntax error near unexpected token `('
I have attached a snippet of the code that I have made please can someone help me. I have spent 8 hours trying to fix this and a late night. I need this to work...
- job: job2
displayName: 'Get Variable Value for Student Env'
dependsOn: job1
steps:
- task: AzureCLI#1
displayName: 'Azure CLI '
inputs:
azureSubscription: $(azureSubscription)
scriptLocation: inlineScript
inlineScript: |
mkdir $(Pipeline.Workspace)\BlobFile
az storage blob download --container-name $(containername) --file '$(Pipeline.Workspace)/s/student.json' --name 'student.json' --connection-string 'MY VALUE'
az storage blob download --container-name 'private' --file '$(Pipeline.Workspace)/s/studentsettings.json' --name 'studentappsettings.json' --connection-string 'MY VALUE'
- pwsh: |
cd '/home/vsts/work/1/s/'
ls
$armOutput = Get-Content '/home/vsts/work/1/s/student.json' | convertfrom-json
$student = $armOutput.studentvalue #use student not studentvalue
$type = $armOutput.type
$appservice = $armOutput.appservicevalue
Write-Host "The value of [$student] is [$appservice]"
Write-Host "##vso[task.setvariable variable=studentvalue;isOutput=true]$student" #use studentvalue not $studentvalue
Write-Host "##vso[task.setvariable variable=appservicevalue;isOutput=true]$appservice" #use appservicevalue not $appservice
name: setvarStep
- script: echo $(setvarStep.studentvalue)
- script: echo $(setvarStep.appservicevalue)
name: echovar
- job: job3
displayName: Create Web App
dependsOn: job2
variables:
webappname: $[ dependencies.job2.outputs['setvarStep.studentvalue'] ]
appservicename: $[ dependencies.job2.outputs['setvarStep.appservicevalue'] ]
steps:
- script: export APPNAME=webappname
- script: echo %APPNAME%
- script: export APPPLAN=appservicename
- script: echo %APPPLAN%
# Create Web App
- task: AzureCLI#1
displayName: 'Create Web App in $(appservicename)'
inputs:
azureSubscription: $(azureSubscription)
scriptLocation: inlineScript
inlineScript: |
az webapp create --resource-group $(RG) --plan $(azureSubscription) --name "%APPNAME%"'
# Download Artifact File
- download: none
- task: DownloadPipelineArtifact#2
displayName: 'Download Build Artifacts'
inputs:
patterns: '**/*.zip'
path: '$(Build.ArtifactStagingDirectory)'
# deploy to Azure Web App
- task: AzureWebApp#1
displayName: 'Azure Web App Deploy: $(webappname)'
inputs:
package: $(Build.ArtifactStagingDirectory)/**/*.zip
azureSubscription: $(appconnectionname)
ConnectedServiceName: $(appconnectionname)
appName: '$(webappname)'
ResourceGroupName: $(RG)
# Change App Settings
- task: AzureCLI#1
displayName: 'Change WebApp Settings'
inputs:
azureSubscription: $(azureSubscription)
scriptLocation: inlineScript
inlineScript: |
az webapp config appsettings set --name "%APPNAME%"' --resource-group $(RG) --settings '/home/vsts/work/1/s/studentsettings.json' --subscription $(azureSubscription)
/home/vsts/work/_temp/azureclitaskscript1617264397722.sh: line 1: syntax error near unexpected token `('
From the error messages, it seems that there are some issue with the format of Azure Cli command.
There are two points you need to check:
1.In the Azure CLI command, It contains an extra character ' at the end of the command.
2.You could try to use the format $(webappname) to call the variable instead of %APPNAME%
Here is an example:
- job: job3
displayName: Create Web App
dependsOn: job2
variables:
webappname: $[ dependencies.job2.outputs['setvarStep.studentvalue'] ]
appservicename: $[ dependencies.job2.outputs['setvarStep.appservicevalue'] ]
steps:
- script: |
set APPNAME=webappname
- script: echo %APPNAME%
- script: export APPPLAN=appservicename
- script: echo %APPPLAN%
# Create Web App
- task: AzureCLI#1
inputs:
azureSubscription: $(azureSubscription)
scriptLocation: 'inlineScript'
inlineScript: |
az webapp create --resource-group $(RG) --plan $(azureSubscription) --name $(webappname)

Can't run PowerShell script in Azure DevOps Pipeline 'parse error'

So, I'm new to Azure Devops (but not Azure or PowerShell). I've got two scripts as tasks in my pipeline, the first runs perfectly (Note: no az module commands). The second one fails (It has one Az call). The error I get in the pipeline is:
ParserError: /home/vsts/work/_temp/3f7b3ce1-6afb-46f3-b00d-1efe35fbac71.ps1:5
Line |
5 | } else {
| ~
| Unexpected token '}' in expression or statement.
Here is the thing... I don't have '} else {' in my script or at least, I removed it and got the same error.
So whatever is causing this is more fundamental than my script. I assumed that '/home/vsts/work/_temp/3f7b3ce1-6afb-46f3-b00d-1efe35fbac71.ps1' was my script copied to the remote syste, but it doesn't seem to be the case.
Is there any way, I can find out what that file is?
The task is 'PowerShell#2' with 'pwsh: true' set.
Thanks!
YAML:
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: 'Pay-As-You-Go(<guid>)'
subscriptionId: '<guid>'
action: 'Create Or Update Resource Group'
resourceGroupName: 'project-Test'
location: 'East US 2'
templateLocation: 'Linked artifact'
csmFile: 'deploy.template.json'
csmParametersFile: 'deploy.parameters.json'
deploymentMode: 'Incremental'
deploymentOutputs: 'DeploymentOutput'
- task: PowerShell#2
inputs:
targetType: 'inline'
script: $(System.DefaultWorkingDirectory)/Get-ArmDeploymentOutput.ps1 -ArmOutputString '$(DeploymentOutput)' -MakeOutput -ErrorAction Stop
pwsh: true
displayName: Get-ArmDeploymentOutput
- task: PowerShell#2
inputs:
targetType: 'inline'
script: $(System.DefaultWorkingDirectory)/Set-AzWebAppIPRestriction.ps1 -Priority 100 -Action 'Allow' -WebAppId '$(WebAppId)' -PipId '$(gwpipId)'' -ErrorAction Stop
pwsh: true
displayName: Set-AzWebAppIPRestriction
I found there is an extra ' in -PipId '$(gwpipId)'' in the script of your second powershell task. Maybe it caused the error.
script: $(System.DefaultWorkingDirectory)/Set-AzWebAppIPRestriction.ps1 -Priority 100 -Action 'Allow' -WebAppId '$(WebAppId)' -PipId '$(gwpipId)'' -ErrorAction Stop
Since you were running your scripts in .ps1 file. You should change the targetType parameter of powershell task to filePath. And set .ps1 file in the filePath parameter. See below example:
steps:
- task: PowerShell#2
displayName: 'PowerShell Script'
inputs:
targetType: filePath
filePath: '$(System.DefaultWorkingDirectory)/Set-AzWebAppIPRestriction.ps1'
arguments: '-Priority 100 -Action "Allow" -WebAppId "$(WebAppId)" -PipId "$(gwpipId)" -ErrorAction Stop'
pwsh: true
If you are using azure powershell module in your scripts. You can use Azure powershell task instead of powershell task..

How to securely login in Az CLI from a DevOps Pipeline

I want to execute AZ cli commands from my Azure DevOps Pipeline. In my YAML file I have this:
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- task: UsePythonVersion#0
inputs:
versionSpec: '3.x'
architecture: 'x64'
# Updating pip to latest
- script: python -m pip install --upgrade pip
displayName: 'Upgrade pip'
# Updating to latest Azure CLI version.
- script: pip install --pre azure-cli --extra-index-url https://azurecliprod.blob.core.windows.net/edge
displayName: 'upgrade azure cli'
- script: az --version
displayName: 'Show Azure CLI version'
- script: az extension add -n azure-devops
displayName: 'Install Azure DevOps Extension'
- script: echo ${AZURE_DEVOPS_CLI_PAT} | az devops login
env:
AZURE_DEVOPS_CLI_PAT: $(System.AccessToken)
displayName: 'Login Azure DevOps Extension'
- script: az aks show --name census-k8s --resource-group Census
displayName: 'Show AKS'
The echo ${AZURE_DEVOPS_CLI_PAT} | az devops login step is completed (with success apparently) with a warning message
Failed to store PAT using keyring; falling back to file storage.
You can clear the stored credential by running az devops logout.
Refer https://aka.ms/azure-devops-cli-auth to know more on sign in with PAT.
The az aks show step fails:
Please run 'az login' to setup account.
I am a little bit lost. The az devops login command should enable me to use the az cli, right? If not, Am I supposed to use az login instead of az devops login? And if I am supposed to use az login, how can I pass my credentials in a secure way?
No, you don't need az devops login. What you need is Azure CLI Task:
- task: AzureCLI#2
displayName: Azure CLI
inputs:
azureSubscription: <Name of the Azure Resource Manager service connection>
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
az --version
az account show
but then you don't have to do any login. Please call there your az aks show --name census-k8s --resource-group Census
Just to Add to Krzysztof's answer (and jeromerg question in the comment): in Azure CLI step you can also use other tools then az, which require being logged in with AzureCLI:
- task: AzureCLI#2
displayName: Publish Function
inputs:
azureSubscription: <Name of the Azure Resource Manager service connection>
scriptType: ps
scriptLocation: inlineScript
inlineScript: |
func azure publish <function-name>
If your scriptLocation is a scriptPath use the following example
- task: AzureCLI#2
displayName: 'update function appsettings'
inputs:
azureSubscription: 'MY-AzureSubscriptionName'
scriptType: ps
scriptLocation: 'scriptPath'
scriptPath: '$(System.DefaultWorkingDirectory)/Scripts/updateSettings.ps1'
arguments:
-ResourceGroupName 'MY-ResourceGroupName' `
-FunctionAppName 'MY-FunctionAppName'
updateSettings.ps1
param (
[string]$ResourceGroupName,
[string]$FunctionAppName)
)
.
. script body here
.
To use Azure CLI from a script (powershell or batch) you must assign $(System.AccessToken) to an environment variable named AZURE_DEVOPS_EXT_PAT.
- pwsh: |
az pipelines build list
displayName: 'Show build list'
env:
AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
Source: https://learn.microsoft.com/en-us/azure/devops/cli/azure-devops-cli-in-yaml?view=azure-devops

Resources