Repository: ansible/ansible
Pull request: meraki_network - Add support for disableRemoteStatusPage
##### SUMMARY
- New feature in the Meraki API
- Yes, it's a double negative, I may fix at some point
Fixes #48965

##### ISSUE TYPE
- Feature Pull Request

##### COMPONENT NAME
meraki_network

Problem statement:
meraki_network - Specify disableMyMerakiCom and disableRemoteStatusPage at creation
##### SUMMARY
Meraki's API now supports creating networks while specifying the parameters in the subject line. The API should be able to support these parameters.

##### ISSUE TYPE
- Feature Idea

##### COMPONENT NAME
meraki_network

Hints from issue discussion:
Hi @kbreit, thank you for submitting this issue!

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: thank_submitter --->
Files identified in the description:
* [lib/ansible/modules/network/meraki/meraki_network.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/meraki/meraki_network.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 --->

Commit message: Update deprecation version

Patch to review:
diff --git a/changelogs/fragments/48971-meraki_network-enable-status-pages.yml b/changelogs/fragments/48971-meraki_network-enable-status-pages.yml
new file mode 100644
index 00000000000000..c6e54780526c9e
--- /dev/null
+++ b/changelogs/fragments/48971-meraki_network-enable-status-pages.yml
@@ -0,0 +1,2 @@
+minor_changes:
+  - meraki_network - Add support for disabling remote status page on a network.
diff --git a/lib/ansible/modules/network/meraki/meraki_network.py b/lib/ansible/modules/network/meraki/meraki_network.py
index 231770f25496c5..a3e0bdea28401e 100644
--- a/lib/ansible/modules/network/meraki/meraki_network.py
+++ b/lib/ansible/modules/network/meraki/meraki_network.py
@@ -71,9 +71,24 @@
     disable_my_meraki:
         description: >
             - Disables the local device status pages (U[my.meraki.com](my.meraki.com), U[ap.meraki.com](ap.meraki.com), U[switch.meraki.com](switch.meraki.com),
-            U[wired.meraki.com](wired.meraki.com))
+            U[wired.meraki.com](wired.meraki.com)).
+            - Mutually exclusive of C(enable_my_meraki).
+            - Will be deprecated in Ansible 2.13 in favor of C(enable_my_meraki).
         type: bool
         version_added: '2.7'
+    enable_my_meraki:
+        description: >
+            - Enables the local device status pages (U[my.meraki.com](my.meraki.com), U[ap.meraki.com](ap.meraki.com), U[switch.meraki.com](switch.meraki.com),
+            U[wired.meraki.com](wired.meraki.com)).
+            - Ansible 2.7 had this parameter as C(disable_my_meraki).
+        type: bool
+        version_added: '2.9'
+    enable_remote_status_page:
+        description:
+            - Enables access to the device status page (U(http://device LAN IP)).
+            - Can only be set if C(enable_my_meraki:) is set to C(yes).
+        type: bool
+        version_added: '2.9'
 
 author:
     - Kevin Breit (@kbreit)
@@ -166,6 +181,11 @@
         returned: success
         type: bool
         sample: true
+      disableRemoteStatusPage:
+        description: Disables access to the device status page.
+        returned: success
+        type: bool
+        sample: true
 '''
 
 import os
@@ -210,8 +230,10 @@ def main():
         timezone=dict(type='str'),
         net_name=dict(type='str', aliases=['name', 'network']),
         state=dict(type='str', choices=['present', 'query', 'absent'], default='present'),
-        disable_my_meraki=dict(type='bool'),
         enable_vlans=dict(type='bool'),
+        disable_my_meraki=dict(type='bool'),
+        enable_my_meraki=dict(type='bool'),
+        enable_remote_status_page=dict(type='bool'),
     )
 
     # the AnsibleModule object will be our abstraction working with Ansible
@@ -220,6 +242,8 @@ def main():
     # supports check mode
     module = AnsibleModule(argument_spec=argument_spec,
                            supports_check_mode=False,
+                           mutually_exclusive=[('disable_my_meraki', 'enable_my_meraki'),
+                                               ]
                            )
 
     meraki = MerakiModule(module, function='network')
@@ -247,6 +271,8 @@ def main():
     if not meraki.params['net_name'] and not meraki.params['net_id']:
         if meraki.params['enable_vlans']:
             meraki.fail_json(msg="The parameter 'enable_vlans' requires 'net_name' or 'net_id' to be specified")
+    if meraki.params['enable_my_meraki'] is True and meraki.params['enable_remote_status_page'] is False:
+        meraki.fail_json(msg='enable_my_meraki must be true when setting enable_remote_status_page')
 
     # 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
@@ -265,8 +291,20 @@ def main():
             payload['tags'] = construct_tags(meraki.params['tags'])
         if meraki.params['timezone']:
             payload['timeZone'] = meraki.params['timezone']
-        if meraki.params['disable_my_meraki'] is not None:
+        if meraki.params['enable_my_meraki'] is not None:
+            if meraki.params['enable_my_meraki'] is True:
+                payload['disableMyMerakiCom'] = False
+            else:
+                payload['disableMyMerakiCom'] = True
+        elif meraki.params['disable_my_meraki'] is not None:
+            meraki.module.deprecate("meraki_network will stop supporting disable_my_meraki in Ansible 2.13. Please update your playbook.", version=2.13)
             payload['disableMyMerakiCom'] = meraki.params['disable_my_meraki']
+        if meraki.params['enable_remote_status_page'] is not None:
+            if meraki.params['enable_remote_status_page'] is True:
+                payload['disableRemoteStatusPage'] = False
+                # meraki.fail_json(msg="Debug", payload=payload)
+            else:
+                payload['disableRemoteStatusPage'] = True
 
     # manipulate or modify the state as needed (this is going to be the
     # part where your module will do what it needs to do)
diff --git a/test/integration/targets/meraki_network/tasks/main.yml b/test/integration/targets/meraki_network/tasks/main.yml
index 9ec9bccd2364fd..0185dcbc3df65d 100644
--- a/test/integration/targets/meraki_network/tasks/main.yml
+++ b/test/integration/targets/meraki_network/tasks/main.yml
@@ -119,7 +119,7 @@
       that:
         - disable_vlan_idempotent is not changed
 
-  - name: Create network with type wireless
+  - name: Create network with type wireless and disable my.meraki.com
     meraki_network:
       auth_key: '{{ auth_key }}'
       state: present
@@ -127,10 +127,11 @@
       net_name: IntTestNetworkWireless
       type: wireless
       timezone: America/Chicago
+      disable_my_meraki: yes
     delegate_to: localhost
     register: create_net_wireless
 
-  - name: Create network with type wireless and check for idempotency
+  - name: Create network with type wireless, disable my.meraki.com, and check for idempotency
     meraki_network:
       auth_key: '{{ auth_key }}'
       state: present
@@ -138,6 +139,7 @@
       net_name: IntTestNetworkWireless
       type: wireless
       timezone: America/Chicago
+      disable_my_meraki: yes
     delegate_to: localhost
     register: create_net_wireless_idempotent
 
@@ -151,7 +153,7 @@
         - appliance
         - switch
       timezone: America/Chicago
-      disable_my_meraki: yes
+      enable_my_meraki: no
     delegate_to: localhost
     register: create_net_combined
 
@@ -161,10 +163,69 @@
       state: present
       org_name: '{{test_org_name}}'
       net_name: IntTestNetworkCombined
-      disable_my_meraki: no
+      enable_my_meraki: yes
     delegate_to: localhost
     register: enable_meraki_com
-    
+
+  - name: Disable my.meraki.com for next test
+    meraki_network:
+      auth_key: '{{ auth_key }}'
+      state: present
+      org_name: '{{test_org_name}}'
+      net_name: IntTestNetworkCombined
+      enable_my_meraki: no
+    delegate_to: localhost
+
+  - name: Enable remote status page
+    meraki_network:
+      auth_key: '{{ auth_key }}'
+      state: present
+      org_name: '{{test_org_name}}'
+      net_name: IntTestNetworkCombined
+      enable_remote_status_page: yes
+    delegate_to: localhost
+    register: disable_remote_status
+
+  - debug:
+      msg: '{{disable_remote_status}}'
+
+  - assert:
+      that:
+        - disable_remote_status.data.disableRemoteStatusPage == False
+
+  - name: Disable remote status page
+    meraki_network:
+      auth_key: '{{ auth_key }}'
+      state: present
+      org_name: '{{test_org_name}}'
+      net_name: IntTestNetworkCombined
+      enable_remote_status_page: no
+    delegate_to: localhost
+    register: enable_remote_status
+
+  - debug:
+      msg: '{{enable_remote_status}}'
+
+  - assert:
+      that:
+        - enable_remote_status.data.disableRemoteStatusPage == True
+
+  - name: Test status pages are mutually exclusive when on
+    meraki_network:
+      auth_key: '{{ auth_key }}'
+      state: present
+      org_name: '{{test_org_name}}'
+      net_name: IntTestNetworkCombined
+      enable_my_meraki: yes
+      enable_remote_status_page: no
+    delegate_to: localhost
+    register: status_exclusivity
+    ignore_errors: yes
+
+  - assert:
+      that:
+        - '"must be true when setting" in status_exclusivity.msg'
+
   - name: Create network with one tag
     meraki_network:
       auth_key: '{{ auth_key }}'
@@ -240,6 +301,7 @@
         - '"IntTestNetworkSwitch" in create_net_switch.data.name'
         - '"IntTestNetworkSwitchOrgID" in create_net_switch_org_id.data.name'
         - '"IntTestNetworkWireless" in create_net_wireless.data.name'
+        - create_net_wireless.data.disableMyMerakiCom == True
         - create_net_wireless_idempotent.changed == False
         - '"first_tag" in create_net_tag.data.tags'
         - '"second_tag" in create_net_tags.data.tags'


Code review comments:
diff_hunk: @@ -265,8 +291,20 @@ def main():
             payload['tags'] = construct_tags(meraki.params['tags'])
         if meraki.params['timezone']:
             payload['timeZone'] = meraki.params['timezone']
-        if meraki.params['disable_my_meraki'] is not None:
+        if meraki.params['enable_my_meraki'] is not None:
+            if meraki.params['enable_my_meraki'] is True:
+                payload['disableMyMerakiCom'] = False
+            else:
+                payload['disableMyMerakiCom'] = True
+        elif meraki.params['disable_my_meraki'] is not None:
+            meraki.module.deprecate("meraki_network will stop supporting disable_my_meraki in Ansible 2.13. Please update your playbook.", version=2.13)
path: lib/ansible/modules/network/meraki/meraki_network.py
text: @user1:
* Name of the new option could be mentioned in the deprecation message.
* `2.13` doesn't need to be mentioned in deprecation message: `This feature will be removed in version 2.13. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.` will automatically be added as suffix.

@author:
Updated.