Repository: ansible/ansible

Issue:
Meraki module methods aren't well documented
##### SUMMARY
All methods and unique situations in the Meraki module utilities should be documented.

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
Meraki module utility

##### 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/modules/network/meraki/meraki_admin.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/meraki/meraki_admin.py)
* [lib/ansible/modules/network/meraki/meraki_network.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/meraki/meraki_network.py)
* [lib/ansible/modules/network/meraki/meraki_organization.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/meraki/meraki_organization.py)
* [lib/ansible/modules/network/meraki/meraki_snmp.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/meraki/meraki_snmp.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 @dagwieers
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/module_utils/network/meraki/meraki.py b/lib/ansible/module_utils/network/meraki/meraki.py
--- a/lib/ansible/module_utils/network/meraki/meraki.py
+++ b/lib/ansible/module_utils/network/meraki/meraki.py
@@ -87,6 +87,7 @@ def __init__(self, module, function=None):
                          'devices': '/networks/{net_id}/devices',
                          }
 
+        # Used to retrieve only one item
         self.get_one_urls = {'organizations': '/organizations/{org_id}',
                              'network': '/networks/{net_id}',
                              }
@@ -103,7 +104,7 @@ def __init__(self, module, function=None):
         if self.module._debug or self.params['output_level'] == 'debug':
             self.module.warn('Enable debug output because ANSIBLE_DEBUG was set or output_level is set to debug.')
 
-        # TODO: This needs to be tested
+        # TODO: This should be removed as org_name isn't always required
         self.module.required_if = [('state', 'present', ['org_name']),
                                    ('state', 'absent', ['org_name']),
                                    ]
@@ -116,21 +117,19 @@ def __init__(self, module, function=None):
                         }
 
     def define_protocol(self):
-        ''' Set protocol based on use_https parameters '''
+        """Set protocol based on use_https parameters."""
         if self.params['use_https'] is True:
             self.params['protocol'] = 'https'
         else:
             self.params['protocol'] = 'http'
 
     def is_update_required(self, original, proposed, optional_ignore=None):
-        ''' Compare original and proposed data to see if an update is needed '''
+        """Compare original and proposed data to see if an update is needed."""
         is_changed = False
         ignored_keys = ('id', 'organizationId')
         if not optional_ignore:
             optional_ignore = ('')
 
-        # self.fail_json(msg="Update required check", original=original, proposed=proposed)
-
         for k, v in original.items():
             try:
                 if k not in ignored_keys and k not in optional_ignore:
@@ -150,12 +149,14 @@ def is_update_required(self, original, proposed, optional_ignore=None):
         return is_changed
 
     def get_orgs(self):
-        ''' Downloads all organizations '''
+        """Downloads all organizations for a user."""
         return self.request('/organizations', method='GET')
 
     def is_org_valid(self, data, org_name=None, org_id=None):
-        ''' Checks whether a specific org exists and is duplicated '''
-        ''' If 0, doesn't exist. 1, exists and not duplicated. >1 duplicated '''
+        """Checks whether a specific org exists and is duplicated.
+
+        If 0, doesn't exist. 1, exists and not duplicated. >1 duplicated.
+        """
         org_count = 0
         if org_name is not None:
             for o in data:
@@ -168,9 +169,10 @@ def is_org_valid(self, data, org_name=None, org_id=None):
         return org_count
 
     def get_org_id(self, org_name):
-        ''' Returns an organization id based on organization name, only if unique
-            If org_id is specified as parameter, return that instead of a lookup
-        '''
+        """Returns an organization id based on organization name, only if unique.
+
+        If org_id is specified as parameter, return that instead of a lookup.
+        """
         orgs = self.get_orgs()
         # self.fail_json(msg='ogs', orgs=orgs)
         if self.params['org_id'] is not None:
@@ -188,6 +190,7 @@ def get_org_id(self, org_name):
                     return str(i['id'])
 
     def get_nets(self, org_name=None, org_id=None):
+        """Downloads all networks in an organization."""
         if org_name:
             org_id = self.get_org_id(org_name)
         path = self.construct_path('get_all', org_id=org_id)
@@ -195,7 +198,8 @@ def get_nets(self, org_name=None, org_id=None):
         return r
 
     def get_net(self, org_name, net_name, data=None):
-        ''' Return network information '''
+        """Return network information about a particular network."""
+        # TODO: Allow method to download data on its own
         # if not data:
         #     org_id = self.get_org_id(org_name)
         #     path = '/organizations/{org_id}/networks/{net_id}'.format(
@@ -213,7 +217,7 @@ def get_net(self, org_name, net_name, data=None):
         return False
 
     def get_net_id(self, org_name=None, net_name=None, data=None):
-        ''' Return network id from lookup or existing data '''
+        """Return network id from lookup or existing data."""
         if data is None:
             self.fail_json(msg='Must implement lookup')
         for n in data:
@@ -222,6 +226,10 @@ def get_net_id(self, org_name=None, net_name=None, data=None):
         self.fail_json(msg='No network found with the name {0}'.format(net_name))
 
     def construct_path(self, action, function=None, org_id=None, net_id=None, org_name=None):
+        """Build a path from the URL catalog.
+
+        Uses function property from class for catalog lookup.
+        """
         built_path = None
         if function is None:
             built_path = self.url_catalog[action][self.function]
@@ -234,7 +242,7 @@ def construct_path(self, action, function=None, org_id=None, net_id=None, org_na
         return built_path
 
     def request(self, path, method=None, payload=None):
-        ''' Generic HTTP method for Meraki requests '''
+        """Generic HTTP method for Meraki requests."""
         self.path = path
         self.define_protocol()
 
@@ -259,6 +267,7 @@ def request(self, path, method=None, payload=None):
             pass
 
     def exit_json(self, **kwargs):
+        """Custom written method to exit from module."""
         self.result['response'] = self.response
         self.result['status'] = self.status
         # Return the gory details when we need it
@@ -270,6 +279,7 @@ def exit_json(self, **kwargs):
         self.module.exit_json(**self.result)
 
     def fail_json(self, msg, **kwargs):
+        """Custom written method to return info on failure."""
         self.result['response'] = self.response
         self.result['status'] = self.status
 


Test patch: