Repository: cloudtools/troposphere

Issue:
Fixed CreationPolicy
Added AWSAttribute class
Switched CreationPolicy and UpdatePolicy to use AWS Attribute class
Added unit tests for CreationPolicy and UpdatePolicy

resolves https://github.com/cloudtools/troposphere/issues/154



Discussion:

Resolving patch:
diff --git a/troposphere/__init__.py b/troposphere/__init__.py
--- a/troposphere/__init__.py
+++ b/troposphere/__init__.py
@@ -36,7 +36,7 @@ def __init__(self, title, template=None, **kwargs):
         self.propnames = self.props.keys()
         self.attributes = ['DependsOn', 'DeletionPolicy',
                            'Metadata', 'UpdatePolicy',
-                           'Condition']
+                           'Condition', 'CreationPolicy']
 
         # unset/None is also legal
         if title and not valid_names.match(title):
@@ -173,6 +173,18 @@ def __init__(self, title=None, **kwargs):
         super(AWSProperty, self).__init__(title, **kwargs)
 
 
+class AWSAttribute(BaseAWSObject):
+    dictname = None
+
+    """
+    Used for CloudFormation Resource Attribute objects
+    http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/
+    aws-product-attribute-reference.html
+    """
+    def __init__(self, title=None, **kwargs):
+        super(AWSAttribute, self).__init__(title, **kwargs)
+
+
 def validate_pausetime(pausetime):
     if not pausetime.startswith('PT'):
         raise ValueError('PauseTime should look like PT#H#M#S')
diff --git a/troposphere/policies.py b/troposphere/policies.py
--- a/troposphere/policies.py
+++ b/troposphere/policies.py
@@ -1,4 +1,4 @@
-from . import BaseAWSObject, AWSProperty, validate_pausetime
+from . import AWSProperty, AWSAttribute, validate_pausetime
 from .validators import positive_integer, integer, boolean
 
 
@@ -18,7 +18,7 @@ class AutoScalingScheduledAction(AWSProperty):
     }
 
 
-class UpdatePolicy(BaseAWSObject):
+class UpdatePolicy(AWSAttribute):
     props = {
         'AutoScalingRollingUpdate': (AutoScalingRollingUpdate, False),
         'AutoScalingScheduledAction': (AutoScalingScheduledAction, False),
@@ -32,7 +32,7 @@ class ResourceSignal(AWSProperty):
     }
 
 
-class CreationPolicy(BaseAWSObject):
+class CreationPolicy(AWSAttribute):
     props = {
         'ResourceSignal': (ResourceSignal, True),
     }


Test patch:
diff --git a/tests/test_policies.py b/tests/test_policies.py
new file mode 100644
--- /dev/null
+++ b/tests/test_policies.py
@@ -0,0 +1,71 @@
+import json
+import unittest
+
+from troposphere import awsencode
+from troposphere.policies import CreationPolicy, ResourceSignal, UpdatePolicy
+from troposphere.policies import AutoScalingRollingUpdate
+
+
+class TestCreationPolicy(unittest.TestCase):
+
+    def test_pausetime(self):
+        with self.assertRaises(ValueError):
+            CreationPolicy(ResourceSignal=ResourceSignal(Count=2,
+                                                         Timeout='90'))
+
+    def test_works(self):
+        policy = CreationPolicy(
+            ResourceSignal=ResourceSignal(
+                Count=2,
+                Timeout='PT10M'
+            )
+        )
+        self.assertEqual(policy.ResourceSignal.Count, 2)
+        self.assertEqual(policy.ResourceSignal.Timeout, 'PT10M')
+
+    def test_json(self):
+        policy = CreationPolicy(
+            ResourceSignal=ResourceSignal(
+                Count=2,
+                Timeout='PT10M'
+            )
+        )
+        p = json.loads(json.dumps(policy, cls=awsencode))
+        self.assertEqual(p['ResourceSignal']['Count'], 2)
+        self.assertEqual(p['ResourceSignal']['Timeout'], 'PT10M')
+
+
+class TestUpdatePolicy(unittest.TestCase):
+
+    def test_pausetime(self):
+        with self.assertRaises(ValueError):
+            UpdatePolicy(AutoScalingRollingUpdate=AutoScalingRollingUpdate(
+                PauseTime='90'
+            ))
+
+    def test_works(self):
+        p = UpdatePolicy(
+            AutoScalingRollingUpdate=AutoScalingRollingUpdate(
+                MaxBatchSize=2,
+                MinInstancesInService=1,
+                PauseTime='PT90S',
+                WaitOnResourceSignals=True))
+        self.assertEqual(p.AutoScalingRollingUpdate.MaxBatchSize, 2)
+        self.assertEqual(p.AutoScalingRollingUpdate.MinInstancesInService, 1)
+        self.assertEqual(p.AutoScalingRollingUpdate.PauseTime, 'PT90S')
+        self.assertTrue(p.AutoScalingRollingUpdate.WaitOnResourceSignals)
+
+    def test_json(self):
+        p = UpdatePolicy(
+            AutoScalingRollingUpdate=AutoScalingRollingUpdate(
+                MaxBatchSize=2,
+                MinInstancesInService=1,
+                PauseTime='PT90S',
+                WaitOnResourceSignals=True))
+        p = json.loads(json.dumps(p, cls=awsencode))
+        self.assertEqual(p['AutoScalingRollingUpdate']['MaxBatchSize'], 2)
+        self.assertEqual(
+            p['AutoScalingRollingUpdate']['MinInstancesInService'], 1
+        )
+        self.assertEqual(p['AutoScalingRollingUpdate']['PauseTime'], 'PT90S')
+        self.assertTrue(p['AutoScalingRollingUpdate']['WaitOnResourceSignals'])