Unable to use | character in AzureFunctionApp appSettings: - azure-devops

I am setting a load of appSettings in my AzureFunctionApp#1 deployment task - but whenever I try to put each on a new line using the | character I get the error:
##[error]Error: Failed to update App service '{{functionName}}' application settings. Error: BadRequest - Parameter name cannot be empty. (CODE: 400)
The output above that seems to show that it has indeed built the JSON with an empty parameter name. But I don't know why? I've tested with the values on separate lines, and still in a single line, so neither of these work:
appSettings: |
'-Values:Setting1 "$(SettingVal1)"
-Values:Setting2 "$(SettingVal2)"'
appSettings: |
'-Value:Setting1 "$(SettingVal1)" -Values:Setting2 "$(SettingVal2)"'
But this does:
appSettings: '-Value:Setting1 "$(SettingVal1)" -Values:Setting2 "$(SettingVal2)"'
I've also tried without the ' - but that made no difference either.

As per your feedback - Converting my comment as an answer, also tried locally in my system.
Multi-line json input works for setting the multiple values in the app settings as this is the closest way.
appSettings: |
[
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "$(Key)",
"slotSetting": false
},
{
"name": "MYSQL_DATABASE_NAME",
"value": "$(DB_Name)",
"slotSetting": false
}
]

Multiline JSON doesn't work with the AzureFunctionApp#1 task's appSettings parameter (for some reason).
If you try to use the multiline JSON appSettings with the AzureFunctionApp#1 task, you will get an error: BadRequest - Parameter name cannot be empty. (CODE: 400)
To use the multiline JSON appSettings, you need to use a separate AzureAppServiceSettings#1 task - as mentioned in this document.
I can confirm this works after the AzureFunctionApp#1 task. So my pipeline now has:
steps:
...
- task: AzureFunctionApp#1
displayName: Deploy the Function App
condition: succeeded()
inputs:
azureSubscription: "${{parameters.AppAzureSubscription}}"
appName: "${{parameters.functionAppName}}"
package: "$(Pipeline.Workspace)/drop/$(Build.BuildId).zip"
- task: AzureAppServiceSettings#1
displayName: Update app settings
inputs:
azureSubscription: "${{parameters.AppAzureSubscription}}"
appName: "${{parameters.functionAppName}}"
appSettings: |
[
{
"name": "Values:DbConnectionString",
"value": "$(DbConnectionString)",
"slotSetting": false
},
...
]

Related

Deploy only certain resources into Azure using DevOps Pipeline

I have a main.bicep template with multiple resources that I deploy to Azure via my DevOps pipeline. My template is currently configured to either deploy all modules to Azure or none. However, I would like to customize this in my pipeline so that only certain resources show up in my resource group so that it acts like a selection catalog.
However, I need advice and help on how to solve the problem as I can’t find the right approach. Attached you can see a snippet from my bicep template below.
– main.bicep–
param deployAppInsights bool = true param deployNetworkWatcher bool = true param deploySentinel bool = true
Example for a module
// Deploy App Insights resource
module appInsights 'AzureMonitor/AppInsights/appInsights-temp.bicep' = if(deployAppInsights) { name: 'appInsightsDeployment' params: { appName: appInsightsName regionId: regionId // tagsArray: tagsArray requestSource: requestSource workspaceResourceId: workspace.outputs.resourceWorkspaceIdOutput } }
This snippet is in my pipeline - yml
(I would like to shorten the parameters block by using override parameters.)
parameters:
- name: appInsights
type: boolean
default: True
values:
- True
- False
inputs: overrideParameters: -deployAppInsights false -deployNetworkWatcher true -deploySentinel true
Currently, my override parameters are hardcoded, but I’d like to keep it in a general way, like for example:
overrideParameters: -deployAppInsights ${{appInsights}} -deployNetworkWatcher ${{networkWatcher}} -deploySentinel ${{sentinel}}
However, this does not unfortunately work. Could anyone please help me in this regard, how I can solve this or how the variables need to look like?
Thank you very much!
Best regards
Jennifer
As far as I understand, the syntax you are using is wrong in the below code
overrideParameters: -deployAppInsights ${{appInsights}} -deployNetworkWatcher ${{networkWatcher}} -deploySentinel ${{sentinel}}
Since you have already defined parameters section in the Yml file. The correct syntax is
overrideParameters: -deployAppInsights ${{parameters.appInsights}} -deployNetworkWatcher ${{parameters.networkWatcher}} -deploySentinel ${{parameters.sentinel}}
A sample code snippet for your reference
parameters:
- name: var1
type: string
- name: var2
type: string
- name: bool1
type: bool
...
omitted
...
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
azureResourceManagerConnection: ''
subscriptionId: ''
action: 'Create Or Update Resource Group'
resourceGroupName: rg-${{parameters.var1}}-${{parameters.var2}}
location: ''
templateLocation: 'Linked artifact'
csmFile: $(System.DefaultWorkingDirectory)/arm.json
csmParametersFile: $(System.DefaultWorkingDirectory)/arm.parameters.json
deploymentMode: 'Incremental'
overrideParameters:
-string1 ${{parameters.var1}}
-string2 ${{parameters.var2}}
-flag ${{parameters.bool1}}
For more, please refer to the link from Microsoft. Azure Devops Template
Edit: After the first comment
Please update your 'appInsights' parameter as follows
parameters:
- name: appInsights
type: boolean
default: true

Azure Devops Yaml Python Script task: PythonScriptV0 , how to pass arrays as the field supports only a strings

I am trying to pass to a python scripts 3 parameters one of them is an array, this works when i run the script locally, i am using sys.argv to achieve this.
However the argument field support only strings as far i can see. How can i go around this any ideas? Thanks
the array is ${{ parameters.packageVersion }}
Code:
- task: PythonScript#0
displayName: 'Modify ansible inventory files (wms_common.yml) with deployed versions'
inputs:
scriptSource: filePath
scriptPath: deployment/s/azure-devops/scripts/script.py
arguments: |
../../inventories/${{ variables.inventory }}/group_vars/all/wms_common.yml
../../inventories/central/${{ variables.inventory }}/group_vars/all/wms_common.yml
${{ parameters.packageVersion }}
Error:
/azure-devops/wms.full.pipeline.yml (Line: 95, Col: 18): Unable to convert from Array to String. Value: Array
Edit: Reframed question
I think the below YAML will help you convert the array to String objects and use them.
variables:
myVariable1: 'value1'
myVariable2: 'value2'
system.debug: true
parameters:
- name: InstanceArgs
type: object
default: [1,2]
steps:
- task: PythonScript#0
inputs:
scriptSource: 'inline'
script: |
import argparse
parse = argparse.ArgumentParser(description="Test")
parse.add_argument("test1")
parse.add_argument("test2")
args = parse.parse_args()
print(args.test1)
print(args.test2)
print('this is a test.')
# arguments: $(myVariable1) $(myVariable2)'
arguments: ${{join(' ',parameters.InstanceArgs)}}
You need to use the join expression in YAML to get the elements:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#join

Azure variable is not being read correctly in build pipeline

In my build pipeline I've defined a variable that holds a password:
To reference a variable in YAML, prefix it with a dollar sign and enclose it in parentheses. For example: $(ACCOUNT_PASSWORD)
I have a task that uses the file creator extension:
- task: file-creator#6
inputs:
filepath: '$(System.DefaultWorkingDirectory)/cypress.env.json'
filecontent: |
{
"ACCOUNT_PASSWORD": $(ACCOUNT_PASSWORD)
}
fileoverwrite: true
But I get this error:
SyntaxError: /home/**/_work/1/s/cypress.env.json: Unexpected token $ in JSON at position 24
So I create a json file and I think the $(ACCOUNT_PASSWORD) is interpreted as a regular string in stead of the value of the variable.
Not sure what kind of syntax, it is expecting but you can try variables['ACCOUNT_PASSWORD']
This worked for me:
- task: file-creator#6
inputs:
filepath: '$(System.DefaultWorkingDirectory)/cypress.env.json'
filecontent: |
{
"ACCOUNT_PASSWORD": "ACCOUNT_PASSWORD"
}
fileoverwrite: true
- task: FileTransform#1
inputs:
folderPath: '$(System.DefaultWorkingDirectory)'
fileType: 'json'
targetFiles: 'cypress.env.json'

Azure Pipelines - File Transform set different values to different files with the same key

I am trying to use the task FileTransform to modify the values of grafana json templates. And it's working for modifying the values of somes keys the following way:
- task: FileTransform#2
displayName: "Transform Jsons"
inputs:
folderPath: 'metrics/dashboards/**/'
xmlTransformationRules: ''
jsonTargetFiles: '**/*.json'
And having declared the variables with the keys to substitute:
templating.list.0.query: $(azureClusterName)
templating.list.0.current.text: $(azureClusterName)
templating.list.0.current.value: $(azureClusterName)
templating.list.0.options.0.text: $(azureClusterName)
templating.list.0.options.0.value: $(azureClusterName)
If in jsonTargetFiles I only declare one file it works perfectly, but I want to know how can I assign different values for files that have the same keys.
I've tried using "replaceTokens", and having different variable names inside of the jsons files:
- task: replacetokens#3
displayName: 'Replace tokens'
inputs:
rootDirectory: 'metrics/dashboards'
targetFiles: '**/*.json'
encoding: 'auto'
verbosity: 'detailed'
actionOnMissing: 'fail'
tokenPrefix: '#{'
tokenSuffix: '}#'
But with replace tokens the template in grafana doesn't work even it says that the values have been replaced correctly.
Best
How can I assign different values for files that have the same keys.
You can use a extension called Magic Chunks
Here is an example:
In transformations, Find the variable you want to assign to using {Node A}/{Node B}/... and specify the value of the variable
- task: MagicChunks#2
inputs:
sourcePath: '{target json file path}'
fileType: 'Auto'
targetPathType: 'source'
transformationType: 'json'
transformations: |
{
"ConnectionStrings/DefaultConnection": "Data Source=10.0.0.5;Initial Catalog=Db1"
}
Target JSON file:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=webapp"
}
}
Output JSON file:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=10.0.0.5;Initial Catalog=Db1"
}
}
But with replace tokens the template in grafana doesn't work even it says that the values have been replaced correctly.
The logic of using the Replace Token task is different from using the File Transform task. In the Replace Token task, you need to place the string you want to replace in specific tokens (defined in tokenPrefix and tokenSuffix). In addition, in variables, you need to place the strings need to be replaced on the left and the strings used to replace on the right. Here is an example:
variables:
enabled: disabled
- task: replacetokens#3
inputs:
targetFiles: 'A.json'
encoding: 'auto'
writeBOM: true
verbosity: 'detailed'
actionOnMissing: 'fail'
keepToken: false
tokenPrefix: '#{'
tokenSuffix: '}'
useLegacyPattern: false
enableTelemetry: true
Target JSON file:
{
"B": "#{enabled}"
}
Output JSON file:
{
"B": "disabled"
}

How to pass Azure ARM template object value from YAML file?

Azure ARM Template parameter.json file has the below object property.
"appInsightsObject": {
"value": {
"name": "appInsghtName",
"id": "appInsgID"
}
}
I have to replace these values from build.yaml file. My build.yaml file has the below
- task: AzureResourceManagerTemplateDeployment#3
displayName: APIM Development CI
inputs:
ConnectedServiceName: My-Service-Name
subscriptionName: My-Subs-Values
resourceGroupName: My-Rg-Name
location:$(locationName)
csmFile: template.json
csmParametersFile: parameters.json
overrideParameters: '-appInsightsObject.name $(appInsightNameValue) '
How to pass appInsightsObject object value?
Update:
I found one way of passing the value as JSON object like '{"name":"name-goes-here", "id":"id-value-goes-here"}'. Is there any better option?
overrideParameters: '-appInsightsObject $(appInsightValue) '
This one works and allows to store values individually for any type of object.
overrideParameters: '-appInsightsObject {"name": "$(dev.insightName)","id": "$(dev.insightId)"} '