From ecb2fcbe2a0b12d4269ba31dc2179358471b2468 Mon Sep 17 00:00:00 2001 From: Andre Anjos <andre.dos.anjos@gmail.com> Date: Fri, 22 Jan 2021 18:30:26 +0100 Subject: [PATCH] [scripts/runners] Streamline, add list command and the possibility to disable a runner through all projects using it --- bob/devtools/scripts/runners.py | 281 +++++++++++++++++++++++--------- 1 file changed, 207 insertions(+), 74 deletions(-) diff --git a/bob/devtools/scripts/runners.py b/bob/devtools/scripts/runners.py index 59de342e..4d40a058 100644 --- a/bob/devtools/scripts/runners.py +++ b/bob/devtools/scripts/runners.py @@ -1,37 +1,61 @@ #!/usr/bin/env python import click +from click_plugins import with_plugins +import pkg_resources from ..log import get_logger from ..log import verbosity_option +from ..log import echo_normal from ..release import get_gitlab_instance from . import bdt logger = get_logger(__name__) -@click.command( - epilog=""" -Examples: +def _get_runner_from_description(gl, descr): - 1. Disables the runner with description "macmini" for all active projects in group "bob": + # search for the runner to affect + the_runner = [ + k + for k in gl.runners.list(all=True) + if k.attributes["description"] == descr + ] + if not the_runner: + raise RuntimeError("Cannot find runner with description = %s", descr) + the_runner = the_runner[0] + logger.info( + "Found runner %s (id=%d)", + the_runner.attributes["description"], + the_runner.attributes["id"], + ) - $ bdt gitlab runners -vv bob disable macmini + return the_runner - 2. Enables the runner with description "linux-srv01" on all projects inside group "beat": +@with_plugins(pkg_resources.iter_entry_points("bdt.gitlab.cli")) +@click.group(cls=bdt.AliasedGroup) +def runners(): + """Commands for handling runners.""" + pass - $ bdt gitlab runners -vv beat enable linux-srv01 +@runners.command( + epilog=""" +Examples: - 3. Enables the runner with description "linux-srv02" on a specific project: + 1. Enables the runner with description "linux-srv01" on all projects inside group "beat": - $ bdt gitlab runners -vv bob/bob.extension enable linux-srv02 + $ bdt gitlab runners enable -vv beat linux-srv01 + + + 2. Enables the runner with description "linux-srv02" on a specific project: + + $ bdt gitlab runners enable -vv bob/bob.extension linux-srv02 """ ) @click.argument("target") -@click.argument("cmd", type=click.Choice(["enable", "disable"])) @click.argument("name") @click.option( "-d", @@ -43,13 +67,14 @@ Examples: ) @verbosity_option() @bdt.raise_on_error -def runners(target, cmd, name, dry_run): - """Enables and disables runners on whole gitlab groups or single - projects.""" +def enable(target, name, dry_run): + """Enables runners on whole gitlab groups or single projects.""" gl = get_gitlab_instance() gl.auth() + the_runner = _get_runner_from_description(gl, name) + if "/" in target: # it is a specific project packages = [gl.projects.get(target)] logger.debug( @@ -65,81 +90,189 @@ def runners(target, cmd, name, dry_run): "Found gitlab group %s (id=%d)", group.attributes["path"], group.id ) logger.warn( - "Retrieving all projects (with details) from group " "%s (id=%d)...", + "Retrieving all projects (with details) from group " + "%s (id=%d)...", group.attributes["path"], group.id, ) packages = [ - gl.projects.get(k.id) for k in group.projects.list(all=True, simple=True) + gl.projects.get(k.id) + for k in group.projects.list(all=True, simple=True) ] logger.info( - "Found %d projects under group %s", len(packages), group.attributes["path"], + "Found %d projects under group %s", + len(packages), + group.attributes["path"], ) - # search for the runner to affect - the_runner = [ - k for k in gl.runners.list(all=True) if k.attributes["description"] == name - ] - if not the_runner: - raise RuntimeError("Cannot find runner with description = %s", name) - the_runner = the_runner[0] - logger.info( - "Found runner %s (id=%d)", - the_runner.attributes["description"], - the_runner.attributes["id"], - ) - for k in packages: logger.info( - "Processing project %s (id=%d)", k.attributes["path_with_namespace"], k.id, + "Processing project %s (id=%d)", + k.attributes["path_with_namespace"], + k.id, ) - if cmd == "enable": - - # checks if runner is not enabled first - enabled = False - for ll in k.runners.list(all=True): - if ll.id == the_runner.id: # it is there already - logger.warn( - "Runner %s (id=%d) is already enabled for project %s", - ll.attributes["description"], - ll.id, - k.attributes["path_with_namespace"], - ) - enabled = True - break - - if not enabled: # enable it - if not dry_run: - k.runners.create({"runner_id": the_runner.id}) - logger.info( - "Enabled runner %s (id=%d) for project %s", - the_runner.attributes["description"], - the_runner.id, + # checks if runner is not enabled first + enabled = False + for ll in k.runners.list(all=True): + if ll.id == the_runner.id: # it is there already + logger.warn( + "Runner %s (id=%d) is already enabled for project %s", + ll.attributes["description"], + ll.id, k.attributes["path_with_namespace"], ) + enabled = True + break + + if not enabled: # enable it + if not dry_run: + k.runners.create({"runner_id": the_runner.id}) + logger.info( + "Enabled runner %s (id=%d) for project %s", + the_runner.attributes["description"], + the_runner.id, + k.attributes["path_with_namespace"], + ) + + +@runners.command( + epilog=""" +Examples: + + 1. Disables the runner with description "macmini" for all active projects in group "bob": + + $ bdt gitlab runners disable -vv bob macmini + + + 2. Disables the runner with description "macmini" on all projects it is associated to: + + $ bdt gitlab runners disable -vv __all__ macmini + - elif cmd == "disable": - - # checks if runner is not already disabled first - disabled = True - for ll in k.runners.list(all=True): - if ll.id == the_runner.id: # it is there already - logger.debug( - "Runner %s (id=%d) is enabled for project %s", - ll.attributes["description"], - ll.id, - k.attributes["path_with_namespace"], - ) - disabled = False - break - - if not disabled: # enable it - if not dry_run: - k.runners.delete(the_runner.id) - logger.info( - "Disabled runner %s (id=%d) for project %s", - the_runner.attributes["description"], - the_runner.id, +""" +) +@click.argument("target") +@click.argument("name") +@click.option( + "-d", + "--dry-run/--no-dry-run", + default=False, + help="Only goes through the actions, but does not execute them " + "(combine with the verbosity flags - e.g. ``-vvv``) to enable " + "printing to help you understand what will be done", +) +@verbosity_option() +@bdt.raise_on_error +def disable(target, name, dry_run): + """Disables runners on whole gitlab groups or single projects.""" + + gl = get_gitlab_instance() + gl.auth() + + the_runner = _get_runner_from_description(gl, name) + + if "/" in target: # it is a specific project + packages = [gl.projects.get(target)] + logger.debug( + "Found gitlab project %s (id=%d)", + packages[0].attributes["path_with_namespace"], + packages[0].id, + ) + + elif target != "__all__": # it is a group - get all projects + logger.warn("Retrieving group by name - may take long...") + group = gl.groups.get(target) + logger.debug( + "Found gitlab group %s (id=%d)", group.attributes["path"], group.id + ) + logger.warn( + "Retrieving all projects (with details) from group " + "%s (id=%d)...", + group.attributes["path"], + group.id, + ) + packages = [ + gl.projects.get(k.id) + for k in group.projects.list(all=True, simple=True) + ] + logger.info( + "Found %d projects under group %s", + len(packages), + group.attributes["path"], + ) + + else: # disables from everywhere + logger.warn("Retrieving all runner associated projects...") + # gets extended version of object + the_runner = gl.runners.get(the_runner.id) + packages = [gl.projects.get(k['id']) for k in the_runner.projects] + logger.info( + "Found %d projects using runner %s", + len(packages), + the_runner.description, + ) + + for k in packages: + logger.info( + "Processing project %s (id=%d)", + k.attributes["path_with_namespace"], + k.id, + ) + + # checks if runner is not already disabled first + disabled = True + for ll in k.runners.list(all=True): + if ll.id == the_runner.id: # it is there already + logger.debug( + "Runner %s (id=%d) is enabled for project %s", + ll.attributes["description"], + ll.id, k.attributes["path_with_namespace"], ) + disabled = False + break + + if not disabled: # enable it + if not dry_run: + k.runners.delete(the_runner.id) + logger.info( + "Disabled runner %s (id=%d) for project %s", + the_runner.attributes["description"], + the_runner.id, + k.attributes["path_with_namespace"], + ) + + +@runners.command( + epilog=""" +Examples: + + 1. Lists all projects a runner is associated to + + $ bdt gitlab runners list -vv macmini + +""" +) +@click.argument("name") +@verbosity_option() +@bdt.raise_on_error +def list(name): + """Lists projects a runner is associated to""" + + gl = get_gitlab_instance() + gl.auth() + + the_runner = _get_runner_from_description(gl, name) + + logger.info("Retrieving all runner associated projects...") + # gets extended version of object + the_runner = gl.runners.get(the_runner.id) + logger.info( + "Found %d projects using runner %s", + len(the_runner.projects), + the_runner.description, + ) + + for k in the_runner.projects: + echo_normal(k["path_with_namespace"]) -- GitLab