Clarify zuul admin CLI scope

We have two CLIs: zuul-client for REST-related operations, which cover
tenant-scoped, workflow modifying actions such as enqueue, dequeue and
promote; and zuul which supercedes zuul-client and covers also true admin
operations like ZooKeeper maintenance, config checking and issueing auth tokens.
This is a bit confusing for users and operators, and can induce code
duplication.

* Rename zuul CLI into zuul-admin. zuul is still a valid endpoint
  and will be removed after next release.
* Print a deprecation warning when invoking the admin CLI as zuul
  instead of zuul-admin, and when running autohold-*, enqueue-*,
  dequeue and promote subcommands. These subcommands will need to be
  run with zuul-client after next release.
* Clarify the scopes and deprecations in the documentation.

Change-Id: I90cf6f2be4e4c8180ad0f5e2696b7eaa7380b411
This commit is contained in:
Matthieu Huin 2022-04-14 11:40:36 +02:00
parent f2297cadb0
commit 57c78c08e1
6 changed files with 193 additions and 154 deletions

View File

@ -1,11 +1,12 @@
:title: Zuul Client
:title: Zuul Admin Client
Zuul Client
===========
Zuul Admin Client
=================
Zuul includes a simple command line client that may be used to affect Zuul's
behavior while running. It must be run on a host with access to Zuul's web
server.
behavior while running.
.. note:: For operations related to normal workflow like enqueue, dequeue, autohold and promote, the `zuul-client` CLI should be used instead.
Configuration
-------------
@ -13,76 +14,168 @@ Configuration
The client uses the same zuul.conf file as the server, and will look
for it in the same locations if not specified on the command line.
The ``webclient`` section is required.
It is also possible to run the client without a configuration file, by using the
``--zuul-url`` option to specify the base URL of the Zuul web server.
.. note:: Not all commands are available through the REST API.
Usage
-----
The general options that apply to all subcommands are:
.. program-output:: zuul --help
.. program-output:: zuul-admin --help
The following subcommands are supported:
Autohold
^^^^^^^^
.. program-output:: zuul autohold --help
tenant-conf-check
^^^^^^^^^^^^^^^^^
.. program-output:: zuul-admin tenant-conf-check --help
Example::
zuul autohold --tenant openstack --project example_project --job example_job --reason "reason text" --count 1
zuul-admin tenant-conf-check
This command validates the tenant configuration schema. It exits '-1' in
case of errors detected.
create-auth-token
^^^^^^^^^^^^^^^^^
.. note:: This command is only available if an authenticator is configured in
``zuul.conf``. Furthermore the authenticator's configuration must
include a signing secret.
.. program-output:: zuul-admin create-auth-token --help
Example::
zuul-admin create-auth-token --auth-config zuul-operator --user alice --tenant tenantA --expires-in 1800
The return value is the value of the ``Authorization`` header the user must set
when querying a protected endpoint on Zuul's REST API.
Example::
bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbWFuYWdlc2Yuc2ZyZG90ZXN0aW5zdGFuY2Uub3JnIiwienV1bC50ZW5hbnRzIjp7ImxvY2FsIjoiKiJ9LCJleHAiOjE1Mzc0MTcxOTguMzc3NTQ0fQ.DLbKx1J84wV4Vm7sv3zw9Bw9-WuIka7WkPQxGDAHz7s
export-keys
^^^^^^^^^^^
.. program-output:: zuul-admin export-keys --help
Example::
zuul-admin export-keys /var/backup/zuul-keys.json
import-keys
^^^^^^^^^^^
.. program-output:: zuul-admin import-keys --help
Example::
zuul-admin import-keys /var/backup/zuul-keys.json
copy-keys
^^^^^^^^^
.. program-output:: zuul-admin copy-keys --help
Example::
zuul-admin copy-keys gerrit old_project gerrit new_project
delete-keys
^^^^^^^^^^^
.. program-output:: zuul-admin delete-keys --help
Example::
zuul-admin delete-keys gerrit old_project
delete-state
^^^^^^^^^^^^
.. program-output:: zuul-admin delete-state --help
Example::
zuul-admin delete-state
delete-pipeline-state
^^^^^^^^^^^^^^^^^^^^^
.. program-output:: zuul-admin delete-pipeline-state --help
Example::
zuul-admin delete-pipeline-state tenant pipeline
Deprecated commands
-------------------
The following commands are deprecated in the zuul-admin CLI, and thus may not be entirely supported in Zuul's current version.
They will be removed in a future release of Zuul. They can still be performed via the `zuul-client` CLI.
Please refer to `zuul-client's documentation <https://zuul-ci.org/docs/zuul-client/>`__
for more details.
In order to run these commands, the ``webclient`` section is required in the configuration file.
It is also possible to run the client without a configuration file, by using the
``--zuul-url`` option to specify the base URL of the Zuul web server.
Autohold
^^^^^^^^
.. program-output:: zuul-admin autohold --help
Example::
zuul-admin autohold --tenant openstack --project example_project --job example_job --reason "reason text" --count 1
Autohold Delete
^^^^^^^^^^^^^^^
.. program-output:: zuul autohold-delete --help
.. program-output:: zuul-admin autohold-delete --help
Example::
zuul autohold-delete --id 0000000123
zuul-admin autohold-delete --id 0000000123
Autohold Info
^^^^^^^^^^^^^
.. program-output:: zuul autohold-info --help
.. program-output:: zuul-admin autohold-info --help
Example::
zuul autohold-info --id 0000000123
zuul-admin autohold-info --id 0000000123
Autohold List
^^^^^^^^^^^^^
.. program-output:: zuul autohold-list --help
.. program-output:: zuul-admin autohold-list --help
Example::
zuul autohold-list --tenant openstack
zuul-admin autohold-list --tenant openstack
Dequeue
^^^^^^^
.. program-output:: zuul dequeue --help
.. program-output:: zuul-admin dequeue --help
Examples::
zuul dequeue --tenant openstack --pipeline check --project example_project --change 5,1
zuul dequeue --tenant openstack --pipeline periodic --project example_project --ref refs/heads/master
zuul-admin dequeue --tenant openstack --pipeline check --project example_project --change 5,1
zuul-admin dequeue --tenant openstack --pipeline periodic --project example_project --ref refs/heads/master
Enqueue
^^^^^^^
.. program-output:: zuul enqueue --help
.. program-output:: zuul-admin enqueue --help
Example::
zuul enqueue --tenant openstack --trigger gerrit --pipeline check --project example_project --change 12345,1
zuul-admin enqueue --tenant openstack --trigger gerrit --pipeline check --project example_project --change 12345,1
Note that the format of change id is <number>,<patchset>.
Enqueue-ref
^^^^^^^^^^^
.. program-output:: zuul enqueue-ref --help
.. program-output:: zuul-admin enqueue-ref --help
This command is provided to manually simulate a trigger from an
external source. It can be useful for testing or replaying a trigger
@ -106,7 +199,7 @@ the jobs, pass the failed tag as the ``ref`` argument and set
``newrev`` to the change associated with the tag in the project
repository (i.e. what you see from ``git show X.Y.Z``)::
zuul enqueue-ref --tenant openstack --trigger gerrit --pipeline release --project openstack/example_project --ref refs/tags/X.Y.Z --newrev abc123..
zuul-admin enqueue-ref --tenant openstack --trigger gerrit --pipeline release --project openstack/example_project --ref refs/tags/X.Y.Z --newrev abc123..
The command can also be used asynchronosly trigger a job in a
``periodic`` pipeline that would usually be run at a specific time by
@ -114,7 +207,7 @@ the ``timer`` driver. For example, the following command would
trigger the ``periodic`` jobs against the current ``master`` branch
top-of-tree for a project::
zuul enqueue-ref --tenant openstack --trigger timer --pipeline periodic --project openstack/example_project --ref refs/heads/master
zuul-admin enqueue-ref --tenant openstack --trigger timer --pipeline periodic --project openstack/example_project --ref refs/heads/master
Another common pipeline is a ``post`` queue listening for ``gerrit``
merge results. Triggering here is slightly more complicated as you
@ -128,7 +221,7 @@ current ``HEAD`` and the prior change, then enqueue the event::
NEW_REF=$(git rev-parse HEAD)
OLD_REF=$(git rev-parse HEAD~1)
zuul enqueue-ref --tenant openstack --trigger gerrit --pipeline post --project openstack/example_project --ref refs/heads/master --newrev $NEW_REF --oldrev $OLD_REF
zuul-admin enqueue-ref --tenant openstack --trigger gerrit --pipeline post --project openstack/example_project --ref refs/heads/master --newrev $NEW_REF --oldrev $OLD_REF
Note that zero values for ``oldrev`` and ``newrev`` can indicate
branch creation and deletion; the source code is the best reference
@ -138,11 +231,11 @@ for these more advanced operations.
Promote
^^^^^^^
.. program-output:: zuul promote --help
.. program-output:: zuul-admin promote --help
Example::
zuul promote --tenant openstack --pipeline gate --changes 12345,1 13336,3
zuul-admin promote --tenant openstack --pipeline gate --changes 12345,1 13336,3
Note that the format of changes id is <number>,<patchset>.
@ -163,90 +256,4 @@ ordering.
If items in independent pipelines are promoted, no jobs will be
restarted, but their change queues within the pipeline will be
re-ordered so that they will be processed first and their node request
priorities will increase.
tenant-conf-check
^^^^^^^^^^^^^^^^^
.. program-output:: zuul tenant-conf-check --help
Example::
zuul tenant-conf-check
This command validates the tenant configuration schema. It exits '-1' in
case of errors detected.
create-auth-token
^^^^^^^^^^^^^^^^^
.. note:: This command is only available if an authenticator is configured in
``zuul.conf``. Furthermore the authenticator's configuration must
include a signing secret.
.. program-output:: zuul create-auth-token --help
Example::
zuul create-auth-token --auth-config zuul-operator --user alice --tenant tenantA --expires-in 1800
The return value is the value of the ``Authorization`` header the user must set
when querying a protected endpoint on Zuul's REST API.
Example::
bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbWFuYWdlc2Yuc2ZyZG90ZXN0aW5zdGFuY2Uub3JnIiwienV1bC50ZW5hbnRzIjp7ImxvY2FsIjoiKiJ9LCJleHAiOjE1Mzc0MTcxOTguMzc3NTQ0fQ.DLbKx1J84wV4Vm7sv3zw9Bw9-WuIka7WkPQxGDAHz7s
export-keys
^^^^^^^^^^^
.. program-output:: zuul export-keys --help
Example::
zuul export-keys /var/backup/zuul-keys.json
import-keys
^^^^^^^^^^^
.. program-output:: zuul import-keys --help
Example::
zuul import-keys /var/backup/zuul-keys.json
copy-keys
^^^^^^^^^
.. program-output:: zuul copy-keys --help
Example::
zuul copy-keys gerrit old_project gerrit new_project
delete-keys
^^^^^^^^^^^
.. program-output:: zuul delete-keys --help
Example::
zuul delete-keys gerrit old_project
delete-state
^^^^^^^^^^^^
.. program-output:: zuul delete-state --help
Example::
zuul delete-state
delete-pipeline-state
^^^^^^^^^^^^^^^^^^^^^
.. program-output:: zuul delete-pipeline-state --help
Example::
zuul delete-pipeline-state tenant pipeline
priorities will increase.

View File

@ -0,0 +1,7 @@
---
deprecations:
- |
The zuul CLI is renamed `zuul-admin`. The `zuul` command will remain usable until a future version,
then will be phased out. Likewise, tenant-scoped, workflow affecting commands such as autohold,
enqueue, dequeue, promote are deprecated from the zuul-admin CLI and will be phased out in a
future version. They can still be performed via the `zuul-client` CLI.

View File

@ -29,6 +29,7 @@ console_scripts =
zuul-scheduler = zuul.cmd.scheduler:main
zuul-merger = zuul.cmd.merger:main
zuul = zuul.cmd.client:main
zuul-admin = zuul.cmd.client:main
zuul-executor = zuul.cmd.executor:main
zuul-bwrap = zuul.driver.bubblewrap:main
zuul-web = zuul.cmd.web:main

View File

@ -66,7 +66,7 @@ class TestTenantValidationClient(BaseClientTestCase):
with open(os.path.join(self.test_root, 'tenant_ok.conf'), 'w') as f:
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', os.path.join(self.test_root, 'tenant_ok.conf'),
'tenant-conf-check'], stdout=subprocess.PIPE)
p.communicate()
@ -78,7 +78,7 @@ class TestTenantValidationClient(BaseClientTestCase):
with open(os.path.join(self.test_root, 'tenant_ko.conf'), 'w') as f:
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', os.path.join(self.test_root, 'tenant_ko.conf'),
'tenant-conf-check'], stdout=subprocess.PIPE)
out, _ = p.communicate()
@ -100,7 +100,7 @@ class TestWebTokenClient(BaseClientTestCase):
'no_zuul_operator.conf'), 'w') as f:
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', os.path.join(self.test_root, 'no_zuul_operator.conf'),
'create-auth-token',
'--auth-config', 'zuul_operator',
@ -122,7 +122,7 @@ class TestWebTokenClient(BaseClientTestCase):
with open(os.path.join(self.test_root, 'JWKS.conf'), 'w') as f:
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', os.path.join(self.test_root, 'JWKS.conf'),
'create-auth-token',
'--auth-config', 'someauth',
@ -140,7 +140,7 @@ class TestWebTokenClient(BaseClientTestCase):
with open(os.path.join(self.test_root, 'good.conf'), 'w') as f:
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', os.path.join(self.test_root, 'good.conf'),
'create-auth-token',
'--auth-conf', 'zuul_operator',
@ -187,7 +187,7 @@ class TestKeyOperations(ZuulTestCase):
# Export keys
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'export-keys', export_root],
stdout=subprocess.PIPE)
@ -204,7 +204,7 @@ class TestKeyOperations(ZuulTestCase):
# Import keys
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'import-keys', export_root],
stdout=subprocess.PIPE)
@ -222,7 +222,7 @@ class TestKeyOperations(ZuulTestCase):
self.config.write(f)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'copy-keys',
'gerrit', 'org/project',
@ -242,7 +242,7 @@ class TestKeyOperations(ZuulTestCase):
data['/keystorage/gerrit/neworg/neworg%2Fnewproject/ssh'])
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-keys',
'gerrit', 'org/project',
@ -269,7 +269,7 @@ class TestKeyOperations(ZuulTestCase):
data.get('/keystorage/gerrit/org'))
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-keys',
'gerrit', 'org/project1',
@ -280,7 +280,7 @@ class TestKeyOperations(ZuulTestCase):
self.assertEqual(p.returncode, 0)
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-keys',
'gerrit', 'org/project2',
@ -328,7 +328,7 @@ class TestOfflineZKOperations(ZuulTestCase):
old_data = self.getZKTree('/keystorage')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-state',
],
@ -367,7 +367,7 @@ class TestOnlineZKOperations(ZuulTestCase):
# Make sure the pipeline exists
self.getZKTree('/zuul/tenant/tenant-one/pipeline/check/item')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-pipeline-state',
'tenant-one', 'check',
@ -405,7 +405,7 @@ class TestOnlineZKOperations(ZuulTestCase):
# Make sure the pipeline exists
self.getZKTree('/zuul/tenant/tenant-one/pipeline/gate/item')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'-c', config_file,
'delete-pipeline-state',
'tenant-one', 'gate',

View File

@ -2892,7 +2892,7 @@ class TestCLIViaWebApi(BaseTestWeb):
token = jwt.encode(authz, key='NoDanaOnlyZuul',
algorithm='HS256')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'--zuul-url', self.base_url, '--auth-token', token,
'autohold', '--reason', 'some reason',
'--tenant', 'tenant-one', '--project', 'org/project',
@ -2931,7 +2931,7 @@ class TestCLIViaWebApi(BaseTestWeb):
token = jwt.encode(authz, key='NoDanaOnlyZuul',
algorithm='HS256')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'--zuul-url', self.base_url, '--auth-token', token,
'enqueue', '--tenant', 'tenant-one',
'--project', 'org/project',
@ -2960,7 +2960,7 @@ class TestCLIViaWebApi(BaseTestWeb):
token = jwt.encode(authz, key='NoDanaOnlyZuul',
algorithm='HS256')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'--zuul-url', self.base_url, '--auth-token', token,
'enqueue-ref', '--tenant', 'tenant-one',
'--project', 'org/project',
@ -2999,7 +2999,7 @@ class TestCLIViaWebApi(BaseTestWeb):
token = jwt.encode(authz, key='NoDanaOnlyZuul',
algorithm='HS256')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'--zuul-url', self.base_url, '--auth-token', token,
'dequeue', '--tenant', 'tenant-one', '--project', 'org/project',
'--pipeline', 'periodic', '--ref', 'refs/heads/stable'],
@ -3050,7 +3050,7 @@ class TestCLIViaWebApi(BaseTestWeb):
token = jwt.encode(authz, key='NoDanaOnlyZuul',
algorithm='HS256')
p = subprocess.Popen(
[os.path.join(sys.prefix, 'bin/zuul'),
[os.path.join(sys.prefix, 'bin/zuul-admin'),
'--zuul-url', self.base_url, '--auth-token', token,
'promote', '--tenant', 'tenant-one',
'--pipeline', 'gate', '--changes', '2,1', '3,1'],

View File

@ -189,7 +189,8 @@ class Client(zuul.cmd.ZuulApp):
# Autohold
cmd_autohold = subparsers.add_parser(
'autohold', help='hold nodes for failed job')
'autohold', help='[DEPRECATED - use zuul-client] '
'hold nodes for failed job')
cmd_autohold.add_argument('--tenant', help='tenant name',
required=True)
cmd_autohold.add_argument('--project', help='project name',
@ -214,25 +215,30 @@ class Client(zuul.cmd.ZuulApp):
cmd_autohold.set_defaults(func=self.autohold)
cmd_autohold_delete = subparsers.add_parser(
'autohold-delete', help='delete autohold request')
'autohold-delete', help='[DEPRECATED - use zuul-client] '
'delete autohold request')
cmd_autohold_delete.set_defaults(func=self.autohold_delete)
cmd_autohold_delete.add_argument('id', metavar='REQUEST_ID',
help='the hold request ID')
cmd_autohold_info = subparsers.add_parser(
'autohold-info', help='retrieve autohold request detailed info')
'autohold-info', help='[DEPRECATED - use zuul-client] '
'retrieve autohold request detailed info')
cmd_autohold_info.set_defaults(func=self.autohold_info)
cmd_autohold_info.add_argument('id', metavar='REQUEST_ID',
help='the hold request ID')
cmd_autohold_list = subparsers.add_parser(
'autohold-list', help='list autohold requests')
'autohold-list', help='[DEPRECATED - use zuul-client] '
'list autohold requests')
cmd_autohold_list.add_argument('--tenant', help='tenant name',
required=True)
cmd_autohold_list.set_defaults(func=self.autohold_list)
# Enqueue/Dequeue
cmd_enqueue = subparsers.add_parser('enqueue', help='enqueue a change')
cmd_enqueue = subparsers.add_parser(
'enqueue',
help='[DEPRECATED - use zuul-client] enqueue a change')
cmd_enqueue.add_argument('--tenant', help='tenant name',
required=True)
# TODO(mhu) remove in a few releases
@ -249,7 +255,8 @@ class Client(zuul.cmd.ZuulApp):
cmd_enqueue.set_defaults(func=self.enqueue)
cmd_enqueue = subparsers.add_parser(
'enqueue-ref', help='enqueue a ref',
'enqueue-ref',
help='[DEPRECATED - use zuul-client] enqueue a ref',
formatter_class=argparse.RawDescriptionHelpFormatter,
description=textwrap.dedent('''\
Submit a trigger event
@ -273,9 +280,11 @@ class Client(zuul.cmd.ZuulApp):
'--newrev', help='new revision', default=None)
cmd_enqueue.set_defaults(func=self.enqueue_ref)
cmd_dequeue = subparsers.add_parser('dequeue',
help='dequeue a buildset by its '
'change or ref')
cmd_dequeue = subparsers.add_parser(
'dequeue',
help='[DEPRECATED - use zuul-client] '
'dequeue a buildset by its '
'change or ref')
cmd_dequeue.add_argument('--tenant', help='tenant name',
required=True)
cmd_dequeue.add_argument('--pipeline', help='pipeline name',
@ -289,8 +298,10 @@ class Client(zuul.cmd.ZuulApp):
cmd_dequeue.set_defaults(func=self.dequeue)
# Promote
cmd_promote = subparsers.add_parser('promote',
help='promote one or more changes')
cmd_promote = subparsers.add_parser(
'promote',
help='[DEPRECATED - use zuul-client] '
'promote one or more changes')
cmd_promote.add_argument('--tenant', help='tenant name',
required=True)
cmd_promote.add_argument('--pipeline', help='pipeline name',
@ -300,8 +311,10 @@ class Client(zuul.cmd.ZuulApp):
cmd_promote.set_defaults(func=self.promote)
# Show
cmd_show = subparsers.add_parser('show',
help='show current statuses')
cmd_show = subparsers.add_parser(
'show',
help='[DEPRECATED - use zuul-client] '
'show current statuses')
cmd_show.set_defaults(func=self.show_running_jobs)
show_subparsers = cmd_show.add_subparsers(title='show')
show_running_jobs = show_subparsers.add_parser(
@ -521,7 +534,13 @@ class Client(zuul.cmd.ZuulApp):
if not self.args.zuul_url:
self.readConfig()
self.setup_logging()
if self.args.func in [self.autohold, self.autohold_delete,
self.enqueue, self.enqueue_ref,
self.dequeue, self.promote]:
print(
"Warning: this command is deprecated with zuul-admin, "
"please use `zuul-client` instead",
file=sys.stderr)
if self.args.func():
sys.exit(0)
else:
@ -990,4 +1009,9 @@ class Client(zuul.cmd.ZuulApp):
def main():
if sys.argv[0].endswith('zuul'):
print(
"Warning: this command name is deprecated, "
"use `zuul-admin` instead",
file=sys.stderr)
Client().main()