mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-08-02 20:24:23 -07:00
add tagging to dynamodb_table.py (#20946)
* add tagging to dynamodb_table.py * fix doc syntax * address PR comments * add boto3 has tagging check
This commit is contained in:
parent
a5b12ff269
commit
34a3ab94d8
1 changed files with 67 additions and 3 deletions
|
@ -31,6 +31,7 @@ description:
|
||||||
author: Alan Loi (@loia)
|
author: Alan Loi (@loia)
|
||||||
requirements:
|
requirements:
|
||||||
- "boto >= 2.37.0"
|
- "boto >= 2.37.0"
|
||||||
|
- "boto3 >= 1.4.4 (for tagging)"
|
||||||
options:
|
options:
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
|
@ -84,6 +85,18 @@ options:
|
||||||
required: false
|
required: false
|
||||||
default: []
|
default: []
|
||||||
version_added: "2.1"
|
version_added: "2.1"
|
||||||
|
tags:
|
||||||
|
version_added: "2.3"
|
||||||
|
description:
|
||||||
|
- a hash/dictionary of tags to add to the new instance or for starting/stopping instance by tag; '{"key":"value"}' and '{"key":"value","key":"value"}'
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
wait_for_active_timeout:
|
||||||
|
version_added: "2.3"
|
||||||
|
description:
|
||||||
|
- how long before wait gives up, in seconds. only used when tags is set
|
||||||
|
required: false
|
||||||
|
default: 60
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- aws
|
- aws
|
||||||
- ec2
|
- ec2
|
||||||
|
@ -100,6 +113,8 @@ EXAMPLES = '''
|
||||||
range_key_type: NUMBER
|
range_key_type: NUMBER
|
||||||
read_capacity: 2
|
read_capacity: 2
|
||||||
write_capacity: 2
|
write_capacity: 2
|
||||||
|
tags:
|
||||||
|
tag_name: tag_value
|
||||||
|
|
||||||
# Update capacity on existing dynamo table
|
# Update capacity on existing dynamo table
|
||||||
- dynamodb_table:
|
- dynamodb_table:
|
||||||
|
@ -138,6 +153,7 @@ table_status:
|
||||||
sample: ACTIVE
|
sample: ACTIVE
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -159,6 +175,13 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_BOTO = False
|
HAS_BOTO = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
import botocore
|
||||||
|
from ansible.module_utils.ec2 import ansible_dict_to_boto3_tag_list, boto3_conn
|
||||||
|
HAS_BOTO3 = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_BOTO3 = False
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.ec2 import AnsibleAWSError, connect_to_aws, ec2_argument_spec, get_aws_connection_info
|
from ansible.module_utils.ec2 import AnsibleAWSError, connect_to_aws, ec2_argument_spec, get_aws_connection_info
|
||||||
|
|
||||||
|
@ -169,7 +192,7 @@ INDEX_OPTIONS = INDEX_REQUIRED_OPTIONS + ['hash_key_type', 'range_key_name', 'ra
|
||||||
INDEX_TYPE_OPTIONS = ['all', 'global_all', 'global_include', 'global_keys_only', 'include', 'keys_only']
|
INDEX_TYPE_OPTIONS = ['all', 'global_all', 'global_include', 'global_keys_only', 'include', 'keys_only']
|
||||||
|
|
||||||
|
|
||||||
def create_or_update_dynamo_table(connection, module):
|
def create_or_update_dynamo_table(connection, module, boto3_dynamodb=None, boto3_sts=None):
|
||||||
table_name = module.params.get('name')
|
table_name = module.params.get('name')
|
||||||
hash_key_name = module.params.get('hash_key_name')
|
hash_key_name = module.params.get('hash_key_name')
|
||||||
hash_key_type = module.params.get('hash_key_type')
|
hash_key_type = module.params.get('hash_key_type')
|
||||||
|
@ -178,6 +201,9 @@ def create_or_update_dynamo_table(connection, module):
|
||||||
read_capacity = module.params.get('read_capacity')
|
read_capacity = module.params.get('read_capacity')
|
||||||
write_capacity = module.params.get('write_capacity')
|
write_capacity = module.params.get('write_capacity')
|
||||||
all_indexes = module.params.get('indexes')
|
all_indexes = module.params.get('indexes')
|
||||||
|
region = module.params.get('region')
|
||||||
|
tags = module.params.get('tags')
|
||||||
|
wait_for_active_timeout = module.params.get('wait_for_active_timeout')
|
||||||
|
|
||||||
for index in all_indexes:
|
for index in all_indexes:
|
||||||
validate_index(index, module)
|
validate_index(index, module)
|
||||||
|
@ -192,7 +218,7 @@ def create_or_update_dynamo_table(connection, module):
|
||||||
indexes, global_indexes = get_indexes(all_indexes)
|
indexes, global_indexes = get_indexes(all_indexes)
|
||||||
|
|
||||||
result = dict(
|
result = dict(
|
||||||
region=module.params.get('region'),
|
region=region,
|
||||||
table_name=table_name,
|
table_name=table_name,
|
||||||
hash_key_name=hash_key_name,
|
hash_key_name=hash_key_name,
|
||||||
hash_key_type=hash_key_type,
|
hash_key_type=hash_key_type,
|
||||||
|
@ -217,6 +243,13 @@ def create_or_update_dynamo_table(connection, module):
|
||||||
if not module.check_mode:
|
if not module.check_mode:
|
||||||
result['table_status'] = table.describe()['Table']['TableStatus']
|
result['table_status'] = table.describe()['Table']['TableStatus']
|
||||||
|
|
||||||
|
if tags:
|
||||||
|
# only tables which are active can be tagged
|
||||||
|
wait_until_table_active(module, table, wait_for_active_timeout)
|
||||||
|
account_id = get_account_id(boto3_sts)
|
||||||
|
boto3_dynamodb.tag_resource(ResourceArn='arn:aws:dynamodb:' + region + ':' + account_id + ':table/' + table_name, Tags=ansible_dict_to_boto3_tag_list(tags))
|
||||||
|
result['tags'] = tags
|
||||||
|
|
||||||
except BotoServerError:
|
except BotoServerError:
|
||||||
result['msg'] = 'Failed to create/update dynamo table due to error: ' + traceback.format_exc()
|
result['msg'] = 'Failed to create/update dynamo table due to error: ' + traceback.format_exc()
|
||||||
module.fail_json(**result)
|
module.fail_json(**result)
|
||||||
|
@ -224,6 +257,19 @@ def create_or_update_dynamo_table(connection, module):
|
||||||
module.exit_json(**result)
|
module.exit_json(**result)
|
||||||
|
|
||||||
|
|
||||||
|
def get_account_id(boto3_sts):
|
||||||
|
return boto3_sts.get_caller_identity()["Account"]
|
||||||
|
|
||||||
|
|
||||||
|
def wait_until_table_active(module, table, wait_timeout):
|
||||||
|
max_wait_time = time.time() + wait_timeout
|
||||||
|
while (max_wait_time > time.time()) and (table.describe()['Table']['TableStatus'] != 'ACTIVE'):
|
||||||
|
time.sleep(5)
|
||||||
|
if max_wait_time <= time.time():
|
||||||
|
# waiting took too long
|
||||||
|
module.fail_json(msg="timed out waiting for table to exist")
|
||||||
|
|
||||||
|
|
||||||
def delete_dynamo_table(connection, module):
|
def delete_dynamo_table(connection, module):
|
||||||
table_name = module.params.get('name')
|
table_name = module.params.get('name')
|
||||||
|
|
||||||
|
@ -398,6 +444,8 @@ def main():
|
||||||
read_capacity=dict(default=1, type='int'),
|
read_capacity=dict(default=1, type='int'),
|
||||||
write_capacity=dict(default=1, type='int'),
|
write_capacity=dict(default=1, type='int'),
|
||||||
indexes=dict(default=[], type='list'),
|
indexes=dict(default=[], type='list'),
|
||||||
|
tags = dict(type='dict'),
|
||||||
|
wait_for_active_timeout = dict(default=60, type='int'),
|
||||||
))
|
))
|
||||||
|
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
|
@ -407,6 +455,9 @@ def main():
|
||||||
if not HAS_BOTO:
|
if not HAS_BOTO:
|
||||||
module.fail_json(msg='boto required for this module')
|
module.fail_json(msg='boto required for this module')
|
||||||
|
|
||||||
|
if not HAS_BOTO3 and module.params.get('tags'):
|
||||||
|
module.fail_json(msg='boto3 required when using tags for this module')
|
||||||
|
|
||||||
region, ec2_url, aws_connect_params = get_aws_connection_info(module)
|
region, ec2_url, aws_connect_params = get_aws_connection_info(module)
|
||||||
if not region:
|
if not region:
|
||||||
module.fail_json(msg='region must be specified')
|
module.fail_json(msg='region must be specified')
|
||||||
|
@ -416,9 +467,22 @@ def main():
|
||||||
except (NoAuthHandlerFound, AnsibleAWSError) as e:
|
except (NoAuthHandlerFound, AnsibleAWSError) as e:
|
||||||
module.fail_json(msg=str(e))
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
if module.params.get('tags'):
|
||||||
|
try:
|
||||||
|
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
|
||||||
|
boto3_dynamodb = boto3_conn(module, conn_type='client', resource='dynamodb', region=region, endpoint=ec2_url, **aws_connect_kwargs)
|
||||||
|
if not hasattr(boto3_dynamodb, 'tag_resource'):
|
||||||
|
module.fail_json(msg='boto3 connection does not have tag_resource(), likely due to using an old version')
|
||||||
|
boto3_sts = boto3_conn(module, conn_type='client', resource='sts', region=region, endpoint=ec2_url, **aws_connect_kwargs)
|
||||||
|
except botocore.exceptions.NoCredentialsError as e:
|
||||||
|
module.fail_json(msg='cannot connect to AWS', exception=traceback.format_exc(e))
|
||||||
|
else:
|
||||||
|
boto3_dynamodb = None
|
||||||
|
boto3_sts = None
|
||||||
|
|
||||||
state = module.params.get('state')
|
state = module.params.get('state')
|
||||||
if state == 'present':
|
if state == 'present':
|
||||||
create_or_update_dynamo_table(connection, module)
|
create_or_update_dynamo_table(connection, module, boto3_dynamodb, boto3_sts)
|
||||||
elif state == 'absent':
|
elif state == 'absent':
|
||||||
delete_dynamo_table(connection, module)
|
delete_dynamo_table(connection, module)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue