def send_event(module,
               service_key,
               event_type,
               desc,
               incident_key=None,
               client=None,
               client_url=None):
    url = "https://events.pagerduty.com/generic/2010-04-15/create_event.json"
    headers = {"Content-type": "application/json"}

    data = {
        "service_key": service_key,
        "event_type": event_type,
        "incident_key": incident_key,
        "description": desc,
        "client": client,
        "client_url": client_url
    }

    response, info = fetch_url(module,
                               url,
                               method='post',
                               headers=headers,
                               data=json.dumps(data))
    if info['status'] != 200:
        module.fail_json(msg="failed to %s. Reason: %s" %
                         (event_type, info['msg']))
    json_out = json.loads(response.read())
    return json_out
def test_fetch_url_connectionerror(open_url_mock, fake_ansible_module):
    open_url_mock.side_effect = ConnectionError('TESTS')
    with pytest.raises(FailJson) as excinfo:
        fetch_url(fake_ansible_module, 'http://ansible.com/')

    assert excinfo.value.kwargs['msg'] == 'TESTS'
    assert 'http://ansible.com/' == excinfo.value.kwargs['url']
    assert excinfo.value.kwargs['status'] == -1

    open_url_mock.side_effect = ValueError('TESTS')
    with pytest.raises(FailJson) as excinfo:
        fetch_url(fake_ansible_module, 'http://ansible.com/')

    assert excinfo.value.kwargs['msg'] == 'TESTS'
    assert 'http://ansible.com/' == excinfo.value.kwargs['url']
    assert excinfo.value.kwargs['status'] == -1
def test_fetch_url(open_url_mock, fake_ansible_module):
    r, info = fetch_url(fake_ansible_module, 'http://ansible.com/')

    dummy, kwargs = open_url_mock.call_args

    open_url_mock.assert_called_once_with('http://ansible.com/',
                                          client_cert=None,
                                          client_key=None,
                                          cookies=kwargs['cookies'],
                                          data=None,
                                          follow_redirects='urllib2',
                                          force=False,
                                          force_basic_auth='',
                                          headers=None,
                                          http_agent='ansible-httpget',
                                          last_mod_time=None,
                                          method=None,
                                          timeout=10,
                                          url_password='',
                                          url_username='',
                                          use_proxy=True,
                                          validate_certs=True,
                                          use_gssapi=False,
                                          unix_socket=None,
                                          ca_path=None)
    def run(self):
        result = {
            'nginx_status_facts': {
                'active_connections': None,
                'accepts': None,
                'handled': None,
                'requests': None,
                'reading': None,
                'writing': None,
                'waiting': None,
                'data': None,
            }
        }
        (response, info) = fetch_url(module=module, url=self.url, force=True, timeout=self.timeout)
        if not response:
            module.fail_json(msg="No valid or no response from url %s within %s seconds (timeout)" % (self.url, self.timeout))

        data = to_text(response.read(), errors='surrogate_or_strict')
        if not data:
            return result

        result['nginx_status_facts']['data'] = data
        expr = r'Active connections: ([0-9]+) \nserver accepts handled requests\n ([0-9]+) ([0-9]+) ([0-9]+) \n' \
            r'Reading: ([0-9]+) Writing: ([0-9]+) Waiting: ([0-9]+)'
        match = re.match(expr, data, re.S)
        if match:
            result['nginx_status_facts']['active_connections'] = int(match.group(1))
            result['nginx_status_facts']['accepts'] = int(match.group(2))
            result['nginx_status_facts']['handled'] = int(match.group(3))
            result['nginx_status_facts']['requests'] = int(match.group(4))
            result['nginx_status_facts']['reading'] = int(match.group(5))
            result['nginx_status_facts']['writing'] = int(match.group(6))
            result['nginx_status_facts']['waiting'] = int(match.group(7))
        return result
Example #5
0
    def send_request(self, commands, output='text'):
        commands = to_list(commands)

        if self._enable:
            commands.insert(0, self._enable)

        body = self._request_builder(commands, output)
        data = self._module.jsonify(body)

        headers = {'Content-Type': 'application/json-rpc'}
        timeout = self._module.params['provider']['timeout']
        use_proxy = self._module.params['provider']['use_proxy']

        response, headers = fetch_url(
            self._module, self._url, data=data, headers=headers,
            method='POST', timeout=timeout, use_proxy=use_proxy
        )

        if headers['status'] != 200:
            self._module.fail_json(**headers)

        try:
            data = response.read()
            response = self._module.from_json(to_text(data, errors='surrogate_then_replace'))
        except ValueError:
            self._module.fail_json(msg='unable to load response from device', data=data)

        if self._enable and 'result' in response:
            response['result'].pop(0)

        return response
    def _post_or_patch(self, api_call, method, data):
        # This helps with tags when we have the full API resource href to update.
        if API_URL not in api_call:
            api_endpoint = API_URL + api_call
        else:
            api_endpoint = api_call

        headers = self._auth_header.copy()
        if data is not None:
            # Sanitize data dictionary
            # Deepcopy: Duplicate the data object for iteration, because
            # iterating an object and changing it at the same time is insecure
            for k, v in deepcopy(data).items():
                if v is None:
                    del data[k]

            data = self._module.jsonify(data)
            headers['Content-type'] = 'application/json'

        resp, info = fetch_url(self._module,
                               api_endpoint,
                               headers=headers,
                               method=method,
                               data=data,
                               timeout=self._module.params['api_timeout'])

        if info['status'] in (200, 201):
            return self._module.from_json(to_text(resp.read(), errors='surrogate_or_strict'))
        elif info['status'] == 204:
            return None
        else:
            self._module.fail_json(msg='Failure while calling the cloudscale.ch API with %s for '
                                       '"%s".' % (method, api_call), fetch_url_info=info)
    def send(self, method, path, data=None, headers=None):
        url = self._url_builder(path)
        data = self.module.jsonify(data)

        resp, info = fetch_url(self.module, url, data=data, headers=self.headers, method=method)

        return Response(resp, info)
Example #8
0
    def login(self):
        ''' Log in to MSO '''

        # Perform login request
        self.url = urljoin(self.baseuri, 'auth/login')
        payload = {
            'username': self.params.get('username'),
            'password': self.params.get('password')
        }
        resp, auth = fetch_url(self.module,
                               self.url,
                               data=json.dumps(payload),
                               method='POST',
                               headers=self.headers,
                               timeout=self.params.get('timeout'),
                               use_proxy=self.params.get('use_proxy'))

        # Handle MSO response
        if auth.get('status') != 201:
            self.response = auth.get('msg')
            self.status = auth.get('status')
            self.fail_json(msg='Authentication failed: {msg}'.format(**auth))

        payload = json.loads(resp.read())

        self.headers['Authorization'] = 'Bearer {token}'.format(**payload)
def send_msg_v1(module,
                token,
                room,
                msg_from,
                msg,
                msg_format='text',
                color='yellow',
                notify=False,
                api=MSG_URI_V1):
    '''sending message to hipchat v1 server'''

    params = {}
    params['room_id'] = room
    params['from'] = msg_from[:15]  # max length is 15
    params['message'] = msg
    params['message_format'] = msg_format
    params['color'] = color
    params['api'] = api
    params['notify'] = int(notify)

    url = api + MSG_URI_V1 + "?auth_token=%s" % (token)
    data = urlencode(params)

    if module.check_mode:
        # In check mode, exit before actually sending the message
        module.exit_json(changed=False)

    response, info = fetch_url(module, url, data=data)
    if info['status'] == 200:
        return response.read()
    else:
        module.fail_json(msg="failed to send message, return status=%s" %
                         str(info['status']))
Example #10
0
def request(url, user, passwd, timeout, data=None, method=None):
    if data:
        data = json.dumps(data)

    # NOTE: fetch_url uses a password manager, which follows the
    # standard request-then-challenge basic-auth semantics. However as
    # JIRA allows some unauthorised operations it doesn't necessarily
    # send the challenge, so the request occurs as the anonymous user,
    # resulting in unexpected results. To work around this we manually
    # inject the basic-auth header up-front to ensure that JIRA treats
    # the requests as authorized for this user.
    auth = to_text(base64.b64encode(to_bytes('{0}:{1}'.format(user, passwd), errors='surrogate_or_strict')))

    response, info = fetch_url(module, url, data=data, method=method, timeout=timeout,
                               headers={'Content-Type': 'application/json',
                                        'Authorization': "Basic %s" % auth})

    if info['status'] not in (200, 201, 204):
        module.fail_json(msg=info['msg'])

    body = response.read()

    if body:
        return json.loads(to_text(body, errors='surrogate_or_strict'))
    else:
        return {}
Example #11
0
    def request_rundeck_api(self, query, data=None, method="GET"):
        resp, info = fetch_url(self.module,
                               "%s/api/%d/%s" %
                               (self.module.params["url"],
                                self.module.params["api_version"], query),
                               data=json.dumps(data),
                               method=method,
                               headers={
                                   "Content-Type":
                                   "application/json",
                                   "Accept":
                                   "application/json",
                                   "X-Rundeck-Auth-Token":
                                   self.module.params["token"]
                               })

        self.handle_http_code_if_needed(info)
        if resp is not None:
            resp = resp.read()
            if resp != "":
                try:
                    json_resp = json.loads(resp)
                    return json_resp, info
                except ValueError as e:
                    self.module.fail_json(
                        msg=
                        "Rundeck response was not a valid JSON. Exception was: %s. "
                        "Object was: %s" % (to_native(e), resp))
        return resp, info
Example #12
0
def get_token(module):
    """
    :param module:
    :return: token
    """
    # defaulting the value for transport_protocol to be : http
    transport_protocol = 'http'
    if module.params['https'] or module.params['validate_certs'] is True:
        transport_protocol = 'https'

    url = transport_protocol + "://" + module.params['iap_fqdn'] + ":" + module.params['iap_port'] + "/login"
    username = module.params['username']
    password = module.params['password']

    login = {
        "user": {
            "username": username,
            "password": password
        }
    }
    json_body = module.jsonify(login)
    headers = {}
    headers['Content-Type'] = 'application/json'

    # Using fetch url instead of requests
    response, info = fetch_url(module, url, data=json_body, headers=headers)
    response_code = str(info['status'])
    if info['status'] not in [200, 201]:
        module.fail_json(msg="Failed to connect to Itential Automation Platform" + response_code)
    response = response.read()
    module.exit_json(changed=True, token=response)
Example #13
0
    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
Example #14
0
    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
Example #15
0
    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
Example #16
0
    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
Example #17
0
    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
Example #18
0
    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
Example #19
0
    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 run(self, priority, msg, title):
        ''' Do, whatever it is, we do. '''

        url = '%s/1/messages.json' % (self.base_uri)

        # parse config
        options = dict(user=self.user,
                       token=self.token,
                       priority=priority,
                       message=msg)

        if title is not None:
            options = dict(options, title=title)

        data = urlencode(options)

        headers = {"Content-type": "application/x-www-form-urlencoded"}
        r, info = fetch_url(self.module,
                            url,
                            method='POST',
                            data=data,
                            headers=headers)
        if info['status'] != 200:
            raise Exception(info)

        return r.read()
    def _get_url_data(self,
                      url,
                      what=None,
                      msg_status=None,
                      msg_exception=None,
                      **kwargs):
        # Compose default messages
        if msg_status is None:
            msg_status = "Cannot get %s" % what

        if msg_exception is None:
            msg_exception = "Retrieval of %s failed." % what

        # Get the URL data
        try:
            response, info = fetch_url(self.module,
                                       url,
                                       timeout=self.timeout,
                                       cookies=self.cookies,
                                       headers=self.crumb,
                                       **kwargs)

            if info['status'] != 200:
                self.module.fail_json(msg=msg_status, details=info['msg'])
        except Exception as e:
            self.module.fail_json(msg=msg_exception, details=to_native(e))

        return response
    def update_repo_importer_config(self, repo_id, **kwargs):
        url = "%s/pulp/api/v2/repositories/%s/importers/" % (self.host,
                                                             repo_id)
        data = dict()
        importer_config = dict()

        for key, value in kwargs.items():
            if value is not None:
                importer_config[key] = value

        data['importer_config'] = importer_config

        if self.repo_type == 'rpm':
            data['importer_type_id'] = "yum_importer"

        response, info = fetch_url(self.module,
                                   url,
                                   data=json.dumps(data),
                                   method='POST')

        if info['status'] != 202:
            self.module.fail_json(
                msg="Failed to set the repo importer configuration",
                status_code=info['status'],
                response=info['msg'],
                importer_config=importer_config,
                url=url)
    def verify_tasks_completed(self, response_dict):
        for task in response_dict['spawned_tasks']:
            task_url = "%s%s" % (self.host, task['_href'])

            while True:
                response, info = fetch_url(self.module,
                                           task_url,
                                           data='',
                                           method='GET')

                if info['status'] != 200:
                    self.module.fail_json(
                        msg="Failed to check async task status.",
                        status_code=info['status'],
                        response=info['msg'],
                        url=task_url)

                task_dict = json.load(response)

                if task_dict['state'] == 'finished':
                    return True

                if task_dict['state'] == 'error':
                    self.module.fail_json(
                        msg="Asynchronous task failed to complete.",
                        error=task_dict['error'])

                sleep(2)
    def request(self, api_url, method, data=None, headers=None):
        headers = headers or {}

        if self.access_token:
            headers.update({
                'Authorization':
                'Bearer {0}'.format(self.access_token),
            })

        if isinstance(data, dict):
            data = self.module.jsonify(data)
            headers.update({
                'Content-type': 'application/json',
            })

        response, info = fetch_url(
            module=self.module,
            url=api_url,
            method=method,
            headers=headers,
            data=data,
            force=True,
        )

        content = {}

        if response is not None:
            body = to_text(response.read())
            if body:
                content = json.loads(body)

        return info, content
Example #25
0
def request(module,
            api_url,
            project,
            path,
            access_token,
            private_token,
            rawdata='',
            method='GET'):
    url = "%s/v4/projects/%s%s" % (api_url, quote_plus(project), path)
    headers = {}
    if access_token:
        headers['Authorization'] = "Bearer %s" % access_token
    else:
        headers['Private-Token'] = private_token

    headers['Accept'] = "application/json"
    headers['Content-Type'] = "application/json"

    response, info = fetch_url(module=module,
                               url=url,
                               headers=headers,
                               data=rawdata,
                               method=method)
    status = info['status']
    content = ""
    if response:
        content = response.read()
    if status == 204:
        return True, content
    elif status == 200 or status == 201:
        return True, json.loads(content)
    else:
        return False, str(status) + ": " + content
    def request(self, path, method=None, payload=None):
        """Generic HTTP method for Meraki requests."""
        self.path = path
        self.define_protocol()

        if method is not None:
            self.method = method
        self.url = '{protocol}://{host}/api/v0/{path}'.format(
            path=self.path.lstrip('/'), **self.params)
        resp, info = fetch_url(
            self.module,
            self.url,
            headers=self.headers,
            data=payload,
            method=self.method,
            timeout=self.params['timeout'],
            use_proxy=self.params['use_proxy'],
        )
        self.response = info['msg']
        self.status = info['status']

        try:
            return json.loads(to_native(resp.read()))
        except Exception:
            pass
Example #27
0
    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
Example #28
0
def post_twilio_api(module,
                    account_sid,
                    auth_token,
                    msg,
                    from_number,
                    to_number,
                    media_url=None):
    URI = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json" \
        % (account_sid,)
    AGENT = "Ansible"

    data = {'From': from_number, 'To': to_number, 'Body': msg}
    if media_url:
        data['MediaUrl'] = media_url
    encoded_data = urlencode(data)

    headers = {
        'User-Agent': AGENT,
        'Content-type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json',
    }

    # Hack module params to have the Basic auth params that fetch_url expects
    module.params['url_username'] = account_sid.replace('\n', '')
    module.params['url_password'] = auth_token.replace('\n', '')

    return fetch_url(module, URI, data=encoded_data, headers=headers)
Example #29
0
def axapi_call(module, url, post=None):
    '''
    Returns a datastructure based on the result of the API call
    '''
    rsp, info = fetch_url(module, url, data=post)
    if not rsp or info['status'] >= 400:
        module.fail_json(
            msg="failed to connect (status code %s), error was %s" %
            (info['status'], info.get('msg', 'no error given')))
    try:
        raw_data = rsp.read()
        data = json.loads(raw_data)
    except ValueError:
        # at least one API call (system.action.write_config) returns
        # XML even when JSON is requested, so do some minimal handling
        # here to prevent failing even when the call succeeded
        if 'status="ok"' in raw_data.lower():
            data = {"response": {"status": "OK"}}
        else:
            data = {"response": {"status": "fail", "err": {"msg": raw_data}}}
    except Exception:
        module.fail_json(msg="could not read the result from the host")
    finally:
        rsp.close()
    return data
Example #30
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)