diff --git a/changelogs/fragments/53597-meraki_config_template_check_mode.yml b/changelogs/fragments/53597-meraki_config_template_check_mode.yml new file mode 100644 index 00000000000..8702c07a150 --- /dev/null +++ b/changelogs/fragments/53597-meraki_config_template_check_mode.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - "meraki_config_template - Enable check mode." diff --git a/lib/ansible/module_utils/network/meraki/meraki.py b/lib/ansible/module_utils/network/meraki/meraki.py index 443ea91e0d9..1b7a9e6b6c6 100644 --- a/lib/ansible/module_utils/network/meraki/meraki.py +++ b/lib/ansible/module_utils/network/meraki/meraki.py @@ -61,6 +61,7 @@ class MerakiModule(object): self.nets = None self.org_id = None self.net_id = None + self.check_mode = module.check_mode # normal output self.existing = None diff --git a/lib/ansible/modules/network/meraki/meraki_config_template.py b/lib/ansible/modules/network/meraki/meraki_config_template.py index 88956cb108d..604069924fa 100644 --- a/lib/ansible/modules/network/meraki/meraki_config_template.py +++ b/lib/ansible/modules/network/meraki/meraki_config_template.py @@ -133,6 +133,13 @@ def get_template_id(meraki, name, data): meraki.fail_json(msg='No configuration template named {0} found'.format(name)) +def is_template_valid(meraki, nets, template_id): + for net in nets: + if net['id'] == template_id: + return True + return False + + def is_network_bound(meraki, nets, net_id, template_id): for net in nets: if net['id'] == net_id: @@ -149,7 +156,7 @@ def delete_template(meraki, org_id, name, data): path = meraki.construct_path('delete', org_id=org_id) path = path + '/' + template_id response = meraki.request(path, 'DELETE') - if meraki.status != 200: + if meraki.status != 204: meraki.fail_json(msg='Unable to remove configuration template') return response @@ -217,9 +224,6 @@ def main(): # if the user is working with this module in only check mode we do not # want to make any changes to the environment, just return the current # state with no modifications - # FIXME: Work with Meraki so they can implement a check mode - if module.check_mode: - meraki.exit_json(**meraki.result) # execute checks for argument completeness @@ -245,7 +249,11 @@ def main(): get_config_templates(meraki, org_id)) if nets is None: nets = meraki.get_nets(org_id=org_id) - if is_network_bound(meraki, nets, net_id, template_id) is False: + if is_network_bound(meraki, nets, net_id, template_id) is False: # Bind template + if meraki.check_mode is True: + meraki.result['data'] = {} + meraki.result['changed'] = True + meraki.exit_json(**meraki.result) template_bind = bind(meraki, net_id, template_id) @@ -253,31 +261,64 @@ def main(): meraki.fail_json(msg='Unable to bind configuration template to network') meraki.result['changed'] = True meraki.result['data'] = template_bind - else: + else: # Network is already bound, being explicit + if meraki.check_mode is True: # Include to be explicit + meraki.result['data'] = {} + meraki.result['changed'] = False + meraki.exit_json(**meraki.result) meraki.result['data'] = {} + meraki.result['changed'] = False + meraki.exit_json(**meraki.result) elif meraki.params['state'] == 'absent': - if not meraki.params['net_name'] and not meraki.params['net_id']: - meraki.result['data'] = delete_template(meraki, - org_id, - meraki.params['config_template'], - get_config_templates(meraki, org_id)) - if meraki.status == 200: - meraki.result['changed'] = True - else: + template_id = get_template_id(meraki, + meraki.params['config_template'], + get_config_templates(meraki, org_id)) + if not meraki.params['net_name'] and not meraki.params['net_id']: # Delete template + if is_template_valid(meraki, nets, template_id) is True: + if meraki.check_mode is True: + meraki.result['data'] = {} + meraki.result['changed'] = True + meraki.exit_json(**meraki.result) + meraki.result['data'] = delete_template(meraki, + org_id, + meraki.params['config_template'], + get_config_templates(meraki, org_id)) + if meraki.status == 204: + meraki.result['data'] = {} + meraki.result['changed'] = True + else: + meraki.fail_json(msg="No template named {0} found.".format(meraki.params['config_template'])) + else: # Unbind template + if meraki.check_mode is True: + meraki.result['data'] = {} + if is_template_valid(meraki, nets, template_id) is True: + meraki.result['changed'] = True + else: + meraki.result['changed'] = False + meraki.exit_json(**meraki.result) template_id = get_template_id(meraki, meraki.params['config_template'], get_config_templates(meraki, org_id)) if nets is None: nets = meraki.get_nets(org_id=org_id) if is_network_bound(meraki, nets, net_id, template_id) is True: + if meraki.check_mode is True: + meraki.result['data'] = {} + meraki.result['changed'] = True + meraki.exit_json(**meraki.result) config_unbind = unbind(meraki, net_id) if meraki.status != 200: meraki.fail_json(msg='Unable to unbind configuration template from network') meraki.result['changed'] = True meraki.result['data'] = config_unbind - else: + else: # No network is bound, nothing to do + if meraki.check_mode is True: # Include to be explicit + meraki.result['data'] = {} + meraki.result['changed'] = False + meraki.exit_json(**meraki.result) meraki.result['data'] = {} + meraki.result['changed'] = False # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results diff --git a/test/integration/targets/meraki_config_template/tasks/main.yml b/test/integration/targets/meraki_config_template/tasks/main.yml index dd061e80786..5785804780c 100644 --- a/test/integration/targets/meraki_config_template/tasks/main.yml +++ b/test/integration/targets/meraki_config_template/tasks/main.yml @@ -53,18 +53,21 @@ net_name: '{{ test_net_name }}' type: appliance delegate_to: localhost - - - name: Get network id - meraki_network: - auth_key: '{{auth_key}}' - state: query - org_name: '{{test_org_name}}' - net_name: '{{test_net_name}}' register: net_info - set_fact: net_id: '{{net_info.data.id}}' + - name: Bind a template to a network with check mode + meraki_config_template: + auth_key: '{{auth_key}}' + state: present + org_name: '{{ test_org_name }}' + net_name: '{{ test_net_name }}' + config_template: '{{test_template_name}}' + check_mode: yes + register: bind_check + - name: Bind a template to a network meraki_config_template: auth_key: '{{auth_key}}' @@ -78,6 +81,10 @@ that: bind.changed == True + - assert: + that: + bind_check is changed + - name: Bind a template to a network when it's already bound meraki_config_template: auth_key: '{{auth_key}}' @@ -145,7 +152,21 @@ - bind_id_idempotent.changed == False - bind_id_idempotent.data is defined - - name: Unbind a template to a network via id + - name: Unbind a template from a network via id with check mode + meraki_config_template: + auth_key: '{{auth_key}}' + state: absent + org_name: '{{test_org_name}}' + net_id: '{{net_id}}' + config_template: '{{test_template_name}}' + check_mode: yes + register: unbind_id_check + + - assert: + that: + unbind_id_check is changed + + - name: Unbind a template from a network via id meraki_config_template: auth_key: '{{auth_key}}' state: absent @@ -158,6 +179,29 @@ that: unbind_id.changed == True + # This is disabled by default since they can't be created via API + - name: Delete sacrificial template with check mode + meraki_config_template: + auth_key: '{{auth_key}}' + state: absent + org_name: '{{test_org_name}}' + config_template: sacrificial_template + check_mode: yes + register: delete_template_check + + # This is disabled by default since they can't be created via API + - name: Delete sacrificial template + meraki_config_template: + auth_key: '{{auth_key}}' + state: absent + org_name: '{{test_org_name}}' + config_template: sacrificial_template + output_level: debug + register: delete_template + + - debug: + var: delete_template + always: - name: Delete network meraki_network: @@ -165,4 +209,4 @@ state: absent org_name: '{{ test_org_name }}' net_name: '{{ test_net_name }}' - delegate_to: localhost \ No newline at end of file + delegate_to: localhost