Guillaume Coré
2018-09-26 da4acef4f06ba4ab34c03de1983879932c502829
Consolidate Cloudformation template generation

This commits introduce a common Cloudformation template to use by default when
the environment (config) does not provide it.

- automate creation of AMI mappings: update find_ami.sh
- put all of them in a variable to be included in the jinja2 template
- set vars in defaults/
- do not use a delegated DNS zone, update root zone for now (simple)
- use the just-some-nodes config
- update hosts inventory file for just-some-nodes config
- add variables for the image to use
- Manage security groups
- simplify the 'instances' keys
3 files deleted
4 files added
11 files modified
1799 ■■■■■ changed files
ansible/cloud_providers/ec2_infrastructure_deployment.yml 9 ●●●●● patch | view | raw | blame | history
ansible/configs/just-some-nodes-example/env_vars.yml 21 ●●●● patch | view | raw | blame | history
ansible/configs/just-some-nodes-example/files/cloud_providers/ec2_cloud_template.j2 287 ●●●●● patch | view | raw | blame | history
ansible/configs/just-some-nodes-example/files/cloud_providers/ec2_cloud_template_json.j2 792 ●●●●● patch | view | raw | blame | history
ansible/configs/just-some-nodes-example/files/hosts_template.j2 33 ●●●● patch | view | raw | blame | history
ansible/configs/just-some-nodes-example/pre_software.yml 11 ●●●● patch | view | raw | blame | history
ansible/configs/ocp-ha-disconnected-lab/env_vars.yml 2 ●●● patch | view | raw | blame | history
ansible/requirements.txt 1 ●●●● patch | view | raw | blame | history
ansible/roles/infra-common-ssh-config-generate/defaults/main.yml 3 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-common-ssh-config-generate/tasks/main.yml 1 ●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-destroy/tasks/main.yml 3 ●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/README.adoc 42 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/defaults/main.yml 183 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/tasks/locate_template.yml 15 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/tasks/main.yml 18 ●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/templates/cloud_template.j2 273 ●●●●● patch | view | raw | blame | history
ansible/roles/infra-ec2-template-generate/templates/region_mapping.j2 73 ●●●●● patch | view | raw | blame | history
scripts/find_ami.sh 32 ●●●●● patch | view | raw | blame | history
ansible/cloud_providers/ec2_infrastructure_deployment.yml
@@ -12,15 +12,6 @@
    - step001.1
    - deploy_infrastructure
  tasks:
    # 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
    #   tags:
    #     - must
    #   set_fact:
    #     ssh_key: "~/.ssh/{{key_name}}.pem"
    - name: Run infra-ec2-template-generate Role
      import_role:
        name: "{{ ANSIBLE_REPO_PATH }}/roles/infra-ec2-template-generate"
ansible/configs/just-some-nodes-example/env_vars.yml
@@ -9,14 +9,17 @@
  ec2: "t2.medium"
  azure: Standard_A2_V2
bastion_instance_image: RHEL75
node_instance_type:
  ec2: "t2.medium"
  azure: Standard_A2_V2
node_instance_image: RHEL75
# How many do you want for each instance type
node_instance_count: 1
# Environment Instances
instances:
@@ -25,7 +28,10 @@
    unique: true
    public_dns: true
    dns_loadbalancer: false
    flavor: "{{bastion_instance_type}}"
    image: "{{ bastion_instance_image }}"
    flavor:
      ec2: "t2.medium"
      azure: Standard_A2_V2
    tags:
      - key: "AnsibleGroup"
        value: "bastions"
@@ -33,13 +39,20 @@
        value: "linux"
      - key: "instance_filter"
        value: "{{ env_type }}-{{ email }}"
    rootfs_size: 20
    volumes:
      - name: '/dev/sda1'
        size: 20
    security_groups:
      - "BastionSG"
  - name: "node"
    count: "{{node_instance_count}}"
    public_dns: true
    dns_loadbalancer: false
    flavor: "{{bastion_instance_type}}"
    image: "{{ node_instance_image }}"
    flavor:
      ec2: "t2.medium"
      azure: Standard_A2_V2
    tags:
      - key: "AnsibleGroup"
        value: "nodes"
ansible/configs/just-some-nodes-example/files/cloud_providers/ec2_cloud_template.j2
File was deleted
ansible/configs/just-some-nodes-example/files/cloud_providers/ec2_cloud_template_json.j2
File was deleted
ansible/configs/just-some-nodes-example/files/hosts_template.j2
@@ -1,5 +1,4 @@
[3tierapp:vars]
[all:vars]
###########################################################################
### Ansible Vars
###########################################################################
@@ -8,33 +7,9 @@
ansible_ssh_user={{remote_user}}
ansible_ssh_private_key_file="~/.ssh/{{guid}}key.pem"
ansible_ssh_common_args="-o StrictHostKeyChecking=no"
[3tierapp:children]
frontends
apps
appdbs
support
[frontends]
[nodes]
## These are the frontends
{% for host in groups['frontends'] %}
frontend{{loop.index}}.{{chomped_zone_internal_dns}} ansible_ssh_host=frontend{{loop.index}}.{{subdomain_base}}
{% endfor %}
[apps]
## These are the apps
{% for host in groups['apps']  %}
app{{loop.index}}.{{chomped_zone_internal_dns}} ansible_ssh_host=app{{loop.index}}.{{subdomain_base}}
{% endfor %}
[appdbs]
## These are the appdbs
{% for host in groups['appdbs'] %}
appdb{{loop.index}}.{{chomped_zone_internal_dns}} ansible_ssh_host=appdb{{loop.index}}.{{subdomain_base}}
{% endfor %}
## These are the support
[support]
{% for host in groups['support'] %}
support{{loop.index}}.{{chomped_zone_internal_dns}} ansible_ssh_host=support{{loop.index}}.{{subdomain_base}}
{% for host in groups['nodes']|d([]) %}
node{{loop.index}}.{{chomped_zone_internal_dns}} ansible_ssh_host=frontend{{loop.index}}.{{subdomain_base}}
{% endfor %}
ansible/configs/just-some-nodes-example/pre_software.yml
@@ -14,9 +14,14 @@
  tags:
    - common_tasks
  roles:
    - { role: "{{ ANSIBLE_REPO_PATH }}/roles/set-repositories", when: 'repo_method is defined' }
    - { role: "{{ ANSIBLE_REPO_PATH }}/roles/common", when: 'install_common' }
    - { role: "{{ ANSIBLE_REPO_PATH }}/roles/set_env_authorized_key", when: 'set_env_authorized_key' }
    - role: "{{ ANSIBLE_REPO_PATH }}/roles/set-repositories"
      when: repo_method is defined
    - role: "{{ ANSIBLE_REPO_PATH }}/roles/common"
      when: install_common | bool
    - role: "{{ ANSIBLE_REPO_PATH }}/roles/set_env_authorized_key"
      when: set_env_authorized_key | bool
- name: Configuring Bastion Hosts
  hosts:
ansible/configs/ocp-ha-disconnected-lab/env_vars.yml
@@ -272,7 +272,7 @@
      - name: MoshPublic
        description: "Public Mosh Access for bastions"
        from_port: 60000
        to_port: 60001
        to_port: 61000
        protocol: udp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
ansible/requirements.txt
@@ -2,3 +2,4 @@
boto
boto3
ansible
awscli
ansible/roles/infra-common-ssh-config-generate/defaults/main.yml
@@ -1,2 +1,5 @@
---
default_key_name: ~/.ssh/{{key_name}}.pem
remote_user_map:
  ec2: ec2-user
  azure: azure
ansible/roles/infra-common-ssh-config-generate/tasks/main.yml
@@ -14,6 +14,7 @@
    # define the communication method to all the hosts in the deployment
    ansible_ssh_config: "{{ ANSIBLE_REPO_PATH }}/workdir/{{ env_type }}_{{ guid }}_ssh_conf"
    ansible_known_host: "{{ ANSIBLE_REPO_PATH }}/workdir/{{ env_type }}_{{ guid }}_ssh_known_hosts"
    remote_user: "{{ remote_user_map[cloud_provider] }}"
- name: Delete dedicated known_host if it exists (new deployment)
  file:
ansible/roles/infra-ec2-template-destroy/tasks/main.yml
@@ -1,5 +1,4 @@
---
- name: Destroy cloudformation template
  cloudformation:
    aws_access_key: "{{ aws_access_key_id }}"
ansible/roles/infra-ec2-template-generate/README.adoc
New file
@@ -0,0 +1,42 @@
= CloudFormation template generation
When creating a config, you can either have the config under the `configs/{{env_type}}/files/cloud_providers/ec2_cloud_template.j2`, or use the default template.
If you choose to use the default template, you can still customize it to your needs.
Have a look at the link:../../configs/just-some-nodes-example/env_vars.yml[env_vars.yml] file from the link:../../configs/just-some-nodes-example/[just-some-nodes-example]  config.
=== Current status and features of the default template
Resources created by the default template:
* Instances
** [x] ElasticIP
** [x] Storage
* DNS
** Mandatory Variables:
*** `subdomain_base`: the AWS top-level Zone to update, for example `.openshift.opentlc.com`
** [ ] TODO: Public DNS Zone
*** [ ] TODO: Allow route53User to access only the delegated zone
** [x] Internal DNS Zone
** [x] Cloud DNS load balancer records
* [x] SecurityGroup
** [x] SecurityGroup rules
* [x] Subnet
* [ ] TODO: S3 Buckets
** [ ] TODO: Create a bucket and a user that has access to it
== Security Groups
The default template comes with 2 default security groups:
* DefaultSG (allow all connections from the bastion)
* BastionSG (allow SSH and mosh connection from the internet)
Have a look at link:defaults/main.yml[defaults/main.yml].
You can add more security group using the `security_groups` variables.
Then you can pick the security group**s** you want for any of the instances defined in the `instances` list.
ansible/roles/infra-ec2-template-generate/defaults/main.yml
New file
@@ -0,0 +1,183 @@
---
# TODO: split into different files. Possible since 2.6 thanks to this commit:
# https://github.com/ansible/ansible/commit/95ce00ff00e2907e89f4106747abaf9d4e4ccd7f
cloudformation_retries: 1
aws_comment: "Created by Ansible Agnostic Deployer"
#################################################################
# VPC
#################################################################
aws_vpc_cidr: 192.199.0.0/16
aws_vpc_name: "{{ subdomain_base }}"
#################################################################
# Subnet
#################################################################
aws_public_subnet_cidr: 192.199.0.0/24
#################################################################
# Security Groups
#################################################################
default_security_groups:
  - name: BastionSG
    rules:
      - name: MoshPublic
        description: "Public Mosh Access for bastions"
        from_port: 60000
        to_port: 61000
        protocol: udp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
      - name: SSHPublic
        description: "Public Access for bastions"
        from_port: 22
        to_port: 22
        protocol: tcp
        cidr: "0.0.0.0/0"
        rule_type: Ingress
  - name: DefaultSG
    rules:
      - name: FromBastionTCP
        description: "Allow everything from Bastion"
        from_port: 0
        to_port: 65535
        protocol: tcp
        from_group: BastionSG
        rule_type: Ingress
      - name: FromBastionUDP
        description: "Allow everything from Bastion"
        from_port: 0
        to_port: 65535
        protocol: tcp
        from_group: BastionSG
        rule_type: Ingress
# Environment specific security groups
security_groups: []
#################################################################
# DNS zones
#################################################################
# The top level DNS zone you want to update
aws_dns_zone_root: "{{ subdomain_base_suffix | regex_replace('^\\.', '') }}."
# Private DNS Zone dedicated to the environment
aws_dns_zone_private: "{{ guid }}.internal."
aws_dns_zone_private_chomped: "{{ guid }}.internal"
aws_dns_ttl_public: 900
aws_dns_ttl_private: 3600
#################################################################
# Volumes
#################################################################
# default size for /dev/sda1
aws_default_rootfs_size: 50
# default Volume type
aws_default_volume_type: gp2
#################################################################
# Images
#################################################################
aws_default_image: RHEL75
aws_ami_region_mapping:
  ap-south-1:
    RHEL75GOLD: ami-0c6ec6988a8df3acc # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-952879fa # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0aa4317636e016115 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-5c2f7e33 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-03087b28576b37511 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  eu-west-3:
    RHEL75GOLD: ami-0a0167e3e2a1d1d9b # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-69d06614 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-039346fed23fb53ad # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-66d0661b # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-080d3d8def91e4f44 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  eu-west-2:
    RHEL75GOLD: ami-01f010afd559615b9 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-55bca731 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0ac5fae255ddac6f6 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-b4b3a8d0 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0699aabf510a3f2f8 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  eu-west-1:
    RHEL75GOLD: ami-0c51cd02617947143 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-b7b6d3ce # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-092acf20fad7f7795 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-ccb7d2b5 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0370c806916d2a17f # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
  ap-northeast-2:
    RHEL75GOLD: ami-031161cd3182e012a # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-9fa201f1 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0d226f15e3e46903a # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-90a201fe # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-02ee840e33e7c2244 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  ap-northeast-1:
    RHEL75GOLD: ami-0bf9ecb88f5719e17 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-ccf695aa # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0b517025bb2f0ad4a # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-36f09350 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-08e310c576c077de1 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  sa-east-1:
    RHEL75GOLD: ami-93b693ff # RHEL-7.5_HVM_GA-JBEAP-7.1.2-20180629-x86_64-1-Access2-GP2
    RHEL74GOLD: ami-dc014db0 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-01c56172f9db84834 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-1a064a76 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-079f7c686ba77c199 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  ca-central-1:
    RHEL75GOLD: ami-e320ad87 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-2a00854e # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-fc20ad98 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-71018415 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-020be7519c99e8064 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  ap-southeast-1:
    RHEL75GOLD: ami-0f44e46fa59e902b6 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-8193eafd # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-09fc728e15fbfb535 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-8d90e9f1 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0906117a55c70d5e7 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  ap-southeast-2:
    RHEL75GOLD: ami-0066ef2f9c72fad96 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-dd9668bf # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0a61d60bde3940420 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-e1996783 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-09fb195e1d6625aab # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  eu-central-1:
    RHEL75GOLD: ami-07d3f0705bebac978 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-b3d841dc # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-05ba90b00a46d83fa # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-8a21bfe5 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-07b8613a03480d559 # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
  us-east-1:
    RHEL75GOLD: ami-0456c465f72bd0c95 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-c5a094bf # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0394fe9914b475c53 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-76a3970c # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-003027603b9c132b3 # Windows_Server-2012-R2_RTM-Japanese-64Bit-SQL_2016_SP1_Express-2018.09.15
  us-east-2:
    RHEL75GOLD: ami-04268981d7c33264d # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-9db09af8 # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0376bbf9be9eac670 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-cebe94ab # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-02fa46b8e1a36044b # Windows_Server-2012-R2_RTM-English-P3-2018.09.15
  us-west-1:
    RHEL75GOLD: ami-02574210e91c38419 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-6f030e0f # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-0bdc0ff10fb093057 # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-c8020fa8 # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0f9c4789993c313f7 # Windows_Server-2012-R2_RTM-English-Deep-Learning-2018.09.15
  us-west-2:
    RHEL75GOLD: ami-0e6bab6682ec471c0 # RHEL-7.5_HVM-20180813-x86_64-0-Access2-GP2
    RHEL74GOLD: ami-c405b8bc # RHEL-7.4_HVM-20180122-x86_64-1-Access2-GP2
    RHEL75: ami-096510cab1b6b2c6d # RHEL-7.5_HVM-20180813-x86_64-0-Hourly2-GP2
    RHEL74: ami-1607ba6e # RHEL-7.4_HVM-20180122-x86_64-1-Hourly2-GP2
    WIN2012R2: ami-0d786d5cc800b2456 # Windows_Server-2012-R2_RTM-English-64Bit-HyperV-2018.09.15
ansible/roles/infra-ec2-template-generate/tasks/locate_template.yml
New file
@@ -0,0 +1,15 @@
---
- name: Check if template exists for the environment
  stat:
    path: "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/files/cloud_providers/{{cloud_provider}}_cloud_template.j2"
  register: stat_local_template
- name: Use CloudFormation template from the environment
  set_fact:
    cloudformation_template_src: "{{ANSIBLE_REPO_PATH}}/configs/{{ env_type }}/files/cloud_providers/{{cloud_provider}}_cloud_template.j2"
  when: stat_local_template.stat.exists
- name: Use the default CloudFormation template
  set_fact:
    cloudformation_template_src: "templates/cloud_template.j2"
  when: not stat_local_template.stat.exists
ansible/roles/infra-ec2-template-generate/tasks/main.yml
@@ -1,7 +1,13 @@
---
- import_tasks: locate_template.yml
- set_fact:
    cloudformation_template: "{{ANSIBLE_REPO_PATH}}/workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
- 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"
    src: "{{ cloudformation_template_src }}"
    dest: "{{ cloudformation_template }}"
  tags:
    - aws_infrastructure_deployment
    - gen_cf_template
@@ -9,7 +15,7 @@
######################### Copy CF Template to S3 if too big
- name: Stat CloudFormation template
  stat:
    path: "{{ANSIBLE_REPO_PATH}}/workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
    path: "{{ cloudformation_template }}"
  register: stat_template
  tags:
    - aws_infrastructure_deployment
@@ -47,7 +53,7 @@
      aws_s3:
        bucket: "{{bucket_templates}}"
        object: "{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
        src: "{{ANSIBLE_REPO_PATH}}/workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template"
        src: "{{ cloudformation_template }}"
        mode: put
######################### Validate CF Template
@@ -60,10 +66,11 @@
  command: >-
    aws cloudformation validate-template
    --region {{ aws_region_final | d(aws_region) | default(region) | default('us-east-1')}}
    --template-body file://../workdir/{{ env_type }}.{{ guid }}.{{cloud_provider}}_cloud_template
    --template-body file://{{ cloudformation_template }}
  changed_when: false
  register: cloudformation_validation
  until: cloudformation_validation is succeeded
  retries: "{{ cloudformation_retries }}"
  delay: 20
  tags:
    - aws_infrastructure_deployment
@@ -82,6 +89,7 @@
  changed_when: false
  register: cloudformation_validation
  until: cloudformation_validation is succeeded
  retries: "{{ cloudformation_retries }}"
  delay: 20
  tags:
    - aws_infrastructure_deployment
ansible/roles/infra-ec2-template-generate/templates/cloud_template.j2
New file
@@ -0,0 +1,273 @@
#jinja2: lstrip_blocks: "True"
---
AWSTemplateFormatVersion: "2010-09-09"
Mappings:
  RegionMapping: {{ aws_ami_region_mapping | to_json }}
Resources:
  Vpc:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: "{{ aws_vpc_cidr }}"
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: "{{ aws_vpc_name }}"
        - Key: Hostlication
          Value:
            Ref: "AWS::StackId"
  VpcInternetGateway:
    Type: "AWS::EC2::InternetGateway"
  VpcRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId:
        Ref: Vpc
  VPCRouteInternetGateway:
    DependsOn: VpcGA
    Type: "AWS::EC2::Route"
    Properties:
      GatewayId:
        Ref: VpcInternetGateway
      DestinationCidrBlock: "0.0.0.0/0"
      RouteTableId:
        Ref: VpcRouteTable
  VpcGA:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId:
        Ref: VpcInternetGateway
      VpcId:
        Ref: Vpc
  PublicSubnet:
    Type: "AWS::EC2::Subnet"
    DependsOn:
      - Vpc
    Properties:
    {% if aws_availability_zone is defined %}
      AvailabilityZone: {{ aws_availability_zone }}
    {% endif %}
      CidrBlock: "{{ aws_public_subnet_cidr }}"
      Tags:
        - Key: Name
          Value: "{{project_tag}}"
        - Key: Hostlication
          Value:
            Ref: "AWS::StackId"
      MapPublicIpOnLaunch: true
      VpcId:
        Ref: Vpc
  PublicSubnetRTA:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId:
        Ref: VpcRouteTable
      SubnetId:
        Ref: PublicSubnet
{% for security_group in security_groups|list + default_security_groups|list %}
  {{security_group['name']}}:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: Host
      VpcId:
        Ref: Vpc
      Tags:
        - Key: Name
          Value: "{{security_group['name']}}"
{% endfor %}
{% for security_group in default_security_groups|list + security_groups|list %}
{% for rule in security_group.rules %}
  {{security_group['name']}}{{rule['name']}}:
    Type: "AWS::EC2::SecurityGroup{{rule['rule_type']}}"
    Properties:
     GroupId:
       Fn::GetAtt:
         - "{{security_group['name']}}"
         - GroupId
     IpProtocol: {{rule['protocol']}}
     FromPort: {{rule['from_port']}}
     ToPort: {{rule['to_port']}}
  {% if rule['cidr'] is defined %}
     CidrIp: "{{rule['cidr']}}"
  {% endif  %}
  {% if rule['from_group'] is defined %}
     SourceSecurityGroupId:
       Fn::GetAtt:
        - "{{rule['from_group']}}"
        - GroupId
  {% endif  %}
{% endfor %}
{% endfor %}
  DnsZonePrivate:
    Type: "AWS::Route53::HostedZone"
    Properties:
      Name: "{{ aws_dns_zone_private }}"
      VPCs:
        - VPCId:
            Ref: Vpc
          VPCRegion:
            Ref: "AWS::Region"
      HostedZoneConfig:
        Comment: "{{ aws_comment }}"
{% for instance in instances %}
{% if instance['dns_loadbalancer'] | d(false) | bool
  and not instance['unique'] | d(false) | bool %}
  {{instance['name']}}DnsLoadBalancer:
    Type: "AWS::Route53::RecordSetGroup"
    DependsOn:
    {% for c in range(1, (instance['count']|int)+1) %}
      - {{instance['name']}}{{c}}
      {% if instance['public_dns'] %}
      - {{instance['name']}}{{c}}EIP
      {% endif %}
    {% endfor %}
    Properties:
      HostedZoneName: {{ aws_dns_zone_root }}
      RecordSets:
      - Name: "{{instance['name']}}.{{ guid }}.{{ aws_dns_zone_root }}"
        Type: A
        TTL: {{ aws_dns_ttl_public }}
        ResourceRecords:
{% for c in range(1,(instance['count'] |int)+1) %}
          - "Fn::GetAtt":
            - {{instance['name']}}{{c}}
            - PublicIp
{% endfor %}
{% endif %}
{% for c in range(1,(instance['count'] |int)+1) %}
  {{instance['name']}}{{loop.index}}:
    Type: "AWS::EC2::Instance"
    Properties:
      ImageId:
        Fn::FindInMap:
        - RegionMapping
        - Ref: AWS::Region
        - {{ instance.image | default(aws_default_image) }}
      InstanceType: "{{instance['flavor'][cloud_provider]}}"
      KeyName: "{{instance.key_name | default(key_name)}}"
    {% if instance['UserData'] is defined %}
      {{instance['UserData']}}
    {% endif %}
    {% if instance['security_groups'] is defined %}
      SecurityGroupIds:
      {% for sg in instance.security_groups %}
        - Ref: {{ sg }}
      {% endfor %}
    {% else %}
      SecurityGroupIds:
        - Ref: DefaultSG
    {% endif %}
      SubnetId:
        Ref: PublicSubnet
      Tags:
    {% if instance['unique'] | d(false) | bool %}
        - Key: Name
          Value: {{instance['name']}}
        - Key: internaldns
          Value: {{instance['name']}}.{{aws_dns_zone_private_chomped}}
    {% else %}
        - Key: Name
          Value: {{instance['name']}}{{loop.index}}
        - Key: internaldns
          Value: {{instance['name']}}{{loop.index}}.{{aws_dns_zone_private_chomped}}
    {% endif %}
        - Key: "owner"
          Value: "{{ email | default('unknownuser') }}"
        - Key: "Project"
          Value: "{{project_tag}}"
        - Key: "{{project_tag}}"
          Value: "{{ instance['name'] }}"
    {% for tag in instance['tags'] %}
        - Key: {{tag['key']}}
          Value: {{tag['value']}}
    {% endfor %}
    {% if '/dev/sda1' not in instance.volumes|d([])|json_query('[].device_name') %}
      BlockDeviceMappings:
        - DeviceName: "/dev/sda1"
          Ebs:
            VolumeSize: {{ instance['rootfs_size'] | default(aws_default_rootfs_size) }}
    {% endif %}
    {% for vol in instance.volumes|default([]) if
      (vol.purpose|d('') == 'glusterfs' and install_glusterfs|bool)
      or (vol.purpose|d('') == 'nfs' and install_nfs|bool)
      or vol.purpose|d('') not in ['glusterfs', 'nfs'] %}
        - DeviceName: "{{ vol.name }}"
          Ebs:
          {% if cloud_provider in vol and 'type' in vol.ec2 %}
            VolumeType: "{{ vol[cloud_provider].type }}"
          {% else %}
            VolumeType: "{{ aws_default_volume_type }}"
          {% endif %}
            VolumeSize: "{{ vol.size }}"
    {% endfor %}
  {{instance['name']}}{{loop.index}}InternalDns:
    Type: "AWS::Route53::RecordSetGroup"
    Properties:
      HostedZoneId:
        Ref: DnsZonePrivate
      RecordSets:
    {% if instance['unique'] | d(false) | bool %}
        - Name: "{{instance['name']}}.{{aws_dns_zone_private}}"
    {% else %}
        - Name: "{{instance['name']}}{{loop.index}}.{{aws_dns_zone_private}}"
    {% endif %}
          Type: A
          TTL: {{ aws_dns_ttl_private }}
          ResourceRecords:
            - "Fn::GetAtt":
              - {{instance['name']}}{{loop.index}}
              - PrivateIp
{% if instance['public_dns'] %}
  {{instance['name']}}{{loop.index}}EIP:
    Type: "AWS::EC2::EIP"
    DependsOn:
    - VpcGA
    Properties:
      InstanceId:
        Ref: {{instance['name']}}{{loop.index}}
  {{instance['name']}}{{loop.index}}PublicDns:
    Type: "AWS::Route53::RecordSetGroup"
    DependsOn:
      - {{instance['name']}}{{loop.index}}EIP
    Properties:
      HostedZoneName: "{{ aws_dns_zone_root }}"
      RecordSets:
      {% if instance['unique'] | d(false) | bool %}
        - Name: "{{instance['name']}}.{{subdomain_base}}."
      {% else %}
        - Name: "{{instance['name']}}{{loop.index}}.{{subdomain_base}}."
      {% endif %}
          Type: A
          TTL: {{ aws_dns_ttl_public }}
          ResourceRecords:
          - "Fn::GetAtt":
            - {{instance['name']}}{{loop.index}}
            - PublicIp
{% endif %}
{% endfor %}
{% endfor %}
Outputs:
  Route53internalzoneOutput:
    Description: The ID of the internal route 53 zone
    Value:
      Ref: DnsZonePrivate
ansible/roles/infra-ec2-template-generate/templates/region_mapping.j2
File was deleted
scripts/find_ami.sh
@@ -1,9 +1,37 @@
#!/bin/bash
name=$1
# Generate yaml containing image information for each region
search_images() {
    owner=$1
    pattern=$2
    ispublic=$3
    aws ec2 describe-images \
        --owners ${owner} \
        --filters "Name=name,Values=${pattern}" "Name=is-public,Values=${ispublic}" \
        --query "reverse(sort_by(Images, &CreationDate))[0].{name: Name, id: ImageId}" \
        --output text \
        --region $region | awk '{print $1 " # " $2}'
}
#for region in us-east-1
for region in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text)
do
  echo "${region}: $(aws ec2 describe-images --owners amazon 309956199498 --filters Name=name,Values=${name} --query "reverse(sort_by(Images, &CreationDate))[0].ImageId" --output text --region $region)"
    echo "${region}:"
    echo -n "  RHEL75GOLD: "
    search_images 309956199498 'RHEL-7.5*Access*' false
    echo -n "  RHEL74GOLD: "
    search_images 309956199498 'RHEL-7.4*Access*' false
    echo -n "  RHEL75: "
    search_images 309956199498 'RHEL-7.5*' true
    echo -n "  RHEL74: "
    search_images 309956199498 'RHEL-7.4*' true
    echo -n "  WIN2012R2: "
    search_images 801119661308 'Windows_Server-2012-R2*' true
done
# For azure