diff --git a/examples/S3_Bucket_With_AccelerateConfiguration.py b/examples/S3_Bucket_With_AccelerateConfiguration.py new file mode 100644 index 000000000..4106c4911 --- /dev/null +++ b/examples/S3_Bucket_With_AccelerateConfiguration.py @@ -0,0 +1,33 @@ +# Converted from S3_Bucket.template located at: +# http://aws.amazon.com/cloudformation/aws-cloudformation-templates/ + +from troposphere import Output, Ref, Template +from troposphere.s3 import Bucket, PublicRead, AccelerateConfiguration + +t = Template() + +t.add_description( + "AWS CloudFormation Sample Template S3_Bucket: Sample template showing :" + "How to create a publicly accessible S3 bucket. " + "How to enable S3 Transfer Acceleration. " + "**WARNING** This template creates an Amazon S3 Bucket. " + "You will be billed for the AWS resources used if you create " + "a stack from this template.") + +s3bucket = t.add_resource(Bucket( + "S3Bucket", + # Make public Read + AccessControl=PublicRead, + # Enable s3 Transfer Acceleration + AccelerateConfiguration=AccelerateConfiguration( + AccelerationStatus="Enabled", + ), +)) + +t.add_output(Output( + "BucketName", + Value=Ref(s3bucket), + Description="Name of S3 bucket with s3 transfer acceleration enabled", +)) + +print(t.to_json()) diff --git a/tests/examples_output/S3_Bucket_With_AccelerateConfiguration.template b/tests/examples_output/S3_Bucket_With_AccelerateConfiguration.template new file mode 100644 index 000000000..256545fb5 --- /dev/null +++ b/tests/examples_output/S3_Bucket_With_AccelerateConfiguration.template @@ -0,0 +1,22 @@ +{ + "Description": "AWS CloudFormation Sample Template S3_Bucket: Sample template showing :How to create a publicly accessible S3 bucket. How to enable S3 Transfer Acceleration. **WARNING** This template creates an Amazon S3 Bucket. You will be billed for the AWS resources used if you create a stack from this template.", + "Outputs": { + "BucketName": { + "Description": "Name of S3 bucket with s3 transfer acceleration enabled", + "Value": { + "Ref": "S3Bucket" + } + } + }, + "Resources": { + "S3Bucket": { + "Properties": { + "AccelerateConfiguration": { + "AccelerationStatus": "Enabled" + }, + "AccessControl": "PublicRead" + }, + "Type": "AWS::S3::Bucket" + } + } +} diff --git a/tests/test_basic.py b/tests/test_basic.py index a3e9d4258..24dc7e0e7 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -3,7 +3,7 @@ from troposphere import If, Join, Ref, Split, Sub, Template from troposphere import depends_on_helper from troposphere.ec2 import Instance, Route, SecurityGroupRule -from troposphere.s3 import Bucket +from troposphere.s3 import Bucket, AccelerateConfiguration from troposphere.elasticloadbalancing import HealthCheck from troposphere.validators import positive_integer @@ -63,6 +63,33 @@ def test_resource_depends_on_attr(self): self.assertEqual(b1.title, b2.DependsOn) +class TestS3AccelerateConfiguration(unittest.TestCase): + def test_accelerate_configuration_enabled(self): + ac = AccelerateConfiguration( + AccelerationStatus='Enabled', + ) + self.assertEqual('Enabled', ac.AccelerationStatus) + + def test_accelerate_configuration_suspended(self): + ac = AccelerateConfiguration( + AccelerationStatus='Suspended', + ) + self.assertEqual('Suspended', ac.AccelerationStatus) + + def test_accelerate_configuration_invalid_value(self): + with self.assertRaises(ValueError): + AccelerateConfiguration(AccelerationStatus='Invalid Value') + + def test_s3_bucket_accelerate_configuration(self): + t = Template() + ac = AccelerateConfiguration(AccelerationStatus="Enabled") + + b = Bucket("s3Bucket", AccelerateConfiguration=ac) + t.add_resource(b) + output = t.to_json() + self.assertIn('"AccelerationStatus": "Enabled"', output) + + def call_correct(x): return x diff --git a/troposphere/s3.py b/troposphere/s3.py index d4f2d8439..f4f9ce148 100644 --- a/troposphere/s3.py +++ b/troposphere/s3.py @@ -6,6 +6,7 @@ from . import AWSObject, AWSProperty, Tags from .validators import positive_integer, s3_bucket_name +from .validators import s3_transfer_acceleration_status try: from awacs.aws import Policy @@ -46,6 +47,12 @@ class VersioningConfiguration(AWSProperty): } +class AccelerateConfiguration(AWSProperty): + props = { + 'AccelerationStatus': (s3_transfer_acceleration_status, True), + } + + class RedirectAllRequestsTo(AWSProperty): props = { 'HostName': (basestring, True), @@ -269,6 +276,7 @@ class Bucket(AWSObject): props = { 'AccessControl': (basestring, False), + 'AccelerateConfiguration': (AccelerateConfiguration, False), 'BucketName': (s3_bucket_name, False), 'CorsConfiguration': (CorsConfiguration, False), 'LifecycleConfiguration': (LifecycleConfiguration, False), diff --git a/troposphere/validators.py b/troposphere/validators.py index 9395e77ce..03bee72e5 100644 --- a/troposphere/validators.py +++ b/troposphere/validators.py @@ -133,6 +133,17 @@ def status(status): return status +def s3_transfer_acceleration_status(value): + valid_status = ['Enabled', 'Suspended'] + if value not in valid_status: + raise ValueError( + 'AccelerationStatus must be one of: "%s"' % ( + ', '.join(valid_status) + ) + ) + return value + + def iam_names(b): iam_name_re = compile(r'^[a-zA-Z0-9_\.\+\=\@\-\,]+$') if iam_name_re.match(b):