Cant get the private ip from an EC2 result - ansible

Trying to create a playbook that will let me choose if i want spot or On-demand EC2 with passing external var, all going fine except the part of getting the private ip from the result and settings it as fact for further usage.
i've tried different paths like item.instances[0].private_ip
and just cant seems to get the right one.
---
- hosts: localhost
tasks:
- name: when true
ec2:
region: us-east-1
instance_type: t2.nano
key_name: test_key
instance_type: t2.micro
image: ami-0aec0138b2*****
wait: yes
count: 1
vpc_subnet_id: subnet-00fdda1452d****
assign_public_ip: no
spot_price: 1
register: ci_ec2_true
when: var == "true"
- name: when false
ec2:
region: us-east-1
instance_type: t2.nano
key_name: test_key
instance_type: t2.micro
image: ami-0aec0138b2****
wait: yes
count: 1
vpc_subnet_id: subnet-00fdda1452d0****
assign_public_ip: no
register: ci_ec2_false
when: var == "false"
- name: ci_ec2_true
debug:
msg: "{{ ci_ec2_true }}"
- name: Spot / On-demand var router
set_fact:
ci_ec2: "{{ ci_ec2_true if ci_ec2_false is skipped else ci_ec2_false }}"
- name: debug ci_ec2
debug:
msg: "{{ ci_ec2 }}"
- name: ec2_prov - set fact for all ci_machine_ips
set_fact: private_ips="{{ item.instances[0].private_ip }}"
with_items: "{{ ci_ec2 }}"
register: ci_ec2_ip_results
- debug:
msg: "{{ ci_ec2_ip_results }}"
The expected result should be the private ip value, instead im getting this error:
TASK [ec2_prov - set fact for all ci_machine_ips] ******************************
**********
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: 'ansible.vars.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'instances'\n\nThe error appears to have been in '/root/test/when-create.yml': line 50, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: ec2_prov - set fact for all ci_machine_ips\n ^ here\n"}
the command used to run the playbook is:
ansible-playbook when-create.yml -e var=true
TASK [debug ci_ec2] ************************************************************
ok: [localhost] => {
"msg": {
"changed": true,
"instance_ids": [
"i-0485794cd8a299b27"
],
"instances": [
{
"ami_launch_index": "0",
"architecture": "x86_64",
"block_device_mapping": {
"/dev/xvda": {
"delete_on_termination": true,
"status": "attached",
"volume_id": "vol-0cd42f8696aef9bbd"
}
},
"dns_name": "",
"ebs_optimized": false,
"groups": {
"sg-07c7177c": "default"
},
"hypervisor": "xen",
"id": "i-0485794cd8a299b27",
"image_id": "ami-0aec0138b2a5****",
"instance_type": "t2.micro",
"kernel": null,
"key_name": "test_Key",
"launch_time": "2019-05-11T16:41:10.000Z",
"placement": "us-east-1a",
"private_dns_name": "ip-10-220-129-224.ec2.internal",
"private_ip": "10.220.129.224",
"public_dns_name": "",
"public_ip": null,
"ramdisk": null,
"region": "us-east-1",
"root_device_name": "/dev/xvda",
"root_device_type": "ebs",
"state": "running",
"state_code": 16,
"tags": {
"Created_By": "InstanceLaunch"
},
"tenancy": "default",
"virtualization_type": "hvm"
}
],
"tagged_instances": []
}
}

so eventually i found the way...
- name: ec2_prov - set fact for all ci_machine_ips
set_fact: private_ips="{{ item.private_ip }}"
with_items: "{{ ci_ec2.instances }}"
register: ci_ec2_ip_results

Related

Output of Ansibble task

I am using command hcloud to create cloud server in Hetzner. I get an output like this:
changed: [localhost] => (item={'name': 'TEST-VARIABLES', 'server_type': 'cx11', 'os_image': 'ubuntu-20.04', 'server_labels': 'Name=test-server', 'server_location': 'hel1'}) => {
"ansible_loop_var": "item",
"changed": true,
"hcloud_server": {
"backup_window": "None",
"datacenter": "hel1-dc2",
"delete_protection": false,
"id": "19461514",
"image": "ubuntu-20.04",
"ipv4_address": "11.111.111.111",
"ipv6": "1a71:7f9:c011:0b09::/64",
"labels": {
"Name": "test-server"
},
"location": "hel1",
"name": "TEST-VARIABLES",
"placement_group": null,
"rebuild_protection": false,
"rescue_enabled": false,
"server_type": "cx11",
"status": "running"
},
"invocation": {
"module_args": {
"allow_deprecated_image": false,
"api_token": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"backups": null,
"datacenter": null,
"delete_protection": null,
"endpoint": "https://api.SERVER.cloud/v1",
"firewalls": null,
"force": false,
"force_upgrade": false,
"id": null,
"image": "ubuntu-20.04",
"labels": {
"Name": "test-server"
},
"location": "hel1",
"name": "TEST-VARIABLES",
"placement_group": null,
"rebuild_protection": null,
"rescue_mode": null,
"server_type": "cx11",
"ssh_keys": null,
"state": "present",
"upgrade_disk": false,
"user_data": null,
"volumes": null
}
},
"item": {
"name": "TEST-VARIABLES",
"os_image": "ubuntu-20.04",
"server_labels": "Name=test-server",
"server_location": "hel1",
"server_type": "cx11"
},
"root_password": "DFLDJFLDFDLFKJDLFKJ"
}
I try to get line with "ipv4_address": "11.111.111.111", and "root_password": "DFLDJFLDFDLFKJDLFKJ", but when I use task:
---
- name: Create a basic server
hcloud_server:
api_token: "{{ token }}"
name: "{{ item.name }}"
server_type: "{{ item.server_type }}"
image: "{{ item.os_image }}"
labels: "{{ item.server_labels }}"
location: "{{ item.server_location }}"
state: present
register: server_info
with_items: "{{ server }}"
- name: Here IP
debug:
var: server_info.root_password
I got error:
TASK [/etc/ansible/roles/CREATE-server : Here IP.] *********************************************************************************************************
ok: [localhost] => {
"server_info.root_password": "VARIABLE IS NOT DEFINED!"
}
Could you please help, how I can get IP line and password line, to use them in the next task (for example to send via email). Thank you!
you register the content of loop, so your result is a list (results):
- name: display
debug:
msg: "ip: {{ item.hcloud_server.ipv4_address }} has password: {{ item.root_password }}"
loop: "{{ server_info.results }}"
result: here you have just one server declared, so just one item in the list results
"msg": "ip: 11.111.111.111 has password: DFDFDFDFDFDFDFDF"
if you want to limit the output of record, you could add loop_control parameter to loop with argument label:
loop: "{{ server_info.results }}"
loop_control:
label: "{{ item.hcloud_server.ipv4_address }}"
you could put another comment if you want with label or even empty string:
loop: "{{ server_info.results }}"
loop_control:
label: "result"

ansible task doesn't resolve variable

I'm trying to get VG_Name using below code. I can see variable value using debug:var but it doesn't work inside actual task & print value as "vg": "hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg"
tasks:
- set_fact:
LV_name: "opt"
- name: Get VG Name
set_fact:
vg_command: "{{ 'hostvars[inventory_hostname].ansible_lvm.lvs.'+ LV_name +'.vg' }}"
- name: Show VG
debug:
var: "{{ vg_command }}"
- name: extend logical volume and file system
community.general.lvol:
vg: "{{ vg_command }}"
lv: "{{ LV_name }}"
size: +100%FREE
resizefs: yes
Output:
TASK [Get VG Name] *********************************************************************************************************************************************************************************
task path: /root/ansible_disk/disk_extend.yml:92
ok: [SERVER-NAME] => {
"ansible_facts": {
"vg_command": "hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg"
},
"changed": false
}
TASK [Show VG] *************************************************************************************************************************************************************************************
task path: /root/ansible_disk/disk_extend.yml:96
ok: [SERVER-NAME] => {
"hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg": "vg_00"
}
TASK [extend logical volume and file system] *******************************************************************************************************************************************************
task path: /root/ansible_disk/disk_extend.yml:109
fatal: [SERVER-NAME]: FAILED! => {
"changed": false,
"err": " Volume group name \"hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg\" has invalid characters.\n Cannot process volume group hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg\n",
"invocation": {
"module_args": {
"active": true,
"force": false,
"lv": "varlog",
"opts": null,
"pvs": null,
"resizefs": true,
"shrink": true,
"size": "+100%FREE",
"snapshot": null,
"state": "present",
"thinpool": null,
"vg": "hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg"
}
},
"msg": "Volume group hostvars[inventory_hostname].ansible_lvm.lvs.varlog.vg does not exist.",
"rc": 5
}
Tried all possible ways(lookup, vars etc) that I could think of but no luck, any help would be appreciated!
You are building your string incoorectly, leaving inventory[hostname] inside the single quotes, it will be treated as a literal; so:
vg_command: "{{ 'hostvars[inventory_hostname].ansible_lvm.lvs.'+ LV_name +'.vg' }}"
should instead be:
vg_command: "{{ hostvars[inventory_hostname].ansible_lvm.lvs[LV_name].vg }}"

Juniper Software upgrade faills cause of not enough space

I've tried to update a EX2300 switch from Juniper with the ansible module(juniper_junos_software) but eveytime i tried it fails cause it doesn't have enough space and i tried a bunch of stuff all from trying to SCP with other Ansible modules such as (net_put and junipernetworks.junos.junos_scp) which to no relief i can't get to work either
The Ansible code is:
- name: Install Junos OS
hosts: EX
roles:
- Juniper.junos
connection: local
gather_facts: no
vars:
OS_version: "20.4R1.12"
OS_package: "junos-arm-32-20.4R1.12.tgz"
pkg_dir: "/etc/JunOS"
log_dir: "/var/log"
netconf_port: 830
wait_time: 3600
tasks:
- name: Checking NETCONF connectivity
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: 5
- name: Clean up the device
juniper_junos_command:
commands:
- request system snapshot delete snap*
- request system software delete jweb
timeout: 200
register: response
- name: Print response from Clean up the device
debug:
var: response
- name: Install Junos OS package
juniper_junos_software:
version: "{{ OS_version }}"
local_package: "{{ pkg_dir }}/{{ OS_package }}"
cleanfs: yes
validate: no
reboot: true
logfile: "{{ log_dir }}/ansible.log"
register: sw
notify:
- wait_reboot
- name: Print response
debug:
var: response
- name: Snapshot Slice alternate
juniper_junos_command:
commands: request system snapshot slice alternate
timeout: 200
register: response
handlers:
- name: wait_reboot
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ netconf_port }}"
timeout: "{{ wait_time }}"
when: not sw.check_mode
The error i get is:
"changed": true,
"check_mode": false,
"invocation": {
"module_args": {
"attempts": null,
"baud": null,
"checksum": null,
"checksum_algorithm": "md5",
"checksum_timeout": 300,
"cleanfs_timeout": 300,
"console": null,
"cs_passwd": null,
"cs_user": null,
"force_host": false,
"host": "10.15.84.100",
"issu": false,
"level": null,
"logdir": null,
"logfile": "/var/log/ansible.log",
"mode": null,
"nssu": false,
"passwd": null,
"port": 830,
"provider": null,
"ssh_config": null,
"ssh_private_key_file": "/etc/ansible/ssh-keys/id_ed25519",
"timeout": 30,
"user": "ansible",
"validate": false,
"vmhost": false
}
},
"msg": [
"Unable to install the software %s",
"\nERROR: estimate of space required: 119 Mbytes, available: 41 Mbytes\n"
]
}
"space required: 119 Mbytes, available: 41 Mbytes" indicates you need to delete some files, usually image files.

Undefined variable when passing dictionary to a submodule-role

I'm having a really weird problem on my ansible role. I send two dictionaries to a submodule like that:
import_role:
name: .submodules/monitoring-plugins
vars:
monitoring_plugins:
check_content:
command: "files/icinga/commands/check_content"
dest: "{{ icinga_server_plugin_directory }}"
group: "root"
owner: "root"
mode: "0755"
package: "curl"
src: "files/plugins/server/check_content"
check_http_response_time:
command: "files/icinga/commands/check_http_response_time"
dest: "{{ icinga_server_plugin_directory }}"
group: "root"
owner: "root"
mode: "0775"
src: "files/plugins/server/check_http_response_time"
check_https_response_time:
command: "files/icinga/commands/check_https_response_time"
dest: "{{ icinga_server_plugin_directory }}"
group: "root"
owner: "root"
mode: "0775"
src: "files/plugins/server/check_https_response_time"
check_port:
command: "files/icinga/commands/check_port"
dest: "{{ icinga_server_plugin_directory }}"
group: "root"
owner: "root"
mode: "0775"
src: "files/plugins/server/check_port"
check_ssl_cert:
command: "files/icinga/commands/check_ssl_cert"
dest: "{{ icinga_server_plugin_directory }}"
group: "root"
owner: "root"
mode: "0775"
src: "files/plugins/server/check_ssl_cert"
custom_services:
content:
service-preamble: 'apply Service "content"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/content.conf') }}"
http_response_time:
service-preamble: 'apply Service "http_response_time"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/http_response_time.conf') }}"
https_response_time:
service-preamble: 'apply Service "https-response-time"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/https_response_time.conf') }}"
http_port:
service-preamble: 'apply Service "http-port"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/http_port.conf') }}"
https_port:
service-preamble: 'apply Service "https-port"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/https_port.conf') }}"
ssl_cert:
service-preamble: 'apply Service "ssl-cert"'
configuration: |
{{ common_service_header }}
assign where host.vars.ansible.system == "Linux"
definition:
"{{ lookup('template', 'config/services/ssl_cert.conf') }}"
on the submodule I created two debug tasks:
- debug:
var: monitoring_plugins
- debug:
var: custom_services
output:
ok: [server.test] => {
"monitoring_plugins": {
"check_content": {
"command": "files/icinga/commands/check_content",
"dest": "/usr/lib/nagios/plugins",
"group": "root",
"mode": "0755",
"owner": "root",
"package": "curl",
"src": "files/plugins/server/check_content"
},
"check_http_response_time": {
"command": "files/icinga/commands/check_http_response_time",
"dest": "/usr/lib/nagios/plugins",
"group": "root",
"mode": "0775",
"owner": "root",
"src": "files/plugins/server/check_http_response_time"
},
"check_https_response_time": {
"command": "files/icinga/commands/check_https_response_time",
"dest": "/usr/lib/nagios/plugins",
"group": "root",
"mode": "0775",
"owner": "root",
"src": "files/plugins/server/check_https_response_time"
},
"check_port": {
"command": "files/icinga/commands/check_port",
"dest": "/usr/lib/nagios/plugins",
"group": "root",
"mode": "0775",
"owner": "root",
"src": "files/plugins/server/check_port"
},
"check_ssl_cert": {
"command": "files/icinga/commands/check_ssl_cert",
"dest": "/usr/lib/nagios/plugins",
"group": "root",
"mode": "0775",
"owner": "root",
"src": "files/plugins/server/check_ssl_cert"
}
}
}
TASK [.submodules/monitoring-plugins : debug] ************************************
ok: [server.test] => {
"custom_services": "VARIABLE IS NOT DEFINED!"
}
Does anybody have any idea what could possibly go wrong? I sent both of them from the very same task but yet one of them looks just fine and the other don't. I even tried to remove the submodule and add it again but it still doesn't work. Any other suggestions would be very appreciated!
The background
A var containing other vars expansion being undefined cannot be interpreted and is undefined.
$ ansible localhost -e undef="{{ i_dont_exist }}" -m debug -a var=undef
localhost | SUCCESS => {
"undef": "VARIABLE IS NOT DEFINED!"
}
To see what is going wrong, you need to actually expand the var at debug time
$ ansible localhost -e undef="{{ i_dont_exist }}" -m debug -a msg="{{ undef }}"
localhost | FAILED! => {
"msg": "The task includes an option with an undefined variable. The error was: 'i_dont_exist' is undefined"
}
Your specific case
The root cause is that common_service_header is undefined. Since it is used inside your variable definition for the role include, ansible tries to interpret it, fails, and the var stays undefined.
You will actually see the same result for monitoring_plugins if you undefine icinga_server_plugin_directory.
To have some more info on what actually happens, the "trick" is to force ansible to interpret the variable in your debug. There are two possible ways to do this:
- name: Use a simple jinja2 expansion
debug:
msg: "{{ custom_services }}"
- name: Use a the 'vars' lookup
debug:
msg: "{{ lookup('vars', 'custom_services') }}"
Which then gives a more meaningful info (reformated for legibility....):
TASK [.submodules/monitoring-plugins : debug] *****************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an
undefined variable. The error was: 'common_service_header' is undefined\n\n
The error appears to be in
'/some/path/.submodules/monitoring-plugins/tasks/main.yml': line 4, column 3,
but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n
The offending line appears to be:\n\n
msg: \"{{ lookup('vars', 'monitoring_plugins') }}\"\n- debug:\n ^ here\n"}

Is it possible to set/lookup Ansible facts when play returns multiple values

I have the following playbook in AWX that looks up Infoblox hosts based on their Mac Address and then outputs the information in a more user friendly format.
The current playbook works providing that a single host with that Mac address exists but fails if there are multiple.
---
- hosts: localhost
connection: local
vars:
niosip: ""
niosmac: ""
niosdhcp: ""
nioshostname: ""
niossearchcatagory: "{{ 'name' if searchcatagory == 'Hostname' else 'ipv4addr' if searchcatagory == 'IP Address' else 'mac' if searchcatagory == 'Mac Address'}}"
pre_tasks:
- include_vars:
file: creds.yml
tasks:
- name: fetch host record
set_fact:
host: "{{ lookup('nios', 'record:host', filter={niossearchcatagory: searchcriteria, 'view': 'Internal'}, provider=nios_provider) }}"
- name: Set niosip
set_fact:
niosip: "{{ host.ipv4addrs[0].ipv4addr }}"
nioshostname: "{{ host.name }}"
niosdhcp: "{{ host.ipv4addrs[0].configure_for_dhcp }}"
niosmac: "{{ host.ipv4addrs[0].mac }}"
when: host != [] and host.ipv4addrs[0].mac is defined
- name: Set niosip
set_fact:
niosip: "{{ host.ipv4addrs[0].ipv4addr }}"
nioshostname: "{{ host.name }}"
niosdhcp: "{{ host.ipv4addrs[0].configure_for_dhcp }}"
when: host != [] and host.ipv4addrs[0].mac is undefined
- name: Host not found
debug:
msg: 'Cant find related host'
when: host == []
- name: Display Display Registration Info
debug:
msg:
- Hostname = {{ nioshostname }}
- IP = {{ niosip }}
- Mac Address {{ niosmac }}
- Registered for DHCP = {{ niosdhcp }}
when: host != [] and host.ipv4addrs[0].mac is defined
Variables niossearchcatagory and searchcriteria are passed into the playbook via an AWX Survey.
I've searched possible options around using loops or splitting the output down but I'm really at a loss on the best way to process this.
If the output matches this then the playbook works as expected
{
"changed": false,
"ansible_facts": {
"host": [
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnVrLmFjLmJoYW0udGVzdC5zbmF0LWF3eHRlc3Q1:snat-awxtest5.test.com/Internal",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudWsuYWMuYmhhbS50ZXN0LnNuYXQtYXd4dGVzdDUuMTQ3LjE4OC4zMS40Lg:192.168.31.4/snat-awxtest5.test.com/Internal",
"configure_for_dhcp": false,
"host": "snat-awxtest5.test.com",
"ipv4addr": "192.168.31.4",
"mac": "10:20:30:40:50:60"
}
],
"name": "snat-awxtest5.test.com",
"view": "Internal"
},
]
},
"_ansible_no_log": false
}
And here's an example of the play returning multiple values
{
"changed": false,
"ansible_facts": {
"host": [
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnVrLmFjLmJoYW0udGVzdC5zbmF0LWF3eHRlc3Q1:snat-awxtest5.test.com/Internal",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudWsuYWMuYmhhbS50ZXN0LnNuYXQtYXd4dGVzdDUuMTQ3LjE4OC4zMS40Lg:192.168.31.4/snat-awxtest5.test.com/Internal",
"configure_for_dhcp": false,
"host": "snat-awxtest5.test.com",
"ipv4addr": "192.168.31.4",
"mac": "10:20:30:40:50:60"
}
],
"name": "snat-awxtest5.test.com",
"view": "Internal"
},
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnVrLmFjLmJoYW0udGVzdC5zbmF0LW15d2Vi:snat-myweb.test.com/Internal",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudWsuYWMuYmhhbS50ZXN0LnNuYXQtbXl3ZWIuMTQ3LjE4OC4zMS4yLg:192.168.31.2/snat-myweb.test.com/Internal",
"configure_for_dhcp": false,
"host": "snat-myweb.test.com",
"ipv4addr": "192.168.31.2",
"mac": "10:20:30:40:50:60"
}
],
"name": "snat-myweb.test.com",
"view": "Internal"
},
{
"_ref": "record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LnVrLmFjLmJoYW0udGVzdC5zbmF0LXdlYg:snat-web.test.com/Internal",
"ipv4addrs": [
{
"_ref": "record:host_ipv4addr/ZG5zLmhvc3RfYWRkcmVzcyQuX2RlZmF1bHQudWsuYWMuYmhhbS50ZXN0LnNuYXQtd2ViLjE0Ny4xODguMzEuMy4:192.168.31.3/snat-web.test.com/Internal",
"configure_for_dhcp": false,
"host": "snat-web.test.com",
"ipv4addr": "192.168.31.3",
"mac": "10:20:30:40:50:60"
}
],
"name": "snat-web.test.com",
"view": "Internal"
}
]
},
"_ansible_no_log": false
}
And this results in an error as the variables host.name, host.ipv4addrs etc.. don't exist which I presume is becasue there are multiples.
Any help on how to output each registration would be gratefully received.

Resources