Skip to content

Commit

Permalink
ec2_instance - add support for placement and `license_specification…
Browse files Browse the repository at this point in the history
…s` (#1825)

ec2_instance - add support for `placement` and `license_specifications`

SUMMARY

Adding placement options and license specifications support

Fixes #1824
ISSUE TYPE


Feature Pull Request

COMPONENT NAME

ec2_instance
ADDITIONAL INFORMATION

Reviewed-by: Mark Chappell
Reviewed-by: Math Fortin
Reviewed-by: Helen Bailey <hebailey@redhat.com>
Reviewed-by: Alina Buzachis
  • Loading branch information
mfortin authored Oct 30, 2023
1 parent 7ad3a12 commit c9fd4b7
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 3 deletions.
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).
159 changes: 156 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,53 @@
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:
description:
- The location where the instance launched, if applicable.
type: dict
version_added: 7.0.0
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 +579,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 +721,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 +915,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 +1390,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 +1436,12 @@ 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 +2224,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 +2242,18 @@ def main():
),
tenancy=dict(type="str", choices=["dedicated", "default"]),
placement_group=dict(type="str"),
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"]),
),
),
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 +2283,8 @@ def main():
["image_id", "image"],
["exact_count", "count"],
["exact_count", "instance_ids"],
["tenancy", "placement"],
["placement_group", "placement"],
],
supports_check_mode=True,
)
Expand All @@ -2159,6 +2298,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:
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
Loading

0 comments on commit c9fd4b7

Please sign in to comment.