Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
minor_changes:
- aws_ec2 inventory plugin - Added a ``use_deprecated_tags`` option to allow disabling the deprecated
``tags`` host variable (and its associated deprecation and reserved-name warnings) independently of
global deprecation warning settings (https://github.com/ansible-collections/amazon.aws/issues/3028).
50 changes: 40 additions & 10 deletions plugins/inventory/aws_ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
role will be used for authentication.
- The C(tags) host variable is deprecated and will be removed in a release after 2026-12-01.
Use C(ec2_tags) instead to avoid conflicts with Ansible reserved variable names.
Set O(use_deprecated_tags=false) to disable the C(tags) host variable, and this warning, before then.
- The C(ec2_tags) host variable was added in version 11.2.0.
- The C(use_contrib_script_compatible_ec2_tag_keys) option is deprecated and will be removed in a release after 2026-12-01.
Use the C(ec2_tags) structure instead (e.g. use C(ec2_tags.TAGNAME) rather than C(ec2_tag_TAGNAME)).
Expand Down Expand Up @@ -130,6 +131,17 @@
type: bool
default: false
version_added: 1.5.0
use_deprecated_tags:
description:
- Whether to include the deprecated C(tags) host variable alongside C(ec2_tags).
- Set to V(false) to stop the plugin from adding the C(tags) host variable, which also
disables this plugin's C(tags) deprecation warning and Ansible's reserved variable
name warning for C(tags).
- The use of this feature is deprecated and will be removed in a release after 2026-12-01.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alinabuzachis @GomathiselviS When are you currently planning for 12.0.0 release? If we're aiming for early November, then we could swap the release dates for versions, and the wording becomes a little less clunky.

Suggested change
- The use of this feature is deprecated and will be removed in a release after 2026-12-01.
- This parameter will be ignored when the deprecated C(tags) host variable is removed
(in a release after 2026-12-01).

If we remove this in 2026-12-01 there's no way to ensure consistent behaviour between 12.0.0 and 13.0.0.

Setting this flag to False will trigger the new behaviour in 12.0.0, but cause failures in 13.0.0. This causes problems for people who need to run a mixed environment (and is an example of why we normally use a 2 year deprecation cycle)

What we've done in the past is add a 2 year deprecation to the feature flag after ignoring it. This means that people can turn off the deprecated feature in advance. Make sure everything's working. They can then run both 12 and 13 while they migrate to 13, followed by dropping the parameter once they finish their migrations. It's a smoother path and doesn't result in multiple breakages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this @tremble I wasn't sure at all tbh, based this on similar bits, and made some assumptions. I agree that a 2 year deprecation would be a smoother path but will wait for @alinabuzachis and @GomathiselviS

Use the C(ec2_tags) structure instead.
type: bool
default: true
version_added: 12.0.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to back port this to 11?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason that I'm aware of. I still need to learn the release process and versions around here.

@tremble tremble Jul 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general main is "future" (the major we've not released yet, currently 12.0.0). Most non-breaking changes get backported into the "current" stable-X branch (stable-11 at the minute), bugfixes to both the current and the previous stable (stable-11 and stable-10) branch, and security fixes sometimes get pulled back even further.

https://github.com/ansible-collections/amazon.aws/blob/main/docs/docsite/rst/dev_guidelines.rst#release-policy-and-backporting-merged-prs

We have patchback configured and a workflow that reads the changelog fragment to estimate which releases it should be backported for (backport tags are added when mergeit is set)

The actual release process is also documented https://github.com/ansible-collections/amazon.aws/blob/main/docs/docsite/rst/collection_release.rst

We also have a workflow which keeps https://github.com/ansible-collections/amazon.aws/releases up to date.

Last release was 11.4.0, so if this is backported it would be 11.5.0.

hostvars_prefix:
description:
- The prefix for host variables names coming from AWS.
Expand Down Expand Up @@ -499,6 +511,7 @@ def _prepare_host_vars(
hostvars_prefix: str = None,
hostvars_suffix: str = None,
use_contrib_script_compatible_ec2_tag_keys: bool = False,
use_deprecated_tags: bool = True,
) -> Dict[str, Any]:
"""
Transform EC2 instance data into Ansible host variables.
Expand All @@ -511,12 +524,18 @@ def _prepare_host_vars(
:param hostvars_prefix: Optional prefix to add to all host variable names
:param hostvars_suffix: Optional suffix to add to all host variable names
:param use_contrib_script_compatible_ec2_tag_keys: If True, create ec2_tag_* variables
:param use_deprecated_tags: If True, also expose the deprecated 'tags' host variable
:return: Dictionary of processed host variables
"""
host_vars = camel_dict_to_snake_dict(original_host_vars, ignore_list=["Tags"])
host_vars["ec2_tags"] = boto3_tag_list_to_ansible_dict(original_host_vars.get("Tags", []))
# ec2_tags is the new key, tags is deprecated but kept for backward compatibility
host_vars["tags"] = host_vars["ec2_tags"]
if use_deprecated_tags:
# ec2_tags is the new key, tags is deprecated but kept for backward compatibility
host_vars["tags"] = host_vars["ec2_tags"]
else:
# camel_dict_to_snake_dict() above already renamed the raw 'Tags' key to 'tags';
# drop it so the deprecated host variable is fully absent, not just left unconverted.
host_vars.pop("tags", None)

# Allow easier grouping by region or by AZ ID
host_vars["placement"]["region"] = host_vars["placement"]["availability_zone"][:-1]
Expand Down Expand Up @@ -976,6 +995,7 @@ def _populate(
hostvars_prefix=None,
hostvars_suffix=None,
use_contrib_script_compatible_ec2_tag_keys=False,
use_deprecated_tags=True,
):
for group in groups:
group = self.inventory.add_group(group)
Expand All @@ -988,6 +1008,7 @@ def _populate(
hostvars_prefix=hostvars_prefix,
hostvars_suffix=hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys=use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags=use_deprecated_tags,
)
self.inventory.add_child("all", group)

Expand All @@ -1000,6 +1021,7 @@ def iter_entry(
hostvars_prefix=None,
hostvars_suffix=None,
use_contrib_script_compatible_ec2_tag_keys=False,
use_deprecated_tags=True,
):
for host in hosts:
if allow_duplicated_hosts:
Expand All @@ -1015,6 +1037,7 @@ def iter_entry(
hostvars_prefix,
hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags,
)
for name in hostname_list:
yield to_text(name), host_vars
Expand All @@ -1029,6 +1052,7 @@ def _add_hosts(
hostvars_prefix=None,
hostvars_suffix=None,
use_contrib_script_compatible_ec2_tag_keys=False,
use_deprecated_tags=True,
):
"""
:param hosts: a list of hosts to be added to a group
Expand All @@ -1039,6 +1063,7 @@ def _add_hosts(
:param str hostvars_prefix: starts the hostvars variable name with this prefix
:param str hostvars_suffix: ends the hostvars variable name with this suffix
:param bool use_contrib_script_compatible_ec2_tag_keys: transform the host name with the legacy naming system
:param bool use_deprecated_tags: if true, also expose the deprecated 'tags' host variable
"""

for name, host_vars in self.iter_entry(
Expand All @@ -1049,6 +1074,7 @@ def _add_hosts(
hostvars_prefix=hostvars_prefix,
hostvars_suffix=hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys=use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags=use_deprecated_tags,
):
self.inventory.add_host(name, group=group)
for k, v in host_vars.items():
Expand Down Expand Up @@ -1076,13 +1102,8 @@ def build_include_filters(self):
def parse(self, inventory, loader, path, cache=True):
super().parse(inventory, loader, path, cache=cache)

self.display.deprecated(
"The 'tags' host variable is deprecated. Use 'ec2_tags' instead.",
date="2026-12-01",
collection_name="amazon.aws",
)

# get user specifications
Comment thread
oraNod marked this conversation as resolved.
collection_name = get_collection_info()["name"]
regions = self.get_option("regions")
include_filters = self.build_include_filters()
exclude_filters = self.get_option("exclude_filters")
Expand All @@ -1094,14 +1115,22 @@ def parse(self, inventory, loader, path, cache=True):
hostvars_suffix = self.get_option("hostvars_suffix")
use_contrib_script_compatible_sanitization = self.get_option("use_contrib_script_compatible_sanitization")
use_contrib_script_compatible_ec2_tag_keys = self.get_option("use_contrib_script_compatible_ec2_tag_keys")
use_deprecated_tags = self.get_option("use_deprecated_tags")
use_ssm_inventory = self.get_option("use_ssm_inventory")

if use_deprecated_tags:
self.display.deprecated(
"The 'tags' host variable is deprecated. Use 'ec2_tags' instead.",
date="2026-12-01",
collection_name=collection_name,
)

if use_contrib_script_compatible_sanitization:
self.display.deprecated(
"The 'use_contrib_script_compatible_sanitization' option is deprecated. "
"Use Ansible's default group name sanitization instead.",
date="2026-12-01",
collection_name="amazon.aws",
collection_name=collection_name,
)

self._sanitize_group_name = self._legacy_script_compatible_group_sanitization
Expand All @@ -1111,7 +1140,7 @@ def parse(self, inventory, loader, path, cache=True):
"The 'use_contrib_script_compatible_ec2_tag_keys' option is deprecated. "
"Use the 'ec2_tags' structure instead.",
date="2026-12-01",
collection_name="amazon.aws",
collection_name=collection_name,
)

if not all(isinstance(element, (dict, str)) for element in hostnames):
Expand All @@ -1135,6 +1164,7 @@ def parse(self, inventory, loader, path, cache=True):
hostvars_prefix=hostvars_prefix,
hostvars_suffix=hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys=use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags=use_deprecated_tags,
)

self.update_cached_result(path, cache, results)
Expand Down
49 changes: 48 additions & 1 deletion tests/unit/plugins/inventory/test_aws_ec2.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def fixture_inventory():
"aws_session_token": "test_security_token",
"iam_role_arn": None,
"use_contrib_script_compatible_ec2_tag_keys": False,
"use_deprecated_tags": True,
"hostvars_prefix": "",
"hostvars_suffix": "",
"strict": True,
Expand Down Expand Up @@ -260,12 +261,14 @@ def test_sanitize_hostname_legacy(inventory):


@pytest.mark.parametrize(
"hostvars_prefix,hostvars_suffix,use_contrib_script_compatible_ec2_tag_keys,availability_zone_ids,expectation",
"hostvars_prefix,hostvars_suffix,use_contrib_script_compatible_ec2_tag_keys,use_deprecated_tags,"
"availability_zone_ids,expectation",
[
(
None,
None,
False,
True,
{"us-east-1a": "use1-az1"},
{
"my_var": 1,
Expand All @@ -282,6 +285,7 @@ def test_sanitize_hostname_legacy(inventory):
"pre",
"post",
False,
True,
{"us-east-1a": "use1-az1"},
{
"premy_varpost": 1,
Expand All @@ -298,6 +302,7 @@ def test_sanitize_hostname_legacy(inventory):
None,
None,
True,
True,
{"us-east-1a": "use1-az1"},
{
"my_var": 1,
Expand All @@ -315,6 +320,7 @@ def test_sanitize_hostname_legacy(inventory):
None,
None,
False,
True,
{},
{
"my_var": 1,
Expand All @@ -323,12 +329,29 @@ def test_sanitize_hostname_legacy(inventory):
"tags": {"Name": "my-name"},
},
),
(
None,
None,
False,
False,
{"us-east-1a": "use1-az1"},
{
"my_var": 1,
"placement": {
"availability_zone": "us-east-1a",
"region": "us-east-1",
"availability_zone_id": "use1-az1",
},
"ec2_tags": {"Name": "my-name"},
},
),
],
)
def test_prepare_host_vars(
hostvars_prefix,
hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags,
availability_zone_ids,
expectation,
):
Expand All @@ -344,11 +367,35 @@ def test_prepare_host_vars(
hostvars_prefix,
hostvars_suffix,
use_contrib_script_compatible_ec2_tag_keys,
use_deprecated_tags,
)
== expectation
)


@pytest.mark.parametrize("use_deprecated_tags", [True, False])
@patch("ansible_collections.amazon.aws.plugins.inventory.aws_ec2.AWSInventoryBase.parse")
def test_parse_tags_deprecation_warning(m_parse, inventory, use_deprecated_tags):
inventory._options["use_deprecated_tags"] = use_deprecated_tags
inventory.display = MagicMock()
inventory.get_cached_result = MagicMock(return_value=(True, {}))
inventory.update_cached_result = MagicMock()
inventory._get_availability_zone_ids = MagicMock(return_value={})
inventory._populate = MagicMock()

inventory.parse(MagicMock(), MagicMock(), "aws_ec2.yml", cache=False)

tags_deprecation_calls = [
c for c in inventory.display.deprecated.call_args_list if "'tags' host variable" in c.args[0]
]
if use_deprecated_tags:
assert len(tags_deprecation_calls) == 1
else:
assert not tags_deprecation_calls

assert inventory._populate.call_args.kwargs["use_deprecated_tags"] == use_deprecated_tags


def test_iter_entry(inventory):
hosts = [
{
Expand Down
Loading