How to use variables in with_items in anisble playbook - ansible

I have create ansible role to create multiple lambda function, where I am passing some parameters from variable file. My variable file looks like
Variable file
S3BucketName: "test_bucket"
S3Key1: "test.zip"
runtime: "python3.6"
handler1: "test.lambda_handler"
role1: "test_role_arn"
memory_size: "128"
timeout: "180"
s3_key2: "temp.zip"
role2: "temp_role_Arn"
handler2: "temp.lambda_handler"
In my playbook, I am using ansible loop to create multiple aws lambda functions at the same time. when I am using variable in with_items.
Playbook file
- hosts: localhost
roles:
- ansible-lambda
vars_files:
- "ansible-lambda/vars/cf_vars.yaml"
lambda:
name: '{{ item.name }}'
region: "{{ aws_region }}"
state: "{{state}}"
runtime: "{{ runtime }}"
timeout: "{{timeout}}"
memory_size : "{{memory_size}}"
s3_bucket: "{{ S3BucketName}}"
s3_key: '{{ item.s3_key }}'
role: '{{ item.role }}'
handler: '{{ item.handler }}'
with_items:
- name: test
s3_key: "{{ S3Key1 }}" #refering to variable 1
- name: temp
s3_key: "{{ S3Key2 }}" #refering to variable 2
- debug:
msg: "Lambda creation Complete!!"
Following is the error:
fatal: [localhost]: FAILED! => {"msg": "'S3Key1' is undefined"}
This playbook works, when I pass the absolute values instead of variables. I mean s3_key: test.zip
how to use variables in with item?

-------------- var file ---------------
aws_region: austin
lambda_list:
- name: lambda1
state: "UR STATE HERE"
S3BucketName: "test_bucket"
S3Key: "test.zip"
runtime: "python3.6"
handler: "test.lambda_handler"
role_desc: "test_role_arn"
memory_size: "128"
timeout: "180"
- name: lambda2
state: "UR STATE HERE"
S3BucketName: "test_bucket"
S3Key: "test2.zip"
runtime: "python2.7"
handler: "test.lambda_handler"
role_desc: "test_role_ARN"
memory_size: "256"
timeout: "150"
---------------playbook------------------------
- hosts: localhost
vars_files: "ansible-lambda/vars/cf_vars.yaml"
tasks:
lambda:
name: '{{ item.name }}'
region: "{{ aws_region }}"
state: "{{ item.state }}"
runtime: "{{ item.runtime }}"
timeout: "{{ item.timeout }}"
memory_size : "{{ item.memory_size }}"
s3_bucket: "{{ item.S3BucketName }}"
s3_key: "{{ item.s3_key }}"
role: "{{ item.role_desc }}"
handler: "{{ item.handler }}"
with_items:
- "{{ lambda_list }}"
Here's a snippet of the correct way IMHO how to achieve what you're trying to do, sure there are few other ways but to be both efficient and easy config in example above you can see that there's a dict which holds every lambda's info as a key dict, when u use with_items it iterates each key to the task while using the item's data as {{ item.name }}.
You could even put a dict/list in a dict. for exmaple:
lambda_list:
- name: lambda1 # <--- each dash('-') is a key with a value, that value is a dict
S3: #
S3BucketName: "test_bucket"
S3Key: "test.zip"
- name: lambda2
S3: # <-- without the dash its indicated as a list inside the dict.
S3BucketName: "test_bucket"
S3Key: "test2.zip"
in this case to access your nested list you would use {{ item.S3.S3BucketName }} or {{ item['S3']['S3BucketName'] }}
if it was a dict in a dict you would get the key/value of each key without a proper way to access a specific key(with loops you can iterate the dict and use 'when' to get the desired key.)
Here's few references worth reading about loops, dicts and how to access them.
http://ansible-docs.readthedocs.io/zh/stable-2.0/rst/playbooks_loops.html#nested-loops

Related

Conditional task based on template parameter fails

I'm trying to use Ansible to deploy to two regions in AWS, I have it working with one region at the moment. The issue is I want to only execute my primary_region or my secondary_region depending on the parameter from the template it's using.
My main.yaml:
- hosts: primary_region
name: Create ECR
tasks:
- name: "Create ECR Repository"
cloudformation:
state: "{{ state }}"
stack_name: "{{ stack_create_ecr.name }}"
profile: "{{ aws_profile }}"
region: "{{ inventory_hostname }}"
template_url: "{{ stack_create_ecr.template_url }}"
template_parameters:
"ansibleFile"
tags:
"{{ stack_create_ecr.tags }}"
tags:
- stack_create_ecr
when: stack_create_ecr.region == "primary_region" <-- This
- hosts: secondary_region
name: Create ECR
tasks:
- name: "Create ECR Repository"
cloudformation:
state: "{{ state }}"
stack_name: "{{ stack_create_ecr.name }}"
profile: "{{ aws_profile }}"
region: "{{ inventory_hostname }}"
template_url: "{{ stack_create_ecr.template_url }}"
template_parameters:
"ansibleFile"
tags:
"{{ stack_create_ecr.tags }}"
tags:
- stack_create_ecr
when: stack_create_ecr.region == "secondary_region" <-- This
The template that I am using
stack_create_ecr.yaml:
stack_create_ecr:
name: cloudFormationTemplateNameOmitted
template_url: S3BucketUrl
parameters:
RepoName: EcrRepoName
DevName: cloud-dev
tags:
ansible_playbook: "{{ ansible_playbook_tag }}"
region: primary_region <-- This is what I'm trying to use
Everytime I try to run my playbook I just get msg: 'argument template_parameters is of type <class ''str''> and we were unable to convert to dict: dictionary requested, could not parse JSON or key=value'
I have tried all sorts of things from putting quotes around the string in the when condition. Nothing seems to work, what am I doing wrong?
It seems you massed up with template_parameters prop. It should be a map but you provided a string:
template_parameters:
PropName: "ansibleFile"

Ansible loop through nested inventory lists

I'm trying to loop through a nested ansible inventory looks like this:
inventory:
group_one:
- name: 'entry-one-a'
description: 'one-a'
group_two:
- name: 'entry-two-aa'
description: 'two-aa'
group_three:
- name: 'entry-three-aaa'
description: 'three-aaa'
- name: 'entry-three-aab'
description: 'three-aab'
I've tried it with the following loop, but without success:
- name: print vars
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ inventory.group_one.group_two|subelements("group_three") }}'
Any good idea how to loop through the inventory?
Iterate the third loop in the included task, e.g.
shell> cat group_three.yml
- debug:
msg: "{{ item.0.name }} {{ item.1.name }} {{ item2.name }}"
loop: "{{ item.1.group_three }}"
loop_control:
loop_var: item2
- include_tasks: group_three.yml
with_subelements:
- "{{ inventory.group_one }}"
- group_two
gives
msg: entry-one-a entry-two-aa entry-three-aaa
msg: entry-one-a entry-two-aa entry-three-aab

how to get the non-repetitive element from two variables in ansible

I am running the Ansible task for creating terraform resources, code is below:
- name: "Run terraform project: {{ tf_project }}"
terraform:
state: present
force_init: true
backend_config:
bucket: "{{ tf_bucket_name }}"
region: "{{ bootstrap_region }}"
kms_key_id: "{{ tf_bucket_kms_id }}"
encrypt: "true"
workspace_key_prefix: "{{ target_infra }}"
key: "{{ tf_project }}.tfstate"
project_path: "../terraform_12/{{ tf_project }}"
variables:
target_region: XXXXXXX
workspace: "Test"
below are the values of the variables:
hostvars[inventory_hostname]['Active_Regions']: ['eu-west-1','ap-southeast-2']
hostvars[inventory_hostname]['Region']: 'eu-west-1'
expected value:
target_region: ['ap-southeast-2']
have tried below:
target_region: "{{ hostvars[inventory_hostname]['Active_Regions'] | difference(hostvars[inventory_hostname]['Region'] | list) }}"
but it's not working.
note: hostvars[inventory_hostname]['Active_Regions'] and hostvars[inventory_hostname]['Regions'] are dynamic.
The second parameter is not a list. You have to enclose it in brackets [], e.g.
- set_fact:
target_region: "{{ hostvars[inventory_hostname]['Active_Regions']|
difference([hostvars[inventory_hostname]['Region']]) }}"

How to get interpolated value of variable in Ansible / Jinja2

I'm trying to define Ansible variables this way:
user:
name: First Last
nick: '{{ vars["user"]["name"] | regex_replace("\W", "_") }}'
email: '{{ vars["user"]["nick"] }}#example.com'
And the result email is: "{{ vars[\"user\"][\"name\"] | regex_replace(\"\\W\", \"_\") }}#example.com.
I also tried to set email like this: {{ lookup("vars", "user.nick") }}#example.com or {{ lookup("vars", "user")["nick"] }}#example.com, and it says An unhandled exception occurred while running the lookup plugin 'vars'.
Is there a way to get resulting variable values as:
user:
name: First Last
nick: First_Last
email: First_Last#example.com
?
ansible 2.9.10,
python version = 3.8.5
It's not possible cross-reference keys in a dictionary. It's necessary to declare the variables outside the dictionary. For example, the playbook
- hosts: localhost
vars:
my_name: First Last
my_nick: "{{ my_name | regex_replace('\\W', '_') }}"
user:
name: "{{ my_name }}"
nick: "{{ my_nick }}"
email: "{{ my_nick }}#example.com"
tasks:
- debug:
var: user
gives (abridged)
user:
email: First_Last#example.com
name: First Last
nick: First_Last
A more flexible option is to create the variables in the loop. For example, the playbook
- hosts: localhost
vars:
users:
"First Last":
domain: example.com
tasks:
- debug:
msg:
- "name: {{ name }}"
- "nick: {{ nick }}"
- "email: {{ email }}"
loop: "{{ users|dict2items }}"
vars:
name: "{{ item.key }}"
nick: "{{ item.key|regex_replace('\\W', '_') }}"
email: "{{ nick ~ '#' ~ item.value.domain }}"
gives (abridged)
msg:
- 'name: First Last'
- 'nick: First_Last'
- 'email: First_Last#example.com'

How can i assign a varaible in a variable

Here's my task.
- name: Add A record for "{{ ec2_hostname }}.{{ internal_domain }}"
route53:
command: create
zone: "{{ internal_domain }}"
private_zone: "{{ private_type }}"
record: "{{ ec2_hostname }}.{{ internal_domain }}"
type: A
ttl: 300
value: "{{ ansible_ec2_[ec2_r53_type]_ipv4 }}"
Specifically having trouble with this line:
value: "{{ ansible_ec2_[ec2_r53_type]_ipv4 }}"
I need to insert ec2_r53_type inside a string to create another variable. This should be either "public" or "local".
So the expected result should be
value: "{{ ansible_ec2_local_ipv4 }}"
or
value: "{{ ansible_ec2_public_ipv4 }}"
Whats the logic here, tried all i knew no luck
This should work
value: "{{ vars['ansible_ec2_' + ec2_r53_type + '_ipv4'] }}"
- find: ^CODEDEPLOY_USER=""
replace: CODEDEPLOY_USER=""{{ app_install_user }}""
"/"{{ app_install_user }}/"" something as such, This is on the vars folder of a play
I would require to add the variable in qoutes on the vars of roles.
roles/xxxx/vars/main.yml
app_install_user is added on group_vars of ansible

Resources