def get_network(self, network_id, network_name, limit=-1): """ Search network_name inside Infinity by using rest api Network id or network_name needs to be provided return the details of a given with given network_id or name """ if network_name is None and network_id is None: self.module.exit_json( msg="You must specify one of the options 'network_name' or 'network_id'.") method = "get" resource_url = '' params = {} response = None if network_id: resource_url = "networks/" + str(network_id) response = self._get_api_call_ansible_handler(method, resource_url) if network_id is None and network_name: method = "get" resource_url = "search" params = {"query": json.dumps( {"name": network_name, "type": "network"})} response = self._get_api_call_ansible_handler( method, resource_url, payload_data=json.dumps(params)) if response and isinstance(response, str): response = json.loads(response) if response and isinstance(response, list) and len( response) > 1 and limit == 1: response = response[0] response = json.dumps(response) return response
def _jsonify(self, data): for encoding in ("utf-8", "latin-1"): try: return json.dumps(data, encoding=encoding) # Old systems using old simplejson module does not support encoding keyword. except TypeError: try: new_data = json_dict_bytes_to_unicode(data, encoding=encoding) except UnicodeDecodeError: continue return json.dumps(new_data) except UnicodeDecodeError: continue self._error(msg='Invalid unicode encoding encountered')
def request(self, method, path, data=None, headers=None): headers = headers or self.DEFAULT_HEADERS if self.token: headers['X-Auth-Token'] = self.token if path.startswith('/'): path = path[1:] url = urlparse.urljoin(self.url, path) if data: data = json.dumps(data) response, headers = fetch_url(self.url_args, url, data=data, headers=headers, method=method) if not 200 <= headers['status'] <= 299: raise NetworkError(response=response, **headers) if int(headers['content-length']) > 0: if headers['content-type'].startswith('application/json'): response = json.load(response) elif headers['content-type'].startswith('text/plain'): response = str(response.read()) return response
def get_network_id(self, network_name="", network_type='lan'): """ query network_id from Infinity via rest api based on given network_name """ method = 'get' resource_url = 'search' response = None if network_name is None: self.module.exit_json( msg="You must specify the option 'network_name'") params = {"query": json.dumps( {"name": network_name, "type": "network"})} response = self._get_api_call_ansible_handler( method, resource_url, payload_data=json.dumps(params)) network_id = "" if response and isinstance(response, str): response = json.loads(response) if response and isinstance(response, list): response = response[0] network_id = response['id'] return network_id
def _get_api_call_ansible_handler( self, method='get', resource_url='', stat_codes=None, params=None, payload_data=None): """ Perform the HTTPS request by using anible get/delete method """ stat_codes = [200] if stat_codes is None else stat_codes request_url = str(self.base_url) + str(resource_url) response = None headers = {'Content-Type': 'application/json'} if not request_url: self.module.exit_json( msg="When sending Rest api call , the resource URL is empty, please check.") if payload_data and not isinstance(payload_data, str): payload_data = json.dumps(payload_data) response_raw = open_url( str(request_url), method=method, timeout=20, headers=headers, url_username=self.auth_user, url_password=self.auth_pass, validate_certs=False, force_basic_auth=True, data=payload_data) response = response_raw.read() payload = '' if response_raw.code not in stat_codes: self.module.exit_json( changed=False, meta=" openurl response_raw.code show error and error code is %r" % (response_raw.code)) else: if isinstance(response, str) and len(response) > 0: payload = response elif method.lower() == 'delete' and response_raw.code == 204: payload = 'Delete is done.' if isinstance(payload, dict) and "text" in payload: self.module.exit_json( changed=False, meta="when calling rest api, returned data is not json ") raise Exception(payload["text"]) return payload
def execute(self, commands, output='json', **kwargs): """Send commands to the device. """ if self.url is None: raise NetworkError('Not connected to endpoint.') if self.enable is not None: commands.insert(0, self.enable) body = self._get_body(commands, output) data = json.dumps(body) headers = {'Content-Type': 'application/json-rpc'} timeout = self.url_args.params['timeout'] response, headers = fetch_url( self.url_args, self.url, data=data, headers=headers, method='POST', timeout=timeout ) if headers['status'] != 200: raise NetworkError(**headers) try: response = json.loads(response.read()) except ValueError: raise NetworkError('unable to load response from device') if 'error' in response: err = response['error'] raise NetworkError( msg=err['message'], code=err['code'], data=err['data'], commands=commands ) if self.enable: response['result'].pop(0) return response['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) meraki.generate_diff(original, diff_payload) original.update(payload) 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: meraki.generate_diff(original, response) 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(clone=dict(type='str'), state=dict(type='str', choices=['present', 'query'], default='present'), org_name=dict(type='str', aliases=['name', 'organization']), org_id=dict(type='int', 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}', } 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 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) 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): 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 # 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, element='str', 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 int_arg_spec = dict(wan_enabled=dict(type='str', choices=['enabled', 'disabled', 'not configured']), using_static_ip=dict(type='bool'), static_ip=dict(type='str'), static_gateway_ip=dict(type='str'), static_subnet_mask=dict(type='str'), static_dns=dict(type='list', elements='str'), vlan=dict(type='int'), ) argument_spec = meraki_argument_spec() argument_spec.update(state=dict(type='str', choices=['absent', 'query', 'present'], default='query'), net_name=dict(type='str'), net_id=dict(type='str'), serial=dict(type='str', required=True), wan1=dict(type='dict', default=None, options=int_arg_spec, aliases=['mgmt1']), wan2=dict(type='dict', default=None, options=int_arg_spec, aliases=['mgmt2']), ) # 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='management_interface') meraki.params['follow_redirects'] = 'all' query_urls = {'management_interface': '/devices/{serial}/managementInterface'} meraki.url_catalog['get_one'].update(query_urls) if meraki.params['net_id'] and meraki.params['net_name']: meraki.fail_json('net_id and net_name are mutually exclusive.') if meraki.params['state'] == 'present': interfaces = ('wan1', 'wan2') for interface in interfaces: if meraki.params[interface] is not None: if meraki.params[interface]['using_static_ip'] is True: if len(meraki.params[interface]['static_dns']) > 2: meraki.fail_json("Maximum number of static DNS addresses is 2.") payload = dict() if meraki.params['state'] == 'present': interfaces = ('wan1', 'wan2') for interface in interfaces: if meraki.params[interface] is not None: wan_int = {'wanEnabled': meraki.params[interface]['wan_enabled'], 'usingStaticIp': meraki.params[interface]['using_static_ip'], } if meraki.params[interface]['vlan'] is not None: wan_int['vlan'] = meraki.params[interface]['vlan'] if meraki.params[interface]['using_static_ip'] is True: wan_int['staticIp'] = meraki.params[interface]['static_ip'] wan_int['staticGatewayIp'] = meraki.params[interface]['static_gateway_ip'] wan_int['staticSubnetMask'] = meraki.params[interface]['static_subnet_mask'] wan_int['staticDns'] = meraki.params[interface]['static_dns'] payload[interface] = wan_int # 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 meraki.params['org_name']: 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('get_one', net_id=net_id, custom={'serial': meraki.params['serial']}) response = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = response elif meraki.params['state'] == 'present': path = meraki.construct_path('get_one', custom={'serial': meraki.params['serial']}) 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) 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 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', element='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(): # define the available arguments/parameters that a user can pass to # the module areas_arg_spec = dict( area_id=dict(type='int', aliases=['id']), area_name=dict(type='str', aliases=['name']), area_type=dict(type='str', aliases=['type'], choices=['normal', 'stub', 'nssa']), ) md5_auth_arg_spec = dict( id=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'), net_id=dict(type='str'), net_name=dict(type='str', aliases=['name', 'network']), enabled=dict(type='bool'), hello_timer=dict(type='int'), dead_timer=dict(type='int'), areas=dict(type='list', default=None, elements='dict', options=areas_arg_spec), md5_authentication_enabled=dict(type='bool'), md5_authentication_key=dict(type='dict', default=None, options=md5_auth_arg_spec, no_log=True), ) # 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='ms_ospf') meraki.params['follow_redirects'] = 'all' query_urls = {'ms_ospf': '/networks/{net_id}/switch/routing/ospf'} update_urls = {'ms_ospf': '/networks/{net_id}/switch/routing/ospf'} meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['update'] = update_urls payload = None # execute checks for argument completeness if meraki.params['dead_timer'] is not None: if meraki.params['dead_timer'] < 1 or meraki.params[ 'dead_timer'] > 65535: meraki.fail_json(msg='dead_timer must be between 1 and 65535') if meraki.params['hello_timer'] is not None: if meraki.params['hello_timer'] < 1 or meraki.params[ 'hello_timer'] > 255: meraki.fail_json(msg='hello_timer must be between 1 and 65535') if meraki.params['md5_authentication_enabled'] is False: if meraki.params['md5_authentication_key'] is not None: meraki.fail_json( msg= 'md5_authentication_key must not be configured when md5_authentication_enabled is false' ) # 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 and meraki.params['net_name']: 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('get_all', net_id=net_id) response = meraki.request(path, method='GET') meraki.result['data'] = response meraki.exit_json(**meraki.result) elif meraki.params['state'] == 'present': original = meraki.request(meraki.construct_path('get_all', net_id=net_id), method='GET') payload = construct_payload(meraki) if meraki.is_update_required(original, payload) is True: if meraki.check_mode is True: meraki.result['data'] = payload meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if 'md5_authentication_key' in response: response['md5_authentication_key'][ 'passphrase'] = 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER' meraki.result['data'] = response meraki.result['changed'] = True meraki.exit_json(**meraki.result) else: if 'md5_authentication_key' in original: original['md5_authentication_key'][ 'passphrase'] = 'VALUE_SPECIFIED_IN_NO_LOG_PARAMETER' meraki.result['data'] = original 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: 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: 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): 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: meraki.result['data'] = original elif meraki.params['state'] == 'absent': if is_vlan_valid(meraki, net_id, meraki.params['vlan_id']): 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 # 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) # 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 system_save(self, backup=False): self._system_save_active(backup=backup) rules = json.dumps(self.state_dict, sort_keys=True, indent=4, separators=(',', ': ')) self._write_rules_to_file(rules, self.state_save_path)
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', 'absent'], default='present'), net_name=dict(type='str'), net_id=dict(type='str'), stack_id=dict(type='str'), serials=dict(type='list', elements='str', default=None), name=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='switch_stack') meraki.params['follow_redirects'] = 'all' query_urls = {'switch_stack': '/networks/{net_id}/switch/stacks'} query_url = {'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}'} add_urls = { 'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}/add' } remove_urls = { 'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}/remove' } create_urls = {'switch_stack': '/networks/{net_id}/switch/stacks'} delete_urls = { 'switch_stack': '/networks/{net_id}/switch/stacks/{stack_id}' } meraki.url_catalog['get_all'].update(query_urls) meraki.url_catalog['get_one'].update(query_url) meraki.url_catalog['add'] = add_urls meraki.url_catalog['remove'] = remove_urls meraki.url_catalog['create'] = create_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) org_id = meraki.params['org_id'] 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: net_id = meraki.get_net_id(net_name=meraki.params['net_name'], data=meraki.get_nets(org_id=org_id)) # assign and lookup stack_id stack_id = meraki.params['stack_id'] if stack_id is None and meraki.params['name'] is not None: stack_id = get_stack_id(meraki, net_id) path = meraki.construct_path('get_all', net_id=net_id) stacks = meraki.request(path, method='GET') if meraki.params['state'] == 'query': if stack_id is None: meraki.result['data'] = stacks else: meraki.result['data'] = get_stack(stack_id, stacks) elif meraki.params['state'] == 'present': if meraki.params['stack_id'] is None: payload = { 'serials': meraki.params['serials'], 'name': meraki.params['name'], } 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: payload = {'serial': meraki.params['serials'][0]} original = get_stack(stack_id, stacks) comparable = deepcopy(original) comparable.update(payload) if meraki.params['serials'][0] not in comparable['serials']: comparable['serials'].append(meraki.params['serials'][0]) # meraki.fail_json(msg=comparable) if meraki.is_update_required(original, comparable, optional_ignore=['serial']): path = meraki.construct_path('add', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='POST', 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 meraki.params['serials'] is None: path = meraki.construct_path('delete', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='DELETE') meraki.result['data'] = {} meraki.result['changed'] = True else: payload = {'serial': meraki.params['serials'][0]} original = get_stack(stack_id, stacks) comparable = deepcopy(original) comparable.update(payload) if meraki.params['serials'][0] in comparable['serials']: comparable['serials'].remove(meraki.params['serials'][0]) if meraki.is_update_required(original, comparable, optional_ignore=['serial']): path = meraki.construct_path('remove', net_id=net_id, custom={'stack_id': stack_id}) response = meraki.request(path, method='POST', payload=json.dumps(payload)) if meraki.status == 200: 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 hubs_args = dict( hub_id=dict(type='str'), use_default_route=dict(type='bool'), ) subnets_args = dict( local_subnet=dict(type='str'), use_vpn=dict(type='bool'), ) 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'), hubs=dict(type='list', default=None, elements='dict', options=hubs_args), subnets=dict(type='list', default=None, elements='dict', options=subnets_args), mode=dict(type='str', choices=['none', 'hub', 'spoke']), ) # 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='site_to_site_vpn') meraki.params['follow_redirects'] = 'all' query_urls = {'site_to_site_vpn': '/networks/{net_id}/siteToSiteVpn/'} update_urls = {'site_to_site_vpn': '/networks/{net_id}/siteToSiteVpn/'} meraki.url_catalog['get_all'].update(query_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'] 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: 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': path = meraki.construct_path('get_all', net_id=net_id) response = meraki.request(path, method='GET') meraki.result['data'] = response elif meraki.params['state'] == 'present': path = meraki.construct_path('get_all', net_id=net_id) original = meraki.request(path, method='GET') payload = assemble_payload(meraki) comparable = deepcopy(original) comparable.update(payload) if meraki.is_update_required(original, payload): path = meraki.construct_path('update', net_id=net_id) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) meraki.result['changed'] = True meraki.result['data'] = response 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(clone=dict(type='str'), state=dict(type='str', choices=['present', 'query'], default='present'), org_name=dict(type='str', aliases=['name', 'organization']), org_id=dict(type='int', 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}', } 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 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) 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 orgs = meraki.get_orgs() meraki.result['data'] = orgs elif meraki.params['state'] == 'present': if meraki.params['clone']: # Cloning payload = {'name': meraki.params['org_name']} meraki.result['data'] = json.loads( meraki.request( meraki.construct_path( 'clone', org_name=meraki.params['clone'] ), payload=json.dumps(payload), method='POST')) elif not meraki.params['org_id'] and meraki.params['org_name']: # Create new organization payload = {'name': meraki.params['org_name']} meraki.result['data'] = json.loads( meraki.request( meraki.construct_path('create'), method='POST', payload=json.dumps(payload))) 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'], } meraki.result['data'] = json.loads( meraki.request( meraki.construct_path( 'update', org_id=meraki.params['org_id'] ), method='PUT', payload=json.dumps(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( 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)
payload['dropUntaggedTraffic'] = meraki.params['drop_untagged'] if meraki.params['drop_untagged'] is True: payload['vlan'] = None 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['appliance_port_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': payload = {'number': meraki.params['appliance_port_id'], 'vlan': '1', 'type': 'Trunk', 'dropUntaggedTraffic': 'False', 'allowedVlans': 'All', 'enabled': True }
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'), lldp_cdp_timespan=dict(type='int'), hostname=dict(type='str', aliases=['name']), model=dict(type='str'), tags=dict(type='list', elements='str', default=None), lat=dict(type='float', aliases=['latitude'], default=None), lng=dict(type='float', aliases=['longitude'], default=None), address=dict(type='str', default=None), move_map_marker=dict(type='bool', default=None), note=dict(type='str', default=None), query=dict(type='str', default=None, choices=['lldp_cdp', 'uplink'])) # 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, ) meraki = MerakiModule(module, function='device') if meraki.params['query'] is not None \ and meraki.params['query'] == '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}/devices'} query_device_urls = {'device': '/networks/{net_id}/devices/{serial}'} query_device_uplink_urls = { 'device': '/networks/{net_id}/devices/{serial}/uplink' } query_device_lldp_urls = { 'device': '/networks/{net_id}/devices/{serial}/lldp_cdp' } 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/{serial}/remove' } 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['get_device_uplink'] = query_device_urls meraki.url_catalog['get_device_lldp'] = query_device_lldp_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 # 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, custom={'serial': meraki.params['serial']}) request = meraki.request(path, method='GET') device.append(request) meraki.result['data'] = device if meraki.params['query'] == 'uplink': path = meraki.construct_path( 'get_device_uplink', net_id=net_id, custom={'serial': meraki.params['serial']}) meraki.result['data'] = (meraki.request(path, method='GET')) elif meraki.params['query'] == '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_lldp', net_id=net_id, custom={'serial': meraki.params['serial']}) 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, params={'perPage': '1000'}) devices = meraki.request(path, method='GET', pagination_items=1000) 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 net_id is None: # Claim a device to an organization 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: # A device is assumed to be in an organization device_list = get_net_devices(meraki, net_id) if is_device_valid( meraki, meraki.params['serial'], device_list) is True: # Device is in network, update query_path = meraki.construct_path('get_all', net_id=net_id) if is_device_valid(meraki, meraki.params['serial'], device_list): payload = construct_payload(meraki.params) query_path = meraki.construct_path( 'get_device', net_id=net_id, custom={'serial': meraki.params['serial']}) device_data = meraki.request(query_path, method='GET') ignore_keys = [ 'lanIp', 'serial', 'mac', 'model', 'networkId', 'moveMapMarker', 'wan1Ip', 'wan2Ip' ] 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: # Claim device into network 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 = {'serials': [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, custom={'serial': meraki.params['serial']}) 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 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'), number=dict(type='int', aliases=['port', 'port_id']), vlan=dict(type='int'), access_policy=dict(type='str', choices=['open', '8021x-radius', 'mac-radius', 'hybris-radius']), allowed_vlans=dict(type='str'), port_type=dict(type='str', choices=['access', 'trunk']), drop_untagged_traffic=dict(type='bool'), 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='mx_l2_interface') module.params['follow_redirects'] = 'all' get_all_urls = {'mx_l2_interface': '/networks/{net_id}/appliance/ports'} get_one_urls = {'mx_l2_interface': '/networks/{net_id}/appliance/ports/{port_id}'} update_urls = {'mx_l2_interface': '/networks/{net_id}/appliance/ports/{port_id}'} meraki.url_catalog['query_all'] = get_all_urls meraki.url_catalog['query_one'] = get_one_urls meraki.url_catalog['update'] = update_urls if meraki.params['net_name'] and meraki.params['net_id']: meraki.fail_json(msg='net_name and net_id are mutually exclusive.') if meraki.params['port_type'] == 'access': if meraki.params['allowed_vlans'] is not None: meraki.meraki.fail_json(msg='allowed_vlans is mutually exclusive with port type trunk.') 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['number'] is not None: path = meraki.construct_path('query_one', net_id=net_id, custom={'port_id': meraki.params['number']}) else: path = meraki.construct_path('query_all', net_id=net_id) response = meraki.request(path, method='GET') meraki.result['data'] = response meraki.exit_json(**meraki.result) elif meraki.params['state'] == 'present': path = meraki.construct_path('query_one', net_id=net_id, custom={'port_id': meraki.params['number']}) original = meraki.request(path, method='GET') payload = construct_payload(meraki) if meraki.is_update_required(original, payload): meraki.generate_diff(original, payload) if meraki.check_mode is True: original.update(payload) meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id, custom={'port_id': meraki.params['number']}) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: meraki.result['data'] = response meraki.result['changed'] = True meraki.exit_json(**meraki.result) else: meraki.result['data'] = original 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 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 # 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']): if meraki.check_mode is True: original.update(proposed) meraki.result['data'] = original meraki.result['changed'] = True meraki.exit_json(**meraki.result) 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(): 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'), 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='int'), 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, element='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', element='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, element='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/'} 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') # 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) + str(ssid_id) meraki.result['data'] = meraki.request(path, method='GET') elif meraki.params['number']: path = meraki.construct_path( 'get_one', net_id=net_id) + 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] ssids = get_ssids(meraki, net_id) original = ssids[get_ssid_number(meraki.params['name'], ssids)] # meraki.fail_json(msg=meraki.is_update_required(original, payload), original=original, payload=payload) if meraki.is_update_required(original, payload): 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 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) # meraki.fail_json(msg='Payload', payload=payload) 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=['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 request(self, path, method=None, data=None, qs=None, api_version="v1"): ''' Generic HTTP method for MSO requests. ''' self.path = path if method is not None: self.method = method # If we PATCH with empty operations, return if method == 'PATCH' and not data: return {} # if method in ['PATCH', 'PUT']: # if qs is not None: # qs['enableVersionCheck'] = 'true' # else: # qs = dict(enableVersionCheck='true') if method in ['PATCH']: if qs is not None: qs['validate'] = 'false' else: qs = dict(validate='false') resp = None if self.module._socket_path: self.connection.set_params(self.params) if api_version is not None: uri = '/mso/api/{0}/{1}'.format(api_version, self.path) else: uri = self.path if qs is not None: uri = uri + update_qs(qs) try: info = self.connection.send_request(method, uri, json.dumps(data)) self.url = info.get('url') info.pop('date') except Exception as e: try: error_obj = json.loads(to_text(e)) except Exception: error_obj = dict(error=dict( code=-1, message= "Unable to parse error output as JSON. Raw error message: {0}" .format(e), exception=to_text(e))) pass self.fail_json(msg=error_obj['error']['message']) else: if api_version is not None: self.url = '{0}api/{1}/{2}'.format(self.base_only_uri, api_version, self.path.lstrip('/')) else: self.url = '{0}{1}'.format(self.base_only_uri, self.path.lstrip('/')) if qs is not None: self.url = self.url + update_qs(qs) resp, info = fetch_url(self.module, self.url, headers=self.headers, data=json.dumps(data), method=self.method, timeout=self.params.get('timeout'), use_proxy=self.params.get('use_proxy')) self.response = info.get('msg') self.status = info.get('status', -1) # Get change status from HTTP headers if 'modified' in info: self.has_modified = True if info.get('modified') == 'false': self.result['changed'] = False elif info.get('modified') == 'true': self.result['changed'] = True # 200: OK, 201: Created, 202: Accepted if self.status in (200, 201, 202): try: output = resp.read() if output: try: return json.loads(output) except Exception as e: self.error = dict( code=-1, message= "Unable to parse output as JSON, see 'raw' output. {0}" .format(e)) self.result['raw'] = output return except AttributeError: return info.get('body') # 204: No Content elif self.status == 204: return {} # 404: Not Found elif self.method == 'DELETE' and self.status == 404: return {} # 400: Bad Request, 401: Unauthorized, 403: Forbidden, # 405: Method Not Allowed, 406: Not Acceptable # 500: Internal Server Error, 501: Not Implemented elif self.status >= 400: self.result['status'] = self.status body = info.get('body') if body is not None: try: if isinstance(body, dict): payload = body else: payload = json.loads(body) except Exception as e: self.error = dict( code=-1, message= "Unable to parse output as JSON, see 'raw' output. %s" % e) self.result['raw'] = body self.fail_json(msg='MSO Error:', data=data, info=info) self.error = payload if 'code' in payload: self.fail_json( msg='MSO Error {code}: {message}'.format(**payload), data=data, info=info, payload=payload) else: self.fail_json(msg='MSO Error:'.format(**payload), data=data, info=info, payload=payload) else: # Connection error msg = 'Connection failed for {0}. {1}'.format( info.get('url'), info.get('msg')) self.error = msg self.fail_json(msg=msg) return {}
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 pf_rules = dict(name=dict(type='str'), lan_ip=dict(type='str'), uplink=dict(type='str', choices=['internet1', 'internet2', 'both']), public_port=dict(type='str'), local_port=dict(type='str'), allowed_ips=dict(type='list'), protocol=dict(type='str', choices=['tcp', 'udp'])) 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=pf_rules), ) # 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_port_forward') meraki.params['follow_redirects'] = 'all' query_urls = {'mx_port_forward': '/networks/{net_id}/portForwardingRules/'} update_urls = { 'mx_port_forward': '/networks/{net_id}/portForwardingRules/' } 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)) if meraki.params['state'] == 'query': meraki.result['data'] = 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 = assemble_payload(meraki) else: payload = dict() update = False try: if len(rules) - 1 != len( payload['rules'] ): # Quick and simple check to avoid more processing update = True if update is False: for r in range(len(rules) - 1): if meraki.is_update_required(rules[r], payload['rules'][r]) is True: update = True except KeyError: pass # if meraki.params['syslog_default_rule']: # meraki.fail_json(msg='Compare', original=rules, proposed=payload) if update is True: response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: 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 = nfvis_argument_spec() argument_spec.update(state=dict(type='str', choices=['absent', 'present'], default='present'), name=dict(type='str', aliases=['bridge']), ports=dict(type='list'), ip=dict(type='list'), vlan=dict(type='int'), purge=dict(type='bool', default=False), dhcp=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, ) nfvis = nfvisModule(module) payload = None port = None nfvis.result['changed'] = False # Get the list of existing bridges response = nfvis.request('/config/bridges?deep') nfvis.result['current'] = response nfvis.result['what_changed'] = [] # Turn the list of dictionaries returned in the call into a dictionary of dictionaries hashed by the bridge name bridge_dict = {} try: for item in response['network:bridges']['bridge']: name = item['name'] bridge_dict[name] = item nfvis.result['debug'] = bridge_dict except TypeError: pass except KeyError: pass if nfvis.params['state'] == 'present': if nfvis.params['name'] not in bridge_dict or nfvis.params[ 'purge'] == True: # If the # Construct the payload payload = {'bridge': {}} payload['bridge']['name'] = nfvis.params['name'] if nfvis.params['dhcp'] == True: payload['bridge']['dhcp'] = [None] payload['bridge']['port'] = [] if nfvis.params['ports']: for port in nfvis.params['ports']: payload['bridge']['port'].append({'name': port}) payload['bridge'].pop('vlan', None) if nfvis.params['vlan']: payload['bridge']['vlan'] = nfvis.params['vlan'] if nfvis.params['ip']: payload['bridge']['ip'] = {} if 'address' in nfvis.params['ip']: payload['bridge']['ip']['address'] = nfvis.params['ip'][ 'address'] else: module.fail_json(msg="address must be specified for ip") if 'netmask' in nfvis.params['ip']: payload['bridge']['ip']['netmask'] = nfvis.params['ip'][ 'netmask'] else: module.fail_json(msg="netmask must be specified for ip") if nfvis.params['name'] in bridge_dict: # We are overwritting (purging) what is on the NFVIS host url_path = '/config/bridges/bridge/{0}'.format( nfvis.params['name']) if not module.check_mode: response = nfvis.request(url_path, method='PUT', payload=json.dumps(payload)) else: url_path = '/config/bridges' if not module.check_mode: response = nfvis.request(url_path, method='POST', payload=json.dumps(payload)) nfvis.result['changed'] = True else: # The bridge exists on the device, so let's start with the original payload and see if anything changed payload = {'bridge': bridge_dict[nfvis.params['name']]} if nfvis.params['ports']: # Check ports if 'port' not in payload['bridge']: payload['bridge']['port'] = [] # No ports are on the NFVIS host, so add them all for port in nfvis.params['ports']: payload['bridge']['port'].append({'name': port}) nfvis.result['what_changed'].append('port') else: # Add the ports that are not already on the NFVIS host existing_ports = [] for item in payload['bridge']['port']: existing_ports.append(item['name']) for port in nfvis.params['ports']: if port not in existing_ports: payload['bridge']['port'].append({'name': port}) nfvis.result['what_changed'].append('port') if nfvis.params['vlan']: if 'vlan' not in payload['bridge'] or nfvis.params[ 'vlan'] != payload['bridge']['vlan']: payload['bridge']['vlan'] = nfvis.params['vlan'] nfvis.result['what_changed'].append('vlan') if nfvis.params['dhcp']: if nfvis.params['dhcp'] == True and 'dhcp' not in payload[ 'bridge']: payload['bridge']['dhcp'] = [nfvis.params['dhcp']] nfvis.result['what_changed'].append('dhcp') elif nfvis.params['dhcp'] == False and 'dhcp' in payload[ 'bridge']: payload['bridge']['dhcp'] = None nfvis.result['what_changed'].append('dhcp') if nfvis.params['ip']: if 'ip' not in payload['bridge']: # No ip on the NFVIS host, so add the entire dict payload['bridge']['ip'] = nfvis.params['ip'] nfvis.result['what_changed'].append('ip') else: if 'address' in nfvis.params['ip']: if payload['bridge']['ip']['address'] != nfvis.params[ 'ip']['address']: payload['bridge']['ip']['address'] = nfvis.params[ 'ip']['address'] nfvis.result['what_changed'].append('ip') else: module.fail_json( msg="address must be specified for ip") if 'netmask' in nfvis.params['ip']: if payload['bridge']['ip']['netmask'] != nfvis.params[ 'ip']['netmask']: payload['bridge']['ip']['netmask'] = nfvis.params[ 'ip']['netmask'] nfvis.result['what_changed'].append('ip') else: module.fail_json( msg="netmask must be specified for ip") if nfvis.result['what_changed']: url_path = '/config/bridges/bridge/{0}'.format( nfvis.params['name']) nfvis.result['changed'] = True if not module.check_mode: response = nfvis.request(url_path, method='PUT', payload=json.dumps(payload)) else: if nfvis.params['name'] in bridge_dict: url_path = '/config/bridges/bridge/{0}'.format( nfvis.params['name']) nfvis.result['changed'] = True if not module.check_mode: response = nfvis.request(url_path, 'DELETE') # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results nfvis.exit_json(**nfvis.result)
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', elements='str'), allowed_ips=dict(type='list', elements='str'), ) 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', elements='str'), 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', elements='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', elements='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', elements='str'), ) 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', elements='str', 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}/appliance/firewall/oneToManyNatRules' } onetoone_urls = { 'nat': '/networks/{net_id}/appliance/firewall/oneToOneNatRules' } port_forwarding_urls = { 'nat': '/networks/{net_id}/appliance/firewall/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 request(self, path, method=None, data=None, qs=None): ''' Generic HTTP method for MSO requests. ''' self.path = path if method is not None: self.method = method # If we PATCH with empty operations, return if method == 'PATCH' and not data: return {} self.url = urljoin(self.baseuri, path) if qs is not None: self.url = self.url + update_qs(qs) resp, info = fetch_url(self.module, self.url, headers=self.headers, data=json.dumps(data), method=self.method, timeout=self.params.get('timeout'), use_proxy=self.params.get('use_proxy')) self.response = info.get('msg') self.status = info.get('status') # self.result['info'] = info # Get change status from HTTP headers if 'modified' in info: self.has_modified = True if info.get('modified') == 'false': self.result['changed'] = False elif info.get('modified') == 'true': self.result['changed'] = True # 200: OK, 201: Created, 202: Accepted, 204: No Content if self.status in (200, 201, 202, 204): output = resp.read() if output: return json.loads(output) # 404: Not Found elif self.method == 'DELETE' and self.status == 404: return {} # 400: Bad Request, 401: Unauthorized, 403: Forbidden, # 405: Method Not Allowed, 406: Not Acceptable # 500: Internal Server Error, 501: Not Implemented elif self.status >= 400: try: output = resp.read() payload = json.loads(output) except (ValueError, AttributeError): try: payload = json.loads(info.get('body')) except Exception: self.fail_json(msg='MSO Error:', data=data, info=info) if 'code' in payload: self.fail_json(msg='MSO Error {code}: {message}'.format(**payload), data=data, info=info, payload=payload) else: self.fail_json(msg='MSO Error:'.format(**payload), data=data, info=info, payload=payload) return {}
def approle_login(login_data): api_url = '/'.join([login_data['vault_addr'], 'auth/approle/login']) r = requests.post(api_url, data=json.dumps(login_data)) return r.json()['auth']['client_token']
def post_pritunl_user(module): result = {} org_name = module.params.get('organization') user_name = module.params.get('user_name') if user_name is None: module.fail_json( msg='Please provide a user name using user_name=<username>') user_params = { 'name': user_name, 'email': module.params.get('user_email'), 'groups': module.params.get('user_groups'), 'disabled': module.params.get('user_disabled'), 'gravatar': module.params.get('user_gravatar'), 'type': module.params.get('user_type'), } org_obj_list = _list_pritunl_organization(module, {"name": org_name}) if len(org_obj_list) == 0: module.fail_json( msg="Can not add user to organization '%s' which does not exist" % org_name) org_id = org_obj_list[0]['id'] # Grab existing users from this org users = _list_pritunl_user(module, org_id, filters={"name": user_name}) # Check if the pritunl user already exists # If yes do nothing if len(users) > 0: # Compare remote user params with local user_params and trigger update if needed user_params_changed = False for key in user_params.keys(): # When a param is not specified grab the existing one to prevent from changing it with the PUT request if user_params[key] is None: user_params[key] = users[0][key] # groups is a list comparison if key == 'groups': if set(users[0][key]) != set(user_params[key]): user_params_changed = True # otherwise it is either a boolean or a string else: if users[0][key] != user_params[key]: user_params_changed = True # Trigger a PUT on the API to update the current user if settings have changed if user_params_changed: response = pritunl_auth_request( module, 'PUT', "/user/%s/%s" % (org_id, users[0]['id']), headers={'Content-Type': 'application/json'}, data=json.dumps(user_params)) if response.getcode() != 200: module.fail_json( msg="Could not update Pritunl user %s from %s organization" % (user_name, org_name)) else: result['changed'] = True result['response'] = json.loads(response.read()) else: result['changed'] = False result['response'] = users else: response = pritunl_auth_request( module, 'POST', "/user/%s" % org_id, headers={'Content-Type': 'application/json'}, data=json.dumps(user_params)) if response.getcode() != 200: module.fail_json( msg="Could not add Pritunl user %s to %s organization" % (user_params['name'], org_name)) else: result['changed'] = True result['response'] = json.loads(response.read()) module.exit_json(**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='present'), org_name=dict(type='str', aliases=['organization']), org_id=dict(type='str'), net_name=dict(type='str'), net_id=dict(type='str'), upgrade_strategy=dict( type='str', choices=['minimize_upgrade_time', 'minimize_client_downtime']), ipv6_bridge_enabled=dict(type='bool'), led_lights_on=dict(type='bool'), location_analytics_enabled=dict(type='bool'), meshing_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='mr_settings') meraki.params['follow_redirects'] = 'all' query_urls = {'mr_settings': '/networks/{net_id}/wireless/settings'} update_urls = {'mr_settings': '/networks/{net_id}/wireless/settings'} meraki.url_catalog['get_one'].update(query_urls) meraki.url_catalog['update'] = update_urls 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': path = meraki.construct_path('get_one', net_id=net_id) response = meraki.request(path, method='GET') meraki.result['data'] = response meraki.exit_json(**meraki.result) elif meraki.params['state'] == 'present': path = meraki.construct_path('get_one', net_id=net_id) original = meraki.request(path, method='GET') payload = construct_payload(meraki) if meraki.is_update_required(original, payload) is True: if meraki.check_mode is True: meraki.result['data'] = payload meraki.result['changed'] = True meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) meraki.result['data'] = response meraki.result['changed'] = True meraki.exit_json(**meraki.result) else: meraki.result['data'] = original 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 argument_spec = nfvis_argument_spec() argument_spec.update(state=dict(type='str', choices=['absent', 'present'], default='present'), name=dict(type='str', aliases=['deployment']), image=dict(type='str'), flavor=dict(type='str'), bootup_time=dict(type='int', default=-1), recovery_wait_time=dict(type='int', default=0), kpi_data=dict(type='bool', default=False), scaling=dict(type='bool', default=False), scaling_min_active=dict(type='int', default=1), scaling_max_active=dict(type='int', default=1), placement_type=dict(type='str', default='zone_host'), placement_enforcement=dict(type='str', default='strict'), placement_host=dict(type='str', default='datastore1'), recovery_type=dict(type='str', default='AUTO'), action_on_recovery=dict(type='str', default='REBOOT_ONLY'), interfaces=dict(type='list'), port_forwarding=dict(type='list'), config_data=dict(type='list'), tenant=dict(type='str', default='admin'), ) # 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, ) nfvis = nfvisModule(module) payload = None port = None response = {} # Get the list of existing deployments url_path = '/config/vm_lifecycle/tenants/tenant/{0}/deployments?deep'.format(nfvis.params['tenant']) response = nfvis.request(url_path, method='GET') # nfvis.result['current'] = response # Turn the list of dictionaries returned in the call into a dictionary of dictionaries hashed by the deployment name deployment_dict = {} try: for item in response['vmlc:deployments']['deployment']: name = item['name'] deployment_dict[name] = item except TypeError: pass except KeyError: pass if nfvis.params['state'] == 'present': if nfvis.params['name'] in deployment_dict: # The deployment exists on the device, so check to see if it is the same configuration nfvis.result['changed'] = False else: # The deployment does not exist on the device, so add it # Construct the payload payload = {'deployment': {}} payload['deployment']['name'] = nfvis.params['name'] payload['deployment']['vm_group'] = {} payload['deployment']['vm_group']['name'] = nfvis.params['name'] if nfvis.params['image']: payload['deployment']['vm_group']['image'] = nfvis.params['image'] else: module.fail_json(msg="image must be specified when state is present") if nfvis.params['flavor']: payload['deployment']['vm_group']['flavor'] = nfvis.params['flavor'] else: module.fail_json(msg="flavor must be specified when state is present") payload['deployment']['vm_group']['bootup_time'] = nfvis.params['bootup_time'] payload['deployment']['vm_group']['recovery_wait_time'] = nfvis.params['recovery_wait_time'] payload['deployment']['vm_group']['kpi_data'] = {} payload['deployment']['vm_group']['kpi_data']['enabled'] = nfvis.params['kpi_data'] payload['deployment']['vm_group']['scaling'] = {} payload['deployment']['vm_group']['scaling']['min_active'] = nfvis.params['scaling_min_active'] payload['deployment']['vm_group']['scaling']['max_active'] = nfvis.params['scaling_max_active'] payload['deployment']['vm_group']['scaling']['elastic'] = nfvis.params['scaling'] payload['deployment']['vm_group']['placement'] = {} payload['deployment']['vm_group']['placement']['type'] = nfvis.params['placement_type'] payload['deployment']['vm_group']['placement']['enforcement'] = nfvis.params['placement_enforcement'] payload['deployment']['vm_group']['placement']['host'] = nfvis.params['placement_host'] payload['deployment']['vm_group']['recovery_policy'] = {} payload['deployment']['vm_group']['recovery_policy']['recovery_type'] = nfvis.params['recovery_type'] payload['deployment']['vm_group']['recovery_policy']['action_on_recovery'] = nfvis.params['action_on_recovery'] port_forwarding = {} if nfvis.params['port_forwarding']: for item in nfvis.params['port_forwarding']: port_forwarding['port'] = {} port_forwarding['port']['type'] = item.get('type', 'ssh') port_forwarding['port']['vnf_port'] = item.get('vnf_port', 22) port_forwarding['port']['external_port_range'] = {} if 'proxy_port' in item: port_forwarding['port']['external_port_range']['start'] = item['proxy_port'] port_forwarding['port']['external_port_range']['end'] = item['proxy_port'] else: module.fail_json(msg="proxy_port must be specified for port_forwarding") port_forwarding['port']['protocol'] = item.get('protocol', 'tcp') port_forwarding['port']['source_bridge'] = item.get('source_bridge', 'MGMT') if nfvis.params['interfaces']: payload['deployment']['vm_group']['interfaces'] = [] for index, item in enumerate(nfvis.params['interfaces']): entry = {} entry['interface'] = {} entry['interface']['nicid'] = item.get('nicid', index) if 'network' in item: entry['interface']['network'] = item['network'] else: module.fail_json(msg="network must be specified for interface") if 'model' in item: entry['interface']['model'] = item['model'] if index == 0 and 'port' in port_forwarding: entry['interface']['port_forwarding'] = port_forwarding payload['deployment']['vm_group']['interfaces'].append(entry) if nfvis.params['config_data']: payload['deployment']['vm_group']['config_data'] = [] for item in nfvis.params['config_data']: entry = {'configuration': {}} if 'dst' in item: entry['configuration']['dst'] = item['dst'] else: module.fail_json(msg="dst must be specified for config_data") if 'data' in item: if isinstance(item['data'], str): entry['configuration']['data'] = item['data'] else: entry['configuration']['data'] = json.dumps(item['data']) else: module.fail_json(msg="data must be specified for config_data") payload['deployment']['vm_group']['config_data'].append(entry) if nfvis.params['kpi_data'] == True or nfvis.params['bootup_time'] > 0: payload['deployment']['vm_group']['kpi_data']['kpi'] = {} payload['deployment']['vm_group']['kpi_data']['kpi']['event_name'] = 'VM_ALIVE' payload['deployment']['vm_group']['kpi_data']['kpi']['metric_value'] = 1 payload['deployment']['vm_group']['kpi_data']['kpi']['metric_cond'] = 'GT' payload['deployment']['vm_group']['kpi_data']['kpi']['metric_type'] = 'UINT32' payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector'] = {} payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector']['type'] = 'ICMPPing' payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector']['nicid'] = 0 payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector']['poll_frequency'] = 3 payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector']['polling_unit'] = 'seconds' payload['deployment']['vm_group']['kpi_data']['kpi']['metric_collector']['continuous_alarm'] = False payload['deployment']['vm_group']['rules'] = {} payload['deployment']['vm_group']['rules']['admin_rules'] = {} payload['deployment']['vm_group']['rules']['admin_rules']['rule'] = {} payload['deployment']['vm_group']['rules']['admin_rules']['rule']['event_name'] = 'VM_ALIVE' payload['deployment']['vm_group']['rules']['admin_rules']['rule']['action'] = [ "ALWAYS log", "FALSE recover autohealing", "TRUE servicebooted.sh" ] nfvis.result['payload'] = payload url_path = '/config/vm_lifecycle/tenants/tenant/{0}/deployments'.format(nfvis.params['tenant']) if not module.check_mode: response = nfvis.request(url_path, method='POST', payload=json.dumps(payload)) nfvis.result['changed'] = True else: if nfvis.params['name'] in deployment_dict: url_path = '/config/vm_lifecycle/tenants/tenant/{0}/deployments/deployment/{1}'.format(nfvis.params['tenant'], nfvis.params['name']) if not module.check_mode: response = nfvis.request(url_path, 'DELETE') nfvis.result['changed'] = True # 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 nfvis so they can implement a check mode # if module.check_mode: # nfvis.exit_json(**nfvis.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) # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results nfvis.exit_json(**nfvis.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: if unit['name'] == meraki.params['hostname']: device.append(unit) meraki.result['data'] = device 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' ] 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: 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 rules_arg_spec = dict(comment=dict(type='str'), policy=dict(type='str', choices=['allow', 'deny']), ip_version=dict(type='str', choices=['ipv4', 'ipv6', 'any']), protocol=dict(type='str', choices=['tcp', 'udp', 'any']), src_cidr=dict(type='str'), src_port=dict(type='str'), dst_cidr=dict(type='str'), dst_port=dict(type='str'), vlan=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'), rules=dict(type='list', elements='dict', options=rules_arg_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='switch_access_list') meraki.params['follow_redirects'] = 'all' query_url = {'switch_access_list': '/networks/{net_id}/switch/accessControlLists'} update_url = {'switch_access_list': '/networks/{net_id}/switch/accessControlLists'} meraki.url_catalog['get_all'].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) if meraki.params['state'] == 'query': path = meraki.construct_path('get_all', net_id=net_id) result = meraki.request(path, method='GET') if meraki.status == 200: meraki.result['data'] = result elif meraki.params['state'] == 'present': path = meraki.construct_path('get_all', net_id=net_id) original = meraki.request(path, method='GET') payload = construct_payload(meraki.params) comparable = deepcopy(original) if len(comparable['rules']) > 1: del comparable['rules'][len(comparable['rules']) - 1] # Delete the default rule for comparison else: del comparable['rules'][0] if meraki.is_update_required(comparable, payload): if meraki.check_mode is True: default_rule = original['rules'][len(original['rules']) - 1] payload['rules'].append(default_rule) new_rules = {'rules': payload['rules']} meraki.result['data'] = new_rules meraki.result['changed'] = True diff = recursive_diff(original, new_rules) meraki.result['diff'] = {'before': diff[0], 'after': diff[1]} meraki.exit_json(**meraki.result) path = meraki.construct_path('update', net_id=net_id) response = meraki.request(path, method='PUT', payload=json.dumps(payload)) if meraki.status == 200: diff = recursive_diff(original, payload) meraki.result['data'] = response meraki.result['changed'] = True meraki.result['diff'] = {'before': diff[0], 'after': diff[1]} 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)