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=True, 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)
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)
def main(): 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) ) 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': 'yes'} 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)
def main(): argument_spec = dict( scheme=dict(choices=["http", "https"], default="http"), host=dict(default="localhost"), port=dict(default="5984"), user=dict(default="admin"), password=dict(default="password", no_log=True), database=dict(), get_db_info=dict(type=bool), get_db_explain=dict(type=bool), get_db_security=dict(type=bool), get_db_shards=dict(type=bool), ) module = AnsibleModule(argument_spec=argument_spec, required_if=( ("get_db_info", True, ["database"]), ("get_db_explain", True, ["database"]), ("get_db_security", True, ["database"]), ("get_db_shards", True, ["database"]), ), mutually_exclusive=[( "get_db_info", "get_db_explain", "get_db_security", "get_db_shards", )]) _url = module.params["scheme"] + "://" + module.params["host"] + ":" \ + module.params["port"] + "/" _auth = (module.params["user"], module.params["password"]) headers = {"Content-Type": "application/json"} if module.params["get_db_info"]: r = requests.get(_url + module.params["database"], auth=_auth, headers=headers) if r.status_code == 200: module.exit_json(database=r.json()) else: module.fail_json(msg=r.json()) elif module.params["get_db_explain"]: r = requests.post(_url + module.params["database"] + "/_explain", auth=_auth, data=module.jsonify({"selector": {}}), headers=headers) if r.status_code == 200: module.exit_json(explain=r.json()) else: module.fail_json(msg=r.json()) elif module.params["get_db_security"]: r = requests.get(_url + module.params["database"] + "/_security", auth=_auth, headers=headers) if r.status_code == 200: module.exit_json(security=r.json()) else: module.fail_json(msg=r.json()) elif module.params["get_db_shards"]: r = requests.get(_url + module.params["database"] + "/_shards", auth=_auth, headers=headers) if r.status_code == 200: module.exit_json(shards=r.json()["shards"]) else: module.fail_json(msg=r.json()) else: module.fail_json(msg="unknown parameters are passed")
def main(): module = AnsibleModule( argument_spec=dict( token=dict(required=False, no_log=True), project_id=dict(required=False, no_log=True), project_key=dict(required=False, no_log=True), environment=dict(required=True), user=dict(required=False), repo=dict(required=False), revision=dict(required=False), url=dict(required=False, default='https://api.airbrake.io/api/v4/projects/'), validate_certs=dict(default='yes', type='bool'), ), supports_check_mode=True, required_together=[('project_id', 'project_key')], mutually_exclusive=[('project_id', 'token')], ) # Build list of params params = {} # If we're in check mode, just exit pretending like we succeeded if module.check_mode: module.exit_json(changed=True) if module.params["token"]: if module.params["environment"]: params["deploy[rails_env]"] = module.params["environment"] if module.params["user"]: params["deploy[local_username]"] = module.params["user"] if module.params["repo"]: params["deploy[scm_repository]"] = module.params["repo"] if module.params["revision"]: params["deploy[scm_revision]"] = module.params["revision"] module.deprecate( "Parameter 'token' is deprecated in 2.10. Please remove it and use 'project_id' and 'project_key' instead", version='2.14') params["api_key"] = module.params["token"] # Allow sending to Airbrake compliant v2 APIs if module.params["url"] == 'https://api.airbrake.io/api/v4/projects/': url = 'https://api.airbrake.io/deploys.txt' else: url = module.params["url"] # Send the data to airbrake data = urlencode(params) response, info = fetch_url(module, url, data=data) if module.params["project_id"] and module.params["project_key"]: if module.params["environment"]: params["environment"] = module.params["environment"] if module.params["user"]: params["username"] = module.params["user"] if module.params["repo"]: params["repository"] = module.params["repo"] if module.params["revision"]: params["revision"] = module.params["revision"] # Build deploy url url = module.params.get('url') + module.params[ "project_id"] + '/deploys?key=' + module.params["project_key"] json_body = module.jsonify(params) # Build header headers = {'Content-Type': 'application/json'} # Notify Airbrake of deploy response, info = fetch_url(module, url, data=json_body, headers=headers, method='POST') if info['status'] == 200 or info['status'] == 201: module.exit_json(changed=True) else: module.fail_json(msg="HTTP result code: %d connecting to %s" % (info['status'], url))
def main(): module_args = dict( url=dict(type='str', required=True), token=dict(type='str', required=True, no_log=True), msg=dict(type='str', required=True), priority=dict(type='int', default=2, required=False), title=dict(type='str', default='Ansible Notification', required=False), ) result = dict( changed=False ) module = AnsibleModule( argument_spec=module_args, supports_check_mode=True ) token = module.params['token'] msg = module.params['msg'] title = module.params['title'] url = module.params['url'] priority = module.params['priority'] # If URL has no trailing slash add it if url[len(url) - 1] != "/": url += "/" full_url = "%smessage?token=%s" % (url, token) # In check mode, exit before actually sending the message # Check mode will only tell you if a required option is missing and won't # check if Gotify is available or if the token is valid. if module.check_mode: module.exit_json(changed=False) payload = { "message": msg, "priority": priority, "title": title } result = module.params payload = module.jsonify(payload) headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', } response, info = fetch_url(module=module, url=full_url, headers=headers, method='POST', data=payload) result['http result'] = info['status'] if info['status'] != 200: result['error'] = info['body'] module.fail_json(**result) result['changed'] = True module.exit_json(**result)
def main(): module = AnsibleModule( argument_spec=dict( domain=dict(type='str'), token=dict(type='str', required=True, no_log=True), msg=dict(type='str'), channel=dict(type='str'), thread_id=dict(type='str'), username=dict(type='str', default='Ansible'), icon_url=dict(type='str', default='https://www.ansible.com/favicon.ico'), icon_emoji=dict(type='str'), link_names=dict(type='int', default=1, choices=[0, 1]), parse=dict(type='str', choices=['none', 'full']), validate_certs=dict(default=True, type='bool'), color=dict(type='str', default='normal'), attachments=dict(type='list', elements='dict'), blocks=dict(type='list', elements='dict'), message_id=dict(type='str'), ), supports_check_mode=True, ) domain = module.params['domain'] token = module.params['token'] text = module.params['msg'] channel = module.params['channel'] thread_id = module.params['thread_id'] username = module.params['username'] icon_url = module.params['icon_url'] icon_emoji = module.params['icon_emoji'] link_names = module.params['link_names'] parse = module.params['parse'] color = module.params['color'] attachments = module.params['attachments'] blocks = module.params['blocks'] message_id = module.params['message_id'] color_choices = ['normal', 'good', 'warning', 'danger'] if color not in color_choices and not is_valid_hex_color(color): module.fail_json(msg="Color value specified should be either one of %r " "or any valid hex value with length 3 or 6." % color_choices) changed = True # if updating an existing message, we can check if there's anything to update if message_id is not None: changed = False msg = get_slack_message(module, token, channel, message_id) for key in ('icon_url', 'icon_emoji', 'link_names', 'color', 'attachments', 'blocks'): if msg.get(key) != module.params.get(key): changed = True break # if check mode is active, we shouldn't do anything regardless. # if changed=False, we don't need to do anything, so don't do it. if module.check_mode or not changed: module.exit_json(changed=changed, ts=msg['ts'], channel=msg['channel']) elif module.check_mode: module.exit_json(changed=changed) payload = build_payload_for_slack(text, channel, thread_id, username, icon_url, icon_emoji, link_names, parse, color, attachments, blocks, message_id) slack_response = do_notify_slack(module, domain, token, payload) if 'ok' in slack_response: # Evaluate WebAPI response if slack_response['ok']: # return payload as a string for backwards compatibility payload_json = module.jsonify(payload) module.exit_json(changed=changed, ts=slack_response['ts'], channel=slack_response['channel'], api=slack_response, payload=payload_json) else: module.fail_json(msg="Slack API error", error=slack_response['error']) else: # Exit with plain OK from WebHook, since we don't have more information # If we get 200 from webhook, the only answer is OK module.exit_json(msg="OK")
def main(): # required_together this means that these two parameters needs to be # specified together. If source_control_repository is specified # then source_control_revision has to be specified as-well required_together = [['source_control_repository', 'source_control_revision']] # we declare the parameters of our Module here # bugsnag needs api_key, api_version and release_stage always # as a result will set the required value to True. We won't be logging the API_KEY # for security reason. the rest are optional arguments = dict( api_key=dict(required=True, no_log=True), app_version=dict(required=True), release_stage=dict(required=True), builder_name=dict(required=False), source_control_repository=dict(required=False), source_control_revision=dict(required=False) ) # we pass the parameters to AnsibleModule class # we declare that this module supports check_mode as-well module = AnsibleModule( argument_spec=arguments, required_together=required_together, supports_check_mode=True ) # Bugsnag requires raw-json data # this is why we will create a dict called "params" params = { 'apiKey': module.params['api_key'], 'appVersion': module.params['app_version'] } headers = {'Content-Type': 'application/json'} if module.params['builder_name']: params['builderName'] = module.params['builder_name'] if module.params['release_stage']: params['releaseStage'] = module.params['release_stage'] if module.params['source_control_repository'] and module.params['source_control_revision']: params['sourceControl'] = {} if module.params['source_control_repository']: params['sourceControl']['repository'] = module.params['source_control_repository'] if module.params['source_control_revision']: params['sourceControl']['revision'] = module.params['source_control_revision'] # Bugsnag API URL url = 'https://build.bugsnag.com/' if module.check_mode: module.exit_json(changed=True) # We will be using Ansible fetch_url method to call API requests. We don't want to # use Python requests as its best to use the utils provided by Ansible. response, info = fetch_url(module, url, module.jsonify(params), headers=headers) # we receive status code 200 we will return it TRUE if info['status'] == 200: module.exit_json(changed=True) else: module.fail_json(msg="unable to call API")
class VaultCloudTokenModule(): argument_spec = dict( vault_addr=dict(type='str', required=True), role_id=dict(type='str', required=True), secret_id=dict(type='str', no_log=True, required=True), secret_name=dict(type='str', required=True), project_name=dict(type='str', required=False), ) module_kwargs = {'supports_check_mode': True} def __init__(self): self.ansible = AnsibleModule(self.argument_spec, **self.module_kwargs) self.params = self.ansible.params self.module_name = self.ansible._name self.exit_json = self.ansible.exit_json self.fail_json = self.ansible.fail_json if not HAS_OPENSTACK: self.fail_json(msg=missing_required_lib('openstacksdk')) def get_vault_token(self, vault_url, role_id, secret_id): url = f"{vault_url}/v1/auth/approle/login" data = self.ansible.jsonify(dict(role_id=role_id, secret_id=secret_id)) response, info = fetch_url(module=self.ansible, url=url, method="POST", data=data) status = info['status'] if status >= 400 and status != 404: self.fail_json(msg='Failed to login to Vault', status_code=status) content = "" if response: content = response.read() try: body = json.loads(content) token = body['auth']['client_token'] return token except Exception as ex: self.fail_json(msg='Failed to process vault response', error=str(ex)) def __call__(self): vault_addr = self.params['vault_addr'] role_id = self.params['role_id'] secret_id = self.params['secret_id'] secret_name = self.params['secret_name'] project_name = self.params['project_name'] result_config = dict() vault_token = self.get_vault_token(vault_addr, role_id, secret_id) response, info = fetch_url( module=self.ansible, url=f"{vault_addr}/v1/secret/data/{secret_name}", method="GET", headers={'X-Vault-Token': vault_token}) status = info['status'] if status >= 400: self.fail_json(msg='Failed to fetch data from vault', status_code=status, info=info) content = "" if response: content = response.read() try: data = json.loads(content) secret = data['data']['data'] cloud_config = dict(auth=dict()) auth_attrs = [ 'auth_url', 'user_domain_name', 'username', 'password', 'project_name', 'project_id' ] for k, v in secret.items(): if k in auth_attrs: cloud_config['auth'][k] = v else: cloud_config[k] = v if project_name: cloud_config['auth'].pop('project_name', None) cloud_config['auth'].pop('project_id', None) cloud_config['auth']['project_name'] = project_name try: conn = openstack.connect(**cloud_config) token = conn.auth_token new_auth = dict() if 'profile' in secret: result_config['profile'] = secret['profile'] result_config['auth_type'] = 'token' new_auth['auth_url'] = conn.config._auth.auth_url new_auth['project_name'] = cloud_config['auth']['project_name'] new_auth['token'] = token result_config['auth'] = new_auth except openstack.exceptions.SDKException as e: self.fail_json(msg='Failure connecting to the cloud', error=str(e)) except Exception as ex: self.fail_json(msg="Failed to process vault response", error=str(ex)) self.exit_json(changed=False, token=token, cloud_config=result_config)
def main(): module = AnsibleModule(argument_spec=dict( integration_key=dict(required=True, type='str', no_log=True), summary=dict(required=True, type='str'), source=dict(required=False, default='Ansible', type='str'), user=dict(required=False, type='str'), repo=dict(required=False, type='str'), revision=dict(required=False, type='str'), environment=dict(required=False, type='str'), link_url=dict(required=False, type='str'), link_text=dict(required=False, type='str'), url=dict(required=False, default='https://events.pagerduty.com/v2/change/enqueue', type='str'), validate_certs=dict(default=True, type='bool')), supports_check_mode=True) # API documented at https://developer.pagerduty.com/docs/events-api-v2/send-change-events/ url = module.params['url'] headers = {'Content-Type': 'application/json'} if module.check_mode: _response, info = fetch_url(module, url, headers=headers, method='POST') if info['status'] == 400: module.exit_json(changed=True) else: module.fail_json( msg= 'Checking the PagerDuty change event API returned an unexpected response: %d' % (info['status'])) custom_details = {} if module.params['user']: custom_details['user'] = module.params['user'] if module.params['repo']: custom_details['repo'] = module.params['repo'] if module.params['revision']: custom_details['revision'] = module.params['revision'] if module.params['environment']: custom_details['environment'] = module.params['environment'] now = datetime.utcnow() timestamp = now.strftime("%Y-%m-%dT%H:%M:%S.%fZ") payload = { 'summary': module.params['summary'], 'source': module.params['source'], 'timestamp': timestamp, 'custom_details': custom_details } event = { 'routing_key': module.params['integration_key'], 'payload': payload } if module.params['link_url']: link = {'href': module.params['link_url']} if module.params['link_text']: link['text'] = module.params['link_text'] event['links'] = [link] _response, info = fetch_url(module, url, data=module.jsonify(event), headers=headers, method='POST') if info['status'] == 202: module.exit_json(changed=True) else: module.fail_json(msg='Creating PagerDuty change event failed with %d' % (info['status']))
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
class VaultCloudConfigModule(): argument_spec = dict(vault_addr=dict(type='str', required=True), vault_role_id=dict(type='str'), vault_secret_id=dict(type='str', no_log=True), vault_token=dict(type='str', no_log=True), cloud_secret_path=dict(type='str'), project_name=dict(type='str'), mode=dict(type='str', defualt='config', chocies=['config', 'token'])) module_kwargs = { 'supports_check_mode': True, 'required_together': [('vault_role_id', 'vault_secret_id')], 'required_one_of': [('vault_token', 'vault_role_id')] } def __init__(self): self.ansible = AnsibleModule(self.argument_spec, **self.module_kwargs) self.params = self.ansible.params self.module_name = self.ansible._name self.exit_json = self.ansible.exit_json self.fail_json = self.ansible.fail_json self.vault_addr = None self.token = None def _fetch(self, url, method, **kwargs): response, info = fetch_url(module=self.ansible, url=url, method=method, **kwargs) status = info['status'] if status >= 400 and status != 404: self.fail_json(msg=f'Failed to fetch {url}', status_code=status) content = "" if response: content = response.read() return (content, status) def _get_secret_data(self, secret_path): response, info = self._fetch( f"{self.vault_addr}/v1/secret/data/{secret_path}", "GET", headers={'X-Vault-Token': self.token}) return json.loads(response)['data']['data'] def get_vault_token(self, role_id, secret_id): url = f"{self.vault_addr}/v1/auth/approle/login" data = self.ansible.jsonify(dict(role_id=role_id, secret_id=secret_id)) response, into = self._fetch(url, "POST", data=data) try: body = json.loads(response) token = body['auth']['client_token'] return token except Exception as ex: self.fail_json(msg='Failed to process vault response', error=str(ex)) def __call__(self): self.vault_addr = self.params['vault_addr'] cloud_secret_path = self.params['cloud_secret_path'] project_name = self.params['project_name'] result = {} if self.params['vault_role_id'] and self.params['vault_secret_id']: self.token = self.get_vault_token(self.params['vault_role_id'], self.params['vault_secret_id']) elif self.params['vault_token']: self.token = self.params['vault_token'] cloud_data = self._get_secret_data(cloud_secret_path) user_secret_name = cloud_data.pop('user_secret_name', '') if user_secret_name: # user_secret_name is found in cloud_data. Resolve it's value cloud_data.update(self._get_secret_data(user_secret_name)) try: cloud_config = dict(auth=dict()) # this attrs go under 'auth' auth_attrs = [ 'auth_url', 'user_domain_name', 'user_domain_id', 'username', 'user_id', 'password', 'project_name', 'project_id', 'project_domain_id', 'project_domain_name', 'domain_id', 'domain_name' ] for k, v in cloud_data.items(): if k in auth_attrs: cloud_config['auth'][k] = v else: cloud_config[k] = v if project_name: cloud_config['auth'].pop('project_name', None) cloud_config['auth'].pop('project_id', None) cloud_config['auth']['project_name'] = project_name result = cloud_config if self.params['mode'] == 'token': if not HAS_OPENSTACK: self.fail_json(msg=missing_required_lib('openstacksdk')) try: conn = openstack.connect(**cloud_config) token = conn.auth_token new_auth = dict() result['auth_type'] = 'token' new_auth['auth_url'] = conn.config._auth.auth_url new_auth['project_name'] = \ cloud_config['auth']['project_name'] new_auth['token'] = token result['auth'] = new_auth except openstack.exceptions.SDKException as e: self.fail_json(msg='Failure connecting to the cloud', error=str(e)) except Exception as ex: self.fail_json(msg="Failed to process vault response", error=str(ex)) self.exit_json(changed=False, token=token, config=result)
class VaultReadModule(): argument_spec = dict( vault_addr=dict(type='str', required=True), vault_token=dict(type='str', required=False, no_log=True), vault_role_id=dict(type='str', required=False), vault_secret_id=dict(type='str', no_log=True, required=False), secret_path=dict(type='str', required=True), ) module_kwargs = { 'supports_check_mode': True, 'required_together': [('vault_role_id', 'vault_secret_id')], 'required_one_of': [('vault_token', 'vault_role_id')] } def __init__(self): self.ansible = AnsibleModule( self.argument_spec, **self.module_kwargs) self.params = self.ansible.params self.module_name = self.ansible._name self.exit_json = self.ansible.exit_json self.fail_json = self.ansible.fail_json self.vault_addr = None self.token = None def _fetch(self, url, method, **kwargs): response, info = fetch_url( module=self.ansible, url=url, method=method, **kwargs ) status = info['status'] if status >= 400 and status != 404: self.fail_json( msg=f'Failed to fetch {url}', status_code=status ) content = "" if response: content = response.read() return (content, status) def _get_secret_data(self, secret_name): response, info = self._fetch( f"{self.vault_addr}/v1/secret/data/{secret_name}", "GET", headers={ 'X-Vault-Token': self.token } ) return json.loads(response)['data']['data'] def get_vault_token(self, role_id, secret_id): url = f"{self.vault_addr}/v1/auth/approle/login" data = self.ansible.jsonify(dict( role_id=role_id, secret_id=secret_id )) response, into = self._fetch( url, "POST", data=data ) try: body = json.loads(response) token = body['auth']['client_token'] return token except Exception as ex: self.fail_json( msg='Failed to process vault response', error=str(ex) ) def __call__(self): self.vault_addr = self.params['vault_addr'] secret_path = self.params['secret_path'] result = {} if self.params['vault_role_id'] and self.params['vault_secret_id']: self.token = self.get_vault_token( self.params['vault_role_id'], self.params['vault_secret_id']) elif self.params['vault_token']: self.token = self.params['vault_token'] result = self._get_secret_data(secret_path) self.exit_json( changed=False, secret=result )
class VaultReadModule(): argument_spec = dict(vault_addr=dict(type='str', required=True), role_id=dict(type='str', required=True), secret_id=dict(type='str', no_log=True, required=True), secret_name=dict(type='str', required=True), mode=dict(type='str', choices=['cloud_config', 'plain'], default='plain')) module_kwargs = {'supports_check_mode': True} def __init__(self): self.ansible = AnsibleModule(self.argument_spec, **self.module_kwargs) self.params = self.ansible.params self.module_name = self.ansible._name self.exit_json = self.ansible.exit_json self.fail_json = self.ansible.fail_json def get_vault_token(self, vault_url, role_id, secret_id): url = f"{vault_url}/v1/auth/approle/login" data = self.ansible.jsonify(dict(role_id=role_id, secret_id=secret_id)) response, info = fetch_url(module=self.ansible, url=url, method="POST", data=data) status = info['status'] if status >= 400 and status != 404: self.fail_json(msg='Failed to login to Vault', status_code=status) content = "" if response: content = response.read() try: body = json.loads(content) token = body['auth']['client_token'] return token except Exception as ex: self.fail_json(msg='Failed to process vault response', error=str(ex)) def __call__(self): vault_addr = self.params['vault_addr'] role_id = self.params['role_id'] secret_id = self.params['secret_id'] secret_name = self.params['secret_name'] mode = self.params['mode'] result = {} vault_token = self.get_vault_token(vault_addr, role_id, secret_id) response, info = fetch_url( module=self.ansible, url=f"{vault_addr}/v1/secret/data/{secret_name}", method="GET", headers={'X-Vault-Token': vault_token}) status = info['status'] if status >= 400: self.fail_json(msg='Failed to fetch data from vault', status_code=status, info=info) content = "" if response: content = response.read() try: data = json.loads(content) secret = data['data']['data'] cloud_config = dict(auth=dict()) if mode == 'plain': result = secret elif mode == 'cloud_config': auth_attrs = [ 'auth_url', 'user_domain_name', 'username', 'password', 'project_name', 'project_id' ] for k, v in secret.items(): if k in auth_attrs: cloud_config['auth'][k] = v else: cloud_config[k] = v result = cloud_config except Exception as ex: self.fail_json(msg="Failed to process vault response", error=str(ex)) self.exit_json(changed=False, secret=result)
class NitroAPICaller(object): _argument_spec = dict( nsip=dict( fallback=(env_fallback, ['NETSCALER_NSIP']), aliases=['mas_ip'], ), nitro_user=dict( fallback=(env_fallback, ['NETSCALER_NITRO_USER']), aliases=['mas_user'], ), nitro_pass=dict(fallback=(env_fallback, ['NETSCALER_NITRO_PASS']), aliases=['mas_pass'], no_log=True), nitro_protocol=dict(type='str', choices=['http', 'https'], fallback=(env_fallback, ['NETSCALER_NITRO_PROTOCOL']), default='https'), validate_certs=dict(default=True, type='bool'), nitro_auth_token=dict(type='str', aliases=['mas_auth_token'], 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', 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', elements='int', default=[0], ), action=dict(type='str'), mas_proxy_call=dict(default=False, type='bool'), instance_ip=dict(type='str'), instance_name=dict(type='str'), instance_id=dict(type='str'), timeout=dict(type='int', default=45), idempotent=dict(type='bool', default=False), ) 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.get( 'mas_proxy_call') is not None and self._module.params.get( '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_result['headers'] = self._headers 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.') # Handle idempotent flag idempotent_querystring = '' idempotent_flag = self._module.params.get('idempotent') if idempotent_flag is not None and idempotent_flag: idempotent_querystring = '?idempotent=yes' url = '%s://%s/nitro/v1/config/%s%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], idempotent_querystring, ) data = self._module.jsonify({ self._module.params['resource']: self._module.params['attributes'] }) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', timeout=timeout, ) 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.') # Handle idempotent flag idempotent_querystring = '' idempotent_flag = self._module.params.get('idempotent') if idempotent_flag is not None and idempotent_flag: idempotent_querystring = '?idempotent=yes' url = '%s://%s/nitro/v1/config/%s/%s%s' % ( self._module.params['nitro_protocol'], self._module.params['nsip'], self._module.params['resource'], self._module.params['name'], idempotent_querystring, ) data = self._module.jsonify({ self._module.params['resource']: self._module.params['attributes'] }) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='PUT', timeout=timeout, ) 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'], ) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', timeout=timeout, ) 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]) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', timeout=timeout, ) 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, ) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', timeout=timeout, ) 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'], ) self._module.debug('headers %s' % self._headers) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', timeout=timeout, ) 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'], ) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='DELETE', timeout=timeout, ) 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]) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='DELETE', timeout=timeout, ) 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'], ) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, method='GET', timeout=timeout, ) 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'] }) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', timeout=timeout, ) 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) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', timeout=timeout, ) self._module.debug(r) self._module.debug(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': {}, }) timeout = self._module.params['timeout'] r, info = fetch_url( self._module, url=url, headers=self._headers, data=data, method='POST', timeout=timeout, ) result = {} self.edit_response_data(r, info, result, success_status=200) self._module_result['changed'] = False return result
def main(): 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) ) argument_spec.update(dellos10_argument_spec) mutually_exclusive = [('lines', '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) if module.params['backup']: if not module.check_mode: result['__backup__'] = get_config(module) commands = list() candidate = get_candidate(module) if any((module.params['lines'], module.params['src'])): if match != 'none': config = get_running_config(module) if parents: contents = get_sublevel_config(config, module) config = NetworkConfig(contents=contents, indent=1) else: config = NetworkConfig(contents=config, indent=1) 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 (['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 = {r'command': 'copy running-config startup-config', r'prompt': r'\[confirm yes/no\]:\s?$', 'answer': 'yes'} 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)
def main(): module = AnsibleModule( argument_spec=dict( project_id=dict(required=True, no_log=True, type='str'), project_key=dict(required=True, no_log=True, type='str'), environment=dict(required=True, type='str'), user=dict(required=False, type='str'), repo=dict(required=False, type='str'), revision=dict(required=False, type='str'), version=dict(required=False, type='str'), url=dict(required=False, default='https://api.airbrake.io/api/v4/projects/', type='str'), validate_certs=dict(default=True, type='bool'), ), supports_check_mode=True, ) # Build list of params params = {} # If we're in check mode, just exit pretending like we succeeded if module.check_mode: module.exit_json(changed=True) # v4 API documented at https://airbrake.io/docs/api/#create-deploy-v4 if module.params["environment"]: params["environment"] = module.params["environment"] if module.params["user"]: params["username"] = module.params["user"] if module.params["repo"]: params["repository"] = module.params["repo"] if module.params["revision"]: params["revision"] = module.params["revision"] if module.params["version"]: params["version"] = module.params["version"] # Build deploy url url = module.params.get('url') + module.params[ "project_id"] + '/deploys?key=' + module.params["project_key"] json_body = module.jsonify(params) # Build header headers = {'Content-Type': 'application/json'} # Notify Airbrake of deploy response, info = fetch_url(module, url, data=json_body, headers=headers, method='POST') if info['status'] == 200 or info['status'] == 201: module.exit_json(changed=True) else: module.fail_json(msg="HTTP result code: %d connecting to %s" % (info['status'], url))
def main(): module = AnsibleModule( argument_spec=dict( token=dict(required=True, no_log=True), app_name=dict(required=False), application_id=dict(required=False), changelog=dict(required=False), description=dict(required=False), revision=dict(required=True), user=dict(required=False), ), required_one_of=[['app_name', 'application_id']], mutually_exclusive=[['app_name', 'application_id']], ) if module.params['app_name']: data = 'filter[name]=' + str(module.params['app_name']) newrelic_api = 'https://api.newrelic.com/v2/applications.json' headers = { 'x-api-key': module.params['token'], 'Content-Type': 'application/x-www-form-urlencoded' } (resp, info) = fetch_url(module, newrelic_api, headers=headers, data=data, method='GET') if info['status'] != 200: module.fail_json( msg="unable to get application list from newrelic: %s" % info['msg']) else: body = json.loads(resp.read()) if body is None: module.fail_json(msg='No Data for applications') else: app_id = body['applications'][0]['id'] if app_id is None: module.fail_json( msg="App not found in NewRelic Registerd Applications List" ) else: app_id = module.params['application_id'] # Send the data to NewRelic url = 'https://api.newrelic.com/v2/applications/' + str( app_id) + '/deployments.json' data = { 'deployment': { 'revision': str(module.params['revision']), 'changelog': str(module.params['changelog']), 'description': str(module.params['description']), 'user': str(module.params['user']), } } headers = { 'x-api-key': module.params['token'], 'Content-Type': 'application/json' } (_, info) = fetch_url(module, url, data=module.jsonify(data), headers=headers, method='POST') if info['status'] == 201: module.exit_json(changed=True) else: module.fail_json(f'unable to update newrelic: {info["msg"]}')