def main(): # define the available arguments/parameters that a user can pass to # the module one_to_one_allowed_inbound_spec = dict( protocol=dict(type='str', choices=['tcp', 'udp', 'icmp-ping', 'any'], default='any'), destination_ports=dict(type='list', element='str'), allowed_ips=dict(type='list'), ) one_to_many_port_inbound_spec = dict( protocol=dict(type='str', choices=['tcp', 'udp']), name=dict(type='str'), local_ip=dict(type='str'), local_port=dict(type='str'), allowed_ips=dict(type='list'), public_port=dict(type='str'), ) one_to_one_spec = dict( name=dict(type='str'), public_ip=dict(type='str'), lan_ip=dict(type='str'), uplink=dict(type='str', choices=['internet1', 'internet2', 'both']), allowed_inbound=dict(type='list', element='dict', options=one_to_one_allowed_inbound_spec), ) one_to_many_spec = dict( public_ip=dict(type='str'), uplink=dict(type='str', choices=['internet1', 'internet2', 'both']), port_rules=dict(type='list', element='dict', options=one_to_many_port_inbound_spec), ) port_forwarding_spec = dict( name=dict(type='str'), lan_ip=dict(type='str'), uplink=dict(type='str', choices=['internet1', 'internet2', 'both']), protocol=dict(type='str', choices=['tcp', 'udp']), public_port=dict(type='int'), local_port=dict(type='int'), allowed_ips=dict(type='list'), ) argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), net_name=dict(type='str', aliases=['name', 'network']), state=dict(type='str', choices=['present', 'query'], default='present'), subset=dict(type='list', choices=['1:1', '1:many', 'all', 'port_forwarding'], default='all'), one_to_one=dict(type='list', elements='dict', options=one_to_one_spec), one_to_many=dict(type='list', elements='dict', options=one_to_many_spec), port_forwarding=dict(type='list', elements='dict', options=port_forwarding_spec), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='nat') module.params['follow_redirects'] = 'all' one_to_one_payload = None one_to_many_payload = None port_forwarding_payload = None if meraki.params['state'] == 'present': if meraki.params['one_to_one'] is not None: rules = [] for i in meraki.params['one_to_one']: data = { 'name': i['name'], 'publicIp': i['public_ip'], 'uplink': i['uplink'], 'lanIp': i['lan_ip'], 'allowedInbound': construct_payload(i['allowed_inbound']) } for inbound in data['allowedInbound']: inbound['destinationPorts'] = list_int_to_str( inbound['destinationPorts']) rules.append(data) one_to_one_payload = {'rules': rules} if meraki.params['one_to_many'] is not None: rules = [] for i in meraki.params['one_to_many']: data = { 'publicIp': i['public_ip'], 'uplink': i['uplink'], } port_rules = [] for port_rule in i['port_rules']: rule = { 'name': port_rule['name'], 'protocol': port_rule['protocol'], 'publicPort': str(port_rule['public_port']), 'localIp': port_rule['local_ip'], 'localPort': str(port_rule['local_port']), 'allowedIps': port_rule['allowed_ips'], } port_rules.append(rule) data['portRules'] = port_rules rules.append(data) one_to_many_payload = {'rules': rules} if meraki.params['port_forwarding'] is not None: port_forwarding_payload = { 'rules': construct_payload(meraki.params['port_forwarding']) } for rule in port_forwarding_payload['rules']: rule['localPort'] = str(rule['localPort']) rule['publicPort'] = str(rule['publicPort']) onetomany_urls = {'nat': '/networks/{net_id}/oneToManyNatRules'} onetoone_urls = {'nat': '/networks/{net_id}/oneToOneNatRules'} port_forwarding_urls = {'nat': '/networks/{net_id}/portForwardingRules'} meraki.url_catalog['1:many'] = onetomany_urls meraki.url_catalog['1:1'] = onetoone_urls meraki.url_catalog['port_forwarding'] = port_forwarding_urls if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive') org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(org_id, meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if meraki.params['subset'][0] == 'all': path = meraki.construct_path('1:many', net_id=net_id) data = {'1:many': meraki.request(path, method='GET')} path = meraki.construct_path('1:1', net_id=net_id) data['1:1'] = meraki.request(path, method='GET') path = meraki.construct_path('port_forwarding', net_id=net_id) data['port_forwarding'] = meraki.request(path, method='GET') meraki.result['data'] = data else: for subset in meraki.params['subset']: path = meraki.construct_path(subset, net_id=net_id) data = {subset: meraki.request(path, method='GET')} try: meraki.result['data'][subset] = data except KeyError: meraki.result['data'] = {subset: data} elif meraki.params['state'] == 'present': meraki.result['data'] = dict() if one_to_one_payload is not None: path = meraki.construct_path('1:1', net_id=net_id) current = meraki.request(path, method='GET') if meraki.is_update_required(current, one_to_one_payload): if meraki.module.check_mode is True: diff = recursive_diff(current, one_to_one_payload) current.update(one_to_one_payload) if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} meraki.result['diff']['before'].update( {'one_to_one': diff[0]}) meraki.result['diff']['after'].update( {'one_to_one': diff[1]}) meraki.result['data'] = {'one_to_one': current} meraki.result['changed'] = True else: r = meraki.request(path, method='PUT', payload=json.dumps(one_to_one_payload)) if meraki.status == 200: diff = recursive_diff(current, one_to_one_payload) if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} meraki.result['diff']['before'].update( {'one_to_one': diff[0]}) meraki.result['diff']['after'].update( {'one_to_one': diff[1]}) meraki.result['data'] = {'one_to_one': r} meraki.result['changed'] = True else: meraki.result['data']['one_to_one'] = current if one_to_many_payload is not None: path = meraki.construct_path('1:many', net_id=net_id) current = meraki.request(path, method='GET') if meraki.is_update_required(current, one_to_many_payload): if meraki.module.check_mode is True: diff = recursive_diff(current, one_to_many_payload) current.update(one_to_many_payload) if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} meraki.result['diff']['before'].update( {'one_to_many': diff[0]}) meraki.result['diff']['after'].update( {'one_to_many': diff[1]}) meraki.result['data']['one_to_many'] = current meraki.result['changed'] = True else: r = meraki.request(path, method='PUT', payload=json.dumps(one_to_many_payload)) if meraki.status == 200: diff = recursive_diff(current, one_to_many_payload) if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} meraki.result['diff']['before'].update( {'one_to_many': diff[0]}) meraki.result['diff']['after'].update( {'one_to_many': diff[1]}) meraki.result['data'].update({'one_to_many': r}) meraki.result['changed'] = True else: meraki.result['data']['one_to_many'] = current if port_forwarding_payload is not None: path = meraki.construct_path('port_forwarding', net_id=net_id) current = meraki.request(path, method='GET') if meraki.is_update_required(current, port_forwarding_payload): if meraki.module.check_mode is True: diff = recursive_diff(current, port_forwarding_payload) current.update(port_forwarding_payload) if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} meraki.result['diff']['before'].update( {'port_forwarding': diff[0]}) meraki.result['diff']['after'].update( {'port_forwarding': diff[1]}) meraki.result['data']['port_forwarding'] = current meraki.result['changed'] = True else: r = meraki.request( path, method='PUT', payload=json.dumps(port_forwarding_payload)) if meraki.status == 200: if 'diff' not in meraki.result: meraki.result['diff'] = {'before': {}, 'after': {}} diff = recursive_diff(current, port_forwarding_payload) meraki.result['diff']['before'].update( {'port_forwarding': diff[0]}) meraki.result['diff']['after'].update( {'port_forwarding': diff[1]}) meraki.result['data'].update({'port_forwarding': r}) meraki.result['changed'] = True else: meraki.result['data']['port_forwarding'] = current # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module fw_rules = dict( policy=dict(type='str', choices=['allow', 'deny']), protocol=dict(type='str', choices=['tcp', 'udp', 'icmp', 'any']), dest_port=dict(type='str'), dest_cidr=dict(type='str'), comment=dict(type='str'), ) argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['present', 'query'], default='present'), net_name=dict(type='str'), net_id=dict(type='str'), number=dict(type='str', aliases=['ssid_number']), ssid_name=dict(type='str', aliases=['ssid']), rules=dict(type='list', default=None, elements='dict', options=fw_rules), allow_lan_access=dict(type='bool', default=True), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='mr_l3_firewall') meraki.params['follow_redirects'] = 'all' query_urls = { 'mr_l3_firewall': '/networks/{net_id}/ssids/{number}/l3FirewallRules' } update_urls = { 'mr_l3_firewall': '/networks/{net_id}/ssids/{number}/l3FirewallRules' } meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['update'] = update_urls payload = None # 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 # state with no modifications # FIXME: Work with Meraki so they can implement a check mode if module.check_mode: meraki.exit_json(**meraki.result) # execute checks for argument completeness # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] orgs = None if org_id is None: orgs = meraki.get_orgs() for org in orgs: if org['name'] == meraki.params['org_name']: org_id = org['id'] net_id = meraki.params['net_id'] if net_id is None: if orgs is None: orgs = meraki.get_orgs() net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=meraki.get_nets(org_id=org_id)) number = meraki.params['number'] if meraki.params['ssid_name']: number = get_ssid_number(meraki.params['ssid_name'], get_ssids(meraki, net_id)) if meraki.params['state'] == 'query': meraki.result['data'] = get_rules(meraki, net_id, number) elif meraki.params['state'] == 'present': rules = get_rules(meraki, net_id, number) path = meraki.construct_path('get_all', net_id=net_id, custom={'number': number}) if meraki.params['rules']: payload = assemble_payload(meraki) else: payload = dict() update = False try: if len(rules) != len( payload['rules'] ): # Quick and simple check to avoid more processing update = True if update is False: for r in range(len(rules) - 2): if meraki.is_update_required(rules[r], payload[r]) is True: update = True except KeyError: pass if rules[len(rules) - 2] != meraki.params['allow_lan_access']: update = True if update is True: payload['allowLanAccess'] = meraki.params['allow_lan_access'] response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = rules # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module server_arg_spec = dict( host=dict(type='str'), port=dict(type='int', default="514"), roles=dict(type='list', choices=[ 'Wireless Event log', 'Appliance event log', 'Switch event log', 'Air Marshal events', 'Flows', 'URLs', 'IDS alerts', 'Security events', ]), ) argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), servers=dict(type='list', elements='dict', options=server_arg_spec), state=dict(type='str', choices=['present', 'query'], default='present'), net_name=dict(type='str', aliases=['name', 'network']), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='syslog') module.params['follow_redirects'] = 'all' payload = None syslog_urls = {'syslog': '/networks/{net_id}/syslogServers'} meraki.url_catalog['query_update'] = syslog_urls if not meraki.params['org_name'] and not meraki.params['org_id']: meraki.fail_json(msg='org_name or org_id parameters are required') if meraki.params['state'] != 'query': if not meraki.params['net_name'] and not meraki.params['net_id']: meraki.fail_json( msg= 'net_name or net_id is required for present or absent states') if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive') # 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 # state with no modifications # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': path = meraki.construct_path('query_update', net_id=net_id) r = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = r elif meraki.params['state'] == 'present': # Construct payload payload = dict() payload['servers'] = meraki.params['servers'] # Convert port numbers to string for idempotency checks for server in payload['servers']: if server['port']: server['port'] = str(server['port']) path = meraki.construct_path('query_update', net_id=net_id) r = meraki.request(path, method='GET') if meraki.status == 200: original = dict() original['servers'] = r if meraki.is_update_required(original, payload): if meraki.module.check_mode is True: diff = recursive_diff(original, payload) original.update(payload) meraki.result['diff'] = {'before': diff[0], 'after': diff[1]} meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('query_update', net_id=net_id) r = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = r meraki.result['changed'] = True else: if meraki.module.check_mode is True: meraki.result['data'] = original meraki.exit_json(**meraki.result) meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): param_map = { 'name': 'name', 'enabled': 'enabled', 'authMode': 'auth_mode', 'encryptionMode': 'encryption_mode', 'psk': 'psk', 'wpaEncryptionMode': 'wpa_encryption_mode', 'splashPage': 'splash_page', 'radiusServers': 'radius_servers', 'radiusCoaEnabled': 'radius_coa_enabled', 'radiusFailoverPolicy': 'radius_failover_policy', 'radiusLoadBalancingPolicy': 'radius_load_balancing_policy', 'radiusAccountingEnabled': 'radius_accounting_enabled', 'radiusAccountingServers': 'radius_accounting_servers', 'ipAssignmentMode': 'ip_assignment_mode', 'useVlanTagging': 'use_vlan_tagging', 'concentratorNetworkId': 'concentrator_network_id', 'vlanId': 'vlan_id', 'defaultVlanId': 'default_vlan_id', 'apTagsAndVlanIds': 'ap_tags_vlan_ids', 'walledGardenEnabled': 'walled_garden_enabled', 'walledGardenRanges': 'walled_garden_ranges', 'minBitrate': 'min_bitrate', 'bandSelection': 'band_selection', 'perClientBandwidthLimitUp': 'per_client_bandwidth_limit_up', 'perClientBandwidthLimitDown': 'per_client_bandwidth_limit_down', } default_payload = { 'name': 'Unconfigured SSID', 'auth_mode': 'open', 'splashPage': 'None', 'perClientBandwidthLimitUp': 0, 'perClientBandwidthLimitDown': 0, 'ipAssignmentMode': 'NAT mode', 'enabled': False, 'bandSelection': 'Dual band operation', 'minBitrate': 11, } # define the available arguments/parameters that a user can pass to # the module radius_arg_spec = dict( host=dict(type='str', required=True), port=dict(type='int'), secret=dict(type='str', no_log=True), ) vlan_arg_spec = dict( tags=dict(type='list', elements='str'), vlan_id=dict(type='int'), ) argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['absent', 'present', 'query'], default='present'), number=dict(type='int', aliases=['ssid_number']), name=dict(type='str'), org_name=dict(type='str', aliases=['organization']), org_id=dict(type='str'), net_name=dict(type='str'), net_id=dict(type='str'), enabled=dict(type='bool'), auth_mode=dict(type='str', choices=[ 'open', 'psk', 'open-with-radius', '8021x-meraki', '8021x-radius' ]), encryption_mode=dict(type='str', choices=['wpa', 'eap', 'wpa-eap']), psk=dict(type='str', no_log=True), wpa_encryption_mode=dict(type='str', choices=['WPA1 and WPA2', 'WPA2 only']), splash_page=dict(type='str', choices=[ 'None', 'Click-through splash page', 'Billing', 'Password-protected with Meraki RADIUS', 'Password-protected with custom RADIUS', 'Password-protected with Active Directory', 'Password-protected with LDAP', 'SMS authentication', 'Systems Manager Sentry', 'Facebook Wi-Fi', 'Google OAuth', 'Sponsored guest' ]), radius_servers=dict(type='list', default=None, elements='dict', options=radius_arg_spec), radius_coa_enabled=dict(type='bool'), radius_failover_policy=dict(type='str', choices=['Deny access', 'Allow access']), radius_load_balancing_policy=dict( type='str', choices=['Strict priority order', 'Round robin']), radius_accounting_enabled=dict(type='bool'), radius_accounting_servers=dict(type='list', elements='dict', options=radius_arg_spec), ip_assignment_mode=dict(type='str', choices=[ 'NAT mode', 'Bridge mode', 'Layer 3 roaming', 'Layer 3 roaming with a concentrator', 'VPN' ]), use_vlan_tagging=dict(type='bool'), concentrator_network_id=dict(type='str'), vlan_id=dict(type='int'), default_vlan_id=dict(type='int'), ap_tags_vlan_ids=dict(type='list', default=None, elements='dict', options=vlan_arg_spec), walled_garden_enabled=dict(type='bool'), walled_garden_ranges=dict(type='list'), min_bitrate=dict(type='float', choices=[1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54]), band_selection=dict(type='str', choices=[ 'Dual band operation', '5 GHz band only', 'Dual band operation with Band Steering' ]), per_client_bandwidth_limit_up=dict(type='int'), per_client_bandwidth_limit_down=dict(type='int'), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='ssid') meraki.params['follow_redirects'] = 'all' query_urls = {'ssid': '/networks/{net_id}/ssids'} query_url = {'ssid': '/networks/{net_id}/ssids/{number}'} update_url = {'ssid': '/networks/{net_id}/ssids/'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['update'] = update_url payload = None # 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 # state with no modifications # FIXME: Work with Meraki so they can implement a check mode if module.check_mode: meraki.exit_json(**meraki.result) # execute checks for argument completeness if meraki.params['psk']: if meraki.params['auth_mode'] != 'psk': meraki.fail_json( msg='PSK is only allowed when auth_mode is set to psk') if meraki.params['encryption_mode'] != 'wpa': meraki.fail_json(msg='PSK requires encryption_mode be set to wpa') if meraki.params['radius_servers']: if meraki.params['auth_mode'] not in ('open-with-radius', '8021x-radius'): meraki.fail_json( msg= 'radius_servers requires auth_mode to be open-with-radius or 8021x-radius' ) if meraki.params['radius_accounting_enabled'] is True: if meraki.params['auth_mode'] not in ('open-with-radius', '8021x-radius'): meraki.fails_json( msg= 'radius_accounting_enabled is only allowed when auth_mode is open-with-radius or 8021x-radius' ) if meraki.params['radius_accounting_servers'] is True: if meraki.params['auth_mode'] not in ( 'open-with-radius', '8021x-radius' ) or meraki.params['radius_accounting_enabled'] is False: meraki.fail_json( msg= 'radius_accounting_servers is only allowed when auth_mode is open_with_radius or 8021x-radius and \ radius_accounting_enabled is true') if meraki.params['use_vlan_tagging'] is True: if meraki.params['default_vlan_id'] is None: meraki.fail_json( msg="default_vlan_id is required when use_vlan_tagging is 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) org_id = meraki.params['org_id'] net_id = meraki.params['net_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(org_id, meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if meraki.params['name']: ssid_id = get_ssid_number(meraki.params['name'], get_ssids(meraki, net_id)) path = meraki.construct_path('get_one', net_id=net_id, custom={'number': ssid_id}) meraki.result['data'] = meraki.request(path, method='GET') elif meraki.params['number'] is not None: path = meraki.construct_path( 'get_one', net_id=net_id, custom={'number': meraki.params['number']}) meraki.result['data'] = meraki.request(path, method='GET') else: meraki.result['data'] = get_ssids(meraki, net_id) elif meraki.params['state'] == 'present': payload = dict() for k, v in param_map.items(): if meraki.params[v] is not None: payload[k] = meraki.params[v] # Short term solution for camelCase/snake_case differences # Will be addressed later with a method in module utils if meraki.params['ap_tags_vlan_ids'] is not None: for i in payload['apTagsAndVlanIds']: try: i['vlanId'] = i['vlan_id'] del i['vlan_id'] except KeyError: pass try: tags = ','.join(i['tags']) del i['tags'] i['tags'] = tags except KeyError: pass ssids = get_ssids(meraki, net_id) number = meraki.params['number'] if number is None: number = get_ssid_number(meraki.params['name'], ssids) original = ssids[number] if meraki.is_update_required(original, payload, optional_ignore=['secret']): ssid_id = meraki.params['number'] if ssid_id is None: # Name should be used to lookup number ssid_id = get_ssid_number(meraki.params['name'], ssids) if ssid_id is False: ssid_id = get_available_number(ssids) if ssid_id is False: meraki.fail_json( msg= 'No unconfigured SSIDs are available. Specify a number.' ) path = meraki.construct_path('update', net_id=net_id) + str(ssid_id) result = meraki.request(path, 'PUT', payload=json.dumps(payload)) meraki.result['data'] = result meraki.result['changed'] = True else: meraki.result['data'] = original elif meraki.params['state'] == 'absent': ssids = get_ssids(meraki, net_id) ssid_id = meraki.params['number'] if ssid_id is None: # Name should be used to lookup number ssid_id = get_ssid_number(meraki.params['name'], ssids) if ssid_id is False: ssid_id = get_available_number(ssids) if ssid_id is False: meraki.fail_json( msg= 'No SSID found by specified name and no number was referenced.' ) path = meraki.construct_path('update', net_id=net_id) + str(ssid_id) payload = default_payload payload['name'] = payload['name'] + ' ' + str(ssid_id + 1) result = meraki.request(path, 'PUT', payload=json.dumps(payload)) meraki.result['data'] = result meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['present', 'query'], default='query'), serial=dict(type='str', required=True), number=dict(type='str'), name=dict(type='str', aliases=['description']), tags=dict(type='str'), enabled=dict(type='bool', default=True), type=dict(type='str', choices=['access', 'trunk'], default='access'), vlan=dict(type='int'), voice_vlan=dict(type='int'), allowed_vlans=dict(type='list', default='all'), poe_enabled=dict(type='bool', default=True), isolation_enabled=dict(type='bool', default=False), rstp_enabled=dict(type='bool', default=True), stp_guard=dict( type='str', choices=['disabled', 'root guard', 'bpdu guard', 'loop guard'], default='disabled'), access_policy_number=dict(type='str'), link_negotiation=dict(type='str', choices=[ 'Auto negotiate', '100Megabit (auto)', '100 Megabit full duplex (forced)' ], default='Auto negotiate'), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='switchport') meraki.params['follow_redirects'] = 'all' if meraki.params['type'] == 'trunk': if not meraki.params['allowed_vlans']: meraki.params['allowed_vlans'] = [ 'all' ] # Backdoor way to set default without conflicting on access query_urls = {'switchport': '/devices/{serial}/switchPorts'} query_url = {'switchport': '/devices/{serial}/switchPorts/{number}'} update_url = {'switchport': '/devices/{serial}/switchPorts/{number}'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['update'] = update_url payload = None # 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 # state with no modifications # FIXME: Work with Meraki so they can implement a check mode if module.check_mode: meraki.exit_json(**meraki.result) # execute checks for argument completeness # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) if meraki.params['state'] == 'query': if meraki.params['number']: path = meraki.construct_path('get_one', custom={ 'serial': meraki.params['serial'], 'number': meraki.params['number'], }) response = meraki.request(path, method='GET') meraki.result['data'] = response else: path = meraki.construct_path( 'get_all', custom={'serial': meraki.params['serial']}) response = meraki.request(path, method='GET') meraki.result['data'] = response elif meraki.params['state'] == 'present': payload = dict() for k, v in meraki.params.items(): try: payload[param_map[k]] = v except KeyError: pass allowed = set() # Use a set to remove duplicate items if meraki.params['allowed_vlans'][0] == 'all': allowed.add('all') else: for vlan in meraki.params['allowed_vlans']: allowed.add(str(vlan)) if meraki.params['vlan'] is not None: allowed.add(str(meraki.params['vlan'])) if len(allowed) > 1: # Convert from list to comma separated payload['allowedVlans'] = sort_vlans(meraki, allowed) else: payload['allowedVlans'] = next(iter(allowed)) # Exceptions need to be made for idempotency check based on how Meraki returns if meraki.params['type'] == 'access': if not meraki.params[ 'vlan']: # VLAN needs to be specified in access ports, but can't default to it payload['vlan'] = 1 proposed = payload.copy() query_path = meraki.construct_path('get_one', custom={ 'serial': meraki.params['serial'], 'number': meraki.params['number'], }) original = meraki.request(query_path, method='GET') if meraki.params['type'] == 'trunk': proposed['voiceVlan'] = original[ 'voiceVlan'] # API shouldn't include voice VLAN on a trunk port if meraki.is_update_required(original, proposed, optional_ignore=['number']): path = meraki.construct_path('update', custom={ 'serial': meraki.params['serial'], 'number': meraki.params['number'], }) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module user_arg_spec = dict(username=dict(type='str'), passphrase=dict(type='str', no_log=True), ) argument_spec = meraki_argument_spec() argument_spec.update(state=dict(type='str', choices=['present', 'query'], default='present'), v2c_enabled=dict(type='bool'), v3_enabled=dict(type='bool'), v3_auth_mode=dict(type='str', choices=['SHA', 'MD5']), v3_auth_pass=dict(type='str', no_log=True), v3_priv_mode=dict(type='str', choices=['DES', 'AES128']), v3_priv_pass=dict(type='str', no_log=True), peer_ips=dict(type='str'), access=dict(type='str', choices=['none', 'community', 'users']), community_string=dict(type='str', no_log=True), users=dict(type='list', default=None, elements='', options=user_arg_spec), net_name=dict(type='str'), net_id=dict(type='str'), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='snmp') meraki.params['follow_redirects'] = 'all' query_urls = {'snmp': '/organizations/{org_id}/snmp'} query_net_urls = {'snmp': '/networks/{net_id}/snmpSettings'} update_urls = {'snmp': '/organizations/{org_id}/snmp'} update_net_urls = {'snmp': '/networks/{net_id}/snmpSettings'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['query_net_all'] = query_net_urls meraki.url_catalog['create'] = update_urls meraki.url_catalog['create_net'] = update_net_urls payload = None if not meraki.params['org_name'] and not meraki.params['org_id']: meraki.fail_json(msg='org_name or org_id is required') org_id = meraki.params['org_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None and meraki.params['net_name']: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(org_id, meraki.params['net_name'], data=nets) if meraki.params['state'] == 'present': if net_id is not None: payload = {'access': meraki.params['access']} if meraki.params['community_string'] is not None: payload['communityString'] = meraki.params['community_string'] elif meraki.params['users'] is not None: payload['users'] = meraki.params['users'] if meraki.params['state'] == 'query': if net_id is None: meraki.result['data'] = get_snmp(meraki, org_id) else: path = meraki.construct_path('query_net_all', net_id=net_id) response = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = response elif meraki.params['state'] == 'present': if net_id is None: meraki.result['data'] = set_snmp(meraki, org_id) else: path = meraki.construct_path('query_net_all', net_id=net_id) original = meraki.request(path, method='GET') if meraki.is_update_required(original, payload): path = meraki.construct_path('create_net', net_id=net_id) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: if response['access'] == 'none': meraki.result['data'] = {} else: meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module application_arg_spec = dict( id=dict(type='str'), name=dict(type='str'), ) rule_arg_spec = dict( policy=dict(type='str', choices=['deny'], default='deny'), type=dict(type='str', choices=[ 'application', 'application_category', 'blacklisted_countries', 'host', 'ip_range', 'port', 'whitelisted_countries' ]), ip_range=dict(type='str'), application=dict(type='dict', default=None, options=application_arg_spec), host=dict(type='str'), port=dict(type='str'), countries=dict(type='list'), ) argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['present', 'query'], default='present'), net_name=dict(type='str'), net_id=dict(type='str'), rules=dict(type='list', default=None, elements='dict', options=rule_arg_spec), categories=dict(type='bool'), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='mx_l7_firewall') # check for argument completeness if meraki.params['rules']: for rule in meraki.params['rules']: if rule['type'] == 'application' and rule['application'] is None: meraki.fail_json( msg= "application argument is required when type is application." ) elif rule['type'] == 'application_category' and rule[ 'application'] is None: meraki.fail_json( msg= "application argument is required when type is application_category." ) elif rule['type'] == 'blacklisted_countries' and rule[ 'countries'] is None: meraki.fail_json( msg= "countries argument is required when type is blacklisted_countries." ) elif rule['type'] == 'host' and rule['host'] is None: meraki.fail_json( msg="host argument is required when type is host.") elif rule['type'] == 'port' and rule['port'] is None: meraki.fail_json( msg="port argument is required when type is port.") elif rule['type'] == 'whitelisted_countries' and rule[ 'countries'] is None: meraki.fail_json( msg= "countries argument is required when type is whitelisted_countries." ) meraki.params['follow_redirects'] = 'all' query_urls = {'mx_l7_firewall': '/networks/{net_id}/l7FirewallRules/'} query_category_urls = { 'mx_l7_firewall': '/networks/{net_id}/l7FirewallRules/applicationCategories' } update_urls = {'mx_l7_firewall': '/networks/{net_id}/l7FirewallRules/'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_categories'] = (query_category_urls) meraki.url_catalog['update'] = update_urls payload = None # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] orgs = None if org_id is None: orgs = meraki.get_orgs() for org in orgs: if org['name'] == meraki.params['org_name']: org_id = org['id'] net_id = meraki.params['net_id'] if net_id is None: if orgs is None: orgs = meraki.get_orgs() net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=meraki.get_nets(org_id=org_id)) if meraki.params['state'] == 'query': if meraki.params['categories'] is True: # Output only applications meraki.result['data'] = get_applications(meraki, net_id) else: meraki.result['data'] = restructure_response( get_rules(meraki, net_id)) elif meraki.params['state'] == 'present': rules = get_rules(meraki, net_id) path = meraki.construct_path('get_all', net_id=net_id) if meraki.params['rules']: payload = {'rules': []} for rule in meraki.params['rules']: payload['rules'].append(assemble_payload(meraki, net_id, rule)) else: payload = dict() ''' The rename_* functions are needed because the key is id and is_update_required() by default ignores id. ''' rules = rename_id_to_appid(rules) payload = rename_id_to_appid(payload) if meraki.is_update_required(rules, payload): rules = rename_appid_to_id(rules) payload = rename_appid_to_id(payload) if meraki.module.check_mode is True: response = restructure_response(payload) diff = recursive_diff(restructure_response(rules), response) meraki.result['diff'] = { 'before': diff[0], 'after': diff[1], } meraki.result['data'] = response meraki.result['changed'] = True meraki.exit_json(**meraki.result) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) response = restructure_response(response) if meraki.status == 200: diff = recursive_diff(restructure_response(rules), response) meraki.result['diff'] = { 'before': diff[0], 'after': diff[1], } meraki.result['data'] = response meraki.result['changed'] = True else: rules = rename_appid_to_id(rules) payload = rename_appid_to_id(payload) if meraki.module.check_mode is True: meraki.result['data'] = rules meraki.result['changed'] = False meraki.exit_json(**meraki.result) meraki.result['data'] = payload # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['absent', 'present', 'query'], default='query'), net_name=dict(type='str', aliases=['network']), net_id=dict(type='str'), serial=dict(type='str'), serial_uplink=dict(type='str'), serial_lldp_cdp=dict(type='str'), lldp_cdp_timespan=dict(type='int'), hostname=dict(type='str', aliases=['name']), model=dict(type='str'), tags=dict(type='str'), lat=dict(type='float', aliases=['latitude']), lng=dict(type='float', aliases=['longitude']), address=dict(type='str'), move_map_marker=dict(type='bool'), note=dict(type='str'), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='device') if meraki.params[ 'serial_lldp_cdp'] and not meraki.params['lldp_cdp_timespan']: meraki.fail_json( msg= 'lldp_cdp_timespan is required when querying LLDP and CDP information' ) if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive') meraki.params['follow_redirects'] = 'all' query_urls = {'device': '/networks/{net_id}/devices'} query_org_urls = {'device': '/organizations/{org_id}/inventory'} query_device_urls = {'device': '/networks/{net_id}/devices/'} claim_device_urls = {'device': '/networks/{net_id}/devices/claim'} bind_org_urls = {'device': '/organizations/{org_id}/claim'} update_device_urls = {'device': '/networks/{net_id}/devices/'} delete_device_urls = {'device': '/networks/{net_id}/devices/'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_all_org'] = query_org_urls meraki.url_catalog['get_device'] = query_device_urls meraki.url_catalog['create'] = claim_device_urls meraki.url_catalog['bind_org'] = bind_org_urls meraki.url_catalog['update'] = update_device_urls meraki.url_catalog['delete'] = delete_device_urls payload = None # 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 # state with no modifications # FIXME: Work with Meraki so they can implement a check mode if module.check_mode: meraki.exit_json(**meraki.result) # execute checks for argument completeness # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) nets = meraki.get_nets(org_id=org_id) net_id = None if meraki.params['net_id'] or meraki.params['net_name']: net_id = meraki.params['net_id'] if net_id is None: net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if meraki.params['net_name'] or meraki.params['net_id']: device = [] if meraki.params['serial']: path = meraki.construct_path( 'get_device', net_id=net_id) + meraki.params['serial'] request = meraki.request(path, method='GET') device.append(request) meraki.result['data'] = device elif meraki.params['serial_uplink']: path = meraki.construct_path( 'get_device', net_id=net_id) + meraki.params['serial_uplink'] + '/uplink' meraki.result['data'] = (meraki.request(path, method='GET')) elif meraki.params['serial_lldp_cdp']: if meraki.params['lldp_cdp_timespan'] > 2592000: meraki.fail_json( msg= 'LLDP/CDP timespan must be less than a month (2592000 seconds)' ) path = meraki.construct_path( 'get_device', net_id=net_id ) + meraki.params['serial_lldp_cdp'] + '/lldp_cdp' path = path + '?timespan=' + str( meraki.params['lldp_cdp_timespan']) device.append(meraki.request(path, method='GET')) meraki.result['data'] = device elif meraki.params['hostname']: path = meraki.construct_path('get_all', net_id=net_id) devices = meraki.request(path, method='GET') for unit in devices: try: if unit['name'] == meraki.params['hostname']: device.append(unit) meraki.result['data'] = device except KeyError: pass elif meraki.params['model']: path = meraki.construct_path('get_all', net_id=net_id) devices = meraki.request(path, method='GET') device_match = [] for device in devices: if device['model'] == meraki.params['model']: device_match.append(device) meraki.result['data'] = device_match else: path = meraki.construct_path('get_all', net_id=net_id) request = meraki.request(path, method='GET') meraki.result['data'] = request else: path = meraki.construct_path('get_all_org', org_id=org_id) devices = meraki.request(path, method='GET') if meraki.params['serial']: for device in devices: if device['serial'] == meraki.params['serial']: meraki.result['data'] = device else: meraki.result['data'] = devices elif meraki.params['state'] == 'present': device = [] if meraki.params['hostname']: query_path = meraki.construct_path('get_all', net_id=net_id) device_list = meraki.request(query_path, method='GET') if is_device_valid(meraki, meraki.params['serial'], device_list): payload = { 'name': meraki.params['hostname'], 'tags': format_tags(meraki.params['tags']), 'lat': meraki.params['lat'], 'lng': meraki.params['lng'], 'address': meraki.params['address'], 'moveMapMarker': meraki.params['move_map_marker'], 'notes': meraki.params['note'], } query_path = meraki.construct_path( 'get_device', net_id=net_id) + meraki.params['serial'] device_data = meraki.request(query_path, method='GET') ignore_keys = [ 'lanIp', 'serial', 'mac', 'model', 'networkId', 'moveMapMarker', 'wan1Ip', 'wan2Ip' ] # meraki.fail_json(msg="Compare", original=device_data, payload=payload, ignore=ignore_keys) if meraki.is_update_required(device_data, payload, optional_ignore=ignore_keys): path = meraki.construct_path( 'update', net_id=net_id) + meraki.params['serial'] updated_device = [] updated_device.append( meraki.request(path, method='PUT', payload=json.dumps(payload))) meraki.result['data'] = updated_device meraki.result['changed'] = True else: meraki.result['data'] = device_data else: if net_id is None: device_list = get_org_devices(meraki, org_id) if is_device_valid(meraki, meraki.params['serial'], device_list) is False: payload = {'serial': meraki.params['serial']} path = meraki.construct_path('bind_org', org_id=org_id) created_device = [] created_device.append( meraki.request(path, method='POST', payload=json.dumps(payload))) meraki.result['data'] = created_device meraki.result['changed'] = True else: query_path = meraki.construct_path('get_all', net_id=net_id) device_list = meraki.request(query_path, method='GET') if is_device_valid(meraki, meraki.params['serial'], device_list) is False: if net_id: payload = {'serial': meraki.params['serial']} path = meraki.construct_path('create', net_id=net_id) created_device = [] created_device.append( meraki.request(path, method='POST', payload=json.dumps(payload))) meraki.result['data'] = created_device meraki.result['changed'] = True elif meraki.params['state'] == 'absent': device = [] query_path = meraki.construct_path('get_all', net_id=net_id) device_list = meraki.request(query_path, method='GET') if is_device_valid(meraki, meraki.params['serial'], device_list) is True: path = meraki.construct_path('delete', net_id=net_id) path = path + meraki.params['serial'] + '/remove' request = meraki.request(path, method='POST') meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module urls_arg_spec = dict( url=dict(type='str'), comment=dict(type='str'), ) files_arg_spec = dict( sha256=dict(type='str', aliases=['hash']), comment=dict(type='str'), ) argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['absent', 'present', 'query'], default='query'), net_name=dict(type='str', aliases=['network']), net_id=dict(type='str'), mode=dict(type='str', choices=['enabled', 'disabled']), allowed_urls=dict(type='list', default=None, elements='dict', options=urls_arg_spec), allowed_files=dict(type='list', default=None, elements='dict', options=files_arg_spec), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='malware') meraki.params['follow_redirects'] = 'all' query_url = {'malware': '/networks/{net_id}/security/malwareSettings'} update_url = {'malware': '/networks/{net_id}/security/malwareSettings'} meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['update'] = update_url org_id = meraki.params['org_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) # Check for argument completeness if meraki.params['state'] == 'present': if meraki.params['allowed_files'] is not None or meraki.params[ 'allowed_urls'] is not None: if meraki.params['mode'] is None: meraki.fail_json( msg= "mode must be set when allowed_files or allowed_urls is set." ) # Assemble payload if meraki.params['state'] == 'present': payload = dict() if meraki.params['mode'] is not None: payload['mode'] = meraki.params['mode'] if meraki.params['allowed_urls'] is not None: payload['allowedUrls'] = meraki.params['allowed_urls'] if meraki.params['allowed_files'] is not None: payload['allowedFiles'] = meraki.params['allowed_files'] if meraki.params['state'] == 'query': path = meraki.construct_path('get_one', net_id=net_id) data = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = data elif meraki.params['state'] == 'present': path = meraki.construct_path('get_one', net_id=net_id) original = meraki.request(path, method='GET') if meraki.is_update_required(original, payload): if meraki.module.check_mode is True: diff = recursive_diff(original, payload) original.update(payload) meraki.result['diff'] = { 'before': diff[0], 'after': diff[1], } meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id) data = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: diff = recursive_diff(original, payload) meraki.result['diff'] = { 'before': diff[0], 'after': diff[1], } meraki.result['data'] = data meraki.result['changed'] = True else: meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), type=dict(type='list', choices=['wireless', 'switch', 'appliance'], aliases=['net_type']), tags=dict(type='list'), timezone=dict(type='str'), net_name=dict(type='str', aliases=['name', 'network']), state=dict(type='str', choices=['present', 'query', 'absent'], default='present'), enable_vlans=dict(type='bool'), disable_my_meraki=dict(type='bool', removed_in_version=2.13), enable_my_meraki=dict(type='bool'), enable_remote_status_page=dict(type='bool'), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # 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') module.params['follow_redirects'] = 'all' payload = None create_urls = {'network': '/organizations/{org_id}/networks'} update_urls = {'network': '/networks/{net_id}'} delete_urls = {'network': '/networks/{net_id}'} enable_vlans_urls = {'network': '/networks/{net_id}/vlansEnabledState'} get_vlan_status_urls = {'network': '/networks/{net_id}/vlansEnabledState'} meraki.url_catalog['create'] = create_urls meraki.url_catalog['update'] = update_urls meraki.url_catalog['delete'] = delete_urls meraki.url_catalog['enable_vlans'] = enable_vlans_urls meraki.url_catalog['status_vlans'] = get_vlan_status_urls if not meraki.params['org_name'] and not meraki.params['org_id']: meraki.fail_json(msg='org_name or org_id parameters are required') if meraki.params['state'] != 'query': if not meraki.params['net_name'] and not meraki.params['net_id']: meraki.fail_json( msg= 'net_name or net_id is required for present or absent states') if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive') 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 # state with no modifications if module.check_mode: return meraki.result # Construct payload if meraki.params['state'] == 'present': payload = dict() if meraki.params['net_name']: payload['name'] = meraki.params['net_name'] if meraki.params['type']: payload['type'] = list_to_string(meraki.params['type']) if meraki.params['tags']: payload['tags'] = construct_tags(meraki.params['tags']) if meraki.params['timezone']: payload['timeZone'] = meraki.params['timezone'] 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: 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) org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) nets = meraki.get_nets(org_id=org_id) # check if network is created net_id = meraki.params['net_id'] net_exists = False if net_id is not None: if is_net_valid(nets, net_id=net_id) is False: meraki.fail_json(msg="Network specified by net_id does not exist.") net_exists = True elif meraki.params['net_name']: if is_net_valid(nets, net_name=meraki.params['net_name']) is True: net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) net_exists = True if meraki.params['state'] == 'query': if not meraki.params['net_name'] and not meraki.params['net_id']: meraki.result['data'] = nets elif meraki.params['net_name'] or meraki.params['net_id'] is not None: meraki.result['data'] = meraki.get_net(meraki.params['org_name'], meraki.params['net_name'], data=nets) elif meraki.params['state'] == 'present': if net_exists is False: # Network needs to be created if 'type' not in meraki.params or meraki.params['type'] is None: meraki.fail_json( msg="type parameter is required when creating a network.") path = meraki.construct_path('create', org_id=org_id) r = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 201: meraki.result['data'] = r meraki.result['changed'] = True else: # Network exists, make changes # meraki.fail_json(msg="nets", nets=nets, net_id=net_id) # meraki.fail_json(msg="compare", original=net, payload=payload) if meraki.params[ 'enable_vlans'] is not None: # Modify VLANs configuration status_path = meraki.construct_path('status_vlans', net_id=net_id) status = meraki.request(status_path, method='GET') payload = {'enabled': meraki.params['enable_vlans']} # meraki.fail_json(msg="here", payload=payload) if meraki.is_update_required(status, payload): path = meraki.construct_path('enable_vlans', net_id=net_id) r = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = r meraki.result['changed'] = True meraki.exit_json(**meraki.result) else: meraki.result['data'] = status meraki.exit_json(**meraki.result) net = meraki.get_net(meraki.params['org_name'], net_id=net_id, data=nets) if meraki.is_update_required(net, payload): path = meraki.construct_path('update', net_id=net_id) # meraki.fail_json(msg="Payload", path=path, payload=payload) r = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = r meraki.result['changed'] = True else: meraki.result['data'] = net elif meraki.params['state'] == 'absent': if is_net_valid(nets, net_id=net_id) is True: path = meraki.construct_path('delete', net_id=net_id) r = meraki.request(path, method='DELETE') if meraki.status == 204: meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( clone=dict(type='str'), state=dict(type='str', choices=['absent', 'present', 'query'], default='present'), org_name=dict(type='str', aliases=['name', 'organization']), org_id=dict(type='str', aliases=['id']), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='organizations') meraki.params['follow_redirects'] = 'all' create_urls = {'organizations': '/organizations'} update_urls = {'organizations': '/organizations/{org_id}'} delete_urls = {'organizations': '/organizations/{org_id}'} clone_urls = {'organizations': '/organizations/{org_id}/clone'} meraki.url_catalog['create'] = create_urls meraki.url_catalog['update'] = update_urls meraki.url_catalog['clone'] = clone_urls meraki.url_catalog['delete'] = delete_urls payload = None # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) orgs = meraki.get_orgs() if meraki.params['state'] == 'query': if meraki.params['org_name']: # Query by organization name module.warn( 'All matching organizations will be returned, even if there are duplicate named organizations' ) for o in orgs: if o['name'] == meraki.params['org_name']: meraki.result['data'] = o elif meraki.params['org_id']: for o in orgs: if o['id'] == meraki.params['org_id']: meraki.result['data'] = o else: # Query all organizations, no matter what meraki.result['data'] = orgs elif meraki.params['state'] == 'present': if meraki.params['clone']: # Cloning payload = {'name': meraki.params['org_name']} response = meraki.request(meraki.construct_path( 'clone', org_name=meraki.params['clone']), payload=json.dumps(payload), method='POST') if meraki.status != 201: meraki.fail_json(msg='Organization clone failed') meraki.result['data'] = response meraki.result['changed'] = True elif not meraki.params['org_id'] and meraki.params[ 'org_name']: # Create new organization payload = {'name': meraki.params['org_name']} response = meraki.request(meraki.construct_path('create'), method='POST', payload=json.dumps(payload)) if meraki.status == 201: meraki.result['data'] = response meraki.result['changed'] = True elif meraki.params['org_id'] and meraki.params[ 'org_name']: # Update an existing organization payload = { 'name': meraki.params['org_name'], 'id': meraki.params['org_id'], } original = get_org(meraki, meraki.params['org_id'], orgs) if meraki.is_update_required(original, payload, optional_ignore=['url']): response = meraki.request(meraki.construct_path( 'update', org_id=meraki.params['org_id']), method='PUT', payload=json.dumps(payload)) if meraki.status != 200: meraki.fail_json(msg='Organization update failed') meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original elif meraki.params['state'] == 'absent': if meraki.params['org_name'] is not None: org_id = meraki.get_org_id(meraki.params['org_name']) elif meraki.params['org_id'] is not None: org_id = meraki.params['org_id'] if meraki.check_mode is True: meraki.result['data'] = {} meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('delete', org_id=org_id) response = meraki.request(path, method='DELETE') if meraki.status == 204: meraki.result['data'] = {} meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module fixed_ip_arg_spec = dict( mac=dict(type='str'), ip=dict(type='str'), name=dict(type='str'), ) reserved_ip_arg_spec = dict( start=dict(type='str'), end=dict(type='str'), comment=dict(type='str'), ) argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), net_name=dict(type='str'), name=dict(type='str'), subnet=dict(type='str'), gateway_ip=dict(type='str'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), fixed_ip_assignments=dict(type='list', elements='dict', options=fixed_ip_arg_spec), reserved_ip_ranges=dict(type='list', elements='dict', options=reserved_ip_arg_spec), route_id=dict(type='str'), enabled=dict(type='bool'), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='static_route') module.params['follow_redirects'] = 'all' payload = None query_urls = {'static_route': '/networks/{net_id}/staticRoutes'} query_one_urls = { 'static_route': '/networks/{net_id}/staticRoutes/{route_id}' } create_urls = {'static_route': '/networks/{net_id}/staticRoutes/'} update_urls = { 'static_route': '/networks/{net_id}/staticRoutes/{route_id}' } delete_urls = { 'static_route': '/networks/{net_id}/staticRoutes/{route_id}' } meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_one_urls) meraki.url_catalog['create'] = create_urls meraki.url_catalog['update'] = update_urls meraki.url_catalog['delete'] = delete_urls if not meraki.params['org_name'] and not meraki.params['org_id']: meraki.fail_json( msg="Parameters 'org_name' or 'org_id' parameters are required") if not meraki.params['net_name'] and not meraki.params['net_id']: meraki.fail_json( msg="Parameters 'net_name' or 'net_id' parameters are required") if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg="'net_name' and 'net_id' are mutually exclusive") # Construct payload if meraki.params['state'] == 'present': payload = dict() if meraki.params['net_name']: payload['name'] = meraki.params['net_name'] # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if meraki.params['route_id'] is not None: meraki.result['data'] = get_static_route(meraki, net_id, meraki.params['route_id']) else: meraki.result['data'] = get_static_routes(meraki, net_id) elif meraki.params['state'] == 'present': payload = { 'name': meraki.params['name'], 'subnet': meraki.params['subnet'], 'gatewayIp': meraki.params['gateway_ip'], } if meraki.params['fixed_ip_assignments'] is not None: payload['fixedIpAssignments'] = fixed_ip_factory( meraki, meraki.params['fixed_ip_assignments']) if meraki.params['reserved_ip_ranges'] is not None: payload['reservedIpRanges'] = meraki.params['reserved_ip_ranges'] # meraki.fail_json(msg="payload", payload=payload) if meraki.params['enabled'] is not None: payload['enabled'] = meraki.params['enabled'] if meraki.params['route_id']: existing_route = get_static_route(meraki, net_id, meraki.params['route_id']) proposed = existing_route.copy() proposed.update(payload) if module.check_mode: meraki.result['data'] = proposed meraki.result['data'].update(payload) meraki.exit_json(**meraki.result) if meraki.is_update_required(existing_route, proposed, optional_ignore=['id']): path = meraki.construct_path( 'update', net_id=net_id, custom={'route_id': meraki.params['route_id']}) meraki.result['data'] = meraki.request( path, method="PUT", payload=json.dumps(payload)) meraki.result['changed'] = True else: meraki.result['data'] = existing_route else: if module.check_mode: meraki.result['data'] = payload meraki.exit_json(**meraki.result) path = meraki.construct_path('create', net_id=net_id) meraki.result['data'] = meraki.request(path, method="POST", payload=json.dumps(payload)) meraki.result['changed'] = True elif meraki.params['state'] == 'absent': if module.check_mode: meraki.exit_json(**meraki.result) path = meraki.construct_path( 'delete', net_id=net_id, custom={'route_id': meraki.params['route_id']}) meraki.result['data'] = meraki.request(path, method='DELETE') meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( state=dict(type='str', choices=['absent', 'present', 'query'], default='query'), net_name=dict(type='str', aliases=['network']), net_id=dict(type='str'), name=dict(type='str'), url=dict(type='str'), shared_secret=dict(type='str', no_log=True), webhook_id=dict(type='str'), test=dict(type='str', choices=['test', 'status']), test_id=dict(type='str'), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict(changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='webhooks') meraki.params['follow_redirects'] = 'all' query_url = {'webhooks': '/networks/{net_id}/httpServers'} query_one_url = {'webhooks': '/networks/{net_id}/httpServers/{hookid}'} create_url = {'webhooks': '/networks/{net_id}/httpServers'} update_url = {'webhooks': '/networks/{net_id}/httpServers/{hookid}'} delete_url = {'webhooks': '/networks/{net_id}/httpServers/{hookid}'} test_url = {'webhooks': '/networks/{net_id}/httpServers/webhookTests'} test_status_url = { 'webhooks': '/networks/{net_id}/httpServers/webhookTests/{testid}' } meraki.url_catalog['get_all'].update(query_url) meraki.url_catalog['get_one'].update(query_one_url) meraki.url_catalog['create'] = create_url meraki.url_catalog['update'] = update_url meraki.url_catalog['delete'] = delete_url meraki.url_catalog['test'] = test_url meraki.url_catalog['test_status'] = test_status_url org_id = meraki.params['org_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) webhook_id = meraki.params['webhook_id'] if webhook_id is None and meraki.params['name']: webhooks = get_all_webhooks(meraki, net_id) webhook_id = get_webhook_id(meraki.params['name'], webhooks) if meraki.params['state'] == 'present' and meraki.params['test'] is None: payload = { 'name': meraki.params['name'], 'url': meraki.params['url'], 'sharedSecret': meraki.params['shared_secret'] } if meraki.params['state'] == 'query': if webhook_id is not None: # Query a single webhook path = meraki.construct_path('get_one', net_id=net_id, custom={'hookid': webhook_id}) response = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = response else: path = meraki.construct_path('get_all', net_id=net_id) response = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = response elif meraki.params['state'] == 'present': if meraki.params['test'] == 'test': payload = {'url': meraki.params['url']} path = meraki.construct_path('test', net_id=net_id) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.exit_json(**meraki.result) elif meraki.params['test'] == 'status': if meraki.params['test_id'] is None: meraki.fail_json( "test_id is required when querying test status.") path = meraki.construct_path( 'test_status', net_id=net_id, custom={'testid': meraki.params['test_id']}) response = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = response meraki.exit_json(**meraki.result) if webhook_id is None: # Make sure it is downloaded if webhooks is None: webhooks = get_all_webhooks(meraki, net_id) webhook_id = get_webhook_id(meraki.params['name'], webhooks) if webhook_id is None: # Test to see if it needs to be created if meraki.check_mode is True: meraki.result['data'] = payload meraki.result['data']['networkId'] = net_id meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('create', net_id=net_id) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 201: meraki.result['data'] = response meraki.result['changed'] = True else: # Need to update path = meraki.construct_path('get_one', net_id=net_id, custom={'hookid': webhook_id}) original = meraki.request(path, method='GET') if meraki.is_update_required(original, payload): if meraki.check_mode is True: diff = recursive_diff(original, payload) original.update(payload) meraki.result['diff'] = { 'before': diff[0], 'after': diff[1] } meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id, custom={'hookid': webhook_id}) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original elif meraki.params['state'] == 'absent': if webhook_id is None: # Make sure it is downloaded if webhooks is None: webhooks = get_all_webhooks(meraki, net_id) webhook_id = get_webhook_id(meraki.params['name'], webhooks) if webhook_id is None: meraki.fail_json(msg="There is no webhook with the name {0}". format(meraki.params['name'])) if webhook_id: # Test to see if it exists if meraki.module.check_mode is True: meraki.result['data'] = None meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('delete', net_id=net_id, custom={'hookid': webhook_id}) response = meraki.request(path, method='DELETE') if meraki.status == 204: meraki.result['data'] = response meraki.result['changed'] = True # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), net_name=dict(type='str', aliases=['network']), state=dict(type='str', default='present', choices=['query', 'present']), service=dict(type='str', default=None, choices=['ICMP', 'SNMP', 'web']), access=dict(type='str', choices=['blocked', 'restricted', 'unrestricted']), allowed_ips=dict(type='list', elements='str'), ) mutually_exclusive = [('net_name', 'net_id')] # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, mutually_exclusive=mutually_exclusive) meraki = MerakiModule(module, function='firewalled_services') module.params['follow_redirects'] = 'all' net_services_urls = { 'firewalled_services': '/networks/{net_id}/firewalledServices' } services_urls = { 'firewalled_services': '/networks/{net_id}/firewalledServices/{service}' } meraki.url_catalog['network_services'] = net_services_urls meraki.url_catalog['service'] = services_urls # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(org_id, meraki.params['net_name'], data=nets) if meraki.params['state'] == 'present': if meraki.params['access'] != 'restricted' and meraki.params[ 'allowed_ips'] is not None: meraki.fail_json( msg="allowed_ips is only allowed when access is restricted.") payload = {'access': meraki.params['access']} if meraki.params['access'] == 'restricted': payload['allowedIps'] = meraki.params['allowed_ips'] if meraki.params['state'] == 'query': if meraki.params['service'] is None: path = meraki.construct_path('network_services', net_id=net_id) response = meraki.request(path, method='GET') meraki.result['data'] = response meraki.exit_json(**meraki.result) else: path = meraki.construct_path( 'service', net_id=net_id, custom={'service': meraki.params['service']}) response = meraki.request(path, method='GET') meraki.result['data'] = response meraki.exit_json(**meraki.result) elif meraki.params['state'] == 'present': path = meraki.construct_path( 'service', net_id=net_id, custom={'service': meraki.params['service']}) original = meraki.request(path, method='GET') if meraki.is_update_required(original, payload, optional_ignore=['service']): if meraki.check_mode is True: diff_payload = { 'service': meraki.params['service'] } # Need to add service as it's not in payload diff_payload.update(payload) diff = recursive_diff(original, diff_payload) original.update(payload) meraki.result['diff'] = {'before': diff[0], 'after': diff[1]} meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path( 'service', net_id=net_id, custom={'service': meraki.params['service']}) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: diff = recursive_diff(original, response) meraki.result['diff'] = {'before': diff[0], 'after': diff[1]} meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = original # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module argument_spec = meraki_argument_spec() argument_spec.update( net_id=dict(type='str'), net_name=dict(type='str', aliases=['network']), state=dict(type='str', default='present', choices=['present', 'query']), allowed_urls=dict(type='list'), blocked_urls=dict(type='list'), blocked_categories=dict(type='list'), category_list_size=dict(type='str', choices=['top sites', 'full list']), subset=dict(type='str', choices=['categories', 'policy']), ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='content_filtering') module.params['follow_redirects'] = 'all' category_urls = { 'content_filtering': '/networks/{net_id}/contentFiltering/categories' } policy_urls = {'content_filtering': '/networks/{net_id}/contentFiltering'} meraki.url_catalog['categories'] = category_urls meraki.url_catalog['policy'] = policy_urls if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive') # manipulate or modify the state as needed (this is going to be the # part where your module will do what it needs to do) org_id = meraki.params['org_id'] if not org_id: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(org_id, meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if meraki.params['subset']: if meraki.params['subset'] == 'categories': path = meraki.construct_path('categories', net_id=net_id) elif meraki.params['subset'] == 'policy': path = meraki.construct_path('policy', net_id=net_id) meraki.result['data'] = meraki.request(path, method='GET') else: response_data = { 'categories': None, 'policy': None, } path = meraki.construct_path('categories', net_id=net_id) response_data['categories'] = meraki.request(path, method='GET') path = meraki.construct_path('policy', net_id=net_id) response_data['policy'] = meraki.request(path, method='GET') meraki.result['data'] = response_data if module.params['state'] == 'present': payload = dict() if meraki.params['allowed_urls']: payload['allowedUrlPatterns'] = meraki.params['allowed_urls'] if meraki.params['blocked_urls']: payload['blockedUrlPatterns'] = meraki.params['blocked_urls'] if meraki.params['blocked_categories']: if len(meraki.params['blocked_categories'] ) == 0: # Corner case for resetting payload['blockedUrlCategories'] = [] else: category_path = meraki.construct_path('categories', net_id=net_id) categories = meraki.request(category_path, method='GET') payload['blockedUrlCategories'] = [] for category in meraki.params['blocked_categories']: payload['blockedUrlCategories'].append( get_category_dict(meraki, categories, category)) if meraki.params['category_list_size']: if meraki.params['category_list_size'].lower() == 'top sites': payload['urlCategoryListSize'] = "topSites" elif meraki.params['category_list_size'].lower() == 'full list': payload['urlCategoryListSize'] = "fullList" path = meraki.construct_path('policy', net_id=net_id) current = meraki.request(path, method='GET') proposed = current.copy() proposed.update(payload) if meraki.is_update_required(current, payload) is True: meraki.result['diff'] = dict() diff = recursive_diff(current, payload) meraki.result['diff']['before'] = diff[0] meraki.result['diff']['after'] = diff[1] if module.check_mode: current.update(payload) meraki.result['changed'] = True meraki.result['data'] = current meraki.exit_json(**meraki.result) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) meraki.result['data'] = response meraki.result['changed'] = True else: meraki.result['data'] = current if module.check_mode: meraki.result['data'] = current meraki.exit_json(**meraki.result) meraki.result['data'] = current meraki.exit_json(**meraki.result) # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)
def main(): # define the available arguments/parameters that a user can pass to # the module fixed_ip_arg_spec = dict(mac=dict(type='str'), ip=dict(type='str'), name=dict(type='str'), ) reserved_ip_arg_spec = dict(start=dict(type='str'), end=dict(type='str'), comment=dict(type='str'), ) argument_spec = meraki_argument_spec() argument_spec.update(state=dict(type='str', choices=['absent', 'present', 'query'], default='query'), net_name=dict(type='str', aliases=['network']), net_id=dict(type='str'), vlan_id=dict(type='int'), name=dict(type='str', aliases=['vlan_name']), subnet=dict(type='str'), appliance_ip=dict(type='str'), fixed_ip_assignments=dict(type='list', default=None, elements='dict', options=fixed_ip_arg_spec), reserved_ip_range=dict(type='list', default=None, elements='dict', options=reserved_ip_arg_spec), vpn_nat_subnet=dict(type='str'), dns_nameservers=dict(type='str'), ) # seed the result dict in the object # we primarily care about changed and state # change is if this module effectively modified the target # state will include any data that you want your module to pass back # for consumption, for example, in a subsequent task result = dict( changed=False, ) # the AnsibleModule object will be our abstraction working with Ansible # this includes instantiation, a couple of common attr would be the # args/params passed to the execution, as well as if the module # supports check mode module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, ) meraki = MerakiModule(module, function='vlan') meraki.params['follow_redirects'] = 'all' query_urls = {'vlan': '/networks/{net_id}/vlans'} query_url = {'vlan': '/networks/{net_id}/vlans/{vlan_id}'} create_url = {'vlan': '/networks/{net_id}/vlans'} update_url = {'vlan': '/networks/{net_id}/vlans/'} delete_url = {'vlan': '/networks/{net_id}/vlans/'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['create'] = create_url meraki.url_catalog['update'] = update_url meraki.url_catalog['delete'] = delete_url payload = None org_id = meraki.params['org_id'] if org_id is None: org_id = meraki.get_org_id(meraki.params['org_name']) net_id = meraki.params['net_id'] if net_id is None: nets = meraki.get_nets(org_id=org_id) net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=nets) if meraki.params['state'] == 'query': if not meraki.params['vlan_id']: meraki.result['data'] = get_vlans(meraki, net_id) else: path = meraki.construct_path('get_one', net_id=net_id, custom={'vlan_id': meraki.params['vlan_id']}) response = meraki.request(path, method='GET') meraki.result['data'] = response elif meraki.params['state'] == 'present': payload = {'id': meraki.params['vlan_id'], 'name': meraki.params['name'], 'subnet': meraki.params['subnet'], 'applianceIp': meraki.params['appliance_ip'], } if is_vlan_valid(meraki, net_id, meraki.params['vlan_id']) is False: # Create new VLAN if meraki.module.check_mode is True: meraki.result['data'] = payload meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('create', net_id=net_id) response = meraki.request(path, method='POST', payload=json.dumps(payload)) meraki.result['changed'] = True meraki.result['data'] = response else: # Update existing VLAN path = meraki.construct_path('get_one', net_id=net_id, custom={'vlan_id': meraki.params['vlan_id']}) original = meraki.request(path, method='GET') if meraki.params['dns_nameservers']: if meraki.params['dns_nameservers'] not in ('opendns', 'google_dns', 'upstream_dns'): payload['dnsNameservers'] = format_dns(meraki.params['dns_nameservers']) else: payload['dnsNameservers'] = meraki.params['dns_nameservers'] if meraki.params['fixed_ip_assignments']: payload['fixedIpAssignments'] = fixed_ip_factory(meraki, meraki.params['fixed_ip_assignments']) if meraki.params['reserved_ip_range']: payload['reservedIpRanges'] = meraki.params['reserved_ip_range'] if meraki.params['vpn_nat_subnet']: payload['vpnNatSubnet'] = meraki.params['vpn_nat_subnet'] ignored = ['networkId'] if meraki.is_update_required(original, payload, optional_ignore=ignored): meraki.result['diff'] = dict() diff = recursive_diff(original, payload) meraki.result['diff']['before'] = diff[0] meraki.result['diff']['after'] = diff[1] if meraki.module.check_mode is True: original.update(payload) meraki.result['changed'] = True meraki.result['data'] = original meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id) + str(meraki.params['vlan_id']) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) meraki.result['changed'] = True meraki.result['data'] = response else: if meraki.module.check_mode is True: meraki.result['data'] = original meraki.exit_json(**meraki.result) meraki.result['data'] = original elif meraki.params['state'] == 'absent': if is_vlan_valid(meraki, net_id, meraki.params['vlan_id']): if meraki.module.check_mode is True: meraki.result['data'] = {} meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('delete', net_id=net_id) + str(meraki.params['vlan_id']) response = meraki.request(path, 'DELETE') meraki.result['changed'] = True meraki.result['data'] = response # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results meraki.exit_json(**meraki.result)