Ejemplo n.º 1
0
    def _run_port_mapper(cls, container, ports):
        network_name = f'{container.name}_network'
        guest_ip = container.attrs['NetworkSettings']['Networks'][
            network_name]['IPAddress']
        containers_names = []
        for port in ports:
            # TODO: Use a single container for all port mappings instead of
            # spinning a container for each port
            name = f'{container.name}_port_mapper_{port}'
            cmd = f'TCP-LISTEN:1234,fork TCP-CONNECT:{guest_ip}:{port}'
            kwargs = {
                'command': cmd,
                'ports': {
                    '1234': f'{port}/tcp'
                },
                'name': name,
                'detach': True,
                'auto_remove': True,
                'network': network_name,
            }

            Client.get_instance().containers.run('alpine/socat', **kwargs)
            containers_names.append(name)

        return containers_names
Ejemplo n.º 2
0
    def assertPortMapperExists(self, env_name, port):
        port_mapper_container_name = (definitions.CONTAINERS_PREFIX +
                                      env_name + f'_port_mapper_{port}')

        try:
            Client.get_instance().containers.get(port_mapper_container_name)
        except docker.errors.NotFound:
            self.fail(
                f'Cannot find port mapper for environment {env_name} with'
                f'port {port}')
Ejemplo n.º 3
0
def save(name, output):
    current_env = StateConfig.get_current_env()

    click.echo(f'Saving environment {current_env}...')

    image_name = _commit(name, current_env)
    _export(image_name, output)

    click.echo(f'Removing image {image_name}...')
    Client.get_instance().images.remove(image_name)
    click.echo(f'Image {image_name} removed')
Ejemplo n.º 4
0
def create_env(image, name, project_dir):
    workdir = os.path.abspath(project_dir)
    mounts = [Mount('/usr/src', workdir, type='bind')]
    kwargs = {
        'command': '/bin/sh',
        'stdin_open': True,
        'name': definitions.CONTAINERS_PREFIX + name,
        'mounts': mounts,
        'network': definitions.CONTAINERS_PREFIX + name + '_network',
    }
    Client.get_instance().containers.create(image, **kwargs)

    StateConfig.get_instance().update_conf(
        {definitions.CONTAINERS_PREFIX + name: {
            'workdir': workdir
        }})
Ejemplo n.º 5
0
    def execute(cls, *args, **kwargs):
        client = Client.get_instance()
        current_env = StateConfig.get_current_env()
        try:
            container = client.containers.get(definitions.CONTAINERS_PREFIX +
                                              current_env)
        except docker.errors.ImageNotFound:
            click.echo(f'Container {current_env} not found, exiting...')
            raise

        # This cannot be done with docker python sdk
        host_base_wd = StateConfig.get_instance().get_env_conf(
            definitions.CONTAINERS_PREFIX + current_env)['workdir']
        current_wd = os.getcwd()
        if not current_wd.startswith(host_base_wd):
            raise RuntimeError(
                f'Cannot run commands outside of {host_base_wd}')

        relative_wd = current_wd[len(host_base_wd):]
        guest_wd = f'/usr/src{relative_wd}'

        detach = kwargs.get('detach')
        env_vars = cls._build_env_vars(kwargs.get('env_vars'))
        with cls._with_mapped_ports(container, kwargs.get('ports'), detach):
            cmd = ['docker', 'exec', '-w', guest_wd]
            if detach:
                cmd.append('-d')
            else:
                cmd.extend(['-i', '-t'])

            cmd = (cmd + env_vars +
                   [(definitions.CONTAINERS_PREFIX + current_env)] +
                   list(args))

            subprocess.check_call(cmd)
Ejemplo n.º 6
0
    def tearDown(self):
        os.chdir(self._cwd)
        try:
            for i in range(1, self._env_index):
                env_name = self._create_env_name(i)
                try:
                    Client.get_instance().containers.get(
                        definitions.CONTAINERS_PREFIX +
                        env_name).remove(force=True)
                    delete_network(env_name)
                except docker.errors.NotFound:
                    pass

                self._remove_port_mappers(env_name)
        finally:
            shutil.rmtree(self._test_dir.name)
Ejemplo n.º 7
0
def load(name, project_dir, input_file):
    click.echo(f'Loading environment {name} from {input_file}...')
    with open(input_file, 'rb') as fin:
        image = Client.get_instance().images.load(fin)[0]

    create_network(name)
    create_env(image, name, project_dir)

    click.echo(f'Environment {name} loaded from {input_file}!')
Ejemplo n.º 8
0
def activate(name):
    click.echo('Activating environment...')
    try:
        container = Client.get_instance().containers.get(
            definitions.CONTAINERS_PREFIX + name)
    except docker.errors.NotFound:
        click.echo(f'Environment {name} not found, exiting...')
    else:
        container.start()
        click.echo('Environment activated!')
Ejemplo n.º 9
0
def deactivate():
    click.echo('Deactivating current environment...')
    current_env = StateConfig.get_current_env()
    try:
        container = Client.get_instance().containers.get(
            definitions.CONTAINERS_PREFIX + current_env)
    except docker.errors.ImageNotFound:
        click.echo(f'Environment {current_env} not found, exiting...')
    else:
        container.stop()
        click.echo('Environment deactivated!')
Ejemplo n.º 10
0
def delete_network(env_name):
    network_name = definitions.CONTAINERS_PREFIX + env_name + '_network'
    try:
        network = Client.get_instance().networks.get(network_name)
    except docker.errors.ImageNotFound:
        click.echo(f'Network {network_name} not found, exiting...')
        raise

    for c in network.containers:
        network.disconnect(c)

    network.remove()
Ejemplo n.º 11
0
def _export(image_name, output):
    click.echo(f'Saving image {image_name} to {output}...')

    try:
        image = Client.get_instance().images.get(image_name)
    except docker.errors.ImageNotFound:
        raise

    output = output or f'{image_name}.tar.gz'
    with open(output, 'wb') as fout:
        for chunk in image.save(named=True):
            fout.write(chunk)

    click.echo(f'Image {image_name} saved to {output}!')
Ejemplo n.º 12
0
    def _with_mapped_ports(cls, container, ports, detach):
        if ports:
            port_mappers_containers_names = cls._run_port_mapper(
                container, ports)
        else:
            port_mappers_containers_names = []

        yield

        if detach:
            return

        for container_name in port_mappers_containers_names:
            container = Client.get_instance().containers.get(container_name)
            container.stop()
Ejemplo n.º 13
0
def create(name, project_dir, version):
    version = version or 'latest'
    click.echo(f'Creating environment {name} with python version {version}...')
    image_name = f'python:{version}'

    client = Client.get_instance()
    try:
        image = client.images.get(image_name)
    except docker.errors.ImageNotFound:
        click.echo(f'Image {image_name} not found, pulling...')
        image = client.images.pull('python', tag=version)

    create_network(name)
    create_env(image, name, project_dir)

    click.echo(f'Environment {name} with python version {version} created!')
Ejemplo n.º 14
0
def remove(name):
    click.echo(f'Removing environment {name}...')
    try:
        container = Client.get_instance().containers.get(
            definitions.CONTAINERS_PREFIX + name)
    except docker.errors.NotFound:
        click.echo(f'Environment {name} not found, exiting...')
        raise

    kwargs = {
        'force': True,
    }
    container.remove(**kwargs)
    delete_network(name)
    StateConfig.get_instance().remove_from_conf(definitions.CONTAINERS_PREFIX +
                                                name)
    click.echo(f'Environment {name} removed!')
Ejemplo n.º 15
0
def list_environments():
    click.echo(f'Listing environments...')
    kwargs = {
        'all': True,
    }
    containers = Client.get_instance().containers.list(kwargs)

    current_env = StateConfig.get_current_env()
    envs = []
    for c in containers:
        if not c.name.startswith(definitions.CONTAINERS_PREFIX):
            continue

        env_name = c.name[len(definitions.CONTAINERS_PREFIX):]
        prefix = '* ' if env_name == current_env else '  '
        envs.append(f'{prefix}{env_name}')

    click.echo('\n'.join(envs))
    click.echo(f'Environments listed!')
Ejemplo n.º 16
0
def _commit(name, current_env):
    click.echo(f'Saving environment {current_env} as image...')
    try:
        container = Client.get_instance().containers.get(
            definitions.CONTAINERS_PREFIX + current_env)
    except docker.errors.ImageNotFound:
        click.echo(f'Container {current_env} not found, exiting...')
        raise

    if not name:
        repository = f'{definitions.CONTAINERS_PREFIX + current_env}'
        tag = 'latest'
    else:
        repository, tag = name.split(':')

    container.commit(repository=repository, tag=tag)

    image_name = f'{repository}:{tag}'
    click.echo(f'Environment {current_env} saved as image {image_name}!')
    return image_name
Ejemplo n.º 17
0
 def _remove_port_mappers(self, env_name):
     prefix = definitions.CONTAINERS_PREFIX + env_name + '_port_mapper_'
     for c in Client.get_instance().containers.list(all=True):
         if c.name.startswith(prefix):
             c.remove(force=True)
Ejemplo n.º 18
0
def create_network(env_name):
    network_name = definitions.CONTAINERS_PREFIX + env_name + '_network'
    Client.get_instance().networks.create(network_name, check_duplicate=True)