Can't figure out why subnet is being updated - amazon-web-services

I am creating a VPC in AWS using Ansible. The following play is run
- name: create vpc with multi-az subnets
ec2_vpc:
region: "{{ region }}"
cidr_block: "{{ vpc_cidr_block }}"
resource_tags: '{"Name":"{{ prefix }}_vpc"}'
subnets:
- cidr: "{{ vpc_cidr_subnet_public_0 }}"
az: "{{ region }}{{ availability_zone_0 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_public_0", "Class":"web", "Partner":prefix }'
- cidr: "{{ vpc_cidr_subnet_private_0 }}"
az: "{{ region }}{{ availability_zone_0 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_private_0", "Class":"db", "Partner":prefix }'
- cidr: "{{ vpc_cidr_subnet_private_1 }}"
az: "{{ region }}{{ availability_zone_1 }}"
resource_tags: '{"Name":"{{ prefix }}_subnet_private_1", "Class":"db", "Partner":prefix }'
internet_gateway: yes
route_tables:
- subnets:
- "{{ vpc_cidr_subnet_public_0 }}"
routes:
- dest: 0.0.0.0/0
gw: igw
wait: yes
register: vpc
First time around this creates everything perfectly. Second time around, I expect it to not do anything as everything has been created, however, the public subnet is updated to a private one.
Why? What am I doing wrong?
[UPDATE]
Here are the variables:
---
region: eu-west-1
prefix: staging
vpc_environment: staging
vpc_cidr_block: 20.0.0.0/16
vpc_cidr_subnet_public_0: 20.0.0.0/24
vpc_cidr_subnet_private_0: 20.0.1.0/24
vpc_cidr_subnet_private_1: 20.0.2.0/24
availability_zone_0: b
availability_zone_1: c
Also just to clarify on what change is happening. All the resource tags of the one subnet (public) are being overwritten with the tags of another subnet (private).

This was caused by a bug in ansible-modules-core in master - ec2_vpc. I have logged a bug and created a PR to resolve the issue. See PR for details and the actual break. Hopefully it gets merged soon!
[UPDATE] Merged

Related

Developing AWS infrastructure provisioning ansible playbook using check / dry-run

I am trying to provision AWS infrastructure using ansible. My simplified playbook vpc.yml for illustration is as follow:
- hosts: localhost
connection: local
gather_facts: false
vars:
vpc_name: "Test VPC"
vpc_cidr_block: "10.0.0.0/16"
aws_region: "ap-east-1"
subnets:
test_net_1a:
az: "ap-east-1a"
cidr: "10.0.1.0/24"
test_net_1a:
az: "ap-east-1b"
cidr: "10.0.2.0/24"
tasks:
- name: Create VPC
ec2_vpc_net:
name: "{{ vpc_name }}"
cidr_block: "{{ vpc_cidr_block }}"
region: "{{ aws_region }}"
state: "present"
register: my_vpc
# Save VPC id in a new variable.
- name: Set VPC ID in variable
set_fact:
vpc_id: "{{ my_vpc.vpc.id }}"
- name: Create Subnets
ec2_vpc_subnet:
state: "present"
vpc_id: "{{ vpc_id }}"
cidr: "{{ item.value.cidr }}"
az: "{{ item.value.az }}"
region: "{{ aws_region }}"
resource_tags:
Name: "{{ item.key }}"
loop: "{{ subnets | dict2items }}"
Now I try to test my playbook with ansible-playbook vpc.yml --check. However the playbook would fail because with --check my_vpc would return:
"changed": true,
"failed": false
Apparently --check cannot be used to preview AWS provisioning changes using ansible, so how do I test my playbook during development without making any actual infrastructure changes?

Associate elastic IPs to ec2 instances

I have some(ie. 3) existing elastic IPs created in AWS earlier. I am trying to provision 3 AWS ec2 instances and associate those IPs to those newly created instances. I need to use those exisiting elastic IPs as they are white listed with my external partner for payment processes. I am not sure how to do that. I have the playbook below to create the ec2:
- name: Provision a set of instances
ec2:
key_name: "{{ key_name }}"
group_id: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ ami_id }}"
wait: true
exact_count: "{{ instances }}"
count_tag:
Name: Demo
instance_tags:
Name: "{{ application }}"
region: "{{ region }}"
register: ec2_instances
- name: Store EC2 instance IPs to provision
add_host:
hostname: "{{ item.public_ip }}"
groupname: ec2_instance_ips
with_items: "{{ ec2_instances.tagged_instances }}"
The second task is get the ready to configure the instances.
I just need to associate the EIP to those instances next.
Thanks,
Philip
Here you go, pulled from one of my roles.
- name: associate with our instance
ec2_eip:
reuse_existing_ip_allowed: true
instance_id: "{{ec2_instance}}"
public_ip: "{{eip}}"
state: present
region: "{{ec2_region|default('us-east-1')}}"
in_vpc: true

Ansible ec2 module ignores "volumes" parameter

I'm trying to get Ansible to bring up new ec2 boxes for me with a volume size larger than the default ~8g. I've added the volumes option with volume_size specified, but when I run with that, the volumes option seems to be ignored and I still get a new box with ~8g. The relevant part of my playbook is as follows:
- name: provision new boxes
hosts: localhost
gather_facts: False
tasks:
- name: Provision a set of instances
ec2:
group: "{{ aws_security_group }}"
instance_type: "{{ aws_instance_type }}"
image: "{{ aws_ami_id }}"
region: "{{ aws_region }}"
vpc_subnet_id: "{{ aws_vpc_subnet_id }}"
key_name: "{{ aws_key_name }}"
wait: true
count: "{{ num_machines }}"
instance_tags: "{{ tags }}"
volumes:
- device_name: /dev/sda1
volume_size: 15
register: ec2
What am I doing wrong?
So, I just updated ansible to 1.9.4 and now all of a sudden it works. So there's my answer. The code above is fine. Ansible was just broken.

Ansible EC2 Module to Retrieve information about the Instance

I see the Ansible EC2 Module's capability to provision / start / stop / terminate. However is there a way to lookup / query for the instance details like Private IP, Public IP etc.
I am looking at the use case to obtain the Public IP [not the Elastic IP] which keeps changing during stop/start and update the Route53 DNS records accordingly.
Any ideas ?
Did you set wait: True? It will wait for the instance to go to running state. I never had issues with the following. I was able to get the public IP after register. If you still have issues, use wait_for for IP to be available. Or post your script here.
- name: Start the instance if not running
ec2:
instance_ids: myinstanceid
region: us-east-1
state: running
wait: True
register: myinst
You can register the new boxes to an ec2 variable and wait for them to get private and public IPs, and then access them like so:
- name: provision new boxes
hosts: localhost
gather_facts: False
tasks:
- name: Provision a set of instances
ec2:
group: "{{ aws_security_group }}"
instance_type: "{{ aws_instance_type }}"
image: "{{ aws_ami_id }}"
region: "{{ aws_region }}"
vpc_subnet_id: "{{ aws_vpc_subnet_id }}"
key_name: "{{ aws_key_name }}"
wait: true
count: "{{ num_machines }}"
instance_tags: "{{ tags }}"
register: ec2
- name: Add all instance public IPs to public group
add_host: hostname={{ item.public_ip }} groups=new_public_ips
with_items: ec2.instances
- name: Add all instance private IPs to private group
add_host: hostname={{ item.private_ip }} groups=new_private_ips
with_items: ec2.instances

Deploy Subnets into different availability zones using Ansible in AWS

I am Working on putting subnets into different availability zones in AWS with the help of ansible. I want to put subnet1 into us-east-1a, then subnet2 into us-east-1b and so on. Currently I can only be able to put servers onto us-east-1a only. Here is the ansible scripts.
---
- name: Create AWS VPC and Subnets
hosts: localhost
connection: local
gather_facts: false
vars:
region: us-east-1
prefix: mahela_ansible
az1: us-east-1a
az2: us-east-1b
az3: us-east-1c
tasks:
- name: Create VPC
local_action:
module: ec2_vpc
region: "{{ region }}"
cidr_block: 10.123.0.0/16
resource_tags: '{"Name":"{{ prefix }}"}'
subnets:
- name: Cassandra Subnet
cidr: 10.123.0.0/24
az: "{{ az1 }}"
resource_tags: '{"Name":"{{ prefix }}_cassandra"}'
- name: MongoDB Subnet
cidr: 10.123.1.0/24
az: "{{ az2 }}"
resource_tags: '{"Name":"{{ prefix }}_Mongodb"}'
- name: Elastic Search
cidr: 10.123.2.0/24
az: "{{ az3 }}"
resource_tags: '{"Name":"{{ prefix }}_elasticsearch"}'
That example might help you.
roles/vpc/defaults/main.yml file look like this:
---
# Variables that can provide as extra vars
VPC_NAME: test
VPC_REGION: us-east-1 # N.Virginia
VPC_CIDR: "172.25.0.0/16"
VPC_CLASS_DEFAULT: "172.25"
# Variables for VPC
vpc_name: "{{ VPC_NAME }}"
vpc_region: "{{ VPC_REGION }}"
vpc_cidr_block: "{{ VPC_CIDR }}"
public_cidr_1: "{{ VPC_CLASS_DEFAULT }}.10.0/24"
public_az_1: "{{ vpc_region }}a"
public_cidr_2: "{{ VPC_CLASS_DEFAULT }}.20.0/24"
public_az_2: "{{ vpc_region }}b"
private_cidr_1: "{{ VPC_CLASS_DEFAULT }}.30.0/24"
private_az_1: "{{ vpc_region }}a"
private_cidr_2: "{{ VPC_CLASS_DEFAULT }}.40.0/24"
private_az_2: "{{ vpc_region }}b"
# Please don't change the variables below, until you know what you are doing
#
# Subnets Defination for VPC
vpc_subnets:
- cidr: "{{ public_cidr_1 }}" # Public Subnet-1
az: "{{ public_az_1 }}"
resource_tags: { "Name":"{{ vpc_name }}-{{ public_az_1 }}-public_subnet-1", "Type":"Public", "Alias":"Public_Subnet_1" }
- cidr: "{{ public_cidr_2 }}" # Public Subnet-2
az: "{{ public_az_2 }}"
resource_tags: { "Name":"{{ vpc_name }}-{{ public_az_2 }}-public-subnet-2", "Type":"Public", "Alias":"Public_Subnet_2" }
- cidr: "{{ private_cidr_1 }}" # Private Subnet-1
az: "{{ private_az_1 }}"
resource_tags: { "Name":"{{ vpc_name }}-{{ private_az_1 }}-private-subnet-1", "Type":"Private", "Alias":"Private_Subnet_1" }
- cidr: "{{ private_cidr_2 }}" # Private Subnet-2
az: "{{ private_az_2 }}"
resource_tags: { "Name":"{{ vpc_name }}-{{ private_az_2 }}-private-subnet-2", "Type":"Private", "Alias":"Private_Subnet_2" }
Then roles/vpc/tasks/main.yml file will be like this:
---
- name: Creating an AWS VPC inside mentioned Region
ec2_vpc:
region: "{{ vpc_region }}"
state: present
cidr_block: "{{ vpc_cidr_block }}"
resource_tags: { "Name":"{{ vpc_name }}-vpc", "Environment":"{{ ENVIRONMENT }}" }
subnets: "{{ vpc_subnets }}"
internet_gateway: yes
register: vpc
- name: Tag the Internet Gateway
ec2_tag:
resource: "{{ vpc.igw_id }}"
region: "{{ vpc_region }}"
state: present
tags:
Name: "{{ vpc_name }}-igw"
register: igw
- name: Set up Public Subnets Route Table
ec2_vpc_route_table:
vpc_id: "{{ vpc.vpc_id }}"
region: "{{ vpc_region }}"
state: present
tags:
Name: "Public-RT-for-{{ vpc_name }}-vpc"
subnets:
"{{ vpc.subnets | get_public_subnets_ids('Type','Public') }}"
routes:
- dest: 0.0.0.0/0
gateway_id: "{{ vpc.igw_id }}"
register: public_rt
For complete reference, take a look at this github repo.
Hope it help you or others.