Skip to content

Commit

Permalink
Make pycfmodel available for Python3.10 (#100)
Browse files Browse the repository at this point in the history
* make pycfmodel available for Python3.10

* update version and changelog

* update changelog

* update changelog

* update version

* update cloudformation_actions.py

Co-authored-by: Ramon <ramon.guimera@skyscanner.net>
Co-authored-by: Jordi Soucheiron <jsoucheiron@users.noreply.github.com>
  • Loading branch information
3 people authored May 19, 2022
1 parent c24d2e9 commit 0201ffa
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 287 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.8', '3.9']
python-version: ['3.7', '3.8', '3.9', '3.10']

name: Python ${{ matrix.python-version }}

Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ All notable changes to this project will be documented in this file.

## 0.20.0
### Additions
- New `RDSDBSecurityGroup` and `RDSDBSecurityGroupIngress` resources
- New `RDSDBSecurityGroup` and `RDSDBSecurityGroupIngress` resources [#103]
### Improvements
- IAM Role is able to return its `AssumeRolePolicyDocument` as a list of `OptionallyNamedPolicyDocument`. [#102](https://github.com/Skyscanner/pycfmodel/pull/102)
### Updates
- Compatible with Python3.10 [#100](https://github.com/Skyscanner/pycfmodel/pull/100)
- Update `CLOUDFORMATION_ACTIONS`.

## 0.19.1
Expand Down
23 changes: 8 additions & 15 deletions tests/resources/properties/test_policy_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,13 @@ def policy_document_not_principal():
**{
"Statement": [
{
"Action": [
"iam:Delete*",
"s3:GetObject*",
],
"Action": ["iam:Delete*", "s3:GetObject*"],
"Effect": "Allow",
"Resource": "arn:aws:s3:::fakebucketfakebucket/*",
"NotPrincipal": {"AWS": ["156460612806"]},
},
{
"Action": [
"s3:List*",
],
"Action": ["s3:List*"],
"Effect": "Deny",
"Resource": "arn:aws:s3:::fakebucketfakebucket/*",
"NotPrincipal": {"AWS": ["156460612806"]},
Expand Down Expand Up @@ -287,13 +282,11 @@ def policy_document_not_action():
**{
"Statement": [
{
"NotAction": [
"rds:*",
],
"NotAction": ["rds:*"],
"Effect": "Allow",
"Resource": "arn:aws:s3:::fakebucketfakebucket/*",
"NotPrincipal": {"AWS": ["156460612806"]},
},
}
]
}
)
Expand All @@ -315,8 +308,8 @@ def policy_document_condition_with_source_ip():
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Resource": "arn:aws:s3:::fakebucketfakebucket/*",
},
],
}
]
}
)

Expand All @@ -332,8 +325,8 @@ def policy_document_condition_with_source_vpce():
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Resource": "arn:aws:s3:::fakebucketfakebucket/*",
},
],
}
]
}
)

Expand Down
10 changes: 2 additions & 8 deletions tests/resources/properties/test_statement_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,7 @@ def test_build_evaluator_null(function: str, arg_a: Any, arg_b: Any, params: Dic

@pytest.mark.parametrize(
"function, arg_a, arg_b, params, expected_output",
[
("NumericEquals", "patata", 1, {"patata": 1}, True),
("NumericEquals", "patata", 1, {"patata": 2}, False),
],
[("NumericEquals", "patata", 1, {"patata": 1}, True), ("NumericEquals", "patata", 1, {"patata": 2}, False)],
)
def test_build_evaluator_numeric_equals(function: str, arg_a: Any, arg_b: Any, params: Dict, expected_output: bool):
node = build_evaluator(function, arg_a, arg_b)
Expand All @@ -167,10 +164,7 @@ def test_build_evaluator_numeric_equals(function: str, arg_a: Any, arg_b: Any, p

@pytest.mark.parametrize(
"function, arg_a, arg_b, params, expected_output",
[
("NumericNotEquals", "patata", 1, {"patata": 1}, False),
("NumericNotEquals", "patata", 1, {"patata": 2}, True),
],
[("NumericNotEquals", "patata", 1, {"patata": 1}, False), ("NumericNotEquals", "patata", 1, {"patata": 2}, True)],
)
def test_build_evaluator_numeric_not_equals(function: str, arg_a: Any, arg_b: Any, params: Dict, expected_output: bool):
node = build_evaluator(function, arg_a, arg_b)
Expand Down
9 changes: 1 addition & 8 deletions tests/resources/test_ec2_vpc_endpoint_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,7 @@ def ec2_vpc_endpoint_policy():
"Properties": {
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": "*",
}
],
"Statement": [{"Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject"], "Resource": "*"}],
},
"RouteTableIds": [{"Ref": "routetableA"}, {"Ref": "routetableB"}],
"ServiceName": "com.amazonaws.eu-west-1.s3",
Expand Down
16 changes: 2 additions & 14 deletions tests/resources/test_es_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@

@pytest.fixture()
def valid_empty_es_domain():
return ESDomain(
**{
"Type": "AWS::Elasticsearch::Domain",
"Properties": {},
}
)
return ESDomain(**{"Type": "AWS::Elasticsearch::Domain", "Properties": {}})


@pytest.fixture()
Expand Down Expand Up @@ -168,14 +163,7 @@ def test_valid_es_domain_from_aws_documentation_examples_resource_can_be_built(

def test_raise_error_if_invalid_fields_in_resource():
with pytest.raises(ValidationError) as exc_info:
ESDomain(
**{
"Type": "AWS::Elasticsearch::Domain",
"Properties": {
"DomainName": [],
},
}
)
ESDomain(**{"Type": "AWS::Elasticsearch::Domain", "Properties": {"DomainName": []}})

assert exc_info.value.errors() == [
{"loc": ("Properties", "DomainName"), "msg": "str type expected", "type": "type_error.str"},
Expand Down
6 changes: 1 addition & 5 deletions tests/resources/test_generic_resoure.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,7 @@ def test_generic_resource_with_bad_json_as_string_is_converted_to_a_string_prope


def test_parse_generic_resource_without_properties():
resource = GenericResource.parse_obj(
{
"Type": "AWS::SNS::Topic",
}
)
resource = GenericResource.parse_obj({"Type": "AWS::SNS::Topic"})
assert isinstance(resource, GenericResource)
assert resource.Properties is None
assert resource.Type == "AWS::SNS::Topic"
10 changes: 3 additions & 7 deletions tests/resources/test_iam_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ def iam_role():
"Action": ["sts:AssumeRole"],
"Condition": {
"StringLike": {
"iam:AssociatedResourceARN": [
"arn:aws:ec2:us-east-1:999999999999:instance/*",
]
},
"iam:AssociatedResourceARN": ["arn:aws:ec2:us-east-1:999999999999:instance/*"]
}
},
},
},
Expand Down Expand Up @@ -69,9 +67,7 @@ def test_all_conditions(iam_role):
}

assert iam_role.assume_role_statement_conditions[0].StringLike == {
"iam:AssociatedResourceARN": [
"arn:aws:ec2:us-east-1:999999999999:instance/*",
]
"iam:AssociatedResourceARN": ["arn:aws:ec2:us-east-1:999999999999:instance/*"]
}


Expand Down
22 changes: 5 additions & 17 deletions tests/resources/test_opensearch_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,7 @@

@pytest.fixture()
def valid_empty_opensearch_domain():
return OpenSearchDomain(
**{
"Type": "AWS::OpenSearchService::Domain",
"Properties": {},
}
)
return OpenSearchDomain(**{"Type": "AWS::OpenSearchService::Domain", "Properties": {}})


@pytest.fixture()
Expand Down Expand Up @@ -82,8 +77,8 @@ def valid_opensearch_domain_with_access_policies():
"Action": "es:*",
"Resource": "arn:aws:es:us-east-1:123456789012:domain/test/*",
}
],
},
]
}
},
}
)
Expand Down Expand Up @@ -201,14 +196,7 @@ def test_valid_opensearch_domain_from_aws_documentation_examples_resource_can_be

def test_raise_error_if_invalid_fields_in_resource():
with pytest.raises(ValidationError) as exc_info:
OpenSearchDomain(
**{
"Type": "AWS::OpenSearchService::Domain",
"Properties": {
"DomainName": [],
},
}
)
OpenSearchDomain(**{"Type": "AWS::OpenSearchService::Domain", "Properties": {"DomainName": []}})

assert exc_info.value.errors() == [
{"loc": ("Properties", "DomainName"), "msg": "str type expected", "type": "type_error.str"},
Expand Down Expand Up @@ -240,5 +228,5 @@ def test_can_obtain_policy_documents_from_inherited_method(valid_opensearch_doma
]
),
name=None,
),
)
]
5 changes: 1 addition & 4 deletions tests/resources/test_s3_bucket.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ def valid_s3_bucket():
"Id": "MyRule1",
"Status": "Enabled",
"Prefix": "MyPrefix",
"Destination": {
"Bucket": "arn:aws:s3:::my-replication-bucket",
"StorageClass": "STANDARD",
},
"Destination": {"Bucket": "arn:aws:s3:::my-replication-bucket", "StorageClass": "STANDARD"},
},
{
"Status": "Enabled",
Expand Down
8 changes: 1 addition & 7 deletions tests/resources/test_sns_topic_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ def sns_topic_policy():
"Id": "MyTopicPolicy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1",
"Effect": "Allow",
"Principal": "*",
"Action": "sns:Publish",
"Resource": "*",
},
{"Sid": "Stmt1", "Effect": "Allow", "Principal": "*", "Action": "sns:Publish", "Resource": "*"},
{
"Sid": "Stmt2",
"Effect": "Allow",
Expand Down
52 changes: 8 additions & 44 deletions tests/test_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,30 +317,10 @@ def test_template_conditions():
@pytest.mark.parametrize(
"conditions, expected",
[
(
{
"testCondition": {"Fn::Equals": [True, False]},
},
[],
),
(
{
"testCondition": {"Fn::Equals": [True, True]},
},
["test_resource_id"],
),
(
{
"whatever": {"Fn::Equals": [True, False]},
},
["test_resource_id"],
),
(
{
"whatever": {"Fn::Equals": [True, True]},
},
["test_resource_id"],
),
({"testCondition": {"Fn::Equals": [True, False]}}, []),
({"testCondition": {"Fn::Equals": [True, True]}}, ["test_resource_id"]),
({"whatever": {"Fn::Equals": [True, False]}}, ["test_resource_id"]),
({"whatever": {"Fn::Equals": [True, True]}}, ["test_resource_id"]),
],
)
def test_resolve_include_resource_when_condition_is_true_or_doesnt_exist(conditions: Dict, expected: List):
Expand All @@ -352,10 +332,7 @@ def test_resolve_include_resource_when_condition_is_true_or_doesnt_exist(conditi
"Type": "AWS::IAM::Role",
"Condition": "testCondition",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [],
},
"AssumeRolePolicyDocument": {"Version": "2012-10-17", "Statement": []},
"Path": "/",
"Policies": [],
},
Expand All @@ -382,10 +359,7 @@ def test_resolve_include_resource_when_condition_is_not_present():
"test_resource_id": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [],
},
"AssumeRolePolicyDocument": {"Version": "2012-10-17", "Statement": []},
"Path": "/",
"Policies": [],
},
Expand Down Expand Up @@ -591,10 +565,7 @@ def test_resolve_booleans():
"Properties": {
"Enabled": True,
"EnableKeyRotation": True,
"KeyPolicy": {
"Version": "2012-10-17",
"Statement": [],
},
"KeyPolicy": {"Version": "2012-10-17", "Statement": []},
},
}
},
Expand Down Expand Up @@ -679,14 +650,7 @@ def test_resolve_booleans_different_properties_for_generic_resource():


def test_resolve_template_with_a_valid_resource_without_properties():
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"MySNSTopic": {
"Type": "AWS::SNS::Topic",
}
},
}
template = {"AWSTemplateFormatVersion": "2010-09-09", "Resources": {"MySNSTopic": {"Type": "AWS::SNS::Topic"}}}

model = parse(template).resolve()
resource = model.Resources["MySNSTopic"]
Expand Down
Loading

0 comments on commit 0201ffa

Please sign in to comment.