refactor moudule utils of hwc_utils.py (#55858)

* use navigate_value instead navigate_hash

* add async wait method

* update dict compare

* remove unuse methods

* not all modules have timeouts parameter

* navigate_value, the input data may be None
This commit is contained in:
zengchen 2019-05-09 21:04:52 +08:00 committed by jctanner
commit d8314e1a45
6 changed files with 305 additions and 327 deletions

View file

@ -34,6 +34,27 @@ options:
type: str
choices: ['present', 'absent']
default: 'present'
timeouts:
description:
- The timeouts for each operations.
type: dict
version_added: '2.9'
suboptions:
create:
description:
- The timeout for create operation.
type: str
default: '15m'
update:
description:
- The timeout for update operation.
type: str
default: '15m'
delete:
description:
- The timeout for delete operation.
type: str
default: '15m'
name:
description:
- the name of vpc.
@ -110,14 +131,12 @@ RETURN = '''
# Imports
###############################################################################
from ansible.module_utils.hwc_utils import (Config, HwcModule, get_region,
HwcClientException, navigate_hash,
HwcClientException404,
remove_nones_from_dict, build_path,
remove_empty_from_dict,
are_dicts_different)
from ansible.module_utils.hwc_utils import (Config, HwcClientException,
HwcClientException404, HwcModule,
are_different_dicts, is_empty_value,
wait_to_finish, get_region,
build_path, navigate_value)
import re
import time
###############################################################################
# Main
@ -129,7 +148,13 @@ def main():
module = HwcModule(
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent'], type='str'),
state=dict(
default='present', choices=['present', 'absent'], type='str'),
timeouts=dict(type='dict', options=dict(
create=dict(default='15m', type='str'),
update=dict(default='15m', type='str'),
delete=dict(default='15m', type='str'),
), default=dict()),
name=dict(required=True, type='str'),
cidr=dict(required=True, type='str')
),
@ -156,7 +181,8 @@ def main():
if state == 'present':
expect = _get_editable_properties(module)
current_state = response_to_hash(module, fetch)
if are_dicts_different(expect, current_state):
current = {"cidr": current_state["cidr"]}
if are_different_dicts(expect, current):
if not module.check_mode:
fetch = update(config, self_link(module))
fetch = response_to_hash(module, fetch.get('vpc'))
@ -195,8 +221,12 @@ def create(config, link):
module.fail_json(msg=msg)
wait_done = wait_for_operation(config, 'create', r)
v = ""
try:
v = navigate_value(wait_done, ['vpc', 'id'])
except Exception as ex:
module.fail_json(msg=str(ex))
v = navigate_hash(wait_done, ['vpc', 'id'])
url = build_path(module, 'vpcs/{op_id}', {'op_id': v})
return fetch_resource(module, client, url)
@ -268,7 +298,8 @@ def get_id_by_name(config):
elif len(ids) == 1:
return ids[0]
else:
module.fail_json(msg="Multiple resources with same name are found.")
module.fail_json(
msg="Multiple resources with same name are found.")
elif none_values:
module.fail_json(
msg="Can not find id by name because url includes None.")
@ -303,28 +334,43 @@ def self_link(module):
def resource_to_create(module):
request = remove_empty_from_dict({
u'name': module.params.get('name'),
u'cidr': module.params.get('cidr')
})
return {'vpc': request}
params = dict()
v = module.params.get('cidr')
if not is_empty_value(v):
params["cidr"] = v
v = module.params.get('name')
if not is_empty_value(v):
params["name"] = v
if not params:
return params
params = {"vpc": params}
return params
def resource_to_update(module):
request = remove_nones_from_dict({
u'name': module.params.get('name'),
u'cidr': module.params.get('cidr')
})
return {'vpc': request}
params = dict()
v = module.params.get('cidr')
if not is_empty_value(v):
params["cidr"] = v
if not params:
return params
params = {"vpc": params}
return params
def _get_editable_properties(module):
request = remove_nones_from_dict({
"name": module.params.get("name"),
return {
"cidr": module.params.get("cidr"),
})
return request
}
def response_to_hash(module, response):
@ -336,14 +382,20 @@ def response_to_hash(module, response):
u'name': response.get(u'name'),
u'cidr': response.get(u'cidr'),
u'status': response.get(u'status'),
u'routes': VpcRoutesArray(response.get(u'routes', []), module).from_response(),
u'routes': VpcRoutesArray(
response.get(u'routes', []), module).from_response(),
u'enable_shared_snat': response.get(u'enable_shared_snat')
}
def wait_for_operation(config, op_type, op_result):
module = config.module
op_id = navigate_hash(op_result, ['vpc', 'id'])
op_id = ""
try:
op_id = navigate_value(op_result, ['vpc', 'id'])
except Exception as ex:
module.fail_json(msg=str(ex))
url = build_path(module, "vpcs/{op_id}", {'op_id': op_id})
timeout = 60 * int(module.params['timeouts'][op_type].rstrip('m'))
states = {
@ -365,47 +417,47 @@ def wait_for_completion(op_uri, timeout, allowed_states,
complete_states, config):
module = config.module
client = config.client(get_region(module), "vpc", "project")
end = time.time() + timeout
while time.time() <= end:
def _refresh_status():
r = None
try:
op_result = fetch_resource(module, client, op_uri)
r = fetch_resource(module, client, op_uri)
except Exception:
time.sleep(1.0)
continue
return None, ""
raise_if_errors(op_result, module)
status = ""
try:
status = navigate_value(r, ['vpc', 'status'])
except Exception:
return None, ""
status = navigate_hash(op_result, ['vpc', 'status'])
if status not in allowed_states:
module.fail_json(msg="Invalid async operation status %s" % status)
if status in complete_states:
return op_result
return r, status
time.sleep(1.0)
module.fail_json(msg="Timeout to wait completion.")
def raise_if_errors(response, module):
errors = navigate_hash(response, [])
if errors:
module.fail_json(msg=navigate_hash(response, []))
try:
return wait_to_finish(complete_states, allowed_states,
_refresh_status, timeout)
except Exception as ex:
module.fail_json(msg=str(ex))
def wait_for_delete(module, client, link):
end = time.time() + 60 * int(
module.params['timeouts']['delete'].rstrip('m'))
while time.time() <= end:
def _refresh_status():
try:
client.get(link)
except HwcClientException404:
return
return True, "Done"
except Exception:
pass
return None, ""
time.sleep(1.0)
return True, "Pending"
module.fail_json(msg="Timeout to wait for deletion to be complete.")
timeout = 60 * int(module.params['timeouts']['delete'].rstrip('m'))
try:
return wait_to_finish(["Done"], ["Pending"], _refresh_status, timeout)
except Exception as ex:
module.fail_json(msg=str(ex))
class VpcRoutesArray(object):

View file

@ -109,11 +109,10 @@ update_time:
# Imports
###############################################################################
from ansible.module_utils.hwc_utils import (Config, HwcModule, build_path,
HwcClientException, navigate_hash,
remove_nones_from_dict, get_region,
remove_empty_from_dict,
are_dicts_different)
from ansible.module_utils.hwc_utils import (Config, HwcClientException,
HwcModule, navigate_value,
are_different_dicts, is_empty_value,
build_path, get_region)
import re
###############################################################################
@ -153,7 +152,8 @@ def main():
if state == 'present':
expect = _get_resource_editable_properties(module)
current_state = response_to_hash(module, fetch)
if are_dicts_different(expect, current_state):
current = {'display_name': current_state['display_name']}
if are_different_dicts(expect, current):
if not module.check_mode:
fetch = update(config)
fetch = response_to_hash(module, fetch)
@ -236,7 +236,13 @@ def get_resource(config, result):
module = config.module
client = config.client(get_region(module), "smn", "project")
d = {'topic_urn': navigate_hash(result, ['topic_urn'])}
v = ""
try:
v = navigate_value(result, ['topic_urn'])
except Exception as ex:
module.fail_json(msg=str(ex))
d = {'topic_urn': v}
url = build_path(module, 'notifications/topics/{topic_urn}', d)
return fetch_resource(module, client, url)
@ -280,24 +286,33 @@ def self_link(module):
def create_resource_opts(module):
request = remove_empty_from_dict({
u'display_name': module.params.get('display_name'),
u'name': module.params.get('name')
})
return request
params = dict()
v = module.params.get('display_name')
if not is_empty_value(v):
params["display_name"] = v
v = module.params.get('name')
if not is_empty_value(v):
params["name"] = v
return params
def update_resource_opts(module):
request = remove_nones_from_dict({
u'display_name': module.params.get('display_name')
})
return request
params = dict()
v = module.params.get('display_name')
if not is_empty_value(v):
params["display_name"] = v
return params
def _get_resource_editable_properties(module):
return remove_nones_from_dict({
return {
"display_name": module.params.get("display_name"),
})
}
def response_to_hash(module, response):