New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typecast from YAML Object to String #427
Comments
Really looking forward for this. Forcing to iterate a collection from the template means I have to restart the same task over and over again. When using script related task which takes a long time to setup/authenticate, like AzureCLI, you are wasting a lot of time (almost 30sec per task run) just to wait for it to complete its initialization. So for a collection of 11 items, this is 300sec or 5 minutes lost just to initialize thing. Also, this allows to perform data validation from the scripting language on the YAML object to ensure the task is being used properly and return proper error message, which cannot be done currently. |
FWIW, I am currently using a hack to manually enumerate the array in order to "stringify" arrays into environment variables to be used in PowerShell scripts. You can try to adapt this sample YAML to reconstruct a complex object. Here I am transferring the - task: PowerShell@2
inputs:
targetType: 'inline'
script: |
$indexes = @("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
$params = $indexes | %{
@{i=$_; KeyName="SCRIPT_PARAM_$($_)_KEY"; ValName="SCRIPT_PARAM_$($_)_VAL"} | % {
$ParamName = (Get-Item env:$($_.KeyName) -ErrorAction SilentlyContinue).Value
$ParamValue = (Get-Item env:$($_.ValName) -ErrorAction SilentlyContinue).Value
if ($ParamName) {
@{ParamName=$ParamName;ParamValue=$ParamValue}
}
}
}
### $params is now an array of key-value pairs
env:
${{ if parameters['mylist'] }}:
${{ each item in parameters['mylist'] }}:
${{ if eq(parameters['mylist'][0]['name'], item['name']) }}:
SCRIPT_PARAM_0_KEY: ${{ item['name'] }}
SCRIPT_PARAM_0_VAL: ${{ item['value'] }}
${{ if eq(parameters['mylist'][1]['name'], item['name']) }}:
SCRIPT_PARAM_1_KEY: ${{ item['name'] }}
SCRIPT_PARAM_1_VAL: ${{ item['value'] }}
${{ if eq(parameters['mylist'][2]['name'], item['name']) }}:
SCRIPT_PARAM_2_KEY: ${{ item['name'] }}
SCRIPT_PARAM_2_VAL: ${{ item['value'] }}
# Repeat hack for indexes > 2 |
@JoeGaggler Nice hack, haven't thought about using the ${{ each }} statement to define my script env variables. parameters:
mylist:[]
#where mylist is a sequence of object matching the mapping:
#- name: 'the name 1'
# value: 'the value of 1'
# index: 0
#- name: 'the name 2'
# value: 'the value of 2'
# index: 1
env:
${{ each item in parameters.mylist }}:
${{ format('SCRIPT_PARAM_{0}_KEY', item.index) }}: ${{ item.name }}
${{ format('SCRIPT_PARAM_{0}_VAL', item.index) }}: ${{ item.value }} But this still remains a pain to implement, especially if your structure has multiple nested levels. |
In order to consolidate to fewer feedback channels, we've moved suggestions and issue reporting to Developer Community. Sorry for any confusion resulting from this move. |
for anyone who (like me) would like to know to what issue this was actually moved: |
another way would be to pass the parameter converted into json and using ConvertFrom-Json to turn it into an object
|
another way would be to pass the parameter converted into json and - pwsh: |
$jsonObject = "${{ convertToJson(parameters.complex) }}" | Convertfrom-Json |
I just wanted to pop a note here that I found easiest way to get this working was following the last point in @guidooliveira's latest comment. parameters:
- name: identityProviders
type: object
default:
- authority: https://an.authority.com/blah/blah
clientId: 12345
clientSecret: notasecretyet
autoProvisionUser: 1
name: customer-oidc
displayName: customer SSO
validateIssuer: true
ssoGroups:
- databaseId: 00000000-0000-0000-0000-000000000000
GroupName: Administrators
SSOGroupName: product-sysadmins
- databaseId: 99999999-9999-9999-9999-999999999999
GroupName: Administrators
SSOGroupName: product-admins
- authority: https://an.authority.com/blah/blah2
clientId: 123452
clientSecret: notasecretyet2
autoProvisionUser: 1
name: customer-oidc2
displayName: customer SSO2
validateIssuer: true
ssoGroups:
- databaseId: 00000000-0000-0000-0000-000000000000
GroupName: Administrators2
SSOGroupName: product-sysadmins2
- databaseId: 99999999-9999-9999-9999-999999999999
AutoRekGroupName: Administrators2
SSOGroupName: product-admins2 To use it I used Powershell@2 task: steps:
- ${{ each idp in parameters.identityProviders }}:
- task: PowerShell@2
name: BuildXml${{idp.clientId}}
inputs:
targetType: inline
pwsh: true
script: |
$inputJson = '${{ convertToJson(idp) }}'
$identityProviders = ConvertFrom-Json -Depth 100 -InputObject $inputJson From here it's easy enough to handle the object as a Powershell object within the script. N.B. I'm not entirely sure why but if I wrapped the line with quotes rather than apostrophes:
I'd get an error:
|
I think you are getting a problem with quotes, because Json, you are enclosing in those, is unescaped, if you escape it, it should work fine. |
Expressions in YAML pipelines may be literals such as String, Boolean, and Number, but also any YAML object, for example the template parameters object is a complex type with members for each parameter.
It would be useful to be able to consume entire YAML objects in YAML tasks such as the PowerShell task. The current options for passing in parameters require strings (often environment variables), which means it is required to somehow "stringify" or serialize YAML objects into Strings.
There currently is no type cast from YAML Object to String, or similarly no such expression function.
Alternatively, an explicit expression function could be added in case an implicit type cast is not appropriate.
The text was updated successfully, but these errors were encountered: