From 17325130f1acea26ffe4b428fa546689d41eb9a1 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 10:29:02 -0500 Subject: [PATCH 01/13] added support for placement constraint --- troposphere/ecs.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 5677e24c7..83de514e6 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -35,6 +35,7 @@ class Service(AWSObject): 'DesiredCount': (positive_integer, False), 'LoadBalancers': ([LoadBalancer], False), 'Role': (basestring, False), + 'PlacementConstraints': (basestring, False), 'TaskDefinition': (basestring, True), } @@ -68,6 +69,11 @@ class VolumesFrom(AWSProperty): 'ReadOnly': (boolean, False), } +class placementConstraints(AWSProperty): + props = { + 'Type': (basestring, True), + 'Expression': (basestring, False), + } class HostEntry(AWSProperty): props = { From a5bafb273d632a6df80541ff8d0bda5908e995a6 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 10:37:35 -0500 Subject: [PATCH 02/13] updated parameter to be a list --- troposphere/ecs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 83de514e6..4fc3a7f88 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -35,7 +35,7 @@ class Service(AWSObject): 'DesiredCount': (positive_integer, False), 'LoadBalancers': ([LoadBalancer], False), 'Role': (basestring, False), - 'PlacementConstraints': (basestring, False), + 'PlacementConstraints': ([PlacementConstraints], False), 'TaskDefinition': (basestring, True), } @@ -69,7 +69,7 @@ class VolumesFrom(AWSProperty): 'ReadOnly': (boolean, False), } -class placementConstraints(AWSProperty): +class PlacementConstraints(AWSProperty): props = { 'Type': (basestring, True), 'Expression': (basestring, False), From 462a87fb181fe0086c4913e4adf4ae332b35d564 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 10:42:17 -0500 Subject: [PATCH 03/13] added support for PlacementStrategies --- troposphere/ecs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 4fc3a7f88..342481141 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -36,6 +36,7 @@ class Service(AWSObject): 'LoadBalancers': ([LoadBalancer], False), 'Role': (basestring, False), 'PlacementConstraints': ([PlacementConstraints], False), + 'PlacementStrategies': ([PlacementStrategies], False), 'TaskDefinition': (basestring, True), } @@ -70,6 +71,12 @@ class VolumesFrom(AWSProperty): } class PlacementConstraints(AWSProperty): + props = { + 'Type': (basestring, True), + 'Field': (basestring, False), + } + +class PlacementStrategies(AWSProperty): props = { 'Type': (basestring, True), 'Expression': (basestring, False), From 47fc5a2751cf8db8b657e9c5a8fa09e9a49f8113 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 10:45:21 -0500 Subject: [PATCH 04/13] renamed classes --- troposphere/ecs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 342481141..64b67536a 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -35,8 +35,8 @@ class Service(AWSObject): 'DesiredCount': (positive_integer, False), 'LoadBalancers': ([LoadBalancer], False), 'Role': (basestring, False), - 'PlacementConstraints': ([PlacementConstraints], False), - 'PlacementStrategies': ([PlacementStrategies], False), + 'PlacementConstraints': ([PlacementConstraint], False), + 'PlacementStrategies': ([PlacementStrategy], False), 'TaskDefinition': (basestring, True), } @@ -70,13 +70,13 @@ class VolumesFrom(AWSProperty): 'ReadOnly': (boolean, False), } -class PlacementConstraints(AWSProperty): +class PlacementConstraint(AWSProperty): props = { 'Type': (basestring, True), 'Field': (basestring, False), } -class PlacementStrategies(AWSProperty): +class PlacementStrategy(AWSProperty): props = { 'Type': (basestring, True), 'Expression': (basestring, False), From 359696aa74b32c55a936ffbde23bd7832ed15d30 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 10:47:13 -0500 Subject: [PATCH 05/13] fixed properties with both classes --- troposphere/ecs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 64b67536a..b2bc99f8a 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -73,13 +73,13 @@ class VolumesFrom(AWSProperty): class PlacementConstraint(AWSProperty): props = { 'Type': (basestring, True), - 'Field': (basestring, False), + 'Expression': (basestring, False), } class PlacementStrategy(AWSProperty): props = { 'Type': (basestring, True), - 'Expression': (basestring, False), + 'Field': (basestring, False), } class HostEntry(AWSProperty): From c00bf9296765aa4ba70f84841ae7d6f185ceb922 Mon Sep 17 00:00:00 2001 From: curras Date: Mon, 1 May 2017 11:03:33 -0500 Subject: [PATCH 06/13] added tests --- tests/test_ecs.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/test_ecs.py b/tests/test_ecs.py index 8e631404c..668d117f9 100644 --- a/tests/test_ecs.py +++ b/tests/test_ecs.py @@ -6,6 +6,31 @@ class TestECS(unittest.TestCase): + def test_allow_placement_strategy_constraint(self): + task_definition = ecs.TaskDefinition( + "mytaskdef", + ContainerDefinitions=[ + ecs.ContainerDefinition( + Image="myimage", + Memory="300", + Name="mycontainer", + ) + ], + Volumes=[ + ecs.Volume(Name="my-vol"), + ], + ) + ecs_service = ecs.Service( + 'Service', + Cluster='cluster', + DesiredCount=2, + PlacementStategies='spread', + PlacementConstraint='distinctInstance', + TaskDefinition=Ref(task_definition), + ) + + ecs_service.to_dict() + def test_allow_string_cluster(self): task_definition = ecs.TaskDefinition( "mytaskdef", @@ -24,6 +49,8 @@ def test_allow_string_cluster(self): 'Service', Cluster='cluster', DesiredCount=2, + PlacementStategies='spread', + PlacementConstraint='distinctInstance', TaskDefinition=Ref(task_definition), ) From 3d54f7cb951a1f083d7d59afd3305f6e1841c889 Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 11:26:55 -0500 Subject: [PATCH 07/13] updated tests --- .gitignore | 1 + tests/test_ecs.py | 4 ++-- troposphere/ecs.py | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index eab571678..cf46a0d2f 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ nosetests.xml .project .pydevproject .idea +.venv # Vim *.sw* diff --git a/tests/test_ecs.py b/tests/test_ecs.py index 668d117f9..2d39c516e 100644 --- a/tests/test_ecs.py +++ b/tests/test_ecs.py @@ -24,8 +24,8 @@ def test_allow_placement_strategy_constraint(self): 'Service', Cluster='cluster', DesiredCount=2, - PlacementStategies='spread', - PlacementConstraint='distinctInstance', + PlacementStrategies=[ecs.PlacementStrategy(Type="blah")], + PlacementConstraints=[ecs.PlacementConstraint(Type="test")], TaskDefinition=Ref(task_definition), ) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index b2bc99f8a..1d31a48ab 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -25,6 +25,17 @@ class DeploymentConfiguration(AWSProperty): 'MinimumHealthyPercent': (positive_integer, False), } +class PlacementConstraint(AWSProperty): + props = { + 'Type': (basestring, True), + 'Expression': (basestring, False), + } + +class PlacementStrategy(AWSProperty): + props = { + 'Type': (basestring, True), + 'Field': (basestring, False), + } class Service(AWSObject): resource_type = "AWS::ECS::Service" @@ -70,17 +81,6 @@ class VolumesFrom(AWSProperty): 'ReadOnly': (boolean, False), } -class PlacementConstraint(AWSProperty): - props = { - 'Type': (basestring, True), - 'Expression': (basestring, False), - } - -class PlacementStrategy(AWSProperty): - props = { - 'Type': (basestring, True), - 'Field': (basestring, False), - } class HostEntry(AWSProperty): props = { From 48a05a2419f8e2804bb6790af9e84462706fa1a4 Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 11:28:25 -0500 Subject: [PATCH 08/13] updated --- tests/test_ecs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_ecs.py b/tests/test_ecs.py index 2d39c516e..914bfb0e3 100644 --- a/tests/test_ecs.py +++ b/tests/test_ecs.py @@ -49,8 +49,6 @@ def test_allow_string_cluster(self): 'Service', Cluster='cluster', DesiredCount=2, - PlacementStategies='spread', - PlacementConstraint='distinctInstance', TaskDefinition=Ref(task_definition), ) From 1afba5bea1dafe013e3f849952c8fed443002b62 Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 12:15:02 -0500 Subject: [PATCH 09/13] updated for pep8 --- troposphere/ecs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 1d31a48ab..7dea7ff79 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -25,18 +25,21 @@ class DeploymentConfiguration(AWSProperty): 'MinimumHealthyPercent': (positive_integer, False), } + class PlacementConstraint(AWSProperty): props = { 'Type': (basestring, True), 'Expression': (basestring, False), } + class PlacementStrategy(AWSProperty): props = { 'Type': (basestring, True), 'Field': (basestring, False), } + class Service(AWSObject): resource_type = "AWS::ECS::Service" From cb1da64fcdbcb2bd05106688fa066d4c26e612ba Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 12:32:03 -0500 Subject: [PATCH 10/13] added service name --- troposphere/ecs.py | 7 ++++--- troposphere/validators.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index 7dea7ff79..d4a27da5b 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -1,5 +1,5 @@ from . import AWSObject, AWSProperty -from .validators import boolean, network_port, positive_integer +from .validators import boolean, network_port, positive_integer, placement_strategy, placement_constraint class Cluster(AWSObject): @@ -28,14 +28,14 @@ class DeploymentConfiguration(AWSProperty): class PlacementConstraint(AWSProperty): props = { - 'Type': (basestring, True), + 'Type': (placement_constraint, True), 'Expression': (basestring, False), } class PlacementStrategy(AWSProperty): props = { - 'Type': (basestring, True), + 'Type': (placement_strategy, True), 'Field': (basestring, False), } @@ -51,6 +51,7 @@ class Service(AWSObject): 'Role': (basestring, False), 'PlacementConstraints': ([PlacementConstraint], False), 'PlacementStrategies': ([PlacementStrategy], False), + 'ServiceName': (basestring, False), 'TaskDefinition': (basestring, True), } diff --git a/troposphere/validators.py b/troposphere/validators.py index 2b15704ef..1be897a7e 100644 --- a/troposphere/validators.py +++ b/troposphere/validators.py @@ -79,6 +79,20 @@ def s3_bucket_name(b): raise ValueError("%s is not a valid s3 bucket name" % b) +def placement_strategy(x): + valid_types = ['random', 'spread', 'binpack'] + if x not in valid_types: + raise ValueError('Type must be one of: %s' %', '.join(valid_types)) + return x + + +def placement_constraint(x): + valid_types = ['distinctInstance', 'memberOf'] + if x not in valid_types: + raise ValueError('Type must be one of: %s' %', '.join(valid_types)) + return x + + def elb_name(b): elb_name_re = compile(r'^[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,30}[a-zA-Z0-9]{1})?$') # noqa if elb_name_re.match(b): From 50a0ab76820cc90f0a705265675a7f13a933bd7d Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 12:34:06 -0500 Subject: [PATCH 11/13] updated service name and reverted validators --- troposphere/ecs.py | 6 +++--- troposphere/validators.py | 14 -------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index d4a27da5b..ab243e438 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -1,5 +1,5 @@ from . import AWSObject, AWSProperty -from .validators import boolean, network_port, positive_integer, placement_strategy, placement_constraint +from .validators import boolean, network_port, positive_integer class Cluster(AWSObject): @@ -28,14 +28,14 @@ class DeploymentConfiguration(AWSProperty): class PlacementConstraint(AWSProperty): props = { - 'Type': (placement_constraint, True), + 'Type': (basestring, True), 'Expression': (basestring, False), } class PlacementStrategy(AWSProperty): props = { - 'Type': (placement_strategy, True), + 'Type': (basestring, True), 'Field': (basestring, False), } diff --git a/troposphere/validators.py b/troposphere/validators.py index 1be897a7e..2b15704ef 100644 --- a/troposphere/validators.py +++ b/troposphere/validators.py @@ -79,20 +79,6 @@ def s3_bucket_name(b): raise ValueError("%s is not a valid s3 bucket name" % b) -def placement_strategy(x): - valid_types = ['random', 'spread', 'binpack'] - if x not in valid_types: - raise ValueError('Type must be one of: %s' %', '.join(valid_types)) - return x - - -def placement_constraint(x): - valid_types = ['distinctInstance', 'memberOf'] - if x not in valid_types: - raise ValueError('Type must be one of: %s' %', '.join(valid_types)) - return x - - def elb_name(b): elb_name_re = compile(r'^[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,30}[a-zA-Z0-9]{1})?$') # noqa if elb_name_re.match(b): From 81ec4c1ebce56de3af415b1434a9d882f733e2d8 Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 15:50:20 -0500 Subject: [PATCH 12/13] updated to add validators --- tests/test_ecs.py | 4 ++-- troposphere/ecs.py | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/test_ecs.py b/tests/test_ecs.py index 914bfb0e3..aee9b6387 100644 --- a/tests/test_ecs.py +++ b/tests/test_ecs.py @@ -24,8 +24,8 @@ def test_allow_placement_strategy_constraint(self): 'Service', Cluster='cluster', DesiredCount=2, - PlacementStrategies=[ecs.PlacementStrategy(Type="blah")], - PlacementConstraints=[ecs.PlacementConstraint(Type="test")], + PlacementStrategies=[ecs.PlacementStrategy(Type="random")], + PlacementConstraints=[ecs.PlacementConstraint(Type="distinctInstance")], TaskDefinition=Ref(task_definition), ) diff --git a/troposphere/ecs.py b/troposphere/ecs.py index ab243e438..a00c0ab21 100644 --- a/troposphere/ecs.py +++ b/troposphere/ecs.py @@ -26,16 +26,32 @@ class DeploymentConfiguration(AWSProperty): } +def placement_strategy_validator(x): + valid_values = ['random', 'spread', 'binpack'] + if x not in valid_values: + raise ValueError("Placement Strategy type must be one of: %s" % + ', '.join(valid_values)) + return x + + +def placement_constraint_validator(x): + valid_values = ['distinctInstance', 'memberOf'] + if x not in valid_values: + raise ValueError("Placement Constraint type must be one of: %s" % + ', '.join(valid_values)) + return x + + class PlacementConstraint(AWSProperty): props = { - 'Type': (basestring, True), + 'Type': (placement_constraint_validator, True), 'Expression': (basestring, False), } class PlacementStrategy(AWSProperty): props = { - 'Type': (basestring, True), + 'Type': (placement_strategy_validator, True), 'Field': (basestring, False), } From 2e9a31e98f733a06bfabc0b159aba8d27f17095f Mon Sep 17 00:00:00 2001 From: "Kevin M. Truckenmiller" Date: Mon, 1 May 2017 15:54:44 -0500 Subject: [PATCH 13/13] pep 8 typo --- tests/test_ecs.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_ecs.py b/tests/test_ecs.py index aee9b6387..73333bec5 100644 --- a/tests/test_ecs.py +++ b/tests/test_ecs.py @@ -24,8 +24,16 @@ def test_allow_placement_strategy_constraint(self): 'Service', Cluster='cluster', DesiredCount=2, - PlacementStrategies=[ecs.PlacementStrategy(Type="random")], - PlacementConstraints=[ecs.PlacementConstraint(Type="distinctInstance")], + PlacementStrategies=[ + ecs.PlacementStrategy( + Type="random", + ) + ], + PlacementConstraints=[ + ecs.PlacementConstraint( + Type="distinctInstance", + ) + ], TaskDefinition=Ref(task_definition), )