forked from softlayer/softlayer-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcore.py
211 lines (178 loc) · 7.12 KB
/
core.py
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 traceback
import click
import requests
from rich.markup import escape
import SoftLayer
from SoftLayer.CLI.command import CommandLoader
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
}
PROG_NAME = "slcli (SoftLayer Command-line)"
VALID_FORMATS = ['table', 'raw', 'json', 'jsonraw', 'csv']
DEFAULT_FORMAT = 'raw'
if sys.stdout.isatty():
DEFAULT_FORMAT = 'table'
def get_latest_version():
"""Gets the latest version of the Softlayer library."""
try:
result = requests.get('https://pypi.org/pypi/SoftLayer/json', timeout=60)
json_result = result.json()
latest = 'v{}'.format(json_result['info']['version'])
except Exception:
latest = "Unable to get version from pypi."
return latest
CONTEXT_SETTINGS = dict(
help_option_names=['--help', '-h'],
auto_envvar_prefix='SLCLI',
max_content_width=999
)
def get_version_message(ctx, param, value):
"""Gets current and latest release versions message."""
if not value or ctx.resilient_parsing:
return
current = SoftLayer.consts.VERSION
latest = get_latest_version()
click.secho("Current: {prog} {current}\nLatest: {prog} {latest}".format(
prog=PROG_NAME, current=current, latest=latest))
ctx.exit()
@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=CONTEXT_SETTINGS)
@click.option('--format',
default=DEFAULT_FORMAT,
show_default=True,
help="Output format",
type=click.Choice(VALID_FORMATS))
@click.option('-C', '--config',
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="HTTPS or HTTP 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.option('--version', is_flag=True, expose_value=False, is_eager=True, callback=get_version_message,
help="Show version information.", allow_from_autoenv=False,)
@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 environment 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.vars['verbose'] = verbose
env.client.transport = env.vars['_timings']
@cli.result_callback()
@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 = formatting.Table(['API Calls'], title=None, align="left")
for call in env.client.transport.get_last_calls():
api_call_value.add_row(["%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)], align="left")
nice_mask = ''
if call.mask is not None:
nice_mask = call.mask
call_table.add_row(['id', call.identifier])
# Need to escape this so Rich doesn't think the mask is a tag and hide it.
call_table.add_row(['mask', escape(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
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()