unable to pass parameter from azure Devops yaml to PowerShell - azure

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)'

Related

Passing Terraform output to Powershell task in Azure Devosps

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.

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)

InvalidDeploymentParameterKey when using overrideParameters on an ARM deployment from Azure Pipelines

Here is an extract from a YAML pipeline in Azure DevOps:
- task: AzureCLI#2
name: GetAppInsightsConnString
displayName: 'Get AppInsights ConnectionString'
inputs:
azureSubscription: ${{ parameters.TelemetryAzureSubscription }}
scriptType: 'pscore'
scriptLocation: 'inlineScript'
inlineScript: |
az extension add -n application-insights
az feature register --name AIWorkspacePreview --namespace microsoft.insights
$resourceInfo = az monitor app-insights component show --app ${{ parameters.AppInsightsResourceName }} --resource-group ${{ parameters.AppInsightsResourceGroupName }}
$instrumentationKey = ($resourceInfo | ConvertFrom-Json).InstrumentationKey
echo "##vso[task.setvariable variable=ApplicationInsightsInstrumentationKey]$instrumentationKey"
- task: FileTransform#2
displayName: "Replace Parameters From Variables"
inputs:
folderPath: '$(Pipeline.Workspace)'
xmlTransformationRules: ''
jsonTargetFiles: '**/${{ parameters.ArmTemplateParameters }}'
- powershell: 'Get-Content $(Pipeline.Workspace)/${{ parameters.ArtifactName }}-provisioning/${{ parameters.ArmTemplateParameters }}'
displayName: 'Preview Arm Template Parameters File'
- task: PowerShell#2
displayName: "TEMP: Test new variable values"
inputs:
targetType: 'inline'
script: |
Write-Host "ApplicationInsightsInstrumentationKey: $(ApplicationInsightsInstrumentationKey)"
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
ConnectedServiceName: ${{ parameters.AzureSubscription }}
action: 'Create Or Update Resource Group'
resourceGroupName: ${{ parameters.ResourceGroupName }}
location: $(locationLong)
templateLocation: 'Linked artifact'
csmFile: '$(Pipeline.Workspace)/${{ parameters.ArtifactName }}-provisioning/${{ parameters.ArmTemplate }}'
csmParametersFile: '$(Pipeline.Workspace)/${{ parameters.ArtifactName }}-provisioning/${{ parameters.ArmTemplateParameters }}'
overrideParameters: '–applicationInsightsInstrumentationKey "$(ApplicationInsightsInstrumentationKey)"'
deploymentMode: 'Incremental'
This is connecting to an App Insights instance, getting the instrumentation key, then doing a variable replacement on an ARM parameters file before previewing it and deploying it.
The instrumentation key is writtent to a ApplicationInsightsInstrumentationKey pipeline variable, and you can see a later task which previews this in the pipeline logs so I can confirm the variable is being set as expected.
On the final task I'm using an overrideParameters option to feed this key into the deployment as the value of the applicationInsightsInstrumentationKey parameter. This is where the pipeline fails, with the error:
##[error]One of the deployment parameters has an empty key. Please see https://aka.ms/resource-manager-parameter-files for details.
My web searching tells me this can occur when the value has spaces and isn't enclosed in double-quotes, but neither of those are the case here. In fact I can even replace that line with a hard-coded value and I still get the same issue.
If I remove that overrideParameters line the deployment succeeds, but obviously the parameter I want isn't included.
Anyone know how to solve this?
As shown by the help dialog on ARM template deployment ADO task:
Since, applicationInsightsInstrumentationKey will not have multiple words, try changing line like below:
overrideParameters: '–applicationInsightsInstrumentationKey $(ApplicationInsightsInstrumentationKey)'

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..

Changing Azure YAML Pipeline causes authorization to be lost to Resources

I've had this happen to me a number of times where I have a working Azure Pipeline written in YAML. Then I change the Pipeline and then I get the error that There was a resource authorization issue. Typically I delete the pipeline, re-create it, and then it works. However, now it is not working and I continuously get the following error:
So, I click the little button, and it pops up saying, Resources have been Authorized. I attempt to run the pipeline again, and I get the same error.
I am an Account/Collection/Organization Administrator, and created the Library Group originally where it is set to have Access to all Pipelines enabled. I've tried renaming the Pipeline and re-creating it a few times to the same error. short of reverting the pipeline back to it original state what should I do?
--EDIT--
Simply resetting the branch to an earlier version of the pipeline worked. Still no clue on why moving the steps into Stages and Jobs failed though.
--EDIT--
Below will is the YAML I used originally and the updated version. When the updated version gave Resource Authorization issues, I performed a git log and took the commit id of the previous commit that worked, and did a git reset $commitId. Pushed the reset branch back up to Azure DevOps, then it just magically worked.
Original Azure Pipeline YAML:
---
trigger: none
variables:
- name: ProjectFolder
value: tf-datafactory
- group: 'Deploy_Terraform_Library_Group'
pool:
vmImage: 'ubuntu-latest'
steps:
- task: replacetokens#3
displayName: Replace tokens
inputs:
targetFiles: '$(System.DefaultWorkingDirectory)/$(ProjectFolder)/variables.tf'
encoding: 'auto'
writeBOM: true
verbosity: 'detailed'
actionOnMissing: 'warn'
keepToken: false
tokenPrefix: '#{{'
tokenSuffix: '}}#'
- task: AzureCLI#2
displayName: Get the storage account key
inputs:
azureSubscription: '$(ARM.SubscriptionEndpoint)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
export ContainerAccessKeyExport=$(az storage account keys list \
--resource-group $(StorageResourceGroupName) \
--account-name $(StorageAccountName) \
--query "[0].value")
echo "##vso[task.setvariable variable=ContainerAccessKey]$ContainerAccessKeyExport"
...
I then moved these steps into stages and jobs.
---
parameters:
- name: TerraformAction
displayName: 'Will Terraform Create or Destroy?'
type: 'string'
default: 'create'
values:
- 'create'
- 'destroy'
trigger: none
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: 'Terraform'
displayName: 'Terraform Stage'
variables:
- name: 'TerraformAction'
value: '${{ parameters.TerraformAction }}'
- name: ProjectFolder
value: tf-datafactory
jobs:
- job: 'DeployTerraform'
displayName: 'Terraform Deploy Data Factory'
condition: eq(variables['TerraformAction'], 'create')
variables:
- group: 'Deploy_Terraform_Library_Group'
steps:
- task: replacetokens#3
displayName: Replace tokens
inputs:
targetFiles: '$(System.DefaultWorkingDirectory)/$(ProjectFolder)/variables.tf'
encoding: 'auto'
writeBOM: true
verbosity: 'detailed'
actionOnMissing: 'warn'
keepToken: false
tokenPrefix: '#{{'
tokenSuffix: '}}#'
- task: AzureCLI#2
displayName: Get the storage account key
inputs:
azureSubscription: '$(ARM.SubscriptionEndpoint)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
export ContainerAccessKeyExport=$(az storage account keys list \
--resource-group $(StorageResourceGroupName) \
--account-name $(StorageAccountName) \
--query "[0].value")
echo "##vso[task.setvariable variable=ContainerAccessKey]$ContainerAccessKeyExport"
...
--EDIT--
What I get from this: https://aka.ms/yamlauthz is that you either need to start with Stages and Jobs from the get go, otherwise you have to stick with the original Pipeline that was created. Most people that let Azure DevOps create their initial pipeline won't know to use the Stages and Jobs because the pipeline generator doesn't do that for them and only starts with Steps.

Resources