Meraki - Convert response keys to snake_case from camelCase (#53891)
* Initial proposal for new parameter option for response format - output_version parameter dictates the response key case - new is snake_case, old is camelCase - If new, conversion is done at the end of module execution - This is purely a proposal and not a final draft * Add support for ANSIBLE_MERAKI_FORMAT env var - If env var is set to 'camelcase' it will output camelcase - Otherwise, will default to snakecase - Added note to documentation fragment - As of now, all module documentation needs to be updated * Fix pep8 errors and remove output_version args * Restructure check in exit_json so it actually works * Add changelog fragment * Change output_format to a parameter with env var fallback - ANSIBLE_MERAKI_FORMAT is the valid env var - Added documentation * Convert to camel_dict_to_snake_dict() which is from Ansible - Fixed integration tests * Fix yaml lint error * exit_json camel_case conversion handles no data - exit_json would fail if data wasn't provided - Updated 3 integration tests for new naming convention * convert_camel_to_snake() handles lists and dicts - The native Ansible method doesn't handle first level lists - convert_camel_to_snake() acts simply as a wrapper for the method - There maybe a situation where nested lists are a problem, must test - Fixed integration tests in some modules * A few integration test fixes * Convert response documentation to snake case
This commit is contained in:
parent
5243cba0b2
commit
a85750dc98
16 changed files with 141 additions and 93 deletions
2
changelogs/53891-meraki_snake_case_conversion.yml
Normal file
2
changelogs/53891-meraki_snake_case_conversion.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- Meraki modules now return data in snake_case instead of camelCase. The ANSIBLE_MERAKI_FORMAT environment variable can be set to camelcase to revert back to camelcase until deprecation in Ansible 2.13.
|
|
@ -30,7 +30,9 @@
|
||||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
from ansible.module_utils.basic import AnsibleModule, json, env_fallback
|
from ansible.module_utils.basic import AnsibleModule, json, env_fallback
|
||||||
|
from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict
|
||||||
from ansible.module_utils.urls import fetch_url
|
from ansible.module_utils.urls import fetch_url
|
||||||
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
from ansible.module_utils.six.moves.urllib.parse import urlencode
|
||||||
from ansible.module_utils._text import to_native, to_bytes, to_text
|
from ansible.module_utils._text import to_native, to_bytes, to_text
|
||||||
|
@ -42,6 +44,7 @@ def meraki_argument_spec():
|
||||||
use_proxy=dict(type='bool', default=False),
|
use_proxy=dict(type='bool', default=False),
|
||||||
use_https=dict(type='bool', default=True),
|
use_https=dict(type='bool', default=True),
|
||||||
validate_certs=dict(type='bool', default=True),
|
validate_certs=dict(type='bool', default=True),
|
||||||
|
output_format=dict(type='str', choices=['camelcase', 'snakecase'], default='snakecase', fallback=(env_fallback, ['ANSIBLE_MERAKI_FORMAT'])),
|
||||||
output_level=dict(type='str', default='normal', choices=['normal', 'debug']),
|
output_level=dict(type='str', default='normal', choices=['normal', 'debug']),
|
||||||
timeout=dict(type='int', default=30),
|
timeout=dict(type='int', default=30),
|
||||||
org_name=dict(type='str', aliases=['organization']),
|
org_name=dict(type='str', aliases=['organization']),
|
||||||
|
@ -62,6 +65,7 @@ class MerakiModule(object):
|
||||||
self.org_id = None
|
self.org_id = None
|
||||||
self.net_id = None
|
self.net_id = None
|
||||||
self.check_mode = module.check_mode
|
self.check_mode = module.check_mode
|
||||||
|
self.key_map = {}
|
||||||
|
|
||||||
# normal output
|
# normal output
|
||||||
self.existing = None
|
self.existing = None
|
||||||
|
@ -130,16 +134,25 @@ class MerakiModule(object):
|
||||||
else:
|
else:
|
||||||
self.params['protocol'] = 'http'
|
self.params['protocol'] = 'http'
|
||||||
|
|
||||||
def sanitize(self, original, proposed):
|
def sanitize_keys(self, data):
|
||||||
"""Determine which keys are unique to original"""
|
if isinstance(data, dict):
|
||||||
keys = []
|
items = {}
|
||||||
for k, v in original.items():
|
for k, v in data.items():
|
||||||
try:
|
try:
|
||||||
if proposed[k] and k not in self.ignored_keys:
|
new = {self.key_map[k]: data[k]}
|
||||||
pass
|
items[self.key_map[k]] = self.sanitize_keys(data[k])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
keys.append(k)
|
snake_k = re.sub('([a-z0-9])([A-Z])', r'\1_\2', k).lower()
|
||||||
return keys
|
new = {snake_k: data[k]}
|
||||||
|
items[snake_k] = self.sanitize_keys(data[k])
|
||||||
|
return items
|
||||||
|
elif isinstance(data, list):
|
||||||
|
items = []
|
||||||
|
for i in data:
|
||||||
|
items.append(self.sanitize_keys(i))
|
||||||
|
return items
|
||||||
|
elif isinstance(data, int) or isinstance(data, str) or isinstance(data, float):
|
||||||
|
return data
|
||||||
|
|
||||||
def is_update_required(self, original, proposed, optional_ignore=None):
|
def is_update_required(self, original, proposed, optional_ignore=None):
|
||||||
''' Compare two data-structures '''
|
''' Compare two data-structures '''
|
||||||
|
@ -269,6 +282,20 @@ class MerakiModule(object):
|
||||||
return template['id']
|
return template['id']
|
||||||
self.fail_json(msg='No configuration template named {0} found'.format(name))
|
self.fail_json(msg='No configuration template named {0} found'.format(name))
|
||||||
|
|
||||||
|
def convert_camel_to_snake(self, data):
|
||||||
|
"""
|
||||||
|
Converts a dictionary or list to snake case from camel case
|
||||||
|
:type data: dict or list
|
||||||
|
:return: Converted data structure, if list or dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
if isinstance(data, dict):
|
||||||
|
return camel_dict_to_snake_dict(data, ignore_list=('tags', 'tag'))
|
||||||
|
elif isinstance(data, list):
|
||||||
|
return [camel_dict_to_snake_dict(item, ignore_list=('tags', 'tag')) for item in data]
|
||||||
|
else:
|
||||||
|
return data
|
||||||
|
|
||||||
def construct_params_list(self, keys, aliases=None):
|
def construct_params_list(self, keys, aliases=None):
|
||||||
qs = {}
|
qs = {}
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
@ -344,8 +371,15 @@ class MerakiModule(object):
|
||||||
if self.params['output_level'] == 'debug':
|
if self.params['output_level'] == 'debug':
|
||||||
self.result['method'] = self.method
|
self.result['method'] = self.method
|
||||||
self.result['url'] = self.url
|
self.result['url'] = self.url
|
||||||
|
|
||||||
self.result.update(**kwargs)
|
self.result.update(**kwargs)
|
||||||
|
if self.params['output_format'] == 'camelcase':
|
||||||
|
self.module.deprecate("Update your playbooks to support snake_case format instead of camelCase format.", version=2.13)
|
||||||
|
else:
|
||||||
|
if 'data' in self.result:
|
||||||
|
try:
|
||||||
|
self.result['data'] = self.convert_camel_to_snake(self.result['data'])
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
pass
|
||||||
self.module.exit_json(**self.result)
|
self.module.exit_json(**self.result)
|
||||||
|
|
||||||
def fail_json(self, msg, **kwargs):
|
def fail_json(self, msg, **kwargs):
|
||||||
|
|
|
@ -193,22 +193,22 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: John Doe
|
sample: John Doe
|
||||||
accountStatus:
|
account_status:
|
||||||
description: Status of account.
|
description: Status of account.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: ok
|
sample: ok
|
||||||
twoFactorAuthEnabled:
|
two_factor_auth_enabled:
|
||||||
description: Enabled state of two-factor authentication for administrator.
|
description: Enabled state of two-factor authentication for administrator.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: false
|
sample: false
|
||||||
hasApiKey:
|
has_api_key:
|
||||||
description: Defines whether administrator has an API assigned to their account.
|
description: Defines whether administrator has an API assigned to their account.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: false
|
sample: false
|
||||||
lastActive:
|
last_active:
|
||||||
description: Date and time of time the administrator was active within Dashboard.
|
description: Date and time of time the administrator was active within Dashboard.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
@ -243,7 +243,7 @@ data:
|
||||||
returned: when tag permissions are set
|
returned: when tag permissions are set
|
||||||
type: str
|
type: str
|
||||||
sample: full
|
sample: full
|
||||||
orgAccess:
|
org_access:
|
||||||
description: The privilege of the dashboard administrator on the organization. Options are 'full', 'read-only', or 'none'.
|
description: The privilege of the dashboard administrator on the organization. Options are 'full', 'read-only', or 'none'.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
|
|
@ -154,7 +154,7 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: YourNet
|
sample: YourNet
|
||||||
organizationId:
|
organization_id:
|
||||||
description: Organization ID which owns the network.
|
description: Organization ID which owns the network.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
@ -164,7 +164,7 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: " production wireless "
|
sample: " production wireless "
|
||||||
timeZone:
|
time_zone:
|
||||||
description: Timezone where network resides.
|
description: Timezone where network resides.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
@ -174,7 +174,7 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: switch
|
sample: switch
|
||||||
disableMyMerakiCom:
|
disable_my_meraki_com:
|
||||||
description: States whether U(my.meraki.com) and other device portals should be disabled.
|
description: States whether U(my.meraki.com) and other device portals should be disabled.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
|
|
|
@ -117,32 +117,32 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: 16100
|
sample: 16100
|
||||||
v2cEnabled:
|
v2c_enabled:
|
||||||
description: Shows enabled state of SNMPv2c
|
description: Shows enabled state of SNMPv2c
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
v3Enabled:
|
v3_enabled:
|
||||||
description: Shows enabled state of SNMPv3
|
description: Shows enabled state of SNMPv3
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
v3AuthMode:
|
v3_auth_mode:
|
||||||
description: The SNMP version 3 authentication mode either MD5 or SHA.
|
description: The SNMP version 3 authentication mode either MD5 or SHA.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: SHA
|
sample: SHA
|
||||||
v3PrivMode:
|
v3_priv_mode:
|
||||||
description: The SNMP version 3 privacy mode DES or AES128.
|
description: The SNMP version 3 privacy mode DES or AES128.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: AES128
|
sample: AES128
|
||||||
v2CommunityString:
|
v2_community_string:
|
||||||
description: Automatically generated community string for SNMPv2c.
|
description: Automatically generated community string for SNMPv2c.
|
||||||
returned: When SNMPv2c is enabled.
|
returned: When SNMPv2c is enabled.
|
||||||
type: str
|
type: str
|
||||||
sample: o/8zd-JaSb
|
sample: o/8zd-JaSb
|
||||||
v3User:
|
v3_user:
|
||||||
description: Automatically generated username for SNMPv3.
|
description: Automatically generated username for SNMPv3.
|
||||||
returned: When SNMPv3c is enabled.
|
returned: When SNMPv3c is enabled.
|
||||||
type: str
|
type: str
|
||||||
|
|
|
@ -294,17 +294,17 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
splashPage:
|
splash_page:
|
||||||
description: Splash page to show when user authenticates.
|
description: Splash page to show when user authenticates.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: Click-through splash page
|
sample: Click-through splash page
|
||||||
ssidAdminAccessible:
|
ssid_admin_accessible:
|
||||||
description: Whether SSID is administratively accessible.
|
description: Whether SSID is administratively accessible.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
authMode:
|
auth_mode:
|
||||||
description: Authentication method.
|
description: Authentication method.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
@ -314,37 +314,37 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: SecretWiFiPass
|
sample: SecretWiFiPass
|
||||||
encryptionMode:
|
encryption_mode:
|
||||||
description: Wireless traffic encryption method.
|
description: Wireless traffic encryption method.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: wpa
|
sample: wpa
|
||||||
wpaEncryptionMode:
|
wpa_encryption_mode:
|
||||||
description: Enabled WPA versions.
|
description: Enabled WPA versions.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: WPA2 only
|
sample: WPA2 only
|
||||||
ipAssignmentMode:
|
ip_assignment_mode:
|
||||||
description: Wireless client IP assignment method.
|
description: Wireless client IP assignment method.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: NAT mode
|
sample: NAT mode
|
||||||
minBitrate:
|
min_bitrate:
|
||||||
description: Minimum bitrate a wireless client can connect at.
|
description: Minimum bitrate a wireless client can connect at.
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
sample: 11
|
sample: 11
|
||||||
bandSelection:
|
band_selection:
|
||||||
description: Wireless RF frequency wireless network will be broadcast on.
|
description: Wireless RF frequency wireless network will be broadcast on.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: 5 GHz band only
|
sample: 5 GHz band only
|
||||||
perClientBandwidthLimitUp:
|
per_client_bandwidth_limit_up:
|
||||||
description: Maximum upload bandwidth a client can use.
|
description: Maximum upload bandwidth a client can use.
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
sample: 1000
|
sample: 1000
|
||||||
perClientBandwidthLimitDown:
|
per_client_bandwidth_limit_down:
|
||||||
description: Maximum download bandwidth a client can use.
|
description: Maximum download bandwidth a client can use.
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
|
|
|
@ -192,7 +192,7 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
poeEnabled:
|
poe_enabled:
|
||||||
description: Power Over Ethernet enabled state of port.
|
description: Power Over Ethernet enabled state of port.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
|
@ -207,32 +207,32 @@ data:
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
sample: 10
|
sample: 10
|
||||||
voiceVlan:
|
voice_vlan:
|
||||||
description: VLAN assigned to port with voice VLAN enabled devices.
|
description: VLAN assigned to port with voice VLAN enabled devices.
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
sample: 20
|
sample: 20
|
||||||
isolationEnabled:
|
isolation_enabled:
|
||||||
description: Port isolation status of port.
|
description: Port isolation status of port.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
rstpEnabled:
|
rstp_enabled:
|
||||||
description: Enabled or disabled state of Rapid Spanning Tree Protocol (RSTP)
|
description: Enabled or disabled state of Rapid Spanning Tree Protocol (RSTP)
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: true
|
sample: true
|
||||||
stpGuard:
|
stp_guard:
|
||||||
description: State of STP guard
|
description: State of STP guard
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: "Root Guard"
|
sample: "Root Guard"
|
||||||
accessPolicyNumber:
|
access_policy_number:
|
||||||
description: Number of assigned access policy. Only applicable to access ports.
|
description: Number of assigned access policy. Only applicable to access ports.
|
||||||
returned: success
|
returned: success
|
||||||
type: int
|
type: int
|
||||||
sample: 1234
|
sample: 1234
|
||||||
linkNegotiation:
|
link_negotiation:
|
||||||
description: Link speed for the port.
|
description: Link speed for the port.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
|
|
@ -138,7 +138,7 @@ response:
|
||||||
returned: success
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
contains:
|
contains:
|
||||||
applianceIp:
|
appliance_ip:
|
||||||
description: IP address of Meraki appliance in the VLAN
|
description: IP address of Meraki appliance in the VLAN
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
|
@ -148,7 +148,7 @@ response:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: upstream_dns
|
sample: upstream_dns
|
||||||
fixedIpAssignments:
|
fixed_ip_assignments:
|
||||||
description: List of MAC addresses which have IP addresses assigned.
|
description: List of MAC addresses which have IP addresses assigned.
|
||||||
returned: success
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
|
@ -168,7 +168,7 @@ response:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: fixed_ip
|
sample: fixed_ip
|
||||||
reservedIpRanges:
|
reserved_ip_ranges:
|
||||||
description: List of IP address ranges which are reserved for static assignment.
|
description: List of IP address ranges which are reserved for static assignment.
|
||||||
returned: success
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
|
@ -208,32 +208,32 @@ response:
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: "192.0.1.0/24"
|
sample: "192.0.1.0/24"
|
||||||
dhcpHandling:
|
dhcp_handling:
|
||||||
description: Status of DHCP server on VLAN.
|
description: Status of DHCP server on VLAN.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: Run a DHCP server
|
sample: Run a DHCP server
|
||||||
dhcpLeaseTime:
|
dhcp_lease_time:
|
||||||
description: DHCP lease time when server is active.
|
description: DHCP lease time when server is active.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: 1 day
|
sample: 1 day
|
||||||
dhcpBootOptionsEnabled:
|
dhcp_boot_options_enabled:
|
||||||
description: Whether DHCP boot options are enabled.
|
description: Whether DHCP boot options are enabled.
|
||||||
returned: success
|
returned: success
|
||||||
type: bool
|
type: bool
|
||||||
sample: no
|
sample: no
|
||||||
dhcpBootNextServer:
|
dhcp_boot_next_server:
|
||||||
description: DHCP boot option to direct boot clients to the server to load the boot file from.
|
description: DHCP boot option to direct boot clients to the server to load the boot file from.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: 192.0.1.2
|
sample: 192.0.1.2
|
||||||
dhcpBootFilename:
|
dhcp_boot_filename:
|
||||||
description: Filename for boot file.
|
description: Filename for boot file.
|
||||||
returned: success
|
returned: success
|
||||||
type: str
|
type: str
|
||||||
sample: boot.txt
|
sample: boot.txt
|
||||||
dhcpOptions:
|
dhcp_options:
|
||||||
description: DHCP options.
|
description: DHCP options.
|
||||||
returned: success
|
returned: success
|
||||||
type: complex
|
type: complex
|
||||||
|
|
|
@ -10,6 +10,8 @@ class ModuleDocFragment(object):
|
||||||
notes:
|
notes:
|
||||||
- More information about the Meraki API can be found at U(https://dashboard.meraki.com/api_docs).
|
- More information about the Meraki API can be found at U(https://dashboard.meraki.com/api_docs).
|
||||||
- Some of the options are likely only used for developers within Meraki.
|
- Some of the options are likely only used for developers within Meraki.
|
||||||
|
- As of Ansible 2.9, Meraki modules output keys as snake case. To use camel case, set the C(ANSIBLE_MERAKI_FORMAT) environment variable to C(camelcase).
|
||||||
|
- Ansible's Meraki modules will stop supporting camel case output in Ansible 2.13. Please update your playbooks.
|
||||||
options:
|
options:
|
||||||
auth_key:
|
auth_key:
|
||||||
description:
|
description:
|
||||||
|
@ -32,6 +34,12 @@ options:
|
||||||
- Only useful for internal Meraki developers.
|
- Only useful for internal Meraki developers.
|
||||||
type: bool
|
type: bool
|
||||||
default: yes
|
default: yes
|
||||||
|
output_format:
|
||||||
|
description:
|
||||||
|
- Instructs module whether response keys should be snake case (ex. C(net_id)) or camel case (ex. C(netId)).
|
||||||
|
type: str
|
||||||
|
choices: [snakecase, camelcase]
|
||||||
|
default: snakecase
|
||||||
output_level:
|
output_level:
|
||||||
description:
|
description:
|
||||||
- Set amount of debug output during module execution.
|
- Set amount of debug output during module execution.
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- single_allowed_check.data.allowedUrlPatterns | length == 1
|
- single_allowed_check.data.allowed_url_patterns | length == 1
|
||||||
- single_allowed_check is changed
|
- single_allowed_check is changed
|
||||||
|
|
||||||
- name: Set single allowed URL pattern
|
- name: Set single allowed URL pattern
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- single_allowed.data.allowedUrlPatterns | length == 1
|
- single_allowed.data.allowed_url_patterns | length == 1
|
||||||
|
|
||||||
- name: Set single allowed URL pattern for idempotency with check mode
|
- name: Set single allowed URL pattern for idempotency with check mode
|
||||||
meraki_content_filtering:
|
meraki_content_filtering:
|
||||||
|
@ -83,6 +83,7 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- single_allowed_idempotent_check is not changed
|
- single_allowed_idempotent_check is not changed
|
||||||
|
- single_allowed.data.allowed_url_patterns | length == 1
|
||||||
|
|
||||||
- name: Set single allowed URL pattern for idempotency
|
- name: Set single allowed URL pattern for idempotency
|
||||||
meraki_content_filtering:
|
meraki_content_filtering:
|
||||||
|
@ -117,7 +118,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- single_blocked.data.blockedUrlPatterns | length == 1
|
- single_blocked.data.blocked_url_patterns | length == 1
|
||||||
|
|
||||||
- name: Set two allowed URL pattern
|
- name: Set two allowed URL pattern
|
||||||
meraki_content_filtering:
|
meraki_content_filtering:
|
||||||
|
@ -136,7 +137,7 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- two_allowed.changed == True
|
- two_allowed.changed == True
|
||||||
- two_allowed.data.allowedUrlPatterns | length == 2
|
- two_allowed.data.allowed_url_patterns | length == 2
|
||||||
|
|
||||||
- name: Set blocked URL category
|
- name: Set blocked URL category
|
||||||
meraki_content_filtering:
|
meraki_content_filtering:
|
||||||
|
@ -155,8 +156,8 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- blocked_category.changed == True
|
- blocked_category.changed == True
|
||||||
- blocked_category.data.blockedUrlCategories | length == 1
|
- blocked_category.data.blocked_url_categories | length == 1
|
||||||
- blocked_category.data.urlCategoryListSize == "fullList"
|
- blocked_category.data.url_category_list_size == "fullList"
|
||||||
|
|
||||||
- name: Set blocked URL category with top sites
|
- name: Set blocked URL category with top sites
|
||||||
meraki_content_filtering:
|
meraki_content_filtering:
|
||||||
|
@ -175,8 +176,8 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- blocked_category.changed == True
|
- blocked_category.changed == True
|
||||||
- blocked_category.data.blockedUrlCategories | length == 1
|
- blocked_category.data.blocked_url_categories | length == 1
|
||||||
- blocked_category.data.urlCategoryListSize == "topSites"
|
- blocked_category.data.url_category_list_size == "topSites"
|
||||||
|
|
||||||
always:
|
always:
|
||||||
- name: Reset policies
|
- name: Reset policies
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- create_one.data|length == 2
|
- create_one.data|length == 2
|
||||||
- create_one.data.0.destCidr == '192.0.1.1/32'
|
- create_one.data.0.dest_cidr == '192.0.1.1/32'
|
||||||
- create_one.data.0.protocol == 'tcp'
|
- create_one.data.0.protocol == 'tcp'
|
||||||
- create_one.data.0.policy == 'deny'
|
- create_one.data.0.policy == 'deny'
|
||||||
- create_one.changed == True
|
- create_one.changed == True
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- query.data.1.syslogEnabled == True
|
- query.data.1.syslog_enabled == True
|
||||||
- default_syslog.changed == True
|
- default_syslog.changed == True
|
||||||
|
|
||||||
- name: Disable syslog for default rule
|
- name: Disable syslog for default rule
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- query.data.1.syslogEnabled == False
|
- query.data.1.syslog_enabled == False
|
||||||
- disable_syslog.changed == True
|
- disable_syslog.changed == True
|
||||||
|
|
||||||
always:
|
always:
|
||||||
|
|
|
@ -198,7 +198,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- disable_remote_status.data.disableRemoteStatusPage == False
|
- disable_remote_status.data.disable_remote_status_page == False
|
||||||
|
|
||||||
- name: Disable remote status page
|
- name: Disable remote status page
|
||||||
meraki_network:
|
meraki_network:
|
||||||
|
@ -215,7 +215,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- enable_remote_status.data.disableRemoteStatusPage == True
|
- enable_remote_status.data.disable_remote_status_page == True
|
||||||
|
|
||||||
- name: Test status pages are mutually exclusive when on
|
- name: Test status pages are mutually exclusive when on
|
||||||
meraki_network:
|
meraki_network:
|
||||||
|
@ -300,15 +300,15 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- create_net_combined.data.type == 'combined'
|
- create_net_combined.data.type == 'combined'
|
||||||
- create_net_combined.data.disableMyMerakiCom == True
|
- create_net_combined.data.disable_my_meraki_com == True
|
||||||
- enable_meraki_com.data.disableMyMerakiCom == False
|
- enable_meraki_com.data.disable_my_meraki_com == False
|
||||||
- '"org_name or org_id parameters are required" in create_net_no_org.msg'
|
- '"org_name or org_id parameters are required" in create_net_no_org.msg'
|
||||||
- '"IntTestNetworkAppliance" in create_net_appliance_no_tz.data.name'
|
- '"IntTestNetworkAppliance" in create_net_appliance_no_tz.data.name'
|
||||||
- create_net_appliance_no_tz.changed == True
|
- create_net_appliance_no_tz.changed == True
|
||||||
- '"IntTestNetworkSwitch" in create_net_switch.data.name'
|
- '"IntTestNetworkSwitch" in create_net_switch.data.name'
|
||||||
- '"IntTestNetworkSwitchOrgID" in create_net_switch_org_id.data.name'
|
- '"IntTestNetworkSwitchOrgID" in create_net_switch_org_id.data.name'
|
||||||
- '"IntTestNetworkWireless" in create_net_wireless.data.name'
|
- '"IntTestNetworkWireless" in create_net_wireless.data.name'
|
||||||
- create_net_wireless.data.disableMyMerakiCom == True
|
- create_net_wireless.data.disable_my_meraki_com == True
|
||||||
- create_net_wireless_idempotent.changed == False
|
- create_net_wireless_idempotent.changed == False
|
||||||
- create_net_wireless_idempotent.data is defined
|
- create_net_wireless_idempotent.data is defined
|
||||||
- '"first_tag" in create_net_tag.data.tags'
|
- '"first_tag" in create_net_tag.data.tags'
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- snmp_v2_enable.data.v2CommunityString is defined
|
- snmp_v2_enable.data.v2_community_string is defined
|
||||||
- snmp_v2_enable.data.v2cEnabled == true
|
- snmp_v2_enable.data.v2c_enabled == true
|
||||||
|
|
||||||
- name: Disable SNMPv2c
|
- name: Disable SNMPv2c
|
||||||
meraki_snmp:
|
meraki_snmp:
|
||||||
|
@ -47,8 +47,8 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- snmp_v2_disable.data.v2CommunityString is not defined
|
- snmp_v2_disable.data.v2_community_string is not defined
|
||||||
- snmp_v2_disable.data.v2cEnabled == False
|
- snmp_v2_disable.data.v2c_enabled == False
|
||||||
|
|
||||||
- name: Enable SNMPv2c with org_id
|
- name: Enable SNMPv2c with org_id
|
||||||
meraki_snmp:
|
meraki_snmp:
|
||||||
|
@ -64,8 +64,8 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- snmp_v2_enable_id.data.v2CommunityString is defined
|
- snmp_v2_enable_id.data.v2_community_string is defined
|
||||||
- snmp_v2_enable_id.data.v2cEnabled == true
|
- snmp_v2_enable_id.data.v2c_enabled == true
|
||||||
|
|
||||||
- name: Disable SNMPv2c with org_id
|
- name: Disable SNMPv2c with org_id
|
||||||
meraki_snmp:
|
meraki_snmp:
|
||||||
|
@ -78,8 +78,8 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- snmp_v2_disable_id.data.v2CommunityString is not defined
|
- snmp_v2_disable_id.data.v2_community_string is not defined
|
||||||
- snmp_v2_disable_id.data.v2cEnabled == False
|
- snmp_v2_disable_id.data.v2c_enabled == False
|
||||||
|
|
||||||
- name: Enable SNMPv3
|
- name: Enable SNMPv3
|
||||||
meraki_snmp:
|
meraki_snmp:
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- snmp_v3_enable.data.v3Enabled == True
|
- snmp_v3_enable.data.v3_enabled == True
|
||||||
- snmp_v3_enable.changed == True
|
- snmp_v3_enable.changed == True
|
||||||
|
|
||||||
- name: Check for idempotency
|
- name: Check for idempotency
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- peers.data.peerIps is defined
|
- peers.data.peer_ips is defined
|
||||||
|
|
||||||
- name: Add invalid peer IPs
|
- name: Add invalid peer IPs
|
||||||
meraki_snmp:
|
meraki_snmp:
|
||||||
|
|
|
@ -229,9 +229,9 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- psk.data.authMode == 'psk'
|
- psk.data.auth_mode == 'psk'
|
||||||
- psk.data.encryptionMode == 'wpa'
|
- psk.data.encryption_mode == 'wpa'
|
||||||
- psk.data.wpaEncryptionMode == 'WPA2 only'
|
- psk.data.wpa_encryption_mode == 'WPA2 only'
|
||||||
|
|
||||||
- name: Set PSK with idempotency
|
- name: Set PSK with idempotency
|
||||||
meraki_ssid:
|
meraki_ssid:
|
||||||
|
@ -269,7 +269,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- splash_click.data.splashPage == 'Click-through splash page'
|
- splash_click.data.splash_page == 'Click-through splash page'
|
||||||
|
|
||||||
- name: Configure RADIUS servers
|
- name: Configure RADIUS servers
|
||||||
meraki_ssid:
|
meraki_ssid:
|
||||||
|
@ -291,7 +291,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- set_radius_server.data.radiusServers.0.host == '192.0.1.200'
|
- set_radius_server.data.radius_servers.0.host == '192.0.1.200'
|
||||||
|
|
||||||
- name: Configure RADIUS servers with idempotency
|
- name: Configure RADIUS servers with idempotency
|
||||||
meraki_ssid:
|
meraki_ssid:
|
||||||
|
|
|
@ -194,7 +194,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- update_port_vvlan.data.voiceVlan == 11
|
- update_port_vvlan.data.voice_vlan == 11
|
||||||
- update_port_vvlan.changed == True
|
- update_port_vvlan.changed == True
|
||||||
|
|
||||||
- name: Check access port for idempotenty
|
- name: Check access port for idempotenty
|
||||||
|
@ -242,7 +242,7 @@
|
||||||
that:
|
that:
|
||||||
- update_trunk.data.tags == 'server'
|
- update_trunk.data.tags == 'server'
|
||||||
- update_trunk.data.type == 'trunk'
|
- update_trunk.data.type == 'trunk'
|
||||||
- update_trunk.data.allowedVlans == 'all'
|
- update_trunk.data.allowed_vlans == 'all'
|
||||||
|
|
||||||
- name: Configure trunk port with specific VLANs
|
- name: Configure trunk port with specific VLANs
|
||||||
meraki_switchport:
|
meraki_switchport:
|
||||||
|
@ -269,7 +269,7 @@
|
||||||
that:
|
that:
|
||||||
- update_trunk.data.tags == 'server'
|
- update_trunk.data.tags == 'server'
|
||||||
- update_trunk.data.type == 'trunk'
|
- update_trunk.data.type == 'trunk'
|
||||||
- update_trunk.data.allowedVlans == '8,10,15,20'
|
- update_trunk.data.allowed_vlans == '8,10,15,20'
|
||||||
|
|
||||||
- name: Configure trunk port with specific VLANs and native VLAN
|
- name: Configure trunk port with specific VLANs and native VLAN
|
||||||
meraki_switchport:
|
meraki_switchport:
|
||||||
|
@ -296,7 +296,7 @@
|
||||||
that:
|
that:
|
||||||
- update_trunk.data.tags == 'server'
|
- update_trunk.data.tags == 'server'
|
||||||
- update_trunk.data.type == 'trunk'
|
- update_trunk.data.type == 'trunk'
|
||||||
- update_trunk.data.allowedVlans == '2,10,15,20'
|
- update_trunk.data.allowed_vlans == '2,10,15,20'
|
||||||
|
|
||||||
- name: Check for idempotency on trunk port
|
- name: Check for idempotency on trunk port
|
||||||
meraki_switchport:
|
meraki_switchport:
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
register: invalid_domain
|
register: invalid_domain
|
||||||
ignore_errors: yes
|
ignore_errors: yes
|
||||||
|
|
||||||
- name: Disable HTTP
|
- name: Disable HTTPS
|
||||||
meraki_vlan:
|
meraki_vlan:
|
||||||
auth_key: '{{ auth_key }}'
|
auth_key: '{{ auth_key }}'
|
||||||
use_https: false
|
use_https: false
|
||||||
|
@ -101,6 +101,8 @@
|
||||||
appliance_ip: 192.168.250.1
|
appliance_ip: 192.168.250.1
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
register: create_vlan
|
register: create_vlan
|
||||||
|
environment:
|
||||||
|
ANSIBLE_MERAKI_FORMAT: camelcase
|
||||||
|
|
||||||
- debug:
|
- debug:
|
||||||
msg: '{{create_vlan}}'
|
msg: '{{create_vlan}}'
|
||||||
|
@ -109,6 +111,7 @@
|
||||||
that:
|
that:
|
||||||
- create_vlan.data.id == 2
|
- create_vlan.data.id == 2
|
||||||
- create_vlan.changed == True
|
- create_vlan.changed == True
|
||||||
|
- create_vlan.data.networkId is defined
|
||||||
|
|
||||||
- name: Update VLAN with check mode
|
- name: Update VLAN with check mode
|
||||||
meraki_vlan:
|
meraki_vlan:
|
||||||
|
@ -167,7 +170,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- update_vlan.data.applianceIp == '192.168.250.2'
|
- update_vlan.data.appliance_ip == '192.168.250.2'
|
||||||
- update_vlan.changed == True
|
- update_vlan.changed == True
|
||||||
|
|
||||||
- name: Update VLAN with idempotency and check mode
|
- name: Update VLAN with idempotency and check mode
|
||||||
|
@ -264,8 +267,8 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- update_vlan_add_ip.changed == True
|
- update_vlan_add_ip.changed == True
|
||||||
- update_vlan_add_ip.data.fixedIpAssignments | length == 2
|
- update_vlan_add_ip.data.fixed_ip_assignments | length == 2
|
||||||
- update_vlan_add_ip.data.reservedIpRanges | length == 2
|
- update_vlan_add_ip.data.reserved_ip_ranges | length == 2
|
||||||
|
|
||||||
- name: Remove IP assignments and reserved IP ranges
|
- name: Remove IP assignments and reserved IP ranges
|
||||||
meraki_vlan:
|
meraki_vlan:
|
||||||
|
@ -295,8 +298,8 @@
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- update_vlan_remove_ip.changed == True
|
- update_vlan_remove_ip.changed == True
|
||||||
- update_vlan_remove_ip.data.fixedIpAssignments | length == 1
|
- update_vlan_remove_ip.data.fixed_ip_assignments | length == 1
|
||||||
- update_vlan_remove_ip.data.reservedIpRanges | length == 1
|
- update_vlan_remove_ip.data.reserved_ip_ranges | length == 1
|
||||||
|
|
||||||
- name: Update VLAN with idempotency
|
- name: Update VLAN with idempotency
|
||||||
meraki_vlan:
|
meraki_vlan:
|
||||||
|
@ -355,7 +358,7 @@
|
||||||
|
|
||||||
- assert:
|
- assert:
|
||||||
that:
|
that:
|
||||||
- '"1.1.1.1" in update_vlan_dns_list.data.dnsNameservers'
|
- '"1.1.1.1" in update_vlan_dns_list.data.dns_nameservers'
|
||||||
- update_vlan_dns_list.changed == True
|
- update_vlan_dns_list.changed == True
|
||||||
|
|
||||||
- name: Query all VLANs in network
|
- name: Query all VLANs in network
|
||||||
|
|
Loading…
Reference in a new issue