Merge two ansible variable - filter

I have cluster command to create stonith device need to convert to ansible task:
- name: Create stonith
shell: pcs stonith create {{ fence_name }} fence_vmware_soap pcmk_host_map="node2.domain.com:TEST_PCS_NODE_2;node1.domain.com:TEST_PCS_NODE_1" ipaddr={{ vcenter_ip }} ssl_insecure=1 login={{ vcenter_username }} passwd={{ vcenter_password }}
I have created variables for below vm names:
node2_name: node2.domain.com
vm2_name: TEST_PCS_NODE_2
node1_name: node1.domain.com
vm1_name: TEST_PCS_NODE_1
But need help in create combine or merge or join filter to get below syntax:
node2.domain.com:TEST_PCS_NODE_2;node1.domain.com:TEST_PCS_NODE_1

There are no special filters required for this, you can simply have a string with variable interpolation:
{{ node2_name }}:{{ vm2_name }};{{ node1_name }}:{{ vm1_name }}
In task:
- name: Create stonith
shell: pcs stonith create {{ fence_name }} fence_vmware_soap pcmk_host_map="{{ node2_name }}:{{ vm2_name }};{{ node1_name }}:{{ vm1_name }}" ipaddr={{ vcenter_ip }} ssl_insecure=1 login={{ vcenter_username }} passwd={{ vcenter_password }}

Related

How can I use set_facts from a role with a when conditional in a delegate_to role after caching?

I have a set of tasks made up of individual roles that are run with 'when' conditionals to only execute on certain hosts, within them I pull specific values by using vars/set_facts that produce what I'm looking for - but the last role in the overall play is to take the results/facts from all and apply them in a Jinja HTML template.
Originally I had a mix of tasks within a role that would run against a single group that contained subgroups - these were dictated by 'when' conditionals - since that Ive split them out, made sure no var/fact was duplicated and even introduced a bridge role that takes set_facts as vars and then sets again as vars but with a delegate_to: localhost.
hosts: "{{ site_code }}"
ignore_errors: True
gather_facts: yes
tasks:
- name: DMVPN Primary Check
include_role:
name: dmvpn-primary
when: inventory_hostname in groups['dmvpn_primary']
- name: DMVPN Backup Check
include_role:
name: dmvpn-secondary
when: inventory_hostname in groups['dmvpn_secondary']
- name: Fact Cache
include_role:
name: fact-gather
- name: HTML Report
include_role:
name: html-report
run_once: true
When I limit to a host within a single group, the delegate_to picks that, and selects it's own facts ok, but combining multiple hosts with the {{ site_code }} var I end up with conflicts and eventually error 'AnsibleUndefinedVariable'
EDIT: Here is a snippet from the dmvpn role, fact gather role and html.j2 file showing the flow of a couple vars that eventually spit out as fatal: [site-vpn01 -> 127.0.0.1]: FAILED! => {
"changed": false,
"msg": "AnsibleUndefinedVariable: 'dmvpn1_host_name' is undefined"
roles\dmvpn-primary
- name: Primary Tunnel Up/Down
vars:
dmvpn1_tun_stat_0: "{{ dmvpn1_result.stdout[0] }}"
dmvpn1_tun_stat_1: "{{ dmvpn1_tun_stat_0.split() }}"
dmvpn1_tun_stat_2: "{{ dmvpn1_tun_stat_1[3] }}"
set_fact:
dmvpn1_tun_status: "{{ dmvpn1_tun_stat_2 }}"
dmvpn1_hostname: "{{ inventory_hostname }}"
dmvpn1_host_ip: "{{ ansible_host }}"
cacheable: yes
roles\fact-gather:
- name: Primary Inventory Facts
vars:
dmvpn1_host_name: "{{ dmvpn1_hostname }}"
dmvpn1_host_ipv4: "{{ dmvpn1_host_ip }}"
dmvpn1_google_dns1_icmp: "{{ dmvpn1_icmp1_loss }}"
set_fact:
dmvpn1_host_name: "{{ dmvpn1_host_name }}"
dmvpn1_host_ipv4: "{{ dmvpn1_host_ipv4 }}"
dmvpn1_google_dns1_ip: "{{ dmvpn1_google_dns1_ip }}"
dmvpn1_google_dns1_icmp: "{{ dmvpn1_google_dns1_icmp }}"
dmvpn1_google_dns1_status: "{{ 'SUCCESS' if ('100' in dmvpn1_google_dns1_icmp) else 'FAIL' }}"
cacheable: yes
delegate_to: 127.0.0.1
delegate_facts: True
when: inventory_hostname in groups['dmvpn_primary']
templates\html.j2:
<tr>
{% if inventory_hostname in groups['dmvpn_primary'] %}
<td>{{ location }}</td>
<td>{{ sitecode[2]|upper }}</td>
<td>{{ dmvpn1_host_name }}</td>
<td>{{ dmvpn1_host_ipv4 }}</td>
<td>ICMP</td>
<td>Google DNS1</td>
<td>{{ dmvpn1_google_dns1_icmp }}%</td>
<td>{{ dmvpn1_google_dns1_status }}</td>
<td>
{% if 'SUCCESS' in dmvpn1_google_dns1_status %}
-
{% else %}
{{ slack_url }}
{% endif %}
</td>
{% else %}
{% endif %}
</tr>

YAML object keys list

I've got this yaml object
users:
user1: some description
user2: another desc
user3: ...
How can I get this object's keys? Result should be [user1, user2, user3]
EDIT: I'm using yaml variables in ansible
Array:
{{ users.keys() }}
Task:
- name: with_dict
debug:
msg: "{{ item.key }}: {{ item.value }}"
with_dict: "{{ users }}"
Template:
{% for key, value in users.iteritems() %}
{{ key|e }}: {{ value|e }}
{% endfor %}
Ansible uses Jinja, so you can do:
[ {{ obj.keys() | join(", ") }} ]

how to avoid variable replacement with ansible

I am having a playbook like
- name: Set Config Knox - knox-config
uri:
url: "http://{{ ansible_fqdn }}:8080/api/v1/clusters/{{ cluster_name }}"
method: PUT
force_basic_auth: yes
user: "{{ ambari_admin_user }}"
password: "{{ ambari_admin_password }}"
body: "{{ lookup('template','templates/knox/knox-config.json') }}"
body_format: json
In general this works fine. But now I have in the knox-config.json itself content which container {{}}. Now it tries to replace it with variables, that doesn't exists.
Any idea how to avoid the variable replacement in the uri module of ansible?
you are using the lookup plugin with template, so i suppose this invokes the jinja2 templating engine and this is why the replacement its done.
To make jinja "ignore" the {{ and }}, you need to somehow replace them with {{ '{{' }} and {{ '}}' }} respectively.
hope it helps.

ansibl inventory : create temporary inventory with multiple groups with add_host or group_by

I have an assignment to provision {{ create new hosts }} according to a given
invonteroy file,
example
[SET1]
1.1.1.1 new_ip=1.1.1.1
[SET2]
1.1.1.2 new_ip=1.1.1.2
[SET3]
1.1.1.3 new_ip=1.1.1.3
Here is the problem. The inventory file contains set of ip addresses that do not exists yet.
What I want to do
- connect to vsphere host(5.5)
- create new machines based on amount of hosts in the inventory
- change the machines ip address to match the one in the given inventory
modules like
vmware_shell
vmware_guest
requires administrative permissions which I don't have.
The only way to hack around this issue is to try and create an in memory or temporary inventory during provisioning task.
Here is my role:
- vsphere_guest:
vcenter_hostname: {{ vcenter }}
validate_certs: no
username: "{{ vsphere.username }}"
password: "{{ vsphere.password }}"
guest: "{{ item }}"
from_template: yes
template_src: Centos_base
resource_pool: "/Resources"
esxi:
datacenter: Remote
hostname: {{ esx_host }}
with_items:
- "{{ play_hosts }}"
- name: wait for power on to finish
pause: seconds=5
- name: get facts from vm
vsphere_guest:
validate_certs: False
vcenter_hostname: {{ vcenter }}
username: "{{ vsphere.username }}"
password: "{{ vsphere.password }}"
guest: "{{ item }}"
vmware_guest_facts: yes
with_items:
- "{{ play_hosts }}"
register: vm_facts
until: vm_facts.ansible_facts.hw_eth0.ipaddresses[0] is defined
retries: 10
delay: 10
- name: grab new ipaddresses
set_fact: myIp="{{ inventory_hostname }}"
- name: Add production VMs to inventory
add_host: hostname={{item.ansible_facts.hw_eth0.ipaddresses[0] }} groups=temp
new_ip={{ myIp }}
with_items: "{{ vm_facts.results }}"
ignore_errors: yes
my question:
is there any way to create a temp inventory with multiple groups and mutilple variables that matches the given inventory!?
update
I hacked a way around it:
- name: Add production VMs to inventory
add_host: hostname={{item.ansible_facts.hw_eth0.ipaddresses[0] }} groups=temp
new_ip="{{ item.ansible_facts.hw_name }}"
with_items: "{{ vm_facts.results }}"
ignore_errors: yes
this works since the machine name is equal to {{ play_host }}

ansible 1.6 > using with_first_found in a with_items loop?

Is it possible to use with_first_found in a with_items loop such as:
- template:
dest=/foo/{{ item.name }}-{{ item.branch | default('master') }}
src={{ item }}
with_first_found:
- {{ item.name }}-{{ item.branch | default('master') }}
- {{ item.name }}.j2
- apache_site.j2
with_items: apache_sites
Can't seem to make it work using with_nested.
Combining loops is unsupported, but you can use them as lookups:
vars:
site_locations:
- {{ item.name }}-{{ item.branch | default('master') }}
- {{ item.name }}.j2
- apache_site.j2
tasks:
- template:
dest=/foo/{{ item.name }}-{{ item.branch | default('master') }}
src={{ lookup('first_found', site_locations }}
with_items: apache_sites
I had a similar need for tc Server (tomcat). This is what I did:
I put the site-specific configuration in a separate tasks file (configure-sites.yml):
- template:
src: "{{ item }}"
dest: /foo/{{ apache_site.name }}-{{ apache_site.branch | default('master') }}
with_first_found:
- "{{ apache_site.name }}-{{ apache_site.branch | default('master') }}"
- "{{ apache_site.name }}.j2"
- apache_site.j2
From a separate tasks file I included that tasks file, passing it each site:
- include: configure-sites.yml
with_items: "{{ apache_sites }}"
loop_control:
loop_var: apache_site
This makes use of loop_control which requires Ansible 2.1+: http://docs.ansible.com/ansible/playbooks_loops.html#loop-control
In case it helps, you can see exactly what I did here:
https://github.com/bmaupin/ansible-role-tcserver/blob/master/tasks/main.yml
https://github.com/bmaupin/ansible-role-tcserver/blob/master/tasks/configure-instances.yml

Resources