async def test_start_stop(dockerspawner_configured_app):
    app = dockerspawner_configured_app
    name = "has@"
    add_user(app.db, app, name=name)
    user = app.users[name]
    server_name = 'also-has@'
    spawner = user.spawners[server_name]
    assert isinstance(spawner, DockerSpawner)
    token = user.new_api_token()
    # start the server
    r = await api_request(app, "users", name, "servers", server_name, method="post")
    pending = r.status_code == 202
    while pending:
        # request again
        r = await api_request(app, "users", name)
        user_info = r.json()
        pending = user_info["servers"][server_name]["pending"]
    assert r.status_code in {201, 200}, r.text

    url = url_path_join(public_url(app, user), server_name, "api/status")
    resp = await AsyncHTTPClient().fetch(
        url, headers={"Authorization": "token %s" % token}
    )
    assert resp.effective_url == url
    resp.rethrow()
    assert "kernels" in resp.body.decode("utf-8")
def test_image_whitelist(app, image):
    name = "checker"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, DockerSpawner)
    user.spawner.remove_containers = True
    user.spawner.image_whitelist = {
        "0.9": "jupyterhub/singleuser:0.9",
        "0.8": "jupyterhub/singleuser:0.8",
    }
    token = user.new_api_token()
    # start the server
    r = yield api_request(
        app, "users", name, "server", method="post", data=json.dumps({"image": image})
    )
    if image not in user.spawner.image_whitelist:
        with pytest.raises(Exception):
            r.raise_for_status()
        return
    while r.status_code == 202:
        # request again
        r = yield api_request(app, "users", name, "server", method="post")
        yield gen.sleep(0.1)
    assert r.status_code == 201, r.text
    url = url_path_join(public_url(app, user), "api/status")
    r = yield async_requests.get(url, headers={"Authorization": "token %s" % token})
    r.raise_for_status()
    assert r.headers['x-jupyterhub-version'].startswith(image)
    r = yield api_request(
        app, "users", name, "server", method="delete",
    )
    r.raise_for_status()
async def test_post_start(dockerspawner_configured_app, caplog):
    app = dockerspawner_configured_app
    name = "post-start"
    add_user(app.db, app, name=name)
    user = app.users[name]
    spawner = user.spawners['']
    log_name = "dockerspawner"
    spawner.log = logging.getLogger(log_name)
    spawner.remove = True
    # mock out ip and port, no need for it
    async def mock_ip_port():
        return ("127.0.0.1", 1234)

    spawner.get_ip_and_port = mock_ip_port

    spawner.image = "busybox:1.29.1"
    spawner.cmd = ["sh", "-c", "sleep 300"]
    spawner.post_start_cmd = "ls /"

    # verify that it's called during startup
    finished_future = asyncio.Future()
    finished_future.set_result(None)
    mock_post_start = mock.Mock(return_value=finished_future)
    with mock.patch.object(spawner, 'post_start_exec', mock_post_start):
        await spawner.start()
    mock_post_start.assert_called_once()

    # verify log capture for 3 combinations:
    # - success
    # - failure
    # - no such command (different failure)

    for (cmd, expected_stdout, expected_stderr) in [
        ("true", False, False),
        ("ls /", True, False),
        ("ls /nosuchfile", False, True),
        ("nosuchcommand", False, True),
        ("echo", False, False),
    ]:
        spawner.post_start_cmd = cmd
        idx = len(caplog.records)
        with caplog.at_level(logging.DEBUG, log_name):
            await spawner.post_start_exec()
        logged = "\n".join(
            f"{rec.levelname}: {rec.message}" for rec in caplog.records[idx:]
        )
        if expected_stdout:
            assert "DEBUG: post_start stdout" in logged
        else:
            assert "post_start stdout" not in logged
        if expected_stderr:
            assert "WARNING: post_start stderr" in logged
        else:
            assert "post_start stderr" not in logged

    await spawner.stop()
示例#4
0
async def test_image_pull_policy(dockerspawner_configured_app):
    app = dockerspawner_configured_app
    name = "gumby"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, DockerSpawner)
    spawner = user.spawners[""]
    spawner.image = "jupyterhub/doesntexist:nosuchtag"
    with pytest.raises(docker.errors.NotFound):
        spawner.image_pull_policy = "never"
        await spawner.pull_image(spawner.image)

    repo = "busybox"
    tag = "1.29.1"  # a version that's definitely not latest
    # ensure image isn't present
    try:
        await asyncio.wrap_future(
            spawner.docker("remove_image", "{}:{}".format(repo, tag)))
    except docker.errors.ImageNotFound:
        pass

    spawner.pull_policy = "ifnotpresent"
    image = "{}:{}".format(repo, tag)
    # should trigger a pull
    await spawner.pull_image(image)
    # verify that the image exists now
    old_image_info = await asyncio.wrap_future(
        spawner.docker("inspect_image", image))
    print(old_image_info)

    # now tag busybox:latest as our current version
    # which is not latest!
    await asyncio.wrap_future(spawner.docker("tag", image, repo))

    image = repo  # implicit :latest
    spawner.pull_policy = "ifnotpresent"
    # check with ifnotpresent shouldn't pull
    await spawner.pull_image(image)
    image_info = await asyncio.wrap_future(
        spawner.docker("inspect_image", repo))
    assert image_info["Id"] == old_image_info["Id"]

    # run again with Always,
    # should trigger a pull even though the image is present
    spawner.pull_policy = "always"
    spawner.pull_image(image)
    image_info = await asyncio.wrap_future(
        spawner.docker("inspect_image", repo))
    assert image_info["Id"] != old_image_info["Id"]

    # run again with never, make sure it's still happy
    spawner.pull_policy = "never"
    spawner.pull_image(image)
示例#5
0
def test_name_collision(dockerspawner_configured_app):
    app = dockerspawner_configured_app
    has_hyphen = "user--foo"
    add_user(app.db, app, name=has_hyphen)
    user = app.users[has_hyphen]
    spawner1 = user.spawners[""]
    assert isinstance(spawner1, DockerSpawner)
    assert spawner1.object_name == "{}-{}".format(spawner1.prefix, has_hyphen)

    part1, part2 = ["user", "foo"]
    add_user(app.db, app, name=part1)
    user2 = app.users[part1]
    spawner2 = user2.spawners[part2]
    assert spawner1.object_name != spawner2.object_name
def test_image_pull_policy(app):
    name = "gumby"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, DockerSpawner)
    spawner = user.spawners[""]
    spawner.image = "jupyterhub/doesntexist:nosuchtag"
    with pytest.raises(docker.errors.NotFound):
        spawner.image_pull_policy = "never"
        yield spawner.pull_image(spawner.image)

    repo = "busybox"
    tag = "1.29.1"  # a version that's definitely not latest
    # ensure image isn't present
    try:
        yield spawner.docker("remove_image", "{}:{}".format(repo, tag))
    except docker.errors.ImageNotFound:
        pass

    spawner.pull_policy = "ifnotpresent"
    image = "{}:{}".format(repo, tag)
    # should trigger a pull
    yield spawner.pull_image(image)
    # verify that the image exists now
    old_image_info = yield spawner.docker("inspect_image", image)
    print(old_image_info)

    # now tag busybox:latest as our current version
    # which is not latest!
    yield spawner.docker("tag", image, repo)

    image = repo  # implicit :latest
    spawner.pull_policy = "ifnotpresent"
    # check with ifnotpresent shouldn't pull
    yield spawner.pull_image(image)
    image_info = yield spawner.docker("inspect_image", repo)
    assert image_info["Id"] == old_image_info["Id"]

    # run again with Always,
    # should trigger a pull even though the image is present
    spawner.pull_policy = "always"
    spawner.pull_image(image)
    image_info = yield spawner.docker("inspect_image", repo)
    assert image_info["Id"] != old_image_info["Id"]

    # run again with never, make sure it's still happy
    spawner.pull_policy = "never"
    spawner.pull_image(image)
示例#7
0
async def test_integration(skein_client, app):
    with clean_cluster(skein_client):
        # Create a user
        add_user(app.db, app, name="alice")
        alice = app.users["alice"]
        assert isinstance(alice.spawner, YarnSpawner)
        token = alice.new_api_token()

        # Not started, status should be 0
        status = await alice.spawner.poll()
        assert status == 0

        # Stop can be called before start, no-op
        await alice.spawner.stop()

        # Start the server, and wait for it to start
        resp = None
        while resp is None or resp.status_code == 202:
            await gen.sleep(2.0)
            resp = await api_request(app,
                                     "users",
                                     "alice",
                                     "server",
                                     method="post")

        # Check that everything is running fine
        url = url_path_join(public_url(app, alice), "api/status")
        resp = await async_requests.get(
            url, headers={'Authorization': 'token %s' % token})
        resp.raise_for_status()
        assert "kernels" in resp.json()

        # Save the app_id to use later
        app_id = alice.spawner.app_id

        # Shutdown the server
        resp = await api_request(app,
                                 "users",
                                 "alice",
                                 "server",
                                 method="delete")
        resp.raise_for_status()
        assert_shutdown_in(skein_client, app_id, timeout=10)

        # Check status
        status = await alice.spawner.poll()
        assert status == 0
示例#8
0
async def test_allowed_image(dockerspawner_configured_app, image):
    app = dockerspawner_configured_app
    name = "checker"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, DockerSpawner)
    user.spawner.remove_containers = True
    user.spawner.allowed_images = {
        "1.0": "jupyterhub/singleuser:1.0",
        "1.1": "jupyterhub/singleuser:1.1",
    }
    token = user.new_api_token()
    # start the server
    r = await api_request(app,
                          "users",
                          name,
                          "server",
                          method="post",
                          data=json.dumps({"image": image}))
    if image not in user.spawner.allowed_images:
        with pytest.raises(Exception):
            r.raise_for_status()
        return
    pending = r.status_code == 202
    while pending:
        # request again
        r = await api_request(app, "users", name)
        user_info = r.json()
        pending = user_info["servers"][""]["pending"]

    url = url_path_join(public_url(app, user), "api/status")
    resp = await AsyncHTTPClient().fetch(
        url, headers={"Authorization": "token %s" % token})
    assert resp.effective_url == url
    resp.rethrow()

    assert resp.headers['x-jupyterhub-version'].startswith(image)
    r = await api_request(
        app,
        "users",
        name,
        "server",
        method="delete",
    )
    r.raise_for_status()
def test_start_stop(app):
    name = "somebody"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, SwarmSpawner)
    token = user.new_api_token()
    # start the server
    r = yield api_request(app, "users", name, "server", method="post")
    while r.status_code == 202:
        # request again
        r = yield api_request(app, "users", name, "server", method="post")
    assert r.status_code == 201, r.text
    url = url_path_join(public_url(app, user), "api/status")
    r = yield async_requests.get(url, headers={"Authorization": "token %s" % token})
    assert r.url == url
    r.raise_for_status()
    print(r.text)
    assert "kernels" in r.json()
def test_start_stop(app):
    name = getuser()
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, SystemUserSpawner)
    token = user.new_api_token()
    # start the server
    r = yield api_request(app, "users", name, "server", method="post")
    while r.status_code == 202:
        # request again
        r = yield api_request(app, "users", name, "server", method="post")
    assert r.status_code == 201, r.text
    url = url_path_join(public_url(app, user), "api/status")
    r = yield async_requests.get(url, headers={"Authorization": "token %s" % token})
    assert r.url == url
    r.raise_for_status()
    print(r.text)
    assert "kernels" in r.json()
示例#11
0
async def test_start_stop(systemuserspawner_configured_app):
    app = systemuserspawner_configured_app
    name = getuser()
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, SystemUserSpawner)
    token = user.new_api_token()
    # start the server
    r = await api_request(app, "users", name, "server", method="post")
    while r.status_code == 202:
        # request again
        r = await api_request(app, "users", name, "server", method="post")
    assert r.status_code == 201, r.text

    url = url_path_join(public_url(app, user), "api/status")
    resp = await AsyncHTTPClient().fetch(url, headers={"Authorization": "token %s" % token})
    assert resp.effective_url == url
    resp.rethrow()
    assert "kernels" in resp.body.decode("utf-8")
示例#12
0
def test_image_whitelist(app, image):
    name = "checker"
    add_user(app.db, app, name=name)
    user = app.users[name]
    assert isinstance(user.spawner, DockerSpawner)
    user.spawner.remove_containers = True
    user.spawner.image_whitelist = {
        "0.9": "jupyterhub/singleuser:0.9",
        "0.8": "jupyterhub/singleuser:0.8",
    }
    token = user.new_api_token()
    # start the server
    r = yield api_request(app,
                          "users",
                          name,
                          "server",
                          method="post",
                          data=json.dumps({"image": image}))
    if image not in user.spawner.image_whitelist:
        with pytest.raises(Exception):
            r.raise_for_status()
        return
    while r.status_code == 202:
        # request again
        r = yield api_request(app, "users", name, "server", method="post")
        yield gen.sleep(0.1)
    assert r.status_code == 201, r.text
    url = url_path_join(public_url(app, user), "api/status")
    r = yield async_requests.get(url,
                                 headers={"Authorization": "token %s" % token})
    r.raise_for_status()
    assert r.headers['x-jupyterhub-version'].startswith(image)
    r = yield api_request(
        app,
        "users",
        name,
        "server",
        method="delete",
    )
    r.raise_for_status()
示例#13
0
async def test_start_stop(swarmspawner_app):
    username = "******"
    server_name = "also-has@"

    app = swarmspawner_app
    add_user(app.db, app, name=username)
    user = app.users[username]

    spawner = user.spawners[server_name]
    assert isinstance(spawner, SwarmSpawner)

    token = user.new_api_token()
    # Start the server
    r = await api_request(app, "users", username, "servers", server_name, method="post")
    pending = r.status_code == 202
    while pending:
        # Request again
        r = await api_request(app, "users", username)
        user_info = r.json()
        pending = user_info["servers"][server_name]["pending"]

    assert r.status_code in {201, 200}, r.text
示例#14
0
async def test_integration(app, auto_login, logged_in):
    app.authenticator.auto_login = auto_login

    # Create a user
    add_user(app.db, app, name="alice")

    if auto_login:
        url = public_url(app, path="/hub/login")
        resp = await async_requests.get(url)
        # Sends back 401 requesting authentication
        assert resp.status_code == 401
        # 401 page is formatted nicely
        assert "Failed to login with Kerberos." in resp.text
        assert resp.text.count("/hub/login") >= 2
        # Before that was a redirect to the auth handler
        assert resp.history[0].status_code == 302
        # Now use the redirected url with auth enabled
        location = resp.history[0].headers['location']
        netloc = urlparse(app.bind_url).netloc
        url = 'http://%s%s' % (netloc, location)
    else:
        url = public_url(app, path="/hub/kerberos_login")

    # Go through the login procedure
    resp = await async_requests.get(
        url, auth=HTTPKerberosAuth(hostname_override="address.example.com"))

    if logged_in:
        # Successful
        resp.raise_for_status()

        # At user notebook, login successful
        assert resp.url.startswith(public_url(app, path="/user/alice"))
    else:
        # Unsuccessful
        assert resp.status_code == 401