Repository: cloudtools/troposphere

Issue:
Add support for serverless Aurora
Cloudformation just added new parameters to [AWS::RDS::DBCluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html) that allows you to deploy a serverless cluster using the following parameters 

[EngineMode](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-enginemode) 
The DB engine mode of the DB cluster. Valid values include provisioned or serverless.

[ScalingConfiguration](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html#cfn-rds-dbcluster-scalingconfiguration)
For DB clusters in serverless DB engine mode, the scaling properties of the DB cluster.



Discussion:

Resolving patch:
diff --git a/troposphere/rds.py b/troposphere/rds.py
--- a/troposphere/rds.py
+++ b/troposphere/rds.py
@@ -16,8 +16,10 @@
                     'oracle-ee', 'sqlserver-ee', 'sqlserver-se',
                     'sqlserver-ex', 'sqlserver-web', 'postgres', 'aurora',
                     'aurora-mysql', 'aurora-postgresql', 'mariadb')
+VALID_DB_ENGINE_MODES = ('provisioned', 'serverless')
 VALID_LICENSE_MODELS = ('license-included', 'bring-your-own-license',
                         'general-public-license', 'postgresql-license')
+VALID_SCALING_CONFIGURATION_CAPACITIES = (2, 4, 8, 16, 32, 64, 128, 256)
 
 
 def validate_iops(iops):
@@ -49,6 +51,15 @@ def validate_engine(engine):
     return engine
 
 
+def validate_engine_mode(engine_mode):
+    """Validate database EngineMode for DBCluster"""
+
+    if engine_mode not in VALID_DB_ENGINE_MODES:
+        raise ValueError("DBCluster EngineMode must be one of: %s" %
+                         ", ".join(VALID_DB_ENGINE_MODES))
+    return engine_mode
+
+
 def validate_license_model(license_model):
     """Validate LicenseModel for DBInstance"""
 
@@ -120,6 +131,21 @@ def validate_backup_retention_period(days):
     return days
 
 
+def validate_capacity(capacity):
+    """Validate ScalingConfiguration capacity for serverless DBCluster"""
+
+    if capacity not in VALID_SCALING_CONFIGURATION_CAPACITIES:
+        raise ValueError(
+            "ScalingConfiguration capacity must be one of: {}".format(
+                ", ".join(map(
+                    str,
+                    VALID_SCALING_CONFIGURATION_CAPACITIES
+                ))
+            )
+        )
+    return capacity
+
+
 class DBInstance(AWSObject):
     resource_type = "AWS::RDS::DBInstance"
 
@@ -345,6 +371,15 @@ class DBClusterParameterGroup(AWSObject):
     }
 
 
+class ScalingConfiguration(AWSProperty):
+    props = {
+        'AutoPause': (boolean, False),
+        'MaxCapacity': (validate_capacity, False),
+        'MinCapacity': (validate_capacity, False),
+        'SecondsUntilAutoPause': (positive_integer, False),
+    }
+
+
 class DBCluster(AWSObject):
     resource_type = "AWS::RDS::DBCluster"
 
@@ -356,6 +391,7 @@ class DBCluster(AWSObject):
         'DBClusterParameterGroupName': (basestring, False),
         'DBSubnetGroupName': (basestring, False),
         'Engine': (validate_engine, True),
+        'EngineMode': (validate_engine_mode, False),
         'EngineVersion': (basestring, False),
         'KmsKeyId': (basestring, False),
         'MasterUsername': (basestring, False),
@@ -364,6 +400,7 @@ class DBCluster(AWSObject):
         'PreferredBackupWindow': (validate_backup_window, False),
         'PreferredMaintenanceWindow': (basestring, False),
         'ReplicationSourceIdentifier': (basestring, False),
+        'ScalingConfiguration': (ScalingConfiguration, False),
         'SnapshotIdentifier': (basestring, False),
         'StorageEncrypted': (boolean, False),
         'Tags': ((Tags, list), False),


Test patch:
diff --git a/tests/test_rds.py b/tests/test_rds.py
--- a/tests/test_rds.py
+++ b/tests/test_rds.py
@@ -268,6 +268,13 @@ def test_validate_engine(self):
         with self.assertRaises(ValueError):
             rds.validate_engine("bad_engine")
 
+    def test_validate_engine_mode(self):
+        for e in rds.VALID_DB_ENGINE_MODES:
+            rds.validate_engine_mode(e)
+
+        with self.assertRaises(ValueError):
+            rds.validate_engine_mode("bad_engine")
+
     def test_validate_license_model(self):
         for lm in rds.VALID_LICENSE_MODELS:
             rds.validate_license_model(lm)
@@ -318,3 +325,10 @@ def test_validate_backup_retention_period(self):
             rds.validate_backup_retention_period(40)
 
         rds.validate_backup_retention_period(10)
+
+    def test_validate_capacity(self):
+        for e in rds.VALID_SCALING_CONFIGURATION_CAPACITIES:
+            rds.validate_capacity(e)
+
+        with self.assertRaises(ValueError):
+            rds.validate_capacity(3)