Beispiel #1
0
    def pull_image(self, image, remote_image_obj, **kwargs):
        assert(isinstance(remote_image_obj, Image))
        debug = kwargs.get('debug', False)
        if image.startswith("dockertar:"):
            path = image.replace("dockertar:", "", 1)
            with open(path, 'rb') as f:
                self.d.load_image(data=f)
            return 0
        fq_name = remote_image_obj.fq_name
        local_image = self.has_image(image)
        if local_image is not None:
            if self.already_has_image(local_image, remote_image_obj):
                raise util.ImageAlreadyExists(image)
        registry, _, _, tag, _ = util.Decompose(fq_name).all
        image = "docker-daemon:{}".format(fq_name)
        if not image.endswith(tag):
            image += ":{}".format(tag)
        if '@sha256:' in image:
            image = image.replace("@sha256:", ":")

        src_creds = kwargs.get('src_creds')
        insecure = True if util.is_insecure_registry(self.d.info()['RegistryConfig'], registry) else False
        trust = Trust()
        trust.discover_sigstore(fq_name)
        util.write_out("Pulling {} ...".format(fq_name))
        util.skopeo_copy("docker://{}".format(fq_name), image, debug=debug, insecure=insecure,
                         policy_filename=trust.policy_filename, src_creds=src_creds)
        return 0
Beispiel #2
0
    def pull_image(self, image, remote_image_obj, **kwargs):
        """
        Pulls an image to the backend
        :param image:
        :param pull_args:
        :return:
        """
        debug = kwargs.get('debug', False)
        fq_name = remote_image_obj.fq_name
        registry, _, _, tag, _ = util.Decompose(fq_name).all
        if not image.endswith(tag):
            image += ":{}".format(tag)
        if '@sha256:' in image:
            image = image.replace("@sha256:", ":")

        insecure = False
        registries_config = util.load_registries_from_yaml()
        if "insecure_registries" in registries_config:
            if registry in registries_config['insecure_registries']:
                insecure = True
        source = "docker://{}".format(image)
        dest = "containers-storage:{}".format(image)
        trust = Trust()
        trust.discover_sigstore(fq_name)
        util.write_out("Pulling {} ...".format(fq_name))
        util.skopeo_copy(source, dest, debug=debug, insecure=insecure, policy_filename=trust.policy_filename)
        return 0
Beispiel #3
0
 def pull_image(self, image, **kwargs):
     debug = kwargs.get("debug", False)
     if image.startswith("dockertar:"):
         path = image.replace("dockertar:", "", 1)
         with open(path, "rb") as f:
             self.d.load_image(data=f)
         return 0
     remote_image = self.make_remote_image(image)
     fq_name = remote_image.fq_name
     local_image = self.has_image(image)
     if local_image is not None:
         if self.already_has_image(local_image, remote_image):
             raise ValueError("Latest version of {} already present.".format(image))
     registry, _, _, tag, _ = util.Decompose(fq_name).all
     image = "docker-daemon:{}".format(image)
     if not image.endswith(tag):
         image += ":{}".format(tag)
     insecure = (
         True if util.is_insecure_registry(self.d.info()["RegistryConfig"], util.strip_port(registry)) else False
     )
     trust = Trust()
     trust.discover_sigstore(fq_name)
     util.write_out("Pulling {} ...".format(fq_name))
     util.skopeo_copy(
         "docker://{}".format(fq_name), image, debug=debug, insecure=insecure, policy_filename=trust.policy_filename
     )
     return 0
Beispiel #4
0
    def _running(self, con_obj, args, atomic):
        requested_image = self.has_image(args.image)
        if requested_image is not None and con_obj.image != requested_image.id:
            requested_image_fq_name = requested_image.fq_name
            raise AtomicError("Warning: container '{}' already points to {}\nRun 'atomic run {}' to run "
                                          "the existing container.\nRun 'atomic run --replace '{}' to replace "
                                          "it".format(con_obj.name,
                                                      con_obj.original_structure['Config']['Image'],
                                                      con_obj.name,
                                                      requested_image_fq_name))
        if con_obj.interactive:
            container_command = con_obj.command if not args.command else args.command
            container_command = container_command if not isinstance(container_command, list) else " ".join(container_command)
            cmd = [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] + container_command.split()
            if args.display:
                return atomic.display(" ".join(cmd))
            else:
                return util.check_call(cmd, stderr=DEVNULL)
        else:
            command = con_obj.command if not args.command else args.command
            try:
                cmd = [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] + command
            except TypeError:
                cmd = [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] + command.split()

            if args.command:
                if args.display:
                    return util.write_out(" ".join(cmd))
                else:
                    return util.check_call(cmd, stderr=DEVNULL)
            else:
                if not args.display:
                    util.write_out("Container is running")
Beispiel #5
0
 def replace_existing_container(self, _iobject, _requested_image, _args):
     if _args.debug:
         util.write_out("Removing the container {} and running with {}".format(_iobject.name,
                                                                               _requested_image.fq_name))
     self.delete_container(_iobject.id, force=True)
     _iobject = _requested_image
     if _args.command:
         _iobject.user_command = _args.command
     return _iobject
Beispiel #6
0
 def update(self):
     if self.args.debug:
         write_out(str(self.args))
     beu = BackendUtils()
     try:
         be, img_obj = beu.get_backend_and_image_obj(self.image, str_preferred_backend=self.args.storage or storage, required=True if self.args.storage else False)
         input_name = img_obj.input_name
     except ValueError:
         raise ValueError("{} not found locally.  Unable to update".format(self.image))
     be.update(input_name, debug=self.args.debug, force=self.args.force, image_object=img_obj)
     return 0
Beispiel #7
0
 def _running(self, con_obj, args, atomic):
     if con_obj.interactive:
         cmd = [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name, con_obj.command]
         if args.display:
             return atomic.display(cmd)
         else:
             return util.check_call(cmd, stderr=DEVNULL)
     else:
         cmd = [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] + con_obj.command
         if args.command:
             if args.display:
                 return util.write_out(" ".join(cmd))
             else:
                 return util.check_call(cmd, stderr=DEVNULL)
         else:
             if not args.display:
                 util.write_out("Container is running")
Beispiel #8
0
    def pull_image(self, image, pull_args):
        # Add this when atomic registry is incorporated.
        # if self.args.reg_type == "atomic":
        #     pull_uri = 'atomic:'
        # else:
        #     pull_uri = 'docker://'
        img_obj = self._make_remote_image(image)
        fq_name = img_obj.fq_name
        insecure = True if util.is_insecure_registry(self.d.info()['RegistryConfig'], util.strip_port(img_obj.registry)) else False

        # This needs to be re-enabled with Aaron's help
        trust = Trust()
        trust.set_args(pull_args)
        trust.discover_sigstore(fq_name)

        util.write_out("Pulling {} ...".format(fq_name))
        util.skopeo_copy("docker://{}".format(fq_name),
                         "docker-daemon:{}".format(image),
                         debug=pull_args.debug, insecure=insecure,
                         policy_filename=pull_args.policy_filename)
Beispiel #9
0
    def _start(self, con_obj, args, atomic):
        exec_error = "Failed to execute the command inside the existing container. In some situations " \
                     "this can happen because the entry point command of the container only runs for " \
                     "a short time. You might want to replace the container by executing your " \
                     "command with --replace. Note any updates to the existing container will be lost"

        if con_obj.interactive:
            if args.command:
                util.check_call([atomic.docker_binary(), "start", con_obj.name], stderr=DEVNULL)
                container_command = args.command if isinstance(args.command, list) else args.command.split()
                try:
                    return util.check_call([atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] + container_command)
                except CalledProcessError as e:
                    if args.debug:
                        util.write_out(str(e))
                    raise AtomicError(exec_error)


            else:
                return util.check_call(
                    [atomic.docker_binary(), "start", "-i", "-a", con_obj.name],
                    stderr=DEVNULL)
        else:
            if args.command:
                util.check_call(
                    [atomic.docker_binary(), "start", con_obj.name],
                    stderr=DEVNULL)
                try:
                    return util.check_call(
                        [atomic.docker_binary(), "exec", "-t", "-i", con_obj.name] +
                        con_obj.command)
                except CalledProcessError as e:
                    if args.debug:
                        util.write_out(str(e))
                    raise AtomicError(exec_error)

            else:
                return util.check_call(
                    [atomic.docker_binary(), "start", con_obj.name],
                    stderr=DEVNULL)
Beispiel #10
0
    def check_args(cmd):
        found_sec_arg = False
        security_args = {
            "--privileged": "This container runs without separation and should be "
            "considered the same as root on your system.",
            "--cap-add": "Adding capabilities to your container could allow processes "
            "from the container to break out onto your host system.",
            "--security-opt label:disable": "Disabling label separation turns off tools like SELinux and "
            "could allow processes from the container to break out onto "
            "your host system.",
            "--net=host": "Processes in this container can listen to ports (and "
            "possibly rawip traffic) on the host's network.",
            "--pid=host": "Processes in this container can see and interact with all "
            "processes on the host and disables SELinux within the "
            "container.",
            "--ipc=host": "Processes in this container can see and possibly interact "
            "with all semaphores and shared memory segments on the host "
            "as well as disables SELinux within the container.",
        }

        for sec_arg in security_args:
            if sec_arg in cmd:
                if not found_sec_arg:
                    util.write_out("\nThis container uses privileged " "security switches:")
                util.write_out("\n\033[1mINFO: {}\033[0m " "\n{}{}".format(sec_arg, " " * 6, security_args[sec_arg]))
                found_sec_arg = True
        if found_sec_arg:
            util.write_out(
                "\nFor more information on these switches and their "
                "security implications, consult the manpage for "
                "'docker run'.\n"
            )
Beispiel #11
0
    def check_args(cmd):
        found_sec_arg = False
        security_args = {
            '--privileged':
            'This container runs without separation and should be '
            'considered the same as root on your system.',
            '--cap-add':
            'Adding capabilities to your container could allow processes '
            'from the container to break out onto your host system.',
            '--security-opt label:disable':
            'Disabling label separation turns off tools like SELinux and '
            'could allow processes from the container to break out onto '
            'your host system.',
            '--security-opt label=disable':
            'Disabling label separation turns off tools like SELinux and '
            'could allow processes from the container to break out onto '
            'your host system.',
            '--net=host':
            'Processes in this container can listen to ports (and '
            'possibly rawip traffic) on the host\'s network.',
            '--pid=host':
            'Processes in this container can see and interact with all '
            'processes on the host and disables SELinux within the '
            'container.',
            '--ipc=host':
            'Processes in this container can see and possibly interact '
            'with all semaphores and shared memory segments on the host '
            'as well as disables SELinux within the container.'
        }

        for sec_arg in security_args:
            if sec_arg in cmd:
                if not found_sec_arg:
                    util.write_out("\nThis container uses privileged "
                                   "security switches:")
                util.write_out("\n\033[1mINFO: {}\033[0m "
                               "\n{}{}".format(sec_arg, " " * 6,
                                               security_args[sec_arg]))
                found_sec_arg = True
        if found_sec_arg:
            util.write_out(
                "\nFor more information on these switches and their "
                "security implications, consult the manpage for "
                "'docker run'.\n")
Beispiel #12
0
def print_scan_list(all_scanners):
    if len(all_scanners) == 0:
        util.write_out("There are no scanners configured for this system.")
        sys.exit(0)
    default_scanner = (util.get_atomic_config())['default_scanner']
    if default_scanner is None:
        default_scanner = ''
    for scanner in all_scanners:
        scanner_name = scanner['scanner_name']
        df = '* ' if scanner_name == default_scanner else ''
        default_scan_type = scanner.get('default_scan')
        if default_scan_type is None:
            raise ValueError("Invalid configuration file: At least one scan type must be "
                                 "declared as the default for {}.".format(scanner_name))
        util.write_out("Scanner: {} {}".format(scanner_name, df))
        util.write_out("{}Image Name: {}".format(" " * 2, scanner['image_name']))
        for scan_type in scanner['scans']:
            df = '* ' if default_scan_type == scan_type['name'] else ''
            util.write_out("{}Scan type: {} {}".format(" " * 5, scan_type['name'], df))
            util.write_out("{}Description: {}\n".format(" " * 5, scan_type['description']))
        util.write_out("\n* denotes defaults")
        sys.exit(0)
Beispiel #13
0
    def run(self, iobject, **kwargs):
        def add_string_or_list_to_list(list_item, value):
            if not isinstance(value, list):
                value = value.split()
            list_item += value
            return list_item

        atomic = kwargs.get('atomic', None)
        args = kwargs.get('args')
        # atomic must be an instance of Atomic
        # args must be a argparse Namespace
        assert(isinstance(atomic, Atomic))
        # The object is a container
        # If container exists and not started, start it
        # If container exists and is started, execute command inside it (docker exec)
        # If container doesn't exist, create one and start it
        if args.command:
            iobject.user_command = args.command
        if isinstance(iobject, Container):
            latest_image = self.inspect_image(iobject.image_name)
            if latest_image.id != iobject.image:
                util.write_out("The '{}' container is using an older version of the installed\n'{}' container image. If "
                               "you wish to use the newer image,\nyou must either create a new container with a "
                               "new name or\nuninstall the '{}' container. \n\n# atomic uninstall --name "
                               "{} {}\n\nand create new container on the {} image.\n\n# atomic update --force "
                               "{}s\n\n removes all containers based on an "
                               "image.".format(iobject.name, iobject.image_name, iobject.name, iobject.name,
                                               iobject.image_name, iobject.image_name, iobject.image_name))

            requested_image = self.has_image(args.image)
            if requested_image is None:
                requested_image = self.has_image(iobject.image)

            if iobject.running:
                if args.replace:
                    iobject = self.replace_existing_container(iobject, requested_image, args)
                    return self.run(iobject, args=args, atomic=atomic)
                return self._running(iobject, args, atomic)
            else:
                # Container with the name exists
                image_id = iobject.image
                if requested_image.id != image_id:
                    if args.replace:
                        iobject = self.replace_existing_container(iobject, requested_image, args)
                    else:
                        try:
                            requested_image_fq_name = requested_image.fq_name
                        except RegistryInspectError:
                            requested_image_fq_name = args.image
                        raise AtomicError("Warning: container '{}' already points to {}\nRun 'atomic run {}' to run "
                                          "the existing container.\nRun 'atomic run --replace '{}' to replace "
                                          "it".format(iobject.name,
                                                      iobject.original_structure['Config']['Image'],
                                                      iobject.name,
                                                      requested_image_fq_name))
                else:
                    if args.replace:
                        iobject = self.replace_existing_container(iobject, requested_image, args)
                    else:
                        return self._start(iobject, args, atomic)

        if iobject.get_label('INSTALL') and not args.ignore and not util.InstallData.image_installed(iobject):
            raise ValueError("The image '{}' appears to have not been installed and has an INSTALL label.  You "
                             "should install this image first.  Re-run with --ignore to bypass this "
                             "error.".format(iobject.name or iobject.image))
        # The object is an image
        command = []
        if iobject.run_command:
            command = add_string_or_list_to_list(command, iobject.run_command)
            if iobject.user_command:
                command = add_string_or_list_to_list(command, iobject.user_command)
            opts_file = iobject.get_label("RUN_OPTS_FILE")
            if opts_file:
                opts_file = atomic.sub_env_strings("".join(opts_file))
                if opts_file.startswith("/"):
                    if os.path.isfile(opts_file):
                        try:
                            atomic.run_opts = open(opts_file, "r").read()
                        except IOError:
                            raise ValueError("Failed to read RUN_OPTS_FILE %s" % opts_file)
                else:
                    raise ValueError("Will not read RUN_OPTS_FILE %s: not absolute path" % opts_file)
        else:
            command += [atomic.docker_binary(), "run"]
            if os.isatty(0):
                command += ["-t"]
            if args.detach:
                command += ["-d"]
            command += atomic.SPC_ARGS if args.spc else atomic.RUN_ARGS
            if iobject.user_command:
                command = add_string_or_list_to_list(command, iobject.user_command)

        if len(command) > 0 and command[0] == "docker":
            command[0] = atomic.docker_binary()

        if iobject.cmd and not iobject.user_command and not iobject.run_command:
            cmd = iobject.cmd if isinstance(iobject.cmd, list) else iobject.cmd.split()
            command += cmd
        command = atomic.gen_cmd(command)
        command = atomic.sub_env_strings(command)
        atomic.display(command)
        if atomic.args.display:
            return

        if not atomic.args.quiet:
            self.check_args(command)
        return util.check_call(command, env=atomic.cmd_env())
Beispiel #14
0
 def prune(self):
     for iid in self.get_dangling_images():
         self.delete_image(iid, force=True)
         util.write_out("Removed dangling Image {}".format(iid))
     return 0
Beispiel #15
0
    def display_all_image_info(self):
        def get_col_lengths(_images):
            '''
            Determine the max length of the repository and tag names
            :param _images:
            :return: a set with len of repository and tag
            If there are no images, return 1, 1
            '''
            repo_tags = [y for x in _images if x.repotags for y in x.split_repotags]

            if repo_tags:
                return max([len(x[0]) for x in repo_tags]) + 2,\
                       max([len(x[1]) for x in repo_tags]) + 2
            else:
                return 1, 1

        if self.args.debug:
            util.write_out(str(self.args))

        _images = self._get_images()
        for i in _images:
            i.repo, i.tag = i.split_repotags[0]

        if self.args.filter:
            _images = [x for x in _images if self._filter_include_image(x)]

        if self.args.json:
            util.output_json(self.return_json(_images))
            return 0

        if len(_images) == 0:
            return

        _max_repo, _max_tag = get_col_lengths(_images)

        if self.args.truncate:
            _max_id = 14
        else:
            _max_id = 65
        col_out = "{0:2} {1:" + str(_max_repo) + "} {2:" + str(_max_tag) + \
                  "} {3:" + str(_max_id) + "} {4:18} {5:14} {6:10}"

        if self.args.heading and not self.args.quiet:
            util.write_out(col_out.format(" ",
                                          "REPOSITORY",
                                          "TAG",
                                          "IMAGE ID",
                                          "CREATED",
                                          "VIRTUAL SIZE",
                                          "TYPE"))
        for image in _images:
            if self.args.quiet:
                util.write_out(image.id)

            else:
                indicator = ""
                if image.is_dangling:
                    indicator += "*"
                elif image.used:
                    indicator += ">"
                if image.vulnerable:
                    space = " " if len(indicator) < 1 else ""
                    if util.is_python2:
                        indicator = indicator + self.skull + space
                    else:
                        indicator = indicator + str(self.skull, "utf-8") + space
                _id = image.short_id if self.args.truncate else image.id
                util.write_out(col_out.format(indicator, image.repo or "<none>", image.tag or "<none>", _id, image.timestamp,
                                              image.virtual_size, image.backend.backend))
        util.write_out("")
        return
Beispiel #16
0
 def dump_backends(self):
     backends = ''
     for i in self.available_backends:
         be = i()
         backends += "{}: Active, ".format(be.backend)
     write_out("Backends({})\n".format(backends))
Beispiel #17
0
 def message_backend_change(previous, new):
     write_out("\nNote: Switching from the '{}' backend to the '{}' backend based on the 'atomic.type' label in the "
               "image.  You can use --storage to override this behaviour.\n".format(previous, new))
Beispiel #18
0
    def display_all_image_info(self):
        def get_col_lengths(_images):
            '''
            Determine the max length of the repository and tag names
            :param _images:
            :return: a set with len of repository and tag
            If there are no images, return 1, 1
            '''
            repo_tags = [
                y for x in _images if x.repotags for y in x.split_repotags
            ]

            if repo_tags:
                return max([len(x[0]) for x in repo_tags]) + 2,\
                       max([len(x[1]) for x in repo_tags]) + 2
            else:
                return 1, 1

        if self.args.debug:
            util.write_out(str(self.args))

        _images = self._get_images()

        if self.args.json:
            util.output_json(self.return_json(_images))
            return 0

        if len(_images) == 0:
            return

        _max_repo, _max_tag = get_col_lengths(_images)

        if self.args.truncate:
            _max_id = 14
        else:
            _max_id = 65
        col_out = "{0:2} {1:" + str(_max_repo) + "} {2:" + str(_max_tag) + \
                  "} {3:" + str(_max_id) + "} {4:18} {5:14} {6:10}"

        if self.args.heading and not self.args.quiet:
            util.write_out(
                col_out.format(" ", "REPOSITORY", "TAG", "IMAGE ID", "CREATED",
                               "VIRTUAL SIZE", "TYPE"))
        for image in _images:
            if self.args.filter:
                if not self._filter_include_image(image):
                    continue
            if self.args.quiet:
                util.write_out(image.id)

            else:
                indicator = ""
                if image.is_dangling:
                    indicator += "*"
                elif image.used:
                    indicator += ">"
                if image.vulnerable:
                    space = " " if len(indicator) < 1 else ""
                    if util.is_python2:
                        indicator = indicator + self.skull + space
                    else:
                        indicator = indicator + str(self.skull,
                                                    "utf-8") + space
                repo, tag = image.split_repotags[0]
                _id = image.short_id if self.args.truncate else image.id
                util.write_out(
                    col_out.format(indicator, repo or "<none>", tag
                                   or "<none>", _id, image.timestamp,
                                   image.virtual_size, image.backend.backend))
        util.write_out("")
        return
Beispiel #19
0
def print_scan_list(all_scanners):
    if len(all_scanners) == 0:
        util.write_out("There are no scanners configured for this system.")
        sys.exit(0)
    default_scanner = (util.get_atomic_config())['default_scanner']
    if default_scanner is None:
        default_scanner = ''
    for scanner in all_scanners:
        scanner_name = scanner['scanner_name']
        df = '* ' if scanner_name == default_scanner else ''
        default_scan_type = scanner.get('default_scan')
        if default_scan_type is None:
            raise ValueError(
                "Invalid configuration file: At least one scan type must be "
                "declared as the default for {}.".format(scanner_name))
        util.write_out("Scanner: {} {}".format(scanner_name, df))
        util.write_out("{}Image Name: {}".format(" " * 2,
                                                 scanner['image_name']))
        for scan_type in scanner['scans']:
            df = '* ' if default_scan_type == scan_type['name'] else ''
            util.write_out("{}Scan type: {} {}".format(" " * 5,
                                                       scan_type['name'], df))
            util.write_out("{}Description: {}\n".format(
                " " * 5, scan_type['description']))
        util.write_out("\n* denotes defaults")
        sys.exit(0)
Beispiel #20
0
    def display_all_image_info(self):
        def get_col_lengths(_images):
            '''
            Determine the max length of the repository and tag names
            :param _images:
            :return: a set with len of repository and tag
            If there are no images, return 1, 1
            '''
            repo_tags = [[i["repo"], i["tag"]] for i in _images]
            if repo_tags:
                return max([len(x[0]) for x in repo_tags]) + 2,\
                       max([len(x[1]) for x in repo_tags]) + 2
            else:
                return 1, 1

        _images = self.images()
        if self.args.json:
            json.dump(_images, sys.stdout)
            return

        if len(_images) >= 0:
            _max_repo, _max_tag = get_col_lengths(_images)
            if self.args.truncate:
                _max_id = 14
            else:
                _max_id = 65

            col_out = "{0:2} {1:" + str(_max_repo) + "} {2:" + str(_max_tag) + \
                      "} {3:" + str(_max_id) + "} {4:18} {5:14} {6:10}"

            if self.args.heading and not self.args.quiet:
                util.write_out(
                    col_out.format(" ", "REPOSITORY", "TAG", "IMAGE ID",
                                   "CREATED", "VIRTUAL SIZE", "TYPE"))

            for image in _images:
                if self.args.filter:
                    image_info = {
                        "repo": image['repo'],
                        "tag": image['tag'],
                        "id": image['id'],
                        "created": image['created'],
                        "size": image['virtual_size'],
                        "type": image['type'],
                        "dangling": "{}".format(image['is_dangling'])
                    }
                    if not self._filter_include_image(image_info):
                        continue
                if self.args.quiet:
                    util.write_out(image['id'])

                else:
                    indicator = ""
                    if image["is_dangling"]:
                        indicator += "*"
                    elif image["used_image"]:
                        indicator += ">"
                    if image["vulnerable"]:
                        space = " " if len(indicator) < 1 else ""
                        if util.is_python2:
                            indicator = indicator + self.skull + space
                        else:
                            indicator = indicator + str(self.skull,
                                                        "utf-8") + space
                    util.write_out(
                        col_out.format(indicator, image['repo'], image['tag'],
                                       image['id'], image['created'],
                                       image['virtual_size'], image['type']))
            util.write_out("")
            return
Beispiel #21
0
    def run(self, iobject, **kwargs):
        def add_string_or_list_to_list(list_item, value):
            if not isinstance(value, list):
                value = value.split()
            list_item += value
            return list_item

        atomic = kwargs.get('atomic', None)
        args = kwargs.get('args')
        # atomic must be an instance of Atomic
        # args must be a argparse Namespace
        assert(isinstance(atomic, Atomic))
        # The object is a container
        # If container exists and not started, start it
        # If container exists and is started, execute command inside it (docker exec)
        # If container doesn't exist, create one and start it
        if args.command:
            iobject.user_command = args.command
        if isinstance(iobject, Container):
            latest_image = self.inspect_image(iobject.image_name)
            if latest_image.id != iobject.image:
                util.write_out("The '{}' container is using an older version of the installed\n'{}' container image. If "
                               "you wish to use the newer image,\nyou must either create a new container with a "
                               "new name or\nuninstall the '{}' container. \n\n# atomic uninstall --name "
                               "{} {}\n\nand create new container on the {} image.\n\n# atomic update --force "
                               "{}s\n\n removes all containers based on an "
                               "image.".format(iobject.name, iobject.image_name, iobject.name, iobject.name,
                                               iobject.image_name, iobject.image_name, iobject.image_name))
            if iobject.running:
                return self._running(iobject, args, atomic)
            else:
                return self._start(iobject, args, atomic)

        if iobject.get_label('INSTALL') and not args.ignore and not util.InstallData.image_installed(iobject):
            raise ValueError("The image '{}' appears to have not been installed and has an INSTALL label.  You "
                             "should install this image first.  Re-run with --ignore to bypass this "
                             "error.".format(iobject.name or iobject.image))
        # The object is an image
        command = []
        if iobject.run_command:
            command = add_string_or_list_to_list(command, iobject.run_command)
            if iobject.user_command:
                command = add_string_or_list_to_list(command, iobject.user_command)
            opts_file = iobject.get_label("RUN_OPTS_FILE")
            if opts_file:
                opts_file = atomic.sub_env_strings("".join(opts_file))
                if opts_file.startswith("/"):
                    if os.path.isfile(opts_file):
                        try:
                            atomic.run_opts = open(opts_file, "r").read()
                        except IOError:
                            raise ValueError("Failed to read RUN_OPTS_FILE %s" % opts_file)
                else:
                    raise ValueError("Will not read RUN_OPTS_FILE %s: not absolute path" % opts_file)
        else:
            command += [atomic.docker_binary(), "run"]
            if os.isatty(0):
                command += ["-t"]
            if args.detach:
                command += ["-d"]
            command += atomic.SPC_ARGS if args.spc else atomic.RUN_ARGS
            if iobject.user_command:
                command = add_string_or_list_to_list(command, iobject.user_command)

        if len(command) > 0 and command[0] == "docker":
            command[0] = atomic.docker_binary()

        if iobject.cmd and not iobject.user_command and not iobject.run_command:
            cmd = iobject.cmd if isinstance(iobject.cmd, list) else iobject.cmd.split()
            command += cmd
        command = atomic.gen_cmd(command)
        command = atomic.sub_env_strings(command)
        atomic.display(command)
        if atomic.args.display:
            return

        if not atomic.args.quiet:
            self.check_args(command)
        return util.check_call(command, env=atomic.cmd_env())
Beispiel #22
0
 def prune(self):
     for iid in self.get_dangling_images():
         self.delete_image(iid, force=True)
         util.write_out("Removed dangling Image {}".format(iid))
     return 0