Skip to content

Commit

Permalink
route53_health_check - add support for CALCULATED type (ansible-colle…
Browse files Browse the repository at this point in the history
…ctions#1631)

route53_health_check - add support for CALCULATED type

SUMMARY

Fixes ansible-collections#1442

ISSUE TYPE


Feature Pull Request

COMPONENT NAME

plugins/modules/route53_health_check.py
ADDITIONAL INFORMATION

Reviewed-by: Helen Bailey <[email protected]>
Reviewed-by: Taeho Park
Reviewed-by: Alina Buzachis
Reviewed-by: Mike Graves <[email protected]>
  • Loading branch information
taehopark32 authored Aug 1, 2023
1 parent 31c7506 commit 625777a
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -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).
84 changes: 69 additions & 15 deletions plugins/modules/route53_health_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -382,15 +398,15 @@ 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")
if ip_addr_in:
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")
Expand All @@ -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")
Expand Down Expand Up @@ -442,6 +467,8 @@ def update_health_check(existing_check):
# - IPAddress
# - Port
# - FullyQualifiedDomainName
# - ChildHealthChecks
# - HealthThreshold

changes = dict()
existing_config = existing_check.get("HealthCheckConfig")
Expand All @@ -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"):
Expand All @@ -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
Expand Down Expand Up @@ -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(),
Expand All @@ -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 = [
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions tests/integration/targets/route53_health_check/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 625777a

Please sign in to comment.