def parse_arguments(options, args, flatpak): "Build a container" if flatpak: usage = _("usage: %prog flatpak-build [options] target <scm url>") else: usage = _("usage: %prog container-build [options] target <scm url or " "archive path>") usage += _("\n(Specify the --help global option for a list of other help " "options)") parser = OptionParser(usage=usage) parser.add_option("--scratch", action="store_true", help=_("Perform a scratch build")) if not flatpak: parser.add_option("--isolated", action="store_true", help=_("Perform an isolated build")) parser.add_option("--arch-override", help=_( "Requires --scratch. Limit a scratch build to " "the specified arches. Comma or space separated.")) parser.add_option("--wait", action="store_true", help=_("Wait on the build, even if running in the " "background")) parser.add_option("--nowait", action="store_false", dest="wait", help=_("Don't wait on build")) parser.add_option("--quiet", action="store_true", help=_("Do not print the task information"), default=options.quiet) parser.add_option("--background", action="store_true", help=_("Run the build at a lower priority")) parser.add_option("--epoch", help=_("Specify container epoch. Requires koji admin " "permission.")) parser.add_option("--repo-url", dest='yum_repourls', metavar="REPO_URL", action='append', help=_("URL of yum repo file. May be used multiple " "times. Cannot be used with --compose-id")) parser.add_option("--git-branch", metavar="GIT_BRANCH", help=_("Git branch")) parser.add_option("--channel-override", help=_("Use a non-standard channel [default: %default]"), default=DEFAULT_CHANNEL) parser.add_option( "--signing-intent", help=_("Signing intent of the ODCS composes [default: %default]." " Cannot be used with --compose-id"), default=None, dest='signing_intent') parser.add_option( "--compose-id", help=_("ODCS composes used. May be used multiple times. Cannot be" " used with --signing-intent or --repo-url"), dest='compose_ids', action='append', metavar="COMPOSE_ID", type="int") if not flatpak: parser.add_option("--release", help=_("Set release value")) parser.add_option( "--koji-parent-build", help=_("Overwrite parent image with image from koji build")) build_opts, args = parser.parse_args(args) if len(args) != 2: parser.error( _("Exactly two arguments (a build target and a SCM URL) " "are required")) assert False if build_opts.arch_override and not (build_opts.scratch or build_opts.isolated): parser.error( _("--arch-override is only allowed for --scratch or --isolated builds" )) if build_opts.signing_intent and build_opts.compose_ids: parser.error(_("--signing-intent cannot be used with --compose-id")) if build_opts.compose_ids and build_opts.yum_repourls: parser.error(_("--compose-id cannot be used with --repo-url")) opts = {} if not build_opts.git_branch: parser.error(_("git-branch must be specified")) keys = ('scratch', 'epoch', 'yum_repourls', 'git_branch', 'signing_intent', 'compose_ids') if flatpak: opts['flatpak'] = True else: if build_opts.isolated and build_opts.scratch: parser.error(_("Build cannot be both isolated and scratch")) keys += ('release', 'isolated', 'koji_parent_build') if build_opts.arch_override: opts['arch_override'] = parse_arches(build_opts.arch_override) for key in keys: val = getattr(build_opts, key) if val is not None: opts[key] = val # create the parser in this function and return it to # simplify the unit test cases return build_opts, args, opts, parser
def handle_runroot(options, session, args): "[admin] Run a command in a buildroot" usage = _("usage: %prog runroot [options] <tag> <arch> <command>") usage += _( "\n(Specify the --help global option for a list of other help options)" ) parser = OptionParser(usage=usage) parser.disable_interspersed_args() parser.add_option("-p", "--package", action="append", default=[], help=_("make sure this package is in the chroot")) parser.add_option("-m", "--mount", action="append", default=[], help=_("mount this directory read-write in the chroot")) parser.add_option("--skip-setarch", action="store_true", default=False, help=_("bypass normal setarch in the chroot")) parser.add_option("-w", "--weight", type='int', help=_("set task weight")) parser.add_option("--channel-override", help=_("use a non-standard channel")) parser.add_option("--task-id", action="store_true", default=False, help=_("Print the ID of the runroot task")) parser.add_option( "--use-shell", action="store_true", default=False, help=_("Run command through a shell, otherwise uses exec")) parser.add_option( "--new-chroot", action="store_true", default=False, help=_( "Run command with the --new-chroot (systemd-nspawn) option to mock" )) parser.add_option("--repo-id", type="int", help=_("ID of the repo to use")) parser.add_option("--nowait", action="store_false", dest="wait", default=True, help=_("Do not wait on task")) parser.add_option("--watch", action="store_true", help=_("Watch task instead of printing runroot.log")) parser.add_option("--quiet", action="store_true", default=options.quiet, help=_("Do not print the task information")) (opts, args) = parser.parse_args(args) if len(args) < 3: parser.error(_("Incorrect number of arguments")) assert False # pragma: no cover activate_session(session, options) tag = args[0] arch = args[1] if opts.use_shell: # everything must be correctly quoted command = ' '.join(args[2:]) else: command = args[2:] try: kwargs = { 'channel': opts.channel_override, 'packages': opts.package, 'mounts': opts.mount, 'repo_id': opts.repo_id, 'skip_setarch': opts.skip_setarch, 'weight': opts.weight } # Only pass this kwarg if it is true - this prevents confusing older # builders with a different function signature if opts.new_chroot: kwargs['new_chroot'] = True task_id = session.runroot(tag, arch, command, **kwargs) except koji.GenericError as e: if 'Invalid method' in str(e): print("* The runroot plugin appears to not be installed on the" " koji hub. Please contact the administrator.") raise if opts.task_id: print(task_id) if not opts.wait: return if opts.watch: session.logout() return watch_tasks(session, [task_id], quiet=opts.quiet, poll_interval=options.poll_interval) try: while True: # wait for the task to finish if session.taskFinished(task_id): break time.sleep(options.poll_interval) except KeyboardInterrupt: # this is probably the right thing to do here print("User interrupt: canceling runroot task") session.cancelTask(task_id) raise output = list_task_output_all_volumes(session, task_id) if 'runroot.log' in output: for volume in output['runroot.log']: log = session.downloadTaskOutput(task_id, 'runroot.log', volume=volume) sys.stdout.write(log) info = session.getTaskInfo(task_id) if info is None: sys.exit(1) state = koji.TASK_STATES[info['state']] if state in ('FAILED', 'CANCELED'): sys.exit(1)
def parse_source_arguments(options, args): "Build a source container" usage = _("usage: %prog source-container-build [options] target") usage += _("\n(Specify the --help global option for a list of other help " "options)") parser = OptionParser(usage=usage) parser.add_option("--scratch", action="store_true", help=_("Perform a scratch build")) parser.add_option("--wait", action="store_true", help=_("Wait on the build, even if running in the " "background")) parser.add_option("--nowait", action="store_false", dest="wait", help=_("Don't wait on build")) parser.add_option("--quiet", action="store_true", help=_("Do not print the task information"), default=options.quiet) parser.add_option("--background", action="store_true", help=_("Run the build at a lower priority")) parser.add_option("--channel-override", help=_("Use a non-standard channel [default: %default]"), default=DEFAULT_CHANNEL) parser.add_option( "--signing-intent", help=_("Signing intent of the ODCS composes [default: %default]."), default=None, dest='signing_intent') parser.add_option("--koji-build-id", type="int", help=_("Koji build id for sources, " "is required or koji-build-nvr is provided")) parser.add_option("--koji-build-nvr", help=_("Koji build nvr for sources, " "is required or koji-build-id is provided")) build_opts, args = parser.parse_args(args) if len(args) != 1: parser.error(_("Exactly one argument (a build target) is required")) assert False if not (build_opts.koji_build_id or build_opts.koji_build_nvr): parser.error( _("at least one of --koji-build-id and --koji-build-nvr has to be specified" )) opts = {} keys = ('scratch', 'signing_intent', 'koji_build_id', 'koji_build_nvr') for key in keys: val = getattr(build_opts, key) if val is not None: opts[key] = val # create the parser in this function and return it to # simplify the unit test cases return build_opts, args, opts, parser
def parse_arguments(options, args, flatpak): "Build a container" if flatpak: usage = _("usage: %prog flatpak-build [options] target <scm url>") else: usage = _("usage: %prog container-build [options] target <scm url or " "archive path>") usage += _("\n(Specify the --help global option for a list of other help " "options)") parser = OptionParser(usage=usage) parser.add_option("--scratch", action="store_true", help=_("Perform a scratch build")) if not flatpak: parser.add_option("--isolated", action="store_true", help=_("Perform an isolated build")) parser.add_option("--arch-override", help=_( "Requires --scratch or --isolated. Limit a build to " "the specified arches. Comma or space separated.")) parser.add_option("--wait", action="store_true", help=_("Wait on the build, even if running in the " "background")) parser.add_option("--nowait", action="store_false", dest="wait", help=_("Don't wait on build")) parser.add_option("--quiet", action="store_true", help=_("Do not print the task information"), default=options.quiet) parser.add_option("--background", action="store_true", help=_("Run the build at a lower priority")) parser.add_option( "--replace-dependency", dest='dependency_replacements', metavar="pkg_manager:name:version[:new_name]", action='append', help=_("Cachito dependency replacement. May be used multiple times.")) parser.add_option( "--repo-url", dest='yum_repourls', metavar="REPO_URL", action='append', help=_("URL of yum repo file. May be used multiple times.")) parser.add_option("--git-branch", metavar="GIT_BRANCH", help=_("Git branch")) parser.add_option("--channel-override", help=_("Use a non-standard channel [default: %default]"), default=DEFAULT_CHANNEL) parser.add_option( "--signing-intent", help=_("Signing intent of the ODCS composes [default: %default]." " Cannot be used with --compose-id"), default=None, dest='signing_intent') parser.add_option( "--compose-id", help=_("ODCS composes used. May be used multiple times. Cannot be" " used with --signing-intent"), dest='compose_ids', action='append', metavar="COMPOSE_ID", type="int") parser.add_option("--skip-build", action="store_true", help=_("Skip build and update buildconfig. " "Use this option to update autorebuild settings")) parser.add_option( "--userdata", help=_("JSON dictionary of user defined custom metadata")) parser.add_option( "--operator-csv-modifications-url", help=_("URL to JSON file with operator CSV modification"), action='store', default=None, dest='operator_csv_modifications_url', metavar='URL', ) if not flatpak: parser.add_option("--release", help=_("Set release value")) parser.add_option( "--koji-parent-build", help=_("Overwrite parent image with image from koji build")) build_opts, args = parser.parse_args(args) if len(args) != 2: parser.error( _("Exactly two arguments (a build target and a SCM URL) " "are required")) assert False source = args[1] if '://' not in source: parser.error( _("scm URL does not look like an URL to a source repository")) if '#' not in source: parser.error( _("scm URL must be of the form <url_to_repository>#<revision>)")) if build_opts.arch_override and not (build_opts.scratch or build_opts.isolated): parser.error( _("--arch-override is only allowed for --scratch or --isolated builds" )) if build_opts.signing_intent and build_opts.compose_ids: parser.error(_("--signing-intent cannot be used with --compose-id")) if build_opts.operator_csv_modifications_url and not build_opts.isolated: parser.error( _("Only --isolated builds support option --operator-csv-modifications-url" )) if (build_opts.operator_csv_modifications_url and '://' not in build_opts.operator_csv_modifications_url): parser.error( _("Value provided to --operator-csv-modifications-url " "does not look like an URL")) opts = {} if not build_opts.git_branch: parser.error(_("git-branch must be specified")) keys = ('scratch', 'yum_repourls', 'git_branch', 'signing_intent', 'compose_ids', 'skip_build', 'userdata', 'dependency_replacements', 'operator_csv_modifications_url') if flatpak: opts['flatpak'] = True else: if build_opts.isolated and build_opts.scratch: parser.error(_("Build cannot be both isolated and scratch")) keys += ('release', 'isolated', 'koji_parent_build') if build_opts.arch_override: opts['arch_override'] = parse_arches(build_opts.arch_override) for key in keys: val = getattr(build_opts, key) if val is not None: opts[key] = val if key == 'userdata': opts[key] = json.loads(val) # create the parser in this function and return it to # simplify the unit test cases return build_opts, args, opts, parser
def handle_save_failed_tree(options, session, args): "Create tarball with whole buildtree" usage = _("usage: %prog save-failed-tree [options] ID") usage += _("\n(Specify the --help global option for a list of other help options)") parser = OptionParser(usage=usage) parser.add_option("-f", "--full", action="store_true", default=False, help=_("Download whole tree, if not specified, only builddir will be downloaded")) parser.add_option("-t", "--task", action="store_const", dest="mode", const="task", default="task", help=_("Treat ID as a task ID (the default)")) parser.add_option("-r", "--buildroot", action="store_const", dest="mode", const="buildroot", help=_("Treat ID as a buildroot ID")) parser.add_option("--quiet", action="store_true", default=options.quiet, help=_("Do not print the task information")) parser.add_option("--nowait", action="store_true", help=_("Don't wait on build")) (opts, args) = parser.parse_args(args) if len(args) != 1: parser.error(_("List exactly one task or buildroot ID")) try: id_val = int(args[0]) except ValueError: parser.error(_("ID must be an integer")) activate_session(session, options) if opts.mode == "buildroot": br_id = id_val else: brs = [b['id'] for b in session.listBuildroots(taskID=id_val)] if not brs: print(_("No buildroots for task %s") % id_val) return 1 br_id = max(brs) if len(brs) > 1: print(_("Multiple buildroots for task. Choosing last one (%s)") % br_id) try: task_id = session.saveFailedTree(br_id, opts.full) except koji.GenericError as e: m = str(e) if 'Invalid method' in m: print(_("* The save_failed_tree plugin appears to not be " "installed on the koji hub. Please contact the " "administrator.")) return 1 raise if not opts.quiet: print(_("Created task %s for buildroot %s") % (task_id, br_id)) print("Task info: %s/taskinfo?taskID=%s" % (options.weburl, task_id)) if opts.nowait: return else: session.logout() return watch_tasks(session, [task_id], quiet=opts.quiet, poll_interval=options.poll_interval)
def parse_arguments(options, args, flatpak): "Build a container" if flatpak: usage = _("usage: %prog flatpak-build [options] target <scm url>") else: usage = _("usage: %prog container-build [options] target <scm url or " "archive path>") usage += _("\n(Specify the --help global option for a list of other help " "options)") parser = OptionParser(usage=usage) parser.add_option("--scratch", action="store_true", help=_("Perform a scratch build")) if not flatpak: parser.add_option("--isolated", action="store_true", help=_("Perform an isolated build")) parser.add_option("--arch-override", help=_("Requires --scratch. Limit a scratch build to " "the specified arches. Comma or space separated.")) parser.add_option("--wait", action="store_true", help=_("Wait on the build, even if running in the " "background")) parser.add_option("--nowait", action="store_false", dest="wait", help=_("Don't wait on build")) parser.add_option("--quiet", action="store_true", help=_("Do not print the task information"), default=options.quiet) parser.add_option("--background", action="store_true", help=_("Run the build at a lower priority")) parser.add_option("--epoch", help=_("Specify container epoch. Requires koji admin " "permission.")) parser.add_option("--repo-url", dest='yum_repourls', metavar="REPO_URL", action='append', help=_("URL of yum repo file. May be used multiple times.")) parser.add_option("--git-branch", metavar="GIT_BRANCH", help=_("Git branch")) parser.add_option("--channel-override", help=_("Use a non-standard channel [default: %default]"), default=DEFAULT_CHANNEL) parser.add_option("--signing-intent", help=_("Signing intent of the ODCS composes [default: %default]." " Cannot be used with --compose-id"), default=None, dest='signing_intent') parser.add_option("--compose-id", help=_("ODCS composes used. May be used multiple times. Cannot be" " used with --signing-intent"), dest='compose_ids', action='append', metavar="COMPOSE_ID", type="int") if not flatpak: parser.add_option("--release", help=_("Set release value")) parser.add_option("--koji-parent-build", help=_("Overwrite parent image with image from koji build")) build_opts, args = parser.parse_args(args) if len(args) != 2: parser.error(_("Exactly two arguments (a build target and a SCM URL) " "are required")) assert False if build_opts.arch_override and not (build_opts.scratch or build_opts.isolated): parser.error(_("--arch-override is only allowed for --scratch or --isolated builds")) if build_opts.signing_intent and build_opts.compose_ids: parser.error(_("--signing-intent cannot be used with --compose-id")) opts = {} if not build_opts.git_branch: parser.error(_("git-branch must be specified")) keys = ('scratch', 'epoch', 'yum_repourls', 'git_branch', 'signing_intent', 'compose_ids') if flatpak: opts['flatpak'] = True else: if build_opts.isolated and build_opts.scratch: parser.error(_("Build cannot be both isolated and scratch")) keys += ('release', 'isolated', 'koji_parent_build') if build_opts.arch_override: opts['arch_override'] = parse_arches(build_opts.arch_override) for key in keys: val = getattr(build_opts, key) if val is not None: opts[key] = val # create the parser in this function and return it to # simplify the unit test cases return build_opts, args, opts, parser
def parse_options(options, args): usage = _("usage: %prog replicate-tasks [options] [<task_id>...]") usage += _( "\nto replicate scratch tasks from existing tasks with specified IDs" " or by query" "\n(Specify the --help global option for a list of" " other help options)") parser = OptionParser(usage=usage) parser.disable_interspersed_args() parser.add_option( "-s", "--strategy", default=Strategy.reuse.name, help=_("specify the strategy to construct the buildroot for" " replicating the task, Options: %s," " [Default: %%default]." % ", ".join(Strategy.__members__.keys()))) parser.add_option( "-T", "--override-tag", help=_( "specify the tag in the inheritance to override the content / config" " of the origin build tag when strategy is clone")) parser.add_option("-C", "--channel", dest="channels", action="append", default=[], help=_("specify channels where tasks are from")) parser.add_option("-H", "--host", dest="hosts", action="append", default=[], help=_("specify hosts where tasks are replicated from")) parser.add_option( "-m", "--method", dest="methods", action="append", default=[], help=_( "specify methods that original tasks are. Only supports 'build' now" )) parser.add_option( "-S", "--state", dest="states", action="append", default=['CLOSED'], help=_( "specify states of tasks which are replicated, [Default: %default]" )) parser.add_option("-w", "--weight", type='int', help=_("set task weight")) parser.add_option("--channel-override", help=_("use a non-standard channel to replicate tasks")) parser.add_option("--arch-override", dest="arches", action="append", default=[], help=_("to override arches to replicate tasks")) parser.add_option("--include-scratch", action="store_true", help=_("also replicate scratch tasks")) # parser.add_option("--limit-by", default='channel', # help=_("specify field used by --limit")) parser.add_option( "--limit", type='int', default=3, help=_( "limit per method and/or per channel/host, [Default: %default]")) parser.add_option("--offset", type="int", default=0, help=_("offset of limit, [Default: %default]")) parser.add_option("--quiet", action="store_true", default=options.quiet, help=_("Do not print the task information")) return (parser, ) + parser.parse_args(args)
def handle_runroot(options, session, args): "[admin] Run a command in a buildroot" usage = _("usage: %prog runroot [options] <tag> <arch> <command>") usage += _("\n(Specify the --help global option for a list of other help options)") parser = OptionParser(usage=usage) parser.disable_interspersed_args() parser.add_option("-p", "--package", action="append", default=[], help=_("make sure this package is in the chroot")) parser.add_option("-m", "--mount", action="append", default=[], help=_("mount this directory read-write in the chroot")) parser.add_option("--skip-setarch", action="store_true", default=False, help=_("bypass normal setarch in the chroot")) parser.add_option("-w", "--weight", type='int', help=_("set task weight")) parser.add_option("--channel-override", help=_("use a non-standard channel")) parser.add_option("--task-id", action="store_true", default=False, help=_("Print the ID of the runroot task")) parser.add_option("--use-shell", action="store_true", default=False, help=_("Run command through a shell, otherwise uses exec")) parser.add_option("--new-chroot", action="store_true", default=None, help=_("Run command with the --new-chroot (systemd-nspawn) option to mock")) parser.add_option("--old-chroot", action="store_false", default=None, dest='new_chroot', help=_("Run command with the --old-chroot (systemd-nspawn) option to mock")) parser.add_option("--repo-id", type="int", help=_("ID of the repo to use")) parser.add_option("--nowait", action="store_false", dest="wait", default=True, help=_("Do not wait on task")) parser.add_option("--watch", action="store_true", help=_("Watch task instead of printing runroot.log")) parser.add_option("--quiet", action="store_true", default=options.quiet, help=_("Do not print the task information")) (opts, args) = parser.parse_args(args) if len(args) < 3: parser.error(_("Incorrect number of arguments")) assert False # pragma: no cover activate_session(session, options) tag = args[0] arch = args[1] if opts.use_shell: # everything must be correctly quoted command = ' '.join(args[2:]) else: command = args[2:] try: kwargs = { 'channel': opts.channel_override, 'packages': opts.package, 'mounts': opts.mount, 'repo_id': opts.repo_id, 'skip_setarch': opts.skip_setarch, 'weight': opts.weight } # Only pass this kwarg if it is true - this prevents confusing older # builders with a different function signature if opts.new_chroot is not None: kwargs['new_chroot'] = opts.new_chroot task_id = session.runroot(tag, arch, command, **kwargs) except koji.GenericError as e: if 'Invalid method' in str(e): print("* The runroot plugin appears to not be installed on the" " koji hub. Please contact the administrator.") raise if opts.task_id: print(task_id) if not opts.wait: return if opts.watch: session.logout() return watch_tasks(session, [task_id], quiet=opts.quiet, poll_interval=options.poll_interval) try: while True: # wait for the task to finish if session.taskFinished(task_id): break time.sleep(options.poll_interval) except KeyboardInterrupt: # this is probably the right thing to do here print("User interrupt: canceling runroot task") session.cancelTask(task_id) raise sys.stdout.flush() if not opts.quiet: output = list_task_output_all_volumes(session, task_id) if 'runroot.log' in output: for volume in output['runroot.log']: log = session.downloadTaskOutput(task_id, 'runroot.log', volume=volume) # runroot output, while normally text, can be *anything*, so # treat it as binary bytes_to_stdout(log) info = session.getTaskInfo(task_id) if info is None: sys.exit(1) state = koji.TASK_STATES[info['state']] if state in ('FAILED', 'CANCELED'): sys.exit(1)