def main(): module = AnsibleModule( supports_check_mode=True, argument_spec=dict( url=dict(type='str', required=True), api_key=dict(type='str', required=True, no_log=True), text=dict(type='str', required=True), channel=dict(type='str', default=None), username=dict(type='str', default='Ansible'), icon_url=dict(type='str', default='https://www.ansible.com/favicon.ico'), validate_certs=dict(default='yes', type='bool'), )) # init return dict result = dict(changed=False, msg="OK") # define webhook webhook_url = "{0}/hooks/{1}".format(module.params['url'], module.params['api_key']) result['webhook_url'] = webhook_url # define payload payload = {} for param in ['text', 'channel', 'username', 'icon_url']: if module.params[param] is not None: payload[param] = module.params[param] payload = module.jsonify(payload) result['payload'] = payload # http headers headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', } # notes: # Nothing is done in check mode # it'll pass even if your server is down or/and if your token is invalid. # If someone find good way to check... # send request if not in test mode if module.check_mode is False: response, info = fetch_url(module=module, url=webhook_url, headers=headers, method='POST', data=payload) # something's wrong if info['status'] != 200: # some problem result[ 'msg'] = "Failed to send mattermost message, the error was: {0}".format( info['msg']) module.fail_json(**result) # Looks good module.exit_json(**result)
class NitroAPICaller(object): _argument_spec = dict( nsip=dict( fallback=(env_fallback, ['NETSCALER_NSIP']), ), nitro_user=dict( fallback=(env_fallback, ['NETSCALER_NITRO_USER']), ), nitro_pass=dict( fallback=(env_fallback, ['NETSCALER_NITRO_PASS']), no_log=True ), nitro_protocol=dict( choices=['http', 'https'], fallback=(env_fallback, ['NETSCALER_NITRO_PROTOCOL']), default='http' ), validate_certs=dict( default=True, type='bool' ), nitro_auth_token=dict( type='str', no_log=True ), resource=dict(type='str'), name=dict(type='str'), attributes=dict(type='dict'), args=dict(type='dict'), filter=dict(type='dict'), operation=dict( type='str', required=True, choices=[ 'add', 'update', 'get', 'get_by_args', 'get_filtered', 'get_all', 'delete', 'delete_by_args', 'count', 'mas_login', # Actions 'save_config', # Generic action handler 'action', ] ), expected_nitro_errorcode=dict( type='list', default=[0], ), action=dict(type='str'), instance_ip=dict(type='str'), instance_name=dict(type='str'), instance_id=dict(type='str'), ) def __init__(self): self._module = AnsibleModule( argument_spec=self._argument_spec, supports_check_mode=False, ) self._module_result = dict( failed=False, ) # Prepare the http headers according to module arguments self._headers = {} self._headers['Content-Type'] = 'application/json' # Check for conflicting authentication methods have_token = self._module.params['nitro_auth_token'] is not None have_userpass = None not in (self._module.params['nitro_user'], self._module.params['nitro_pass']) login_operation = self._module.params['operation'] == 'mas_login' if have_token and have_userpass: self.fail_module(msg='Cannot define both authentication token and username/password') if have_token: self._headers['Cookie'] = "NITRO_AUTH_TOKEN=%s" % self._module.params['nitro_auth_token'] if have_userpass and not login_operation: self._headers['X-NITRO-USER'] = self._module.params['nitro_user'] self._headers['X-NITRO-PASS'] = self._module.params['nitro_pass'] # Do header manipulation when doing a MAS proxy call if self._module.params['instance_ip'] is not None: self._headers['_MPS_API_PROXY_MANAGED_INSTANCE_IP'] = self._module.params['instance_ip'] elif self._module.params['instance_name'] is not None: self._headers['_MPS_API_PROXY_MANAGED_INSTANCE_NAME'] = self._module.params['instance_name'] elif self._module.params['instance_id'] is not None: self._headers['_MPS_API_PROXY_MANAGED_INSTANCE_ID'] = self._module.params['instance_id'] def edit_response_data(self, r, info, result, success_status): # Search for body in both http body and http data if r is not None: result['http_response_body'] = codecs.decode(r.read(), 'utf-8') elif 'body' in info: result['http_response_body'] = codecs.decode(info['body'], 'utf-8') del info['body'] else: result['http_response_body'] = '' result['http_response_data'] = info # Update the nitro_* parameters according to expected success_status # Use explicit return values from http response or deduce from http status code # Nitro return code in http data result['nitro_errorcode'] = None result['nitro_message'] = None result['nitro_severity'] = None if result['http_response_body'] != '': try: data = self._module.from_json(result['http_response_body']) except ValueError: data = {} result['nitro_errorcode'] = data.get('errorcode') result['nitro_message'] = data.get('message') result['nitro_severity'] = data.get('severity') # If we do not have the nitro errorcode from body deduce it from the http status if result['nitro_errorcode'] is None: # HTTP status failed if result['http_response_data'].get('status') != success_status: result['nitro_errorcode'] = -1 result['nitro_message'] = result['http_response_data'].get('msg', 'HTTP status %s' % result['http_response_data']['status']) result['nitro_severity'] = 'ERROR' # HTTP status succeeded else: result['nitro_errorcode'] = 0 result['nitro_message'] = 'Success' result['nitro_severity'] = 'NONE' def handle_get_return_object(self, result): result['nitro_object'] = [] if result['nitro_errorcode'] == 0: if result['http_response_body'] != '': data = self._module.from_json(result['http_response_body']) if self._module.params['resource'] in data: result['nitro_object'] = data[self._module.params['resource']] else: del result['nitro_object'] def fail_module(self, msg, **kwargs): self._module_result['failed'] = True self._module_result['changed'] = False self._module_result.update(kwargs) self._module_result['msg'] = msg self._module.fail_json(**self._module_result) def main(self): if self._module.params['operation'] == 'add': result = self.add() if self._module.params['operation'] == 'update': result = self.update() if self._module.params['operation'] == 'delete': result = self.delete() if self._module.params['operation'] == 'delete_by_args': result = self.delete_by_args() if self._module.params['operation'] == 'get': result = self.get() if self._module.params['operation'] == 'get_by_args': result = self.get_by_args() if self._module.params['operation'] == 'get_filtered': result = self.get_filtered() if self._module.params['operation'] == 'get_all': result = self.get_all() if self._module.params['operation'] == 'count': result = self.count() if self._module.params['operation'] == 'mas_login': result = self.mas_login() if self._module.params['operation'] == 'action': result = self.action() if self._module.params['operation'] == 'save_config': result = self.save_config() if result['nitro_errorcode'] not in self._module.params['expected_nitro_errorcode']: self.fail_module(msg='NITRO Failure', **result) self._module_result.update(result) self._module.exit_json(**self._module_result) def exit_module(self): self._module.exit_json() def add(self): # Check if required attributes are present if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['attributes'] is None: self.fail_module(msg='NITRO resource attributes are undefined.') url = '%s://%s/nitro/v1/config/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], ) data = self._module.jsonify({self._module.params['resource']: self._module.params['attributes']}) r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', ) result = {} self.edit_response_data(r, info, result, success_status=201) if result['nitro_errorcode'] == 0: self._module_result['changed'] = True else: self._module_result['changed'] = False return result def update(self): # Check if required attributes are arguments present if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['name'] is None: self.fail_module(msg='NITRO resource name is undefined.') if self._module.params['attributes'] is None: self.fail_module(msg='NITRO resource attributes are undefined.') url = '%s://%s/nitro/v1/config/%s/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], self._module.params['name'], ) data = self._module.jsonify({self._module.params['resource']: self._module.params['attributes']}) r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='PUT', ) result = {} self.edit_response_data(r, info, result, success_status=200) if result['nitro_errorcode'] == 0: self._module_result['changed'] = True else: self._module_result['changed'] = False return result def get(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['name'] is None: self.fail_module(msg='NITRO resource name is undefined.') url = '%s://%s/nitro/v1/config/%s/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], self._module.params['name'], ) r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', ) result = {} self.edit_response_data(r, info, result, success_status=200) self.handle_get_return_object(result) self._module_result['changed'] = False return result def get_by_args(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['args'] is None: self.fail_module(msg='NITRO args is undefined.') url = '%s://%s/nitro/v1/config/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], ) args_dict = self._module.params['args'] args = ','.join(['%s:%s' % (k, args_dict[k]) for k in args_dict]) args = 'args=' + args url = '?'.join([url, args]) r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', ) result = {} self.edit_response_data(r, info, result, success_status=200) self.handle_get_return_object(result) self._module_result['changed'] = False return result def get_filtered(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['filter'] is None: self.fail_module(msg='NITRO filter is undefined.') keys = list(self._module.params['filter'].keys()) filter_key = keys[0] filter_value = self._module.params['filter'][filter_key] filter_str = '%s:%s' % (filter_key, filter_value) url = '%s://%s/nitro/v1/config/%s?filter=%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], filter_str, ) r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', ) result = {} self.edit_response_data(r, info, result, success_status=200) self.handle_get_return_object(result) self._module_result['changed'] = False return result def get_all(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') url = '%s://%s/nitro/v1/config/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], ) print('headers %s' % self._headers) r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', ) result = {} self.edit_response_data(r, info, result, success_status=200) self.handle_get_return_object(result) self._module_result['changed'] = False return result def delete(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['name'] is None: self.fail_module(msg='NITRO resource is undefined.') # Deletion by name takes precedence over deletion by attributes url = '%s://%s/nitro/v1/config/%s/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], self._module.params['name'], ) r, info = fetch_url( self._module, url=url, headers=self._headers, method='DELETE', ) result = {} self.edit_response_data(r, info, result, success_status=200) if result['nitro_errorcode'] == 0: self._module_result['changed'] = True else: self._module_result['changed'] = False return result def delete_by_args(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['args'] is None: self.fail_module(msg='NITRO args is undefined.') url = '%s://%s/nitro/v1/config/%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], ) args_dict = self._module.params['args'] args = ','.join(['%s:%s' % (k, args_dict[k]) for k in args_dict]) args = 'args=' + args url = '?'.join([url, args]) r, info = fetch_url( self._module, url=url, headers=self._headers, method='DELETE', ) result = {} self.edit_response_data(r, info, result, success_status=200) if result['nitro_errorcode'] == 0: self._module_result['changed'] = True else: self._module_result['changed'] = False return result def count(self): if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') url = '%s://%s/nitro/v1/config/%s?count=yes' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], ) r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', ) result = {} self.edit_response_data(r, info, result) if result['http_response_body'] != '': data = self._module.from_json(result['http_response_body']) result['nitro_errorcode'] = data['errorcode'] result['nitro_message'] = data['message'] result['nitro_severity'] = data['severity'] if self._module.params['resource'] in data: result['nitro_count'] = data[self._module.params['resource']][0]['__count'] self._module_result['changed'] = False return result def action(self): # Check if required attributes are present if self._module.params['resource'] is None: self.fail_module(msg='NITRO resource is undefined.') if self._module.params['attributes'] is None: self.fail_module(msg='NITRO resource attributes are undefined.') if self._module.params['action'] is None: self.fail_module(msg='NITRO action is undefined.') url = '%s://%s/nitro/v1/config/%s?action=%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], self._module.params['action'], ) data = self._module.jsonify({self._module.params['resource']: self._module.params['attributes']}) r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', ) result = {} self.edit_response_data(r, info, result, success_status=200) if result['nitro_errorcode'] == 0: self._module_result['changed'] = True else: self._module_result['changed'] = False return result def mas_login(self): url = '%s://%s/nitro/v1/config/login' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], ) login_credentials = { 'login': { 'username': self._module.params['nitro_user'], 'password': self._module.params['nitro_pass'], } } data = 'object=\n%s' % self._module.jsonify(login_credentials) r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', ) print(r, info) result = {} self.edit_response_data(r, info, result, success_status=200) if result['nitro_errorcode'] == 0: body_data = self._module.from_json(result['http_response_body']) result['nitro_auth_token'] = body_data['login'][0]['sessionid'] self._module_result['changed'] = False return result def save_config(self): url = '%s://%s/nitro/v1/config/nsconfig?action=save' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], ) data = self._module.jsonify( { 'nsconfig': {}, } ) r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', ) result = {} self.edit_response_data(r, info, result, success_status=200) self._module_result['changed'] = False return result
def main(): backup_spec = dict(filename=dict(), dir_path=dict(type='path')) argument_spec = dict(lines=dict(aliases=['commands'], type='list'), parents=dict(type='list'), src=dict(type='path'), before=dict(type='list'), after=dict(type='list'), match=dict( default='line', choices=['line', 'strict', 'exact', 'none']), replace=dict(default='line', choices=['line', 'block']), update=dict(choices=['merge', 'check'], default='merge'), save=dict(type='bool', default=False), config=dict(), backup=dict(type='bool', default=False), backup_options=dict(type='dict', options=backup_spec)) argument_spec.update(dellos6_argument_spec) mutually_exclusive = [('lines', 'src'), ('parents', 'src')] module = AnsibleModule(argument_spec=argument_spec, mutually_exclusive=mutually_exclusive, supports_check_mode=True) parents = module.params['parents'] or list() match = module.params['match'] replace = module.params['replace'] warnings = list() check_args(module, warnings) result = dict(changed=False, saved=False, warnings=warnings) candidate = get_candidate(module) if module.params['backup']: if not module.check_mode: result['__backup__'] = get_config(module) commands = list() if any((module.params['lines'], module.params['src'])): if match != 'none': config = get_running_config(module) config = Dellos6NetworkConfig(contents=config, indent=0) if parents: config = get_sublevel_config(config, module) configobjs = candidate.difference(config, match=match, replace=replace) else: configobjs = candidate.items if configobjs: commands = dumps(configobjs, 'commands') if ((isinstance(module.params['lines'], list)) and (isinstance(module.params['lines'][0], dict)) and set(['prompt', 'answer']).issubset( module.params['lines'][0])): cmd = { 'command': commands, 'prompt': module.params['lines'][0]['prompt'], 'answer': module.params['lines'][0]['answer'] } commands = [module.jsonify(cmd)] else: commands = commands.split('\n') if module.params['before']: commands[:0] = module.params['before'] if module.params['after']: commands.extend(module.params['after']) if not module.check_mode and module.params['update'] == 'merge': load_config(module, commands) result['changed'] = True result['commands'] = commands result['updates'] = commands if module.params['save']: result['changed'] = True if not module.check_mode: cmd = { 'command': 'copy running-config startup-config', 'prompt': r'\(y/n\)\s?$', 'answer': 'y' } run_commands(module, [cmd]) result['saved'] = True else: module.warn('Skipping command `copy running-config startup-config`' 'due to check_mode. Configuration not copied to ' 'non-volatile storage') module.exit_json(**result)