예제 #1
0
 def test_multiple(self) -> None:
     """
     Multiple sidecars can exist at once.
     """
     with DockerLoopbackVolume(size_megabytes=1) as first:
         with DockerLoopbackVolume(size_megabytes=1) as second:
             assert first.path != second.path
예제 #2
0
def clean() -> None:
    """
    Remove containers, volumes and networks created by this tool.
    """

    client = docker_client()

    filters = {
        'label': [
            '{key}={value}'.format(
                key=NODE_TYPE_LABEL_KEY,
                value=NODE_TYPE_LOOPBACK_SIDECAR_LABEL_VALUE,
            ),
        ],
    }
    loopback_sidecars = client.containers.list(filters=filters)
    for loopback_sidecar in loopback_sidecars:
        DockerLoopbackVolume.destroy(container=loopback_sidecar)

    node_filters = {'name': Docker().container_name_prefix}
    network_filters = {'name': Docker().container_name_prefix}

    node_containers = client.containers.list(filters=node_filters, all=True)

    for container in node_containers:
        container.stop()
        container.remove(v=True)

    networks = client.networks.list(filters=network_filters)
    for network in networks:
        network.remove()
예제 #3
0
def destroy_loopback_sidecar(name: str) -> None:
    """
    Destroy a loopback sidecar.
    """
    loopback_sidecars = loopback_sidecars_by_name(name=name)

    if not loopback_sidecars:
        message = 'Loopback sidecar "{name}" does not exist'.format(
            name=name, )
        raise click.BadParameter(message)

    [loopback_sidecar] = loopback_sidecars
    with Halo(enabled=sys.stdout.isatty()):  # type: ignore
        DockerLoopbackVolume.destroy(container=loopback_sidecar)
예제 #4
0
def destroy_loopback_sidecar(enable_spinner: bool, name: str) -> None:
    """
    Destroy a loopback sidecar.
    """
    loopback_sidecars = loopback_sidecars_by_name(name=name)

    if not loopback_sidecars:
        message = 'Loopback sidecar "{name}" does not exist'.format(
            name=name,
        )
        raise click.BadParameter(message)

    [loopback_sidecar] = loopback_sidecars
    with Halo(enabled=enable_spinner):
        DockerLoopbackVolume.destroy(container=loopback_sidecar)
예제 #5
0
    def test_destroy(self) -> None:
        """
        The container and block device are destroyed.
        """
        client = docker.from_env(version='auto')
        key = uuid.uuid4().hex
        value = uuid.uuid4().hex
        labels = {key: value}

        with DockerLoopbackVolume(size_megabytes=1, labels=labels) as device:
            filters = {'label': ['{key}={value}'.format(key=key, value=value)]}
            [existing_container] = client.containers.list(filters=filters)
            block_device_exists_cmd = ['lsblk', device.path]

        with pytest.raises(docker.errors.NotFound):
            existing_container.reload()

        new_container = client.containers.create(
            privileged=True,
            detach=True,
            image='centos:7',
        )
        new_container.start()
        exit_code, output = new_container.exec_run(cmd=block_device_exists_cmd)
        new_container.stop()
        new_container.remove()

        assert exit_code != 0, output.decode()
예제 #6
0
    def test_loopback(self) -> None:
        """
        A block device is created which is accessible to multiple containers.
        """
        client = docker.from_env(version='auto')

        with DockerLoopbackVolume(size_megabytes=1) as device:
            new_container = client.containers.create(
                privileged=True,
                detach=True,
                image='centos:7',
            )
            new_container.start()

            try:
                block_device_exists_cmd = ['lsblk', device.path]
                exit_code, output = new_container.exec_run(
                    cmd=block_device_exists_cmd, )
                assert exit_code == 0, device.path + ': ' + output.decode()

                block_device_has_right_size = [
                    'stat',
                    '-f',
                    '"%z"',
                    device.path,
                ]
                exit_code, output = new_container.exec_run(
                    cmd=block_device_has_right_size, )
                assert exit_code == 0, device.path + ': ' + output.decode()
                assert output == '1048576'
            finally:
                new_container.stop()
                new_container.remove()
예제 #7
0
    def test_loopback(self, size_megabytes: int) -> None:
        """
        A block device is created which is accessible to multiple containers.
        """
        client = docker.from_env(version='auto')
        container = client.containers.create(
            privileged=True,
            detach=True,
            image='centos:7',
            entrypoint=['/bin/sleep', 'infinity'],
        )
        with DockerLoopbackVolume(size_megabytes=size_megabytes) as device:
            container.start()
            path = device.path
            block_device_exists = ['lsblk', path]
            block_device_has_right_size = ['blockdev', '--getsize64', path]
            exists_exit_code, exists_output = container.exec_run(
                cmd=block_device_exists, )
            size_exit_code, size_output = container.exec_run(
                cmd=block_device_has_right_size, )

        container.stop()
        container.remove()

        assert exists_exit_code == 0, path + ': ' + exists_output.decode()
        assert size_exit_code == 0, path + ': ' + size_output.decode()
        expected_output = str(1024 * 1024 * size_megabytes)
        assert size_output.decode().strip() == expected_output
예제 #8
0
    def test_labels(self) -> None:
        """
        The given labels are applied to the new container.
        """
        client = docker.from_env(version='auto')
        key = uuid.uuid4().hex
        value = uuid.uuid4().hex
        labels = {key: value}

        with DockerLoopbackVolume(size_megabytes=1, labels=labels):
            filters = {'label': ['{key}={value}'.format(key=key, value=value)]}
            [existing_container] = client.containers.list(filters=filters)
            for key, value in labels.items():
                assert existing_container.labels[key] == value
예제 #9
0
def create_loopback_sidecar(size: int, name: str) -> None:
    """
    Create a loopback sidecar.

    A loopback sidecar provides a loopback device that points to a
    (unformatted) block device.
    """

    if loopback_sidecars_by_name(name=name):
        message = 'Loopback sidecar "{name}" already exists'.format(
            name=name, )
        raise click.BadParameter(message)

    loopback_volume = DockerLoopbackVolume(
        size_megabytes=size,
        labels={
            NODE_TYPE_LABEL_KEY: NODE_TYPE_LOOPBACK_SIDECAR_LABEL_VALUE,
            SIDECAR_NAME_LABEL_KEY: name,
        },
    )

    click.echo(loopback_volume.path)