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.
|
||||
|
||||
import os
|
||||
import re
|
||||
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.six.moves.urllib.parse import urlencode
|
||||
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_https=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']),
|
||||
timeout=dict(type='int', default=30),
|
||||
org_name=dict(type='str', aliases=['organization']),
|
||||
|
@ -62,6 +65,7 @@ class MerakiModule(object):
|
|||
self.org_id = None
|
||||
self.net_id = None
|
||||
self.check_mode = module.check_mode
|
||||
self.key_map = {}
|
||||
|
||||
# normal output
|
||||
self.existing = None
|
||||
|
@ -130,16 +134,25 @@ class MerakiModule(object):
|
|||
else:
|
||||
self.params['protocol'] = 'http'
|
||||
|
||||
def sanitize(self, original, proposed):
|
||||
"""Determine which keys are unique to original"""
|
||||
keys = []
|
||||
for k, v in original.items():
|
||||
def sanitize_keys(self, data):
|
||||
if isinstance(data, dict):
|
||||
items = {}
|
||||
for k, v in data.items():
|
||||
try:
|
||||
if proposed[k] and k not in self.ignored_keys:
|
||||
pass
|
||||
new = {self.key_map[k]: data[k]}
|
||||
items[self.key_map[k]] = self.sanitize_keys(data[k])
|
||||
except KeyError:
|
||||
keys.append(k)
|
||||
return keys
|
||||
snake_k = re.sub('([a-z0-9])([A-Z])', r'\1_\2', k).lower()
|
||||
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):
|
||||
''' Compare two data-structures '''
|
||||
|
@ -269,6 +282,20 @@ class MerakiModule(object):
|
|||
return template['id']
|
||||
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):
|
||||
qs = {}
|
||||
for key in keys:
|
||||
|
@ -344,8 +371,15 @@ class MerakiModule(object):
|
|||
if self.params['output_level'] == 'debug':
|
||||
self.result['method'] = self.method
|
||||
self.result['url'] = self.url
|
||||
|
||||
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)
|
||||
|
||||
def fail_json(self, msg, **kwargs):
|
||||
|
|
|
@ -193,22 +193,22 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: John Doe
|
||||
accountStatus:
|
||||
account_status:
|
||||
description: Status of account.
|
||||
returned: success
|
||||
type: str
|
||||
sample: ok
|
||||
twoFactorAuthEnabled:
|
||||
two_factor_auth_enabled:
|
||||
description: Enabled state of two-factor authentication for administrator.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
hasApiKey:
|
||||
has_api_key:
|
||||
description: Defines whether administrator has an API assigned to their account.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: false
|
||||
lastActive:
|
||||
last_active:
|
||||
description: Date and time of time the administrator was active within Dashboard.
|
||||
returned: success
|
||||
type: str
|
||||
|
@ -243,7 +243,7 @@ data:
|
|||
returned: when tag permissions are set
|
||||
type: str
|
||||
sample: full
|
||||
orgAccess:
|
||||
org_access:
|
||||
description: The privilege of the dashboard administrator on the organization. Options are 'full', 'read-only', or 'none'.
|
||||
returned: success
|
||||
type: str
|
||||
|
|
|
@ -154,7 +154,7 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: YourNet
|
||||
organizationId:
|
||||
organization_id:
|
||||
description: Organization ID which owns the network.
|
||||
returned: success
|
||||
type: str
|
||||
|
@ -164,7 +164,7 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: " production wireless "
|
||||
timeZone:
|
||||
time_zone:
|
||||
description: Timezone where network resides.
|
||||
returned: success
|
||||
type: str
|
||||
|
@ -174,7 +174,7 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: switch
|
||||
disableMyMerakiCom:
|
||||
disable_my_meraki_com:
|
||||
description: States whether U(my.meraki.com) and other device portals should be disabled.
|
||||
returned: success
|
||||
type: bool
|
||||
|
|
|
@ -117,32 +117,32 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: 16100
|
||||
v2cEnabled:
|
||||
v2c_enabled:
|
||||
description: Shows enabled state of SNMPv2c
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
v3Enabled:
|
||||
v3_enabled:
|
||||
description: Shows enabled state of SNMPv3
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
v3AuthMode:
|
||||
v3_auth_mode:
|
||||
description: The SNMP version 3 authentication mode either MD5 or SHA.
|
||||
returned: success
|
||||
type: str
|
||||
sample: SHA
|
||||
v3PrivMode:
|
||||
v3_priv_mode:
|
||||
description: The SNMP version 3 privacy mode DES or AES128.
|
||||
returned: success
|
||||
type: str
|
||||
sample: AES128
|
||||
v2CommunityString:
|
||||
v2_community_string:
|
||||
description: Automatically generated community string for SNMPv2c.
|
||||
returned: When SNMPv2c is enabled.
|
||||
type: str
|
||||
sample: o/8zd-JaSb
|
||||
v3User:
|
||||
v3_user:
|
||||
description: Automatically generated username for SNMPv3.
|
||||
returned: When SNMPv3c is enabled.
|
||||
type: str
|
||||
|
|
|
@ -294,17 +294,17 @@ data:
|
|||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
splashPage:
|
||||
splash_page:
|
||||
description: Splash page to show when user authenticates.
|
||||
returned: success
|
||||
type: str
|
||||
sample: Click-through splash page
|
||||
ssidAdminAccessible:
|
||||
ssid_admin_accessible:
|
||||
description: Whether SSID is administratively accessible.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
authMode:
|
||||
auth_mode:
|
||||
description: Authentication method.
|
||||
returned: success
|
||||
type: str
|
||||
|
@ -314,37 +314,37 @@ data:
|
|||
returned: success
|
||||
type: str
|
||||
sample: SecretWiFiPass
|
||||
encryptionMode:
|
||||
encryption_mode:
|
||||
description: Wireless traffic encryption method.
|
||||
returned: success
|
||||
type: str
|
||||
sample: wpa
|
||||
wpaEncryptionMode:
|
||||
wpa_encryption_mode:
|
||||
description: Enabled WPA versions.
|
||||
returned: success
|
||||
type: str
|
||||
sample: WPA2 only
|
||||
ipAssignmentMode:
|
||||
ip_assignment_mode:
|
||||
description: Wireless client IP assignment method.
|
||||
returned: success
|
||||
type: str
|
||||
sample: NAT mode
|
||||
minBitrate:
|
||||
min_bitrate:
|
||||
description: Minimum bitrate a wireless client can connect at.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 11
|
||||
bandSelection:
|
||||
band_selection:
|
||||
description: Wireless RF frequency wireless network will be broadcast on.
|
||||
returned: success
|
||||
type: str
|
||||
sample: 5 GHz band only
|
||||
perClientBandwidthLimitUp:
|
||||
per_client_bandwidth_limit_up:
|
||||
description: Maximum upload bandwidth a client can use.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1000
|
||||
perClientBandwidthLimitDown:
|
||||
per_client_bandwidth_limit_down:
|
||||
description: Maximum download bandwidth a client can use.
|
||||
returned: success
|
||||
type: int
|
||||
|
|
|
@ -192,7 +192,7 @@ data:
|
|||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
poeEnabled:
|
||||
poe_enabled:
|
||||
description: Power Over Ethernet enabled state of port.
|
||||
returned: success
|
||||
type: bool
|
||||
|
@ -207,32 +207,32 @@ data:
|
|||
returned: success
|
||||
type: int
|
||||
sample: 10
|
||||
voiceVlan:
|
||||
voice_vlan:
|
||||
description: VLAN assigned to port with voice VLAN enabled devices.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 20
|
||||
isolationEnabled:
|
||||
isolation_enabled:
|
||||
description: Port isolation status of port.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
rstpEnabled:
|
||||
rstp_enabled:
|
||||
description: Enabled or disabled state of Rapid Spanning Tree Protocol (RSTP)
|
||||
returned: success
|
||||
type: bool
|
||||
sample: true
|
||||
stpGuard:
|
||||
stp_guard:
|
||||
description: State of STP guard
|
||||
returned: success
|
||||
type: str
|
||||
sample: "Root Guard"
|
||||
accessPolicyNumber:
|
||||
access_policy_number:
|
||||
description: Number of assigned access policy. Only applicable to access ports.
|
||||
returned: success
|
||||
type: int
|
||||
sample: 1234
|
||||
linkNegotiation:
|
||||
link_negotiation:
|
||||
description: Link speed for the port.
|
||||
returned: success
|
||||
type: str
|
||||
|
|
|
@ -138,7 +138,7 @@ response:
|
|||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
applianceIp:
|
||||
appliance_ip:
|
||||
description: IP address of Meraki appliance in the VLAN
|
||||
returned: success
|
||||
type: str
|
||||
|
@ -148,7 +148,7 @@ response:
|
|||
returned: success
|
||||
type: str
|
||||
sample: upstream_dns
|
||||
fixedIpAssignments:
|
||||
fixed_ip_assignments:
|
||||
description: List of MAC addresses which have IP addresses assigned.
|
||||
returned: success
|
||||
type: complex
|
||||
|
@ -168,7 +168,7 @@ response:
|
|||
returned: success
|
||||
type: str
|
||||
sample: fixed_ip
|
||||
reservedIpRanges:
|
||||
reserved_ip_ranges:
|
||||
description: List of IP address ranges which are reserved for static assignment.
|
||||
returned: success
|
||||
type: complex
|
||||
|
@ -208,32 +208,32 @@ response:
|
|||
returned: success
|
||||
type: str
|
||||
sample: "192.0.1.0/24"
|
||||
dhcpHandling:
|
||||
dhcp_handling:
|
||||
description: Status of DHCP server on VLAN.
|
||||
returned: success
|
||||
type: str
|
||||
sample: Run a DHCP server
|
||||
dhcpLeaseTime:
|
||||
dhcp_lease_time:
|
||||
description: DHCP lease time when server is active.
|
||||
returned: success
|
||||
type: str
|
||||
sample: 1 day
|
||||
dhcpBootOptionsEnabled:
|
||||
dhcp_boot_options_enabled:
|
||||
description: Whether DHCP boot options are enabled.
|
||||
returned: success
|
||||
type: bool
|
||||
sample: no
|
||||
dhcpBootNextServer:
|
||||
dhcp_boot_next_server:
|
||||
description: DHCP boot option to direct boot clients to the server to load the boot file from.
|
||||
returned: success
|
||||
type: str
|
||||
sample: 192.0.1.2
|
||||
dhcpBootFilename:
|
||||
dhcp_boot_filename:
|
||||
description: Filename for boot file.
|
||||
returned: success
|
||||
type: str
|
||||
sample: boot.txt
|
||||
dhcpOptions:
|
||||
dhcp_options:
|
||||
description: DHCP options.
|
||||
returned: success
|
||||
type: complex
|
||||
|
|
|
@ -10,6 +10,8 @@ class ModuleDocFragment(object):
|
|||
notes:
|
||||
- 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.
|
||||
- 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:
|
||||
auth_key:
|
||||
description:
|
||||
|
@ -32,6 +34,12 @@ options:
|
|||
- Only useful for internal Meraki developers.
|
||||
type: bool
|
||||
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:
|
||||
description:
|
||||
- Set amount of debug output during module execution.
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- single_allowed_check.data.allowedUrlPatterns | length == 1
|
||||
- single_allowed_check.data.allowed_url_patterns | length == 1
|
||||
- single_allowed_check is changed
|
||||
|
||||
- name: Set single allowed URL pattern
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
- assert:
|
||||
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
|
||||
meraki_content_filtering:
|
||||
|
@ -83,6 +83,7 @@
|
|||
- assert:
|
||||
that:
|
||||
- single_allowed_idempotent_check is not changed
|
||||
- single_allowed.data.allowed_url_patterns | length == 1
|
||||
|
||||
- name: Set single allowed URL pattern for idempotency
|
||||
meraki_content_filtering:
|
||||
|
@ -117,7 +118,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- single_blocked.data.blockedUrlPatterns | length == 1
|
||||
- single_blocked.data.blocked_url_patterns | length == 1
|
||||
|
||||
- name: Set two allowed URL pattern
|
||||
meraki_content_filtering:
|
||||
|
@ -136,7 +137,7 @@
|
|||
- assert:
|
||||
that:
|
||||
- two_allowed.changed == True
|
||||
- two_allowed.data.allowedUrlPatterns | length == 2
|
||||
- two_allowed.data.allowed_url_patterns | length == 2
|
||||
|
||||
- name: Set blocked URL category
|
||||
meraki_content_filtering:
|
||||
|
@ -155,8 +156,8 @@
|
|||
- assert:
|
||||
that:
|
||||
- blocked_category.changed == True
|
||||
- blocked_category.data.blockedUrlCategories | length == 1
|
||||
- blocked_category.data.urlCategoryListSize == "fullList"
|
||||
- blocked_category.data.blocked_url_categories | length == 1
|
||||
- blocked_category.data.url_category_list_size == "fullList"
|
||||
|
||||
- name: Set blocked URL category with top sites
|
||||
meraki_content_filtering:
|
||||
|
@ -175,8 +176,8 @@
|
|||
- assert:
|
||||
that:
|
||||
- blocked_category.changed == True
|
||||
- blocked_category.data.blockedUrlCategories | length == 1
|
||||
- blocked_category.data.urlCategoryListSize == "topSites"
|
||||
- blocked_category.data.blocked_url_categories | length == 1
|
||||
- blocked_category.data.url_category_list_size == "topSites"
|
||||
|
||||
always:
|
||||
- name: Reset policies
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
- assert:
|
||||
that:
|
||||
- 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.policy == 'deny'
|
||||
- create_one.changed == True
|
||||
|
@ -165,7 +165,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- query.data.1.syslogEnabled == True
|
||||
- query.data.1.syslog_enabled == True
|
||||
- default_syslog.changed == True
|
||||
|
||||
- name: Disable syslog for default rule
|
||||
|
@ -207,7 +207,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- query.data.1.syslogEnabled == False
|
||||
- query.data.1.syslog_enabled == False
|
||||
- disable_syslog.changed == True
|
||||
|
||||
always:
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- disable_remote_status.data.disableRemoteStatusPage == False
|
||||
- disable_remote_status.data.disable_remote_status_page == False
|
||||
|
||||
- name: Disable remote status page
|
||||
meraki_network:
|
||||
|
@ -215,7 +215,7 @@
|
|||
|
||||
- assert:
|
||||
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
|
||||
meraki_network:
|
||||
|
@ -300,15 +300,15 @@
|
|||
assert:
|
||||
that:
|
||||
- create_net_combined.data.type == 'combined'
|
||||
- create_net_combined.data.disableMyMerakiCom == True
|
||||
- enable_meraki_com.data.disableMyMerakiCom == False
|
||||
- create_net_combined.data.disable_my_meraki_com == True
|
||||
- enable_meraki_com.data.disable_my_meraki_com == False
|
||||
- '"org_name or org_id parameters are required" in create_net_no_org.msg'
|
||||
- '"IntTestNetworkAppliance" in create_net_appliance_no_tz.data.name'
|
||||
- create_net_appliance_no_tz.changed == True
|
||||
- '"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.data.disable_my_meraki_com == True
|
||||
- create_net_wireless_idempotent.changed == False
|
||||
- create_net_wireless_idempotent.data is defined
|
||||
- '"first_tag" in create_net_tag.data.tags'
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- snmp_v2_enable.data.v2CommunityString is defined
|
||||
- snmp_v2_enable.data.v2cEnabled == true
|
||||
- snmp_v2_enable.data.v2_community_string is defined
|
||||
- snmp_v2_enable.data.v2c_enabled == true
|
||||
|
||||
- name: Disable SNMPv2c
|
||||
meraki_snmp:
|
||||
|
@ -47,8 +47,8 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- snmp_v2_disable.data.v2CommunityString is not defined
|
||||
- snmp_v2_disable.data.v2cEnabled == False
|
||||
- snmp_v2_disable.data.v2_community_string is not defined
|
||||
- snmp_v2_disable.data.v2c_enabled == False
|
||||
|
||||
- name: Enable SNMPv2c with org_id
|
||||
meraki_snmp:
|
||||
|
@ -64,8 +64,8 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- snmp_v2_enable_id.data.v2CommunityString is defined
|
||||
- snmp_v2_enable_id.data.v2cEnabled == true
|
||||
- snmp_v2_enable_id.data.v2_community_string is defined
|
||||
- snmp_v2_enable_id.data.v2c_enabled == true
|
||||
|
||||
- name: Disable SNMPv2c with org_id
|
||||
meraki_snmp:
|
||||
|
@ -78,8 +78,8 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- snmp_v2_disable_id.data.v2CommunityString is not defined
|
||||
- snmp_v2_disable_id.data.v2cEnabled == False
|
||||
- snmp_v2_disable_id.data.v2_community_string is not defined
|
||||
- snmp_v2_disable_id.data.v2c_enabled == False
|
||||
|
||||
- name: Enable SNMPv3
|
||||
meraki_snmp:
|
||||
|
@ -96,7 +96,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- snmp_v3_enable.data.v3Enabled == True
|
||||
- snmp_v3_enable.data.v3_enabled == True
|
||||
- snmp_v3_enable.changed == True
|
||||
|
||||
- name: Check for idempotency
|
||||
|
@ -139,7 +139,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- peers.data.peerIps is defined
|
||||
- peers.data.peer_ips is defined
|
||||
|
||||
- name: Add invalid peer IPs
|
||||
meraki_snmp:
|
||||
|
|
|
@ -229,9 +229,9 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- psk.data.authMode == 'psk'
|
||||
- psk.data.encryptionMode == 'wpa'
|
||||
- psk.data.wpaEncryptionMode == 'WPA2 only'
|
||||
- psk.data.auth_mode == 'psk'
|
||||
- psk.data.encryption_mode == 'wpa'
|
||||
- psk.data.wpa_encryption_mode == 'WPA2 only'
|
||||
|
||||
- name: Set PSK with idempotency
|
||||
meraki_ssid:
|
||||
|
@ -269,7 +269,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- splash_click.data.splashPage == 'Click-through splash page'
|
||||
- splash_click.data.splash_page == 'Click-through splash page'
|
||||
|
||||
- name: Configure RADIUS servers
|
||||
meraki_ssid:
|
||||
|
@ -291,7 +291,7 @@
|
|||
|
||||
- assert:
|
||||
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
|
||||
meraki_ssid:
|
||||
|
|
|
@ -194,7 +194,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- update_port_vvlan.data.voiceVlan == 11
|
||||
- update_port_vvlan.data.voice_vlan == 11
|
||||
- update_port_vvlan.changed == True
|
||||
|
||||
- name: Check access port for idempotenty
|
||||
|
@ -242,7 +242,7 @@
|
|||
that:
|
||||
- update_trunk.data.tags == 'server'
|
||||
- update_trunk.data.type == 'trunk'
|
||||
- update_trunk.data.allowedVlans == 'all'
|
||||
- update_trunk.data.allowed_vlans == 'all'
|
||||
|
||||
- name: Configure trunk port with specific VLANs
|
||||
meraki_switchport:
|
||||
|
@ -269,7 +269,7 @@
|
|||
that:
|
||||
- update_trunk.data.tags == 'server'
|
||||
- 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
|
||||
meraki_switchport:
|
||||
|
@ -296,7 +296,7 @@
|
|||
that:
|
||||
- update_trunk.data.tags == 'server'
|
||||
- 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
|
||||
meraki_switchport:
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
register: invalid_domain
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Disable HTTP
|
||||
- name: Disable HTTPS
|
||||
meraki_vlan:
|
||||
auth_key: '{{ auth_key }}'
|
||||
use_https: false
|
||||
|
@ -101,6 +101,8 @@
|
|||
appliance_ip: 192.168.250.1
|
||||
delegate_to: localhost
|
||||
register: create_vlan
|
||||
environment:
|
||||
ANSIBLE_MERAKI_FORMAT: camelcase
|
||||
|
||||
- debug:
|
||||
msg: '{{create_vlan}}'
|
||||
|
@ -109,6 +111,7 @@
|
|||
that:
|
||||
- create_vlan.data.id == 2
|
||||
- create_vlan.changed == True
|
||||
- create_vlan.data.networkId is defined
|
||||
|
||||
- name: Update VLAN with check mode
|
||||
meraki_vlan:
|
||||
|
@ -167,7 +170,7 @@
|
|||
|
||||
- assert:
|
||||
that:
|
||||
- update_vlan.data.applianceIp == '192.168.250.2'
|
||||
- update_vlan.data.appliance_ip == '192.168.250.2'
|
||||
- update_vlan.changed == True
|
||||
|
||||
- name: Update VLAN with idempotency and check mode
|
||||
|
@ -264,8 +267,8 @@
|
|||
- assert:
|
||||
that:
|
||||
- update_vlan_add_ip.changed == True
|
||||
- update_vlan_add_ip.data.fixedIpAssignments | length == 2
|
||||
- update_vlan_add_ip.data.reservedIpRanges | length == 2
|
||||
- update_vlan_add_ip.data.fixed_ip_assignments | length == 2
|
||||
- update_vlan_add_ip.data.reserved_ip_ranges | length == 2
|
||||
|
||||
- name: Remove IP assignments and reserved IP ranges
|
||||
meraki_vlan:
|
||||
|
@ -295,8 +298,8 @@
|
|||
- assert:
|
||||
that:
|
||||
- update_vlan_remove_ip.changed == True
|
||||
- update_vlan_remove_ip.data.fixedIpAssignments | length == 1
|
||||
- update_vlan_remove_ip.data.reservedIpRanges | length == 1
|
||||
- update_vlan_remove_ip.data.fixed_ip_assignments | length == 1
|
||||
- update_vlan_remove_ip.data.reserved_ip_ranges | length == 1
|
||||
|
||||
- name: Update VLAN with idempotency
|
||||
meraki_vlan:
|
||||
|
@ -355,7 +358,7 @@
|
|||
|
||||
- assert:
|
||||
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
|
||||
|
||||
- name: Query all VLANs in network
|
||||
|
|
Loading…
Reference in a new issue