Ejemplo n.º 1
0
def test_fetch_url_connectionerror(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = ConnectionError('TESTS')
    with pytest.raises(FailJson) as excinfo:
        fetch_url(fake_assible_module, 'http://assible.com/')

    assert excinfo.value.kwargs['msg'] == 'TESTS'
    assert 'http://assible.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_assible_module, 'http://assible.com/')

    assert excinfo.value.kwargs['msg'] == 'TESTS'
    assert 'http://assible.com/' == excinfo.value.kwargs['url']
    assert excinfo.value.kwargs['status'] == -1
Ejemplo n.º 2
0
def test_fetch_url(open_url_mock, fake_assible_module):
    r, info = fetch_url(fake_assible_module, 'http://assible.com/')

    dummy, kwargs = open_url_mock.call_args

    open_url_mock.assert_called_once_with('http://assible.com/', client_cert=None, client_key=None, cookies=kwargs['cookies'], data=None,
                                          follow_redirects='urllib2', force=False, force_basic_auth='', headers=None,
                                          http_agent='assible-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)
Ejemplo n.º 3
0
def test_fetch_url_nossl(open_url_mock, fake_assible_module, mocker):
    mocker.patch('assible.module_utils.urls.get_distribution', return_value='notredhat')

    open_url_mock.side_effect = NoSSLError
    with pytest.raises(FailJson) as excinfo:
        fetch_url(fake_assible_module, 'http://assible.com/')

    assert 'python-ssl' not in excinfo.value.kwargs['msg']

    mocker.patch('assible.module_utils.urls.get_distribution', return_value='redhat')

    open_url_mock.side_effect = NoSSLError
    with pytest.raises(FailJson) as excinfo:
        fetch_url(fake_assible_module, 'http://assible.com/')

    assert 'python-ssl' in excinfo.value.kwargs['msg']
    assert 'http://assible.com/' == excinfo.value.kwargs['url']
    assert excinfo.value.kwargs['status'] == -1
Ejemplo n.º 4
0
    def _get_ppa_info(self, owner_name, ppa_name):
        lp_api = self.LP_API % (owner_name, ppa_name)

        headers = dict(Accept='application/json')
        response, info = fetch_url(self.module, lp_api, headers=headers)
        if info['status'] != 200:
            self.module.fail_json(
                msg="failed to fetch PPA information, error was: %s" %
                info['msg'])
        return json.loads(to_native(response.read()))
Ejemplo n.º 5
0
def test_fetch_url_httperror(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = urllib_error.HTTPError(
        'http://assible.com/',
        500,
        'Internal Server Error',
        {'Content-Type': 'application/json'},
        StringIO('TESTS')
    )

    r, info = fetch_url(fake_assible_module, 'http://assible.com/')

    assert info == {'msg': 'HTTP Error 500: Internal Server Error', 'body': 'TESTS',
                    'status': 500, 'url': 'http://assible.com/', 'content-type': 'application/json'}
Ejemplo n.º 6
0
def download_key(module, url):
    # FIXME: move get_url code to common, allow for in-memory D/L, support proxies
    # and reuse here
    if url is None:
        module.fail_json(msg="needed a URL but was not specified")

    try:
        rsp, info = fetch_url(module, url)
        if info['status'] != 200:
            module.fail_json(msg="Failed to download key at %s: %s" %
                             (url, info['msg']))

        return rsp.read()
    except Exception:
        module.fail_json(msg="error getting key id from url: %s" % url,
                         traceback=format_exc())
Ejemplo n.º 7
0
def test_fetch_url_cookies(mocker, fake_assible_module):
    def make_cookies(*args, **kwargs):
        cookies = kwargs['cookies']
        r = MagicMock()
        try:
            r.headers = HTTPMessage()
            add_header = r.headers.add_header
        except TypeError:
            # PY2
            r.headers = HTTPMessage(StringIO())
            add_header = r.headers.addheader
        r.info.return_value = r.headers
        for name, value in (('Foo', 'bar'), ('Baz', 'qux')):
            cookie = Cookie(
                version=0,
                name=name,
                value=value,
                port=None,
                port_specified=False,
                domain="assible.com",
                domain_specified=True,
                domain_initial_dot=False,
                path="/",
                path_specified=True,
                secure=False,
                expires=None,
                discard=False,
                comment=None,
                comment_url=None,
                rest=None
            )
            cookies.set_cookie(cookie)
            add_header('Set-Cookie', '%s=%s' % (name, value))

        return r

    mocker = mocker.patch('assible.module_utils.urls.open_url', new=make_cookies)

    r, info = fetch_url(fake_assible_module, 'http://assible.com/')

    assert info['cookies'] == {'Baz': 'qux', 'Foo': 'bar'}
    # Python sorts cookies in order of most specific (ie. longest) path first
    # items with the same path are reversed from response order
    assert info['cookies_string'] == 'Baz=qux; Foo=bar'
    # The key here has a `-` as opposed to what we see in the `uri` module that converts to `_`
    # Note: this is response order, which differs from cookies_string
    assert info['set-cookie'] == 'Foo=bar, Baz=qux'
Ejemplo n.º 8
0
    def fetch_key(self, url):
        """Downloads a key from url, returns a valid path to a gpg key"""
        rsp, info = fetch_url(self.module, url)
        if info['status'] != 200:
            self.module.fail_json(
                msg="failed to fetch key at %s , error was: %s" %
                (url, info['msg']))

        key = rsp.read()
        if not is_pubkey(key):
            self.module.fail_json(msg="Not a public key: %s" % url)
        tmpfd, tmpname = tempfile.mkstemp()
        self.module.add_cleanup_file(tmpname)
        tmpfile = os.fdopen(tmpfd, "w+b")
        tmpfile.write(key)
        tmpfile.close()
        return tmpname
Ejemplo n.º 9
0
def test_fetch_url_params(open_url_mock, fake_assible_module):
    fake_assible_module.params = {
        'validate_certs': False,
        'url_username': '******',
        'url_password': '******',
        'http_agent': 'assible-test',
        'force_basic_auth': True,
        'follow_redirects': 'all',
        'client_cert': 'client.pem',
        'client_key': 'client.key',
    }

    r, info = fetch_url(fake_assible_module, 'http://assible.com/')

    dummy, kwargs = open_url_mock.call_args

    open_url_mock.assert_called_once_with('http://assible.com/', client_cert='client.pem', client_key='client.key', cookies=kwargs['cookies'], data=None,
                                          follow_redirects='all', force=False, force_basic_auth=True, headers=None,
                                          http_agent='assible-test', last_mod_time=None, method=None, timeout=10, url_password='******', url_username='******',
                                          use_proxy=True, validate_certs=False, use_gssapi=False, unix_socket=None, ca_path=None)
Ejemplo n.º 10
0
def url_get(module,
            url,
            dest,
            use_proxy,
            last_mod_time,
            force,
            timeout=10,
            headers=None,
            tmp_dest=''):
    """
    Download data from the url and store in a temporary file.

    Return (tempfile, info about the request)
    """
    if module.check_mode:
        method = 'HEAD'
    else:
        method = 'GET'

    start = datetime.datetime.utcnow()
    rsp, info = fetch_url(module,
                          url,
                          use_proxy=use_proxy,
                          force=force,
                          last_mod_time=last_mod_time,
                          timeout=timeout,
                          headers=headers,
                          method=method)
    elapsed = (datetime.datetime.utcnow() - start).seconds

    if info['status'] == 304:
        module.exit_json(url=url,
                         dest=dest,
                         changed=False,
                         msg=info.get('msg', ''),
                         status_code=info['status'],
                         elapsed=elapsed)

    # Exceptions in fetch_url may result in a status -1, the ensures a proper error to the user in all cases
    if info['status'] == -1:
        module.fail_json(msg=info['msg'], url=url, dest=dest, elapsed=elapsed)

    if info['status'] != 200 and not url.startswith('file:/') and not (
            url.startswith('ftp:/') and info.get('msg', '').startswith('OK')):
        module.fail_json(msg="Request failed",
                         status_code=info['status'],
                         response=info['msg'],
                         url=url,
                         dest=dest,
                         elapsed=elapsed)

    # create a temporary file and copy content to do checksum-based replacement
    if tmp_dest:
        # tmp_dest should be an existing dir
        tmp_dest_is_dir = os.path.isdir(tmp_dest)
        if not tmp_dest_is_dir:
            if os.path.exists(tmp_dest):
                module.fail_json(
                    msg="%s is a file but should be a directory." % tmp_dest,
                    elapsed=elapsed)
            else:
                module.fail_json(msg="%s directory does not exist." % tmp_dest,
                                 elapsed=elapsed)
    else:
        tmp_dest = module.tmpdir

    fd, tempname = tempfile.mkstemp(dir=tmp_dest)

    f = os.fdopen(fd, 'wb')
    try:
        shutil.copyfileobj(rsp, f)
    except Exception as e:
        os.remove(tempname)
        module.fail_json(msg="failed to create temporary content file: %s" %
                         to_native(e),
                         elapsed=elapsed,
                         exception=traceback.format_exc())
    f.close()
    rsp.close()
    return tempname, info
Ejemplo n.º 11
0
def test_fetch_url_no_urlparse(mocker, fake_assible_module):
    mocker.patch('assible.module_utils.urls.HAS_URLPARSE', new=False)

    with pytest.raises(FailJson):
        fetch_url(fake_assible_module, 'http://assible.com/')
Ejemplo n.º 12
0
def test_fetch_url_badstatusline(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = httplib.BadStatusLine('TESTS')
    r, info = fetch_url(fake_assible_module, 'http://assible.com/')
    assert info == {'msg': 'Connection failure: connection was closed before a valid response was received: TESTS', 'status': -1, 'url': 'http://assible.com/'}
Ejemplo n.º 13
0
def test_fetch_url_exception(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = Exception('TESTS')
    r, info = fetch_url(fake_assible_module, 'http://assible.com/')
    exception = info.pop('exception')
    assert info == {'msg': 'An unknown error occurred: TESTS', 'status': -1, 'url': 'http://assible.com/'}
    assert "Exception: TESTS" in exception
Ejemplo n.º 14
0
def test_fetch_url_socketerror(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = socket.error('TESTS')
    r, info = fetch_url(fake_assible_module, 'http://assible.com/')
    assert info == {'msg': 'Connection failure: TESTS', 'status': -1, 'url': 'http://assible.com/'}
Ejemplo n.º 15
0
def test_fetch_url_urlerror(open_url_mock, fake_assible_module):
    open_url_mock.side_effect = urllib_error.URLError('TESTS')
    r, info = fetch_url(fake_assible_module, 'http://assible.com/')
    assert info == {'msg': 'Request failed: <urlopen error TESTS>', 'status': -1, 'url': 'http://assible.com/'}
Ejemplo n.º 16
0
def uri(module, url, dest, body, body_format, method, headers, socket_timeout):
    # is dest is set and is a directory, let's check if we get redirected and
    # set the filename from that url
    redirected = False
    redir_info = {}
    r = {}

    src = module.params['src']
    if src:
        try:
            headers.update({
                'Content-Length': os.stat(src).st_size
            })
            data = open(src, 'rb')
        except OSError:
            module.fail_json(msg='Unable to open source file %s' % src, elapsed=0)
    else:
        data = body

    kwargs = {}
    if dest is not None:
        # Stash follow_redirects, in this block we don't want to follow
        # we'll reset back to the supplied value soon
        follow_redirects = module.params['follow_redirects']
        module.params['follow_redirects'] = False
        if os.path.isdir(dest):
            # first check if we are redirected to a file download
            _, redir_info = fetch_url(module, url, data=body,
                                      headers=headers,
                                      method=method,
                                      timeout=socket_timeout, unix_socket=module.params['unix_socket'])
            # if we are redirected, update the url with the location header,
            # and update dest with the new url filename
            if redir_info['status'] in (301, 302, 303, 307):
                url = redir_info['location']
                redirected = True
            dest = os.path.join(dest, url_filename(url))
        # if destination file already exist, only download if file newer
        if os.path.exists(dest):
            kwargs['last_mod_time'] = datetime.datetime.utcfromtimestamp(os.path.getmtime(dest))

        # Reset follow_redirects back to the stashed value
        module.params['follow_redirects'] = follow_redirects

    resp, info = fetch_url(module, url, data=data, headers=headers,
                           method=method, timeout=socket_timeout, unix_socket=module.params['unix_socket'],
                           **kwargs)

    try:
        content = resp.read()
    except AttributeError:
        # there was no content, but the error read()
        # may have been stored in the info as 'body'
        content = info.pop('body', '')

    if src:
        # Try to close the open file handle
        try:
            data.close()
        except Exception:
            pass

    r['redirected'] = redirected or info['url'] != url
    r.update(redir_info)
    r.update(info)

    return r, content, dest