Skip to content

Commit 2f26da4

Browse files
hakbaileypatchback[bot]
authored andcommitted
Merge pull request #123 from mandar242/ec2-create-instance-role
Add new manage_ec2_instance role (cherry picked from commit 8bc3076)
1 parent aaab9d7 commit 2f26da4

File tree

14 files changed

+637
-0
lines changed

14 files changed

+637
-0
lines changed

roles/manage_ec2_instance/README.md

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# manage_ec2_instance
2+
3+
A role to create or delete an EC2 instance in AWS.
4+
5+
Users can specify various parameters for instance configuration, including instance type, AMI ID, key pair, tags, VPC/subnet configuration, and whether to associate an EIP. You can choose to wait for the EC2 instance to finish booting/terminating before continuing.
6+
7+
This role can be combined with the [cloud.aws_ops.ec2_networking_resources role](../ec2_networking_resources/README.md) to create/delete networking resources for the instance, see [examples](#examples).
8+
9+
EC2 instance details and the private key (if a key pair is created) will be displayed as role output. The instance and key pair details are accessible via variables `ec2_instance_manage_create_result` and `ec2_instance_manage_key_pair_result`, respectively.
10+
11+
## Requirements
12+
13+
An AWS account with the following permissions:
14+
15+
* ec2:AllocateAddress
16+
* ec2:AssociateAddress
17+
* ec2:CreateKeyPair
18+
* ec2:DeleteKeyPair
19+
* ec2:DescribeAddresses
20+
* ec2:DescribeInstanceAttribute
21+
* ec2:DescribeInstances
22+
* ec2:DescribeInstanceStatus
23+
* ec2:DescribeKeyPairs
24+
* ec2:DescribeSecurityGroups
25+
* ec2:DescribeSubnets
26+
* ec2:DescribeVpcs
27+
* ec2:DisassociateAddress
28+
* ec2:ModifyInstanceAttribute
29+
* ec2:ReleaseAddress
30+
* ec2:RunInstances
31+
* ec2:TerminateInstances
32+
33+
## Role Variables
34+
35+
The following variables can be set in the role to customize EC2 instance creation and networking configurations:
36+
37+
* **manage_ec2_instance_operation**: (Optional)
38+
Target operation for the ec2 instance role. Choices are ["create", "delete"]. Defaults to "create".
39+
40+
* **manage_ec2_instance_instance_name**: (Required)
41+
The name of the EC2 instance to be created/deleted.
42+
43+
* **manage_ec2_instance_instance_type**: (Optional)
44+
The instance type for the EC2 instance (e.g., `t2.micro`, `m5.large`). Required when `manage_ec2_instance_operation` is `create`
45+
46+
* **manage_ec2_instance_ami_id**: (Optional)
47+
The AMI ID for the EC2 instance. Required when `manage_ec2_instance_operation` is `create`
48+
49+
* **manage_ec2_instance_key_name**: (Optional)
50+
The name of the key pair to use for SSH access to the EC2 instance.
51+
If the key does not exist, a key pair will be created with the name.
52+
If not provided, instance will not be accessible via SSH.
53+
If provided when `manage_ec2_instance_operation` is `delete`, the keypair will also be deleted.
54+
55+
* **manage_ec2_instance_vpc_subnet_id**: (Optional)
56+
The ID of the VPC subnet in which the instance will be launched.
57+
If not provided, instance will be created in the default subnet for the default VPC in the AWS region if present.
58+
59+
* **manage_ec2_instance_tags**: (Optional)
60+
A dictionary of tags to assign to the EC2 instance.
61+
62+
* **manage_ec2_instance_wait_for_state**: (Optional)
63+
Whether to wait for the EC2 instance to be in the "running" (if creating an instance) or "terminated" (if deleting an instance) state before continuing. Default is `true`.
64+
65+
* **manage_ec2_instance_associate_security_groups**: (Optional)
66+
List of security group IDs to associate with the EC2 instance.
67+
68+
* **manage_ec2_instance_associate_eip**: (Optional)
69+
Whether to create an Elastic IP (EIP) and associate it with the EC2 instance. Default is `false`.
70+
If true, EC2 instance must be launched in a VPC with an Internet Gateway (IGW) attached, otherwise this will fail. Use [cloud.aws_ops.ec2_networking_resources role](../ec2_networking_resources/README.md) to create the necessary networking resources.
71+
72+
* **manage_ec2_instance_eip_tags**: (Optional)
73+
Tags to assign to the elastic IP.
74+
75+
## Dependencies
76+
77+
- role: [aws_setup_credentials](../aws_setup_credentials/README.md)
78+
79+
## Examples
80+
81+
Using the role on its own in a playbook:
82+
83+
```yaml
84+
---
85+
- name: Create EC2 instance
86+
hosts: localhost
87+
gather_facts: false
88+
roles:
89+
- role: cloud.aws_ops.manage_ec2_instance
90+
vars:
91+
manage_ec2_instance_operation: create
92+
manage_ec2_instance_aws_region: us-west-2
93+
manage_ec2_instance_instance_name: my-test-instance
94+
manage_ec2_instance_instance_type: t2.micro
95+
manage_ec2_instance_ami_id: ami-066a7fbaa12345678
96+
manage_ec2_instance_vpc_subnet_id: subnet-071443aa123456789
97+
manage_ec2_instance_tags:
98+
Component: my-test-instance
99+
Environment: Testing
100+
manage_ec2_instance_wait_for_state: true
101+
```
102+
103+
Combining the role with [cloud.aws_ops.ec2_networking_resources](../ec2_networking_resources/README.md):
104+
105+
```yaml
106+
---
107+
- name: Create EC2 networking resources and EC2 instance
108+
hosts: localhost
109+
gather_facts: false
110+
roles:
111+
- role: cloud.aws_ops.ec2_networking_resources:
112+
vars:
113+
ec2_networking_resources_vpc_name: my-vpc
114+
ec2_networking_resources_vpc_cidr_block: 10.0.0.0/24
115+
ec2_networking_resources_subnet_cidr_block: 10.0.0.0/25
116+
ec2_networking_resources_sg_internal_name: my-internal-sg
117+
ec2_networking_resources_sg_external_name: my-external-sg
118+
ec2_networking_resources_create_igw: true
119+
- role: cloud.aws_ops.manage_ec2_instance
120+
vars:
121+
manage_ec2_instance_operation: present
122+
manage_ec2_instance_instance_name: my-test-instance
123+
manage_ec2_instance_instance_type: t2.micro
124+
manage_ec2_instance_ami_id: ami-066a7fbaa12345678
125+
manage_ec2_instance_vpc_subnet_id: "{{ ec2_networking_resources_subnet_result.subnet.id }}"
126+
manage_ec2_instance_associate_security_groups:
127+
- my-internal-sg
128+
- my-external-sg
129+
manage_ec2_instance_associate_eip: true
130+
```
131+
132+
Deleting an EC2 instance:
133+
134+
```yaml
135+
---
136+
- name: Delete EC2 instance
137+
hosts: localhost
138+
gather_facts: false
139+
roles:
140+
- role: cloud.aws_ops.manage_ec2_instance
141+
vars:
142+
manage_ec2_instance_operation: delete
143+
manage_ec2_instance_instance_name: my-test-instance
144+
manage_ec2_instance_wait_for_state: true
145+
```
146+
147+
## License
148+
149+
GNU General Public License v3.0 or later
150+
151+
See [LICENSE](../../LICENSE) to see the full text.
152+
153+
## Author Information
154+
155+
- Ansible Cloud Content Team
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
manage_ec2_instance_operation: create
3+
manage_ec2_instance_wait_for_state: true
4+
manage_ec2_instance_associate_eip: false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
argument_specs:
3+
main:
4+
short_description: A role to create or delete an EC2 instance with optional networking resources.
5+
description:
6+
- A role to create or delete an EC2 instance.
7+
- Can optionally attach security groups and associate an Elastic IP with the instance.
8+
- Supports custom configurations for instance settings including instance type, AMI, key pair, tags, VPC/subnet, and networking configurations.
9+
options:
10+
manage_ec2_instance_operation:
11+
description:
12+
- Whether to create or delete resources using the role.
13+
required: false
14+
type: str
15+
default: create
16+
choices: [create, delete]
17+
manage_ec2_instance_instance_name:
18+
description:
19+
- The name of the EC2 instance to be created.
20+
required: true
21+
type: str
22+
manage_ec2_instance_instance_type:
23+
description:
24+
- The instance type for the EC2 instance. Required when `manage_ec2_instance_operation` is `create`.
25+
required: false
26+
type: str
27+
manage_ec2_instance_ami_id:
28+
description:
29+
- The AMI ID for the EC2 instance. Required when `manage_ec2_instance_operation` is `create`.
30+
required: false
31+
type: str
32+
manage_ec2_instance_key_name:
33+
description:
34+
- The name of the key pair to use for SSH access to the EC2 instance. If the key does not exist, a key pair will be created with the name. If not provided, instance will not be accessible via SSH. If provided when `manage_ec2_instance_operation` is `delete`, the keypair will also be deleted.
35+
required: false
36+
type: str
37+
manage_ec2_instance_vpc_subnet_id:
38+
description:
39+
- The ID of the VPC subnet in which the instance will be launched. If not provided, instance will be created in the default subnet for the default VPC in the AWS region, if present.
40+
required: false
41+
type: str
42+
manage_ec2_instance_tags:
43+
description:
44+
- A dictionary of tags to assign to the EC2 instance.
45+
required: false
46+
type: dict
47+
manage_ec2_instance_wait_for_state:
48+
description:
49+
- Whether to wait for the EC2 instance to be in the running/terminated state before continuing.
50+
required: false
51+
default: true
52+
type: bool
53+
manage_ec2_instance_associate_security_groups:
54+
description:
55+
- List of security group names or IDs to associate with the EC2 instance.
56+
required: false
57+
type: list
58+
elements: str
59+
manage_ec2_instance_associate_eip:
60+
description:
61+
- Whether to create and associate an Elastic IP (EIP) with the EC2 instance.
62+
required: false
63+
default: false
64+
type: bool
65+
manage_ec2_instance_eip_tags:
66+
description:
67+
- Tags to assign to the Elastic IP.
68+
required: false
69+
type: dict
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
dependencies:
3+
- role: cloud.aws_ops.aws_setup_credentials
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
- name: Verify that an instance with same name does not exist
3+
block:
4+
- name: Get instance info with provided name
5+
amazon.aws.ec2_instance_info:
6+
filters:
7+
tag:Name: "{{ manage_ec2_instance_instance_name }}"
8+
instance-state-name: ["pending", "running", "stopping", "stopped"]
9+
register: ec2_info_result
10+
11+
- name: Print warning and exit if instance exists
12+
ansible.builtin.fail:
13+
msg: "Instance with name {{ manage_ec2_instance_instance_name }} already exists in {{ aws_region }}. Please provide a different name to avoid updating the existing instance."
14+
when: ec2_info_result.instances | length > 0
15+
16+
- name: Create a key pair if required
17+
when: manage_ec2_instance_key_name is defined and manage_ec2_instance_key_name | length > 0
18+
block:
19+
- name: Get key pair info
20+
amazon.aws.ec2_key_info:
21+
names:
22+
- "{{ manage_ec2_instance_key_name }}"
23+
register: key_info_result
24+
25+
- name: Create new key pair
26+
amazon.aws.ec2_key:
27+
name: "{{ manage_ec2_instance_key_name }}"
28+
state: present
29+
when: key_info_result.keypairs | length == 0
30+
register: ec2_instance_manage_key_pair_result
31+
32+
- name: Create EC2 instance with provided configuration
33+
amazon.aws.ec2_instance:
34+
state: running
35+
name: "{{ manage_ec2_instance_instance_name }}"
36+
instance_type: "{{ manage_ec2_instance_instance_type }}"
37+
image_id: "{{ manage_ec2_instance_ami_id }}"
38+
key_name: "{{ manage_ec2_instance_key_name | default(omit) }}"
39+
security_groups: "{{ manage_ec2_instance_associate_security_groups | default(omit, true) }}"
40+
vpc_subnet_id: "{{ manage_ec2_instance_vpc_subnet_id | default(omit) }}"
41+
tags: "{{ manage_ec2_instance_tags | default(omit) }}"
42+
wait: "{{ manage_ec2_instance_wait_for_state }}"
43+
register: ec2_instance
44+
45+
- name: Allocate and associate Elastic IP if enabled
46+
when: manage_ec2_instance_associate_eip is true
47+
amazon.aws.ec2_eip:
48+
device_id: "{{ ec2_instance.instance_ids[0] }}"
49+
state: present
50+
register: instance_eip
51+
52+
- name: Get EC2 instance info
53+
amazon.aws.ec2_instance_info:
54+
instance_ids: "{{ ec2_instance.instance_ids[0] }}"
55+
register: ec2_instance_manage_create_result
56+
57+
- name: Output details of the created EC2 instance
58+
ansible.builtin.debug:
59+
msg:
60+
- "EC2 instance {{ ec2_instance.instance_ids[0] }} created successfully"
61+
- "Instance details: {{ ec2_instance_manage_create_result.instances[0] }}"
62+
63+
- name: Output private key if a new keypair was created
64+
when: ec2_instance_manage_key_pair_result.key is defined
65+
ansible.builtin.debug:
66+
msg: "A new key pair was created for ssh access to the instance. Please save this private key for reference: {{ ec2_instance_manage_key_pair_result.key.private_key }}"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
- name: Get instance info with provided name
3+
amazon.aws.ec2_instance_info:
4+
filters:
5+
tag:Name: "{{ manage_ec2_instance_instance_name }}"
6+
instance-state-name: ["pending", "running", "stopping", "stopped"]
7+
register: ec2_info_result
8+
9+
- name: Disassociate and release EIP if present
10+
when: ec2_info_result.instances | length > 0
11+
# and ec2_info_result.instances[0].network_interfaces.association.public_ip is defined
12+
amazon.aws.ec2_eip:
13+
device_id: "{{ ec2_info_result.instances[0].instance_id }}"
14+
state: absent
15+
release_on_disassociation: true
16+
17+
- name: Terminate EC2 Instance if present
18+
when: ec2_info_result.instances | length > 0
19+
amazon.aws.ec2_instance:
20+
state: terminated
21+
wait: "{{ manage_ec2_instance_wait_for_state }}"
22+
instance_ids:
23+
- "{{ ec2_info_result.instances[0].instance_id }}"
24+
25+
- name: Delete keypair if provided
26+
when: manage_ec2_instance_key_name is defined and manage_ec2_instance_key_name | length > 0
27+
amazon.aws.ec2_key:
28+
name: "{{ manage_ec2_instance_key_name }}"
29+
state: absent
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
- name: EC2 Instance creation or deletion based on operation
3+
module_defaults:
4+
group/aws: "{{ aws_setup_credentials__output }}"
5+
block:
6+
- name: Include create operations
7+
ansible.builtin.include_tasks: ec2_instance_create_operations.yml
8+
when: manage_ec2_instance_operation == 'create'
9+
10+
- name: Include delete operations
11+
ansible.builtin.include_tasks: ec2_instance_delete_operations.yml
12+
when: manage_ec2_instance_operation == 'delete'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cloud/aws
2+
role/manage_ec2_instance
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
aws_security_token: "{{ security_token | default(omit) }}"
3+
4+
# Network Configuration
5+
test_vpc_name: "{{ resource_prefix }}-vpc"
6+
test_vpc_cidr: '101.{{ 255 | random(seed=resource_prefix) }}.0.0/16'
7+
test_subnet_cidr: '101.{{ 255 | random(seed=resource_prefix) }}.0.0/24'
8+
test_security_group_name: "{{ resource_prefix }}-sg"
9+
10+
# EC2 Instance Configuration
11+
test_ec2_instance_name: "{{ resource_prefix }}-ec2-instance"
12+
test_ec2_instance_type: t2.micro
13+
test_ec2_key_name: "{{ resource_prefix }}-ec2-key"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
- name: Integration tests for manage_ec2_instance role
3+
module_defaults:
4+
group/aws:
5+
aws_access_key: "{{ aws_access_key }}"
6+
aws_secret_key: "{{ aws_secret_key }}"
7+
security_token: "{{ security_token | default(omit) }}"
8+
region: "{{ aws_region }}"
9+
block:
10+
- name: Create resources required for test
11+
ansible.builtin.include_tasks: setup.yml
12+
13+
- name: Run tests for case 1 - EC2 instance with required options only
14+
ansible.builtin.include_tasks: tasks/test_ec2_required_options.yml
15+
16+
- name: Run tests for case 2 - EC2 instance with all options
17+
ansible.builtin.include_tasks: tasks/test_ec2_all_options.yml
18+
19+
always:
20+
- name: Delete any leftover resources used in tests
21+
ansible.builtin.include_tasks: teardown.yml

0 commit comments

Comments
 (0)