-
Notifications
You must be signed in to change notification settings - Fork 398
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cloudwatchlogs_log_group - Tagging support (#1233)
cloudwatchlogs_log_group - Tagging support SUMMARY Ensure cloudwatchlogs_log_group returns values defined in RETURN docs Add support for updating tags (including purge_tags) split cloudwatchlogs_log_group tests Add some basic integration tests for cloudwatchlogs_log_group_info ISSUE TYPE Bugfix Pull Request Feature Pull Request COMPONENT NAME cloudwatchlogs_log_group cloudwatchlogs_log_group_info ADDITIONAL INFORMATION Reviewed-by: Joseph Torcasso <None> Reviewed-by: Mark Chappell <None>
- Loading branch information
Showing
9 changed files
with
554 additions
and
102 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
changelogs/fragments/1233-cloudwatchlogs_log_group-tagging.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
minor_changes: | ||
- cloudwatchlogs_log_group - now consistently returns the values as defined in the return documentation (https://github.com/ansible-collections/community.aws/pull/1233). | ||
- cloudwatchlogs_log_group - adds support for updating tags (https://github.com/ansible-collections/community.aws/pull/1233). | ||
- cloudwatchlogs_log_group - adds support for returning tags (https://github.com/ansible-collections/community.aws/pull/1233). | ||
- cloudwatchlogs_log_group_info - adds support for returning tags (https://github.com/ansible-collections/community.aws/pull/1233). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,58 +13,55 @@ | |
version_added: 1.0.0 | ||
short_description: create or delete log_group in CloudWatchLogs | ||
notes: | ||
- For details of the parameters and returns see U(http://boto3.readthedocs.io/en/latest/reference/services/logs.html). | ||
- For details of the parameters and returns see U(http://boto3.readthedocs.io/en/latest/reference/services/logs.html). | ||
- Support for I(purge_tags) was added in release 4.0.0. | ||
description: | ||
- Create or delete log_group in CloudWatchLogs. | ||
- Create or delete log_group in CloudWatchLogs. | ||
author: | ||
- Willian Ricardo (@willricardo) <[email protected]> | ||
- Willian Ricardo (@willricardo) <[email protected]> | ||
options: | ||
state: | ||
description: | ||
- Whether the rule is present or absent. | ||
choices: ["present", "absent"] | ||
default: present | ||
required: false | ||
type: str | ||
log_group_name: | ||
description: | ||
- The name of the log group. | ||
required: true | ||
type: str | ||
kms_key_id: | ||
description: | ||
- The Amazon Resource Name (ARN) of the CMK to use when encrypting log data. | ||
required: false | ||
type: str | ||
tags: | ||
description: | ||
- The key-value pairs to use for the tags. | ||
required: false | ||
type: dict | ||
retention: | ||
description: | ||
- The number of days to retain the log events in the specified log group. | ||
- "Valid values are: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]" | ||
- Mutually exclusive with I(purge_retention_policy). | ||
required: false | ||
type: int | ||
purge_retention_policy: | ||
description: | ||
- "Whether to purge the retention policy or not." | ||
- "Mutually exclusive with I(retention) and I(overwrite)." | ||
default: false | ||
required: false | ||
type: bool | ||
overwrite: | ||
description: | ||
- Whether an existing log group should be overwritten on create. | ||
- Mutually exclusive with I(purge_retention_policy). | ||
default: false | ||
required: false | ||
type: bool | ||
state: | ||
description: | ||
- Whether the rule is present or absent. | ||
choices: ["present", "absent"] | ||
default: present | ||
required: false | ||
type: str | ||
log_group_name: | ||
description: | ||
- The name of the log group. | ||
required: true | ||
type: str | ||
kms_key_id: | ||
description: | ||
- The Amazon Resource Name (ARN) of the CMK to use when encrypting log data. | ||
required: false | ||
type: str | ||
retention: | ||
description: | ||
- The number of days to retain the log events in the specified log group. | ||
- "Valid values are: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653]" | ||
- Mutually exclusive with I(purge_retention_policy). | ||
required: false | ||
type: int | ||
purge_retention_policy: | ||
description: | ||
- "Whether to purge the retention policy or not." | ||
- "Mutually exclusive with I(retention) and I(overwrite)." | ||
default: false | ||
required: false | ||
type: bool | ||
overwrite: | ||
description: | ||
- Whether an existing log group should be overwritten on create. | ||
- Mutually exclusive with I(purge_retention_policy). | ||
default: false | ||
required: false | ||
type: bool | ||
extends_documentation_fragment: | ||
- amazon.aws.aws | ||
- amazon.aws.ec2 | ||
- amazon.aws.aws | ||
- amazon.aws.ec2 | ||
- amazon.aws.tags | ||
''' | ||
|
||
|
@@ -96,6 +93,7 @@ | |
description: Return the list of complex objects representing log groups | ||
returned: success | ||
type: complex | ||
version_added: 4.0.0 | ||
contains: | ||
log_group_name: | ||
description: The name of the log group. | ||
|
@@ -125,6 +123,10 @@ | |
description: The Amazon Resource Name (ARN) of the CMK to use when encrypting log data. | ||
returned: always | ||
type: str | ||
tags: | ||
description: A dictionary representing the tags on the log group. | ||
returned: always | ||
type: dict | ||
''' | ||
|
||
try: | ||
|
@@ -135,6 +137,8 @@ | |
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict | ||
|
||
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule | ||
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code | ||
from ansible_collections.amazon.aws.plugins.module_utils.tagging import compare_aws_tags | ||
|
||
|
||
def create_log_group(client, log_group_name, kms_key_id, tags, retention, module): | ||
|
@@ -154,15 +158,11 @@ def create_log_group(client, log_group_name, kms_key_id, tags, retention, module | |
log_group_name=log_group_name, | ||
retention=retention, module=module) | ||
|
||
desc_log_group = describe_log_group(client=client, | ||
log_group_name=log_group_name, | ||
module=module) | ||
found_log_group = describe_log_group(client=client, log_group_name=log_group_name, module=module) | ||
|
||
if 'logGroups' in desc_log_group: | ||
for i in desc_log_group['logGroups']: | ||
if log_group_name == i['logGroupName']: | ||
return i | ||
module.fail_json(msg="The aws CloudWatchLogs log group was not created. \n please try again!") | ||
if not found_log_group: | ||
module.fail_json(msg="The aws CloudWatchLogs log group was not created. \n please try again!") | ||
return found_log_group | ||
|
||
|
||
def input_retention_policy(client, log_group_name, retention, module): | ||
|
@@ -187,35 +187,78 @@ def delete_retention_policy(client, log_group_name, module): | |
|
||
|
||
def delete_log_group(client, log_group_name, module): | ||
desc_log_group = describe_log_group(client=client, | ||
log_group_name=log_group_name, | ||
module=module) | ||
|
||
try: | ||
if 'logGroups' in desc_log_group: | ||
for i in desc_log_group['logGroups']: | ||
if log_group_name == i['logGroupName']: | ||
client.delete_log_group(logGroupName=log_group_name) | ||
|
||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: | ||
client.delete_log_group(logGroupName=log_group_name) | ||
except is_boto3_error_code('ResourceNotFoundException'): | ||
return {} | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except | ||
module.fail_json_aws(e, msg="Unable to delete log group {0}".format(log_group_name)) | ||
|
||
|
||
def describe_log_group(client, log_group_name, module): | ||
try: | ||
desc_log_group = client.describe_log_groups(logGroupNamePrefix=log_group_name) | ||
return desc_log_group | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: | ||
module.fail_json_aws(e, msg="Unable to describe log group {0}".format(log_group_name)) | ||
|
||
matching_logs = [log for log in desc_log_group.get('logGroups', []) if log['logGroupName'] == log_group_name] | ||
|
||
if not matching_logs: | ||
return {} | ||
|
||
found_log_group = matching_logs[0] | ||
|
||
try: | ||
tags = client.list_tags_log_group(logGroupName=log_group_name) | ||
except is_boto3_error_code('AccessDeniedException'): | ||
tags = {} | ||
module.warn('Permission denied listing tags for log group {0}'.format(log_group_name)) | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except | ||
module.fail_json_aws(e, msg="Unable to describe tags for log group {0}".format(log_group_name)) | ||
|
||
found_log_group['tags'] = tags.get('tags', {}) | ||
return found_log_group | ||
|
||
|
||
def format_result(found_log_group): | ||
# Prior to 4.0.0 we documented returning log_groups=[log_group], but returned **log_group | ||
# Return both to avoid a breaking change. | ||
log_group = camel_dict_to_snake_dict(found_log_group, ignore_list=['tags']) | ||
return dict(log_groups=[log_group], **log_group) | ||
|
||
|
||
def ensure_tags(client, found_log_group, desired_tags, purge_tags, module): | ||
if desired_tags is None: | ||
return False | ||
|
||
group_name = module.params.get('log_group_name') | ||
current_tags = found_log_group.get('tags', {}) | ||
tags_to_add, tags_to_remove = compare_aws_tags(current_tags, desired_tags, purge_tags) | ||
|
||
if not tags_to_add and not tags_to_remove: | ||
return False | ||
if module.check_mode: | ||
return True | ||
|
||
try: | ||
if tags_to_remove: | ||
client.untag_log_group(logGroupName=group_name, tags=tags_to_remove) | ||
if tags_to_add: | ||
client.tag_log_group(logGroupName=group_name, tags=tags_to_add) | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: | ||
module.fail_json_aws(e, msg='Failed to update tags') | ||
|
||
return True | ||
|
||
|
||
def main(): | ||
argument_spec = dict( | ||
log_group_name=dict(required=True, type='str'), | ||
state=dict(choices=['present', 'absent'], | ||
default='present'), | ||
kms_key_id=dict(required=False, type='str'), | ||
tags=dict(required=False, type='dict'), | ||
tags=dict(required=False, type='dict', aliases=['resource_tags']), | ||
purge_tags=dict(required=False, type='bool', default=True), | ||
retention=dict(required=False, type='int'), | ||
purge_retention_policy=dict(required=False, type='bool', default=False), | ||
overwrite=dict(required=False, type='bool', default=False), | ||
|
@@ -233,12 +276,7 @@ def main(): | |
changed = False | ||
|
||
# Determine if the log group exists | ||
desc_log_group = describe_log_group(client=logs, log_group_name=module.params['log_group_name'], module=module) | ||
found_log_group = {} | ||
for i in desc_log_group.get('logGroups', []): | ||
if module.params['log_group_name'] == i['logGroupName']: | ||
found_log_group = i | ||
break | ||
found_log_group = describe_log_group(client=logs, log_group_name=module.params['log_group_name'], module=module) | ||
|
||
if state == 'present': | ||
if found_log_group: | ||
|
@@ -251,20 +289,29 @@ def main(): | |
tags=module.params['tags'], | ||
retention=module.params['retention'], | ||
module=module) | ||
elif module.params['purge_retention_policy']: | ||
if found_log_group.get('retentionInDays'): | ||
changed = True | ||
delete_retention_policy(client=logs, | ||
log_group_name=module.params['log_group_name'], | ||
module=module) | ||
elif module.params['retention'] != found_log_group.get('retentionInDays'): | ||
if module.params['retention'] is not None: | ||
changed = True | ||
input_retention_policy(client=logs, | ||
log_group_name=module.params['log_group_name'], | ||
retention=module.params['retention'], | ||
module=module) | ||
found_log_group['retentionInDays'] = module.params['retention'] | ||
else: | ||
changed |= ensure_tags(client=logs, | ||
found_log_group=found_log_group, | ||
desired_tags=module.params['tags'], | ||
purge_tags=module.params['purge_tags'], | ||
module=module) | ||
if module.params['purge_retention_policy']: | ||
if found_log_group.get('retentionInDays'): | ||
changed = True | ||
delete_retention_policy(client=logs, | ||
log_group_name=module.params['log_group_name'], | ||
module=module) | ||
elif module.params['retention'] != found_log_group.get('retentionInDays'): | ||
if module.params['retention'] is not None: | ||
changed = True | ||
input_retention_policy(client=logs, | ||
log_group_name=module.params['log_group_name'], | ||
retention=module.params['retention'], | ||
module=module) | ||
if changed: | ||
found_log_group = describe_log_group(client=logs, | ||
log_group_name=module.params['log_group_name'], | ||
module=module) | ||
|
||
elif not found_log_group: | ||
changed = True | ||
|
@@ -275,7 +322,8 @@ def main(): | |
retention=module.params['retention'], | ||
module=module) | ||
|
||
module.exit_json(changed=changed, **camel_dict_to_snake_dict(found_log_group)) | ||
result = format_result(found_log_group) | ||
module.exit_json(changed=changed, **result) | ||
|
||
elif state == 'absent': | ||
if found_log_group: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,18 +13,17 @@ | |
version_added: 1.0.0 | ||
short_description: Get information about log_group in CloudWatchLogs | ||
description: | ||
- Lists the specified log groups. You can list all your log groups or filter the results by prefix. | ||
- Lists the specified log groups. You can list all your log groups or filter the results by prefix. | ||
author: | ||
- Willian Ricardo (@willricardo) <[email protected]> | ||
- Willian Ricardo (@willricardo) <[email protected]> | ||
options: | ||
log_group_name: | ||
description: | ||
- The name or prefix of the log group to filter by. | ||
type: str | ||
log_group_name: | ||
description: | ||
- The name or prefix of the log group to filter by. | ||
type: str | ||
extends_documentation_fragment: | ||
- amazon.aws.aws | ||
- amazon.aws.ec2 | ||
- amazon.aws.aws | ||
- amazon.aws.ec2 | ||
''' | ||
|
||
EXAMPLES = ''' | ||
|
@@ -67,6 +66,11 @@ | |
description: The Amazon Resource Name (ARN) of the CMK to use when encrypting log data. | ||
returned: always | ||
type: str | ||
tags: | ||
description: A dictionary representing the tags on the log group. | ||
returned: always | ||
type: dict | ||
version_added: 4.0.0 | ||
''' | ||
|
||
try: | ||
|
@@ -77,6 +81,7 @@ | |
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict | ||
|
||
from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule | ||
from ansible_collections.amazon.aws.plugins.module_utils.core import is_boto3_error_code | ||
|
||
|
||
def describe_log_group(client, log_group_name, module): | ||
|
@@ -86,10 +91,22 @@ def describe_log_group(client, log_group_name, module): | |
try: | ||
paginator = client.get_paginator('describe_log_groups') | ||
desc_log_group = paginator.paginate(**params).build_full_result() | ||
return desc_log_group | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: | ||
module.fail_json_aws(e, msg="Unable to describe log group {0}".format(log_group_name)) | ||
|
||
for log_group in desc_log_group['logGroups']: | ||
log_group_name = log_group['logGroupName'] | ||
try: | ||
tags = client.list_tags_log_group(logGroupName=log_group_name) | ||
except is_boto3_error_code('AccessDeniedException'): | ||
tags = {} | ||
module.warn('Permission denied listing tags for log group {0}'.format(log_group_name)) | ||
except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except | ||
module.fail_json_aws(e, msg="Unable to describe tags for log group {0}".format(log_group_name)) | ||
log_group['tags'] = tags.get('tags', {}) | ||
|
||
return desc_log_group | ||
|
||
|
||
def main(): | ||
argument_spec = dict( | ||
|
@@ -109,7 +126,7 @@ def main(): | |
final_log_group_snake = [] | ||
|
||
for log_group in desc_log_group['logGroups']: | ||
final_log_group_snake.append(camel_dict_to_snake_dict(log_group)) | ||
final_log_group_snake.append(camel_dict_to_snake_dict(log_group, ignore_list=['tags'])) | ||
|
||
desc_log_group_result = dict(changed=False, log_groups=final_log_group_snake) | ||
module.exit_json(**desc_log_group_result) | ||
|
Oops, something went wrong.