Reputation: 84
I was trying to use Ansible to add IP addresses to an AWS security group.
I came up with a task syntax that looks like this:
- hosts: localhost
gather_facts: False
vars:
ip_addresses:
- 1.2.3.4/32
- 2.3.4.5/32
tasks:
- ec2_group:
name: security-group-name
description: Security group description
vpc_id: vpc-1234567
region: us-east-1
profile: profile-name
purge_rules: false
rules:
- proto: tcp
from_port: 123
to_port: 123
cidr_ip: "{{ item }}"
with_items: ip_addresses
This does not do exactly what I was looking for as it basically runs the ec2_group
task multiple times instead of just looping over the rules.
This also does not work if I set the purge_rules
to true
as then it will purge all existing rules on each iteration, effectively removing all but the last IP address on the list.
I'm wondering if there is something similar to with_items
that I can apply to the rules
attribute to provide it a list of IP addresses but calling ec2_task
only once?
Upvotes: 3
Views: 2278
Reputation: 20759
This does not do exactly what I was looking for as it basically runs the ec2_group task multiple times instead of just looping over the rules.
Ansible implements loops by invoking the task once for each item in the loop, so that's expected behavior.
I'm wondering if there is something similar to with_items that I can apply to the rules attribute to provide it a list of IP addresses but calling ec2_task only once?
Since the rules
property for ec2_group
actually takes a list of rules, you should be able to do the following:
- ec2_group:
name: security-group-name
description: Security group description
vpc_id: vpc-1234567
region: us-east-1
profile: profile-name
purge_rules: true
rules:
- proto: tcp
from_port: 123
to_port: 123
cidr_ip: 1.2.3.4/32
- proto: tcp
from_port: 123
to_port: 123
cidr_ip: 2.3.4.5/32
Or, if you want to use pre-defined vars as in your example:
vars:
my_rules:
- proto: tcp
from_port: 123
to_port: 123
cidr_ip: 1.2.3.4/32
- proto: tcp
from_port: 123
to_port: 123
cidr_ip: 2.3.4.5/32
tasks:
- ec2_group:
name: security-group-name
description: Security group description
vpc_id: vpc-1234567
region: us-east-1
profile: profile-name
purge_rules: true
rules: my_rules
Upvotes: 3
Reputation: 624
You can achieve what you want with a custom filter plugin.
Create a directory in the root of your playbook called filter_plugins
and create a file in there called make_rules.py
with the following contents:
def make_rules(hosts, ports, proto):
return [{"proto": proto,
"from_port": port,
"to_port": port,
"cidr_ip": host} for host in hosts for port in map(int, ports.split(","))]
class FilterModule(object):
def filters(self):
return {'make_rules': make_rules}
Then you can do this:
- hosts: localhost
gather_facts: False
vars:
ip_addresses:
- 1.2.3.4/32
- 2.3.4.5/32
tasks:
- ec2_group:
name: security-group-name
description: Security group description
vpc_id: vpc-1234567
region: us-east-1
profile: profile-name
purge_rules: true
rules: {{ ip_addresses | make_rules('123', 'tcp') }}
Taken from: https://gist.github.com/viesti/1febe79938c09cc29501
Upvotes: 4