From f36b02bb4d14fa3bdaa746341e40b34fec55bcf2 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 24 Jul 2023 23:44:29 +0200 Subject: [PATCH 1/7] Update changelog to reflect the 6.2.0 release (#1648) Update changelog to reflect the 6.2.0 release SUMMARY Update changelog to reflect the 6.2.0 release ISSUE TYPE Docs Pull Request COMPONENT NAME ADDITIONAL INFORMATION Reviewed-by: Helen Bailey Reviewed-by: Mike Graves --- CHANGELOG.rst | 34 +++++++++++ changelogs/changelog.yaml | 57 +++++++++++++++++++ .../1589-return_false_when_no_change..yml | 3 - ...1604-c2_vpc_nat_gateway-fails-silently.yml | 3 - .../1615-no_formatted_with_extra_space.yml | 3 - ...ate-eip-when-connectivity_type=private.yml | 2 - .../1633-backup-selection-conditions.yml | 5 -- .../fragments/1843-iam_instance_profile.yml | 2 - changelogs/fragments/1846-arn-validation.yml | 5 -- .../20230506-autoscaling_group-fix_sanity.yml | 2 - ...up_plan-remove-none-from-nested-params.yml | 3 - .../20230612-backup_vault-fix-tag-update.yml | 3 - changelogs/fragments/20230627-ci-fixup.yml | 3 - 13 files changed, 91 insertions(+), 34 deletions(-) delete mode 100644 changelogs/fragments/1589-return_false_when_no_change..yml delete mode 100644 changelogs/fragments/1604-c2_vpc_nat_gateway-fails-silently.yml delete mode 100644 changelogs/fragments/1615-no_formatted_with_extra_space.yml delete mode 100644 changelogs/fragments/1632-changes-to-no-allocate-eip-when-connectivity_type=private.yml delete mode 100644 changelogs/fragments/1633-backup-selection-conditions.yml delete mode 100644 changelogs/fragments/1843-iam_instance_profile.yml delete mode 100644 changelogs/fragments/1846-arn-validation.yml delete mode 100644 changelogs/fragments/20230506-autoscaling_group-fix_sanity.yml delete mode 100644 changelogs/fragments/202306012-backup_plan-remove-none-from-nested-params.yml delete mode 100644 changelogs/fragments/20230612-backup_vault-fix-tag-update.yml delete mode 100644 changelogs/fragments/20230627-ci-fixup.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 79caa61e435..fdd8c166857 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,40 @@ amazon.aws Release Notes .. contents:: Topics +v6.2.0 +====== + +Release Summary +--------------- + +This release brings some new modules, features, and several bugfixes. + +Minor Changes +------------- + +- backup_selection - add validation and documentation for all conditions suboptions (https://github.com/ansible-collections/amazon.aws/pull/1633). +- ec2_instance - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). +- iam_user - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). +- module_utils.arn - add ``resource_id`` and ``resource_type`` to ``parse_aws_arn`` return values (https://github.com/ansible-collections/amazon.aws/pull/1619). +- module_utils.arn - added ``validate_aws_arn`` function to handle common pattern matching for ARNs (https://github.com/ansible-collections/amazon.aws/pull/1619). + +Bugfixes +-------- + +- cloudwatchevent_rule - Fixes changed status to report False when no change has been made. The module had incorrectly always reported a change. (https://github.com/ansible-collections/amazon.aws/pull/1589) +- lambda_execute - Fixes to the stack trace output, where it does not contain spaces between each character. The module had incorrectly always outputted extra spaces between each character. (https://github.com/ansible-collections/amazon.aws/pull/1615) +- backup_plan - Use existing ``scrub_none_values`` function from module_utils to remove None values from nested dicts in supplied params. Nested None values were being retained and causing an error when sent through to the boto3 client operation (https://github.com/ansible-collections/amazon.aws/pull/1611). +- backup_vault - fix error when updating tags on a backup vault by using the correct boto3 client methods for tagging and untagging backup resources (https://github.com/ansible-collections/amazon.aws/pull/1610). +- ec2_vpc_nat_gateway - adding a boolean parameter called ``default_create`` to allow users to have the option to choose whether they want to display an error message or create a NAT gateway when an EIP address is not found. The module (ec2_vpc_nat_gateway) had incorrectly failed silently if EIP didn't exist (https://github.com/ansible-collections/amazon.aws/issues/1295). +- ec2_vpc_nat_gateway - fixes to nat gateway so that when the user creates a private NAT gateway, an Elastic IP address should not be allocated. The module had inncorrectly always allocate elastic IP address when creating private nat gateway (https://github.com/ansible-collections/amazon.aws/pull/1632). +- module_utils.backup - get_selection_details fix empty list returned when multiple backup selections exist (https://github.com/ansible-collections/amazon.aws/pull/1633). + +New Modules +----------- + +- iam_instance_profile - manage IAM instance profiles +- iam_instance_profile_info - gather information on IAM instance profiles + v6.1.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 3686ed2a1b6..5fdc9b178b7 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -2174,3 +2174,60 @@ releases: - release_summary.yml - test-reqs.yml release_date: '2023-06-07' + 6.2.0: + changes: + bugfixes: + - cloudwatchevent_rule - Fixes changed status to report False when no change has been made. The module + had incorrectly always reported a change. (https://github.com/ansible-collections/amazon.aws/pull/1589) + - lambda_execute - Fixes to the stack trace output, where it does not contain spaces between + each character. The module had incorrectly always outputted extra spaces between + each character. (https://github.com/ansible-collections/amazon.aws/pull/1615) + - backup_plan - Use existing ``scrub_none_values`` function from module_utils + to remove None values from nested dicts in supplied params. Nested None values + were being retained and causing an error when sent through to the boto3 client + operation (https://github.com/ansible-collections/amazon.aws/pull/1611). + - backup_vault - fix error when updating tags on a backup vault by using the + correct boto3 client methods for tagging and untagging backup resources (https://github.com/ansible-collections/amazon.aws/pull/1610). + - ec2_vpc_nat_gateway - adding a boolean parameter called ``default_create`` + to allow users to have the option to choose whether they want to display an + error message or create a NAT gateway when an EIP address is not found. The + module (ec2_vpc_nat_gateway) had incorrectly failed silently if EIP didn't + exist (https://github.com/ansible-collections/amazon.aws/issues/1295). + - ec2_vpc_nat_gateway - fixes to nat gateway so that when the user creates a + private NAT gateway, an Elastic IP address should not be allocated. The module + had inncorrectly always allocate elastic IP address when creating private + nat gateway (https://github.com/ansible-collections/amazon.aws/pull/1632). + - module_utils.backup - get_selection_details fix empty list returned when multiple + backup selections exist (https://github.com/ansible-collections/amazon.aws/pull/1633). + minor_changes: + - backup_selection - add validation and documentation for all conditions suboptions + (https://github.com/ansible-collections/amazon.aws/pull/1633). + - ec2_instance - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). + - iam_user - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). + - module_utils.arn - add ``resource_id`` and ``resource_type`` to ``parse_aws_arn`` + return values (https://github.com/ansible-collections/amazon.aws/pull/1619). + - module_utils.arn - added ``validate_aws_arn`` function to handle common pattern + matching for ARNs (https://github.com/ansible-collections/amazon.aws/pull/1619). + release_summary: This release brings some new modules, features, and several + bugfixes. + fragments: + - 1589-return_false_when_no_change..yml + - 1604-c2_vpc_nat_gateway-fails-silently.yml + - 1615-no_formatted_with_extra_space.yml + - 1632-changes-to-no-allocate-eip-when-connectivity_type=private.yml + - 1633-backup-selection-conditions.yml + - 1843-iam_instance_profile.yml + - 1846-arn-validation.yml + - 20230506-autoscaling_group-fix_sanity.yml + - 202306012-backup_plan-remove-none-from-nested-params.yml + - 20230612-backup_vault-fix-tag-update.yml + - 20230627-ci-fixup.yml + - release_summary.yml + modules: + - description: manage IAM instance profiles + name: iam_instance_profile + namespace: '' + - description: gather information on IAM instance profiles + name: iam_instance_profile_info + namespace: '' + release_date: '2023-07-05' diff --git a/changelogs/fragments/1589-return_false_when_no_change..yml b/changelogs/fragments/1589-return_false_when_no_change..yml deleted file mode 100644 index 5b5367c5f63..00000000000 --- a/changelogs/fragments/1589-return_false_when_no_change..yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: -- Fixes changed status to report False when no change has been made. The module had incorrectly always reported a change. (https://github.com/ansible-collections/amazon.aws/pull/1589) \ No newline at end of file diff --git a/changelogs/fragments/1604-c2_vpc_nat_gateway-fails-silently.yml b/changelogs/fragments/1604-c2_vpc_nat_gateway-fails-silently.yml deleted file mode 100644 index e72d9944607..00000000000 --- a/changelogs/fragments/1604-c2_vpc_nat_gateway-fails-silently.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: -- ec2_vpc_nat_gateway - adding a boolean parameter called ``default_create`` to allow users to have the option to choose whether they want to display an error message or create a NAT gateway when an EIP address is not found. The module (ec2_vpc_nat_gateway) had incorrectly failed silently if EIP didn't exist (https://github.com/ansible-collections/amazon.aws/issues/1295). \ No newline at end of file diff --git a/changelogs/fragments/1615-no_formatted_with_extra_space.yml b/changelogs/fragments/1615-no_formatted_with_extra_space.yml deleted file mode 100644 index 693362b6950..00000000000 --- a/changelogs/fragments/1615-no_formatted_with_extra_space.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: -- Fixes to the stack trace output, where it does not contain spaces between each character. The module had incorrectly always outputted extra spaces between each character. (https://github.com/ansible-collections/amazon.aws/pull/1615) \ No newline at end of file diff --git a/changelogs/fragments/1632-changes-to-no-allocate-eip-when-connectivity_type=private.yml b/changelogs/fragments/1632-changes-to-no-allocate-eip-when-connectivity_type=private.yml deleted file mode 100644 index 4b820a3498f..00000000000 --- a/changelogs/fragments/1632-changes-to-no-allocate-eip-when-connectivity_type=private.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- ec2_vpc_nat_gateway - fixes to nat gateway so that when the user creates a private NAT gateway, an Elastic IP address should not be allocated. The module had inncorrectly always allocate elastic IP address when creating private nat gateway (https://github.com/ansible-collections/amazon.aws/pull/1632). \ No newline at end of file diff --git a/changelogs/fragments/1633-backup-selection-conditions.yml b/changelogs/fragments/1633-backup-selection-conditions.yml deleted file mode 100644 index 8fac9ef4ce3..00000000000 --- a/changelogs/fragments/1633-backup-selection-conditions.yml +++ /dev/null @@ -1,5 +0,0 @@ -minor_changes: -- backup_selection - add validation and documentation for all conditions suboptions (https://github.com/ansible-collections/amazon.aws/pull/1633). - -bugfixes: -- module_utils.backup - get_selection_details fix empty list returned when multiple backup selections exist (https://github.com/ansible-collections/amazon.aws/pull/1633). diff --git a/changelogs/fragments/1843-iam_instance_profile.yml b/changelogs/fragments/1843-iam_instance_profile.yml deleted file mode 100644 index 3cfb18270d4..00000000000 --- a/changelogs/fragments/1843-iam_instance_profile.yml +++ /dev/null @@ -1,2 +0,0 @@ -trivial: -- new modules - iam_instance_profile, iam_instance_profile_info diff --git a/changelogs/fragments/1846-arn-validation.yml b/changelogs/fragments/1846-arn-validation.yml deleted file mode 100644 index 56be4417e26..00000000000 --- a/changelogs/fragments/1846-arn-validation.yml +++ /dev/null @@ -1,5 +0,0 @@ -minor_changes: -- ec2_instance - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). -- iam_user - refactored ARN validation handling (https://github.com/ansible-collections/amazon.aws/pull/1619). -- module_utils.arn - added ``validate_aws_arn`` function to handle common pattern matching for ARNs (https://github.com/ansible-collections/amazon.aws/pull/1619). -- module_utils.arn - add ``resource_id`` and ``resource_type`` to ``parse_aws_arn`` return values (https://github.com/ansible-collections/amazon.aws/pull/1619). diff --git a/changelogs/fragments/20230506-autoscaling_group-fix_sanity.yml b/changelogs/fragments/20230506-autoscaling_group-fix_sanity.yml deleted file mode 100644 index 4a51fd47532..00000000000 --- a/changelogs/fragments/20230506-autoscaling_group-fix_sanity.yml +++ /dev/null @@ -1,2 +0,0 @@ -trivial: - - "Fix sanity errors autoscaling_group and autoscaling_group_info." diff --git a/changelogs/fragments/202306012-backup_plan-remove-none-from-nested-params.yml b/changelogs/fragments/202306012-backup_plan-remove-none-from-nested-params.yml deleted file mode 100644 index d244b1ee3de..00000000000 --- a/changelogs/fragments/202306012-backup_plan-remove-none-from-nested-params.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: - - backup_plan - Use existing `scrub_none_values` function from module_utils to remove None values from nested dicts in supplied params. Nested None values were being retained and causing an error when sent through to the boto3 client operation (https://github.com/ansible-collections/amazon.aws/pull/1611). diff --git a/changelogs/fragments/20230612-backup_vault-fix-tag-update.yml b/changelogs/fragments/20230612-backup_vault-fix-tag-update.yml deleted file mode 100644 index 7ed9c45ca0b..00000000000 --- a/changelogs/fragments/20230612-backup_vault-fix-tag-update.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: - - backup_vault - fix error when updating tags on a backup vault by using the correct boto3 client methods for tagging and untagging backup resources (https://github.com/ansible-collections/amazon.aws/pull/1610). diff --git a/changelogs/fragments/20230627-ci-fixup.yml b/changelogs/fragments/20230627-ci-fixup.yml deleted file mode 100644 index 160eb26b459..00000000000 --- a/changelogs/fragments/20230627-ci-fixup.yml +++ /dev/null @@ -1,3 +0,0 @@ -trivial: -- CI fixup - ``include:`` should be ``include_tasks:``. -- CI fixup - YAML ``Null`` no longer matches any explicit parameter type requirements. From 3db86e54529af5664a424d946d8af5002a8323f7 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Tue, 25 Jul 2023 22:02:34 +0200 Subject: [PATCH 2/7] Drop vendored copy of LooseVersion (#1587) --- PSF-license.txt | 48 --- changelogs/fragments/1587-LooseVersion.yml | 4 + plugins/module_utils/_version.py | 344 --------------------- plugins/module_utils/botocore.py | 22 +- plugins/module_utils/version.py | 9 +- 5 files changed, 26 insertions(+), 401 deletions(-) delete mode 100644 PSF-license.txt create mode 100644 changelogs/fragments/1587-LooseVersion.yml delete mode 100644 plugins/module_utils/_version.py diff --git a/PSF-license.txt b/PSF-license.txt deleted file mode 100644 index 35acd7fb5ff..00000000000 --- a/PSF-license.txt +++ /dev/null @@ -1,48 +0,0 @@ -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. diff --git a/changelogs/fragments/1587-LooseVersion.yml b/changelogs/fragments/1587-LooseVersion.yml new file mode 100644 index 00000000000..4e334cc0bb2 --- /dev/null +++ b/changelogs/fragments/1587-LooseVersion.yml @@ -0,0 +1,4 @@ +breaking_changes: +- module_utils._version - vendored copy of distutils.version has been dropped (https://github.com/ansible-collections/amazon.aws/pull/1587). +minor_changes: +- module_utils.botocore - migrate from vendored copy of LooseVersion to packaging.version.Version (https://github.com/ansible-collections/amazon.aws/pull/1587). diff --git a/plugins/module_utils/_version.py b/plugins/module_utils/_version.py deleted file mode 100644 index d91cf3ab447..00000000000 --- a/plugins/module_utils/_version.py +++ /dev/null @@ -1,344 +0,0 @@ -# Vendored copy of distutils/version.py from CPython 3.9.5 -# -# Implements multiple version numbering conventions for the -# Python Module Distribution Utilities. -# -# PSF License (see PSF-license.txt or https://opensource.org/licenses/Python-2.0) -# - -"""Provides classes to represent module version numbers (one class for -each style of version numbering). There are currently two such classes -implemented: StrictVersion and LooseVersion. - -Every version number class implements the following interface: - * the 'parse' method takes a string and parses it to some internal - representation; if the string is an invalid version number, - 'parse' raises a ValueError exception - * the class constructor takes an optional string argument which, - if supplied, is passed to 'parse' - * __str__ reconstructs the string that was passed to 'parse' (or - an equivalent string -- ie. one that will generate an equivalent - version number instance) - * __repr__ generates Python code to recreate the version number instance - * _cmp compares the current instance with either another instance - of the same class or a string (which will be parsed to an instance - of the same class, thus must follow the same rules) -""" - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -import re - -try: - RE_FLAGS = re.VERBOSE | re.ASCII -except AttributeError: - RE_FLAGS = re.VERBOSE - - -class Version: - """Abstract base class for version numbering classes. Just provides - constructor (__init__) and reproducer (__repr__), because those - seem to be the same for all version numbering classes; and route - rich comparisons to _cmp. - """ - - def __init__(self, vstring=None): - if vstring: - self.parse(vstring) - - def __repr__(self): - return "%s ('%s')" % (self.__class__.__name__, str(self)) - - def __eq__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c == 0 - - def __lt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c < 0 - - def __le__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c <= 0 - - def __gt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c > 0 - - def __ge__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c >= 0 - - -# Interface for version-number classes -- must be implemented -# by the following classes (the concrete ones -- Version should -# be treated as an abstract class). -# __init__ (string) - create and take same action as 'parse' -# (string parameter is optional) -# parse (string) - convert a string representation to whatever -# internal representation is appropriate for -# this style of version numbering -# __str__ (self) - convert back to a string; should be very similar -# (if not identical to) the string supplied to parse -# __repr__ (self) - generate Python code to recreate -# the instance -# _cmp (self, other) - compare two version numbers ('other' may -# be an unparsed version string, or another -# instance of your version class) - - -class StrictVersion(Version): - """Version numbering for anal retentives and software idealists. - Implements the standard interface for version number classes as - described above. A version number consists of two or three - dot-separated numeric components, with an optional "pre-release" tag - on the end. The pre-release tag consists of the letter 'a' or 'b' - followed by a number. If the numeric components of two version - numbers are equal, then one with a pre-release tag will always - be deemed earlier (lesser) than one without. - - The following are valid version numbers (shown in the order that - would be obtained by sorting according to the supplied cmp function): - - 0.4 0.4.0 (these two are equivalent) - 0.4.1 - 0.5a1 - 0.5b3 - 0.5 - 0.9.6 - 1.0 - 1.0.4a3 - 1.0.4b1 - 1.0.4 - - The following are examples of invalid version numbers: - - 1 - 2.7.2.2 - 1.3.a4 - 1.3pl1 - 1.3c4 - - The rationale for this version numbering system will be explained - in the distutils documentation. - """ - - version_re = re.compile(r"^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$", RE_FLAGS) - - def parse(self, vstring): - match = self.version_re.match(vstring) - if not match: - raise ValueError("invalid version number '%s'" % vstring) - - (major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 4, 5, 6) - - if patch: - self.version = tuple(map(int, [major, minor, patch])) - else: - self.version = tuple(map(int, [major, minor])) + (0,) - - if prerelease: - self.prerelease = (prerelease[0], int(prerelease_num)) - else: - self.prerelease = None - - def __str__(self): - if self.version[2] == 0: - vstring = ".".join(map(str, self.version[0:2])) - else: - vstring = ".".join(map(str, self.version)) - - if self.prerelease: - vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) - - return vstring - - def _cmp(self, other): - if isinstance(other, str): - other = StrictVersion(other) - elif not isinstance(other, StrictVersion): - return NotImplemented - - if self.version != other.version: - # numeric versions don't match - # prerelease stuff doesn't matter - if self.version < other.version: - return -1 - else: - return 1 - - # have to compare prerelease - # case 1: neither has prerelease; they're equal - # case 2: self has prerelease, other doesn't; other is greater - # case 3: self doesn't have prerelease, other does: self is greater - # case 4: both have prerelease: must compare them! - - if not self.prerelease and not other.prerelease: - return 0 - elif self.prerelease and not other.prerelease: - return -1 - elif not self.prerelease and other.prerelease: - return 1 - elif self.prerelease and other.prerelease: - if self.prerelease == other.prerelease: - return 0 - elif self.prerelease < other.prerelease: - return -1 - else: - return 1 - else: - raise AssertionError("never get here") - - -# end class StrictVersion - -# The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separated by a period or by -# sequences of letters. If only periods, then these are compared -# left-to-right to determine an ordering. -# 2) sequences of letters are part of the tuple for comparison and are -# compared lexicographically -# 3) recognize the numeric components may have leading zeroes -# -# The LooseVersion class below implements these rules: a version number -# string is split up into a tuple of integer and string components, and -# comparison is a simple tuple comparison. This means that version -# numbers behave in a predictable and obvious way, but a way that might -# not necessarily be how people *want* version numbers to behave. There -# wouldn't be a problem if people could stick to purely numeric version -# numbers: just split on period and compare the numbers as tuples. -# However, people insist on putting letters into their version numbers; -# the most common purpose seems to be: -# - indicating a "pre-release" version -# ('alpha', 'beta', 'a', 'b', 'pre', 'p') -# - indicating a post-release patch ('p', 'pl', 'patch') -# but of course this can't cover all version number schemes, and there's -# no way to know what a programmer means without asking him. -# -# The problem is what to do with letters (and other non-numeric -# characters) in a version number. The current implementation does the -# obvious and predictable thing: keep them as strings and compare -# lexically within a tuple comparison. This has the desired effect if -# an appended letter sequence implies something "post-release": -# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". -# -# However, if letters in a version number imply a pre-release version, -# the "obvious" thing isn't correct. Eg. you would expect that -# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison -# implemented here, this just isn't so. -# -# Two possible solutions come to mind. The first is to tie the -# comparison algorithm to a particular set of semantic rules, as has -# been done in the StrictVersion class above. This works great as long -# as everyone can go along with bondage and discipline. Hopefully a -# (large) subset of Python module programmers will agree that the -# particular flavour of bondage and discipline provided by StrictVersion -# provides enough benefit to be worth using, and will submit their -# version numbering scheme to its domination. The free-thinking -# anarchists in the lot will never give in, though, and something needs -# to be done to accommodate them. -# -# Perhaps a "moderately strict" version class could be implemented that -# lets almost anything slide (syntactically), and makes some heuristic -# assumptions about non-digits in version number strings. This could -# sink into special-case-hell, though; if I was as talented and -# idiosyncratic as Larry Wall, I'd go ahead and implement a class that -# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is -# just as happy dealing with things like "2g6" and "1.13++". I don't -# think I'm smart enough to do it right though. -# -# In any case, I've coded the test suite for this module (see -# ../test/test_version.py) specifically to fail on things like comparing -# "1.2a2" and "1.2". That's not because the *code* is doing anything -# wrong, it's because the simple, obvious design doesn't match my -# complicated, hairy expectations for real-world version numbers. It -# would be a snap to fix the test suite to say, "Yep, LooseVersion does -# the Right Thing" (ie. the code matches the conception). But I'd rather -# have a conception that matches common notions about version numbers. - - -class LooseVersion(Version): - """Version numbering for anarchists and software realists. - Implements the standard interface for version number classes as - described above. A version number consists of a series of numbers, - separated by either periods or strings of letters. When comparing - version numbers, the numeric components will be compared - numerically, and the alphabetic components lexically. The following - are all valid version numbers, in no particular order: - - 1.5.1 - 1.5.2b2 - 161 - 3.10a - 8.02 - 3.4j - 1996.07.12 - 3.2.pl0 - 3.1.1.6 - 2g6 - 11g - 0.960923 - 2.2beta29 - 1.13++ - 5.5.kw - 2.0b1pl0 - - In fact, there is no such thing as an invalid version number under - this scheme; the rules for comparison are simple and predictable, - but may not always give the results you want (for some definition - of "want"). - """ - - component_re = re.compile(r"(\d+ | [a-z]+ | \.)", re.VERBOSE) - - def __init__(self, vstring=None): - if vstring: - self.parse(vstring) - - def parse(self, vstring): - # I've given up on thinking I can reconstruct the version string - # from the parsed tuple -- so I just store the string here for - # use by __str__ - self.vstring = vstring - components = [x for x in self.component_re.split(vstring) if x and x != "."] - for i, obj in enumerate(components): - try: - components[i] = int(obj) - except ValueError: - pass - - self.version = components - - def __str__(self): - return self.vstring - - def __repr__(self): - return "LooseVersion ('%s')" % str(self) - - def _cmp(self, other): - if isinstance(other, str): - other = LooseVersion(other) - elif not isinstance(other, LooseVersion): - return NotImplemented - - if self.version == other.version: - return 0 - if self.version < other.version: - return -1 - if self.version > other.version: - return 1 - - -# end class LooseVersion diff --git a/plugins/module_utils/botocore.py b/plugins/module_utils/botocore.py index 8f6296a3a5b..c04b27d53a9 100644 --- a/plugins/module_utils/botocore.py +++ b/plugins/module_utils/botocore.py @@ -47,6 +47,13 @@ BOTO3_IMP_ERR = traceback.format_exc() HAS_BOTO3 = False +try: + from packaging.version import Version + + HAS_PACKAGING = True +except ImportError: + HAS_PACKAGING = False + from ansible.module_utils._text import to_native from ansible.module_utils.ansible_release import __version__ from ansible.module_utils.basic import missing_required_lib @@ -55,7 +62,6 @@ from .exceptions import AnsibleBotocoreError from .retries import AWSRetry -from .version import LooseVersion from .common import get_collection_info MINIMUM_BOTOCORE_VERSION = "1.25.0" @@ -444,6 +450,10 @@ def check_sdk_version_supported(botocore_version=None, boto3_version=None, warn= supported = True + if not HAS_PACKAGING: + if warn: + warn("packaging.version Python module not installed, unable to check AWS SDK versions") + return True if not botocore_at_least(botocore_version): supported = False if warn: @@ -456,6 +466,12 @@ def check_sdk_version_supported(botocore_version=None, boto3_version=None, warn= return supported +def _version_at_least(a, b): + if not HAS_PACKAGING: + return True + return Version(a) >= Version(b) + + def boto3_at_least(desired): """Check if the available boto3 version is greater than or equal to a desired version. @@ -465,7 +481,7 @@ def boto3_at_least(desired): module.fail_json(msg="Boto3 can't deal with EC2 IPv6 addresses before version 1.4.4.") """ existing = gather_sdk_versions() - return LooseVersion(existing["boto3_version"]) >= LooseVersion(desired) + return _version_at_least(existing["boto3_version"], desired) def botocore_at_least(desired): @@ -479,4 +495,4 @@ def botocore_at_least(desired): 'To wait until Service X resources are fully available, update botocore.') """ existing = gather_sdk_versions() - return LooseVersion(existing["botocore_version"]) >= LooseVersion(desired) + return _version_at_least(existing["botocore_version"], desired) diff --git a/plugins/module_utils/version.py b/plugins/module_utils/version.py index 51c77536aee..444bde5d6ee 100644 --- a/plugins/module_utils/version.py +++ b/plugins/module_utils/version.py @@ -5,9 +5,6 @@ """Provide version object to compare version numbers.""" -# Once we drop support for Ansible 2.9, ansible-base 2.10, and ansible-core 2.11, we can -# remove the _version.py file, and replace the following import by -# -# from ansible.module_utils.compat.version import LooseVersion - -from ._version import LooseVersion # pylint: disable=unused-import +# This should be directly imported by modules, rather than importing from here. +# The import is being kept for backwards compatibility. +from ansible.module_utils.compat.version import LooseVersion # pylint: disable=unused-import From 82162752ed79c810e16e0801a14b2126e3b6506b Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 26 Jul 2023 11:24:14 +0200 Subject: [PATCH 3/7] Allow user to associate rds cluster with a global rds cluster by passing GlobalClusterIdentifier (#1663) Allow user to associate rds cluster with a global rds cluster SUMMARY Allow user to associate rds cluster with a global rds cluster ISSUE TYPE Bugfix Pull Request COMPONENT NAME rds_cluster ADDITIONAL INFORMATION Reviewed-by: Jill R Reviewed-by: Mandar Kulkarni --- changelogs/fragments/20230725-rds_cluster-fix.yml | 2 ++ plugins/modules/rds_cluster.py | 1 + 2 files changed, 3 insertions(+) create mode 100644 changelogs/fragments/20230725-rds_cluster-fix.yml diff --git a/changelogs/fragments/20230725-rds_cluster-fix.yml b/changelogs/fragments/20230725-rds_cluster-fix.yml new file mode 100644 index 00000000000..9070a63cdb6 --- /dev/null +++ b/changelogs/fragments/20230725-rds_cluster-fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - rds_cluster - Allow to pass GlobalClusterIdentifier to rds cluster on creation (https://github.com/ansible-collections/amazon.aws/pull/1663)." diff --git a/plugins/modules/rds_cluster.py b/plugins/modules/rds_cluster.py index 3cc781a8bb2..5609654a810 100644 --- a/plugins/modules/rds_cluster.py +++ b/plugins/modules/rds_cluster.py @@ -770,6 +770,7 @@ def get_create_options(params_dict): "Domain", "DomainIAMRoleName", "EnableGlobalWriteForwarding", + "GlobalClusterIdentifier", ] return dict((k, v) for k, v in params_dict.items() if k in options and v is not None) From 70aafdd9ab53fede7d948c89382125e98aa1bc11 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 31 Jul 2023 14:05:33 +0200 Subject: [PATCH 4/7] Add AllocatedStorage, DBClusterInstanceClass, StorageType, Iops, and EngineMode to the list of parameters that can be passed when creating or modifying a Multi-AZ RDS cluster. (#1657) rds_cluster - enable creation or modification of AllocatedStorage, DBClusterInstanceClass, StorageType, Iops, and EngineMode SUMMARY Add AllocatedStorage, DBClusterInstanceClass, StorageType, Iops and EngineMode to the list of parameters that can be passed when creating or modifying a Multi-AZ RDS cluster. ISSUE TYPE Bugfix Pull Request COMPONENT NAME rds_cluster Reviewed-by: Taeho Park Reviewed-by: Mike Graves --- .../20230713-rds_cluster-fix_params_passage.yml | 2 ++ plugins/modules/rds_cluster.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/20230713-rds_cluster-fix_params_passage.yml diff --git a/changelogs/fragments/20230713-rds_cluster-fix_params_passage.yml b/changelogs/fragments/20230713-rds_cluster-fix_params_passage.yml new file mode 100644 index 00000000000..ddac3a69de2 --- /dev/null +++ b/changelogs/fragments/20230713-rds_cluster-fix_params_passage.yml @@ -0,0 +1,2 @@ +bugfixes: + - rds_cluster - Add ``AllocatedStorage``, ``DBClusterInstanceClass``, ``StorageType``, ``Iops``, and ``EngineMode`` to the list of parameters that can be passed when creating or modifying a Multi-AZ RDS cluster (https://github.com/ansible-collections/amazon.aws/pull/1657). diff --git a/plugins/modules/rds_cluster.py b/plugins/modules/rds_cluster.py index 5609654a810..7acf6717f56 100644 --- a/plugins/modules/rds_cluster.py +++ b/plugins/modules/rds_cluster.py @@ -771,6 +771,11 @@ def get_create_options(params_dict): "DomainIAMRoleName", "EnableGlobalWriteForwarding", "GlobalClusterIdentifier", + "AllocatedStorage", + "DBClusterInstanceClass", + "StorageType", + "Iops", + "EngineMode", ] return dict((k, v) for k, v in params_dict.items() if k in options and v is not None) @@ -800,6 +805,11 @@ def get_modify_options(params_dict, force_update_password): "EnableGlobalWriteForwarding", "Domain", "DomainIAMRoleName", + "AllocatedStorage", + "DBClusterInstanceClass", + "StorageType", + "Iops", + "EngineMode", ] modify_options = dict((k, v) for k, v in params_dict.items() if k in options and v is not None) if not force_update_password: @@ -1029,6 +1039,7 @@ def ensure_present(cluster, parameters, method_name, method_options_name): if not cluster: if parameters.get("Tags") is not None: parameters["Tags"] = ansible_dict_to_boto3_tag_list(parameters["Tags"]) + call_method(client, module, method_name, eval(method_options_name)(parameters)) changed = True else: @@ -1215,7 +1226,6 @@ def main(): ) parameters = arg_spec_to_rds_params(dict((k, module.params[k]) for k in module.params if k in parameter_options)) - changed = False method_name, method_options_name = get_rds_method_attribute_name(cluster) From ca9eb87af328ac4afe371d94fdaaa23de02261ee Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Mon, 31 Jul 2023 18:36:38 +0200 Subject: [PATCH 5/7] Update .github/workflows/units.yml to use defaults from https://github.com/ansible-network/github_actions/blob/main/.github/workflows/unit_source.yml Signed-off-by: Alina Buzachis --- .github/workflows/units.yml | 60 ------------------------------------- 1 file changed, 60 deletions(-) diff --git a/.github/workflows/units.yml b/.github/workflows/units.yml index adfa2dddd1f..d05d8c10294 100644 --- a/.github/workflows/units.yml +++ b/.github/workflows/units.yml @@ -6,63 +6,3 @@ on: [workflow_call] # allow this workflow to be called from other workflows jobs: unit-source: uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main - with: - matrix_exclude: >- - [ - { - "python-version": "3.11" - }, - { - "ansible-version": "stable-2.12", - "python-version": "3.7" - }, - { - "ansible-version": "stable-2.13", - "python-version": "3.7" - }, - { - "ansible-version": "stable-2.12", - "python-version": "3.8" - }, - { - "ansible-version": "stable-2.13", - "python-version": "3.8" - }, - { - "ansible-version": "stable-2.14", - "python-version": "3.7" - }, - { - "ansible-version": "stable-2.14", - "python-version": "3.8" - }, - { - "ansible-version": "stable-2.15", - "python-version": "3.7" - }, - { - "ansible-version": "stable-2.15", - "python-version": "3.8" - }, - { - "ansible-version": "milestone", - "python-version": "3.7" - }, - { - "ansible-version": "milestone", - "python-version": "3.8" - }, - { - "ansible-version": "devel", - "python-version": "3.7" - }, - { - "ansible-version": "devel", - "python-version": "3.8" - }, - { - "ansible-version": "devel", - "python-version": "3.9" - } - ] - collection_pre_install: '' From 31c750691949b2271324eef187928680a2ee3888 Mon Sep 17 00:00:00 2001 From: Brant Evans Date: Tue, 1 Aug 2023 06:44:37 -0700 Subject: [PATCH 6/7] Default filters to empty dictionary (#1670) Default filters to empty dictionary SUMMARY Changes the default for the filters option from None to an empty dictionary. Fixes: #1668 ISSUE TYPE Bugfix Pull Request COMPONENT NAME ec2_vpc_route_table_info ADDITIONAL INFORMATION This matches what other *info modules (e.g. ec2_vpc_endpoint_info or ec2_vpc_subnet_info) do for the filters option default. Reviewed-by: Alina Buzachis Reviewed-by: Brant Evans Reviewed-by: Mark Chappell Reviewed-by: Mike Graves --- changelogs/fragments/ec2_vpc_route_table_info-filter-fix.yml | 2 ++ plugins/modules/ec2_vpc_route_table_info.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/ec2_vpc_route_table_info-filter-fix.yml diff --git a/changelogs/fragments/ec2_vpc_route_table_info-filter-fix.yml b/changelogs/fragments/ec2_vpc_route_table_info-filter-fix.yml new file mode 100644 index 00000000000..9b3d315dcca --- /dev/null +++ b/changelogs/fragments/ec2_vpc_route_table_info-filter-fix.yml @@ -0,0 +1,2 @@ +bugfixes: + - ec2_vpc_route_table_info - default filters to empty dictionary (https://github.com/ansible-collections/amazon.aws/issues/1668). diff --git a/plugins/modules/ec2_vpc_route_table_info.py b/plugins/modules/ec2_vpc_route_table_info.py index 0e5bfb329c7..21c9fc6674a 100644 --- a/plugins/modules/ec2_vpc_route_table_info.py +++ b/plugins/modules/ec2_vpc_route_table_info.py @@ -20,6 +20,7 @@ - A dict of filters to apply. Each dict item consists of a filter key and a filter value. See U(https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeRouteTables.html) for possible filters. type: dict + default: {} extends_documentation_fragment: - amazon.aws.common.modules - amazon.aws.region.modules @@ -260,7 +261,7 @@ def list_ec2_vpc_route_tables(connection, module): def main(): argument_spec = dict( - filters=dict(default=None, type="dict"), + filters=dict(default={}, type="dict"), ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) From 625777a125f6f0cad6035dcf166469684541185d Mon Sep 17 00:00:00 2001 From: Taeho Park <113317744+taehopark32@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:42:04 -0400 Subject: [PATCH 7/7] route53_health_check - add support for CALCULATED type (#1631) route53_health_check - add support for CALCULATED type SUMMARY Fixes #1442 ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/modules/route53_health_check.py ADDITIONAL INFORMATION Reviewed-by: Helen Bailey Reviewed-by: Taeho Park Reviewed-by: Alina Buzachis Reviewed-by: Mike Graves --- ...route53_health_check-added-calculcated.yml | 5 + plugins/modules/route53_health_check.py | 84 ++++++++-- .../tasks/calculate_health_check.yml | 156 ++++++++++++++++++ .../route53_health_check/tasks/main.yml | 3 + 4 files changed, 233 insertions(+), 15 deletions(-) create mode 100644 changelogs/fragments/1631-route53_health_check-added-calculcated.yml create mode 100644 tests/integration/targets/route53_health_check/tasks/calculate_health_check.yml diff --git a/changelogs/fragments/1631-route53_health_check-added-calculcated.yml b/changelogs/fragments/1631-route53_health_check-added-calculcated.yml new file mode 100644 index 00000000000..ca1cc62dcb8 --- /dev/null +++ b/changelogs/fragments/1631-route53_health_check-added-calculcated.yml @@ -0,0 +1,5 @@ +--- +minor_changes: + - route53_health_check - add support for another ``type`` choice called ``CALCULATED`` (https://github.com/ansible-collections/amazon.aws/pull/1631). + - route53_health_check - add support for a string list parameter called ``child_health_checks`` to specify health checks that must be healthy for the calculated health check (https://github.com/ansible-collections/amazon.aws/pull/1631). + - route53_health_check - add support for an integer parameter called ``health_threshold`` to specify the minimum number of healthy child health checks that must be healthy for the calculated health check (https://github.com/ansible-collections/amazon.aws/pull/1631). \ No newline at end of file diff --git a/plugins/modules/route53_health_check.py b/plugins/modules/route53_health_check.py index 99efc0143a0..b9325cae418 100644 --- a/plugins/modules/route53_health_check.py +++ b/plugins/modules/route53_health_check.py @@ -45,8 +45,22 @@ - The type of health check that you want to create, which indicates how Amazon Route 53 determines whether an endpoint is healthy. - Once health_check is created, type can not be changed. - choices: [ 'HTTP', 'HTTPS', 'HTTP_STR_MATCH', 'HTTPS_STR_MATCH', 'TCP' ] + - The CALCULATED choice was added in 6.3.0. + choices: [ 'HTTP', 'HTTPS', 'HTTP_STR_MATCH', 'HTTPS_STR_MATCH', 'TCP', 'CALCULATED' ] type: str + child_health_checks: + description: + - The child health checks used for a calculated health check. + - This parameter takes in the child health checks ids. + type: list + elements: str + version_added: 6.3.0 + health_threshold: + description: + - The minimum number of healthy child health checks for a calculated health check to be considered healthy. + default: 1 + type: int + version_added: 6.3.0 resource_path: description: - The path that you want Amazon Route 53 to request when performing @@ -373,7 +387,9 @@ def delete_health_check(check_id): return True, "delete" -def create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in): +def create_health_check( + ip_addr_in, fqdn_in, type_in, request_interval_in, port_in, child_health_checks_in, health_threshold_in +): # In general, if a request is repeated with the same CallerRef it won't # result in a duplicate check appearing. This means we can safely use our # retry decorators @@ -382,8 +398,6 @@ def create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_ health_check = dict( Type=type_in, - RequestInterval=request_interval_in, - Port=port_in, ) if module.params.get("disabled") is not None: health_check["Disabled"] = module.params.get("disabled") @@ -391,6 +405,8 @@ def create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_ health_check["IPAddress"] = ip_addr_in if fqdn_in: health_check["FullyQualifiedDomainName"] = fqdn_in + if port_in: + health_check["Port"] = port_in if type_in in ["HTTP", "HTTPS", "HTTP_STR_MATCH", "HTTPS_STR_MATCH"]: resource_path = module.params.get("resource_path") @@ -404,10 +420,19 @@ def create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_ missing_args.append("string_match") health_check["SearchString"] = module.params.get("string_match") - failure_threshold = module.params.get("failure_threshold") - if not failure_threshold: - failure_threshold = 3 - health_check["FailureThreshold"] = failure_threshold + if type_in == "CALCULATED": + if not child_health_checks_in: + missing_args.append("child_health_checks") + if not health_threshold_in: + missing_args.append("health_threshold") + health_check["ChildHealthChecks"] = child_health_checks_in + health_check["HealthThreshold"] = health_threshold_in + else: + failure_threshold = module.params.get("failure_threshold") + if not failure_threshold: + failure_threshold = 3 + health_check["FailureThreshold"] = failure_threshold + health_check["RequestInterval"] = request_interval_in if module.params.get("measure_latency") is not None: health_check["MeasureLatency"] = module.params.get("measure_latency") @@ -442,6 +467,8 @@ def update_health_check(existing_check): # - IPAddress # - Port # - FullyQualifiedDomainName + # - ChildHealthChecks + # - HealthThreshold changes = dict() existing_config = existing_check.get("HealthCheckConfig") @@ -455,9 +482,11 @@ def update_health_check(existing_check): if search_string and search_string != existing_config.get("SearchString"): changes["SearchString"] = search_string - failure_threshold = module.params.get("failure_threshold", None) - if failure_threshold and failure_threshold != existing_config.get("FailureThreshold"): - changes["FailureThreshold"] = failure_threshold + type_in = module.params.get("type", None) + if type_in != "CALCULATED": + failure_threshold = module.params.get("failure_threshold", None) + if failure_threshold and failure_threshold != existing_config.get("FailureThreshold"): + changes["FailureThreshold"] = failure_threshold disabled = module.params.get("disabled", None) if disabled is not None and disabled != existing_config.get("Disabled"): @@ -477,6 +506,15 @@ def update_health_check(existing_check): if fqdn is not None and fqdn != existing_config.get("FullyQualifiedDomainName"): changes["FullyQualifiedDomainName"] = module.params.get("fqdn") + if type_in == "CALCULATED": + child_health_checks = module.params.get("child_health_checks", None) + if child_health_checks is not None and child_health_checks != existing_config.get("ChildHealthChecks"): + changes["ChildHealthChecks"] = module.params.get("child_health_checks") + + health_threshold = module.params.get("health_threshold", None) + if health_threshold is not None and health_threshold != existing_config.get("HealthThreshold"): + changes["HealthThreshold"] = module.params.get("health_threshold") + # No changes... if not changes: return False, None, check_id @@ -522,7 +560,9 @@ def main(): disabled=dict(type="bool"), ip_address=dict(), port=dict(type="int"), - type=dict(choices=["HTTP", "HTTPS", "HTTP_STR_MATCH", "HTTPS_STR_MATCH", "TCP"]), + type=dict(choices=["HTTP", "HTTPS", "HTTP_STR_MATCH", "HTTPS_STR_MATCH", "TCP", "CALCULATED"]), + child_health_checks=dict(type="list", elements="str"), + health_threshold=dict(type="int", default=1), resource_path=dict(), fqdn=dict(), string_match=dict(), @@ -537,11 +577,12 @@ def main(): ) args_one_of = [ - ["ip_address", "fqdn", "health_check_id"], + ["ip_address", "fqdn", "health_check_id", "child_health_checks"], ] args_if = [ ["type", "TCP", ("port",)], + ["type", "CALCULATED", ("child_health_checks", "health_threshold")], ] args_required_together = [ @@ -550,6 +591,9 @@ def main(): args_mutually_exclusive = [ ["health_check_id", "health_check_name"], + ["child_health_checks", "ip_address"], + ["child_health_checks", "port"], + ["child_health_checks", "fqdn"], ] global module @@ -577,6 +621,8 @@ def main(): health_check_name = module.params.get("health_check_name") tags = module.params.get("tags") purge_tags = module.params.get("purge_tags") + child_health_checks_in = module.params.get("child_health_checks") + health_threshold_in = module.params.get("health_threshold") # Default port if port_in is None: @@ -624,7 +670,9 @@ def main(): # Create Health Check elif state_in == "present": if existing_check is None and not module.params.get("use_unique_names") and not update_delete_by_id: - changed, action, check_id = create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in) + changed, action, check_id = create_health_check( + ip_addr_in, fqdn_in, type_in, request_interval_in, port_in, child_health_checks_in, health_threshold_in + ) # Update Health Check else: @@ -642,7 +690,13 @@ def main(): else: # create a new health_check if another health check with same name does not exists changed, action, check_id = create_health_check( - ip_addr_in, fqdn_in, type_in, request_interval_in, port_in + ip_addr_in, + fqdn_in, + type_in, + request_interval_in, + port_in, + child_health_checks_in, + health_threshold_in, ) else: diff --git a/tests/integration/targets/route53_health_check/tasks/calculate_health_check.yml b/tests/integration/targets/route53_health_check/tasks/calculate_health_check.yml new file mode 100644 index 00000000000..99a27dd232b --- /dev/null +++ b/tests/integration/targets/route53_health_check/tasks/calculate_health_check.yml @@ -0,0 +1,156 @@ +--- +- block: + # Create Health Check ================================================================= + - name: 'Create Health Check with name' + amazon.aws.route53_health_check: + state: present + name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations' + ip_address: '{{ ip_address }}' + port: '{{ port }}' + type: '{{ type_http }}' + resource_path: '{{ resource_path }}' + use_unique_names: true + fqdn: '{{ fqdn }}' + register: create_result + + # Create and Update =================================================================== + - name: 'Create Invalid Parameter Calculated Health Check' + route53_health_check: + health_check_name: "calculated_health_check" + ip_address: '{{ ip_address }}' + port: '{{ port }}' + type: CALCULATED + use_unique_names: true + fqdn: '{{ fqdn }}' + health_threshold: 1 + child_health_checks: '{{ create_result.health_check.id }}' + ignore_errors: true + register: error_create_calculated + + - name: 'Check result - Create Invalid Parameter Calculated Health Check' + ansible.builtin.assert: + that: + - error_create_calculated is failed + - "error_create_calculated.msg == 'parameters are mutually exclusive: child_health_checks|ip_address, child_health_checks|port, child_health_checks|fqdn'" + + - name: 'Create Calculated Health Check - check_mode' + route53_health_check: + health_check_name: "calculated_health_check" + use_unique_names: true + type: CALCULATED + health_threshold: 1 + child_health_checks: '{{ create_result.health_check.id }}' + register: check_create_calculated + check_mode: true + + - name: 'Check result - Calculated Health Check' + ansible.builtin.assert: + that: + - check_create_calculated is not failed + - check_create_calculated is changed + + - name: 'Create Calculated Health Check' + route53_health_check: + health_check_name: "calculated_health_check" + use_unique_names: true + type: CALCULATED + health_threshold: 1 + child_health_checks: '{{ create_result.health_check.id }}' + register: create_calculated + + - name: 'Check result - Calculated Health Check' + ansible.builtin.assert: + that: + - create_calculated is not failed + - create_calculated is changed + + - name: 'Check result - Create Calculated Health Check - idempotency' + route53_health_check: + health_check_name: "calculated_health_check" + use_unique_names: true + type: CALCULATED + health_threshold: 1 + child_health_checks: '{{ create_result.health_check.id }}' + register: create_idem + + - name: 'Check result - Calculated Health Check - idempotency' + ansible.builtin.assert: + that: + - create_idem is not failed + - create_idem is not changed + + - name: 'Update Calculated Health Check' + route53_health_check: + health_check_name: "calculated_health_check" + use_unique_names: true + type: CALCULATED + health_threshold: 2 + child_health_checks: '{{ create_result.health_check.id }}' + register: check_updated_calculated + check_mode: true + + - name: 'Check result - Update Calculated Health Check - check_mode' + ansible.builtin.assert: + that: + - check_updated_calculated is not failed + - check_updated_calculated is changed + + - name: 'Update Calculated Health Check' + route53_health_check: + health_check_name: "calculated_health_check" + use_unique_names: true + type: CALCULATED + health_threshold: 2 + child_health_checks: '{{ create_result.health_check.id }}' + register: updated_calculated + + - name: 'Check result - Update Calculated Health Check' + ansible.builtin.assert: + that: + - updated_calculated is not failed + - updated_calculated is changed + + # Deleting Calculated Health Check ====================================================== + - name: 'Delete Calculated Health Check' + amazon.aws.route53_health_check: + state: absent + health_check_id: '{{ create_calculated.health_check.id }}' + register: deleted_calculated + + - name: 'Check if Calculated Health Check can be deleted' + ansible.builtin.assert: + that: + - deleted_calculated is not failed + - deleted_calculated is changed + + - name: 'Delete HTTP health check with use_unique_names' + amazon.aws.route53_health_check: + state: absent + name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations' + ip_address: '{{ ip_address }}' + port: '{{ port }}' + type: '{{ type_http }}' + resource_path: '{{ resource_path }}' + use_unique_names: true + fqdn: '{{ fqdn }}' + register: delete_result + + - name: 'Check if HTTP health check with use_unique_names can be deleted' + ansible.builtin.assert: + that: + - delete_result is changed + - delete_result is not failed + + always: + # Cleanup starts here ================================================================= + - name: 'Delete Calculated Health Check' + amazon.aws.route53_health_check: + state: absent + health_check_id: '{{ create_calculated.health_check.id }}' + ignore_errors: true + + - name: 'Delete HTTP health check with use_unique_names' + amazon.aws.route53_health_check: + state: absent + name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations' + ignore_errors: true diff --git a/tests/integration/targets/route53_health_check/tasks/main.yml b/tests/integration/targets/route53_health_check/tasks/main.yml index 4a13464e343..4a1752d9713 100644 --- a/tests/integration/targets/route53_health_check/tasks/main.yml +++ b/tests/integration/targets/route53_health_check/tasks/main.yml @@ -41,6 +41,9 @@ - name: Run tests for update and delete health check by ID include_tasks: update_delete_by_id.yml + - name: Run tests for create, update, and delete calculated health check + include_tasks: calculate_health_check.yml + # Minimum possible definition - name: 'Create a TCP health check - check_mode' route53_health_check: