Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/roboto/awsqueryrequest.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 # Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ | |
| 2 # Copyright (c) 2010, Eucalyptus Systems, Inc. | |
| 3 # | |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 # copy of this software and associated documentation files (the | |
| 6 # "Software"), to deal in the Software without restriction, including | |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 10 # lowing conditions: | |
| 11 # | |
| 12 # The above copyright notice and this permission notice shall be included | |
| 13 # in all copies or substantial portions of the Software. | |
| 14 # | |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 21 # IN THE SOFTWARE. | |
| 22 import sys | |
| 23 import os | |
| 24 import boto | |
| 25 import optparse | |
| 26 import copy | |
| 27 import boto.exception | |
| 28 import boto.roboto.awsqueryservice | |
| 29 | |
| 30 import bdb | |
| 31 import traceback | |
| 32 try: | |
| 33 import epdb as debugger | |
| 34 except ImportError: | |
| 35 import pdb as debugger | |
| 36 | |
| 37 def boto_except_hook(debugger_flag, debug_flag): | |
| 38 def excepthook(typ, value, tb): | |
| 39 if typ is bdb.BdbQuit: | |
| 40 sys.exit(1) | |
| 41 sys.excepthook = sys.__excepthook__ | |
| 42 | |
| 43 if debugger_flag and sys.stdout.isatty() and sys.stdin.isatty(): | |
| 44 if debugger.__name__ == 'epdb': | |
| 45 debugger.post_mortem(tb, typ, value) | |
| 46 else: | |
| 47 debugger.post_mortem(tb) | |
| 48 elif debug_flag: | |
| 49 print(traceback.print_tb(tb)) | |
| 50 sys.exit(1) | |
| 51 else: | |
| 52 print(value) | |
| 53 sys.exit(1) | |
| 54 | |
| 55 return excepthook | |
| 56 | |
| 57 class Line(object): | |
| 58 | |
| 59 def __init__(self, fmt, data, label): | |
| 60 self.fmt = fmt | |
| 61 self.data = data | |
| 62 self.label = label | |
| 63 self.line = '%s\t' % label | |
| 64 self.printed = False | |
| 65 | |
| 66 def append(self, datum): | |
| 67 self.line += '%s\t' % datum | |
| 68 | |
| 69 def print_it(self): | |
| 70 if not self.printed: | |
| 71 print(self.line) | |
| 72 self.printed = True | |
| 73 | |
| 74 class RequiredParamError(boto.exception.BotoClientError): | |
| 75 | |
| 76 def __init__(self, required): | |
| 77 self.required = required | |
| 78 s = 'Required parameters are missing: %s' % self.required | |
| 79 super(RequiredParamError, self).__init__(s) | |
| 80 | |
| 81 class EncoderError(boto.exception.BotoClientError): | |
| 82 | |
| 83 def __init__(self, error_msg): | |
| 84 s = 'Error encoding value (%s)' % error_msg | |
| 85 super(EncoderError, self).__init__(s) | |
| 86 | |
| 87 class FilterError(boto.exception.BotoClientError): | |
| 88 | |
| 89 def __init__(self, filters): | |
| 90 self.filters = filters | |
| 91 s = 'Unknown filters: %s' % self.filters | |
| 92 super(FilterError, self).__init__(s) | |
| 93 | |
| 94 class Encoder(object): | |
| 95 | |
| 96 @classmethod | |
| 97 def encode(cls, p, rp, v, label=None): | |
| 98 if p.name.startswith('_'): | |
| 99 return | |
| 100 try: | |
| 101 mthd = getattr(cls, 'encode_'+p.ptype) | |
| 102 mthd(p, rp, v, label) | |
| 103 except AttributeError: | |
| 104 raise EncoderError('Unknown type: %s' % p.ptype) | |
| 105 | |
| 106 @classmethod | |
| 107 def encode_string(cls, p, rp, v, l): | |
| 108 if l: | |
| 109 label = l | |
| 110 else: | |
| 111 label = p.name | |
| 112 rp[label] = v | |
| 113 | |
| 114 encode_file = encode_string | |
| 115 encode_enum = encode_string | |
| 116 | |
| 117 @classmethod | |
| 118 def encode_integer(cls, p, rp, v, l): | |
| 119 if l: | |
| 120 label = l | |
| 121 else: | |
| 122 label = p.name | |
| 123 rp[label] = '%d' % v | |
| 124 | |
| 125 @classmethod | |
| 126 def encode_boolean(cls, p, rp, v, l): | |
| 127 if l: | |
| 128 label = l | |
| 129 else: | |
| 130 label = p.name | |
| 131 if v: | |
| 132 v = 'true' | |
| 133 else: | |
| 134 v = 'false' | |
| 135 rp[label] = v | |
| 136 | |
| 137 @classmethod | |
| 138 def encode_datetime(cls, p, rp, v, l): | |
| 139 if l: | |
| 140 label = l | |
| 141 else: | |
| 142 label = p.name | |
| 143 rp[label] = v | |
| 144 | |
| 145 @classmethod | |
| 146 def encode_array(cls, p, rp, v, l): | |
| 147 v = boto.utils.mklist(v) | |
| 148 if l: | |
| 149 label = l | |
| 150 else: | |
| 151 label = p.name | |
| 152 label = label + '.%d' | |
| 153 for i, value in enumerate(v): | |
| 154 rp[label%(i+1)] = value | |
| 155 | |
| 156 class AWSQueryRequest(object): | |
| 157 | |
| 158 ServiceClass = None | |
| 159 | |
| 160 Description = '' | |
| 161 Params = [] | |
| 162 Args = [] | |
| 163 Filters = [] | |
| 164 Response = {} | |
| 165 | |
| 166 CLITypeMap = {'string' : 'string', | |
| 167 'integer' : 'int', | |
| 168 'int' : 'int', | |
| 169 'enum' : 'choice', | |
| 170 'datetime' : 'string', | |
| 171 'dateTime' : 'string', | |
| 172 'file' : 'string', | |
| 173 'boolean' : None} | |
| 174 | |
| 175 @classmethod | |
| 176 def name(cls): | |
| 177 return cls.__name__ | |
| 178 | |
| 179 def __init__(self, **args): | |
| 180 self.args = args | |
| 181 self.parser = None | |
| 182 self.cli_options = None | |
| 183 self.cli_args = None | |
| 184 self.cli_output_format = None | |
| 185 self.connection = None | |
| 186 self.list_markers = [] | |
| 187 self.item_markers = [] | |
| 188 self.request_params = {} | |
| 189 self.connection_args = None | |
| 190 | |
| 191 def __repr__(self): | |
| 192 return self.name() | |
| 193 | |
| 194 def get_connection(self, **args): | |
| 195 if self.connection is None: | |
| 196 self.connection = self.ServiceClass(**args) | |
| 197 return self.connection | |
| 198 | |
| 199 @property | |
| 200 def status(self): | |
| 201 retval = None | |
| 202 if self.http_response is not None: | |
| 203 retval = self.http_response.status | |
| 204 return retval | |
| 205 | |
| 206 @property | |
| 207 def reason(self): | |
| 208 retval = None | |
| 209 if self.http_response is not None: | |
| 210 retval = self.http_response.reason | |
| 211 return retval | |
| 212 | |
| 213 @property | |
| 214 def request_id(self): | |
| 215 retval = None | |
| 216 if self.aws_response is not None: | |
| 217 retval = getattr(self.aws_response, 'requestId') | |
| 218 return retval | |
| 219 | |
| 220 def process_filters(self): | |
| 221 filters = self.args.get('filters', []) | |
| 222 filter_names = [f['name'] for f in self.Filters] | |
| 223 unknown_filters = [f for f in filters if f not in filter_names] | |
| 224 if unknown_filters: | |
| 225 raise FilterError('Unknown filters: %s' % unknown_filters) | |
| 226 for i, filter in enumerate(self.Filters): | |
| 227 name = filter['name'] | |
| 228 if name in filters: | |
| 229 self.request_params['Filter.%d.Name' % (i+1)] = name | |
| 230 for j, value in enumerate(boto.utils.mklist(filters[name])): | |
| 231 Encoder.encode(filter, self.request_params, value, | |
| 232 'Filter.%d.Value.%d' % (i+1, j+1)) | |
| 233 | |
| 234 def process_args(self, **args): | |
| 235 """ | |
| 236 Responsible for walking through Params defined for the request and: | |
| 237 | |
| 238 * Matching them with keyword parameters passed to the request | |
| 239 constructor or via the command line. | |
| 240 * Checking to see if all required parameters have been specified | |
| 241 and raising an exception, if not. | |
| 242 * Encoding each value into the set of request parameters that will | |
| 243 be sent in the request to the AWS service. | |
| 244 """ | |
| 245 self.args.update(args) | |
| 246 self.connection_args = copy.copy(self.args) | |
| 247 if 'debug' in self.args and self.args['debug'] >= 2: | |
| 248 boto.set_stream_logger(self.name()) | |
| 249 required = [p.name for p in self.Params+self.Args if not p.optional] | |
| 250 for param in self.Params+self.Args: | |
| 251 if param.long_name: | |
| 252 python_name = param.long_name.replace('-', '_') | |
| 253 else: | |
| 254 python_name = boto.utils.pythonize_name(param.name, '_') | |
| 255 value = None | |
| 256 if python_name in self.args: | |
| 257 value = self.args[python_name] | |
| 258 if value is None: | |
| 259 value = param.default | |
| 260 if value is not None: | |
| 261 if param.name in required: | |
| 262 required.remove(param.name) | |
| 263 if param.request_param: | |
| 264 if param.encoder: | |
| 265 param.encoder(param, self.request_params, value) | |
| 266 else: | |
| 267 Encoder.encode(param, self.request_params, value) | |
| 268 if python_name in self.args: | |
| 269 del self.connection_args[python_name] | |
| 270 if required: | |
| 271 l = [] | |
| 272 for p in self.Params+self.Args: | |
| 273 if p.name in required: | |
| 274 if p.short_name and p.long_name: | |
| 275 l.append('(%s, %s)' % (p.optparse_short_name, | |
| 276 p.optparse_long_name)) | |
| 277 elif p.short_name: | |
| 278 l.append('(%s)' % p.optparse_short_name) | |
| 279 else: | |
| 280 l.append('(%s)' % p.optparse_long_name) | |
| 281 raise RequiredParamError(','.join(l)) | |
| 282 boto.log.debug('request_params: %s' % self.request_params) | |
| 283 self.process_markers(self.Response) | |
| 284 | |
| 285 def process_markers(self, fmt, prev_name=None): | |
| 286 if fmt and fmt['type'] == 'object': | |
| 287 for prop in fmt['properties']: | |
| 288 self.process_markers(prop, fmt['name']) | |
| 289 elif fmt and fmt['type'] == 'array': | |
| 290 self.list_markers.append(prev_name) | |
| 291 self.item_markers.append(fmt['name']) | |
| 292 | |
| 293 def send(self, verb='GET', **args): | |
| 294 self.process_args(**args) | |
| 295 self.process_filters() | |
| 296 conn = self.get_connection(**self.connection_args) | |
| 297 self.http_response = conn.make_request(self.name(), | |
| 298 self.request_params, | |
| 299 verb=verb) | |
| 300 self.body = self.http_response.read() | |
| 301 boto.log.debug(self.body) | |
| 302 if self.http_response.status == 200: | |
| 303 self.aws_response = boto.jsonresponse.Element(list_marker=self.list_markers, | |
| 304 item_marker=self.item_markers) | |
| 305 h = boto.jsonresponse.XmlHandler(self.aws_response, self) | |
| 306 h.parse(self.body) | |
| 307 return self.aws_response | |
| 308 else: | |
| 309 boto.log.error('%s %s' % (self.http_response.status, | |
| 310 self.http_response.reason)) | |
| 311 boto.log.error('%s' % self.body) | |
| 312 raise conn.ResponseError(self.http_response.status, | |
| 313 self.http_response.reason, | |
| 314 self.body) | |
| 315 | |
| 316 def add_standard_options(self): | |
| 317 group = optparse.OptionGroup(self.parser, 'Standard Options') | |
| 318 # add standard options that all commands get | |
| 319 group.add_option('-D', '--debug', action='store_true', | |
| 320 help='Turn on all debugging output') | |
| 321 group.add_option('--debugger', action='store_true', | |
| 322 default=False, | |
| 323 help='Enable interactive debugger on error') | |
| 324 group.add_option('-U', '--url', action='store', | |
| 325 help='Override service URL with value provided') | |
| 326 group.add_option('--region', action='store', | |
| 327 help='Name of the region to connect to') | |
| 328 group.add_option('-I', '--access-key-id', action='store', | |
| 329 help='Override access key value') | |
| 330 group.add_option('-S', '--secret-key', action='store', | |
| 331 help='Override secret key value') | |
| 332 group.add_option('--version', action='store_true', | |
| 333 help='Display version string') | |
| 334 if self.Filters: | |
| 335 self.group.add_option('--help-filters', action='store_true', | |
| 336 help='Display list of available filters') | |
| 337 self.group.add_option('--filter', action='append', | |
| 338 metavar=' name=value', | |
| 339 help='A filter for limiting the results') | |
| 340 self.parser.add_option_group(group) | |
| 341 | |
| 342 def process_standard_options(self, options, args, d): | |
| 343 if hasattr(options, 'help_filters') and options.help_filters: | |
| 344 print('Available filters:') | |
| 345 for filter in self.Filters: | |
| 346 print('%s\t%s' % (filter.name, filter.doc)) | |
| 347 sys.exit(0) | |
| 348 if options.debug: | |
| 349 self.args['debug'] = 2 | |
| 350 if options.url: | |
| 351 self.args['url'] = options.url | |
| 352 if options.region: | |
| 353 self.args['region'] = options.region | |
| 354 if options.access_key_id: | |
| 355 self.args['aws_access_key_id'] = options.access_key_id | |
| 356 if options.secret_key: | |
| 357 self.args['aws_secret_access_key'] = options.secret_key | |
| 358 if options.version: | |
| 359 # TODO - Where should the version # come from? | |
| 360 print('version x.xx') | |
| 361 exit(0) | |
| 362 sys.excepthook = boto_except_hook(options.debugger, | |
| 363 options.debug) | |
| 364 | |
| 365 def get_usage(self): | |
| 366 s = 'usage: %prog [options] ' | |
| 367 l = [ a.long_name for a in self.Args ] | |
| 368 s += ' '.join(l) | |
| 369 for a in self.Args: | |
| 370 if a.doc: | |
| 371 s += '\n\n\t%s - %s' % (a.long_name, a.doc) | |
| 372 return s | |
| 373 | |
| 374 def build_cli_parser(self): | |
| 375 self.parser = optparse.OptionParser(description=self.Description, | |
| 376 usage=self.get_usage()) | |
| 377 self.add_standard_options() | |
| 378 for param in self.Params: | |
| 379 ptype = action = choices = None | |
| 380 if param.ptype in self.CLITypeMap: | |
| 381 ptype = self.CLITypeMap[param.ptype] | |
| 382 action = 'store' | |
| 383 if param.ptype == 'boolean': | |
| 384 action = 'store_true' | |
| 385 elif param.ptype == 'array': | |
| 386 if len(param.items) == 1: | |
| 387 ptype = param.items[0]['type'] | |
| 388 action = 'append' | |
| 389 elif param.cardinality != 1: | |
| 390 action = 'append' | |
| 391 if ptype or action == 'store_true': | |
| 392 if param.short_name: | |
| 393 self.parser.add_option(param.optparse_short_name, | |
| 394 param.optparse_long_name, | |
| 395 action=action, type=ptype, | |
| 396 choices=param.choices, | |
| 397 help=param.doc) | |
| 398 elif param.long_name: | |
| 399 self.parser.add_option(param.optparse_long_name, | |
| 400 action=action, type=ptype, | |
| 401 choices=param.choices, | |
| 402 help=param.doc) | |
| 403 | |
| 404 def do_cli(self): | |
| 405 if not self.parser: | |
| 406 self.build_cli_parser() | |
| 407 self.cli_options, self.cli_args = self.parser.parse_args() | |
| 408 d = {} | |
| 409 self.process_standard_options(self.cli_options, self.cli_args, d) | |
| 410 for param in self.Params: | |
| 411 if param.long_name: | |
| 412 p_name = param.long_name.replace('-', '_') | |
| 413 else: | |
| 414 p_name = boto.utils.pythonize_name(param.name) | |
| 415 value = getattr(self.cli_options, p_name) | |
| 416 if param.ptype == 'file' and value: | |
| 417 if value == '-': | |
| 418 value = sys.stdin.read() | |
| 419 else: | |
| 420 path = os.path.expanduser(value) | |
| 421 path = os.path.expandvars(path) | |
| 422 if os.path.isfile(path): | |
| 423 fp = open(path) | |
| 424 value = fp.read() | |
| 425 fp.close() | |
| 426 else: | |
| 427 self.parser.error('Unable to read file: %s' % path) | |
| 428 d[p_name] = value | |
| 429 for arg in self.Args: | |
| 430 if arg.long_name: | |
| 431 p_name = arg.long_name.replace('-', '_') | |
| 432 else: | |
| 433 p_name = boto.utils.pythonize_name(arg.name) | |
| 434 value = None | |
| 435 if arg.cardinality == 1: | |
| 436 if len(self.cli_args) >= 1: | |
| 437 value = self.cli_args[0] | |
| 438 else: | |
| 439 value = self.cli_args | |
| 440 d[p_name] = value | |
| 441 self.args.update(d) | |
| 442 if hasattr(self.cli_options, 'filter') and self.cli_options.filter: | |
| 443 d = {} | |
| 444 for filter in self.cli_options.filter: | |
| 445 name, value = filter.split('=') | |
| 446 d[name] = value | |
| 447 if 'filters' in self.args: | |
| 448 self.args['filters'].update(d) | |
| 449 else: | |
| 450 self.args['filters'] = d | |
| 451 try: | |
| 452 response = self.main() | |
| 453 self.cli_formatter(response) | |
| 454 except RequiredParamError as e: | |
| 455 print(e) | |
| 456 sys.exit(1) | |
| 457 except self.ServiceClass.ResponseError as err: | |
| 458 print('Error(%s): %s' % (err.error_code, err.error_message)) | |
| 459 sys.exit(1) | |
| 460 except boto.roboto.awsqueryservice.NoCredentialsError as err: | |
| 461 print('Unable to find credentials.') | |
| 462 sys.exit(1) | |
| 463 except Exception as e: | |
| 464 print(e) | |
| 465 sys.exit(1) | |
| 466 | |
| 467 def _generic_cli_formatter(self, fmt, data, label=''): | |
| 468 if fmt['type'] == 'object': | |
| 469 for prop in fmt['properties']: | |
| 470 if 'name' in fmt: | |
| 471 if fmt['name'] in data: | |
| 472 data = data[fmt['name']] | |
| 473 if fmt['name'] in self.list_markers: | |
| 474 label = fmt['name'] | |
| 475 if label[-1] == 's': | |
| 476 label = label[0:-1] | |
| 477 label = label.upper() | |
| 478 self._generic_cli_formatter(prop, data, label) | |
| 479 elif fmt['type'] == 'array': | |
| 480 for item in data: | |
| 481 line = Line(fmt, item, label) | |
| 482 if isinstance(item, dict): | |
| 483 for field_name in item: | |
| 484 line.append(item[field_name]) | |
| 485 elif isinstance(item, basestring): | |
| 486 line.append(item) | |
| 487 line.print_it() | |
| 488 | |
| 489 def cli_formatter(self, data): | |
| 490 """ | |
| 491 This method is responsible for formatting the output for the | |
| 492 command line interface. The default behavior is to call the | |
| 493 generic CLI formatter which attempts to print something | |
| 494 reasonable. If you want specific formatting, you should | |
| 495 override this method and do your own thing. | |
| 496 | |
| 497 :type data: dict | |
| 498 :param data: The data returned by AWS. | |
| 499 """ | |
| 500 if data: | |
| 501 self._generic_cli_formatter(self.Response, data) | |
| 502 | |
| 503 |
