def __iter__(self):
     yield "version", self.version,
     yield "version_type", self.version_type.value
     yield "source", self.source if isinstance(self.source, str) else dict(
         self.source),
     yield "tags", sorted(list(self.tags)),
     yield "updated", format_time(self.updated),
     yield "origin", self.origin,
     yield "size", self.size
Example #2
0
 def __iter__(self):
     yield "name", self.name,
     yield "updated", format_time(self.updated),
     yield "location", self.location,
     yield "versions", [dict(v) for v in self.versions],
     # if self.upstream_v:
     #     yield "upstream_v", [dict(v) for v in self.upstream_v],
     yield "description", self.description
     yield "meta_hash", self.meta_hash
def test_version_info_iter():
    obj = VersionInfo(**FAKE_VERSION_INFO_WITH_CHECKER)
    obj.updated = datetime.now()
    test_dict = {
        "version": "1.1",
        "version_type": "upstream",
        "source": {
            "uri": "https://test.uri",
            "repository": "test_repository",
            "tool": "test_tool",
            "provider": "test_provider",
            "method": "test_release",
            "suite": "test_suite",
            "origin": True,
            "docker_origin": True,
            "version": "1.1",
            "extra_info": "Test information",
        },
        "tags": ["latest", "latest-stable"],
        "updated": format_time(obj.updated),
        "origin": True,
        "size": "3.95 MB",
    }
    assert dict(obj) == test_dict
    obj = VersionInfo(**FAKE_VERSION_INFO_NO_CHECKER)
    obj.updated = datetime.now()
    test_dict2 = {
        "version": "0.9",
        "version_type": "remote",
        "source": "no_checker_case",
        "tags": ["latest", "latest-stable"],
        "updated": format_time(obj.updated),
        "origin": False,
        "size": "39.53 MB",
    }
    assert dict(obj) == test_dict2

    assert json.dumps(test_dict)
    assert json.dumps(test_dict2)
Example #4
0
def test_tool_info_iter():
    t_info = ToolInfo(**FAKE_TOOL_INFO)
    t_info.versions.append(VersionInfo(**FAKE_VERSION_INFO_NO_CHECKER))
    t_info.versions.append(VersionInfo(**FAKE_VERSION_INFO_WITH_CHECKER))
    t_info_dict = dict(t_info)

    assert t_info_dict.get("name") == "test_tool"
    assert t_info_dict.get("updated") == "2020-03-13T13:37:00"
    assert t_info_dict.get("location") == "test_location"
    assert t_info_dict.get("description") == "test_description"
    assert t_info_dict.get("versions")[0] == {
        "version": "0.9",
        "version_type": VersionType.REMOTE.value,
        "source": "no_checker_case",
        "tags": ["latest", "latest-stable"],
        "updated": format_time(datetime(2020, 3, 3, 13, 37,)),
        "size": "39.53 MB",
        "origin": False,
    }
Example #5
0
def main():
    """Parse command line and run the tool"""
    description_text = '''\
  CinCan Command - https://gitlab.com/CinCan/cincan-command/\n
  For full documentation, see: https://cincan.gitlab.io/cincan-command/
    '''
    epilog = '''  Report issues at https://gitlab.com/CinCan/cincan-command/-/issues
    '''
    m_parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=description_text,
        epilog=epilog)

    m_parser.add_argument(
        "-l",
        "--log",
        dest="log_level",
        choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
        help="Set the logging level",
        default=None)
    m_parser.add_argument('--batch',
                          action='store_true',
                          help='Use with automation. Disables some '
                          'properties meant for interactive tty device(s): '
                          'Version checking disabled, '
                          'pull-progress-bar disabled.')
    m_parser.add_argument('-q',
                          '--quiet',
                          action='store_true',
                          help='Be quite quiet')
    m_parser.add_argument(
        '-v',
        '--version',
        action='store_true',
        help='Shows currently installed version of the tool.')
    subparsers = m_parser.add_subparsers(dest='sub_command')

    run_parser = subparsers.add_parser('run')
    image_default_args(run_parser)

    test_parser = subparsers.add_parser('test')
    image_default_args(test_parser)

    shell_parser = subparsers.add_parser('shell')
    image_default_args(shell_parser)
    shell_parser.add_argument('-s',
                              '--shell',
                              nargs="?",
                              help="Give custom path to desirable shell."
                              " By default, /bin/bash >> /bin/sh are used",
                              default="/bin/bash")

    list_parser = create_list_argparse(subparsers)
    mani_parser = subparsers.add_parser('manifest')
    image_default_args(mani_parser)
    help_parser = subparsers.add_parser('help')
    if len(sys.argv) > 1:
        args = m_parser.parse_args(args=sys.argv[1:])
    else:
        args = m_parser.parse_args(args=['help'])
    if args.version:
        print(get_version_information())
        sys.exit(0)
    log_level = args.log_level if args.log_level else (
        'WARNING' if args.quiet else 'INFO')
    if log_level not in {'DEBUG'}:
        sys.tracebacklimit = 0  # avoid track traces unless debugging
    logging.basicConfig(format='%(name)s: %(message)s',
                        level=getattr(logging, log_level))

    sub_command = args.sub_command
    if sub_command == 'help':
        m_parser.print_help()
        sys.exit(1)
    elif sub_command in {'run', 'test', 'shell'}:
        # We do not want informative version logs here unless DEBUG mode
        if logging.DEBUG < logging.getLogger().getEffectiveLevel(
        ) < logging.ERROR:
            logging.getLogger('versions').setLevel(logging.ERROR)
            # Also suppress meta handler output
            logging.getLogger('metahandler').setLevel(logging.ERROR)
        if len(args.tool) == 0:
            sys.exit('Missing tool name argument')
        name = args.tool[0]
        if args.path is None:
            tool = ToolImage(name,
                             image=name,
                             pull=args.pull,
                             batch=args.batch)
        elif args.path is not None:
            tool = ToolImage(name, path=args.path, batch=args.batch)
        else:
            tool = ToolImage(name, batch=args.batch)  # should raise exception

        tool.input_tar = args.input_tar if args.input_tar else None
        tool.output_tar = args.output_tar if args.output_tar else None
        tool.output_dirs = args.output_dir or []
        tool.implicit_output = not args.no_implicit_output
        tool.explicit_output = args.explicit_output
        tool.input_filters = FileMatcher.parse(
            args.in_filter) if args.in_filter is not None else None
        tool.output_filters = FileMatcher.parse(
            args.out_filter) if args.out_filter is not None else None
        tool.no_defaults = args.no_defaults if args.no_defaults else False

        if tool.input_tar and tool.input_filters:
            sys.exit("Cannot specify input filters with input tar file")

        tool.create_image = args.create_image
        tool.entrypoint = args.entrypoint if sub_command != "shell" else ""
        tool.network_mode = args.network
        tool.user = args.user
        tool.cap_add = args.cap_add
        tool.cap_drop = args.cap_drop
        tool.runtime = args.runtime
        tool.is_tty = args.tty if sub_command != "shell" else True
        tool.read_stdin = args.interactive if sub_command != "shell" else True

        all_args = args.tool[1:]
        if sub_command == 'test':
            check = ContainerCheck(tool)
            tool.logger.info("# {} {}".format(
                ','.join(tool.get_tags()),
                format_time(tool.get_creation_time())))
            log = check.run(all_args)
        elif sub_command == "shell":
            tool.shell = args.shell
            log = tool.run(all_args)
        else:
            log = tool.run(all_args)

        if log.exit_code == 0:
            if tool.config.is_command_log():
                log_writer = CommandLogWriter()
                log_writer.write(log)
        if log.stdout:
            sys.stdout.buffer.write(log.stdout)
        if log.stderr:
            sys.stderr.buffer.write(log.stderr)
        sys.exit(log.exit_code)  # exit code
    elif sub_command == 'manifest':
        # sub command 'manifest'
        if len(args.tool) == 0:
            sys.exit('Missing tool name argument')
        name = args.tool[0]
        reg = ToolRegistry()
        conf = Configuration()
        name, tag = name.rsplit(
            ":", 1) if ":" in name else [name, conf.default_stable_tag]
        info = reg.remote_registry.fetch_manifest(name, tag)
        print(info)
    elif sub_command == 'list':
        list_handler(args)
    else:
        sys.exit(f"Unexpected sub command '{sub_command}")