Create directories with Ansible using two separate lists - list

I want to create a series of directory trees dependent on two seperate lists.
Example:
---
# variable file ...
datacenters:
- london
- paris
types:
- databases
- baremetal
- vms
So I want my trees to be like so ...
dest: "/{{ datacenter.0 }}/{{ types.0 }}"
dest: "/{{ datacenter.0 }}/{{ types.1 }}"
dest: "/{{ datacenter.0 }}/{{ types.2 }}"
dest: "/{{ datacenter.1 }}/{{ types.0 }}"
dest: "/{{ datacenter.1 }}/{{ types.1 }}"
dest: "/{{ datacenter.1 }}/{{ types.2 }}"
dest: "/{{ datacenter.N }}/{{ types.N }} .... etc
I'm not exactly sure how to do this without using an include file ....

You can use Nested Loops
- name: Test with_nested
hosts: localhost
vars:
datacenters:
- london
- paris
types:
- databases
- baremetal
- vms
tasks:
- name: Do it
debug: msg="{{item[0]}}/{{item[1]}}"
with_nested:
- datacenters
- types

Related

Using variable for tag name in Ansible AWS modules

ec2_snapshot module allows me to create snapshots of volumes and tag at the same time. This is straight forward while using fix names for tags. But how can I set tag name itself from a variable?
Example task:
- name: AWS EBS Disks Snapshot For Volumes
ec2_snapshot:
aws_access_key: "{{ aws_access_key_id }}"
aws_secret_key: "{{ aws_secret_key_id }}"
security_token: "{{ aws_security_token }}"
volume_id: "{{ item.id }}"
region: "{{ aws_region }}"
snapshot_tags:
Name: "{{ timestamp.stdout }}"
"{{ tagname_variable }}": "{{ tagvalue_variable }}"
type: "{{ item.type }}"
description: "{{ timestamp.stdout }}_snapshot"
with_items:
- "{{ volumeinputs }}"
The tagname_variable is literally created as a tag name, not the value of the variable.
How I can make this work?
You will need to dynamically create that part of you dictionary, for example, with a combine, as YAML dictionaries key are usually not templated by Ansible.
This can be done in a vars sections of the task itself:
- name: AWS EBS Disks Snapshot For Volumes
ec2_snapshot:
aws_access_key: "{{ aws_access_key_id }}"
aws_secret_key: "{{ aws_secret_key_id }}"
security_token: "{{ aws_security_token }}"
volume_id: "{{ item.id }}"
region: "{{ aws_region }}"
snapshot_tags: "{{ _snapshot_tags }}"
description: "{{ timestamp.stdout }}_snapshot"
loop: "{{ volumeinputs }}"
vars:
_snapshot_tags_static:
Name: "{{ timestamp.stdout }}"
type: "{{ item.type }}"
_snapshot_tags: >-
{{
_snapshot_tags_static
| combine({tagname_variable: tagvalue_variable})
}}

Ansible: playbook to deploy VM (Linux)

I created this playbook to deploy new VM from template.
Now if I try to deploy a new Linux VM it works correctly but the hostname won't be customized
It keeps the same hostname from the template and I don't know why ??
Here is my playbook (this is just a test):
- name: Clone multiple VMs
hosts: localhost
gather_facts: false
vars_files:
multiple_vms.yml
tasks:
- name: Clone multiple Ubuntu VMS from Template
local_action:
module: vmware_guest
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
folder: "{{ folder }}"
template: "{{ vmtemplate }}"
name: "{{ item }}"
cluster: "{{ vcenter_cluster }}"
datacenter: "{{ vcenter_datacenter }}"
state: poweredon
networks:
- name: "{{ network }}"
type: "{{ network_dhcp_or_static }}"
hardware:
memory_mb: {{ number_memory }}
num_cpus: {{ number_cpu }}
customization:
hostname: "{{ servers }}"
domain : "mydomaine.test"
#customization_spec: "{{ customization_spec }}"
with_items: "{{ servers }}"
where vars multiple_vms.yml:
servers:
- ubuntu_test01
- ubuntu_test02
....
So I need my new VMS to take the hostname from the servers list (ubuntu_test01.mydomaine.test ..etc)
Thanks for the help
Using vmware_guest and customization option
First, try hostname: "{{ item }}"
Second, don't do the loop thing at all. Make a proper inventory, then:
- name: Clone multiple VMs
hosts: all
gather_facts: false
vars_files:
multiple_vms.yml
tasks:
- name: Clone multiple Ubuntu VMS from Template
vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
folder: "{{ folder }}"
template: "{{ vmtemplate }}"
name: "{{ ansible_hostname }}"
cluster: "{{ vcenter_cluster }}"
datacenter: "{{ vcenter_datacenter }}"
state: poweredon
networks:
- name: "{{ network }}"
type: "{{ network_dhcp_or_static }}"
hardware:
memory_mb: {{ number_memory }}
num_cpus: {{ number_cpu }}
customization:
hostname: "{{ ansible_hostname }}"
domain : "mydomaine.test"
delegate_to: localhost
N.B.: local_action is deprecated. Use delegate_to: localhost.

Using Ansible to enable logs AWS Application Load Balancer

name: Add HTTP listener rules
elb_application_lb:
state: present
name: "{{ albinfo.load_balancer_name }}"
subnets:
- "{{ albinfo.availability_zones[0].subnet_id }}"
- "{{ albinfo.availability_zones[1].subnet_id }}"
- "{{ albinfo.availability_zones[2].subnet_id }}"
security_groups:
- "{{ albinfo.security_groups[0] }}"
listeners:
- Protocol: HTTP
Port: 80
DefaultActions:
- Type: forward
TargetGroupName: default
Rules:
- Conditions:
- Field: host-header
Values: "{{ item.url }}"
Priority: "{{ item.priority }}"
Actions:
- TargetGroupName: "{{ item.name }}"
Type: forward
purge_listeners: no
with_items: "{{ regions }}"

How to evaluate a yaml key using jinja and then evaluate its value using jinja in .j2 file using ansible?

I have a kubernetes secrets manifest in the form of secret.j2 file which has a password key. This password key is supposed assigned a value from an ansible-vault encrypted string present in a dev.yml file. This dev.yml looks like below:-
dev_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I am passing "dev" as a runtime parameter "namespace=dev" to my playbook. The stringData of secret.j2 looks like this:-
stringData:
consoleadminpassword: "{{'{{'}} {{ namespace + '_console_password' }} {{'}}'}}"
consolenonadminpassword: "{{'{{'}} {{ namespace + '_console_password' }} {{'}}'}}"
dbpassword: "{{'{{'}} {{ namespace + '_console_password' }} {{'}}'}}"
When I am templating secret.j2 to secret.yml, the resulting output of stringData looks like this:-
stringData:
consoleadminpassword: "{{ dev_console_password }}"
consolenonadminpassword: "{{ dev_console_password }}"
dbpassword: "{{ dev_db_password }}"
Now I want it to further evaluate the "dev_db_password" to set "dbpassword" key to the decrypted value from dev.yml while ansible templates secret.j2 to secret.yml. Is there a way to achieve this in the same line by modifying dbpassword: "{{'{{'}} {{ namespace + '_db_password' }} {{'}}'}}" ?
Q: "evaluate the dev_db_password ... while ansible templates secret.j2. Is there a way to achieve this in the same line by modifying dbpassword: ... ?"
A: Yes. There is. Try lookup plugin vars. See ansible-doc -t lookup vars
dbpassword: "{{'{{'}} {{ lookup('vars', namespace + '_db_password') }} {{'}}'}}"
For example, the template
shell> cat secret.j2
stringData:
consoleadminpassword: "{{'{{'}} {{ lookup('vars', namespace + '_console_password') }} {{'}}'}}"
consolenonadminpassword: "{{'{{'}} {{ lookup('vars', namespace + '_console_password') }} {{'}}'}}"
dbpassword: "{{'{{'}} {{ lookup('vars', namespace + '_db_password') }} {{'}}'}}"
and the playbook
- hosts: localhost
tasks:
- template:
src: secret.j2
dest: secret.yml
vars:
namespace: dev
dev_console_password: passwd_console
dev_db_password: passwd_db
give
shell> cat secret.yml
stringData:
consoleadminpassword: "{{ passwd_console }}"
consolenonadminpassword: "{{ passwd_console }}"
dbpassword: "{{ passwd_db }}"
If you don't need the next evaluation of the variables (passwords) in the dictionary the template below
shell> cat secret.j2
stringData:
consoleadminpassword: {{ lookup('vars', namespace + '_console_password') }}
consolenonadminpassword: {{ lookup('vars', namespace + '_console_password') }}
dbpassword: {{ lookup('vars', namespace + '_db_password') }}
will give
shell> cat secret.yml
stringData:
consoleadminpassword: passwd_console
consolenonadminpassword: passwd_console
dbpassword: passwd_db
If you put the passwords into an encrypted file
shell> cat dev.yml
dev_console_password: passwd_console
dev_db_password: passwd_db
shell> ansible-vault encrypt dev.yml
Encryption successful
shell> cat dev.yml
$ANSIBLE_VAULT;1.1;AES256
30663636653963333864346339303034356463356234383035363561356365376130396465323736
...
the playbook will give the same results
- hosts: localhost
vars:
namespace: dev
tasks:
- include_vars: "{{ namespace }}.yml"
- template:
src: secret.j2
dest: secret.yml

Keep YAML list structure in Ansible templates

Say I have a variable file
---
app1:
environments:
- test
- demo
paths:
- /home/someuser/_env_/*.log
- /var/log/something/*.log
id: _env_
that's included in my playbook like this
---
- hosts: all
become: yes
vars:
apps:
- app1
vars_files:
- ~/vars/app1_vars.yml
tasks:
- name: Update config
template:
src: foo.j2
dest: /home/configurer/test.conf
owner: configurer
group: configurer
mode: '0644'
lstrip_blocks: yes
and the template itself is
{% for app in apps %}
{% for env in vars[app]['environments'] %}
- type: log
enabled: true
paths:
{% for path in vars[app]['paths'] %}
- {{ path | replace("_env_", env) }}
{% endfor %}
fields:
app_id: {{ vars[app]['id'] | replace("_env_", env) }}
{% endfor %}
{% endfor %}
That gives me as output
- type: log
enabled: true
paths:
- /home/someuser/test/*.log
- /var/log/something/*.log
fields:
app_id: test
- type: log
enabled: true
paths:
- /home/someuser/demo/*.log
- /var/log/something/*.log
fields:
app_id: demo
Is there a more compact and nicer way to iterate over the paths variable list and keep the YAML list structure with the -s?
After some experimenting I did the following as an alternative:
Changed the variable file:
---
app1:
environments:
- test
- demo
filebeat_properties:
paths:
- /home/someuser/_env_/*.log
- /var/log/something/*.log
fields:
app_id: _env_
Used to_nice_yaml to pretty-print the config:
{% for app in apps %}
{% for env in vars[app]['environments'] %}
- type: log
enabled: true
{{ vars[app]["filebeat_properties"] | to_nice_yaml(indent=2, width=9999) | indent(2) | replace("_env_", env) }}
{% endfor %}
{% endfor %}