Iterating in a with_items loop ansible - amazon-web-services

Hi there i am atm trying to get the hang of ansible with aws and i am really likeing the flexibility of it so far.
Sadly now i am starting to hit a brick wall with my experiments. I am trying to tag volumes for specific instances that have the tag environment: test with the tages environment: test and backup: true . The playbook is working as intended if i specify every single Index of the array in the with_items loop. Here's my playbook so far:
---
- name: Tag the EBS Volumes
hosts: tag_environment_test
gather_facts: False
tags: tag
vars_files:
- /etc/ansible/vars/aws.yml
tasks:
- name: Gather instance instance_ids
local_action:
module: ec2_remote_facts
region: '{{ aws_region }}'
filters:
instance-state-name: running
"tag:environment": test
register: test_id
- name: Gather volume information for instance
local_action:
module: ec2_vol
region: '{{ aws_region }}'
instance: "{{ item.id }}"
state: list
with_items:
- "{{ test_id.instances }}"
register: ec2_volumes
- debug:
var: ec2_volumes
- name: Do some actual tagging
local_action:
module: ec2_tag
region: '{{ aws_region }}'
resource: "{{ item.id }}"
args:
tags:
environment: test
backup: true
with_items:
- "{{ ec2_volumes.results[0].volumes }}"
# - "{{ ec2_volumes.results[1].volumes }}"
My question now is it possible to iterate over the full array in ec2_volumes.results without having the need to specify every single value in the array. Like for example _ec2_volumes.results[X].volumes X=X+1_ so every time he goes through the loop he iterates +1 until the end of the array.
Every Input also on the rest of the playbook would be very appriciated (like i said still trying to get the hang of ansible. :)
Greeting
Drees

You can iterate over your list of results:
- name: Do some actual tagging
delegate_to: localhost
ec2_tag:
region: '{{ aws_region }}'
resource: "{{ item.volume.id }}"
tags:
environment: test
backup: true
with_items: "{{ ec2_volumes.results }}"
Every Input also on the rest of the playbook would be very appreciated
Consider using delegate_to: localhost instead of local_action. Consider this task:
- name: an example
command: do something
Using delegate_to, I only need to add a single line:
- name: an example
delegate_to: localhost
command: do something
Whereas using local_action I need to rewrite the task:
- name: an example
local_action:
module: command do something
And of course, delegate_to is more flexible: you can use it to delegate to hosts other than localhost.
Update
Without seeing your actual playbook it's hard to identify the source of the error. Here's a complete playbook that runs successfully (using synthesized data and wrapping your ec2_tag task in a debug task):
---
- hosts: localhost
gather_facts: false
vars:
aws_region: example
ec2_volumes:
results:
- volume:
id: 1
- volume:
id: 2
tasks:
- name: Do some actual tagging
debug:
msg:
ec2_tag:
region: '{{ aws_region }}'
resource: '{{ item.volume.id }}'
tags:
environment: test
backup: true
with_items: "{{ ec2_volumes.results }}"

Related

Using Ansible playbook to create instances in google cloud (gcp)

I'm using the following code
- name: create a instance
gcp_compute_instance:
name: test_object
machine_type: n1-standard-1
disks:
- auto_delete: 'false'
boot: 'true'
source: "{{ disk }}"
metadata:
startup-script-url:
cost-center:
labels:
environment: production
network_interfaces:
- network: "{{ network }}"
access_configs:
- name: External NAT
nat_ip: "{{ address }}"
type: ONE_TO_ONE_NAT
zone: us-central1-a
project: test-12y38912634812648
auth_kind: serviceaccount
service_account_file: "~/programming/gcloud/test-1283891264812-8h3981f3.json"
state: present
and I saved the file as create2.yml
Then I run Ansible-playbook create2.yml and I get the following error
ERROR! 'gcp_compute_instance' is not a valid attribute for a Play
The error appears to be in '/Users/xxx/programming/gcloud-test/create2.yml': line 1, column 3, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: create a instance
^ here
I followed the documentation. What am I doing wrong and how do I fix it?
You haven't created a playbook, you've just created a file with a task which won't run on it's own as you've discovered.
A playbook is a collection of tasks. You should start with the playbook documentation:
Playbook Documentation
For GCP, here's a working example to create a network, external IP, disk and VM.
- name: 'Deploy gcp vm'
hosts: localhost
connection: local
become: false
gather_facts: no
vars:
gcp_project: "671245944514"
gcp_cred_kind: "serviceaccount"
gcp_cred_file: "/tmp/test-project.json"
gcp_region: "us-central1"
gcp_zone: "us-central1-a"
# Roles & Tasks
tasks:
- name: create a disk
gcp_compute_disk:
name: disk-instance
size_gb: 50
source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-2004-lts
zone: "{{ gcp_zone }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
state: present
register: disk
- name: create a network
gcp_compute_network:
name: network-instance
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
state: present
register: network
- name: create a address
gcp_compute_address:
name: address-instance
region: "{{ gcp_region }}"
project: "{{ gcp_project }}"
auth_kind: "{{ gcp_cred_kind }}"
service_account_file: "{{ gcp_cred_file }}"
state: present
register: address
- name: create a instance
gcp_compute_instance:
name: vm-instance
project: "{{ gcp_project }}"
zone: "{{ gcp_zone }}"
machine_type: n1-standard-1
disks:
- auto_delete: 'true'
boot: 'true'
source: "{{ disk }}"
labels:
environment: testing
network_interfaces:
- network: "{{ network }}"
access_configs:
- name: External NAT
nat_ip: "{{ address }}"
type: ONE_TO_ONE_NAT
auth_kind: serviceaccount
service_account_file: "{{ gcp_cred_file }}"
state: present

Ansible 2.5.2, AWS Lambda, Want to create a template that works whether or not I have subnets or security groups assigned

I'm using Ansible 2.5.2 to try and automate deployment of Lambda into AWS.
How do I create template so that if the security groups section is blank, the code deploys?
Below results in the error EC2 Error Message: The subnet ID '' does not exist
---
- name: Deploy and Update Lambda
hosts: localhost
gather_facts: no
connection: local
tasks:
- name: Lambda Deploy
lambda:
profile: "{{ profile }}"
name: '{{ item.name }}'
state: present #absent or present
zip_file: '{{ item.zip_file }}'
runtime: 'python2.7'
role: '{{ item.role }}'
handler: 'hello_python.my_handler'
vpc_subnet_ids: '{{ item.vpc_subnet_ids }}'
vpc_security_group_ids: '{{ item.vpc_security_group_ids }}'
environment_variables: '{{ item.env_vars }}'
tags: "{{ item.tags }}"
with_items:
- name: AnsibleTest
role: 'arn:aws:iam::xxxxxxxxxx:role/Dev-LambdaRole'
zip_file: hello-code.zip
vpc_subnet_ids:
# - subnet-080802e6660be744c
# - subnet-00a8380a28ae0528c
# - subnet-0723ad3c29a435ee0
vpc_security_group_ids:
- sg-0fa788da8ecd36fe5
env_vars:
key1: "first"
key2: "second"
tags:
x: "133"
xx: "1"
project-name: "x"
xxx: "Ansible"
app-function: "automation"
Name: "AnsibleTest"

Ansible, ec2_remote_facts. Using vars in the roles

Please give advice. How to use vars from ec2_remote_facts in the roles?
---
- name: Sandbox
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Get facts by filter
ec2_remote_facts:
region: "{{ aws_default_region }}"
filters:
instance-state-name: running
"tag:Group": "{{ aws_default_instance_tag_group }}"
register: ec2_remote_facts
- name: Add running sandbox instances to in-memory inventory host group
add_host:
hostname: "{{ item.public_ip_address }}"
groups: running
with_items: "{{ ec2_remote_facts.instances }}"
- name: prov
hosts: running
gather_facts: true
user: ec2-user
become: true
roles:
- httpd
In this case I would like to use some of the vars from running instances for httpd role.
Thanks in advance!
I see at least 3 ways:
Define variable within add_host task:
- name: Add running sandbox instances to in-memory inventory host group
add_host:
hostname: "{{ item.public_ip_address }}"
groups: running
ec2_interfaces: "{{ item.interfaces }}"
with_items: "{{ ec2_remote_facts.instances }}"
Call ec2_facts as pre-task:
- name: prov
hosts: running
gather_facts: true
user: ec2-user
become: true
pre_tasks:
- ec2_facts:
roles:
- httpd
Use hostvars:
- name: prov
hosts: running
gather_facts: true
user: ec2-user
become: true
roles:
- role: httpd
first_instance_interfaces: "{{ hostvars['localhost'].ec2_remote_facts.instances[0].interfaces }}"

ansible ec2 ami module not working time out

I'm trying to implement a playbook dealing with Amazon EC2 .
I came to the part where I want to create a new image( I used a role for that ), here is what I did:
---
- debug: msg="{{ id_image }}"
- ec2_ami:
instance_id: "{{ id_image }}"
name: azzouz
wait: no
region: "{{ aws_region }}"
tags:
project: "{{ project }}"
register: image
I tried to specifiy the timeout to 900 and it's still not working. I changed it to wait: no and I'm still dealing with the same problem, here is last part of the error:
... return self._sslobj.read(len)\nssl.SSLError: The read operation timed out\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
could you please help me.
You don't have to set wait: no. Use this syntax and it will work.
- ec2_ami:
aws_access_key: xxxxxxxxxxxxxxxxxxxxxxx
aws_secret_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
instance_id: i-xxxxxx
wait: yes
name: newtest
tags:
Name: newtest
Service: TestService
register: instance

Create many AWS instances with Ansible, 'count' does not work

I have this playbook:
---
# Run it like this:
# ansible-playbook --extra-vars '{"VAR":"var-value", "VAR":"var-value"}' playbook-name.yml
- hosts: localhost
vars:
instance_tag : "{{ TAG }}"
instances_num: 2
tasks:
- name: Create new AWS instances
local_action:
module: ec2
region: us-east-1
key_name: integration
instance_type: m3.medium
image: ami-61dcvfa
group: mysecgroup
instance_tags:
Name: "{{ instance_tag }}"
with_sequence: count = {{ instances_num | int }}
When I run it it throws this:
TASK: [Create new AWS instances] **********************************************
fatal: [localhost] => unknown error parsing with_sequence arguments: u'count = 1'
FATAL: all hosts have already failed -- aborting
What am I doing wrong?
I have tried with 2 also, but throws the same error.
I have tried also with "{{instances_num}}" but nothing.
The ec2 module has a count parameter that you can use directly rather than trying to loop the task over a sequence.
You can use it like this:
---
# Run it like this:
# ansible-playbook --extra-vars '{"VAR":"var-value", "VAR":"var-value"}' playbook-name.yml
- hosts: localhost
vars:
instance_tag : "{{ TAG }}"
instances_num: 2
tasks:
- name: Create new AWS instances
local_action:
module: ec2
region: us-east-1
key_name: integration
instance_type: m3.medium
image: ami-61dcvfa
group: mysecgroup
instance_tags:
Name: "{{ instance_tag }}"
count: "{{ instances_num }}"