def container(request, docker_client, wrapper_class, **kwargs):
    """ Docker container: image={image} """

    wrapper_class = wrapper_class or Container

    kwargs.update({"detach": True})
    set_reusable_labels(kwargs, request)

    signature = hash_params(kwargs)
    set_signature(kwargs, signature)

    if request.config.option.reuse_containers:
        if "name" not in kwargs.keys():
            pytest.fail(
                "Tried to use '--reuse-containers' command line argument without "
                "setting 'name' attribute on container"
            )

        name = kwargs["name"]

        try:
            current = docker_client.containers.get(name)
        except NotFound:
            pass
        else:
            # Found a container with the right name, but it doesn't have pytest-docker-tools labels
            # We shouldn't just clobber it, its not ours. Bail out.
            if not is_reusable_container(current):
                pytest.fail(
                    f"Tried to reuse {name} but it does not appear to be a reusable container"
                )

            # It's ours, and its not stale. Reuse it!
            if check_signature(current.labels, signature):
                return wrapper_class(current)

            # It's ours and it is stale. Clobber it.
            print(f"Removing stale reusable container: {name}")
            current.remove(force=True)

    timeout = kwargs.pop("timeout", 30)

    raw_container = docker_client.containers.run(**kwargs)
    if not request.config.option.reuse_containers:
        request.addfinalizer(
            lambda: raw_container.remove(force=True) and raw_container.wait(timeout=10)
        )

    container = wrapper_class(raw_container)

    try:
        wait_for_callable("Waiting for container to be ready", container.ready, timeout)
    except TimeoutError:
        raise ContainerNotReady(
            container, "Timeout while waiting for container to be ready"
        )

    return container
Esempio n. 2
0
def volume(request, docker_client, wrapper_class, **kwargs):
    """ Docker volume """
    wrapper_class = wrapper_class or (lambda volume: volume)

    set_reusable_labels(kwargs, request)

    signature = hash_params(kwargs)
    set_signature(kwargs, signature)

    if request.config.option.reuse_containers:
        if "name" not in kwargs.keys():
            pytest.fail(
                "Error: Tried to use '--reuse-containers' command line argument without "
                "setting 'name' attribute on volume")

        name = kwargs["name"]
        try:
            volume = docker_client.volumes.get(name)
        except NotFound:
            pass
        else:
            # Found a volume with the right name, but it doesn't have pytest-docker-tools labels
            # We shouldn't just clobber it, its not ours. Bail out.
            if not is_reusable_volume(volume):
                pytest.fail(
                    f"Tried to reuse {name} but it does not appear to be a reusable volume"
                )

            # It's ours, and its not stale. Reuse it!
            if check_signature(volume.attrs["Labels"], signature):
                return wrapper_class(volume)

            # It's ours and it is stale. Clobber it.
            _remove_stale_volume(docker_client, volume)

    name = kwargs.pop("name", "pytest-{uuid}").format(uuid=str(uuid.uuid4()))
    seeds = kwargs.pop("initial_content", {})

    print(f"Creating volume {name}")
    volume = docker_client.volumes.create(name, **kwargs)

    if not request.config.option.reuse_containers:
        request.addfinalizer(lambda: volume.remove(True))

    if seeds:
        _populate_volume(docker_client, volume, seeds)

    return wrapper_class(volume)
Esempio n. 3
0
def test_set_signature_no_existing_labels():
    signature = "1c67a2e8dd405725a4cdf7b58fed3e948aed135ac25c494a3b336c83a72ac0c8"

    kwargs = {
        "name": "hello",
        "image": "alpine:3.13",
    }
    set_signature(kwargs, signature)

    assert kwargs == {
        "name": "hello",
        "image": "alpine:3.13",
        "labels": {
            "pytest-docker-tools.signature": signature,
        },
    }
def network(request, docker_client: DockerClient, wrapper_class, **kwargs):
    """ Docker network """

    set_reusable_labels(kwargs, request)

    signature = hash_params(kwargs)
    set_signature(kwargs, signature)

    wrapper_class = wrapper_class or (lambda network: network)

    if request.config.option.reuse_containers:
        if "name" not in kwargs.keys():
            pytest.fail(
                "Error: Tried to use '--reuse-containers' command line argument without "
                "setting 'name' attribute on network")

        name = kwargs["name"]
        try:
            network = docker_client.networks.get(name)
        except NotFound:
            pass
        else:
            # Found a network with the right name, but it doesn't have pytest-docker-tools labels
            # We shouldn't just clobber it, its not ours. Bail out.
            if not is_reusable_network(network):
                pytest.fail(
                    f"Tried to reuse {network.name} but it does not appear to be a reusable network"
                )

            # It's ours, and its not stale. Reuse it!
            if check_signature(network.attrs["Labels"], signature):
                return wrapper_class(network)

            # It's ours and it is stale. Clobber it.
            _remove_stale_network(network)

    name = kwargs.pop("name", "pytest-{uuid}").format(uuid=str(uuid.uuid4()))

    print(f"Creating network {name}")
    network = docker_client.networks.create(name, **kwargs)

    if not request.config.option.reuse_containers:
        request.addfinalizer(lambda: network.remove())

    return wrapper_class(network)