Ansible loop over list var - ubuntu-14.04

I am trying to add users belongs to group abc into group xyz. to do this in ansible I am doing following
- name: Get the list of user belongs to abc group
command: lid -g -n abc
register: abc_users
- name: Add user belongs to abc group to xyz group
user: name={{ items }} groups=xyz append=yes
with_items: "{{ abc_users.stdout }}"
But getting following error
fatal: [10.8.17.14]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'items' is undefined\n\nThe error appears to have been in '/home/#/workspace/#/ansible/roles/ubuntu-common/tasks/main.yml': line 26, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Add user belongs to sentience group to docker group\n ^ here\n"}
Anyone know better way to do this ?
Thanks

Replace {{ items }} with {{ item }}.
Update: as #udondan points out, iterate over stdout_lines
- name: Add user belongs to abc group to xyz group
user: name={{ item }} groups=xyz append=yes
with_items: "{{ abc_users.stdout_lines }}"

Related

Azure pipeline yaml: Cannot use strategy matrix variable in conditions

I am having problem in calling template as the pre-condition is not getting satisfied, I am comparing parameter value to select which template to call at runtime, here I am having parameter value coming from strategy matrix and I think that might be the issue.
pipeline yaml :
stages:
- stage: build_stage
jobs:
- job:
strategy:
matrix:
Dev_Build:
build_type: "dev"
Rel_Build:
build_type: "rel"
steps:
- template: test_conditional_template.yml#templates_repo
parameters:
build: $(build_type)
test_conditional_template.yml :
parameters:
- name: build
type: string
default: 'dev'
steps:
- ${{ if eq(parameters.build, 'dev') }}: # this condition is not working
- template: test_conditional_template_generic.yml#templates_repo
parameters:
build_quality: ${{ parameters.build }}
test_conditional_template-generic.yml :
parameters:
- name: build
type: string
default: 'dev'
steps:
- script: |
echo "build quality : ${{ parameters.build }}"
displayName: "print build quality, test_conditional_template-generic"
I am not even able to compare the parameter value with normal script step too :
- script: |
echo "build quality : ${{ parameters.build }}"
condition: eq('${{ parameters.build }}', 'dev')
This is what pipeline prints for above step :
if template is called with hard-coded parameter value, condition works fine :
steps:
- template: test_conditional_template.yml#templates_repo
parameters:
build: 'dev' #this works fine with above template code
we're avoiding so much of boilerplate code with usage of strategy matrix so dont really want to get away from it, any pointers will be helpful.
I wanted to add this as a comment but my first thought was that it's comparing 'dev' with "dev" in the first example and ''dev'' (double single quotes) in the script example, so both would evaluate as false,
I've been writing quite a few templates and have had a lot of similar issues, it would be nice if we could find out before checking the code in but ehh yaml...

Azure yaml pipeline display parameter value and have another actual value

I have a yaml pipeline in which I have a string parameter with several values. I want to have a human readable options to choose from but when reading the parameter I want to have an actual different value.
a psuedo yaml declaration for what I mean:
- name: actionParam
displayName: Choose Action
type: string
default: 'Action0': 'no action'
values:
- 'Action1' : 'drop tables'
- 'Action2' : 'hack NASA'
- 'Action3' : 'solve world hunger'
In this example I want for the user to see the options on the right but when doing {{parameters.actionParam}} I want to get the corresponding option on the left.
Is such a thing possible?
Based on your requirement, you need to display parameter value and have another actual value.
I am afraid that there is no out-of-box method to achieve this requirement.
For a workaround, I suggest that you can define the parameters with the options on the right and then you can set the variable value based on the value of the parameters.
Here is an example:
parameters:
- name: actionParam
displayName: Choose Action
type: string
default: 'no action'
values:
- 'drop tables'
- 'hack NASA'
- 'solve world hunger'
variables:
- ${{ if eq(parameters.actionParam, 'solve world hunger') }}:
- name: actionParam
value: Action1
- ${{ if eq(parameters.actionParam, 'drop tables') }}:
- name: actionParam
value: Action2
- ${{ if eq(parameters.actionParam, 'hack NASA') }}:
- name: actionParam
value: Action3
Result:
Then you can use the actual value with the format: $(actionParam)

Hide/Show parameters based on a condition in Azure DevOps Pipelines YAML

I have a use case where I have multiple parameters in ADO build pipeline but those parameters should be visible based on a condition e.g. the branch name (for releases/* branches). Following is a template to showcase what I am trying to achieve:
variables:
- name: systemAccessToken
value: $(System.AccessToken)
- name: system.debug
value: true
- ${{if startsWith(variables['Build.SourceBranch'], 'refs/heads/releases/') }}:
- name: START_DATE_TIME
value: ${{ parameters.startDateTime }}
- name: END_DATE_TIME
value: ${{ parameters.endDateTime }}
- ${{if startsWith(variables['Build.SourceBranch'], 'refs/heads/releases/') }}:
parameters:
- name: startDateTime
displayName: Enter the Start Datetime
type: string
default: 04-14-2022 14:55:00
- name: endDateTime
displayName: Enter the End Datetime
type: string
default: 04-14-2022 23:00:00
resources:
repositories:
...
...
stages:
...
...
The above doesn't work but I would like to get an idea if there is some way I can achieve this using any workaround like injecting the parameters at runtime. Would appreciate any help on this
Sorry, can't be done. The list of parameters is fixed and the pipeline is compiled, before it ever knows about any runtime variables such as Build.SourceBranch.
Instead, you could perhaps define two different pipelines with different sets of parameters? You can avoid duplicating code by extracting the common elements (resources, variables, stages) into a template.

ansible - changing a specific line in configuration file using a jinja template

I have an .ini config file that I'd like to template, but I only want to manipulate one or two lines with the jinja2 files.
example config file:
[configuration]
config1 = this_is_fine
config2 = to_be_templated
config3 = to_be_templated
config_4 = this_is_fine
What would be the best way to define a configuration.ini.j2 that would only change
config2 = {{ assigned_value }}
config3 = {{ assigned_value }}
while keeping the formatting and remaining configuration in place when running the playbook?
Q: "Manipulate one or two lines with the Jinja2 files."
A: "One or two lines" means a block. Use blockinfile to manipulate a block in a file. You'll need markers to do this, e.g. given the file
shell> cat conf.ini
[configuration]
config1 = this_is_fine
config2 = to_be_templated
config3 = to_be_templated
config_4 = this_is_fine
the two tasks below put markers around the block starting config2 and ending config3
- replace:
path: conf.ini
regexp: '(config2.*)'
replace: |-
{{ '#' }} BEGIN ANSIBLE MANAGED BLOCK c2-3
\g<1>
- replace:
path: conf.ini
regexp: '(config2.*[\s\S]*?config3.*)'
replace: |-
\g<1>
{{ '#' }} END ANSIBLE MANAGED BLOCK c2-3
gives
shell> cat conf.ini
[configuration]
config1 = this_is_fine
# BEGIN ANSIBLE MANAGED BLOCK c2-3
config2 = to_be_templated
config3 = to_be_templated
# END ANSIBLE MANAGED BLOCK c2-3
config_4 = this_is_fine
These two tasks are not idempotent. Run them only once. Either put them in a separate playbook to set up the project or test the presence of the markers.
Now you can use the template
shell> cat conf.ini.j2
config2 = {{ assigned_value }}
config3 = {{ assigned_value }}
For example, the task below
- blockinfile:
path: conf.ini
marker: '# {mark} ANSIBLE MANAGED BLOCK c2-3'
block: |
{{ lookup('template', 'conf.ini.j2') }}
vars:
assigned_value: AVALUE
gives
shell> cat conf.ini
[configuration]
config1 = this_is_fine
# BEGIN ANSIBLE MANAGED BLOCK c2-3
config2 = AVALUE
config3 = AVALUE
# END ANSIBLE MANAGED BLOCK c2-3
config_4 = this_is_fine

In Twig, how do I use a dynamic key when translating

In my translation yml file I have these translations setup
pages:
training_missions:
...
application_name:
admin: "Admin Website"
mobile: "Mobile App"
kiosk: "Kiosk"
In my twig file, I need to set the application_name dynamically, but I can't get it to work properly.
This will translate fine, it gives me "Mobile App"
{{ 'pages.training_missions.application_name.mobile' | trans()}}
But this doesn't work, it gives me "pages.training_missions.application_name.mobile"
{{ 'pages.training_missions.application_name.'~trainingMission.application | trans() }}
edit:
The variable trainingMission.application contains one of the 3 strings I put in the yaml file : admin, mobile, kiosk
edit 2:
The solution is to wrap the string in parenthesis as per #Matteo 'Ingannatore' G. comment
It is possible! Use round brackets like this:
{{ ('pages.training_missions.application_name.'~trainingMission.application) | trans() }}
Use array accessor syntax:
{{ pages[training_missions].application_name.mobile }}

Resources