Ejemplo n.º 1
0
def web_command(command,
                ro=None,
                rw=None,
                links=None,
                image='datacats/web',
                volumes_from=None,
                commit=False,
                clean_up=False,
                stream_output=None,
                entrypoint=None):
    """
    Run a single command in a web image optionally preloaded with the ckan
    source and virtual envrionment.

    :param command: command to execute
    :param ro: {localdir: binddir} dict for read-only volumes
    :param rw: {localdir: binddir} dict for read-write volumes
    :param links: links passed to start
    :param image: docker image name to use
    :param volumes_from:
    :param commit: True to create a new image based on result
    :param clean_up: True to remove container even on error
    :param stream_output: file to write stderr+stdout from command
    :param entrypoint: override entrypoint (script that runs command)

    :returns: image id if commit=True
    """
    binds = ro_rw_to_binds(ro, rw)
    c = _get_docker().create_container(image=image,
                                       command=command,
                                       volumes=binds_to_volumes(binds),
                                       detach=False,
                                       host_config=HostConfig(
                                           version=MINIMUM_API_VERSION,
                                           binds=binds,
                                           links=links,
                                           volumes_from=volumes_from),
                                       entrypoint=entrypoint)
    _get_docker().start(container=c['Id'])
    if stream_output:
        for output in _get_docker().attach(c['Id'],
                                           stdout=True,
                                           stderr=True,
                                           stream=True):
            stream_output.write(output)
    if _get_docker().wait(c['Id']):
        # Before the (potential) cleanup, grab the logs!
        logs = _get_docker().logs(c['Id'])

        if clean_up:
            remove_container(c['Id'])
        raise WebCommandError(command, c['Id'][:12], logs)
    if commit:
        rval = _get_docker().commit(c['Id'])
    if not remove_container(c['Id']):
        # circle ci doesn't let us remove containers, quiet the warnings
        if not environ.get('CIRCLECI', False):
            warn('failed to remove container: {0}'.format(c['Id']))
    if commit:
        return rval['Id']
Ejemplo n.º 2
0
    def run_config_init(self):
        workdir = os.getcwd()
        image = f"gluufederation/config-init:{self.settings['CONFIG_INIT_VERSION']}"

        volumes = [
            f"{workdir}/{CONFIG_DIR}:/app/db/",
            f"{workdir}/vault_role_id.txt:/etc/certs/vault_role_id",
            f"{workdir}/vault_secret_id.txt:/etc/certs/vault_secret_id",
        ]

        gen_file = f"{workdir}/generate.json"
        if os.path.isfile(gen_file):
            volumes.append(f"{gen_file}:/app/db/generate.json")

        with self.top_level_cmd() as tlc:
            retry = 0
            while retry < 3:
                try:
                    if not tlc.project.client.images(name=image):
                        print(
                            f"{self.settings['CONFIG_INIT_VERSION']}: Pulling from gluufederation/config-init"
                        )
                        tlc.project.client.pull(image)
                        break
                except (requests.exceptions.Timeout,
                        docker.errors.APIError) as exc:
                    print(f"[W] Unable to get {image}; reason={exc}; "
                          "retrying in 10 seconds")
                time.sleep(10)
                retry += 1

            cid = None
            try:
                cid = tlc.project.client.create_container(
                    image=
                    f"gluufederation/config-init:{self.settings['CONFIG_INIT_VERSION']}",
                    name="config-init",
                    command="load",
                    environment={
                        "GLUU_CONFIG_CONSUL_HOST": "consul",
                        "GLUU_SECRET_VAULT_HOST": "vault",
                    },
                    host_config=HostConfig(
                        version="1.25",
                        network_mode=self.network_name,
                        binds=volumes,
                    ),
                ).get("Id")

                tlc.project.client.start(cid)
                for log in tlc.project.client.logs(cid, stream=True):
                    print(log.decode().strip())
            except Exception:
                raise
            finally:
                if cid:
                    tlc.project.client.remove_container(cid, force=True)
Ejemplo n.º 3
0
def run_container(name,
                  image,
                  command=None,
                  environment=None,
                  ro=None,
                  rw=None,
                  links=None,
                  detach=True,
                  volumes_from=None,
                  port_bindings=None,
                  log_syslog=False):
    """
    Wrapper for docker create_container, start calls

    :param log_syslog: bool flag to redirect container's logs to host's syslog

    :returns: container info dict or None if container couldn't be created

    Raises PortAllocatedError if container couldn't start on the
    requested port.
    """
    binds = ro_rw_to_binds(ro, rw)
    log_config = LogConfig(type=LogConfig.types.JSON)
    if log_syslog:
        log_config = LogConfig(type=LogConfig.types.SYSLOG,
                               config={'syslog-tag': name})

    host_config = HostConfig(version=MINIMUM_API_VERSION,
                             binds=binds,
                             log_config=log_config,
                             links=links,
                             volumes_from=volumes_from,
                             port_bindings=port_bindings)

    c = _get_docker().create_container(
        name=name,
        image=image,
        command=command,
        environment=environment,
        volumes=binds_to_volumes(binds),
        detach=detach,
        stdin_open=False,
        tty=False,
        ports=list(port_bindings) if port_bindings else None,
        host_config=host_config)
    try:
        _get_docker().start(container=c['Id'])
    except APIError as e:
        if 'address already in use' in e.explanation:
            try:
                _get_docker().remove_container(name, force=True)
            except APIError:
                pass
            raise PortAllocatedError()
        raise
    return c
Ejemplo n.º 4
0
def create_host_config(docker_api, resource_limits, binds, port_bindings):
    resource_limits = resource_limits or {}
    privileged = get_ship_config().get('privileged', 'false').lower() == 'true'
    params = {
        'privileged': privileged,
        'publish_all_ports': True,
        'binds': binds,
        'port_bindings': port_bindings,
        'mem_limit': resource_limits.get('memory'),
        'memswap_limit': resource_limits.get('memory_swap'),
        'cgroup_parent': resource_limits.get('cgroup_parent'),
        'cpu_shares': resource_limits.get('cpu_shares'),
    }

    return HostConfig(DOCKER_API_VERSION, **params)
Ejemplo n.º 5
0
    def _get_container_host_config(self,
                                   override_options,
                                   one_off=False,
                                   intermediate_container=None):
        options = dict(self.options, **override_options)
        port_bindings = build_port_bindings(options.get('ports') or [])

        volume_bindings = dict(
            build_volume_binding(parse_volume_spec(volume))
            for volume in options.get('volumes') or [] if ':' in volume)

        privileged = options.get('privileged', False)
        cap_add = options.get('cap_add', None)
        cap_drop = options.get('cap_drop', None)
        pid = options.get('pid', None)

        dns = options.get('dns', None)
        if isinstance(dns, six.string_types):
            dns = [dns]

        dns_search = options.get('dns_search', None)
        if isinstance(dns_search, six.string_types):
            dns_search = [dns_search]

        restart = parse_restart_spec(options.get('restart', None))

        extra_hosts = build_extra_hosts(options.get('extra_hosts', None))

        return HostConfig(
            version='1.21',
            links=self._get_links(link_to_self=one_off),
            port_bindings=port_bindings,
            binds=volume_bindings,
            volumes_from=self._get_volumes_from(intermediate_container),
            privileged=privileged,
            network_mode=self._get_net(),
            dns=dns,
            dns_search=dns_search,
            restart_policy=restart,
            cap_add=cap_add,
            cap_drop=cap_drop,
            extra_hosts=extra_hosts,
            pid_mode=pid)
Ejemplo n.º 6
0
    def recreate_container(self, container, **override_options):
        """Recreate a container. An intermediate container is created so that
        the new container has the same name, while still supporting
        `volumes-from` the original container.
        """
        try:
            container.stop()
        except APIError as e:
            if (e.response.status_code == 500
                    and e.explanation
                    and 'no such process' in str(e.explanation)):
                pass
            else:
                raise

        intermediate_container = Container.create(
            self.client,
            image=container.image,
            entrypoint=['/bin/echo'],
            command=[],
            detach=True,
            host_config=HostConfig(volumes_from=[container.id]),
        )
        intermediate_container.start()
        intermediate_container.wait()
        container.remove()

        options = dict(override_options)
        new_container = self.create_container(
            do_build=False,
            intermediate_container=intermediate_container,
            **options
        )
        self.start_container(new_container)

        intermediate_container.remove()

        return (intermediate_container, new_container)
Ejemplo n.º 7
0
def create_host_config(*args, **kwargs):
    return HostConfig(*args, **kwargs)