Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ec2_instance - add support for placement and license_specifications #1825

Merged
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
71ce43c
feat: Adding additional placement options and license specifications
mfortin Oct 21, 2023
fecec46
docs: Adding changelog
mfortin Oct 21, 2023
8895084
fix: typo in ec2_instance
mfortin Oct 21, 2023
0273bd4
Adding tests
mfortin Oct 24, 2023
0aa84f6
(break): Removing legacy tenancy and placement_group options
mfortin Oct 24, 2023
3274392
typo: Removing extra double quote
mfortin Oct 24, 2023
623f78d
bug: updated variable name
mfortin Oct 24, 2023
8e874a5
fix: missing license_specifications definition
mfortin Oct 24, 2023
2a7394d
fix: Updating tests
mfortin Oct 24, 2023
0f61860
fix: Update License Specifications expected structure
mfortin Oct 24, 2023
22de104
feat: Down the rabbit hole of supporting placement groups
mfortin Oct 24, 2023
2477ca0
fix: Updating runtime for new module
mfortin Oct 24, 2023
db87617
doc: Updating changelog entry
mfortin Oct 24, 2023
93bf042
fix: Updating placement group restrictions
mfortin Oct 24, 2023
edd7a99
fix: Handle placement group not found
mfortin Oct 24, 2023
55364ab
fix: Missing variable for placement group test
mfortin Oct 24, 2023
82df660
fix: Yet another placement group fix
mfortin Oct 24, 2023
902629b
Update tests
mfortin Oct 24, 2023
cc96cfb
fix: Update create/update/delete methods
mfortin Oct 24, 2023
0c79c75
fix: wrong function name
mfortin Oct 24, 2023
08c3919
fix: wrong function name
mfortin Oct 25, 2023
78800e3
Update test
mfortin Oct 25, 2023
015755b
bug: typo
mfortin Oct 25, 2023
f161dbf
doc: Update ec2_placement_group_info
mfortin Oct 25, 2023
1472aa5
doc: Update ec2_placement_group returns
mfortin Oct 25, 2023
dc8933d
doc: Update ec2_placement_group returns
mfortin Oct 25, 2023
d49dfe0
fix: Update tests for placement group
mfortin Oct 25, 2023
88448b4
fix: Update tests for placement group
mfortin Oct 25, 2023
463b294
fix: Update tests for placement group
mfortin Oct 25, 2023
7d1df45
fix: typo, extra trailing coma
mfortin Oct 25, 2023
262361b
fix: another bug fix
mfortin Oct 25, 2023
462f2a1
fix: Multiple fixes
mfortin Oct 25, 2023
beaf388
fix: Multiple fixes
mfortin Oct 25, 2023
024dfd0
fix: Multiple fixes
mfortin Oct 25, 2023
b8c7612
fix: Multiple fixes
mfortin Oct 25, 2023
f481da4
fix: Multiple fixes
mfortin Oct 25, 2023
676acf1
fix: another bug fix
mfortin Oct 26, 2023
9d45eb7
debug: adding debug messages temporarily
mfortin Oct 26, 2023
7f4eb06
fix: updating tests
mfortin Oct 26, 2023
0554acb
fix: update test
mfortin Oct 26, 2023
db0caa4
fix: update test
mfortin Oct 26, 2023
c14f6b0
fix: update test
mfortin Oct 26, 2023
900e29f
fix: update test
mfortin Oct 26, 2023
77e1f18
fix: update tests
mfortin Oct 26, 2023
8d3052f
fix: Adding EC2 License Specifications tests
mfortin Oct 26, 2023
cf03aaa
fix: Update test
mfortin Oct 26, 2023
803474e
fix: Update test
mfortin Oct 26, 2023
4ed4062
fix: Update test
mfortin Oct 26, 2023
dd8ac99
fix: Update test
mfortin Oct 26, 2023
c13caf1
fix: Update test
mfortin Oct 26, 2023
779bfcc
fix: another round of test
mfortin Oct 26, 2023
26fbdca
disabling some tests due to permission errors
mfortin Oct 26, 2023
f3632a2
doc: update changelog message
mfortin Oct 26, 2023
ffa2ee3
doc: deprecating tenancy and placement_group
mfortin Oct 27, 2023
6d2707a
Fix: typos and output
mfortin Oct 27, 2023
002bace
Fix: typos and output
mfortin Oct 27, 2023
1f1e564
Using a supported dedicated instance type
mfortin Oct 27, 2023
cd0d06a
fix: update tests
mfortin Oct 27, 2023
025bd95
Updating property name
mfortin Oct 27, 2023
00cabc9
fix: Updating test
mfortin Oct 27, 2023
e3eccac
fix: nad indentation
mfortin Oct 27, 2023
9f1b0ab
fix: update test validation
mfortin Oct 27, 2023
a4562d0
Docs formatting fixes
tremble Oct 30, 2023
6a634c4
Cleanup deprecation and set date
tremble Oct 30, 2023
8f0c014
version_added
tremble Oct 30, 2023
00b1975
fix: black-lint issue
mfortin Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelogs/fragments/1825-ec2_instances.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
minor_changes:
- ec2_instance - add support for additional ``placement`` options and ``license_specifications`` in run instance spec (https://github.com/ansible-collections/amazon.aws/issues/1824).
deprecated_features:
- ec2_instance - deprecation of ``tenancy`` and ``placement_group`` in favor of ``placement`` attribute (https://github.com/ansible-collections/amazon.aws/pull/1825).
156 changes: 153 additions & 3 deletions plugins/modules/ec2_instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
tenancy:
description:
- What type of tenancy to allow an instance to use. Default is shared tenancy. Dedicated tenancy will incur additional charges.
- This field is deprecated and will be removed in a release after 2025-12-01, use I(placement) instead.
choices: ['dedicated', 'default']
type: str
termination_protection:
Expand Down Expand Up @@ -325,7 +326,52 @@
placement_group:
description:
- The placement group that needs to be assigned to the instance.
- This field is deprecated and will be removed in a release after 2025-12-01, use I(placement) instead.
type: str
placement:
tremble marked this conversation as resolved.
Show resolved Hide resolved
description:
- The location where the instance launched, if applicable.
type: dict
suboptions:
affinity:
description: The affinity setting for the instance on the Dedicated Host.
type: str
required: false
availability_zone:
description: The Availability Zone of the instance.
type: str
required: false
group_name:
description: The name of the placement group the instance is in.
type: str
required: false
host_id:
description: The ID of the Dedicated Host on which the instance resides.
type: str
required: false
host_resource_group_arn:
description: The ARN of the host resource group in which to launch the instances.
type: str
required: false
partition_number:
description: The number of the partition the instance is in.
type: int
required: false
tenancy:
description: Type of tenancy to allow an instance to use. Default is shared tenancy. Dedicated tenancy will incur additional charges.
type: str
required: false
choices: ['dedicated', 'default']
license_specifications:
description:
- The license specifications to be used for the instance.
type: list
elements: dict
suboptions:
license_configuration_arn:
description: The Amazon Resource Name (ARN) of the license configuration.
type: str
required: true
metadata_options:
description:
- Modify the metadata options for the instance.
Expand Down Expand Up @@ -532,6 +578,22 @@
state: present
tags:
foo: bar

# launches a mac instance with HostResourceGroupArn and LicenseSpecifications
- name: start a mac instance with a host resource group and license specifications
amazon.aws.ec2_instance:
name: "mac-compute-instance"
key_name: "prod-ssh-key"
vpc_subnet_id: subnet-5ca1ab1e
instance_type: mac1.metal
security_group: default
placement:
host_resource_group_arn: arn:aws:resource-groups:us-east-1:123456789012:group/MyResourceGroup
license_specifications:
- license_configuration_arn: arn:aws:license-manager:us-east-1:123456789012:license-configuration:lic-0123456789
image_id: ami-123456
tags:
Environment: Testing
"""

RETURN = r"""
Expand Down Expand Up @@ -658,6 +720,17 @@
returned: always
type: str
sample: "2017-03-23T22:51:24+00:00"
licenses:
description: The license configurations for the instance.
returned: When license specifications are provided.
type: list
elements: dict
contains:
license_configuration_arn:
description: The Amazon Resource Name (ARN) of the license configuration.
returned: always
type: str
sample: arn:aws:license-manager:us-east-1:123456789012:license-configuration:lic-0123456789
monitoring:
description: The monitoring for the instance.
returned: always
Expand Down Expand Up @@ -841,13 +914,36 @@
returned: always
type: str
sample: ap-southeast-2a
affinity:
description: The affinity setting for the instance on the Dedicated Host.
returned: When a placement group is specified.
type: str
group_id:
description: The ID of the placement group the instance is in (for cluster compute instances).
returned: always
type: str
sample: "pg-01234566"
group_name:
description: The name of the placement group the instance is in (for cluster compute instances).
returned: always
type: str
sample: ""
sample: "my-placement-group"
host_id:
description: The ID of the Dedicated Host on which the instance resides.
returned: always
type: str
host_resource_group_arn:
description: The ARN of the host resource group in which the instance is in.
returned: always
type: str
sample: "arn:aws:resource-groups:us-east-1:123456789012:group/MyResourceGroup"
partition_number:
description: The number of the partition the instance is in.
returned: always
type: int
sample: 1
tenancy:
description: The tenancy of the instance (if the instance is running in a VPC).
description: Type of tenancy to allow an instance to use. Default is shared tenancy. Dedicated tenancy will incur additional charges.
returned: always
type: str
sample: default
Expand Down Expand Up @@ -1293,6 +1389,22 @@ def build_top_level_options(params):
spec["Placement"]["GroupName"] = str(params.get("placement_group"))
else:
spec.setdefault("Placement", {"GroupName": str(params.get("placement_group"))})
if params.get("placement") is not None:
spec["Placement"] = {}
if params.get("placement").get("availability_zone") is not None:
spec["Placement"]["AvailabilityZone"] = params.get("placement").get("availability_zone")
if params.get("placement").get("affinity") is not None:
spec["Placement"]["Affinity"] = params.get("placement").get("affinity")
if params.get("placement").get("group_name") is not None:
spec["Placement"]["GroupName"] = params.get("placement").get("group_name")
if params.get("placement").get("host_id") is not None:
spec["Placement"]["HostId"] = params.get("placement").get("host_id")
if params.get("placement").get("host_resource_group_arn") is not None:
spec["Placement"]["HostResourceGroupArn"] = params.get("placement").get("host_resource_group_arn")
if params.get("placement").get("partition_number") is not None:
spec["Placement"]["PartitionNumber"] = params.get("placement").get("partition_number")
if params.get("placement").get("tenancy") is not None:
spec["Placement"]["Tenancy"] = params.get("placement").get("tenancy")
if params.get("ebs_optimized") is not None:
spec["EbsOptimized"] = params.get("ebs_optimized")
if params.get("instance_initiated_shutdown_behavior"):
Expand Down Expand Up @@ -1323,7 +1435,10 @@ def build_top_level_options(params):
)
spec["MetadataOptions"]["HttpProtocolIpv6"] = params.get("metadata_options").get("http_protocol_ipv6")
spec["MetadataOptions"]["InstanceMetadataTags"] = params.get("metadata_options").get("instance_metadata_tags")

if params.get("license_specifications"):
spec["LicenseSpecifications"] = []
for license_configuration in params.get("license_specifications"):
spec["LicenseSpecifications"].append({"LicenseConfigurationArn": license_configuration.get("license_configuration_arn")})
return spec


Expand Down Expand Up @@ -2106,6 +2221,13 @@ def main():
purge_tags=dict(type="bool", default=True),
filters=dict(type="dict", default=None),
launch_template=dict(type="dict"),
license_specifications=dict(
type="list",
elements="dict",
options=dict(
license_configuration_arn=dict(type="str", required=True),
),
),
key_name=dict(type="str"),
cpu_credit_specification=dict(type="str", choices=["standard", "unlimited"]),
cpu_options=dict(
Expand All @@ -2117,6 +2239,18 @@ def main():
),
tenancy=dict(type="str", choices=["dedicated", "default"]),
mfortin marked this conversation as resolved.
Show resolved Hide resolved
placement_group=dict(type="str"),
mfortin marked this conversation as resolved.
Show resolved Hide resolved
placement=dict(
type="dict",
options=dict(
affinity=dict(type="str"),
availability_zone=dict(type="str"),
group_name=dict(type="str"),
host_id=dict(type="str"),
host_resource_group_arn=dict(type="str"),
partition_number=dict(type="int"),
tenancy=dict(type="str", choices=["dedicated", "default"]),
mfortin marked this conversation as resolved.
Show resolved Hide resolved
),
),
instance_initiated_shutdown_behavior=dict(type="str", choices=["stop", "terminate"]),
termination_protection=dict(type="bool"),
hibernation_options=dict(type="bool", default=False),
Expand Down Expand Up @@ -2146,6 +2280,8 @@ def main():
["image_id", "image"],
["exact_count", "count"],
["exact_count", "instance_ids"],
["tenancy", "placement"],
["placement_group", "placement"],
mfortin marked this conversation as resolved.
Show resolved Hide resolved
],
supports_check_mode=True,
)
Expand All @@ -2159,6 +2295,20 @@ def main():
if module.params.get("security_groups"):
module.fail_json(msg="Parameter network.interfaces can't be used with security_groups")

if module.params.get("placement_group"):
module.deprecate(
"The placement_group parameter has been deprecated, please use placement.group_name instead.",
date="2025-12-01",
collection_name="amazon.aws",
)

if module.params.get("tenancy"):
module.deprecate(
"The tenancy parameter has been deprecated, please use placement.tenancy instead.",
date="2025-12-01",
collection_name="amazon.aws",
)

state = module.params.get("state")

retry_decorator = AWSRetry.jittered_backoff(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
time=10m

cloud/aws

ec2_instance_info
ec2_instance
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# defaults file for ec2_instance_block_devices
ec2_instance_type: 't3.micro'
ec2_instance_tag_TestId: '{{ resource_prefix }}-license-specifications'
ec2_host_resource_group_arn: 'arn:aws:resource-groups:{{ aws_region }}:123456789012:group/{{ resource_prefix }}-resource-group'
ec2_license_configuration_arn: 'arn:aws:license-manager:{{ aws_region }}:123456789012:license-configuration:lic-0123456789'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# this just makes sure they're in the right place
dependencies:
- role: setup_ec2_facts
- role: setup_ec2_instance_env
vars:
ec2_instance_test_name: license_specifications
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
- module_defaults:
mfortin marked this conversation as resolved.
Show resolved Hide resolved
group/aws:
access_key: "{{ aws_access_key }}"
secret_key: "{{ aws_secret_key }}"
session_token: "{{ security_token | default(omit) }}"
region: "{{ aws_region }}"
block:
- name: "New instance with license specifications"
ec2_instance:
state: running
name: "{{ resource_prefix }}-test-ebs-vols"
image_id: "{{ ec2_ami_id }}"
vpc_subnet_id: "{{ testing_subnet_b.subnet.id }}"
placement:
host_resource_group_arn: "{{ ec2_host_resource_group_arn }}"
license_specifications:
- license_configuration_arn: "{{ ec2_license_configuration_arn }}"
tags:
TestId: "{{ ec2_instance_tag_TestId }}"
instance_type: "{{ ec2_instance_type }}"
wait: true
ignore_errors: true
register: instance_creation

- name: "Validate instance with license specifications"
assert:
that:
- instance_creation is failed
- '"An instance is associated with one or more unshared license configurations." in instance_creation.msg'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
time=10m

cloud/aws

ec2_instance_info
ec2_instance
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# defaults file for ec2_instance_block_devices
ec2_instance_type: 't3.micro'
ec2_instance_tag_TestId: '{{ resource_prefix }}-placement-group'
ec2_tenancy: 'dedicated'
ec2_placement_group_name: '{{ resource_prefix}}-placement-group'
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# this just makes sure they're in the right place
dependencies:
- role: setup_ec2_facts
- role: setup_ec2_instance_env
vars:
ec2_instance_test_name: placement_options
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
- module_defaults:
group/aws:
access_key: "{{ aws_access_key }}"
secret_key: "{{ aws_secret_key }}"
session_token: "{{ security_token | default(omit) }}"
region: "{{ aws_region }}"
block:
- name: New placement group
community.aws.ec2_placement_group:
name: "{{ ec2_placement_group_name }}"
strategy: partition
partition_count: 1
state: present

- name: New instance with placement group name
ec2_instance:
state: running
name: "{{ resource_prefix }}-test-placement-group-name"
image_id: "{{ ec2_ami_id }}"
placement:
group_name: "{{ ec2_placement_group_name }}"
tags:
Name: "{{ resource_prefix }}-test-placement-group-name"
TestId: "{{ ec2_instance_tag_TestId }}"
security_group: default
instance_type: "{{ ec2_instance_type }}"
wait: true
ignore_errors: true
register: instance_creation

- name: Gather ec2 facts to check placement group options
ec2_instance_info:
filters:
"tag:Name": "{{ resource_prefix }}-test-placement-group-name"
"tag:TestId": "{{ ec2_instance_tag_TestId }}"
"instance-state-name": "running"
ignore_errors: true
register: instance_facts

- name: Validate instance with placement group name
assert:
that:
- instance_creation is success
- instance_creation is changed
- instance_facts.instances[0].placement.group_name == ec2_placement_group_name
# - instance_creation is failed
# - '"You are not authorized to perform this operation." in instance_creation.msg'

- name: New instance with dedicated tenancy
ec2_instance:
state: running
name: "{{ resource_prefix }}-test-dedicated-tenancy"
image_id: "{{ ec2_ami_id }}"
placement:
tenancy: "{{ ec2_tenancy }}"
tags:
TestId: "{{ ec2_instance_tag_TestId }}"
security_group: default
instance_type: "{{ ec2_instance_type }}"
wait: true
ignore_errors: true
register: instance_creation

- name: Gather ec2 facts to check placement tenancy
ec2_instance_info:
filters:
"tag:Name": "{{ resource_prefix }}-test-dedicated-tenancy"
"tag:TestId": "{{ ec2_instance_tag_TestId }}"
"instance-state-name": "running"
ignore_errors: true
register: instance_facts

- name: Validate instance with dedicated tenancy
assert:
that:
- instance_creation is success
- instance_creation is changed
- instance_facts.instances[0].placement.tenancy == ec2_tenancy
# - instance_creation is failed
# - '"You are not authorized to perform this operation." in instance_creation.msg'
Loading