Store ansible output to variable - amazon-ec2

I want to use Ansible that would get information about an AWS Ec2 instance. I am really looking for it's Instance-ID. I am going to use this to loop through a template. But I can't seem to get the instance-ID. Here is what I have so far:
---
- name: Including Variables
include_vars:
file: Linux.yml
- name: Gathering EC2 Facts
ec2_remote_facts:
aws_access_key: "{{ access_key }}"
aws_secret_key: "{{ secret_key }}"
region: us-east-1
filters:
"tag:Name": "{{ ansible_hostname }}"
register: instanceId
- debug: var=instanceId.instances.id
I know this is incorrect as when I run this i get:
"instanceId.instances.id": "VARIABLE IS NOT DEFINED!"
Can someone tell me of a way to return the instanceId?

If you do something for the first time, do it gradually... To understand what's inside. Like:
- debug: var=instanceId
# to see raw result and find out that `instances` is there
- debug: var=instanceId.instances
# to see what `instanses` is, and to see it is a list
- debug: var=instanceId.instances[0]
# to see the first element of the list and see it's properties
- debug: var=instanceId.instances[0].id
# to see instance ID

Related

ansible how to load variables from another role, without executing it?

I have a task to create a one-off cleanup playbook which is using variables from a role, but i don't need to execute that role. Is there a way to provide a role name to get everything from it's defaults and vars, without hardcoding paths to it? I also want to use vars defined in group_vars or host_vars with higher precedence than the ones included from role.
Example task:
- name: stop kafka and zookeeper services if they exist
service:
name: "{{ item }}"
state: stopped
with_items:
- "{{ kafka_service_name }}"
- "{{ zookeeper_service_name }}"
ignore_errors: true
where kafka_service_name and zookeeper_service_name are contained in role kafka, but may also be present in i.e. group_vars.
I came up with a fairly hacky solution, which looks like this:
- name: save old host_vars
set_fact:
old_host_vars: "{{ hostvars[inventory_hostname] }}"
- name: load kafka role variables
include_vars:
dir: "{{ item.root }}/{{ item.path }}"
vars:
params:
files:
- kafka
paths: "{{ ['roles'] + lookup('config', 'DEFAULT_ROLES_PATH') }}"
with_filetree: "{{ lookup('first_found', params) }}"
when: item.state == 'directory' and item.path in ['defaults', 'vars']
- name: stop kafka and zookeeper services if they exist
service:
name: "{{ item }}"
state: stopped
with_items:
- "{{ old_host_vars['kafka_service_name'] | default(kafka_service_name) }}"
- "{{ old_host_vars['zookeeper_service_name'] | default(zookeeper_service_name) }}"
include_vars task finds the first kafka role folder in ./roles and in default role locations, then includes files from directories defaults and vars, in correct order.
I had to save old hostvars due to include_vars having higher priority than anything but extra vars as per ansible doc, and then using included var only if old_host_vars returned nothing.
If you don't have a requirement to load group_vars - include vars works quite nice in one task and looks way better.
UPD: Here is the regexp that i used to replace vars with old_host_vars hack.
This was tested in vscode search/replace, but can be adjusted for any other editor
Search for vars that start with kafka_:
\{\{ (kafka_\w*) \}\}
Replace with:
{{ old_host_vars['$1'] | default($1) }}

Write Host Variables to file in a loop with ansible

I am trying to build up a config file that contains the list of my inventory host servers and their fields eg. IP,FQDN etc.
Here is my part of inventory file :
ocp_cluster:
hosts:
anbootstrap.ocp.hattusas.tst:
fqdn: anbootstrap.ocp.hattusas.tst
ip: 10.72.217.92
anmaster1.ocp.hattusas.tst:
fqdn: anmaster1.ocp.hattusas.tst
ip: 10.72.217.93
anmaster2.ocp.hattusas.tst:
fqdn: anmaster2.ocp.hattusas.tst
ip: 10.72.217.94
anmaster3.ocp.hattusas.tst:
And here is my playbook:
- name: Adding OCP Clusters to DHCP configuration
debug:
"{{ hostvars[item][fqdn] }}"
loop: "{{ groups['ocp_cluster'] }}"
(I will use blockinfile soon)
When I ran my playbook I am getting undefined error fqdn. I tried using a for loop and it didn't help. Any suggestions?
Thanks a lot.
The fixed task is below
- debug:
msg: "{{ hostvars[item]['fqdn'] }}"
loop: "{{ groups['ocp_cluster'] }}"
Debug parameter msg was missing
fqdn is an attribute of a dictionary. It must be quoted in brackets. Similar to ocp_cluster.
It's possible to use the dot notation and simplify the references to the attributes of the dictionaries
- debug:
msg: "{{ hostvars[item].fqdn }}"
loop: "{{ groups.ocp_cluster }}"

Ansible loop returns outputs entire object

I am gathering information about AWS ec2 instances and then attempting to loop through them to output the instance_id property of the registered results.
When I run through the loop I get the expected results, but I also get the entire registered object outputted as well. It appears to flatten the object to a string and output it. What is the reason for the additional output and is there a better loop method I should use?
Thank you in advance!
---
- hosts: localhost
gather_facts: false
connection: local
tasks:
- name: get ec2 instance info
ec2_instance_info:
region: us-east-1
filters:
"tag:app": ansible
"tag:env": dev
register: ec2
- debug:
msg: "{{ item['instance_id'] }}"
loop: "{{ ec2['instances'] }}"
FIX
- debug:
msg: "{{ item['instance_id'] }}"
loop: "{{ ec2['instances'] }}"
loop_control:
label: "{{ item.instance_id }}"
I think I found your answer #duffney.
By the looks of things Was addressed as a bug/feature and amended
https://github.com/ansible/ansible/issues/35493
Does it help out what you are looking for?

How can Ansible "register" in a variable the result of including a playbook?

How can an Ansible playbook register in a variable the result of including another playbook?
For example, would the following register the result of executing tasks/foo.yml in result_of_foo?
tasks:
- include: tasks/foo.yml
- register: result_of_foo
How else can Ansible record the result of a task sequence?
The short answer is that this can't be done.
The register statement is used to store the output of a single task into a variable. The exact contents of the registered variable can vary widely depending on the type of task (for example a shell task will include stdout & stderr output from the command you run in the registered variable, while the stat task will provide details of the file that is passed to the task).
If you have an include file with an arbitrary number of tasks within it then Ansible would have no way of knowing what to store in the variable in your example.
Each individual task within your include file can register variables, and you can reference those variables elsewhere, so there's really no need to even do something like this.
I was able to do this by passing a variable name as a variable to be used in the task. I included my main.yaml and included cgw.yaml files below.
main.yaml:
- name: Create App A CGW
include: cgw.yaml
vars:
bgp_asn: "{{ asn_spoke }}"
ip_address: "{{ eip_app_a.public_ip }}"
name: cgw-app-a
region: "{{ aws_region }}"
aws_access_key: "{{ ec2_access_key }}"
aws_secret_key: "{{ ec2_secret_key }}"
register: cgw_app_a
cgw.yaml:
- name: "{{ name }}"
ec2_customer_gateway:
bgp_asn: "{{ bgp_asn }}"
ip_address: "{{ ip_address }}"
name: "{{ name }}"
region: "{{ region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
register: "{{ register }}"

Tag Name from EC2-group in Ansible

This is another question coming from the following post...:
loops over the registered variable to inspect the results in ansible
So basically having:
- name: EC2Group | Creating an EC2 Security Group inside the Mentioned VPC
local_action:
module: ec2_group
name: "{{ item.sg_name }}"
description: "{{ item.sg_description }}"
region: "{{ vpc_region }}" # Change the AWS region here
vpc_id: "{{ vpc.vpc_id }}" # vpc is the resgister name, you can also set it manually
state: present
rules: "{{ item.sg_rules }}"
with_items: ec2_security_groups
register: aws_sg
- name: Tag the security group with a name
local_action:
module: ec2_tag
resource: "{{ item.group_id }}"
region: "{{ vpc_region }}"
state: present
tags:
Name: "{{vpc_name }}-group"
with_items: aws_sg.results
I wonder how is possible to get the TAG NAME
tags:
Name: "{{ item.sg_name }}"
The same value as per the primary name definition on the Security Groups?
local_action:
module: ec2_group
name: "{{ item.sg_name }}"
I am trying to make that possible but I am not sure how to do it. If it's also possible to retrieve that item?
Thanks!
Tags are available after the ec2.py inventory script is run - they always take the value of tag_key_value where 'key' is the name of the tag, and 'value' is the value within that tag. i.e. if you create a tag called 'Application' and give it a value of 'AwesomeApplication' you would get 'tag_Application_AwesomeApplication'.
That said, if you have just created instances and want to run some commands against those new instances, parse the output from the create instance command to get a list of the IP addresses, and add them to a temporary group, and then you can run commands against that group within the same playbook:
...
- name: add hosts to temporary group
add_host: name="{{ item }}" groups=temporarygroup
with_items: parsedipaddresses
- hosts: temporarygroup
tasks:
- name: awesome script to do stuff goes here
...

Resources