From 8940fb8c7edf64cd6914adb5f97ab7c91dd79025 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Mon, 19 May 2025 11:28:00 -0700 Subject: [PATCH] Add manage-events admin commands This adds commands to manage event queue processing. Change-Id: Iec54aab7e88e9e60423bc2a9c4fa623ca50b415a Depends-On: https://review.opendev.org/c/zuul/zuul/+/950346 --- doc/source/commands.rst | 8 +++ .../notes/manage-events-5440173cde48d938.yaml | 5 ++ zuulclient/api/__init__.py | 22 ++++++++ zuulclient/cmd/__init__.py | 52 +++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 releasenotes/notes/manage-events-5440173cde48d938.yaml diff --git a/doc/source/commands.rst b/doc/source/commands.rst index 0f685bd..dcb1c48 100644 --- a/doc/source/commands.rst +++ b/doc/source/commands.rst @@ -131,6 +131,14 @@ type of trigger. Some familiarity with the arguments emitted by such as ``patchset-created`` and ``ref-updated`` is recommended. Some examples of common operations are provided below. +Manage-events +^^^^^^^^^^^^^ + +.. note:: This command is only available with a valid authentication token. + +.. program-output:: zuul-client manage-events --help + + Manual enqueue examples *********************** diff --git a/releasenotes/notes/manage-events-5440173cde48d938.yaml b/releasenotes/notes/manage-events-5440173cde48d938.yaml new file mode 100644 index 0000000..bd0c11c --- /dev/null +++ b/releasenotes/notes/manage-events-5440173cde48d938.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + A new subcommand, `manage-events` has been added to manage event + queue processing. diff --git a/zuulclient/api/__init__.py b/zuulclient/api/__init__.py index d2f0f93..3a17235 100644 --- a/zuulclient/api/__init__.py +++ b/zuulclient/api/__init__.py @@ -1,4 +1,5 @@ # Copyright 2020 Red Hat, inc +# Copyright 2025 Acme Gating, LLC # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -267,6 +268,27 @@ class ZuulRESTClient(object): self._check_request_status(req) return req.json() + def tenants(self): + url = urllib.parse.urljoin(self.base_url, 'tenants') + req = self.session.get(url) + self._check_request_status(req) + return req.json() + + def tenant_state(self, tenant, **args): + if not self.auth_token: + raise Exception('Auth Token required') + if self.info.get('tenant'): + self._check_scope(tenant) + suffix = 'state' + else: + suffix = 'tenant/%s/state' % tenant + url = urllib.parse.urljoin( + self.base_url, + suffix) + req = self.session.post(url, json=args) + self._check_request_status(req) + return req.json() + def get_key(self, tenant, project): if self.info.get('tenant'): self._check_scope(tenant) diff --git a/zuulclient/cmd/__init__.py b/zuulclient/cmd/__init__.py index 77d7ddc..df74583 100644 --- a/zuulclient/cmd/__init__.py +++ b/zuulclient/cmd/__init__.py @@ -1,4 +1,5 @@ # Copyright 2020 Red Hat, inc +# Copyright 2025 Acme Gating, LLC # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -123,6 +124,7 @@ class ZuulClient(): self.add_enqueue_ref_subparser(subparsers) self.add_dequeue_subparser(subparsers) self.add_promote_subparser(subparsers) + self.add_manage_events_subparser(subparsers) self.add_encrypt_subparser(subparsers) self.add_builds_list_subparser(subparsers) self.add_build_info_subparser(subparsers) @@ -504,6 +506,56 @@ class ZuulClient(): r = client.promote(**kwargs) return r + def add_manage_events_subparser(self, subparsers): + cmd_me = subparsers.add_parser('manage-events', + help='manage event processing') + cmd_me.add_argument('--tenant', help='tenant name', + required=False, default='') + cmd_me.add_argument('--all-tenants', + help='set the state for all tenants', + required=False, action='store_true') + cmd_me.add_argument('state', + help='new tenant event state', + choices=[ + 'normal', + 'discard-trigger', + 'pause-trigger', + 'pause-result', + ]) + cmd_me.add_argument('--reason', + help='reason to display on status page', + required=False) + cmd_me.set_defaults(func=self.manage_events) + self.cmd_manage_events = cmd_me + + def manage_events(self): + client = self.get_client() + + if self.args.all_tenants: + tenants = [x['name'] for x in client.tenants()] + else: + self._check_tenant_scope(client) + tenants = [self.tenant()] + + kwargs = dict( + trigger_queue_discarding=False, + trigger_queue_paused=False, + result_queue_paused=False, + reason=self.args.reason, + ) + if self.args.state == 'discard-trigger': + kwargs['trigger_queue_discarding'] = True + elif self.args.state == 'pause-trigger': + kwargs['trigger_queue_paused'] = True + elif self.args.state == 'pause-result': + kwargs['trigger_queue_paused'] = True + kwargs['result_queue_paused'] = True + for tenant in tenants: + self.log.info('Invoking tenant_state with arguments: %s %s' % + (tenant, kwargs)) + client.tenant_state(tenant, **kwargs) + return True + def get_config_section(self): conf_sections = self.config.sections() if len(conf_sections) == 1 and self.args.zuul_config is None: