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)
|
||||
requirements:
|
||||
- "boto >= 2.37.0"
|
||||
- "boto3 >= 1.4.4 (for tagging)"
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
|
@ -84,6 +85,18 @@ options:
|
|||
required: false
|
||||
default: []
|
||||
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:
|
||||
- aws
|
||||
- ec2
|
||||
|
@ -100,6 +113,8 @@ EXAMPLES = '''
|
|||
range_key_type: NUMBER
|
||||
read_capacity: 2
|
||||
write_capacity: 2
|
||||
tags:
|
||||
tag_name: tag_value
|
||||
|
||||
# Update capacity on existing dynamo table
|
||||
- dynamodb_table:
|
||||
|
@ -138,6 +153,7 @@ table_status:
|
|||
sample: ACTIVE
|
||||
'''
|
||||
|
||||
import time
|
||||
import traceback
|
||||
|
||||
try:
|
||||
|
@ -159,6 +175,13 @@ try:
|
|||
except ImportError:
|
||||
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.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']
|
||||
|
||||
|
||||
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')
|
||||
hash_key_name = module.params.get('hash_key_name')
|
||||
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')
|
||||
write_capacity = module.params.get('write_capacity')
|
||||
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:
|
||||
validate_index(index, module)
|
||||
|
@ -192,7 +218,7 @@ def create_or_update_dynamo_table(connection, module):
|
|||
indexes, global_indexes = get_indexes(all_indexes)
|
||||
|
||||
result = dict(
|
||||
region=module.params.get('region'),
|
||||
region=region,
|
||||
table_name=table_name,
|
||||
hash_key_name=hash_key_name,
|
||||
hash_key_type=hash_key_type,
|
||||
|
@ -217,6 +243,13 @@ def create_or_update_dynamo_table(connection, module):
|
|||
if not module.check_mode:
|
||||
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:
|
||||
result['msg'] = 'Failed to create/update dynamo table due to error: ' + traceback.format_exc()
|
||||
module.fail_json(**result)
|
||||
|
@ -224,6 +257,19 @@ def create_or_update_dynamo_table(connection, module):
|
|||
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):
|
||||
table_name = module.params.get('name')
|
||||
|
||||
|
@ -398,6 +444,8 @@ def main():
|
|||
read_capacity=dict(default=1, type='int'),
|
||||
write_capacity=dict(default=1, type='int'),
|
||||
indexes=dict(default=[], type='list'),
|
||||
tags = dict(type='dict'),
|
||||
wait_for_active_timeout = dict(default=60, type='int'),
|
||||
))
|
||||
|
||||
module = AnsibleModule(
|
||||
|
@ -407,6 +455,9 @@ def main():
|
|||
if not HAS_BOTO:
|
||||
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)
|
||||
if not region:
|
||||
module.fail_json(msg='region must be specified')
|
||||
|
@ -416,9 +467,22 @@ def main():
|
|||
except (NoAuthHandlerFound, AnsibleAWSError) as 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')
|
||||
if state == 'present':
|
||||
create_or_update_dynamo_table(connection, module)
|
||||
create_or_update_dynamo_table(connection, module, boto3_dynamodb, boto3_sts)
|
||||
elif state == 'absent':
|
||||
delete_dynamo_table(connection, module)
|
||||
|
||||
|
|
Loading…
Reference in a new issue