We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
st2 cli commands in "usage" must be in alphabetical order

```
usage: st2 [-h] [--version] [--url BASE_URL] [--auth-url AUTH_URL]
           [--api-url API_URL] [--stream-url STREAM_URL]
           [--api-version API_VERSION] [--cacert CACERT]
           [--config-file CONFIG_FILE] [--print-config] [--skip-config]
           [--debug]
           {action,action-alias,auth,apikey,execution,key,login,pack,policy,policy-type,rule,run,runner,sensor,trace,trigger,trigger-instance,webhook,whoami,timer,rule-enforcement,role,role-assignment}
```

Backstory: someone didn't see `timer` just because they're out of the order. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `st2client/st2client/shell.py`
Content:
```
1 #!/usr/bin/env python
2 
3 # Licensed to the StackStorm, Inc ('StackStorm') under one or more
4 # contributor license agreements.  See the NOTICE file distributed with
5 # this work for additional information regarding copyright ownership.
6 # The ASF licenses this file to You under the Apache License, Version 2.0
7 # (the "License"); you may not use this file except in compliance with
8 # the License.  You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 
18 """
19 Command-line interface to StackStorm.
20 """
21 
22 from __future__ import print_function
23 from __future__ import absolute_import
24 
25 import sys
26 import argcomplete
27 import argparse
28 import logging
29 
30 import six
31 
32 from st2client import __version__
33 from st2client import models
34 from st2client.base import BaseCLIApp
35 from st2client.commands import auth
36 from st2client.commands import action
37 from st2client.commands import action_alias
38 from st2client.commands import keyvalue
39 from st2client.commands import pack
40 from st2client.commands import policy
41 from st2client.commands import resource
42 from st2client.commands import sensor
43 from st2client.commands import trace
44 from st2client.commands import trigger
45 from st2client.commands import triggerinstance
46 from st2client.commands import timer
47 from st2client.commands import webhook
48 from st2client.commands import rule
49 from st2client.commands import rule_enforcement
50 from st2client.commands import rbac
51 from st2client.config import set_config
52 from st2client.exceptions.operations import OperationFailureException
53 from st2client.utils.logging import LogLevelFilter, set_log_level_for_all_loggers
54 from st2client.commands.auth import TokenCreateCommand
55 from st2client.commands.auth import LoginCommand
56 from st2client.commands.auth import WhoamiCommand
57 
58 
59 __all__ = [
60     'Shell'
61 ]
62 
63 LOGGER = logging.getLogger(__name__)
64 
65 CLI_DESCRIPTION = 'CLI for StackStorm event-driven automation platform. https://stackstorm.com'
66 
67 
68 class Shell(BaseCLIApp):
69     LOG = LOGGER
70 
71     SKIP_AUTH_CLASSES = [
72         TokenCreateCommand.__name__,
73         LoginCommand.__name__,
74         WhoamiCommand.__name__
75     ]
76 
77     def __init__(self):
78         # Set up of endpoints is delayed until program is run.
79         self.client = None
80 
81         # Set up the main parser.
82         self.parser = argparse.ArgumentParser(description=CLI_DESCRIPTION)
83 
84         # Set up general program options.
85         self.parser.add_argument(
86             '--version',
87             action='version',
88             version='%(prog)s {version}'.format(version=__version__))
89 
90         self.parser.add_argument(
91             '--url',
92             action='store',
93             dest='base_url',
94             default=None,
95             help='Base URL for the API servers. Assumes all servers use the '
96                  'same base URL and default ports are used. Get ST2_BASE_URL '
97                  'from the environment variables by default.'
98         )
99 
100         self.parser.add_argument(
101             '--auth-url',
102             action='store',
103             dest='auth_url',
104             default=None,
105             help='URL for the authentication service. Get ST2_AUTH_URL '
106                  'from the environment variables by default.'
107         )
108 
109         self.parser.add_argument(
110             '--api-url',
111             action='store',
112             dest='api_url',
113             default=None,
114             help='URL for the API server. Get ST2_API_URL '
115                  'from the environment variables by default.'
116         )
117 
118         self.parser.add_argument(
119             '--stream-url',
120             action='store',
121             dest='stream_url',
122             default=None,
123             help='URL for the stream endpoint. Get ST2_STREAM_URL'
124                  'from the environment variables by default.'
125         )
126 
127         self.parser.add_argument(
128             '--api-version',
129             action='store',
130             dest='api_version',
131             default=None,
132             help='API version to use. Get ST2_API_VERSION '
133                  'from the environment variables by default.'
134         )
135 
136         self.parser.add_argument(
137             '--cacert',
138             action='store',
139             dest='cacert',
140             default=None,
141             help='Path to the CA cert bundle for the SSL endpoints. '
142                  'Get ST2_CACERT from the environment variables by default. '
143                  'If this is not provided, then SSL cert will not be verified.'
144         )
145 
146         self.parser.add_argument(
147             '--config-file',
148             action='store',
149             dest='config_file',
150             default=None,
151             help='Path to the CLI config file'
152         )
153 
154         self.parser.add_argument(
155             '--print-config',
156             action='store_true',
157             dest='print_config',
158             default=False,
159             help='Parse the config file and print the values'
160         )
161 
162         self.parser.add_argument(
163             '--skip-config',
164             action='store_true',
165             dest='skip_config',
166             default=False,
167             help='Don\'t parse and use the CLI config file'
168         )
169 
170         self.parser.add_argument(
171             '--debug',
172             action='store_true',
173             dest='debug',
174             default=False,
175             help='Enable debug mode'
176         )
177 
178         # Set up list of commands and subcommands.
179         self.subparsers = self.parser.add_subparsers()
180         self.commands = dict()
181 
182         self.commands['action'] = action.ActionBranch(
183             'An activity that happens as a response to the external event.',
184             self, self.subparsers)
185 
186         self.commands['action-alias'] = action_alias.ActionAliasBranch(
187             'Action aliases.',
188             self, self.subparsers)
189 
190         self.commands['auth'] = auth.TokenCreateCommand(
191             models.Token, self, self.subparsers, name='auth')
192 
193         self.commands['api-key'] = auth.ApiKeyBranch(
194             'API Keys.',
195             self, self.subparsers)
196 
197         self.commands['execution'] = action.ActionExecutionBranch(
198             'An invocation of an action.',
199             self, self.subparsers)
200 
201         self.commands['key'] = keyvalue.KeyValuePairBranch(
202             'Key value pair is used to store commonly used configuration '
203             'for reuse in sensors, actions, and rules.',
204             self, self.subparsers)
205 
206         self.commands['login'] = auth.LoginCommand(
207             models.Token, self, self.subparsers, name='login')
208 
209         self.commands['pack'] = pack.PackBranch(
210             'A group of related integration resources: '
211             'actions, rules, and sensors.',
212             self, self.subparsers)
213 
214         self.commands['policy'] = policy.PolicyBranch(
215             'Policy that is enforced on a resource.',
216             self, self.subparsers)
217 
218         self.commands['policy-type'] = policy.PolicyTypeBranch(
219             'Type of policy that can be applied to resources.',
220             self, self.subparsers)
221 
222         self.commands['rule'] = rule.RuleBranch(
223             'A specification to invoke an "action" on a "trigger" selectively '
224             'based on some criteria.',
225             self, self.subparsers)
226 
227         self.commands['run'] = action.ActionRunCommand(
228             models.Action, self, self.subparsers, name='run', add_help=False)
229 
230         self.commands['runner'] = resource.ResourceBranch(
231             models.RunnerType,
232             'Runner is a type of handler for a specific class of actions.',
233             self, self.subparsers, read_only=True, has_disable=True)
234 
235         self.commands['sensor'] = sensor.SensorBranch(
236             'An adapter which allows you to integrate StackStorm with external system.',
237             self, self.subparsers)
238 
239         self.commands['trace'] = trace.TraceBranch(
240             'A group of executions, rules and triggerinstances that are related.',
241             self, self.subparsers)
242 
243         self.commands['trigger'] = trigger.TriggerTypeBranch(
244             'An external event that is mapped to a st2 input. It is the '
245             'st2 invocation point.',
246             self, self.subparsers)
247 
248         self.commands['trigger-instance'] = triggerinstance.TriggerInstanceBranch(
249             'Actual instances of triggers received by st2.',
250             self, self.subparsers)
251 
252         self.commands['webhook'] = webhook.WebhookBranch(
253             'Webhooks.',
254             self, self.subparsers)
255 
256         self.commands['whoami'] = auth.WhoamiCommand(
257             models.Token, self, self.subparsers, name='whoami')
258 
259         self.commands['timer'] = timer.TimerBranch(
260             'Timers.',
261             self, self.subparsers)
262 
263         self.commands['rule-enforcement'] = rule_enforcement.RuleEnforcementBranch(
264             'Models that represent enforcement of rules.',
265             self, self.subparsers)
266 
267         # RBAC
268         self.commands['role'] = rbac.RoleBranch(
269             'RBAC roles.',
270             self, self.subparsers)
271         self.commands['role-assignment'] = rbac.RoleAssignmentBranch(
272             'RBAC role assignments.',
273             self, self.subparsers)
274 
275     def run(self, argv):
276         debug = False
277 
278         # Provide autocomplete for shell
279         argcomplete.autocomplete(self.parser)
280 
281         if '--print-config' in argv:
282             # Hack because --print-config requires no command to be specified
283             argv = argv + ['action', 'list']
284 
285         # Parse command line arguments.
286         args = self.parser.parse_args(args=argv)
287 
288         print_config = args.print_config
289         if print_config:
290             self._print_config(args=args)
291             return 3
292 
293         # Parse config and store it in the config module
294         config = self._parse_config_file(args=args)
295         set_config(config=config)
296 
297         # Setup client and run the command
298         try:
299             debug = getattr(args, 'debug', False)
300             if debug:
301                 set_log_level_for_all_loggers(level=logging.DEBUG)
302 
303             # Set up client.
304             self.client = self.get_client(args=args, debug=debug)
305 
306             # Execute command.
307             args.func(args)
308 
309             return 0
310         except OperationFailureException as e:
311             if debug:
312                 self._print_debug_info(args=args)
313             return 2
314         except Exception as e:
315             # We allow exception to define custom exit codes
316             exit_code = getattr(e, 'exit_code', 1)
317 
318             print('ERROR: %s\n' % e)
319             if debug:
320                 self._print_debug_info(args=args)
321 
322             return exit_code
323 
324     def _print_config(self, args):
325         config = self._parse_config_file(args=args)
326 
327         for section, options in six.iteritems(config):
328             print('[%s]' % (section))
329 
330             for name, value in six.iteritems(options):
331                 print('%s = %s' % (name, value))
332 
333 
334 def setup_logging(argv):
335     debug = '--debug' in argv
336 
337     root = LOGGER
338     root.setLevel(logging.WARNING)
339 
340     handler = logging.StreamHandler(sys.stderr)
341     handler.setLevel(logging.WARNING)
342     formatter = logging.Formatter('%(asctime)s  %(levelname)s - %(message)s')
343     handler.setFormatter(formatter)
344 
345     if not debug:
346         handler.addFilter(LogLevelFilter(log_levels=[logging.ERROR]))
347 
348     root.addHandler(handler)
349 
350 
351 def main(argv=sys.argv[1:]):
352     setup_logging(argv)
353     return Shell().run(argv)
354 
355 
356 if __name__ == '__main__':
357     sys.exit(main(sys.argv[1:]))
358
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/st2client/st2client/shell.py b/st2client/st2client/shell.py
--- a/st2client/st2client/shell.py
+++ b/st2client/st2client/shell.py
@@ -63,6 +63,15 @@
 LOGGER = logging.getLogger(__name__)
 
 CLI_DESCRIPTION = 'CLI for StackStorm event-driven automation platform. https://stackstorm.com'
+USAGE_STRING = """
+Usage: %(prog)s [options] <command> <sub command> [options]
+
+For example:
+
+    %(prog)s action list --pack=st2
+    %(prog)s run core.local cmd=date
+    %(prog)s --debug run core.local cmd=date
+""".strip()
 
 
 class Shell(BaseCLIApp):
@@ -177,7 +186,10 @@
 
         # Set up list of commands and subcommands.
         self.subparsers = self.parser.add_subparsers()
-        self.commands = dict()
+        self.commands = {}
+
+        self.commands['run'] = action.ActionRunCommand(
+            models.Action, self, self.subparsers, name='run', add_help=False)
 
         self.commands['action'] = action.ActionBranch(
             'An activity that happens as a response to the external event.',
@@ -190,6 +202,12 @@
         self.commands['auth'] = auth.TokenCreateCommand(
             models.Token, self, self.subparsers, name='auth')
 
+        self.commands['login'] = auth.LoginCommand(
+            models.Token, self, self.subparsers, name='login')
+
+        self.commands['whoami'] = auth.WhoamiCommand(
+            models.Token, self, self.subparsers, name='whoami')
+
         self.commands['api-key'] = auth.ApiKeyBranch(
             'API Keys.',
             self, self.subparsers)
@@ -203,9 +221,6 @@
             'for reuse in sensors, actions, and rules.',
             self, self.subparsers)
 
-        self.commands['login'] = auth.LoginCommand(
-            models.Token, self, self.subparsers, name='login')
-
         self.commands['pack'] = pack.PackBranch(
             'A group of related integration resources: '
             'actions, rules, and sensors.',
@@ -224,8 +239,13 @@
             'based on some criteria.',
             self, self.subparsers)
 
-        self.commands['run'] = action.ActionRunCommand(
-            models.Action, self, self.subparsers, name='run', add_help=False)
+        self.commands['webhook'] = webhook.WebhookBranch(
+            'Webhooks.',
+            self, self.subparsers)
+
+        self.commands['timer'] = timer.TimerBranch(
+            'Timers.',
+            self, self.subparsers)
 
         self.commands['runner'] = resource.ResourceBranch(
             models.RunnerType,
@@ -249,17 +269,6 @@
             'Actual instances of triggers received by st2.',
             self, self.subparsers)
 
-        self.commands['webhook'] = webhook.WebhookBranch(
-            'Webhooks.',
-            self, self.subparsers)
-
-        self.commands['whoami'] = auth.WhoamiCommand(
-            models.Token, self, self.subparsers, name='whoami')
-
-        self.commands['timer'] = timer.TimerBranch(
-            'Timers.',
-            self, self.subparsers)
-
         self.commands['rule-enforcement'] = rule_enforcement.RuleEnforcementBranch(
             'Models that represent enforcement of rules.',
             self, self.subparsers)
@@ -275,6 +284,17 @@
     def run(self, argv):
         debug = False
 
+        parser = self.parser
+
+        if len(argv) == 0:
+            # Print a more user-friendly help string if no arguments are provided
+            # Note: We only set usage variable for the main parser. If we passed "usage" argument
+            # to the main ArgumentParser class above, this would also set a custom usage string for
+            # sub-parsers which we don't want.
+            parser.usage = USAGE_STRING
+            sys.stderr.write(parser.format_help())
+            return 2
+
         # Provide autocomplete for shell
         argcomplete.autocomplete(self.parser)

{"golden_diff": "diff --git a/st2client/st2client/shell.py b/st2client/st2client/shell.py\n--- a/st2client/st2client/shell.py\n+++ b/st2client/st2client/shell.py\n@@ -63,6 +63,15 @@\n LOGGER = logging.getLogger(__name__)\n \n CLI_DESCRIPTION = 'CLI for StackStorm event-driven automation platform. https://stackstorm.com'\n+USAGE_STRING = \"\"\"\n+Usage: %(prog)s [options] <command> <sub command> [options]\n+\n+For example:\n+\n+    %(prog)s action list --pack=st2\n+    %(prog)s run core.local cmd=date\n+    %(prog)s --debug run core.local cmd=date\n+\"\"\".strip()\n \n \n class Shell(BaseCLIApp):\n@@ -177,7 +186,10 @@\n \n         # Set up list of commands and subcommands.\n         self.subparsers = self.parser.add_subparsers()\n-        self.commands = dict()\n+        self.commands = {}\n+\n+        self.commands['run'] = action.ActionRunCommand(\n+            models.Action, self, self.subparsers, name='run', add_help=False)\n \n         self.commands['action'] = action.ActionBranch(\n             'An activity that happens as a response to the external event.',\n@@ -190,6 +202,12 @@\n         self.commands['auth'] = auth.TokenCreateCommand(\n             models.Token, self, self.subparsers, name='auth')\n \n+        self.commands['login'] = auth.LoginCommand(\n+            models.Token, self, self.subparsers, name='login')\n+\n+        self.commands['whoami'] = auth.WhoamiCommand(\n+            models.Token, self, self.subparsers, name='whoami')\n+\n         self.commands['api-key'] = auth.ApiKeyBranch(\n             'API Keys.',\n             self, self.subparsers)\n@@ -203,9 +221,6 @@\n             'for reuse in sensors, actions, and rules.',\n             self, self.subparsers)\n \n-        self.commands['login'] = auth.LoginCommand(\n-            models.Token, self, self.subparsers, name='login')\n-\n         self.commands['pack'] = pack.PackBranch(\n             'A group of related integration resources: '\n             'actions, rules, and sensors.',\n@@ -224,8 +239,13 @@\n             'based on some criteria.',\n             self, self.subparsers)\n \n-        self.commands['run'] = action.ActionRunCommand(\n-            models.Action, self, self.subparsers, name='run', add_help=False)\n+        self.commands['webhook'] = webhook.WebhookBranch(\n+            'Webhooks.',\n+            self, self.subparsers)\n+\n+        self.commands['timer'] = timer.TimerBranch(\n+            'Timers.',\n+            self, self.subparsers)\n \n         self.commands['runner'] = resource.ResourceBranch(\n             models.RunnerType,\n@@ -249,17 +269,6 @@\n             'Actual instances of triggers received by st2.',\n             self, self.subparsers)\n \n-        self.commands['webhook'] = webhook.WebhookBranch(\n-            'Webhooks.',\n-            self, self.subparsers)\n-\n-        self.commands['whoami'] = auth.WhoamiCommand(\n-            models.Token, self, self.subparsers, name='whoami')\n-\n-        self.commands['timer'] = timer.TimerBranch(\n-            'Timers.',\n-            self, self.subparsers)\n-\n         self.commands['rule-enforcement'] = rule_enforcement.RuleEnforcementBranch(\n             'Models that represent enforcement of rules.',\n             self, self.subparsers)\n@@ -275,6 +284,17 @@\n     def run(self, argv):\n         debug = False\n \n+        parser = self.parser\n+\n+        if len(argv) == 0:\n+            # Print a more user-friendly help string if no arguments are provided\n+            # Note: We only set usage variable for the main parser. If we passed \"usage\" argument\n+            # to the main ArgumentParser class above, this would also set a custom usage string for\n+            # sub-parsers which we don't want.\n+            parser.usage = USAGE_STRING\n+            sys.stderr.write(parser.format_help())\n+            return 2\n+\n         # Provide autocomplete for shell\n         argcomplete.autocomplete(self.parser)\n", "issue": "st2 cli commands in \"usage\" must be in alphabetical order\n\r\n```\r\nusage: st2 [-h] [--version] [--url BASE_URL] [--auth-url AUTH_URL]\r\n           [--api-url API_URL] [--stream-url STREAM_URL]\r\n           [--api-version API_VERSION] [--cacert CACERT]\r\n           [--config-file CONFIG_FILE] [--print-config] [--skip-config]\r\n           [--debug]\r\n           {action,action-alias,auth,apikey,execution,key,login,pack,policy,policy-type,rule,run,runner,sensor,trace,trigger,trigger-instance,webhook,whoami,timer,rule-enforcement,role,role-assignment}\r\n```\r\n\r\nBackstory: someone didn't see `timer` just because they're out of the order. \n", "before_files": [{"content": "#!/usr/bin/env python\n\n# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nCommand-line interface to StackStorm.\n\"\"\"\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\n\nimport sys\nimport argcomplete\nimport argparse\nimport logging\n\nimport six\n\nfrom st2client import __version__\nfrom st2client import models\nfrom st2client.base import BaseCLIApp\nfrom st2client.commands import auth\nfrom st2client.commands import action\nfrom st2client.commands import action_alias\nfrom st2client.commands import keyvalue\nfrom st2client.commands import pack\nfrom st2client.commands import policy\nfrom st2client.commands import resource\nfrom st2client.commands import sensor\nfrom st2client.commands import trace\nfrom st2client.commands import trigger\nfrom st2client.commands import triggerinstance\nfrom st2client.commands import timer\nfrom st2client.commands import webhook\nfrom st2client.commands import rule\nfrom st2client.commands import rule_enforcement\nfrom st2client.commands import rbac\nfrom st2client.config import set_config\nfrom st2client.exceptions.operations import OperationFailureException\nfrom st2client.utils.logging import LogLevelFilter, set_log_level_for_all_loggers\nfrom st2client.commands.auth import TokenCreateCommand\nfrom st2client.commands.auth import LoginCommand\nfrom st2client.commands.auth import WhoamiCommand\n\n\n__all__ = [\n    'Shell'\n]\n\nLOGGER = logging.getLogger(__name__)\n\nCLI_DESCRIPTION = 'CLI for StackStorm event-driven automation platform. https://stackstorm.com'\n\n\nclass Shell(BaseCLIApp):\n    LOG = LOGGER\n\n    SKIP_AUTH_CLASSES = [\n        TokenCreateCommand.__name__,\n        LoginCommand.__name__,\n        WhoamiCommand.__name__\n    ]\n\n    def __init__(self):\n        # Set up of endpoints is delayed until program is run.\n        self.client = None\n\n        # Set up the main parser.\n        self.parser = argparse.ArgumentParser(description=CLI_DESCRIPTION)\n\n        # Set up general program options.\n        self.parser.add_argument(\n            '--version',\n            action='version',\n            version='%(prog)s {version}'.format(version=__version__))\n\n        self.parser.add_argument(\n            '--url',\n            action='store',\n            dest='base_url',\n            default=None,\n            help='Base URL for the API servers. Assumes all servers use the '\n                 'same base URL and default ports are used. Get ST2_BASE_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--auth-url',\n            action='store',\n            dest='auth_url',\n            default=None,\n            help='URL for the authentication service. Get ST2_AUTH_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--api-url',\n            action='store',\n            dest='api_url',\n            default=None,\n            help='URL for the API server. Get ST2_API_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--stream-url',\n            action='store',\n            dest='stream_url',\n            default=None,\n            help='URL for the stream endpoint. Get ST2_STREAM_URL'\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--api-version',\n            action='store',\n            dest='api_version',\n            default=None,\n            help='API version to use. Get ST2_API_VERSION '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--cacert',\n            action='store',\n            dest='cacert',\n            default=None,\n            help='Path to the CA cert bundle for the SSL endpoints. '\n                 'Get ST2_CACERT from the environment variables by default. '\n                 'If this is not provided, then SSL cert will not be verified.'\n        )\n\n        self.parser.add_argument(\n            '--config-file',\n            action='store',\n            dest='config_file',\n            default=None,\n            help='Path to the CLI config file'\n        )\n\n        self.parser.add_argument(\n            '--print-config',\n            action='store_true',\n            dest='print_config',\n            default=False,\n            help='Parse the config file and print the values'\n        )\n\n        self.parser.add_argument(\n            '--skip-config',\n            action='store_true',\n            dest='skip_config',\n            default=False,\n            help='Don\\'t parse and use the CLI config file'\n        )\n\n        self.parser.add_argument(\n            '--debug',\n            action='store_true',\n            dest='debug',\n            default=False,\n            help='Enable debug mode'\n        )\n\n        # Set up list of commands and subcommands.\n        self.subparsers = self.parser.add_subparsers()\n        self.commands = dict()\n\n        self.commands['action'] = action.ActionBranch(\n            'An activity that happens as a response to the external event.',\n            self, self.subparsers)\n\n        self.commands['action-alias'] = action_alias.ActionAliasBranch(\n            'Action aliases.',\n            self, self.subparsers)\n\n        self.commands['auth'] = auth.TokenCreateCommand(\n            models.Token, self, self.subparsers, name='auth')\n\n        self.commands['api-key'] = auth.ApiKeyBranch(\n            'API Keys.',\n            self, self.subparsers)\n\n        self.commands['execution'] = action.ActionExecutionBranch(\n            'An invocation of an action.',\n            self, self.subparsers)\n\n        self.commands['key'] = keyvalue.KeyValuePairBranch(\n            'Key value pair is used to store commonly used configuration '\n            'for reuse in sensors, actions, and rules.',\n            self, self.subparsers)\n\n        self.commands['login'] = auth.LoginCommand(\n            models.Token, self, self.subparsers, name='login')\n\n        self.commands['pack'] = pack.PackBranch(\n            'A group of related integration resources: '\n            'actions, rules, and sensors.',\n            self, self.subparsers)\n\n        self.commands['policy'] = policy.PolicyBranch(\n            'Policy that is enforced on a resource.',\n            self, self.subparsers)\n\n        self.commands['policy-type'] = policy.PolicyTypeBranch(\n            'Type of policy that can be applied to resources.',\n            self, self.subparsers)\n\n        self.commands['rule'] = rule.RuleBranch(\n            'A specification to invoke an \"action\" on a \"trigger\" selectively '\n            'based on some criteria.',\n            self, self.subparsers)\n\n        self.commands['run'] = action.ActionRunCommand(\n            models.Action, self, self.subparsers, name='run', add_help=False)\n\n        self.commands['runner'] = resource.ResourceBranch(\n            models.RunnerType,\n            'Runner is a type of handler for a specific class of actions.',\n            self, self.subparsers, read_only=True, has_disable=True)\n\n        self.commands['sensor'] = sensor.SensorBranch(\n            'An adapter which allows you to integrate StackStorm with external system.',\n            self, self.subparsers)\n\n        self.commands['trace'] = trace.TraceBranch(\n            'A group of executions, rules and triggerinstances that are related.',\n            self, self.subparsers)\n\n        self.commands['trigger'] = trigger.TriggerTypeBranch(\n            'An external event that is mapped to a st2 input. It is the '\n            'st2 invocation point.',\n            self, self.subparsers)\n\n        self.commands['trigger-instance'] = triggerinstance.TriggerInstanceBranch(\n            'Actual instances of triggers received by st2.',\n            self, self.subparsers)\n\n        self.commands['webhook'] = webhook.WebhookBranch(\n            'Webhooks.',\n            self, self.subparsers)\n\n        self.commands['whoami'] = auth.WhoamiCommand(\n            models.Token, self, self.subparsers, name='whoami')\n\n        self.commands['timer'] = timer.TimerBranch(\n            'Timers.',\n            self, self.subparsers)\n\n        self.commands['rule-enforcement'] = rule_enforcement.RuleEnforcementBranch(\n            'Models that represent enforcement of rules.',\n            self, self.subparsers)\n\n        # RBAC\n        self.commands['role'] = rbac.RoleBranch(\n            'RBAC roles.',\n            self, self.subparsers)\n        self.commands['role-assignment'] = rbac.RoleAssignmentBranch(\n            'RBAC role assignments.',\n            self, self.subparsers)\n\n    def run(self, argv):\n        debug = False\n\n        # Provide autocomplete for shell\n        argcomplete.autocomplete(self.parser)\n\n        if '--print-config' in argv:\n            # Hack because --print-config requires no command to be specified\n            argv = argv + ['action', 'list']\n\n        # Parse command line arguments.\n        args = self.parser.parse_args(args=argv)\n\n        print_config = args.print_config\n        if print_config:\n            self._print_config(args=args)\n            return 3\n\n        # Parse config and store it in the config module\n        config = self._parse_config_file(args=args)\n        set_config(config=config)\n\n        # Setup client and run the command\n        try:\n            debug = getattr(args, 'debug', False)\n            if debug:\n                set_log_level_for_all_loggers(level=logging.DEBUG)\n\n            # Set up client.\n            self.client = self.get_client(args=args, debug=debug)\n\n            # Execute command.\n            args.func(args)\n\n            return 0\n        except OperationFailureException as e:\n            if debug:\n                self._print_debug_info(args=args)\n            return 2\n        except Exception as e:\n            # We allow exception to define custom exit codes\n            exit_code = getattr(e, 'exit_code', 1)\n\n            print('ERROR: %s\\n' % e)\n            if debug:\n                self._print_debug_info(args=args)\n\n            return exit_code\n\n    def _print_config(self, args):\n        config = self._parse_config_file(args=args)\n\n        for section, options in six.iteritems(config):\n            print('[%s]' % (section))\n\n            for name, value in six.iteritems(options):\n                print('%s = %s' % (name, value))\n\n\ndef setup_logging(argv):\n    debug = '--debug' in argv\n\n    root = LOGGER\n    root.setLevel(logging.WARNING)\n\n    handler = logging.StreamHandler(sys.stderr)\n    handler.setLevel(logging.WARNING)\n    formatter = logging.Formatter('%(asctime)s  %(levelname)s - %(message)s')\n    handler.setFormatter(formatter)\n\n    if not debug:\n        handler.addFilter(LogLevelFilter(log_levels=[logging.ERROR]))\n\n    root.addHandler(handler)\n\n\ndef main(argv=sys.argv[1:]):\n    setup_logging(argv)\n    return Shell().run(argv)\n\n\nif __name__ == '__main__':\n    sys.exit(main(sys.argv[1:]))\n", "path": "st2client/st2client/shell.py"}], "after_files": [{"content": "#!/usr/bin/env python\n\n# Licensed to the StackStorm, Inc ('StackStorm') under one or more\n# contributor license agreements.  See the NOTICE file distributed with\n# this work for additional information regarding copyright ownership.\n# The ASF licenses this file to You under the Apache License, Version 2.0\n# (the \"License\"); you may not use this file except in compliance with\n# the License.  You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nCommand-line interface to StackStorm.\n\"\"\"\n\nfrom __future__ import print_function\nfrom __future__ import absolute_import\n\nimport sys\nimport argcomplete\nimport argparse\nimport logging\n\nimport six\n\nfrom st2client import __version__\nfrom st2client import models\nfrom st2client.base import BaseCLIApp\nfrom st2client.commands import auth\nfrom st2client.commands import action\nfrom st2client.commands import action_alias\nfrom st2client.commands import keyvalue\nfrom st2client.commands import pack\nfrom st2client.commands import policy\nfrom st2client.commands import resource\nfrom st2client.commands import sensor\nfrom st2client.commands import trace\nfrom st2client.commands import trigger\nfrom st2client.commands import triggerinstance\nfrom st2client.commands import timer\nfrom st2client.commands import webhook\nfrom st2client.commands import rule\nfrom st2client.commands import rule_enforcement\nfrom st2client.commands import rbac\nfrom st2client.config import set_config\nfrom st2client.exceptions.operations import OperationFailureException\nfrom st2client.utils.logging import LogLevelFilter, set_log_level_for_all_loggers\nfrom st2client.commands.auth import TokenCreateCommand\nfrom st2client.commands.auth import LoginCommand\nfrom st2client.commands.auth import WhoamiCommand\n\n\n__all__ = [\n    'Shell'\n]\n\nLOGGER = logging.getLogger(__name__)\n\nCLI_DESCRIPTION = 'CLI for StackStorm event-driven automation platform. https://stackstorm.com'\nUSAGE_STRING = \"\"\"\nUsage: %(prog)s [options] <command> <sub command> [options]\n\nFor example:\n\n    %(prog)s action list --pack=st2\n    %(prog)s run core.local cmd=date\n    %(prog)s --debug run core.local cmd=date\n\"\"\".strip()\n\n\nclass Shell(BaseCLIApp):\n    LOG = LOGGER\n\n    SKIP_AUTH_CLASSES = [\n        TokenCreateCommand.__name__,\n        LoginCommand.__name__,\n        WhoamiCommand.__name__\n    ]\n\n    def __init__(self):\n        # Set up of endpoints is delayed until program is run.\n        self.client = None\n\n        # Set up the main parser.\n        self.parser = argparse.ArgumentParser(description=CLI_DESCRIPTION)\n\n        # Set up general program options.\n        self.parser.add_argument(\n            '--version',\n            action='version',\n            version='%(prog)s {version}'.format(version=__version__))\n\n        self.parser.add_argument(\n            '--url',\n            action='store',\n            dest='base_url',\n            default=None,\n            help='Base URL for the API servers. Assumes all servers use the '\n                 'same base URL and default ports are used. Get ST2_BASE_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--auth-url',\n            action='store',\n            dest='auth_url',\n            default=None,\n            help='URL for the authentication service. Get ST2_AUTH_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--api-url',\n            action='store',\n            dest='api_url',\n            default=None,\n            help='URL for the API server. Get ST2_API_URL '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--stream-url',\n            action='store',\n            dest='stream_url',\n            default=None,\n            help='URL for the stream endpoint. Get ST2_STREAM_URL'\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--api-version',\n            action='store',\n            dest='api_version',\n            default=None,\n            help='API version to use. Get ST2_API_VERSION '\n                 'from the environment variables by default.'\n        )\n\n        self.parser.add_argument(\n            '--cacert',\n            action='store',\n            dest='cacert',\n            default=None,\n            help='Path to the CA cert bundle for the SSL endpoints. '\n                 'Get ST2_CACERT from the environment variables by default. '\n                 'If this is not provided, then SSL cert will not be verified.'\n        )\n\n        self.parser.add_argument(\n            '--config-file',\n            action='store',\n            dest='config_file',\n            default=None,\n            help='Path to the CLI config file'\n        )\n\n        self.parser.add_argument(\n            '--print-config',\n            action='store_true',\n            dest='print_config',\n            default=False,\n            help='Parse the config file and print the values'\n        )\n\n        self.parser.add_argument(\n            '--skip-config',\n            action='store_true',\n            dest='skip_config',\n            default=False,\n            help='Don\\'t parse and use the CLI config file'\n        )\n\n        self.parser.add_argument(\n            '--debug',\n            action='store_true',\n            dest='debug',\n            default=False,\n            help='Enable debug mode'\n        )\n\n        # Set up list of commands and subcommands.\n        self.subparsers = self.parser.add_subparsers()\n        self.commands = {}\n\n        self.commands['run'] = action.ActionRunCommand(\n            models.Action, self, self.subparsers, name='run', add_help=False)\n\n        self.commands['action'] = action.ActionBranch(\n            'An activity that happens as a response to the external event.',\n            self, self.subparsers)\n\n        self.commands['action-alias'] = action_alias.ActionAliasBranch(\n            'Action aliases.',\n            self, self.subparsers)\n\n        self.commands['auth'] = auth.TokenCreateCommand(\n            models.Token, self, self.subparsers, name='auth')\n\n        self.commands['login'] = auth.LoginCommand(\n            models.Token, self, self.subparsers, name='login')\n\n        self.commands['whoami'] = auth.WhoamiCommand(\n            models.Token, self, self.subparsers, name='whoami')\n\n        self.commands['api-key'] = auth.ApiKeyBranch(\n            'API Keys.',\n            self, self.subparsers)\n\n        self.commands['execution'] = action.ActionExecutionBranch(\n            'An invocation of an action.',\n            self, self.subparsers)\n\n        self.commands['key'] = keyvalue.KeyValuePairBranch(\n            'Key value pair is used to store commonly used configuration '\n            'for reuse in sensors, actions, and rules.',\n            self, self.subparsers)\n\n        self.commands['pack'] = pack.PackBranch(\n            'A group of related integration resources: '\n            'actions, rules, and sensors.',\n            self, self.subparsers)\n\n        self.commands['policy'] = policy.PolicyBranch(\n            'Policy that is enforced on a resource.',\n            self, self.subparsers)\n\n        self.commands['policy-type'] = policy.PolicyTypeBranch(\n            'Type of policy that can be applied to resources.',\n            self, self.subparsers)\n\n        self.commands['rule'] = rule.RuleBranch(\n            'A specification to invoke an \"action\" on a \"trigger\" selectively '\n            'based on some criteria.',\n            self, self.subparsers)\n\n        self.commands['webhook'] = webhook.WebhookBranch(\n            'Webhooks.',\n            self, self.subparsers)\n\n        self.commands['timer'] = timer.TimerBranch(\n            'Timers.',\n            self, self.subparsers)\n\n        self.commands['runner'] = resource.ResourceBranch(\n            models.RunnerType,\n            'Runner is a type of handler for a specific class of actions.',\n            self, self.subparsers, read_only=True, has_disable=True)\n\n        self.commands['sensor'] = sensor.SensorBranch(\n            'An adapter which allows you to integrate StackStorm with external system.',\n            self, self.subparsers)\n\n        self.commands['trace'] = trace.TraceBranch(\n            'A group of executions, rules and triggerinstances that are related.',\n            self, self.subparsers)\n\n        self.commands['trigger'] = trigger.TriggerTypeBranch(\n            'An external event that is mapped to a st2 input. It is the '\n            'st2 invocation point.',\n            self, self.subparsers)\n\n        self.commands['trigger-instance'] = triggerinstance.TriggerInstanceBranch(\n            'Actual instances of triggers received by st2.',\n            self, self.subparsers)\n\n        self.commands['rule-enforcement'] = rule_enforcement.RuleEnforcementBranch(\n            'Models that represent enforcement of rules.',\n            self, self.subparsers)\n\n        # RBAC\n        self.commands['role'] = rbac.RoleBranch(\n            'RBAC roles.',\n            self, self.subparsers)\n        self.commands['role-assignment'] = rbac.RoleAssignmentBranch(\n            'RBAC role assignments.',\n            self, self.subparsers)\n\n    def run(self, argv):\n        debug = False\n\n        parser = self.parser\n\n        if len(argv) == 0:\n            # Print a more user-friendly help string if no arguments are provided\n            # Note: We only set usage variable for the main parser. If we passed \"usage\" argument\n            # to the main ArgumentParser class above, this would also set a custom usage string for\n            # sub-parsers which we don't want.\n            parser.usage = USAGE_STRING\n            sys.stderr.write(parser.format_help())\n            return 2\n\n        # Provide autocomplete for shell\n        argcomplete.autocomplete(self.parser)\n\n        if '--print-config' in argv:\n            # Hack because --print-config requires no command to be specified\n            argv = argv + ['action', 'list']\n\n        # Parse command line arguments.\n        args = self.parser.parse_args(args=argv)\n\n        print_config = args.print_config\n        if print_config:\n            self._print_config(args=args)\n            return 3\n\n        # Parse config and store it in the config module\n        config = self._parse_config_file(args=args)\n        set_config(config=config)\n\n        # Setup client and run the command\n        try:\n            debug = getattr(args, 'debug', False)\n            if debug:\n                set_log_level_for_all_loggers(level=logging.DEBUG)\n\n            # Set up client.\n            self.client = self.get_client(args=args, debug=debug)\n\n            # Execute command.\n            args.func(args)\n\n            return 0\n        except OperationFailureException as e:\n            if debug:\n                self._print_debug_info(args=args)\n            return 2\n        except Exception as e:\n            # We allow exception to define custom exit codes\n            exit_code = getattr(e, 'exit_code', 1)\n\n            print('ERROR: %s\\n' % e)\n            if debug:\n                self._print_debug_info(args=args)\n\n            return exit_code\n\n    def _print_config(self, args):\n        config = self._parse_config_file(args=args)\n\n        for section, options in six.iteritems(config):\n            print('[%s]' % (section))\n\n            for name, value in six.iteritems(options):\n                print('%s = %s' % (name, value))\n\n\ndef setup_logging(argv):\n    debug = '--debug' in argv\n\n    root = LOGGER\n    root.setLevel(logging.WARNING)\n\n    handler = logging.StreamHandler(sys.stderr)\n    handler.setLevel(logging.WARNING)\n    formatter = logging.Formatter('%(asctime)s  %(levelname)s - %(message)s')\n    handler.setFormatter(formatter)\n\n    if not debug:\n        handler.addFilter(LogLevelFilter(log_levels=[logging.ERROR]))\n\n    root.addHandler(handler)\n\n\ndef main(argv=sys.argv[1:]):\n    setup_logging(argv)\n    return Shell().run(argv)\n\n\nif __name__ == '__main__':\n    sys.exit(main(sys.argv[1:]))\n", "path": "st2client/st2client/shell.py"}]}