Repository: ansible/ansible

Issue:
Meraki modules should analyze HTTP response code for detailed success
##### SUMMARY
Meraki's API returns a HTTP code and sometimes it varies depending on the endpoint and method. The module utility looks for HTTP status codes greater than 300 for errors, but 2xx codes aren't reviewed by the module.

##### ISSUE TYPE
 - Bug report

##### COMPONENT NAME
meraki
meraki_organization
meraki_network
meraki_snmp
meraki_admin
meraki_vlan
meraki_switchport
meraki_device
meraki_config_template

##### ANSIBLE VERSION
```
ansible 2.6.0.dev0 (backport/2.6/40856 4188435156) last updated 2018/06/07 15:49:33 (GMT -500)
  config file = None
  configured module search path = ['/Users/kbreit/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/kbreit/Documents/Programming/ansible/lib/ansible
  executable location = /Users/kbreit/Documents/Programming/ansible/bin/ansible
  python version = 3.5.4 (default, Feb 25 2018, 14:56:02) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)]
```


Discussion:
Files identified in the description:
* [lib/ansible/module_utils/network/meraki/__init__.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/network/meraki/__init__.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @Qalthos @dagwieers @ganeshrn @gdpak @gundalow @privateip @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
!assign kbreit
Only members of the Ansible GitHub organisation can be assigned. Sorry.

**Update:** Hmm, apparently not ?

Resolving patch:
diff --git a/lib/ansible/modules/network/meraki/meraki_config_template.py b/lib/ansible/modules/network/meraki/meraki_config_template.py
--- a/lib/ansible/modules/network/meraki/meraki_config_template.py
+++ b/lib/ansible/modules/network/meraki/meraki_config_template.py
@@ -83,6 +83,8 @@
 def get_config_templates(meraki, org_id):
     path = meraki.construct_path('get_all', org_id=org_id)
     response = meraki.request(path, 'GET')
+    if meraki.status != 200:
+        meraki.fail_json(msg='Unable to get configuration templates')
     return response
 
 
@@ -96,10 +98,8 @@ def get_template_id(meraki, name, data):
 def is_network_bound(meraki, nets, net_name, template_id):
     for net in nets:
         if net['name'] == net_name:
-            # meraki.fail_json(msg=net['name'])
             try:
                 if net['configTemplateId'] == template_id:
-                    # meraki.fail_json(msg='Network is already bound.')
                     return True
             except KeyError:
                 pass
@@ -111,6 +111,8 @@ 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:
+        meraki.fail_json(msg='Unable to remove configuration template')
     return response
 
 
@@ -126,7 +128,10 @@ def bind(meraki, org_name, net_name, name, data):
         if meraki.params['auto_bind']:
             payload['autoBind'] = meraki.params['auto_bind']
         meraki.result['changed'] = True
-        return meraki.request(path, method='POST', payload=json.dumps(payload))
+        r = meraki.request(path, method='POST', payload=json.dumps(payload))
+        if meraki.status != 200:
+            meraki.fail_json(msg='Unable to bind configuration template to network')
+        return r
 
 
 def unbind(meraki, org_name, net_name, name, data):
@@ -136,7 +141,10 @@ def unbind(meraki, org_name, net_name, name, data):
     if is_network_bound(meraki, nets, net_name, template_id) is True:
         path = meraki.construct_path('unbind', function='config_template', net_id=net_id)
         meraki.result['changed'] = True
-        return meraki.request(path, method='POST')
+        r = meraki.request(path, method='POST')
+        if meraki.status != 200:
+            meraki.fail_json(msg='Unable to unbind configuration template from network')
+        return r
 
 
 def main():
@@ -215,8 +223,6 @@ def main():
                                  meraki.params['net_name'],
                                  meraki.params['config_template'],
                                  get_config_templates(meraki, org_id))
-            # meraki.fail_json(msg='Output', bind_output=template_bind)
-            # meraki.result['data'] = json.loads(template_bind)
     elif meraki.params['state'] == 'absent':
         if not meraki.params['net_name']:
             meraki.result['data'] = delete_template(meraki,
@@ -229,7 +235,6 @@ def main():
                                    meraki.params['net_name'],
                                    meraki.params['config_template'],
                                    get_config_templates(meraki, org_id))
-            # meraki.result['data'] = json.loads(config_unbind)
 
     # in the event of a successful module execution, you will want to
     # simple AnsibleModule.exit_json(), passing the key/value results


Test patch:
diff --git a/test/integration/targets/meraki_config_template/tasks/main.yml b/test/integration/targets/meraki_config_template/tasks/main.yml
--- a/test/integration/targets/meraki_config_template/tasks/main.yml
+++ b/test/integration/targets/meraki_config_template/tasks/main.yml
@@ -47,6 +47,15 @@
     that:
       - '"No configuration template named" in deleted.msg'
 
+- name: Create a network
+  meraki_network:
+    auth_key: '{{auth_key}}'
+    state: present
+    org_name: '{{ test_org_name }}'
+    net_name: '{{ test_net_name }}'
+    type: appliance
+  delegate_to: localhost
+
 - name: Bind a template to a network
   meraki_config_template:
     auth_key: '{{auth_key}}'
@@ -102,3 +111,11 @@
 - assert:
     that:
       unbind_invalid.changed == False
+
+- name: Delete network
+  meraki_network:
+    auth_key: '{{auth_key}}'
+    state: absent
+    org_name: '{{ test_org_name }}'
+    net_name: '{{ test_net_name }}'
+  delegate_to: localhost
\ No newline at end of file