Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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")
Beispiel #5
0
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))
Beispiel #6
0
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)
Beispiel #7
0
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")
Beispiel #9
0
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
Beispiel #16
0
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)
Beispiel #17
0
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))
Beispiel #18
0
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"]}')