Exemple #1
0
    def determine_image(self,
                        image,
                        overview,
                        configuration,
                        needs_image=True):
        """Complain if we don't have an image"""
        images = configuration["images"]

        available = None
        available = images.keys()

        if needs_image:
            if not image:
                info = {}
                if available:
                    info["available"] = list(available)
                raise BadOption(
                    "Please use --image to specify an image to run /bin/bash in",
                    **info)

            if image not in images:
                raise BadOption("No such image",
                                wanted=image,
                                available=list(images.keys()))

        return images
Exemple #2
0
def tag(collector, image, artifact, **kwargs):
    """Tag an image!"""
    if artifact in (None, "", NotSpecified):
        raise BadOption("Please specify a tag using the artifact option")

    if image.image_index in (None, "", NotSpecified):
        raise BadOption("Please specify an image with an image_index option")

    tag = image.image_name
    if image.tag is NotSpecified:
        tag = "{0}:latest".format(tag)

    images = image.harpoon.docker_context.images()
    current_tags = chain.from_iterable(image_conf["RepoTags"]
                                       for image_conf in images)
    if tag not in current_tags:
        raise BadOption(
            "Please build or pull the image down to your local cache before tagging it"
        )

    for image_conf in images:
        if tag in image_conf["RepoTags"]:
            image_id = image_conf["Id"]
            break

    log.info("Tagging {0} ({1}) as {2}".format(image_id, image.image_name,
                                               artifact))
    image.harpoon.docker_context.tag(image_id,
                                     repository=image.image_name,
                                     tag=artifact,
                                     force=True)

    image.tag = artifact
    Syncer().push(image)
Exemple #3
0
    def find_image(self, image, configuration):
        """Complain if we don't have an image"""
        images = configuration["images"]
        available = list(images.keys())

        if not image:
            info = {}
            if available:
                info["available"] = available
            raise BadOption("Please use --image to specify an image", **info)

        if image not in images:
            raise BadOption("No such image", wanted=image, available=available)
Exemple #4
0
    def parse_args(self, argv=None):
        """Split the args into <args> -- <extra_args> and run <args> through our argparse.ArgumentParser"""
        if argv is None:
            argv = sys.argv[1:]

        argv = list(argv)
        args = []
        extras = None
        default_task = NotSpecified
        default_image = NotSpecified

        if argv:
            if not argv[0].startswith("-"):
                default_task = argv[0]
                argv.pop(0)

            if argv and not argv[0].startswith("-"):
                default_image = argv[0]
                argv.pop(0)

        while argv:
            nxt = argv.pop(0)
            if extras is not None:
                extras.append(nxt)
            elif nxt == "--":
                extras = []
            else:
                args.append(nxt)

        other_args = ""
        if extras:
            other_args = " ".join(extras)

        parser = self.make_parser(default_task=default_task,
                                  default_image=default_image)
        args = parser.parse_args(args)
        if default_task is not NotSpecified and args.harpoon_chosen_task != default_task:
            raise BadOption(
                "Please don't specify task as a positional argument and as a --task option",
                positional=default_task,
                kwarg=args.task)
        if default_image is not NotSpecified and args.harpoon_chosen_image != default_image:
            raise BadOption(
                "Please don't specify image as a positional argument and as a --image option",
                positional=default_image,
                kwargs=args.image)

        return args, other_args
Exemple #5
0
 def validate(self, meta, val):
     if ' ' not in val:
         raise BadOption(
             "Expected string to have a space (<ACTION> <COMMAND>)",
             meta=meta,
             got=val)
     return val
Exemple #6
0
def pull(overview, configuration, images, image, **kwargs):
    """Pull an image"""
    if not image.image_index:
        raise BadOption(
            "The chosen image does not have a image_index configuration",
            wanted=image.name)
    Syncer().pull(image, ignore_missing=image.harpoon.ignore_missing)
Exemple #7
0
def push(overview, configuration, images, image):
    """Push an image"""
    if not image.image_index:
        raise BadOption(
            "The chosen image does not have a image_index configuration",
            wanted=image.name)
    Builder().make_image(image, images)
    Syncer().push(image)
Exemple #8
0
def push(collector, image, **kwargs):
    """Push an image"""
    if not image.image_index:
        raise BadOption(
            "The chosen image does not have a image_index configuration",
            wanted=image.name)
    Builder().make_image(image,
                         collector.configuration["images"],
                         pushing=True)
    Syncer().push(image)
Exemple #9
0
    def find_missing_env(self):
        """Find any missing environment variables"""
        missing = []
        for e in self.env:
            if e.default_val is None and e.set_val is None:
                if e.env_name not in os.environ:
                    missing.append(e.env_name)

        if missing:
            raise BadOption(
                "Some environment variables aren't in the current environment",
                missing=missing)
Exemple #10
0
def pull(collector, image, **kwargs):
    """Pull an image"""
    if not image.image_index:
        raise BadOption(
            "The chosen image does not have a image_index configuration",
            wanted=image.name)
    tag = kwargs["artifact"]
    if tag is NotSpecified:
        collector.configuration["harpoon"].tag
    if tag is not NotSpecified:
        image.tag = tag
        log.info("Pulling tag: %s", tag)
    Syncer().pull(image, ignore_missing=image.harpoon.ignore_missing)
Exemple #11
0
def push(collector, image, **kwargs):
    """Push an image"""
    if not image.image_index:
        raise BadOption(
            "The chosen image does not have a image_index configuration",
            wanted=image.name)
    tag = kwargs["artifact"]
    if tag is NotSpecified:
        tag = collector.configuration["harpoon"].tag
    if tag is not NotSpecified:
        image.tag = tag
    Builder().make_image(image,
                         collector.configuration["images"],
                         pushing=True)
    Syncer().push(image)
Exemple #12
0
    def the_context(self, content, silent_build=False):
        """Return either a file with the content written to it, or a whole new context tar"""
        if isinstance(content, six.string_types):
            with a_temp_file() as fle:
                fle.write(content.encode('utf-8'))
                fle.seek(0)
                yield fle
        elif "context" in content:
            with ContextBuilder().make_context(content["context"], silent_build=silent_build) as wrapper:
                wrapper.close()
                yield wrapper.tmpfile
        elif "image" in content:
            from harpoon.ship.runner import Runner
            with a_temp_file() as fle:
                content["conf"].command = "yes"
                with Runner()._run_container(content["conf"], content["images"], detach=True, delete_anyway=True):
                    try:
                        strm, stat = content["docker_context"].get_archive(content["conf"].container_id, content["path"])
                    except docker.errors.NotFound:
                        raise BadOption("Trying to get something from an image that don't exist!", path=content["path"], image=content["conf"].image_name)
                    else:
                        log.debug(stat)

                        fo = BytesIO(strm.read())
                        tf = tarfile.TarFile(fileobj=fo)

                        if tf.firstmember.isdir():
                            tf2 = tarfile.TarFile(fileobj=fle, mode='w')
                            name = tf.firstmember.name
                            for member in tf.getmembers()[1:]:
                                member.name = member.name[len(name)+1:]
                                if member.issym():
                                    with tempfile.NamedTemporaryFile() as symfle:
                                        os.remove(symfle.name)
                                        os.symlink(member.linkpath, symfle.name)
                                        tf2.addfile(member, fileobj=symfle)
                                elif not member.isdir():
                                    tf2.addfile(member, fileobj=tf.extractfile(member.name))
                            tf2.close()
                        else:
                            fle.write(tf.extractfile(tf.firstmember.name).read())

                        tf.close()
                        log.info("Got '{0}' from {1} for context".format(content["path"], content["conf"].container_id))

                fle.seek(0)
                yield fle
Exemple #13
0
    def create_container(self, conf, detach, tty):
        """Create a single container"""

        name = conf.name
        image_name = conf.image_name
        container_name = conf.container_name

        with conf.assumed_role():
            env = dict(e.pair for e in conf.env)

        links = [link.pair for link in conf.links]
        binds = conf.volumes.binds
        command = conf.formatted_command
        volume_names = conf.volumes.volume_names
        volumes_from = list(conf.volumes.share_with_names)
        no_tty_option = conf.no_tty_option

        ports = [p.container_port.port_pair for p in conf.ports]
        port_bindings = self.exposed(conf.ports)

        uncreated = []
        for name in binds:
            if not os.path.exists(name):
                log.info("Making volume for mounting\tvolume=%s", name)
                try:
                    os.makedirs(name)
                except OSError as error:
                    uncreated.append((name, error))
        if uncreated:
            raise BadOption("Failed to create some volumes on the host",
                            uncreated=uncreated)

        log.info(
            "Creating container from %s\timage=%s\tcontainer_name=%s\ttty=%s",
            image_name, name, container_name, tty)
        if binds:
            log.info("\tUsing volumes\tvolumes=%s", volume_names)
        if env:
            log.info("\tUsing environment\tenv=%s", sorted(env.keys()))
        if links:
            log.info("\tLinks: %s", links)
        if ports:
            log.info("\tUsing ports\tports=%s", ports)
        if port_bindings:
            log.info("\tPort bindings: %s", port_bindings)
        if volumes_from:
            log.info("\tVolumes from: %s", volumes_from)

        host_config = conf.harpoon.docker_context.create_host_config(
            links=links,
            binds=binds,
            volumes_from=volumes_from,
            port_bindings=port_bindings,
            devices=conf.devices,
            lxc_conf=conf.lxc_conf,
            privileged=conf.privileged,
            restart_policy=conf.restart_policy,
            dns=conf.network.dns,
            dns_search=conf.network.dns_search,
            extra_hosts=conf.network.extra_hosts,
            network_mode=conf.network.network_mode,
            publish_all_ports=conf.network.publish_all_ports,
            cap_add=conf.cpu.cap_add,
            cap_drop=conf.cpu.cap_drop,
            mem_limit=conf.cpu.mem_limit,
            memswap_limit=conf.cpu.memswap_limit,
            ulimits=conf.ulimits,
            read_only=conf.read_only_rootfs,
            log_config=conf.log_config,
            security_opt=conf.security_opt,
            **conf.other_options.host_config)

        container_id = conf.harpoon.docker_context.create_container(
            image_name,
            name=container_name,
            detach=detach,
            command=command,
            volumes=volume_names,
            environment=env,
            tty=False if no_tty_option else tty,
            user=conf.user,
            ports=ports,
            stdin_open=tty,
            dns=conf.network.dns,
            hostname=conf.network.hostname,
            domainname=conf.network.domainname,
            network_disabled=conf.network.disabled,
            cpuset=conf.cpu.cpuset,
            cpu_shares=conf.cpu.cpu_shares,
            host_config=host_config,
            **conf.other_options.create)

        if isinstance(container_id, dict):
            if "errorDetail" in container_id:
                raise BadImage("Failed to create container",
                               image=name,
                               error=container_id["errorDetail"])
            container_id = container_id["Id"]

        return container_id