From 72e4cc721449478a4651e6918fd4650727706952 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 15 Jul 2019 10:26:41 -0700 Subject: [PATCH] Spanner Fixes (#301) Signed-off-by: Modular Magician --- plugins/modules/gcp_compute_instance.py | 2 +- .../modules/gcp_compute_instance_template.py | 2 +- plugins/modules/gcp_compute_target_pool.py | 2 +- plugins/modules/gcp_spanner_database.py | 45 ++++++++++++++++--- plugins/modules/gcp_spanner_instance.py | 2 +- .../gcp_spanner_database/tasks/main.yml | 4 +- .../gcp_spanner_instance/tasks/main.yml | 4 +- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/plugins/modules/gcp_compute_instance.py b/plugins/modules/gcp_compute_instance.py index c8b4f61..875ac20 100644 --- a/plugins/modules/gcp_compute_instance.py +++ b/plugins/modules/gcp_compute_instance.py @@ -1139,7 +1139,7 @@ def wait_for_operation(module, response): return {} status = navigate_hash(op_result, ['status']) wait_done = wait_for_completion(status, op_result, module) - return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#instance') + return decode_response(fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#instance'), module) def wait_for_completion(status, op_result, module): diff --git a/plugins/modules/gcp_compute_instance_template.py b/plugins/modules/gcp_compute_instance_template.py index 24fb4b1..68efdc7 100644 --- a/plugins/modules/gcp_compute_instance_template.py +++ b/plugins/modules/gcp_compute_instance_template.py @@ -1058,7 +1058,7 @@ def wait_for_operation(module, response): return {} status = navigate_hash(op_result, ['status']) wait_done = wait_for_completion(status, op_result, module) - return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#instanceTemplate') + return decode_response(fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#instanceTemplate'), module) def wait_for_completion(status, op_result, module): diff --git a/plugins/modules/gcp_compute_target_pool.py b/plugins/modules/gcp_compute_target_pool.py index 32a77c9..46ad75e 100644 --- a/plugins/modules/gcp_compute_target_pool.py +++ b/plugins/modules/gcp_compute_target_pool.py @@ -410,7 +410,7 @@ def wait_for_operation(module, response): return {} status = navigate_hash(op_result, ['status']) wait_done = wait_for_completion(status, op_result, module) - return fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#targetPool') + return decode_response(fetch_resource(module, navigate_hash(wait_done, ['targetLink']), 'compute#targetPool'), module) def wait_for_completion(status, op_result, module): diff --git a/plugins/modules/gcp_spanner_database.py b/plugins/modules/gcp_spanner_database.py index fe585a0..c9e1bb5 100644 --- a/plugins/modules/gcp_spanner_database.py +++ b/plugins/modules/gcp_spanner_database.py @@ -127,6 +127,7 @@ instance: from ansible.module_utils.gcp_utils import navigate_hash, GcpSession, GcpModule, GcpRequest, replace_resource_dict import json +import time ################################################################################ # Main @@ -177,7 +178,7 @@ def main(): def create(module, link): auth = GcpSession(module, 'spanner') - return return_if_object(module, auth.post(link, resource_to_request(module))) + return wait_for_operation(module, auth.post(link, resource_to_request(module))) def update(module, link): @@ -191,11 +192,7 @@ def delete(module, link): def resource_to_request(module): - request = { - u'instance': replace_resource_dict(module.params.get(u'instance', {}), 'name'), - u'name': module.params.get('name'), - u'extraStatements': module.params.get('extra_statements'), - } + request = {u'name': module.params.get('name'), u'extraStatements': module.params.get('extra_statements')} request = encode_request(request, module) return_vals = {} for k, v in request.items(): @@ -268,6 +265,42 @@ def response_to_hash(module, response): return {u'name': module.params.get('name'), u'extraStatements': module.params.get('extra_statements')} +def async_op_url(module, extra_data=None): + if extra_data is None: + extra_data = {} + url = "https://spanner.googleapis.com/v1/{op_id}" + combined = extra_data.copy() + combined.update(module.params) + return url.format(**combined) + + +def wait_for_operation(module, response): + op_result = return_if_object(module, response) + if op_result is None: + return {} + status = navigate_hash(op_result, ['done']) + wait_done = wait_for_completion(status, op_result, module) + raise_if_errors(op_result, ['error'], module) + return navigate_hash(wait_done, ['response']) + + +def wait_for_completion(status, op_result, module): + op_id = navigate_hash(op_result, ['name']) + op_uri = async_op_url(module, {'op_id': op_id}) + while not status: + raise_if_errors(op_result, ['error'], module) + time.sleep(1.0) + op_result = fetch_resource(module, op_uri, False) + status = navigate_hash(op_result, ['done']) + return op_result + + +def raise_if_errors(response, err_path, module): + errors = navigate_hash(response, err_path) + if errors is not None: + module.fail_json(msg=errors) + + def decode_response(response, module): if not response: return response diff --git a/plugins/modules/gcp_spanner_instance.py b/plugins/modules/gcp_spanner_instance.py index 588a594..d0a41c5 100644 --- a/plugins/modules/gcp_spanner_instance.py +++ b/plugins/modules/gcp_spanner_instance.py @@ -202,7 +202,7 @@ def update(module, link): def delete(module, link): auth = GcpSession(module, 'spanner') - return wait_for_operation(module, auth.delete(link)) + return return_if_object(module, auth.delete(link)) def resource_to_request(module): diff --git a/tests/integration/gcp_spanner_database/tasks/main.yml b/tests/integration/gcp_spanner_database/tasks/main.yml index 25b399d..693c6d5 100644 --- a/tests/integration/gcp_spanner_database/tasks/main.yml +++ b/tests/integration/gcp_spanner_database/tasks/main.yml @@ -60,7 +60,7 @@ - name: verify that command succeeded assert: that: - - "'webstore' in \"{{ results['resources'] | map(attribute='name') | list }}\"" + - results['resources'] | map(attribute='name') | select("match", ".*webstore.*") | list | length == 1 # ---------------------------------------------------------------------------- - name: create a database that already exists gcp_spanner_database: @@ -101,7 +101,7 @@ - name: verify that command succeeded assert: that: - - "'webstore' not in \"{{ results['resources'] | map(attribute='name') | list }}\"" + - results['resources'] | map(attribute='name') | select("match", ".*webstore.*") | list | length == 0 # ---------------------------------------------------------------------------- - name: delete a database that does not exist gcp_spanner_database: diff --git a/tests/integration/gcp_spanner_instance/tasks/main.yml b/tests/integration/gcp_spanner_instance/tasks/main.yml index 41b1d78..0dd460f 100644 --- a/tests/integration/gcp_spanner_instance/tasks/main.yml +++ b/tests/integration/gcp_spanner_instance/tasks/main.yml @@ -54,7 +54,7 @@ - name: verify that command succeeded assert: that: - - "\"{{resource_name}}\" in \"{{ results['resources'] | map(attribute='name') | list }}\"" + - results['resources'] | map(attribute='name') | select("match", ".*testinstance.*") | list | length == 1 # ---------------------------------------------------------------------------- - name: create a instance that already exists gcp_spanner_instance: @@ -102,7 +102,7 @@ - name: verify that command succeeded assert: that: - - "\"{{resource_name}}\" not in \"{{ results['resources'] | map(attribute='name') | list }}\"" + - results['resources'] | map(attribute='name') | select("match", ".*testinstance.*") | list | length == 0 # ---------------------------------------------------------------------------- - name: delete a instance that does not exist gcp_spanner_instance: