forked from softlayer/softlayer-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.py
More file actions
211 lines (176 loc) · 6.89 KB
/
core.py
File metadata and controls
211 lines (176 loc) · 6.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
"""
SoftLayer.CLI.core
~~~~~~~~~~~~~~~~~~
Core for the SoftLayer CLI
:license: MIT, see LICENSE for more details.
"""
import logging
import os
import sys
import time
import types
import click
import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import exceptions
from SoftLayer.CLI import formatting
from SoftLayer import consts
# pylint: disable=too-many-public-methods, broad-except, unused-argument
# pylint: disable=redefined-builtin, super-init-not-called, arguments-differ
START_TIME = time.time()
DEBUG_LOGGING_MAP = {
0: logging.CRITICAL,
1: logging.WARNING,
2: logging.INFO,
3: logging.DEBUG
}
VALID_FORMATS = ['table', 'raw', 'json', 'jsonraw']
DEFAULT_FORMAT = 'raw'
if sys.stdout.isatty():
DEFAULT_FORMAT = 'table'
class CommandLoader(click.MultiCommand):
"""Loads module for click."""
def __init__(self, *path, **attrs):
click.MultiCommand.__init__(self, **attrs)
self.path = path
def list_commands(self, ctx):
"""List all sub-commands."""
env = ctx.ensure_object(environment.Environment)
env.load()
return sorted(env.list_commands(*self.path))
def get_command(self, ctx, name):
"""Get command for click."""
env = ctx.ensure_object(environment.Environment)
env.load()
# Do alias lookup (only available for root commands)
if len(self.path) == 0:
name = env.resolve_alias(name)
new_path = list(self.path)
new_path.append(name)
module = env.get_command(*new_path)
if isinstance(module, types.ModuleType):
return CommandLoader(*new_path, help=module.__doc__ or '')
else:
return module
@click.group(help="SoftLayer Command-line Client",
epilog="""To use most commands your SoftLayer
username and api_key need to be configured. The easiest way to do that is to
use: 'slcli setup'""",
cls=CommandLoader,
context_settings={'help_option_names': ['-h', '--help'],
'auto_envvar_prefix': 'SLCLI',
'max_content_width': 999})
@click.option('--format',
default=DEFAULT_FORMAT,
show_default=True,
help="Output format",
type=click.Choice(VALID_FORMATS))
@click.option('--config', '-C',
required=False,
default=click.get_app_dir('softlayer', force_posix=True),
show_default=True,
help="Config file location",
type=click.Path(resolve_path=True))
@click.option('--verbose', '-v',
help="Sets the debug noise level, specify multiple times for more verbosity.",
type=click.IntRange(0, 3, clamp=True),
count=True)
@click.option('--proxy',
required=False,
help="HTTP[S] proxy to be use to make API calls")
@click.option('--really / --not-really', '-y',
is_flag=True,
required=False,
help="Confirm all prompt actions")
@click.option('--demo / --no-demo',
is_flag=True,
required=False,
help="Use demo data instead of actually making API calls")
@click.version_option(prog_name="slcli (SoftLayer Command-line)")
@environment.pass_env
def cli(env,
format='table',
config=None,
verbose=0,
proxy=None,
really=False,
demo=False,
**kwargs):
"""Main click CLI entry-point."""
# Populate environement with client and set it as the context object
env.skip_confirmations = really
env.config_file = config
env.format = format
env.ensure_client(config_file=config, is_demo=demo, proxy=proxy)
env.vars['_start'] = time.time()
logger = logging.getLogger()
if demo is False:
logger.addHandler(logging.StreamHandler())
else:
# This section is for running CLI tests.
logging.getLogger("urllib3").setLevel(logging.WARNING)
logger.addHandler(logging.NullHandler())
logger.setLevel(DEBUG_LOGGING_MAP.get(verbose, logging.DEBUG))
env.vars['_timings'] = SoftLayer.DebugTransport(env.client.transport)
env.client.transport = env.vars['_timings']
@cli.resultcallback()
@environment.pass_env
def output_diagnostics(env, result, verbose=0, **kwargs):
"""Output diagnostic information."""
if verbose > 0:
diagnostic_table = formatting.Table(['name', 'value'])
diagnostic_table.add_row(['execution_time', '%fs' % (time.time() - START_TIME)])
api_call_value = []
for call in env.client.transport.get_last_calls():
api_call_value.append("%s::%s (%fs)" % (call.service, call.method, call.end_time - call.start_time))
diagnostic_table.add_row(['api_calls', api_call_value])
diagnostic_table.add_row(['version', consts.USER_AGENT])
diagnostic_table.add_row(['python_version', sys.version])
diagnostic_table.add_row(['library_location', os.path.dirname(SoftLayer.__file__)])
env.err(env.fmt(diagnostic_table))
if verbose > 1:
for call in env.client.transport.get_last_calls():
call_table = formatting.Table(['', '{}::{}'.format(call.service, call.method)])
nice_mask = ''
if call.mask is not None:
nice_mask = call.mask
call_table.add_row(['id', call.identifier])
call_table.add_row(['mask', nice_mask])
call_table.add_row(['filter', call.filter])
call_table.add_row(['limit', call.limit])
call_table.add_row(['offset', call.offset])
env.err(env.fmt(call_table))
if verbose > 2:
for call in env.client.transport.get_last_calls():
env.err(env.client.transport.print_reproduceable(call))
def main(reraise_exceptions=False, **kwargs):
"""Main program. Catches several common errors and displays them nicely."""
exit_status = 0
try:
cli.main(**kwargs)
except SoftLayer.SoftLayerAPIError as ex:
if 'invalid api token' in ex.faultString.lower():
print("Authentication Failed: To update your credentials, use 'slcli config setup'")
exit_status = 1
else:
print(str(ex))
exit_status = 1
except SoftLayer.SoftLayerError as ex:
print(str(ex))
exit_status = 1
except exceptions.CLIAbort as ex:
print(str(ex.message))
exit_status = ex.code
except Exception:
if reraise_exceptions:
raise
import traceback
print("An unexpected error has occured:")
print(str(traceback.format_exc()))
print("Feel free to report this error as it is likely a bug:")
print(" https://github.com/softlayer/softlayer-python/issues")
print("The following snippet should be able to reproduce the error")
exit_status = 1
sys.exit(exit_status)
if __name__ == '__main__':
main()