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 }}"
Related
For example, I want to take this example play below.
# demo_setup.yml
- hosts: localhost
gather_facts: False
tasks:
- name: Set up NAT-protected route table
community.aws.ec2_vpc_route_table:
vpc_id: vpc-1245678
region: us-west-1
tags:
Name: Internal
subnets:
- 'SMTP Subnet'
- 'Database Subnet'
- 'Bastion Subnet'
routes:
- dest: 0.0.0.0/0
instance_id: "{{ nat.instance_id }}"
Then use the group_vars/all.yml to call my variables
# group_vars/all.yml
vpc: vpc-1245678
region: us-west-1
igw: igw-036dde5c85EXAMPLE
subnet_list:
- name: 'SMTP Subnet'
- name: 'Database Subnet'
- name: 'Database Subnet'
# demo_setup.yml
- hosts: localhost
gather_facts: False
tasks:
- name: Set up NAT-protected route table
community.aws.ec2_vpc_route_table:
vpc_id: {{ vpc }}
region: {{ region }}
tags:
Name: Internal
subnets:
- "{{ subnet_list }}"
routes:
- dest: 0.0.0.0/0
instance_id: "{{ igw }}"
The problem I am having is how can I input my subnet_list and place it in the community.aws.ec2_vpc_route_table module.
Instead of making subnet_list as a list of dictionaries, just make it a list of strings. This will make your life easier.
subnet_list:
- SMTP Subnet
- Database Subnet
- Database Subnet2
# demo_setup.yml
- hosts: localhost
gather_facts: False
tasks:
- name: Set up NAT-protected route table
community.aws.ec2_vpc_route_table:
vpc_id: "{{ vpc }}"
region: "{{ region }}"
tags:
Name: Internal
subnets: "{{ subnet_list }}"
routes:
- dest: 0.0.0.0/0
instance_id: "{{ igw }}"
I created a playbook aws.yml and want to run it over my local host
---
- hosts: webserver
- vars:
region: ap-south-1
instance_type: t2.micro
ami: ami-005956c5f0f757d37 # Amazon linux LTS
keypair: ansible # pem file name
- tasks:
- ec2:
key_name: "{{ ansible }}"
group: ansible # security group name
instance_type: "{{ t2.micro }}"
image: "{{ ami-005956c5f0f757d37 }}"
wait: true
wait_timeout: 500
region: "{{ ap-south-1 }}"
count: 1 # default
count_tag:
Name: Prod-Instance
instance_tags:
Name: Prod-Instance
vpc_subnet_id: subnet-00efd068
assign_public_ip: yes
Content of the host file /etc/ansible/hosts
[web]
localhost
When I try to run my aws.yml, it gives the below error
[root#localhost ~]# ansible-playbook aws.yml
PLAY [web] ********************************************************************************************************************************************************************************************************
ERROR! the field 'hosts' is required but was not set
[root#localhost ~]#
Your playbook and your hosts group name does not match.
In aws.yml
- hosts: webserver
And in /etc/ansible/hosts
[web]
You should either change your aws.yml playbook to read
- hosts: web
Or your hosts file /etc/ansible/hosts to read
[webserver]
Too many -s. Remove the ones in front of tasks and vars.
Also, use delegate_to: localhost on the ec2 task:
---
- hosts: webserver
vars:
region: ap-south-1
instance_type: t2.micro
ami: ami-005956c5f0f757d37 # Amazon linux LTS
keypair: ansible # pem file name
tasks:
- ec2:
key_name: "{{ ansible }}"
group: ansible # security group name
instance_type: "{{ t2.micro }}"
image: "{{ ami-005956c5f0f757d37 }}"
wait: true
wait_timeout: 500
region: "{{ ap-south-1 }}"
count: 1 # default
count_tag:
Name: Prod-Instance
instance_tags:
Name: Prod-Instance
vpc_subnet_id: subnet-00efd068
assign_public_ip: yes
delegate_to: localhost
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 }}"
What I want to achieve
I want to create an EC2 instance with LAMP stack installed using one Ansible playbook.
Problem
The instance creation works fine, and I can modify it in the EC2 Console, but the problem appears when trying to access the instance for example install apache or create keys.
This is the error:
fatal: [35.154.26.86]: UNREACHABLE! => {
"changed": false,
"msg": "[Errno None] Unable to connect to port 22 on or 35.154.26.86",
"unreachable": true
}
Error Screenshot
Code
This is my playbook:
---
- name: Power up an ec2 with LAMP stack installed
hosts: localhost
become: true
become_user: root
gather_facts: False
vars:
keypair: myKeyPair
security_group: launch-wizard-1
instance_type: t2.micro
image: ami-47205e28
region: x-x-x
tasks:
- name: Adding Python-pip
apt: name=python-pip state=latest
- name: Install Boto Library
pip: name=boto
- name: Launch instance (Amazon Linux)
ec2:
key_name: "{{ keypair }}"
group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: true
region: "{{ region }}"
aws_access_key: "xxxxxxxxxxxxxxxxxxx"
aws_secret_key: "Xxxxxxxxxxxxxxxxxxx"
register: ec2
- name: Print all ec2 variables
debug: var=ec2
- name: Add all instance public IPs to host group
add_host: hostname={{ item.public_ip }} groups=ec2hosts
with_items: "{{ ec2.instances }}"
- hosts: ec2hosts
remote_user: ec2-user
become: true
gather_facts: false
tasks:
#I need help here, don't know what to do.
- name: Create an EC2 key
ec2_key:
name: "privateKey"
region: "x-x-x"
register: ec2_key
- name: Save private key
copy: content="{{ ec2_key.private_key }}" dest="./privateKey.pem" mode=0600
when: ec2_key.changed
# The Rest is installing LAMP
Information:
1- My hosts file is default.
2- I used this command to run the playbook:
sudo ansible-playbook lamp.yml -vvv -c paramiko
3- launch-wizard-1 has SSH.
4- myKeyPair is a public key imported from my device to the console(don't know if this is ok)
5- I am a big newbie
Ansible requires Python installed on VM to work.
Here is your required code:
- name: upload an ssh keypair to ec2
hosts: localhost
connection: local
gather_facts: False
vars:
keypair_name: Key_name
key_material: "{{ lookup('file', 'keyfile') }}"
region: "{{ region }}"
tasks:
- name: ssh keypair for ec2
ec2_key:
aws_access_key: "xxxxxxxxxxxxxxxxxxx"
aws_secret_key: "Xxxxxxxxxxxxxxxxxxx"
region: "{{ region }}"
name: "{{ keypair_name }}"
key_material: "{{ key_material }}"
state: present
- name: Power up an ec2 with LAMP stack installed
hosts: localhost
become: true
become_user: root
gather_facts: False
vars:
keypair: myKeyPair
security_group: launch-wizard-1
instance_type: t2.micro
image: ami-47205e28
region: x-x-x
my_user_data: | # install Python: Ansible needs Python pre-installed on the instance to work!
#!/bin/bash
sudo apt-get install python -y
tasks:
- name: Adding Python-pip
apt: name=python-pip state=latest
- name: Install Boto Library
pip: name=boto
- name: Launch instance (Amazon Linux)
ec2:
key_name: "{{ keypair }}"
group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ image }}"
wait: true
wait_timeout: 300
user_data: "{{my_user_data}}"
region: "{{ region }}"
aws_access_key: "xxxxxxxxxxxxxxxxxxx"
aws_secret_key: "Xxxxxxxxxxxxxxxxxxx"
register: ec2
- name: Add all instance public IPs to host group
add_host: hostname={{ item.public_ip }} groups=ec2hosts
with_items: "{{ ec2.instances }}"
This playbook appears to be SSHing onto my local machine rather than the remote one. This condition is guessed based on the output I've included at the bottom.
I've adapted the example from here: http://docs.ansible.com/ansible/guide_aws.html#provisioning
The playbook is split into two plays:
creation of the EC2 instance and
configuration of the EC2 instance
Note: To run this you'll need to create a key-pair with the same name as the project (you can get more information here: https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#KeyPairs:sort=keyName)
The playbook is listed below:
# Create instance
- hosts: 127.0.0.1
connection: local
gather_facts: false
vars:
project_name: my-test
tasks:
- name: Get the current username
local_action: command whoami
register: username_on_the_host
- name: Capture current instances
ec2_remote_facts:
region: "us-west-2"
register: ec2_instances
- name: Create instance
ec2:
region: "us-west-2"
zone: "us-west-2c"
keypair: "{{ project_name }}"
group:
- "SSH only"
instance_type: "t2.nano"
image: "ami-59799439" # debian:jessie amd64 hvm on us-west 2
count_tag: "{{ project_name }}-{{ username_on_the_host.stdout }}-test"
exact_count: 1
wait: yes
instance_tags:
Name: "{{ project_name }}-{{ username_on_the_host.stdout }}-test"
"{{ project_name }}-{{ username_on_the_host.stdout }}-test": simple_ec2
Creator: "{{ username_on_the_host.stdout }}"
register: ec2_info
- name: Wait for instances to listen on port 22
wait_for:
state: started
host: "{{ item.public_dns_name }}"
port: 22
with_items: "{{ ec2_info.instances }}"
when: ec2_info|changed
- name: Add new instance to launched group
add_host:
hostname: "{{ item.public_dns_name }}"
groupname: launched
with_items: "{{ ec2_info.instances }}"
when: ec2_info|changed
- name: Get ec2_info information
debug:
msg: "{{ ec2_info }}"
# Configure and install all we need
- hosts: launched
remote_user: admin
gather_facts: true
tasks:
- name: Display all variables/facts known for a host
debug:
var: hostvars[inventory_hostname]
- name: List hosts
debug: msg="groups={{groups}}"
- name: Get current user
command: whoami
- name: Prepare system
become: yes
become_method: sudo
apt: "name={{item}} state=latest"
with_items:
- software-properties-common
- python-software-properties
- devscripts
- build-essential
- libffi-dev
- libssl-dev
- vim
The output I have is:
TASK [Get current user] ********************************************************
changed: [ec2-35-167-142-43.us-west-2.compute.amazonaws.com] => {"changed": true, "cmd": ["whoami"], "delta": "0:00:00.006532", "end": "2017-01-09 14:53:55.806000", "rc": 0, "start": "2017-01-09 14:53:55.799468", "stderr": "", "stdout": "brianbruggeman", "stdout_lines": ["brianbruggeman"], "warnings": []}
TASK [Prepare system] **********************************************************
failed: [ec2-35-167-142-43.us-west-2.compute.amazonaws.com] (item=['software-properties-common', 'python-software-properties', 'devscripts', 'build-essential', 'libffi-dev', 'libssl-dev', 'vim']) => {"failed": true, "item": ["software-properties-common", "python-software-properties", "devscripts", "build-essential", "libffi-dev", "libssl-dev", "vim"], "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE"}
This should work.
- name: Create Ec2 Instances
hosts: localhost
connection: local
gather_facts: False
vars:
project_name: device-graph
ami_id: ami-59799439 # debian jessie 64-bit hvm
region: us-west-2
zone: "us-west-2c"
instance_size: "t2.nano"
tasks:
- name: Provision a set of instances
ec2:
key_name: my_key
group: ["SSH only"]
instance_type: "{{ instance_size }}"
image: "{{ ami_id }}"
wait: true
exact_count: 1
count_tag:
Name: "{{ project_name }}-{{ username.stdout }}-test"
Creator: "{{ username.stdout }}"
Project: "{{ project_name }}"
instance_tags:
Name: "{{ project_name }}-{{ username.stdout }}-test"
Creator: "{{ username.stdout }}"
Project: "{{ project_name }}"
register: ec2
- name: Add all instance public IPs to host group
add_host:
hostname: "{{ item.public_ip }}"
groups: launched_ec2_hosts
with_items: "{{ ec2.tagged_instances }}"
- name: configuration play
hosts: launched_ec2_hosts
user: admin
gather_facts: true
vars:
ansible_ssh_private_key_file: "~/.ssh/project-name.pem"
tasks:
- name: get the username running the deploy
shell: whoami
register: username