Skip to content

Commit 6b0afc5

Browse files
authored
Merge release-v1.47.0 into main
2 parents 496d3ab + b52af65 commit 6b0afc5

40 files changed

+1456
-334
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,17 @@ The AWS Serverless Application Model (SAM) is an open-source framework for build
1111
It provides shorthand syntax to express functions, APIs, databases, and event source mappings.
1212
With just a few lines of configuration, you can define the application you want and model it.
1313

14-
[![Getting Started with AWS SAM](./docs/get-started-youtube.png)](https://www.youtube.com/watch?v=1dzihtC5LJ0)
14+
[![Getting Started with AWS SAM](./docs/get-started-youtube.png)](https://www.youtube.com/watch?v=QBBewrKR1qg)
15+
16+
## Recent blogposts and workshops
17+
18+
* **Develop Node projects with SAM CLI using esbuild (Beta)** - and use SAM Accelerate on Typescript projects. [Read blogpost here](https://s12d.com/5Aa6u0o7)
19+
20+
* **Speed up development with SAM Accelerate (Beta)** - quickly test your changes in the cloud. [Read blogpost here](https://s12d.com/WeMib4nf)
21+
22+
* **Getting started with CI/CD? SAM pipelines can help you get started** - [This workshop](https://s12d.com/_JQ48d5T) walks you through the basics
23+
24+
* **Get started with Serverless Application development using SAM CLI** - [This workshop](https://s12d.com/Tq9ZE-Br) walks you through the basics.
1525

1626
## Get Started
1727

integration/combination/test_api_settings.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
except ImportError:
66
from pathlib2 import Path
77

8-
import requests
98
from parameterized import parameterized
109

1110
from integration.helpers.base_test import BaseTest
@@ -158,7 +157,7 @@ def test_implicit_api_settings(self):
158157

159158
def verify_binary_media_request(self, url, expected_status_code):
160159
headers = {"accept": "image/png"}
161-
response = requests.get(url, headers=headers)
160+
response = BaseTest.do_get_request_with_logging(url, headers)
162161

163162
status = response.status_code
164163
expected_file_path = str(Path(self.code_dir, "AWS_logo_RGB.png"))

integration/combination/test_api_with_authorizer_apikey.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
from unittest.case import skipIf
2-
3-
import requests
4-
51
from integration.helpers.base_test import BaseTest
62
from integration.helpers.deployer.utils.retry import retry
73
from integration.helpers.exception import StatusCodeError
8-
from integration.helpers.resource import current_region_does_not_support
9-
from integration.config.service_names import COGNITO
104

115

126
class TestApiWithAuthorizerApiKey(BaseTest):
@@ -82,10 +76,10 @@ def verify_authorized_request(
8276
header_value=None,
8377
):
8478
if not header_key or not header_value:
85-
response = requests.get(url)
79+
response = BaseTest.do_get_request_with_logging(url)
8680
else:
8781
headers = {header_key: header_value}
88-
response = requests.get(url, headers=headers)
82+
response = BaseTest.do_get_request_with_logging(url, headers)
8983
status = response.status_code
9084
if status != expected_status_code:
9185
raise StatusCodeError(

integration/combination/test_api_with_authorizers.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from unittest.case import skipIf
22

3-
import requests
4-
53
from integration.helpers.base_test import BaseTest
64
from integration.helpers.deployer.utils.retry import retry
75
from integration.helpers.exception import StatusCodeError
@@ -436,11 +434,12 @@ def verify_authorized_request(
436434
header_value=None,
437435
):
438436
if not header_key or not header_value:
439-
response = requests.get(url)
437+
response = BaseTest.do_get_request_with_logging(url)
440438
else:
441439
headers = {header_key: header_value}
442-
response = requests.get(url, headers=headers)
440+
response = BaseTest.do_get_request_with_logging(url, headers)
443441
status = response.status_code
442+
444443
if status != expected_status_code:
445444
raise StatusCodeError(
446445
"Request to {} failed with status: {}, expected status: {}".format(url, status, expected_status_code)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Logger configurations
2+
import logging
3+
4+
5+
class LoggingConfiguration:
6+
@staticmethod
7+
def configure_request_logger(logger):
8+
console_handler = logging.StreamHandler()
9+
console_handler.setLevel(logging.INFO)
10+
console_handler.setFormatter(
11+
logging.Formatter("%(asctime)s %(message)s | Status: %(status)s | Headers: %(headers)s ")
12+
)
13+
logger.addHandler(console_handler)
14+
logger.propagate = False

integration/helpers/base_test.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import logging
22
import os
3+
import requests
34
import shutil
45

56
import botocore
67
import pytest
7-
import requests
88

9+
from integration.config.logger_configurations import LoggingConfiguration
910
from integration.helpers.client_provider import ClientProvider
1011
from integration.helpers.deployer.exceptions.exceptions import ThrottlingError
1112
from integration.helpers.deployer.utils.retry import retry_with_exponential_backoff_and_jitter
13+
from integration.helpers.request_utils import RequestUtils
1214
from integration.helpers.resource import generate_suffix, create_bucket, verify_stack_resources
1315
from integration.helpers.s3_uploader import S3Uploader
1416
from integration.helpers.yaml_utils import dump_yaml, load_yaml
@@ -28,6 +30,10 @@
2830
from integration.helpers.file_resources import FILE_TO_S3_URI_MAP, CODE_KEY_TO_FILE_MAP
2931

3032
LOG = logging.getLogger(__name__)
33+
34+
REQUEST_LOGGER = logging.getLogger(f"{__name__}.requests")
35+
LoggingConfiguration.configure_request_logger(REQUEST_LOGGER)
36+
3137
STACK_NAME_PREFIX = "sam-integ-stack-"
3238
S3_BUCKET_PREFIX = "sam-integ-bucket-"
3339

@@ -496,7 +502,7 @@ def verify_stack(self, end_state="CREATE_COMPLETE"):
496502
if error:
497503
self.fail(error)
498504

499-
def verify_get_request_response(self, url, expected_status_code):
505+
def verify_get_request_response(self, url, expected_status_code, headers=None):
500506
"""
501507
Verify if the get request to a certain url return the expected status code
502508
@@ -506,9 +512,10 @@ def verify_get_request_response(self, url, expected_status_code):
506512
the url for the get request
507513
expected_status_code : string
508514
the expected status code
515+
headers : dict
516+
headers to use in request
509517
"""
510-
print("Making request to " + url)
511-
response = requests.get(url)
518+
response = BaseTest.do_get_request_with_logging(url, headers)
512519
self.assertEqual(response.status_code, expected_status_code, " must return HTTP " + str(expected_status_code))
513520
return response
514521

@@ -547,3 +554,19 @@ def generate_parameter(key, value, previous_value=False, resolved_value="string"
547554
"ResolvedValue": resolved_value,
548555
}
549556
return parameter
557+
558+
@staticmethod
559+
def do_get_request_with_logging(url, headers=None):
560+
"""
561+
Perform a get request to an APIGW endpoint and log relevant info
562+
Parameters
563+
----------
564+
url : string
565+
the url for the get request
566+
headers : dict
567+
headers to use in request
568+
"""
569+
response = requests.get(url, headers=headers) if headers else requests.get(url)
570+
amazon_headers = RequestUtils(response).get_amazon_headers()
571+
REQUEST_LOGGER.info("Request made to " + url, extra={"status": response.status_code, "headers": amazon_headers})
572+
return response

integration/helpers/request_utils.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Utils for requests
2+
3+
# Relevant headers that should be captured for debugging
4+
AMAZON_HEADERS = [
5+
"x-amzn-requestid",
6+
"x-amz-apigw-id",
7+
"x-amz-cf-id",
8+
"x-amzn-errortype",
9+
"apigw-requestid",
10+
]
11+
12+
13+
class RequestUtils:
14+
def __init__(self, response):
15+
self.response = response
16+
self.headers = self._normalize_response_headers()
17+
18+
def get_amazon_headers(self):
19+
"""
20+
Get a list of relevant amazon headers that could be useful for debugging
21+
"""
22+
amazon_headers = {}
23+
for header, header_val in self.headers.items():
24+
if header in AMAZON_HEADERS:
25+
amazon_headers[header] = header_val
26+
return amazon_headers
27+
28+
def _normalize_response_headers(self):
29+
"""
30+
API gateway can return headers with letters in different cases i.e. x-amzn-requestid or x-amzn-requestId
31+
We make them all lowercase here to more easily match them up
32+
"""
33+
if self.response is None or not self.response.headers:
34+
# Need to check for response is None here since the __bool__ method checks 200 <= status < 400
35+
return {}
36+
37+
return dict((k.lower(), v) for k, v in self.response.headers.items())

integration/resources/templates/combination/api_with_authorizers_invokefunction_set_none.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Resources:
1212
InlineCode: |
1313
print("hello")
1414
Handler: index.handler
15-
Runtime: python3.6
15+
Runtime: python3.8
1616
Events:
1717
API3:
1818
Type: Api

integration/resources/templates/single/basic_api_with_mode.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Resources:
99
Type: 'AWS::Serverless::Function'
1010
Properties:
1111
Handler: index.handler
12-
Runtime: python3.6
12+
Runtime: python3.8
1313
AutoPublishAlias: live
1414
InlineCode: |
1515
import json

integration/resources/templates/single/basic_api_with_mode_update.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Resources:
99
Type: 'AWS::Serverless::Function'
1010
Properties:
1111
Handler: index.handler
12-
Runtime: python3.6
12+
Runtime: python3.8
1313
AutoPublishAlias: live
1414
InlineCode: |
1515
def handler(event, context):

0 commit comments

Comments
 (0)