I am using Ansible to manage numerous CloudFormation stacks all based on the same playbook and CloudFormation template. I would like to treat the stacks as if they were nodes in an inventory, is this possible?
For example, I have one CloudFormation template and one Ansible playbook configured as follows:
- name: CloudFormation
hosts: localhost
connection: local
gather_facts: false
vars_files:
- vars/global.yml
tasks:
- name: Network Stack
cloudformation:
stack_name: "{{ name }}-{{ env }}-network"
I then have a stack specific var file that I pass in at runtime ansible-playbook -e @one-prod-network.yml play.yml
.
I need a way to run the playbook against all stacks in a group as if they were inventory items, for example:
[test]
one-test-network
two-test-network
[prod]
three-prod-network
four-prod-network
I thought roles might be the answer, but after investigating that I'm not so sure - obviously I don't want to duplicate the templates for each role. At present I am using a Makefile to run the command for each stack, but would prefer to do it in Ansible.
I would like to treat the stacks as if they were nodes in an inventory, is this possible?
From what I understand, yes you could do it by specifying that the ansible_connection
is local
on all hosts of a group cloud_formation
then nest all your hosts (or hosts groups) inside it.
Here would be an example inventory:
[cloud_formation:children]
test
prod
[cloud_formation:vars]
ansible_connection=local
[test]
one-test-network name=one
two-test-network name=two
[test:vars]
env=test
[prod]
three-prod-network name=three
four-prod-network name=four
[prod:vars]
env=prod
Running this playbook against it:
- hosts: cloud_formation
gather_facts: false
tasks:
- debug:
msg:
cloudformation:
stack_name: "{{ name }}-{{ env }}-network"
Would yield:
ok: [one-test-network] =>
msg:
cloudformation:
stack_name: one-test-network
ok: [two-test-network] =>
msg:
cloudformation:
stack_name: two-test-network
ok: [three-prod-network] =>
msg:
cloudformation:
stack_name: three-prod-network
ok: [four-prod-network] =>
msg:
cloudformation:
stack_name: four-prod-network
Then, if my guess of what you are trying to achieve is correct, you could even simplify further, with the inventory:
[cloud_formation:children]
test
prod
[cloud_formation:vars]
ansible_connection=local
[test]
one-test-network
two-test-network
[prod]
three-prod-network
four-prod-network
Running against the playbook:
- hosts: cloud_formation
gather_facts: false
tasks:
- debug:
msg:
cloudformation:
stack_name: "{{ inventory_hostname }}"
Would yield:
ok: [one-test-network] =>
msg:
cloudformation:
stack_name: one-test-network
ok: [two-test-network] =>
msg:
cloudformation:
stack_name: two-test-network
ok: [three-prod-network] =>
msg:
cloudformation:
stack_name: three-prod-network
ok: [four-prod-network] =>
msg:
cloudformation:
stack_name: four-prod-network
Or, without a parent group, the inventory:
[test]
one
two
[test:vars]
ansible_connection=local
[prod]
three
four
[prod:vars]
ansible_connection=local
Run against the playbook:
- hosts: test, prod
gather_facts: false
tasks:
- debug:
msg:
cloudformation:
stack_name: >-
{{ inventory_hostname -}}
-{{ group_names[0] -}}
-network
## /!\ Mind that this only works accuratly
## if the hosts are present in a single group
Would yield:
ok: [one] =>
msg:
cloudformation:
stack_name: one-test-network
ok: [two] =>
msg:
cloudformation:
stack_name: two-test-network
ok: [three] =>
msg:
cloudformation:
stack_name: three-prod-network
ok: [four] =>
msg:
cloudformation:
stack_name: four-prod-network