1# Copyright (c) 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved 2# 3# Permission is hereby granted, free of charge, to any person obtaining a 4# copy of this software and associated documentation files (the 5# "Software"), to deal in the Software without restriction, including 6# without limitation the rights to use, copy, modify, merge, publish, dis- 7# tribute, sublicense, and/or sell copies of the Software, and to permit 8# persons to whom the Software is furnished to do so, subject to the fol- 9# lowing conditions: 10# 11# The above copyright notice and this permission notice shall be included 12# in all copies or substantial portions of the Software. 13# 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 17# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20# IN THE SOFTWARE. 21# 22 23import boto 24from boto.compat import json 25from boto.connection import AWSQueryConnection 26from boto.regioninfo import RegionInfo 27from boto.exception import JSONResponseError 28from boto.support import exceptions 29 30 31class SupportConnection(AWSQueryConnection): 32 """ 33 AWS Support 34 The AWS Support API reference is intended for programmers who need 35 detailed information about the AWS Support operations and data 36 types. This service enables you to manage your AWS Support cases 37 programmatically. It uses HTTP methods that return results in JSON 38 format. 39 40 The AWS Support service also exposes a set of `Trusted Advisor`_ 41 features. You can retrieve a list of checks and their 42 descriptions, get check results, specify checks to refresh, and 43 get the refresh status of checks. 44 45 The following list describes the AWS Support case management 46 operations: 47 48 49 + **Service names, issue categories, and available severity 50 levels. **The DescribeServices and DescribeSeverityLevels 51 operations return AWS service names, service codes, service 52 categories, and problem severity levels. You use these values when 53 you call the CreateCase operation. 54 + **Case creation, case details, and case resolution.** The 55 CreateCase, DescribeCases, DescribeAttachment, and ResolveCase 56 operations create AWS Support cases, retrieve information about 57 cases, and resolve cases. 58 + **Case communication.** The DescribeCommunications, 59 AddCommunicationToCase, and AddAttachmentsToSet operations 60 retrieve and add communications and attachments to AWS Support 61 cases. 62 63 64 The following list describes the operations available from the AWS 65 Support service for Trusted Advisor: 66 67 68 + DescribeTrustedAdvisorChecks returns the list of checks that run 69 against your AWS resources. 70 + Using the `CheckId` for a specific check returned by 71 DescribeTrustedAdvisorChecks, you can call 72 DescribeTrustedAdvisorCheckResult to obtain the results for the 73 check you specified. 74 + DescribeTrustedAdvisorCheckSummaries returns summarized results 75 for one or more Trusted Advisor checks. 76 + RefreshTrustedAdvisorCheck requests that Trusted Advisor rerun a 77 specified check. 78 + DescribeTrustedAdvisorCheckRefreshStatuses reports the refresh 79 status of one or more checks. 80 81 82 For authentication of requests, AWS Support uses `Signature 83 Version 4 Signing Process`_. 84 85 See `About the AWS Support API`_ in the AWS Support User Guide for 86 information about how to use this service to create and manage 87 your support cases, and how to call Trusted Advisor for results of 88 checks on your resources. 89 """ 90 APIVersion = "2013-04-15" 91 DefaultRegionName = "us-east-1" 92 DefaultRegionEndpoint = "support.us-east-1.amazonaws.com" 93 ServiceName = "Support" 94 TargetPrefix = "AWSSupport_20130415" 95 ResponseError = JSONResponseError 96 97 _faults = { 98 "CaseCreationLimitExceeded": exceptions.CaseCreationLimitExceeded, 99 "AttachmentLimitExceeded": exceptions.AttachmentLimitExceeded, 100 "CaseIdNotFound": exceptions.CaseIdNotFound, 101 "DescribeAttachmentLimitExceeded": exceptions.DescribeAttachmentLimitExceeded, 102 "AttachmentSetIdNotFound": exceptions.AttachmentSetIdNotFound, 103 "InternalServerError": exceptions.InternalServerError, 104 "AttachmentSetExpired": exceptions.AttachmentSetExpired, 105 "AttachmentIdNotFound": exceptions.AttachmentIdNotFound, 106 "AttachmentSetSizeLimitExceeded": exceptions.AttachmentSetSizeLimitExceeded, 107 } 108 109 110 def __init__(self, **kwargs): 111 region = kwargs.pop('region', None) 112 if not region: 113 region = RegionInfo(self, self.DefaultRegionName, 114 self.DefaultRegionEndpoint) 115 116 if 'host' not in kwargs or kwargs['host'] is None: 117 kwargs['host'] = region.endpoint 118 119 super(SupportConnection, self).__init__(**kwargs) 120 self.region = region 121 122 def _required_auth_capability(self): 123 return ['hmac-v4'] 124 125 def add_attachments_to_set(self, attachments, attachment_set_id=None): 126 """ 127 Adds one or more attachments to an attachment set. If an 128 `AttachmentSetId` is not specified, a new attachment set is 129 created, and the ID of the set is returned in the response. If 130 an `AttachmentSetId` is specified, the attachments are added 131 to the specified set, if it exists. 132 133 An attachment set is a temporary container for attachments 134 that are to be added to a case or case communication. The set 135 is available for one hour after it is created; the 136 `ExpiryTime` returned in the response indicates when the set 137 expires. The maximum number of attachments in a set is 3, and 138 the maximum size of any attachment in the set is 5 MB. 139 140 :type attachment_set_id: string 141 :param attachment_set_id: The ID of the attachment set. If an 142 `AttachmentSetId` is not specified, a new attachment set is 143 created, and the ID of the set is returned in the response. If an 144 `AttachmentSetId` is specified, the attachments are added to the 145 specified set, if it exists. 146 147 :type attachments: list 148 :param attachments: One or more attachments to add to the set. The 149 limit is 3 attachments per set, and the size limit is 5 MB per 150 attachment. 151 152 """ 153 params = {'attachments': attachments, } 154 if attachment_set_id is not None: 155 params['attachmentSetId'] = attachment_set_id 156 return self.make_request(action='AddAttachmentsToSet', 157 body=json.dumps(params)) 158 159 def add_communication_to_case(self, communication_body, case_id=None, 160 cc_email_addresses=None, 161 attachment_set_id=None): 162 """ 163 Adds additional customer communication to an AWS Support case. 164 You use the `CaseId` value to identify the case to add 165 communication to. You can list a set of email addresses to 166 copy on the communication using the `CcEmailAddresses` value. 167 The `CommunicationBody` value contains the text of the 168 communication. 169 170 The response indicates the success or failure of the request. 171 172 This operation implements a subset of the behavior on the AWS 173 Support `Your Support Cases`_ web form. 174 175 :type case_id: string 176 :param case_id: The AWS Support case ID requested or returned in the 177 call. The case ID is an alphanumeric string formatted as shown in 178 this example: case- 12345678910-2013-c4c1d2bf33c5cf47 179 180 :type communication_body: string 181 :param communication_body: The body of an email communication to add to 182 the support case. 183 184 :type cc_email_addresses: list 185 :param cc_email_addresses: The email addresses in the CC line of an 186 email to be added to the support case. 187 188 :type attachment_set_id: string 189 :param attachment_set_id: The ID of a set of one or more attachments 190 for the communication to add to the case. Create the set by calling 191 AddAttachmentsToSet 192 193 """ 194 params = {'communicationBody': communication_body, } 195 if case_id is not None: 196 params['caseId'] = case_id 197 if cc_email_addresses is not None: 198 params['ccEmailAddresses'] = cc_email_addresses 199 if attachment_set_id is not None: 200 params['attachmentSetId'] = attachment_set_id 201 return self.make_request(action='AddCommunicationToCase', 202 body=json.dumps(params)) 203 204 def create_case(self, subject, communication_body, service_code=None, 205 severity_code=None, category_code=None, 206 cc_email_addresses=None, language=None, issue_type=None, 207 attachment_set_id=None): 208 """ 209 Creates a new case in the AWS Support Center. This operation 210 is modeled on the behavior of the AWS Support Center `Open a 211 new case`_ page. Its parameters require you to specify the 212 following information: 213 214 215 #. **IssueType.** The type of issue for the case. You can 216 specify either "customer-service" or "technical." If you do 217 not indicate a value, the default is "technical." 218 #. **ServiceCode.** The code for an AWS service. You obtain 219 the `ServiceCode` by calling DescribeServices. 220 #. **CategoryCode.** The category for the service defined for 221 the `ServiceCode` value. You also obtain the category code for 222 a service by calling DescribeServices. Each AWS service 223 defines its own set of category codes. 224 #. **SeverityCode.** A value that indicates the urgency of the 225 case, which in turn determines the response time according to 226 your service level agreement with AWS Support. You obtain the 227 SeverityCode by calling DescribeSeverityLevels. 228 #. **Subject.** The **Subject** field on the AWS Support 229 Center `Open a new case`_ page. 230 #. **CommunicationBody.** The **Description** field on the AWS 231 Support Center `Open a new case`_ page. 232 #. **AttachmentSetId.** The ID of a set of attachments that 233 has been created by using AddAttachmentsToSet. 234 #. **Language.** The human language in which AWS Support 235 handles the case. English and Japanese are currently 236 supported. 237 #. **CcEmailAddresses.** The AWS Support Center **CC** field 238 on the `Open a new case`_ page. You can list email addresses 239 to be copied on any correspondence about the case. The account 240 that opens the case is already identified by passing the AWS 241 Credentials in the HTTP POST method or in a method or function 242 call from one of the programming languages supported by an 243 `AWS SDK`_. 244 245 246 A successful CreateCase request returns an AWS Support case 247 number. Case numbers are used by the DescribeCases operation 248 to retrieve existing AWS Support cases. 249 250 :type subject: string 251 :param subject: The title of the AWS Support case. 252 253 :type service_code: string 254 :param service_code: The code for the AWS service returned by the call 255 to DescribeServices. 256 257 :type severity_code: string 258 :param severity_code: The code for the severity level returned by the 259 call to DescribeSeverityLevels. 260 261 :type category_code: string 262 :param category_code: The category of problem for the AWS Support case. 263 264 :type communication_body: string 265 :param communication_body: The communication body text when you create 266 an AWS Support case by calling CreateCase. 267 268 :type cc_email_addresses: list 269 :param cc_email_addresses: A list of email addresses that AWS Support 270 copies on case correspondence. 271 272 :type language: string 273 :param language: The ISO 639-1 code for the language in which AWS 274 provides support. AWS Support currently supports English ("en") and 275 Japanese ("ja"). Language parameters must be passed explicitly for 276 operations that take them. 277 278 :type issue_type: string 279 :param issue_type: The type of issue for the case. You can specify 280 either "customer-service" or "technical." If you do not indicate a 281 value, the default is "technical." 282 283 :type attachment_set_id: string 284 :param attachment_set_id: The ID of a set of one or more attachments 285 for the case. Create the set by using AddAttachmentsToSet. 286 287 """ 288 params = { 289 'subject': subject, 290 'communicationBody': communication_body, 291 } 292 if service_code is not None: 293 params['serviceCode'] = service_code 294 if severity_code is not None: 295 params['severityCode'] = severity_code 296 if category_code is not None: 297 params['categoryCode'] = category_code 298 if cc_email_addresses is not None: 299 params['ccEmailAddresses'] = cc_email_addresses 300 if language is not None: 301 params['language'] = language 302 if issue_type is not None: 303 params['issueType'] = issue_type 304 if attachment_set_id is not None: 305 params['attachmentSetId'] = attachment_set_id 306 return self.make_request(action='CreateCase', 307 body=json.dumps(params)) 308 309 def describe_attachment(self, attachment_id): 310 """ 311 Returns the attachment that has the specified ID. Attachment 312 IDs are generated by the case management system when you add 313 an attachment to a case or case communication. Attachment IDs 314 are returned in the AttachmentDetails objects that are 315 returned by the DescribeCommunications operation. 316 317 :type attachment_id: string 318 :param attachment_id: The ID of the attachment to return. Attachment 319 IDs are returned by the DescribeCommunications operation. 320 321 """ 322 params = {'attachmentId': attachment_id, } 323 return self.make_request(action='DescribeAttachment', 324 body=json.dumps(params)) 325 326 def describe_cases(self, case_id_list=None, display_id=None, 327 after_time=None, before_time=None, 328 include_resolved_cases=None, next_token=None, 329 max_results=None, language=None, 330 include_communications=None): 331 """ 332 Returns a list of cases that you specify by passing one or 333 more case IDs. In addition, you can filter the cases by date 334 by setting values for the `AfterTime` and `BeforeTime` request 335 parameters. 336 337 Case data is available for 12 months after creation. If a case 338 was created more than 12 months ago, a request for data might 339 cause an error. 340 341 The response returns the following in JSON format: 342 343 344 #. One or more CaseDetails data types. 345 #. One or more `NextToken` values, which specify where to 346 paginate the returned records represented by the `CaseDetails` 347 objects. 348 349 :type case_id_list: list 350 :param case_id_list: A list of ID numbers of the support cases you want 351 returned. The maximum number of cases is 100. 352 353 :type display_id: string 354 :param display_id: The ID displayed for a case in the AWS Support 355 Center user interface. 356 357 :type after_time: string 358 :param after_time: The start date for a filtered date search on support 359 case communications. Case communications are available for 12 360 months after creation. 361 362 :type before_time: string 363 :param before_time: The end date for a filtered date search on support 364 case communications. Case communications are available for 12 365 months after creation. 366 367 :type include_resolved_cases: boolean 368 :param include_resolved_cases: Specifies whether resolved support cases 369 should be included in the DescribeCases results. The default is 370 false . 371 372 :type next_token: string 373 :param next_token: A resumption point for pagination. 374 375 :type max_results: integer 376 :param max_results: The maximum number of results to return before 377 paginating. 378 379 :type language: string 380 :param language: The ISO 639-1 code for the language in which AWS 381 provides support. AWS Support currently supports English ("en") and 382 Japanese ("ja"). Language parameters must be passed explicitly for 383 operations that take them. 384 385 :type include_communications: boolean 386 :param include_communications: Specifies whether communications should 387 be included in the DescribeCases results. The default is true . 388 389 """ 390 params = {} 391 if case_id_list is not None: 392 params['caseIdList'] = case_id_list 393 if display_id is not None: 394 params['displayId'] = display_id 395 if after_time is not None: 396 params['afterTime'] = after_time 397 if before_time is not None: 398 params['beforeTime'] = before_time 399 if include_resolved_cases is not None: 400 params['includeResolvedCases'] = include_resolved_cases 401 if next_token is not None: 402 params['nextToken'] = next_token 403 if max_results is not None: 404 params['maxResults'] = max_results 405 if language is not None: 406 params['language'] = language 407 if include_communications is not None: 408 params['includeCommunications'] = include_communications 409 return self.make_request(action='DescribeCases', 410 body=json.dumps(params)) 411 412 def describe_communications(self, case_id, before_time=None, 413 after_time=None, next_token=None, 414 max_results=None): 415 """ 416 Returns communications (and attachments) for one or more 417 support cases. You can use the `AfterTime` and `BeforeTime` 418 parameters to filter by date. You can use the `CaseId` 419 parameter to restrict the results to a particular case. 420 421 Case data is available for 12 months after creation. If a case 422 was created more than 12 months ago, a request for data might 423 cause an error. 424 425 You can use the `MaxResults` and `NextToken` parameters to 426 control the pagination of the result set. Set `MaxResults` to 427 the number of cases you want displayed on each page, and use 428 `NextToken` to specify the resumption of pagination. 429 430 :type case_id: string 431 :param case_id: The AWS Support case ID requested or returned in the 432 call. The case ID is an alphanumeric string formatted as shown in 433 this example: case- 12345678910-2013-c4c1d2bf33c5cf47 434 435 :type before_time: string 436 :param before_time: The end date for a filtered date search on support 437 case communications. Case communications are available for 12 438 months after creation. 439 440 :type after_time: string 441 :param after_time: The start date for a filtered date search on support 442 case communications. Case communications are available for 12 443 months after creation. 444 445 :type next_token: string 446 :param next_token: A resumption point for pagination. 447 448 :type max_results: integer 449 :param max_results: The maximum number of results to return before 450 paginating. 451 452 """ 453 params = {'caseId': case_id, } 454 if before_time is not None: 455 params['beforeTime'] = before_time 456 if after_time is not None: 457 params['afterTime'] = after_time 458 if next_token is not None: 459 params['nextToken'] = next_token 460 if max_results is not None: 461 params['maxResults'] = max_results 462 return self.make_request(action='DescribeCommunications', 463 body=json.dumps(params)) 464 465 def describe_services(self, service_code_list=None, language=None): 466 """ 467 Returns the current list of AWS services and a list of service 468 categories that applies to each one. You then use service 469 names and categories in your CreateCase requests. Each AWS 470 service has its own set of categories. 471 472 The service codes and category codes correspond to the values 473 that are displayed in the **Service** and **Category** drop- 474 down lists on the AWS Support Center `Open a new case`_ page. 475 The values in those fields, however, do not necessarily match 476 the service codes and categories returned by the 477 `DescribeServices` request. Always use the service codes and 478 categories obtained programmatically. This practice ensures 479 that you always have the most recent set of service and 480 category codes. 481 482 :type service_code_list: list 483 :param service_code_list: A JSON-formatted list of service codes 484 available for AWS services. 485 486 :type language: string 487 :param language: The ISO 639-1 code for the language in which AWS 488 provides support. AWS Support currently supports English ("en") and 489 Japanese ("ja"). Language parameters must be passed explicitly for 490 operations that take them. 491 492 """ 493 params = {} 494 if service_code_list is not None: 495 params['serviceCodeList'] = service_code_list 496 if language is not None: 497 params['language'] = language 498 return self.make_request(action='DescribeServices', 499 body=json.dumps(params)) 500 501 def describe_severity_levels(self, language=None): 502 """ 503 Returns the list of severity levels that you can assign to an 504 AWS Support case. The severity level for a case is also a 505 field in the CaseDetails data type included in any CreateCase 506 request. 507 508 :type language: string 509 :param language: The ISO 639-1 code for the language in which AWS 510 provides support. AWS Support currently supports English ("en") and 511 Japanese ("ja"). Language parameters must be passed explicitly for 512 operations that take them. 513 514 """ 515 params = {} 516 if language is not None: 517 params['language'] = language 518 return self.make_request(action='DescribeSeverityLevels', 519 body=json.dumps(params)) 520 521 def describe_trusted_advisor_check_refresh_statuses(self, check_ids): 522 """ 523 Returns the refresh status of the Trusted Advisor checks that 524 have the specified check IDs. Check IDs can be obtained by 525 calling DescribeTrustedAdvisorChecks. 526 527 :type check_ids: list 528 :param check_ids: The IDs of the Trusted Advisor checks. 529 530 """ 531 params = {'checkIds': check_ids, } 532 return self.make_request(action='DescribeTrustedAdvisorCheckRefreshStatuses', 533 body=json.dumps(params)) 534 535 def describe_trusted_advisor_check_result(self, check_id, language=None): 536 """ 537 Returns the results of the Trusted Advisor check that has the 538 specified check ID. Check IDs can be obtained by calling 539 DescribeTrustedAdvisorChecks. 540 541 The response contains a TrustedAdvisorCheckResult object, 542 which contains these three objects: 543 544 545 + TrustedAdvisorCategorySpecificSummary 546 + TrustedAdvisorResourceDetail 547 + TrustedAdvisorResourcesSummary 548 549 550 In addition, the response contains these fields: 551 552 553 + **Status.** The alert status of the check: "ok" (green), 554 "warning" (yellow), "error" (red), or "not_available". 555 + **Timestamp.** The time of the last refresh of the check. 556 + **CheckId.** The unique identifier for the check. 557 558 :type check_id: string 559 :param check_id: The unique identifier for the Trusted Advisor check. 560 561 :type language: string 562 :param language: The ISO 639-1 code for the language in which AWS 563 provides support. AWS Support currently supports English ("en") and 564 Japanese ("ja"). Language parameters must be passed explicitly for 565 operations that take them. 566 567 """ 568 params = {'checkId': check_id, } 569 if language is not None: 570 params['language'] = language 571 return self.make_request(action='DescribeTrustedAdvisorCheckResult', 572 body=json.dumps(params)) 573 574 def describe_trusted_advisor_check_summaries(self, check_ids): 575 """ 576 Returns the summaries of the results of the Trusted Advisor 577 checks that have the specified check IDs. Check IDs can be 578 obtained by calling DescribeTrustedAdvisorChecks. 579 580 The response contains an array of TrustedAdvisorCheckSummary 581 objects. 582 583 :type check_ids: list 584 :param check_ids: The IDs of the Trusted Advisor checks. 585 586 """ 587 params = {'checkIds': check_ids, } 588 return self.make_request(action='DescribeTrustedAdvisorCheckSummaries', 589 body=json.dumps(params)) 590 591 def describe_trusted_advisor_checks(self, language): 592 """ 593 Returns information about all available Trusted Advisor 594 checks, including name, ID, category, description, and 595 metadata. You must specify a language code; English ("en") and 596 Japanese ("ja") are currently supported. The response contains 597 a TrustedAdvisorCheckDescription for each check. 598 599 :type language: string 600 :param language: The ISO 639-1 code for the language in which AWS 601 provides support. AWS Support currently supports English ("en") and 602 Japanese ("ja"). Language parameters must be passed explicitly for 603 operations that take them. 604 605 """ 606 params = {'language': language, } 607 return self.make_request(action='DescribeTrustedAdvisorChecks', 608 body=json.dumps(params)) 609 610 def refresh_trusted_advisor_check(self, check_id): 611 """ 612 Requests a refresh of the Trusted Advisor check that has the 613 specified check ID. Check IDs can be obtained by calling 614 DescribeTrustedAdvisorChecks. 615 616 The response contains a RefreshTrustedAdvisorCheckResult 617 object, which contains these fields: 618 619 620 + **Status.** The refresh status of the check: "none", 621 "enqueued", "processing", "success", or "abandoned". 622 + **MillisUntilNextRefreshable.** The amount of time, in 623 milliseconds, until the check is eligible for refresh. 624 + **CheckId.** The unique identifier for the check. 625 626 :type check_id: string 627 :param check_id: The unique identifier for the Trusted Advisor check. 628 629 """ 630 params = {'checkId': check_id, } 631 return self.make_request(action='RefreshTrustedAdvisorCheck', 632 body=json.dumps(params)) 633 634 def resolve_case(self, case_id=None): 635 """ 636 Takes a `CaseId` and returns the initial state of the case 637 along with the state of the case after the call to ResolveCase 638 completed. 639 640 :type case_id: string 641 :param case_id: The AWS Support case ID requested or returned in the 642 call. The case ID is an alphanumeric string formatted as shown in 643 this example: case- 12345678910-2013-c4c1d2bf33c5cf47 644 645 """ 646 params = {} 647 if case_id is not None: 648 params['caseId'] = case_id 649 return self.make_request(action='ResolveCase', 650 body=json.dumps(params)) 651 652 def make_request(self, action, body): 653 headers = { 654 'X-Amz-Target': '%s.%s' % (self.TargetPrefix, action), 655 'Host': self.region.endpoint, 656 'Content-Type': 'application/x-amz-json-1.1', 657 'Content-Length': str(len(body)), 658 } 659 http_request = self.build_base_http_request( 660 method='POST', path='/', auth_path='/', params={}, 661 headers=headers, data=body) 662 response = self._mexe(http_request, sender=None, 663 override_num_retries=10) 664 response_body = response.read().decode('utf-8') 665 boto.log.debug(response_body) 666 if response.status == 200: 667 if response_body: 668 return json.loads(response_body) 669 else: 670 json_body = json.loads(response_body) 671 fault_name = json_body.get('__type', None) 672 exception_class = self._faults.get(fault_name, self.ResponseError) 673 raise exception_class(response.status, response.reason, 674 body=json_body) 675