예제 #1
0
    def test_cannot_merge_if_sam_transform_version_is_different(self):
        source = Stack(Transform="123")
        target = Stack(Transform="456")

        # Exercise & Verify
        with pytest.raises(StackMergeError) as excinfo:
            target.merge_stack(source)

        assert "transform version" in str(excinfo.value).lower()
예제 #2
0
    def test_cannot_merge_if_template_version_is_different(self):
        source = Stack(AWSTemplateFormatVersion="123")
        target = Stack(AWSTemplateFormatVersion="456")

        # Exercise & Verify
        with pytest.raises(StackMergeError) as excinfo:
            target.merge_stack(source)

        assert "template version" in str(excinfo.value).lower()
예제 #3
0
    def test_merge_returns_target_stack(self):
        # Setup
        source = Stack(Resources={"SomeResource": SimpleResource()})
        target = Stack()

        # Exercise
        result = target.merge_stack(source)

        # Verify
        assert target is result
예제 #4
0
    def test_does_not_copy_description(self):
        # Setup
        source = Stack(Description="Source Description")
        original_description = "Target Description"
        target = Stack(Description=original_description)

        # Exercise
        target.merge_stack(source)

        # Verify
        assert target.Description == original_description
예제 #5
0
    def test_stack_cannot_be_set_when_it_is_already_set(self):
        # Setup
        dumper = AmazonCFNDumper(None)
        stack1 = Stack()
        stack2 = Stack()

        dumper.cfn_stack = stack1

        # Exercise & Verify
        with pytest.raises(RuntimeError) as excinfo:
            dumper.cfn_stack = stack2

        assert "already set" in str(excinfo.value)
예제 #6
0
    def test_does_not_copy_flying_circus_metadata(self):
        # Setup
        source = Stack()
        source.Metadata["FlyingCircus"]["version"] = "gamma-gamma"

        target = Stack()
        original_fc_data = target.Metadata["FlyingCircus"]

        # Exercise
        target.merge_stack(source)

        # Verify
        assert target.Metadata["FlyingCircus"] == original_fc_data
예제 #7
0
    def test_fail_if_object_doesnt_exist_except_in_another_stack(self):
        # Setup
        name = "Foo"
        stack = Stack()
        stack2 = Stack()
        data = ZeroAttributeObject()
        stack2.Resources[name] = data

        # Exercise & Verify
        with pytest.raises(ValueError) as excinfo:
            stack.get_logical_name(data)

        assert "not part of this stack" in str(excinfo.value)
예제 #8
0
    def test_item_is_added_to_the_target_stack(self, stack_attribute, item):
        # Setup
        item_name = "SomeChildProperty"
        source = Stack()
        source[stack_attribute] = {item_name: item}
        target = Stack()

        # Exercise
        target.merge_stack(source)

        # Verify
        assert len(target[stack_attribute]) == 1
        assert target[stack_attribute][item_name] is item
예제 #9
0
    def test_stack_can_be_set_after_it_has_been_reset(self):
        # Setup
        dumper = AmazonCFNDumper(None)
        stack1 = Stack()
        stack2 = Stack()

        dumper.cfn_stack = stack1
        dumper.cfn_stack = None

        # Exercise
        dumper.cfn_stack = stack2

        # Verify
        assert dumper.cfn_stack is stack2
예제 #10
0
    def test_item_is_not_removed_from_source_stack(self, stack_attribute,
                                                   item):
        # Setup
        item_name = "SomeChildProperty"
        source = Stack()
        source[stack_attribute] = {item_name: item}
        target = Stack()

        # Exercise
        target.merge_stack(source)

        # Verify
        assert len(source[stack_attribute]) == 1
        assert source[stack_attribute][item_name] is item
예제 #11
0
    def test_should_throw_error_when_called_a_second_time_with_wrong_stack(
            self):
        # Setup: Create stack with gateway
        stack = Stack()
        stack.Resources["MyVPC"] = vpc = VPC()
        vpc.ensure_internet_gateway_exists(stack)

        # Setup: Create second stack
        unrelated_stack = Stack()

        # Exercise & Verify
        with pytest.raises(RuntimeError) as excinfo:
            vpc.ensure_internet_gateway_exists(unrelated_stack)

        assert "not in this stack" in str(excinfo.value)
예제 #12
0
    def test_should_use_existing_igw_attached_to_vpc_in_stack(self):
        # Setup
        stack = Stack()
        stack.Resources["MyVPC"] = vpc = VPC()
        stack.Resources["MyGateway"] = igw = InternetGateway()
        stack.Resources[
            "MyGatewayAttachment"] = attachment = VPCGatewayAttachment(
                Properties=dict(
                    InternetGatewayId=Ref(igw),
                    VpcId=Ref(vpc),
                ))

        # Exercise
        vpc.ensure_internet_gateway_exists(stack)

        # Verify
        self._verify_vpc_has_valid_internet_gateway(vpc)
        self._verify_resource_is_in_stack(vpc.internet_gateway,
                                          stack,
                                          unique=True)
        self._verify_resource_is_in_stack(vpc.internet_gateway_attachment,
                                          stack,
                                          unique=True)

        # Verify existing Internet Gateway is used
        assert vpc.internet_gateway is igw
        assert vpc.internet_gateway_attachment is attachment
예제 #13
0
def simple_scaling_policy(alarm, asg_name, downscale=False):
    """Create a simple scaling policy using the supplied alarm."""
    stack = Stack(Description="Resources for a single scaling policy.")

    scaling_policy = ScalingPolicy(
        Properties=dict(
            AdjustmentType="ChangeInCapacity",  # TODO consider making this a lookup value
            AutoScalingGroupName=asg_name,
            Cooldown=1,
            ScalingAdjustment=-1 if downscale else 1,
        ),
    )
    stack.Resources["ScalingPolicy"] = scaling_policy

    # TODO need properties to be a real object (not a dict), and to auto-create empty lists.
    alarm.Properties.setdefault("AlarmActions", []).append(fn.Ref(scaling_policy))
    alarm.Properties.setdefault("Dimensions", []).append(
        # TODO logical class that wraps this up instead, and allows you to express in a mroe convenient way
        dict(
            Name="AutoScalingGroupName",
            Value=asg_name,
        )
    )
    stack.Resources["ScalingAlarm"] = alarm

    return stack
예제 #14
0
    def test_standard_metadata_is_present(self):
        # Exercise
        stack = Stack()

        # Verify
        assert stack.Metadata["FlyingCircus"][
            "version"] == flyingcircus.__version__
예제 #15
0
    def test_cannot_merge_if_two_outputs_have_the_same_export_name(self):
        # Setup
        export_name = "SpecialExportedValue"

        source_output = Output(Value=123, Export={"Name": export_name})
        source = Stack(Outputs={"SourceOutput": source_output})

        target_output = Output(Value=987, Export={"Name": export_name})
        target = Stack(Outputs={"TargetOutput": target_output})

        # Exercise & Verify
        with pytest.raises(StackMergeError) as excinfo:
            target.merge_stack(source)

        assert "the target stack already has exports" in str(
            excinfo.value).lower()
예제 #16
0
    def test_should_not_use_existing_igw_attached_to_different_vpc_in_stack(
            self):
        # Setup
        stack = Stack()
        stack.Resources["MyVPC"] = vpc = VPC()
        stack.Resources["OtherVPC"] = other_vpc = VPC()
        stack.Resources["MyGateway"] = igw = InternetGateway()
        stack.Resources[
            "MyGatewayAttachment"] = attachment = VPCGatewayAttachment(
                Properties=dict(
                    InternetGatewayId=Ref(igw),
                    VpcId=Ref(other_vpc),
                ))

        # Exercise
        vpc.ensure_internet_gateway_exists(stack)

        # Verify
        self._verify_vpc_has_valid_internet_gateway(vpc)
        self._verify_resource_is_in_stack(vpc.internet_gateway, stack)
        self._verify_resource_is_in_stack(vpc.internet_gateway_attachment,
                                          stack)

        # Verify existing Internet Gateway attachment is not used
        assert igw is not vpc.internet_gateway
        self._verify_resource_is_in_stack(igw, stack)

        assert attachment is not vpc.internet_gateway_attachment
        self._verify_resource_is_in_stack(attachment, stack)
예제 #17
0
    def test_find_a_pseudo_parameter(self):
        # Setup
        data = AWS_Region
        stack = Stack()

        # Exercise & Verify
        assert stack.get_logical_name(data) == "AWS::Region"
예제 #18
0
    def test_should_do_nothing_when_called_a_second_time(self):
        # Setup: Create stack
        stack = Stack()
        stack.Resources["MyVPC"] = vpc = VPC()

        # Setup: Call once
        vpc.ensure_internet_gateway_exists(stack)
        original_igw = vpc.internet_gateway
        original_attachment = vpc.internet_gateway_attachment

        # Exercise
        vpc.ensure_internet_gateway_exists(stack)

        # Verify
        self._verify_vpc_has_valid_internet_gateway(vpc)
        self._verify_resource_is_in_stack(vpc.internet_gateway,
                                          stack,
                                          unique=True)
        self._verify_resource_is_in_stack(vpc.internet_gateway_attachment,
                                          stack,
                                          unique=True)

        # Verify Internet Gateway hasn't changed
        assert vpc.internet_gateway is original_igw
        assert vpc.internet_gateway_attachment is original_attachment
예제 #19
0
    def test_resource_like_object_has_tags_applied(self, apply_tags):
        # Setup Resource-like object.
        #
        # For simplicity of testing we use the same data structure as a
        # normal resource to store the tagging information
        class ResourceLikeThing(AWSObject):
            AWS_ATTRIBUTES = {"Properties"}

            def tag(self, tags=None, tag_derived_resources=True):
                # noinspection PyAttributeOutsideInit
                self.Properties = ResourceProperties(
                    property_names={"Tags"},
                    Tags=[{
                        "Key": key,
                        "Value": value
                    } for key, value in tags.items()],
                )

        resource = ResourceLikeThing()

        # Setup
        stack = Stack(Resources={"Foo": resource})

        key = "foo"
        value = "bar"

        # Exercise
        apply_tags(stack, key, value)

        # Verify
        self.verify_tag_exists(resource, key, value)
예제 #20
0
    def test_cannot_merge_if_logical_name_is_already_used_for_that_item_type(
            self, stack_attribute, item):
        # Setup
        item_name = "SomeChildProperty"
        source = Stack()
        source[stack_attribute] = {item_name: item}

        existing_item = copy(item)
        target = Stack()
        target[stack_attribute] = {item_name: existing_item}

        # Exercise & Verify
        with pytest.raises(StackMergeError) as excinfo:
            target.merge_stack(source)

        assert "in this stack already has an item with the logical name" in str(
            excinfo.value)
예제 #21
0
    def test_find_a_resource_when_only_searching_resources(self):
        # Setup
        name = "Foo"
        stack = Stack()
        data = ZeroAttributeObject()
        stack.Resources[name] = data

        # Exercise & Verify
        assert stack.get_logical_name(data, resources_only=True) == name
예제 #22
0
    def test_find_a_resource_which_is_a_plain_dict(self):
        # Setup
        name = "Foo"
        stack = Stack()
        data = dict()
        stack.Resources[name] = data

        # Exercise & Verify
        assert stack.get_logical_name(data) == name
예제 #23
0
    def test_find_a_resource(self):
        # Setup
        name = "Foo"
        stack = Stack()
        data = ZeroAttributeObject()
        stack.Resources[name] = data

        # Exercise & Verify
        assert stack.get_logical_name(data) == name
예제 #24
0
    def test_find_a_parameter(self):
        # Setup
        name = "Foo"
        stack = Stack()
        data = Parameter(Type="String")
        stack.Parameters[name] = data

        # Exercise & Verify
        assert stack.get_logical_name(data) == name
예제 #25
0
    def test_prefix_must_be_string(self, prefix):
        # Setup
        stack = Stack(Resources={"SomeName": SimpleResource()})

        # Exercise & Verify
        with pytest.raises(TypeError) as excinfo:
            _ = stack.with_prefixed_names(prefix)

        assert "string" in str(excinfo.value).lower()
예제 #26
0
    def test_prefix_cannot_contain_special_characters(self, prefix):
        # Setup
        stack = Stack(Resources={"SomeName": SimpleResource()})

        # Exercise & Verify
        with pytest.raises(ValueError) as excinfo:
            _ = stack.with_prefixed_names(prefix)

        assert "alphanumeric" in str(excinfo.value).lower()
예제 #27
0
    def test_prefix_cannot_be_empty(self):
        # Setup
        stack = Stack(Resources={"SomeName": SimpleResource()})

        # Exercise & Verify
        with pytest.raises(ValueError) as excinfo:
            _ = stack.with_prefixed_names("")

        assert "empty" in str(excinfo.value).lower()
예제 #28
0
    def test_stack_returns_the_supplied_value(self):
        # Setup
        dumper = AmazonCFNDumper(None)
        stack = Stack()

        dumper.cfn_stack = stack

        # Exercise & Verify
        assert dumper.cfn_stack is stack
예제 #29
0
    def test_prefix_must_have_leading_capital(self):
        # Setup
        stack = Stack(Resources={"SomeName": SimpleResource()})

        # Exercise & Verify
        with pytest.raises(ValueError) as excinfo:
            _ = stack.with_prefixed_names(
                "lowercasedCamelsAreBactrianButInvalid")

        assert "uppercase" in str(excinfo.value).lower()
예제 #30
0
    def test_return_value_is_a_new_stack(self):
        # Setup
        stack = Stack(Resources={"SomeName": SimpleResource()})

        # Exercise
        new_stack = stack.with_prefixed_names(self.STACK_PREFIX)

        # Verify
        assert isinstance(new_stack, Stack)
        assert new_stack is not stack