Skip to content

Commit 48eb41d

Browse files
authored
Merge pull request #2870 from aws/release-v1.59.0
Release 1.59.0 (to main)
2 parents 3a2da9e + 6094eeb commit 48eb41d

File tree

163 files changed

+337926
-5818
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

163 files changed

+337926
-5818
lines changed

.coveragerc

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@ omit =
55
samtranslator/schema/*
66
[report]
77
exclude_lines =
8-
pragma: no cover
9-
raise NotImplementedError.*
8+
pragma: no cover

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,4 @@ venv.bak/
119119
# Companion stack config
120120
integration/config/file_to_s3_map_modified.json
121121

122-
.tmp_schema.json
122+
.tmp

.pylintrc

+1-12
Original file line numberDiff line numberDiff line change
@@ -76,30 +76,19 @@ disable=
7676
R0401, # Cyclic import
7777
C0411, # import ordering
7878
W9015, # missing parameter in doc strings
79-
R0205, # useless-object-inheritanc
8079
C0301, # line to long
8180
C0114, # missing-module-docstring
8281
W1202, # Use lazy % formatting in logging functions (logging-format-interpolation)
83-
E1101, # No member
84-
W0622, # Redefining built-in 'property' (redefined-builtin)
82+
E1101, # No member
8583
W0212, # protected-access
8684
W0201, # attribute-defined-outside-init
87-
R1725, # Consider using Python 3 style super() without arguments (super-with-arguments)
8885
C2001, # Avoid comparisons to zero (compare-to-zero)
8986
R0912, # too many branches
90-
W0235, # Useless super delegation in method '__init__' (useless-super-delegation)
9187
C0412, # Imports from package samtranslator are not grouped (ungrouped-imports)
92-
W0223, # abstract-method
93-
W0107, # unnecessary-pass
94-
W0707, # raise-missing-from
9588
E0203, # access-member-before-definition
9689
W0221, # arguments-differ
97-
R1710, # inconsistent-return-statements
9890
R1702, # too-many-nested-blocks
99-
C0123, # Use isinstance() rather than type() for a typecheck. (unidiomatic-typecheck)
10091
W0105, # String statement has no effect (pointless-string-statement)
101-
C0206, # Consider iterating with .items() (consider-using-dict-items)
102-
W9008, # Redundant returns documentation (redundant-returns-doc)
10392
C0112, # empty-docstring
10493
C0116, # missing-function-docstring
10594
W9017, # differing-param-doc

MANIFEST.in

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ include samtranslator/policy_templates_data/schema.json
77
include samtranslator/model/connector_profiles/profiles.json
88
include samtranslator/schema/docs.json
99
include samtranslator/schema/schema.json
10+
include samtranslator/schema/sam.schema.json
11+
include samtranslator/schema/cloudformation.schema.json
1012
include README.md
1113
include THIRD_PARTY_LICENSES
1214

Makefile

+11-4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ black:
2525

2626
black-check:
2727
# Checking latest schema was generated (run `make schema` if this fails)
28-
python samtranslator/schema/schema.py > .tmp_schema.json
29-
diff -u samtranslator/schema/schema.json .tmp_schema.json
30-
rm .tmp_schema.json
28+
mkdir -p .tmp
29+
python samtranslator/schema/schema.py --sam-schema .tmp/sam.schema.json --cfn-schema samtranslator/schema/cloudformation.schema.json --unified-schema .tmp/schema.json
30+
diff -u samtranslator/schema/sam.schema.json .tmp/sam.schema.json
31+
diff -u samtranslator/schema/schema.json .tmp/schema.json
3132
black --check setup.py samtranslator/* tests/* integration/* bin/*.py
3233
bin/json-format.py --check tests integration samtranslator/policy_templates_data
3334
bin/yaml-format.py --check tests
@@ -44,15 +45,21 @@ lint:
4445
prepare-companion-stack:
4546
pytest -v --no-cov integration/setup -m setup
4647

48+
update-cfn-schema:
49+
curl -o samtranslator/schema/cloudformation.schema.json https://raw.githubusercontent.com/awslabs/goformation/master/schema/cloudformation.schema.json
50+
4751
schema:
48-
python samtranslator/schema/schema.py > samtranslator/schema/schema.json
52+
python samtranslator/schema/schema.py --sam-schema samtranslator/schema/sam.schema.json --cfn-schema samtranslator/schema/cloudformation.schema.json --unified-schema samtranslator/schema/schema.json
4953

5054
# Command to run everytime you make changes to verify everything works
5155
dev: test
5256

5357
# Verifications to run before sending a pull request
5458
pr: black-check lint init dev
5559

60+
clean:
61+
rm -r .tmp
62+
5663
define HELP_MESSAGE
5764

5865
Usage: $ make [TARGETS]

bin/run_cfn_lint.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ VENV=.venv_cfn_lint
77
# See https://github.com/aws/serverless-application-model/issues/1042
88
if [ ! -d "${VENV}" ]; then
99
python3 -m venv "${VENV}"
10-
"${VENV}/bin/python" -m pip install cfn-lint==0.72.2 --quiet
10+
"${VENV}/bin/python" -m pip install cfn-lint --quiet
1111
fi
1212

1313
"${VENV}/bin/cfn-lint" --format parseable

integration/combination/test_connectors.py

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ def tearDown(self):
4747
("combination/connector_sqs_to_function",),
4848
("combination/connector_sns_to_function_write",),
4949
("combination/connector_table_to_function_read",),
50+
("combination/embedded_connector",),
5051
]
5152
)
5253
@retry_once
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"LogicalResourceId": "MyRole1",
4+
"ResourceType": "AWS::IAM::Role"
5+
},
6+
{
7+
"LogicalResourceId": "MyRole2",
8+
"ResourceType": "AWS::IAM::Role"
9+
},
10+
{
11+
"LogicalResourceId": "TriggerFunction",
12+
"ResourceType": "AWS::Lambda::Function"
13+
},
14+
{
15+
"LogicalResourceId": "MyFunction2",
16+
"ResourceType": "AWS::Lambda::Function"
17+
},
18+
{
19+
"LogicalResourceId": "TriggerFunctionMyConnectorPolicy",
20+
"ResourceType": "AWS::IAM::ManagedPolicy"
21+
}
22+
]

integration/resources/templates/combination/api_with_authorizer_apikey.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Outputs:
104104
ApiKeyId:
105105
Description: API Key ID
106106
Value:
107-
Fn::GetAtt: MyFirstApiKey.APIKeyId
107+
Ref: MyFirstApiKey
108108
ApiUrl:
109109
Description: API endpoint URL for Prod environment
110110
Value:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
Resources:
2+
MyRole1:
3+
Type: AWS::IAM::Role
4+
Properties:
5+
AssumeRolePolicyDocument:
6+
Statement:
7+
- Effect: Allow
8+
Action: sts:AssumeRole
9+
Principal:
10+
Service: lambda.amazonaws.com
11+
ManagedPolicyArns:
12+
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
13+
14+
MyRole2:
15+
Type: AWS::IAM::Role
16+
Properties:
17+
AssumeRolePolicyDocument:
18+
Statement:
19+
- Effect: Allow
20+
Action: sts:AssumeRole
21+
Principal:
22+
Service: lambda.amazonaws.com
23+
ManagedPolicyArns:
24+
- !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
25+
26+
TriggerFunction:
27+
Type: AWS::Lambda::Function
28+
Connectors:
29+
MyConnector:
30+
Properties:
31+
Destination:
32+
Id: MyFunction2
33+
Permissions:
34+
- Write
35+
Properties:
36+
Role: !GetAtt MyRole1.Arn
37+
Runtime: nodejs14.x
38+
Handler: index.handler
39+
Code:
40+
ZipFile: |
41+
const AWS = require('aws-sdk');
42+
exports.handler = async (event) => {
43+
const params = {
44+
FunctionName: process.env.FUNCTION_NAME,
45+
InvocationType: 'RequestResponse',
46+
Payload: '{}',
47+
};
48+
const lambda = new AWS.Lambda();
49+
const response = await lambda.invoke(params).promise();
50+
if(response.StatusCode !== 200){
51+
throw new Error('Failed to get response from lambda function')
52+
}
53+
return response;
54+
};
55+
Environment:
56+
Variables:
57+
FUNCTION_NAME: !Ref MyFunction2
58+
59+
MyFunction2:
60+
Type: AWS::Lambda::Function
61+
Properties:
62+
Role: !GetAtt MyRole2.Arn
63+
Runtime: nodejs14.x
64+
Handler: index.handler
65+
Code:
66+
ZipFile: |
67+
const AWS = require('aws-sdk');
68+
exports.handler = async (event) => {
69+
console.log(JSON.stringify(event));
70+
};
71+
Metadata:
72+
SamTransformTest: true

requirements/base.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
boto3>=1.19.5,==1.*
22
jsonschema<5,>=3.2 # TODO: evaluate risk of removing jsonschema 3.x support
3-
pydantic~=1.10.2
3+
pydantic~=1.8
44
typing_extensions~=4.4.0 # 3.7 doesn't have Literal

samtranslator/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "1.58.1"
1+
__version__ = "1.59.0"

samtranslator/feature_toggle/dialup.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import hashlib
2+
from abc import ABC, abstractmethod
23

34

4-
class BaseDialup(object):
5+
class BaseDialup(ABC):
56
"""BaseDialup class to provide an interface for all dialup classes"""
67

78
def __init__(self, region_config, **kwargs): # type: ignore[no-untyped-def]
89
self.region_config = region_config
910

10-
def is_enabled(self): # type: ignore[no-untyped-def]
11+
@abstractmethod
12+
def is_enabled(self) -> bool:
1113
"""
1214
Returns a bool on whether this dialup is enabled or not
1315
"""
14-
raise NotImplementedError
1516

16-
def __str__(self): # type: ignore[no-untyped-def]
17+
def __str__(self) -> str:
1718
return self.__class__.__name__
1819

1920

@@ -23,7 +24,7 @@ class DisabledDialup(BaseDialup):
2324
"""
2425

2526
def __init__(self, region_config, **kwargs): # type: ignore[no-untyped-def]
26-
super(DisabledDialup, self).__init__(region_config) # type: ignore[no-untyped-call]
27+
super().__init__(region_config) # type: ignore[no-untyped-call]
2728

2829
def is_enabled(self) -> bool:
2930
return False
@@ -36,7 +37,7 @@ class ToggleDialup(BaseDialup):
3637
"""
3738

3839
def __init__(self, region_config, **kwargs): # type: ignore[no-untyped-def]
39-
super(ToggleDialup, self).__init__(region_config) # type: ignore[no-untyped-call]
40+
super().__init__(region_config) # type: ignore[no-untyped-call]
4041
self.region_config = region_config
4142

4243
def is_enabled(self): # type: ignore[no-untyped-def]
@@ -50,11 +51,11 @@ class SimpleAccountPercentileDialup(BaseDialup):
5051
"""
5152

5253
def __init__(self, region_config, account_id, feature_name, **kwargs): # type: ignore[no-untyped-def]
53-
super(SimpleAccountPercentileDialup, self).__init__(region_config) # type: ignore[no-untyped-call]
54+
super().__init__(region_config) # type: ignore[no-untyped-call]
5455
self.account_id = account_id
5556
self.feature_name = feature_name
5657

57-
def _get_account_percentile(self): # type: ignore[no-untyped-def]
58+
def _get_account_percentile(self) -> int:
5859
"""
5960
Get account percentile based on sha256 hash of account ID and feature_name
6061
@@ -65,10 +66,10 @@ def _get_account_percentile(self): # type: ignore[no-untyped-def]
6566
m.update(self.feature_name.encode())
6667
return int(m.hexdigest(), 16) % 100
6768

68-
def is_enabled(self): # type: ignore[no-untyped-def]
69+
def is_enabled(self) -> bool:
6970
"""
7071
Enable when account_percentile falls within target_percentile
7172
Meaning only (target_percentile)% of accounts will be enabled
7273
"""
73-
target_percentile = self.region_config.get("enabled-%", 0)
74-
return self._get_account_percentile() < target_percentile # type: ignore[no-untyped-call]
74+
target_percentile: int = self.region_config.get("enabled-%", 0)
75+
return self._get_account_percentile() < target_percentile

samtranslator/feature_toggle/feature_toggle.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import json
2+
from abc import ABC, abstractmethod
3+
from typing import Any, Dict, cast
4+
25
import boto3
36
import logging
47

@@ -87,15 +90,16 @@ def is_enabled(self, feature_name: str) -> bool:
8790
return is_enabled
8891

8992

90-
class FeatureToggleConfigProvider:
93+
class FeatureToggleConfigProvider(ABC):
9194
"""Interface for all FeatureToggle config providers"""
9295

9396
def __init__(self) -> None:
9497
pass
9598

9699
@property
97-
def config(self): # type: ignore[no-untyped-def]
98-
raise NotImplementedError
100+
@abstractmethod
101+
def config(self) -> Dict[str, Any]:
102+
pass
99103

100104

101105
class FeatureToggleDefaultConfigProvider(FeatureToggleConfigProvider):
@@ -105,7 +109,7 @@ def __init__(self) -> None:
105109
FeatureToggleConfigProvider.__init__(self)
106110

107111
@property
108-
def config(self): # type: ignore[no-untyped-def]
112+
def config(self) -> Dict[str, Any]:
109113
return {}
110114

111115

@@ -116,10 +120,10 @@ def __init__(self, local_config_path): # type: ignore[no-untyped-def]
116120
FeatureToggleConfigProvider.__init__(self)
117121
with open(local_config_path, "r", encoding="utf-8") as f:
118122
config_json = f.read()
119-
self.feature_toggle_config = json.loads(config_json)
123+
self.feature_toggle_config = cast(Dict[str, Any], json.loads(config_json))
120124

121125
@property
122-
def config(self): # type: ignore[no-untyped-def]
126+
def config(self) -> Dict[str, Any]:
123127
return self.feature_toggle_config
124128

125129

@@ -147,13 +151,13 @@ def __init__(self, application_id, environment_id, configuration_profile_id, app
147151
ClientId="FeatureToggleAppConfigConfigProvider",
148152
)
149153
binary_config_string = response["Content"].read()
150-
self.feature_toggle_config = json.loads(binary_config_string.decode("utf-8"))
154+
self.feature_toggle_config = cast(Dict[str, Any], json.loads(binary_config_string.decode("utf-8")))
151155
LOG.info("Finished loading feature toggle config from AppConfig.")
152156
except Exception as ex:
153157
LOG.error("Failed to load config from AppConfig: {}. Using empty config.".format(ex))
154158
# There is chance that AppConfig is not available in a particular region.
155-
self.feature_toggle_config = json.loads("{}")
159+
self.feature_toggle_config = {}
156160

157161
@property
158-
def config(self): # type: ignore[no-untyped-def]
162+
def config(self) -> Dict[str, Any]:
159163
return self.feature_toggle_config

0 commit comments

Comments
 (0)