Skip to content

Commit a131dc0

Browse files
authored
Launch AWS Edges in multiple AWS regions (#45)
1 parent 2ca95af commit a131dc0

File tree

8 files changed

+134
-33
lines changed

8 files changed

+134
-33
lines changed

roles/aws_edges/tasks/aws_cedge_ec2_instance.yml

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,46 @@
1010
# 2 aws_eip
1111
# 1 ec2 instance
1212

13+
- name: Discover required information about network infrastructure if edge is in different zone
14+
when: "'region' not in all_aws_security_group_config or 'region' not in all_aws_sunbnets_config"
15+
block:
16+
- name: Gather network resources information
17+
ansible.builtin.include_role:
18+
name: aws_network_infrastructure
19+
tasks_from: aws_gather_network_resources.yml
20+
vars:
21+
aws_region: "{{ region }}"
22+
23+
- name: Set reusable infrastructure facts from discovered variables
24+
ansible.builtin.set_fact:
25+
all_aws_security_group_config: "{{ all_aws_security_group_config | combine({region: aws_discovered_security_group}) }}"
26+
all_aws_subnets_config: "{{ all_aws_subnets_config | combine({region: aws_discovered_subnets}) }}"
27+
28+
- name: Use information about network infrastructure from default region
29+
ansible.builtin.set_fact:
30+
regional_security_group_config: "{{ all_aws_security_group_config[region] }}"
31+
regional_subnets_config: "{{ all_aws_subnets_config[region] }}"
1332

1433
# NICs
1534
- name: Filter required subnets for instance creation. Set aws_mgmt_subnet and aws_transport_subnet facts
1635
ansible.builtin.set_fact:
17-
aws_mgmt_subnet: "{{ aws_subnets_config | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
18-
aws_transport_subnet: "{{ aws_subnets_config | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
36+
aws_mgmt_subnet: "{{ regional_subnets_config | selectattr('tags.type', 'equalto', 'mgmt') | list | first }}"
37+
aws_transport_subnet: "{{ regional_subnets_config | selectattr('tags.type', 'equalto', 'transport') | list | first }}"
1938

2039
- name: Create network interfaces for cedge
2140
amazon.aws.ec2_eni:
2241
subnet_id: "{{ subnet_item.id }}"
2342
description: Network interface for SD-WAN Controller
24-
security_groups: "{{ aws_security_group_config.group_id }}"
25-
region: "{{ aws_region }}"
43+
security_groups: "{{ regional_security_group_config.group_id }}"
44+
region: "{{ region }}"
2645
tags:
2746
Name: "nic-{{ subnet_item.tags.Name }}"
2847
Creator: "{{ aws_tag_creator }}"
2948
Machine: "{{ hostname }}"
3049
VPN: "{{ subnet_item.tags.VPN }}"
3150
type: "{{ subnet_item.tags.type }}"
3251
register: network_interfaces_cedge
33-
loop: "{{ aws_subnets_config }}"
52+
loop: "{{ regional_subnets_config }}"
3453
loop_control:
3554
loop_var: subnet_item
3655
label: "nic-{{ subnet_item.tags.Name }}"
@@ -50,7 +69,7 @@
5069
- name: Associate EIP with mgmt network interface
5170
amazon.aws.ec2_eip:
5271
device_id: "{{ interface_item.id }}"
53-
region: "{{ aws_region }}"
72+
region: "{{ region }}"
5473
in_vpc: true
5574
state: present
5675
tags:
@@ -106,10 +125,10 @@
106125
count: 1
107126
instance_type: "{{ aws_cedge_instance_type }}"
108127
image:
109-
id: "{{ aws_cedge_ami_id }}"
128+
id: "{{ ami }}"
110129
state: present
111130
vpc_subnet_id: "{{ aws_mgmt_subnet.id }}"
112-
region: "{{ aws_region }}"
131+
region: "{{ region }}"
113132
key_name: "{{ aws_key_name | default('') | bool | ternary(aws_key_name, omit) }}"
114133
network:
115134
assign_public_ip: false

roles/aws_edges/tasks/main.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@
3030
aws_security_group_config: "{{ aws_discovered_security_group }}"
3131
aws_subnets_config: "{{ aws_discovered_subnets }}"
3232

33+
- name: Cache network infrastructure information for default AWS region
34+
ansible.builtin.set_fact:
35+
all_aws_security_group_config:
36+
"{{ aws_region }}": "{{ aws_discovered_security_group }}"
37+
all_aws_subnets_config:
38+
"{{ aws_region }}": "{{ aws_discovered_subnets }}"
39+
default_aws_region: "{{ aws_region }}"
40+
3341
- name: Assert all required variables for AWS edges deployment
3442
ansible.builtin.include_role:
3543
name: common
@@ -63,6 +71,9 @@
6371
vbond: "{{ instance_item.vbond }}"
6472
system_ip: "{{ instance_item.system_ip }}"
6573
site_id: "{{ instance_item.site_id }}"
74+
wan_edges_item: "{{ wan_edges | default([]) | json_query('[?uuid==`'~instance_item.uuid~'`] | [0]') }}"
75+
region: "{{ wan_edges_item.aws_region | default(default_aws_region) }}"
76+
ami: "{{ wan_edges_item.aws_cedge_ami_id | default(aws_cedge_ami_id) }}"
6677
loop: "{{ edge_instances }}"
6778
loop_control:
6879
loop_var: instance_item

roles/aws_network_infrastructure/defaults/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ organization_name: null # has to be set by user
1717
aws_region: null
1818
aws_resources_prefix: "{{ organization_name }}"
1919
aws_tag_creator: "{{ organization_name }}"
20+
all_aws_regions: "{{ [aws_region] + wan_edges | default([]) | json_query('[?aws_region].aws_region') | unique }}"
2021

2122
# VPC
2223
aws_vpc_name: "{{ aws_resources_prefix }}-vpc"

roles/aws_network_infrastructure/tasks/main.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,11 @@
2626
mode: "0755"
2727

2828
- name: Create network infrastructure on AWS
29-
ansible.builtin.include_tasks: aws_create_network_infrastructure.yml
29+
ansible.builtin.include_tasks:
30+
file: aws_create_network_infrastructure.yml
31+
apply:
32+
vars:
33+
aws_region: "{{ item }}"
34+
loop: "{{ all_aws_regions }}"
35+
loop_control:
36+
label: "{{ item }}"

roles/aws_teardown/defaults/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ teardown_specific_instances: false
1717
aws_region: null
1818
aws_resources_prefix: "{{ organization_name }}"
1919
aws_tag_creator: "{{ organization_name }}"
20+
all_aws_regions: "{{ [aws_region] + wan_edges | default([]) | json_query('[?aws_region].aws_region') | unique }}"
2021

2122
aws_vpc_name: "{{ aws_resources_prefix }}-vpc"
2223
aws_security_group_name: "{{ aws_resources_prefix }}-sg"

roles/aws_teardown/tasks/main.yml

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,31 @@
2020
# VPC info
2121
- name: Retrieve VPC details # noqa: syntax-check[unknown-module]
2222
amazon.aws.ec2_vpc_net_info: # noqa: syntax-check[unknown-module]
23-
region: "{{ aws_region }}"
23+
region: "{{ _region }}"
2424
filters:
2525
"tag:Name": "{{ aws_vpc_name }}"
2626
"tag:Creator": "{{ aws_tag_creator }}"
2727
register: vpc_info
28+
loop: "{{ all_aws_regions }}"
29+
loop_control:
30+
label: "{{ _region }}"
31+
loop_var: _region
2832

2933
- name: Check if VPC info is not empty
3034
ansible.builtin.assert:
3135
that:
32-
- vpc_info.vpcs | length > 0
36+
- vpc_info.results | map(attribute='vpcs') | flatten | length > 0
3337
fail_msg: "No VPC found. Please check your VPC configuration. Might be that you already removed your configuration."
3438

3539
- name: Set fact from register variable
3640
ansible.builtin.set_fact:
37-
aws_vpc_id: "{{ vpc_info.vpcs[0].id }}"
38-
39-
40-
# SUBNET info
41-
- name: Gather information about all subnets in VPC
42-
amazon.aws.ec2_vpc_subnet_info:
43-
filters:
44-
vpc-id: "{{ aws_vpc_id }}"
45-
region: "{{ aws_region }}"
46-
register: vpc_subnets
47-
48-
- name: Set fact from register variable
49-
ansible.builtin.set_fact:
50-
aws_vpc_subnets: "{{ vpc_subnets }}"
51-
41+
aws_vpc_region: "{{ aws_vpc_region | default([]) + [{'vpc_id': _vpc.vpcs[0].id, 'region': _vpc._region}] }}"
42+
loop:
43+
"{{ vpc_info.results }}"
44+
when: _vpc.vpcs
45+
loop_control:
46+
label: "{{ _vpc._region }}"
47+
loop_var: _vpc
5248

5349
####################### Teardown #######################
5450

@@ -60,33 +56,82 @@
6056
- name: Stop and terminate ec2 instance
6157
ansible.builtin.include_tasks: ec2_instance.yml
6258
when: not teardown_specific_instances
59+
loop: "{{ aws_vpc_region }}"
60+
loop_control:
61+
label: "{{ _vpc_region.region }}"
62+
loop_var: _vpc_region
63+
vars:
64+
aws_region: "{{ _vpc_region.region }}"
65+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
6366

6467
# eip and network interfaces
6568
- name: Remove all network interfaces associated with VPC
6669
ansible.builtin.include_tasks: ec2_eni.yml
6770
when: not teardown_specific_instances
71+
loop: "{{ aws_vpc_region }}"
72+
loop_control:
73+
label: "{{ _vpc_region.region }}"
74+
loop_var: _vpc_region
75+
vars:
76+
aws_region: "{{ _vpc_region.region }}"
77+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
6878

6979
# security groups
7080
- name: Remove all security groups associated with VPC
7181
when: not teardown_specific_instances
7282
ansible.builtin.include_tasks: ec2_group.yml
83+
loop: "{{ aws_vpc_region }}"
84+
loop_control:
85+
label: "{{ _vpc_region.region }}"
86+
loop_var: _vpc_region
87+
vars:
88+
aws_region: "{{ _vpc_region.region }}"
89+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
7390

7491
# route tables
7592
- name: Remove all route tables associated with VPC
7693
when: not teardown_specific_instances
7794
ansible.builtin.include_tasks: ec2_vpc_route_table.yml
95+
loop: "{{ aws_vpc_region }}"
96+
loop_control:
97+
label: "{{ _vpc_region.region }}"
98+
loop_var: _vpc_region
99+
vars:
100+
aws_region: "{{ _vpc_region.region }}"
101+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
78102

79103
# subnets
80104
- name: Remove all subnets associated with VPC
81105
when: not teardown_specific_instances
82106
ansible.builtin.include_tasks: ec2_vpc_subnet.yml
107+
loop: "{{ aws_vpc_region }}"
108+
loop_control:
109+
label: "{{ _vpc_region.region }}"
110+
loop_var: _vpc_region
111+
vars:
112+
aws_region: "{{ _vpc_region.region }}"
113+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
83114

84115
# igw
85116
- name: Remove all internet gateways
86117
when: not teardown_specific_instances
87118
ansible.builtin.include_tasks: ec2_vpc_igw.yml
119+
loop: "{{ aws_vpc_region }}"
120+
loop_control:
121+
label: "{{ _vpc_region.region }}"
122+
loop_var: _vpc_region
123+
vars:
124+
aws_region: "{{ _vpc_region.region }}"
125+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"
88126

89127
# vpc
90128
- name: Remove VPC
91129
when: not teardown_specific_instances
92130
ansible.builtin.include_tasks: ec2_vpc_net.yml
131+
loop: "{{ aws_vpc_region }}"
132+
loop_control:
133+
label: "{{ _vpc_region.region }}"
134+
loop_var: _vpc_region
135+
vars:
136+
aws_region: "{{ _vpc_region.region }}"
137+
aws_vpc_id: "{{ _vpc_region.vpc_id }}"

roles/common/defaults/main.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright 2025 Cisco Systems, Inc. and its affiliates
2+
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
3+
4+
---
5+
6+
# Common
7+
all_aws_regions: "{{ [aws_region] + wan_edges | default([]) | json_query('[?aws_region].aws_region') | unique }}"

roles/common/tasks/aws_existing_instances.yml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,54 @@
55
# VPC info
66
- name: Retrieve VPC details
77
amazon.aws.ec2_vpc_net_info: # noqa: syntax-check[unknown-module]
8-
region: "{{ aws_region }}"
8+
region: "{{ region }}"
99
filters:
1010
"tag:Name": "{{ aws_vpc_config.tags.Name }}"
1111
"tag:Creator": "{{ aws_vpc_config.tags.Creator }}"
1212
register: ec2_vpc_net_info
13+
loop: "{{ all_aws_regions }}"
14+
loop_control:
15+
label: "{{ region }}"
16+
loop_var: region
1317

1418
- name: Initialize instances_info dictionary
1519
ansible.builtin.set_fact:
1620
instances_info: {}
1721

1822
- name: Gather facts about all instances in VPC
1923
amazon.aws.ec2_instance_info:
20-
region: "{{ aws_region }}"
24+
region: "{{ vpc.region }}"
2125
filters:
22-
vpc-id: "{{ ec2_vpc_net_info.vpcs[0].id }}"
26+
vpc-id: "{{ vpc.vpcs[0].id }}"
2327
instance-state-name: ["pending", "running", "shutting-down", "stopping", "stopped"]
2428
register: ec2_instance_info
25-
when: ec2_vpc_net_info.vpcs | length > 0
29+
when: vpc.vpcs | length > 0
30+
loop: "{{ ec2_vpc_net_info.results }}"
31+
loop_control:
32+
label: "{{ vpc.region }}"
33+
loop_var: vpc
2634

2735

2836
# We are working inside one VPC, consider changing desing in order to maintain more VPCs.
2937
- name: Verify if there are instances with requested parameters already present
30-
when: ec2_instance_info is defined and ec2_instance_info.instances | length > 0
38+
when: ec2_instance_info is defined and ec2_instance_info.results | map(attribute='instances') | flatten | length > 0
3139
block:
3240
- name: Set instance status and state, variable 'instances_info' will hold list of existing instances
3341
ansible.builtin.set_fact:
3442
instances_info: >-
3543
{{
3644
instances_info | default({}) | combine({
3745
instance_item.hostname: {
38-
'state': (ec2_instance_info.instances | selectattr('tags.Name', 'equalto', instance_item.hostname) | map(attribute='state.name') | first)
46+
'state': (_instances | selectattr('tags.Name', 'equalto', instance_item.hostname) | map(attribute='state.name') | first)
3947
}
40-
}) if instance_item.hostname in (ec2_instance_info.instances | map(attribute='tags.Name') | list) else instances_info
48+
}) if instance_item.hostname in (_instances | map(attribute='tags.Name') | list) else instances_info
4149
}}
4250
loop: "{{ instances_marked_for_deployment }}"
4351
loop_control:
4452
loop_var: instance_item
4553
when: instance_item | length > 0
54+
vars:
55+
_instances: "{{ ec2_instance_info.results | map(attribute='instances') | flatten }}"
4656

4757
- name: Prompt user information about existing instances
4858
ansible.builtin.pause:

0 commit comments

Comments
 (0)