---
|
- name: Step 001 Deploy Infrastructure
|
hosts: localhost
|
connection: local
|
gather_facts: false
|
become: false
|
vars_files:
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_vars.yml"
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_secret_vars.yml"
|
tags:
|
- step001
|
- deploy_infrastructure
|
tasks:
|
- name: AWS Generate CloudFormation Template
|
template:
|
src: "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/files/cloud_providers/{{cloud_provider}}_cloud_template.j2"
|
dest: "{{ANSIBLE_REPO_PATH}}/workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template-orig"
|
tags:
|
- aws_infrastructure_deployment
|
- gen_cf_template
|
|
# for SSH first access to ec2 instances we always use the key defined in the CloudFormation
|
# template by the name {{key_name}}
|
# This variable is used when generation ssh config.
|
- name: Get ssh pub key
|
set_fact:
|
ssh_key: "~/.ssh/{{key_name}}.pem"
|
|
######################### Minimize template (avoid size limitation as much as possible)
|
- name: minimize json
|
shell: "jq -c . < ../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template-orig > ../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
|
register: jq_minify
|
ignore_errors: true
|
tags:
|
- aws_infrastructure_deployment
|
- gen_cf_template
|
- minify_template
|
|
- name: use original if jq failed
|
command: "cp ../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template-orig ../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
|
when: jq_minify|failed
|
tags:
|
- aws_infrastructure_deployment
|
- gen_cf_template
|
- minify_template
|
|
######################### Validate CF Template
|
|
- name: validate cloudformation template
|
environment:
|
AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
|
AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
|
AWS_DEFAULT_REGION: "{{aws_region}}"
|
shell: "aws cloudformation validate-template --region {{ aws_region | default(region) | default('us-east-1')}} --template-body file://../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
|
changed_when: false
|
tags:
|
- aws_infrastructure_deployment
|
- validate_cf_template
|
|
######################### Launch CF Template
|
|
- name: Launch CloudFormation template
|
# environment:
|
# AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
|
# AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
|
# AWS_DEFAULT_REGION: "{{aws_region}}"
|
cloudformation:
|
aws_access_key: "{{ aws_access_key_id }}"
|
aws_secret_key: "{{ aws_secret_access_key }}"
|
stack_name: "{{ project_tag }}"
|
state: "present"
|
region: "{{ aws_region | default(region) | default('us-east-1')}}"
|
disable_rollback: true
|
template: "{{ANSIBLE_REPO_PATH}}/workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
|
tags:
|
Stack: "project {{ project_tag }}"
|
owner: "{{ email | default('unknown') }}"
|
tags:
|
- aws_infrastructure_deployment
|
- provision_cf_template
|
register: cloudformation_out
|
until:
|
- cloudformation_out|succeeded
|
- cloudformation_out.output in ["Stack CREATE complete", "Stack is already up-to-date."]
|
retries: "{{ cloudformation_retries | default(25) }}"
|
delay: 60
|
ignore_errors: yes
|
|
- name: debug cloudformation
|
debug:
|
var: cloudformation_out
|
tags: provision_cf_template
|
when: not cloudformation_out|succeeded
|
|
- name: report Cloudformation error
|
fail:
|
msg: "FAIL {{ project_tag }} Create Cloudformation"
|
when: not cloudformation_out|succeeded
|
tags:
|
- provision_cf_template
|
|
- name: debug cloudformation
|
debug:
|
var: cloudformation_out
|
verbosity: 2
|
tags: provision_cf_template
|
|
- name: Gather EC2 facts
|
ec2_remote_facts:
|
aws_access_key: "{{ aws_access_key_id }}"
|
aws_secret_key: "{{ aws_secret_access_key }}"
|
region: "{{ aws_region | default(region) | default('us-east-1')}}"
|
filters:
|
instance-state-name: running
|
"tag:Project": "{{project_tag}}"
|
register: ec2_facts
|
tags:
|
- create_inventory
|
- must
|
|
- name: debug ec2_facts
|
debug:
|
var: ec2_facts
|
verbosity: 2
|
|
- name: windows ostype workaround
|
set_fact:
|
project_tag_ostype: "{{project_tag}}_ostype"
|
tags:
|
- create_inventory
|
- must
|
|
- set_fact:
|
stack_tag: "{{env_type | replace('-', '_')}}_{{guid}}"
|
tags:
|
- create_inventory
|
- must
|
|
- add_host:
|
name: "{{item.tags.internaldns | default(item.private_dns_name)}}"
|
shortname: "{{item.tags.Name | default(item.private_dns_name)}}"
|
groups:
|
- "tag_Project_{{stack_tag}}"
|
- "tag_{{stack_tag}}_{{item['tags'][project_tag] | default('unknowns')}}"
|
- "tag_{{stack_tag}}_ostype_{{item['tags'][project_tag_ostype] | default('unknown')}}"
|
- "{{item.tags.ostype | default('unknowns')}}"
|
- "{{item['tags'][project_tag_ostype] | default('unknowns')}}"
|
- "{{ 'newnodes' if (item.tags.newnode|d()|bool) else 'all'}}"
|
ansible_ssh_user: ec2-user
|
remote_user: ec2-user
|
ansible_ssh_private_key_file: "{{item['key_name']}}"
|
key_name: "{{item['key_name']}}"
|
state: "{{item['state']}}"
|
internaldns: "{{item.tags.internaldns | default(item.private_dns_name)}}"
|
instance_id: "{{ item.id }}"
|
region: "{{item['region']}}"
|
public_dns_name: "{{item['public_dns_name']}}"
|
private_dns_name: "{{item['private_dns_name']}}"
|
private_ip_address: "{{item['private_ip_address']}}"
|
public_ip_address: "{{item['public_ip_address']}}"
|
placement: "{{item['placement']['zone']}}"
|
image_id: "{{item['image_id']}}"
|
ansible_ssh_extra_args: "-o StrictHostKeyChecking=no"
|
with_items: "{{ec2_facts['instances']}}"
|
loop_control:
|
label: "{{item.tags.internaldns | default(item.private_dns_name)}}"
|
tags:
|
- create_inventory
|
- must
|
|
# AnsibleGroup tag can have several comma-separated values. Ex: activedirectories,windows
|
- add_host:
|
name: "{{item.tags.internaldns | default(item.private_dns_name)}}"
|
groups: "{{item.tags.AnsibleGroup}}"
|
with_items: "{{ec2_facts['instances']}}"
|
loop_control:
|
label: "{{item.tags.internaldns | default(item.private_dns_name)}}"
|
tags:
|
- create_inventory
|
- must
|
|
- name: debug hostvars
|
debug:
|
var: hostvars
|
verbosity: 2
|
|
- name: debug groups
|
debug:
|
var: groups
|
verbosity: 2
|
|
- name: Configure local ssh config for bastion proxy use
|
include: "{{ANSIBLE_REPO_PATH}}/cloud_providers/{{cloud_provider}}_ssh_config_setup.yml"
|
when: groups['bastions']
|
|
- name: wait_for_connection for all non-windows machines and set hostname
|
hosts:
|
- all:!windows:!network
|
vars_files:
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_vars.yml"
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_secret_vars.yml"
|
gather_facts: false
|
any_errors_fatal: true
|
ignore_errors: false
|
become: true
|
tags:
|
- step001
|
- wait_ssh
|
- set_hostname
|
tasks:
|
- name: wait for linux host to be available
|
wait_for_connection:
|
timeout: 300
|
register: rwait
|
ignore_errors: true
|
|
- name: restart instance if wait_for_connection failed
|
become: false
|
environment:
|
AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
|
AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
|
AWS_DEFAULT_REGION: "{{aws_region}}"
|
command: "aws ec2 reboot-instances --instance-ids '{{instance_id}}'"
|
delegate_to: localhost
|
when: rwait|failed
|
|
- name: wait for linux host to be available (retry)
|
wait_for_connection:
|
when: rwait|failed
|
|
- ping:
|
register: rping
|
retries: 3
|
delay: 10
|
until: rping | succeeded
|
|
- name: Set hostname based on tag_internaldns
|
hostname:
|
name: "{{internaldns}}"
|
when: internaldns is defined
|
|
- stat:
|
path: /etc/cloud/cloud.cfg
|
register: cloud_cfg_file
|
|
- name: disable updating hostname in /etc/cloud/cloud.cfg
|
lineinfile:
|
dest: /etc/cloud/cloud.cfg
|
regexp: 'update_hostname$'
|
line: '# - update_hostname'
|
backup: yes
|
when: cloud_cfg_file.stat.exists
|
tags: disable_cloud_cfg_hostname
|
|
- name: Set facts for Windows hosts if any exist and wait_for_connection
|
gather_facts: false
|
hosts:
|
- windows
|
vars_files:
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_vars.yml"
|
- "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/env_secret_vars.yml"
|
tasks:
|
- name: set facts for remote access
|
set_fact:
|
ansible_become: false
|
ansible_connection: winrm
|
ansible_host: "{{ public_dns_name }}"
|
ansible_password: "{{ windows_password | default(hostvars['localhost'].generated_windows_password) }}"
|
ansible_port: 5986
|
ansible_user: Administrator
|
ansible_ssh_user: Administrator
|
ansible_winrm_server_cert_validation: ignore
|
|
- name: wait for windows host to be available
|
wait_for_connection:
|
timeout: 900
|
connect_timeout: 60
|
delay: 120
|
register: rwait
|
ignore_errors: true
|
|
- name: restart instance if wait_for_connection failed
|
become: false
|
environment:
|
AWS_ACCESS_KEY_ID: "{{aws_access_key_id}}"
|
AWS_SECRET_ACCESS_KEY: "{{aws_secret_access_key}}"
|
AWS_DEFAULT_REGION: "{{aws_region}}"
|
command: "aws ec2 reboot-instances --instance-ids '{{instance_id}}'"
|
delegate_to: localhost
|
when: rwait|failed
|
|
- name: wait for windows host to be available (retry)
|
wait_for_connection:
|
timeout: 900
|
connect_timeout: 60
|
delay: 120
|
when: rwait|failed
|