From bd34191712ea7d0b377bb91002ac855b23772c29 Mon Sep 17 00:00:00 2001 From: Mark Woolley Date: Sat, 22 Jan 2022 13:13:18 +0000 Subject: [PATCH 1/6] Add dynamodb table class support --- plugins/modules/dynamodb_table.py | 22 +++++++++++ .../targets/dynamodb_table/tasks/main.yml | 39 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/plugins/modules/dynamodb_table.py b/plugins/modules/dynamodb_table.py index 1ea4391223c..4914522feb7 100644 --- a/plugins/modules/dynamodb_table.py +++ b/plugins/modules/dynamodb_table.py @@ -121,6 +121,13 @@ default: [] type: list elements: dict + table_class: + description: + - The class of the table + choices: ['STANDARD', 'STANDARD_INFREQUENT_ACCESS'] + default: 'STANDARD' + type: str + version_added: 3.1.0 tags: description: - A hash/dictionary of tags to add to the new instance or for starting/stopping instance by tag. @@ -410,6 +417,7 @@ def compatability_results(current_table): billing_mode=billing_mode, region=module.region, table_name=current_table.get('table_name', None), + table_class=current_table.get('table_class', None), table_status=current_table.get('table_status', None), tags=current_table.get('tags', {}), ) @@ -753,6 +761,7 @@ def _update_table(current_table): changes = dict() additional_global_index_changes = list() + # Get throughput / billing_mode changes throughput_changes = _throughput_changes(current_table) if throughput_changes: changes['ProvisionedThroughput'] = throughput_changes @@ -766,6 +775,15 @@ def _update_table(current_table): if current_billing_mode != new_billing_mode: changes['BillingMode'] = new_billing_mode + # Update table_class use exisiting if none is defined + if module.params.get('table_class'): + table_class = module.params.get('table_class') + else: + table_class = current_table.get('table_class') + + if table_class != current_table.get('billing_mode'): + changes['TableClass'] = table_class + global_index_changes = _global_index_changes(current_table) if global_index_changes: changes['GlobalSecondaryIndexUpdates'] = global_index_changes @@ -868,6 +886,7 @@ def update_table(current_table): def create_table(): table_name = module.params.get('name') + table_class = module.params.get('table_class') hash_key_name = module.params.get('hash_key_name') billing_mode = module.params.get('billing_mode') @@ -901,6 +920,8 @@ def create_table(): # SSESpecification, ) + if table_class: + params['TableClass'] = table_class if billing_mode == "PROVISIONED": params['ProvisionedThroughput'] = throughput if local_indexes: @@ -982,6 +1003,7 @@ def main(): read_capacity=dict(type='int'), write_capacity=dict(type='int'), indexes=dict(default=[], type='list', elements='dict', options=index_options), + table_class=dict(type='str', choices=['STANDARD', 'STANDARD_INFREQUENT_ACCESS']), tags=dict(type='dict'), purge_tags=dict(type='bool', default=True), wait=dict(type='bool', default=True), diff --git a/tests/integration/targets/dynamodb_table/tasks/main.yml b/tests/integration/targets/dynamodb_table/tasks/main.yml index cd41e031d64..39c725de0bb 100644 --- a/tests/integration/targets/dynamodb_table/tasks/main.yml +++ b/tests/integration/targets/dynamodb_table/tasks/main.yml @@ -585,6 +585,7 @@ range_key_type: "{{ range_index_type }}" read_capacity: 3 write_capacity: 3 + table_class: "STANDARD_INFREQUENT_ACCESS" tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table @@ -606,6 +607,7 @@ range_key_type: "{{ range_index_type }}" read_capacity: 3 write_capacity: 3 + table_class: "STANDARD_INFREQUENT_ACCESS" tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table @@ -633,6 +635,7 @@ - create_complex_table.range_key_type == range_index_type - create_complex_table.read_capacity == 3 - create_complex_table.table_name == table_name + - create_complex_table.table_class == "STANDARD_INFREQUENT_ACCESS" - create_complex_table.write_capacity == 3 - create_complex_table.tags == tags_default @@ -646,6 +649,7 @@ range_key_type: "{{ range_index_type }}" read_capacity: 3 write_capacity: 3 + table_class: "STANDARD_INFREQUENT_ACCESS" tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table @@ -667,6 +671,7 @@ range_key_type: "{{ range_index_type }}" read_capacity: 3 write_capacity: 3 + table_class: "STANDARD_INFREQUENT_ACCESS" tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table @@ -694,10 +699,44 @@ - create_complex_table.range_key_type == range_index_type - create_complex_table.read_capacity == 3 - create_complex_table.table_name == table_name + - create_complex_table.table_class == "STANDARD_INFREQUENT_ACCESS" - create_complex_table.write_capacity == 3 - create_complex_table.tags == tags_default # ============================================== + # Update table class on exisiting table + + - name: Update table class - check_mode + dynamodb_table: + state: present + name: "{{ table_name }}" + table_class: "STANDARD" + register: update_class + check_mode: True + + - name: Check results - Update table class - check_mode + assert: + that: + - update_class is successful + - update_class is changed + + - name: Update table class + dynamodb_table: + state: present + name: "{{ table_name }}" + table_class: "STANDARD" + register: update_class + + - name: Check results - Update table class + assert: + that: + - update_class is successful + - update_class is changed + - update_class.table_name == table_name + - update_class.table_class == "STANDARD" + + # ============================================== + # Update table index on exisiting table - name: Update table update index - check_mode dynamodb_table: From dc2ff0fea0d17d84dafadefe9619e79c7de0651e Mon Sep 17 00:00:00 2001 From: Mark Woolley Date: Sat, 22 Jan 2022 13:18:22 +0000 Subject: [PATCH 2/6] add changelog fragment --- changelogs/fragments/880-add-table-class-param.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelogs/fragments/880-add-table-class-param.yml diff --git a/changelogs/fragments/880-add-table-class-param.yml b/changelogs/fragments/880-add-table-class-param.yml new file mode 100644 index 00000000000..21d08216cd6 --- /dev/null +++ b/changelogs/fragments/880-add-table-class-param.yml @@ -0,0 +1,2 @@ +minor_changes: + - dynamodb_table - the ``table_class`` parameter has been added (https://github.com/ansible-collections/community.aws/pull/880). From 35068c399ec78538295ef6706094af57ec5a8baa Mon Sep 17 00:00:00 2001 From: Mark Woolley Date: Sat, 22 Jan 2022 13:55:10 +0000 Subject: [PATCH 3/6] Make some adjustments and fix tests --- plugins/modules/dynamodb_table.py | 15 +++++++-------- .../targets/dynamodb_table/meta/main.yml | 4 +++- .../targets/dynamodb_table/tasks/main.yml | 13 ++++++++++++- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/plugins/modules/dynamodb_table.py b/plugins/modules/dynamodb_table.py index 4914522feb7..14a6c5b5eba 100644 --- a/plugins/modules/dynamodb_table.py +++ b/plugins/modules/dynamodb_table.py @@ -125,7 +125,6 @@ description: - The class of the table choices: ['STANDARD', 'STANDARD_INFREQUENT_ACCESS'] - default: 'STANDARD' type: str version_added: 3.1.0 tags: @@ -417,7 +416,7 @@ def compatability_results(current_table): billing_mode=billing_mode, region=module.region, table_name=current_table.get('table_name', None), - table_class=current_table.get('table_class', None), + table_class=current_table.get('table_class_summary', {}).get('table_class', None), table_status=current_table.get('table_status', None), tags=current_table.get('tags', {}), ) @@ -777,12 +776,8 @@ def _update_table(current_table): # Update table_class use exisiting if none is defined if module.params.get('table_class'): - table_class = module.params.get('table_class') - else: - table_class = current_table.get('table_class') - - if table_class != current_table.get('billing_mode'): - changes['TableClass'] = table_class + if module.params.get('table_class') != current_table.get('table_class'): + changes['TableClass'] = module.params.get('table_class') global_index_changes = _global_index_changes(current_table) if global_index_changes: @@ -1021,6 +1016,10 @@ def main(): ) client = module.client('dynamodb', retry_decorator=retry_decorator) + if module.params.get('table_class'): + if not module.botocore_at_least("1.23.18"): + module.fail_json(msg='botocore version >= 1.23.18 is required setting table_class') + current_table = get_dynamodb_table() changed = False table = None diff --git a/tests/integration/targets/dynamodb_table/meta/main.yml b/tests/integration/targets/dynamodb_table/meta/main.yml index 07faa217762..504e72117b6 100644 --- a/tests/integration/targets/dynamodb_table/meta/main.yml +++ b/tests/integration/targets/dynamodb_table/meta/main.yml @@ -1,2 +1,4 @@ dependencies: - - prepare_tests + - role: setup_botocore_pip + vars: + botocore_version: "1.23.18" diff --git a/tests/integration/targets/dynamodb_table/tasks/main.yml b/tests/integration/targets/dynamodb_table/tasks/main.yml index 39c725de0bb..21c7f465b20 100644 --- a/tests/integration/targets/dynamodb_table/tasks/main.yml +++ b/tests/integration/targets/dynamodb_table/tasks/main.yml @@ -574,7 +574,6 @@ - delete_table is not changed # ============================================== - - name: Create complex table - check_mode dynamodb_table: state: present @@ -589,6 +588,8 @@ tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" check_mode: True - name: Check results - Create complex table - check_mode @@ -611,6 +612,8 @@ tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" - name: Check results - Create complex table assert: @@ -653,6 +656,8 @@ tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" check_mode: True - name: Check results - Create complex table - idempotent - check_mode @@ -675,6 +680,8 @@ tags: "{{ tags_default }}" indexes: "{{ indexes }}" register: create_complex_table + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" - name: Check results - Create complex table - idempotent assert: @@ -712,6 +719,8 @@ name: "{{ table_name }}" table_class: "STANDARD" register: update_class + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" check_mode: True - name: Check results - Update table class - check_mode @@ -725,6 +734,8 @@ state: present name: "{{ table_name }}" table_class: "STANDARD" + vars: + ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}" register: update_class - name: Check results - Update table class From 71b6fcaf9b1538204977c577884f0a81f3139d10 Mon Sep 17 00:00:00 2001 From: Mark Woolley Date: Sat, 22 Jan 2022 17:43:12 +0000 Subject: [PATCH 4/6] missed update --- plugins/modules/dynamodb_table.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/modules/dynamodb_table.py b/plugins/modules/dynamodb_table.py index 14a6c5b5eba..276b4e6a540 100644 --- a/plugins/modules/dynamodb_table.py +++ b/plugins/modules/dynamodb_table.py @@ -459,6 +459,9 @@ def get_dynamodb_table(): table['size'] = table['table_size_bytes'] table['tags'] = tags + if 'table_class_summary' in table: + table['table_class'] = table['table_class_summary']['table_class'] + # billing_mode_summary doesn't always seem to be set but is always set for PAY_PER_REQUEST # and when updating the billing_mode if 'billing_mode_summary' in table: From 2a20b4de728e4ae18be9b09cd413d9c0ae3c1a87 Mon Sep 17 00:00:00 2001 From: mark-woolley Date: Fri, 4 Feb 2022 13:28:06 +0000 Subject: [PATCH 5/6] PR feedback --- plugins/modules/dynamodb_table.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/modules/dynamodb_table.py b/plugins/modules/dynamodb_table.py index 276b4e6a540..ce35f38c30a 100644 --- a/plugins/modules/dynamodb_table.py +++ b/plugins/modules/dynamodb_table.py @@ -123,7 +123,8 @@ elements: dict table_class: description: - - The class of the table + - The class of the table. + - Requires at least botocore version 1.23.18. choices: ['STANDARD', 'STANDARD_INFREQUENT_ACCESS'] type: str version_added: 3.1.0 @@ -212,6 +213,11 @@ returned: success type: str sample: ACTIVE +table_class: + description: The current table class. + returned: when state present + type: str + sample: STANDARD_INFREQUENT_ACCESS ''' try: @@ -1020,8 +1026,7 @@ def main(): client = module.client('dynamodb', retry_decorator=retry_decorator) if module.params.get('table_class'): - if not module.botocore_at_least("1.23.18"): - module.fail_json(msg='botocore version >= 1.23.18 is required setting table_class') + module.require_botocore_at_least('1.23.18', reason='to set table_class') current_table = get_dynamodb_table() changed = False From 13ce472a900d37f52595d26dbc6a40f76fc4116b Mon Sep 17 00:00:00 2001 From: mark-woolley Date: Fri, 4 Feb 2022 17:02:52 +0000 Subject: [PATCH 6/6] PR feedback --- plugins/modules/dynamodb_table.py | 51 +++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/plugins/modules/dynamodb_table.py b/plugins/modules/dynamodb_table.py index ce35f38c30a..839178256aa 100644 --- a/plugins/modules/dynamodb_table.py +++ b/plugins/modules/dynamodb_table.py @@ -208,16 +208,49 @@ ''' RETURN = r''' +table: + description: The returned table params from the describe API call. + returned: success + type: complex + contains: {} + sample: { + "arn": "arn:aws:dynamodb:us-east-1:721066863947:table/ansible-test-table", + "attribute_definitions": [ + { + "attribute_name": "id", + "attribute_type": "N" + } + ], + "billing_mode": "PROVISIONED", + "creation_date_time": "2022-02-04T13:36:01.578000+00:00", + "id": "533b45fe-0870-4b66-9b00-d2afcfe96f19", + "item_count": 0, + "key_schema": [ + { + "attribute_name": "id", + "key_type": "HASH" + } + ], + "name": "ansible-test-14482047-alinas-mbp", + "provisioned_throughput": { + "number_of_decreases_today": 0, + "read_capacity_units": 1, + "write_capacity_units": 1 + }, + "size": 0, + "status": "ACTIVE", + "table_arn": "arn:aws:dynamodb:us-east-1:721066863947:table/ansible-test-table", + "table_id": "533b45fe-0870-4b66-9b00-d2afcfe96f19", + "table_name": "ansible-test-table", + "table_size_bytes": 0, + "table_status": "ACTIVE", + "tags": {} + } table_status: - description: The current status of the table. - returned: success - type: str - sample: ACTIVE -table_class: - description: The current table class. - returned: when state present - type: str - sample: STANDARD_INFREQUENT_ACCESS + description: The current status of the table. + returned: success + type: str + sample: ACTIVE ''' try: