Saving debug msg into variables list - amazon-web-services

I want to create multiple aws accounts at once and to save different output list into variables.
I tried with debug msg but maybe is not the proper option.
The idea is the following:
-
name: Create accounts.
hosts: localhost
vars_prompt:
- name: "tag_start"
prompt: "Please set the starting number for the account"
private: no
- name: "tag_end"
prompt: "Please set the ending number for the account"
private: no
tasks:
- name: "Emails"
debug:
msg: "test+{{item}}#gmail.com"
with_sequence: start={{ tag_start }} end={{ tag_end }}
register: email
- name: "Account name"
debug:
msg: "account{{item}}"
with_sequence: start={{ tag_start }} end={{ tag_end }}
register: account_name
- name: "Emails list"
debug:
msg: "{{email}}"
- name: "Account names"
debug:
msg: "{{account_name}}"
- name: Create AWS account
shell: >
aws organizations create-account --email "{{ item[0] }}" \
--account-name "{{ item[1] }}" \
--role-name admin \
--iam-user-access-to-billing ALLOW \
--profile default
with_together:
- "{{ email }}"
- "{{ account_name }}"
The point is that first and second task seems to work as expected showing only what I need like:
TASK [Emails] ********************************************************************************************************************************************************************************************************************************************************************************************************
task path: /Users/me/repos/create_aws_account.yaml:15
ok: [localhost] => (item=46) => {
"msg": "test+46#gmail.com"
}
ok: [localhost] => (item=47) => {
"msg": "test+47#gmail.com"
}
TASK [Account name] **************************************************************************************************************************************************************************************************************************************************************************************************
task path: /Users/me/create_aws_account.yaml:21
ok: [localhost] => (item=46) => {
"msg": "account46"
}
ok: [localhost] => (item=47) => {
"msg": "account47"
}
But when I check the output with another debug msg of the variables saved I get the following:
TASK [Emails] ********************************************************************************************************************************************************************************************************************************************************************************************************
task path: /Users/me/create_aws_account.yaml:27
ok: [localhost] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "46",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"failed": false,
"item": "46",
"msg": "test+46#gmail.com"
},
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "47",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"failed": false,
"item": "47",
"msg": "test+47#gmail.com"
}
]
}
}
TASK [Account names] *************************************************************************************************************************************************************************************************************************************************************************************************
task path: /Users/me/create_aws_account.yaml:31
ok: [localhost] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "46",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"failed": false,
"item": "46",
"msg": "account46"
},
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "47",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_verbose_always": true,
"changed": false,
"failed": false,
"item": "47",
"msg": "account47"
}
]
}
}
So what can I do to save only the msg or stdout?
I tried also with set_fact but it seems to does not work either.

An option would be to create lists with set_fact
vars:
email: []
account_name: []
tasks:
- set_fact:
email: "{{ email }} + [ 'test{{ item }}#gmail.com' ]"
account_name: "{{ account_name }} + [ 'account{{ item }}' ]"
with_sequence: start="{{ tag_start }}" end="{{ tag_end }}"

Finally found what I was exactly looking for, and found it here, it is a reply from the user KaffeeKiffer. (The second reply).
Link
At the end is the following:
- set_fact:
emails: "{{ email.results | map(attribute='msg') | list }}"
- set_fact:
account_names: "{{ account_name.results | map(attribute='msg') | list }}"
For completeness sake: | list is required, because map will always return an iterator.

Related

How to combine/match list with specific key/values as hostvar

I have a question about dicts and lists.
What I want to achieve is, have the key and value from a seperate list saved as fact/hostvar for each matching host.
I'm getting a list from a Confluence API that looks like this (abbreviated):
[
{
"title": "MACHINE1",
"_links": {
"tinyui": "/x/1234"
}
},
{
"title": "MACHINE2",
"_links": {
"tinyui": "/x/5678"
}
},
{
"title": "MACHINE3",
"_links": {
"tinyui": "/x/9876"
}
}
]
What worked to get each individual item (just to debug, and show that the loop itself works) is:
- name: DEBUG specific item in list of get_children.json.results
debug:
msg: "{{ item.title }} {{ item._links.tinyui }}"
loop:
"{{ get_children.json.results }}"
delegate_to: 127.0.0.1
Ansible Output (here: output for only one machine):
"msg": "MACHINE1 /x/1234"
Machine Hostnames:
Yes, they are lowercase in my inventory, and in the above list output they are uppercase. But I guess a simple item.title|lower would do fine.
machine1
machine2
machine3
How can I now match the item.title with ansible_hostname and save above API Output as a fact for each machine?
And for clarification: item.title|lower == ansible_hostname
I hope it gets clear to what I want to achieve and thanks to everyone in advance :)
EDIT: Thanks to both answers I managed to get it to work. Using '(?i)^'+VAR+'$' and some other conditional checks you guys posted definitely helped. :)
In a nutshell, given the inventories/tinyui/main.yml inventory:
---
all:
hosts:
machine1:
machine2:
machine3:
i.do.not.exist:
The folowing tinyui.yml playbook:
---
- hosts: all
gather_facts: false
vars:
# In real life, this is returned by your API call
get_children:
json:
results: [
{
"title": "MACHINE1",
"_links": {
"tinyui": "/x/1234"
}
},
{
"title": "MACHINE2",
"_links": {
"tinyui": "/x/5678"
}
},
{
"title": "MACHINE3",
"_links": {
"tinyui": "/x/9876"
}
}
]
# This won't be defined before you call the API which
# returns and registers the correct result. If there is
# no match for host in the returned json, '!no uri!' will
# be returned below. Adapt with a default uri if needed
tinyui: "{{ get_children.json.results
| selectattr('title', '==', inventory_hostname | upper)
| map(attribute='_links.tinyui')
| default(['!no uri!'], true) | first }}"
tasks:
# In real life, you would have called your API
# and registered the result in `get_children` e.g.
# - name: get info from confluence
# uri:
# url: <confluence api endpoint url>
# <more parameters here>
# run_once: true
# delegate_to: localhost
# register: get_children
- name: Display tinyui for host
debug:
msg: "tinyui for host {{ inventory_hostname }} is {{ tinyui }}"
Gives:
$ ansible-playbook -i inventories/tinyui/ tinyui.yml
PLAY [all] ***********************************************************************************************************************
TASK [Display tinyui for host] ***************************************************************************************************
ok: [machine1] => {
"msg": "tinyui for host machine1 is /x/1234"
}
ok: [machine2] => {
"msg": "tinyui for host machine2 is /x/5678"
}
ok: [machine3] => {
"msg": "tinyui for host machine3 is /x/9876"
}
ok: [i.do.not.exist] => {
"msg": "tinyui for host i.do.not.exist is !no uri!"
}
PLAY RECAP ***********************************************************************************************************************
i.do.not.exist : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
machine1 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
machine2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
machine3 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can filter the list of dictionaries by title, taking out the right dict.
You can do this with the following line:
"{{ hostsdata | selectattr('title', 'match', '(?i)^'+host+'$') | first }}"
With selectattr you filter your list of dicts by the title, where this must match '(?i)^'+host+'$'.
The (?i) is the ignore case inline flag for pattern matching, concatenated with the hostname (case does not matter because of ignore case flag). ^...$ specifies that the whole string must match, from start to end.
Since selectattr returns a list as result, you can use first to take out the first element of the list.
Instead of using (?i) you can also set the ignorecase parameter, which will look like this:
"{{ hostsdata | selectattr('title', 'match', '^'+host+'$', 'ignorecase=true') | first }}"
Both variants work equivalently.
Entire playbook:
---
- hosts: localhost
gather_facts: no
vars:
hostsdata:
- {
"title": "MACHINE1",
"_links": {
"tinyui": "/x/1234"
}
}
- {
"title": "MACHINE2",
"_links": {
"tinyui": "/x/5678"
}
}
- {
"title": "MACHINE3",
"_links": {
"tinyui": "/x/9876"
}
}
tasks:
- debug:
var: hostsdata
- name: Pick out host specific dict
set_fact:
machine_data: "{{ hostsdata | selectattr('title', 'match', '(?i)'+host) | first }}"
vars:
host: machine3
- debug:
var: machine_data
- debug:
msg: "{{ machine_data.title }} {{ machine_data._links.tinyui }}"
Resulting output:
TASK [debug] ***********************************************************************************************************
ok: [localhost] => {
"hostsdata": [
{
"_links": {
"tinyui": "/x/1234"
},
"title": "MACHINE1"
},
{
"_links": {
"tinyui": "/x/5678"
},
"title": "MACHINE2"
},
{
"_links": {
"tinyui": "/x/9876"
},
"title": "MACHINE3"
}
]
}
TASK [Pick out host specific dict] *************************************************************************************
ok: [localhost]
TASK [debug] ***********************************************************************************************************
ok: [localhost] => {
"machine_data": {
"_links": {
"tinyui": "/x/9876"
},
"title": "MACHINE3"
}
}
TASK [debug] ***********************************************************************************************************
ok: [localhost] => {
"msg": "MACHINE3 /x/9876"
}
To filter multiple machines, here is another example:
- debug:
msg: "{{ md.title }} {{ md._links.tinyui }}"
when: md | length
vars:
md: "{{ hostsdata | selectattr('title', 'match', '(?i)^'+item+'$') | first | default('') }}"
with_items:
- MachINE1
- MACHINE2
- machine3
- unknown
Add a default('') and a when: to skip a non-existent hostname.
Output:
TASK [debug] ***********************************************************************************************************
ok: [localhost] => (item=MachINE1) => {
"msg": "MACHINE1 /x/1234"
}
ok: [localhost] => (item=MACHINE2) => {
"msg": "MACHINE2 /x/5678"
}
ok: [localhost] => (item=machine3) => {
"msg": "MACHINE3 /x/9876"
}
skipping: [localhost] => (item=unknown)
Convert the titles to lowercase
titles: "{{ get_children.json.results|
map(attribute='title')|
map('lower')|
map('community.general.dict_kv', 'title')|
list }}"
gives
titles:
- title: machine1
- title: machine2
- title: machine3
Replace the lowercase titles and create a dictionary
title_links: "{{ get_children.json.results|
zip(titles)|
map('combine')|
items2dict(key_name='title', value_name='_links') }}"
gives
title_links:
machine1:
tinyui: /x/1234
machine2:
tinyui: /x/5678
machine3:
tinyui: /x/9876
Put these declarations, for example, into the group_vars
shell> cat group_vars/all/title_links.yml
titles: "{{ get_children.json.results|
map(attribute='title')|
map('lower')|
map('community.general.dict_kv', 'title')|
list }}"
title_links: "{{ get_children.json.results|
zip(titles)|
map('combine')|
items2dict(key_name='title', value_name='_links') }}"
Now, you can use the dictionary. For example, given the inventory
shell> cat hosts
10.1.0.11 ansible_hostname=machine1
10.1.0.12 ansible_hostname=machine2
10.1.0.13 ansible_hostname=machine3
the playbook
- hosts: all
gather_facts: false
vars:
get_children:
json:
results:
- _links: {tinyui: /x/1234}
title: MACHINE1
- _links: {tinyui: /x/5678}
title: MACHINE2
- _links: {tinyui: /x/9876}
title: MACHINE3
tasks:
- debug:
msg: "My links: {{ title_links[ansible_hostname] }}"
gives (abridged)
TASK [debug] *********************************************************
ok: [10.1.0.11] =>
msg: 'My links: {''tinyui'': ''/x/1234''}'
ok: [10.1.0.12] =>
msg: 'My links: {''tinyui'': ''/x/5678''}'
ok: [10.1.0.13] =>
msg: 'My links: {''tinyui'': ''/x/9876''}'

Ansible - remove empty elements from the list

I have an ansible output from which I want to remove all empty (none) elements for a specific attribute. Here is the example list:
"resources": [
{
"id": "9c40900909",
"name": "some_name1"
},
{
"id": "pc4b09090"
},
{
"id": "8lknkkn45"
},
{
"id": "9df40900909",
"name": "some_name2"
}
]
Here is how I reduced the list to be just "resources" with attribute "name":
- set_fact:
resources_names: "{{ output.resources | map(attribute='name') }}"
Problem with that is that I get the elements that does not have any value for the name. These are "AnsibleUndefined" in the following output:
- debug:
msg: resources_names list is "{{ resources_names }}"
ok: [localhost] => {
"msg": "resources_names list is \"['some_name1', AnsibleUndefined, AnsibleUndefined, 'some_name2']\""
}
I tried to remove it with reject and regexp but that's not working.
- set_fact:
list2: "{{ resources_names | reject('match', '^$') | list }}"
Same with this one:
- set_fact:
resources_names: "{{ output.resources | map(attribute='name') | rejectattr('name', 'none') }}"
Any idea?
Thanks.
In a nutshell:
---
- hosts: localhost
gather_facts: false
vars:
resources: [
{
"id": "9c40900909",
"name": "some_name1"
},
{
"id": "pc4b09090"
},
{
"id": "8lknkkn45"
},
{
"id": "9df40900909",
"name": "some_name2"
}
]
tasks:
- debug:
msg: "{{ resources | selectattr('name', 'defined') | map(attribute='name') }}"
which gives:
$ ansible-playbook /tmp/play.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
PLAY [localhost] *******************************************************************************************************************************************************************************
TASK [debug] ***********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"some_name1",
"some_name2"
]
}
PLAY RECAP *************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Note for your next question: please make sure you double check your examples and paste valid json/yaml data in your question. Thanks
Use the filter json_query. This filter ignores missing attributes
resources_names: "{{ output.resources|json_query('[].name') }}"
gives
resources_names:
- some_name1
- some_name2

ansible: how to split string with multiple delimiters

Here is my output.
"result.containers": [
{
"Image": "cna.docker.dev/webproxy:1.0.0",
},
{
"Image": "cna-docker-dev-local.docker.dev/lega-customer:1.0.1",
}
]
Here is my code
- name: adding it to groups using images
add_host:
name: "{{ inventory_hostname }}"
groups: '{{ (item.Image.split("/")[1:] | regex_replace("^/", "")).split(":")[0] }}'
with_items: "{{ result.containers }}"
I'm getting the below output:
"add_host": {
"groups": [
"['webproxy"
],
"host_name": "vm4.nodekite.com",
"host_vars": {
}
I would like to filter webproxy from cna.docker.dev/webproxy:1.0.0.
But I'm getting "['webproxy" instead of "webproxy.
Could someone please help!! I even tried this code which fails
(item.Image.split("/")[1:]).split(":")[0]
- debug:
msg: "{{ item.Image | regex_replace('.*?/(.*?):.*', '\\1') }}"
loop: "{{ result.containers | flatten(1) }}"
Example regex is non greedy, adjust as needed.
Gives
ok: [localhost] => (item={'Image': 'cna.docker.dev/webproxy:1.0.0'}) => {
"msg": "webproxy"
}
ok: [localhost] => (item={'Image': 'cna-docker-dev-local.docker.dev/lega-customer:1.0.1'}) => {
"msg": "lega-customer"
}

Ansible and AWS Subnets

I am relatively new to working with Ansible Core / Tower and I am at a complete loss what is causing the following issues. I have spent the past two days reading everything I could find on the topic and I am still stuck, looking for help.
Here is what I currently have setup (among other Ansible playbooks, roles, and tasks to create brand new VPC).
Below are the tasks that I am using to create a set of new subnets, one per availability zone, and get the results back from what is created. These tasks all works perfectly as verified through the AWS Console.
### Create the Internet-facing DMZ subnets ###
- name: Create Subnet(s) in VPC - DMZ
ec2_vpc_subnet:
state: present
vpc_id: "{{ new_vpc_info['vpcs'][0]['id'] }}"
region: "{{ vpc_region }}"
az: "{{ item.az }}"
cidr: "{{ item.subnet }}"
resource_tags:
Name: "{{ item.name }}"
Role: "{{ role_tag }}"
Team: "{{ team_tag }}"
Product Area: "{{ product_area_tag }}"
Portfolio: "{{ portfolio_tag }}"
with_items: "{{ dmz_subnet_az }}"
- name: Get Sunbet Info - DMZ
ec2_vpc_subnet_facts:
region: "{{ vpc_region }}"
filters:
"tag:Name": "{{ item.name }}"
with_items: "{{ dmz_subnet_az }}"
register: new_dmz_subnets
- debug:
var=new_dmz_subnets
The output of the "debug" command is provided below, truncated to remove the rest of the subnets and redacted so I do not get yelled at, which matches up to what is in the AWS Console.
{
"changed": false,
"_ansible_verbose_always": true,
"new_dmz_subnets": {
"msg": "All items completed",
"changed": false,
"results": [
{
"_ansible_parsed": true,
"subnets": [
{
"tags": {
"Product Area": "Engineering Tools",
"Portfolio": "Shared Platform and Operations",
"Role": "splunk-proof-of-concept",
"Name": "DMZ_Subnet_A",
"Team": "Engineering Tools"
},
"subnet_id": "subnet-XXXX",
"assign_ipv6_address_on_creation": false,
"default_for_az": false,
"state": "available",
"ipv6_cidr_block_association_set": [],
"availability_zone": "us-east-1a",
"vpc_id": "vpc-XXXX",
"cidr_block": "x.x.x.x/24",
"available_ip_address_count": 251,
"id": "subnet-XXXX",
"map_public_ip_on_launch": false
}
],
"changed": false,
"_ansible_item_label": {
"subnet": "x.x.x.x/24",
"az": "us-east-1a",
"name": "DMZ_Subnet_A"
},
"item": {
"subnet": "x.x.x.x/24",
"az": "us-east-1a",
"name": "DMZ_Subnet_A"
},
"_ansible_item_result": true,
"failed": false,
"invocation": {
"module_args": {
"profile": null,
"aws_secret_key": null,
"aws_access_key": null,
"security_token": null,
"region": "us-east-1",
"filters": {
"tag:Name": "DMZ_Subnet_A"
},
"ec2_url": null,
"subnet_ids": [],
"validate_certs": true
}
},
"_ansible_ignore_errors": null,
"_ansible_no_log": false
},
{
"_ansible_parsed": true,
"subnets": [
{
"tags": {
"Product Area": "Engineering Tools",
"Portfolio": "Shared Platform and Operations",
"Role": "splunk-proof-of-concept",
"Name": "DMZ_Subnet_B",
"Team": "Engineering Tools"
},
"subnet_id": "subnet-XXXX",
"assign_ipv6_address_on_creation": false,
"default_for_az": false,
"state": "available",
"ipv6_cidr_block_association_set": [],
"availability_zone": "us-east-1b",
"vpc_id": "vpc-XXXX",
"cidr_block": "x.x.x.x/24",
"available_ip_address_count": 251,
"id": "subnet-XXXX",
"map_public_ip_on_launch": false
}
],
"changed": false,
"_ansible_item_label": {
"subnet": "x.x.x.x/24",
"az": "us-east-1b",
"name": "DMZ_Subnet_B"
},
"item": {
"subnet": "x.x.x.x/24",
"az": "us-east-1b",
"name": "DMZ_Subnet_B"
},
"_ansible_item_result": true,
"failed": false,
"invocation": {
"module_args": {
"profile": null,
"aws_secret_key": null,
"aws_access_key": null,
"security_token": null,
"region": "us-east-1",
"filters": {
"tag:Name": "DMZ_Subnet_B"
},
"ec2_url": null,
"subnet_ids": [],
"validate_certs": true
}
},
"_ansible_ignore_errors": null,
"_ansible_no_log": false
},
......
}
]
},
"_ansible_no_log": false
}
Now onto the tasks that I am having issues getting working, below is my most recent attempt, which may be completely in left field due to me trying everything I found to get it working. I am attempting to get a list of the "subnet_id" from the registered "new_dmz_subnets" variable, then concatenating it with a "name" that is set in a vars file, and finally using that information to create a NAT Gateway within each of the subnets.
### Create the NAT Gateway in VPC ###
- name: Set DMZ Subnet facts
set_fact:
subnet_id_items:
subnet_id: '{{ item.subnets | map(attribute="subnet_id") | list }}'
with_items: "{{ new_dmz_subnets }}"
register: subnet_id_list
- name: Set Name and DMZ Subnet loop facts
set_fact:
name_subnet_items:
name: "{{ nat_gateway.name }}"
subnet_id: "{{ item.subnet_id }}"
loop: "{{ subnet_id_list }}"
register: name_subnet_list
- debug:
var=name_subnet_list
- name: Create NAT Gateway, allocate new EIP, in VPC
ec2_vpc_nat_gateway:
state: present
subnet_id: "{{ item.subnet_id }}"
region: "{{ vpc_region }}"
wait: yes
if_exist_do_not_create: true
tags:
Name: "{{ item.name }}"
Role: "{{ role_tag }}"
Team: "{{ team_tag }}"
Product Area: "{{ product_area_tag }}"
Portfolio: "{{ portfolio_tag }}"
with_items: "{{ name_subnet_list }}"
register: new_nat_gateway
- debug:
var=new_nat_gateway
When I ran this setup, I got the following fatal error message, which is pretty much the same across every variation I have attempted.
12:55:15
fatal: [localhost]: FAILED! => {
"msg": "The task includes an option with an undefined variable. The error was: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'subnets'\n\nThe error appears to have been in '/var/lib/awx/projects/_6__erik_andresen_git/ansible/splunk_poc_playbook/roles/create_networking_role/tasks/create_gateways_task.yml': line 21, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n### Starting working on this Task ###\n- name: Set DMZ Subnet facts\n ^ here\n"
}
Please let me know if I can provide any additional details and thanks in advance for the help!!!
-- Erik
I came across a setup that actually works! It may not be the best way to do it and I am still open to suggestions, but it at least works.
Here is code of the "ec2_vpc_subnet" module and collecting the Subnet IDs for later use in the playbook.
### Create the Internet-facing DMZ subnets ###
- name: Create Subnet(s) in VPC - DMZ
ec2_vpc_subnet:
state: present
vpc_id: "{{ vpc_id }}"
region: "{{ vpc_region }}"
az: "{{ item.az }}"
cidr: "{{ item.subnet }}"
resource_tags:
Name: "{{ item.name }}"
Role: "{{ role_tag }}"
Team: "{{ team_tag }}"
Product Area: "{{ product_area_tag }}"
Portfolio: "{{ portfolio_tag }}"
Created By: "{{ created_by }}"
with_items: "{{ dmz_subnet_az }}"
register: new_dmz_subnets
- name: Set facts for Subnet - DMZ
set_fact:
subnet_dmz_id: "{{ subnet_dmz_id | default({}) | combine({ item.subnet.tags.Name: item.subnet.id }) }}"
loop: "{{ new_dmz_subnets.results }}"
- debug:
var=subnet_dmz_id
And here is the use of the Subnet IDs in the "ec2_vpc_nat_gateway" module to create a NAT Gateway within each Availability Zone.
### Create the NAT Gateway in VPC ###
- name: Create NAT Gateway, allocate new EIP, in VPC
ec2_vpc_nat_gateway:
state: present
# NAT Gateways being deployed in DMZ subnets
subnet_id: "{{ subnet_dmz_id[item.subnet_name] }}"
region: "{{ vpc_region }}"
wait: yes
if_exist_do_not_create: true
# Tags not supported in the "ec2_vpc_nat_gateway" module
# https://github.com/ansible/ansible/issues/44339
#tags:
# Name: "{{ item.name }}"
# Role: "{{ role_tag }}"
# Team: "{{ team_tag }}"
# Product Area: "{{ product_area_tag }}"
# Portfolio: "{{ portfolio_tag }}"
# Created By: "{{ created_by }}"
with_items: "{{ nat_gateway }}"
register: new_nat_gateway
- debug:
var=new_nat_gateway

Ansible: Not able to get AMI ID of newly created AMI

I am using a playbook to create ami and trying to fetch the newly created ami id. But the debug is getting 'msg": "AMI not updated"'' Please help
- name: Create AMI
ec2_ami:
region: "{{ec2_region}}"
name: "aws-{{ec2_region}}"
state: present
instance_id: "{{ec2_info.instances.0.id}}"
wait: yes
tags:
Name: "aws-{{ec2_region}}-mr-ami"
deployment_type: "{{deployment_type}}"
pop_type: "{{pop_type}}"
register: image
- pause:
seconds: 10
- debug:
msg: "{{image}}"
- name: Set image id as fact
set_fact:
mr_ami_id: "{{image.image_id}}"
Playbook output
TASK [Create AMI]
*************************************************************************************************************************** ok: [localhost] => {
"changed": false,
"invocation": {
"module_args": {
"architecture": "x86_64",
"aws_access_key": null,
"aws_secret_key": null,
"delete_snapshot": false,
"description": "",
"device_mapping": null,
"ec2_url": null,
"image_id": null,
"instance_id": "i-065404d0d37e0acfb",
"kernel_id": null,
"launch_permissions": null,
"name": "aws-ap-southeast-2-MessageRelay",
"no_reboot": false,
"profile": null,
"region": "ap-southeast-2",
"root_device_name": null,
"security_token": null,
"state": "present",
"tags": {
"Name": "aws-ap-southeast-2-mr-ami",
"deployment_type": "dev",
"pop_type": "mgmt"
},
"validate_certs": true,
"virtualization_type": "hvm",
"wait": true,
"wait_timeout": "900"
}
},
"launch_permissions": {},
"msg": "AMI not updated" }
TASK [pause]
******************************************************************************************************************************** task path: /root/*********************/create_ami.yml:24 Pausing for 10 seconds (ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort) ok: [localhost] => {
"changed": false,
"delta": 10,
"rc": 0,
"start": "2017-08-01 08:48:29.756546",
"stderr": "",
"stdout": "Paused for 10.0 seconds",
"stop": "2017-08-01 08:48:39.756843",
"user_input": "" }
TASK [debug]
******************************************************************************************************************************** task path: /root/*****************/create_ami.yml:27 ok: [localhost]
=> {
"changed": false,
"msg": {
"changed": false,
"launch_permissions": {},
"msg": "AMI not updated"
} }
TASK [Set image id as fact]
***************************************************************************************************************** task path: /root/***********/trunk/ncs/pop-deployment/********_asg/tasks/create_ami.yml:30 fatal: [localhost]: FAILED! => {
"failed": true,
"msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'dict object' has no attribute 'image_id'\n\nThe error appears to have been in '/root/**************************/create_ami.yml': line 30, 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: Set image id as fact\n ^ here\n" }
PLAY RECAP
********************************************************************************************************************************** ip-10-10-5-111.ap-southeast-2.compute.internal : ok=13 changed=9 unreachable=0 failed=0 localhost : ok=69 changed=31 unreachable=0 failed=1
This was happening because AMI with name "aws-{{ec2_region}}" was already there and hence no new ami was getting created. I deleted the old AMI and ran the playbook again without any issues.