def test_uses_abbreviated_tag_for_yaml_sequence(self):
        # Setup
        dumper = create_refsafe_dumper(None)
        func = Sub("Something-${foo}", foo="bar")

        # Exercise
        node = func.as_yaml_node(dumper)

        # Verify
        assert isinstance(node, SequenceNode)
        assert node.tag == "!Sub"
    def test_always_uses_string_quoting_for_input(self):
        # Setup
        dumper = create_refsafe_dumper(None)
        func = Sub("Something something")

        # Exercise
        node = func.as_yaml_node(dumper)

        # Verify
        assert isinstance(node, ScalarNode)
        assert node.style != ""
    def test_uses_abbreviated_tag_for_yaml_scalar(self):
        # Setup
        dumper = create_refsafe_dumper(None)
        func = Sub("Something something")

        # Exercise
        node = func.as_yaml_node(dumper)

        # Verify
        assert isinstance(node, ScalarNode)
        assert node.tag == "!Sub"
    def test_yaml_output_doesnt_modify_multiline_string(self):
        # Setup. Use (modified) example from AWS documentation
        func = Sub(
            dedent("""
            #!/bin/bash -xe
            yum update -y aws-cfn-bootstrap
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region}
            /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region}
            echo hello from ${user}
            """),
            user="******",
        )

        data = SingleAttributeObject(one=func)

        # Exercise
        output = data.export("yaml")

        # Verify
        assert output == dedent("""
            ---
            one: !Sub
            - |
              #!/bin/bash -xe
              yum update -y aws-cfn-bootstrap
              /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region}
              /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region}
              echo hello from ${user}
            - user: bobbytables
            """)
    def test_variable_map_can_include_functions(self):
        # Setup
        dumper = create_refsafe_dumper(None)
        func = Sub(
            "arn:aws:ec2:${AWS::Region}:${account}:vpc/${vpc}",
            account="123456789012",
            vpc=ImportValue("my-vpc-id"),
        )

        # Exercise
        node = func.as_yaml_node(dumper)

        # Verify
        varmap_node = node.value[1]
        vpc_var_node = varmap_node.value[1]
        assert (vpc_var_node[1].tag == "!ImportValue"
                )  # The dict value is the second element in a tuple
    def test_yaml_output_doesnt_modify_complex_string(self):
        # Setup. Use example from AWS documentation
        func = Sub("arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}")
        data = SingleAttributeObject(one=func)

        # Exercise
        output = data.export("yaml")

        # Verify
        assert output == dedent("""
            ---
            one: !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}'
            """)
    def test_yaml_output(self):
        # Setup
        func = Sub("Something")
        data = SingleAttributeObject(one=func)

        # Exercise
        output = data.export("yaml")

        # Verify
        assert output == dedent("""
            ---
            one: !Sub 'Something'
            """)
    def test_nested_function_forces_longform_name(self):
        # Setup
        dumper = create_refsafe_dumper(Stack())
        func = ImportValue(Sub("${AWS::Region}-SharedLogBucket"))

        # Exercise
        node = func.as_yaml_node(dumper)

        # Verify
        assert node.tag == dumper.DEFAULT_MAPPING_TAG
        assert len(node.value) == 1

        function_name = get_mapping_node_key(node, 0)
        assert function_name == "Fn::ImportValue"
    def test_yaml_output_with_nested_function(self):
        """Nested YAML functions can't both use the ! short form."""
        # Setup
        func = ImportValue(Sub("${AWS::Region}-SharedLogBucket"))
        data = SingleAttributeObject(one=func)
        stack = Stack(Resources=dict(SomeResource=data))
        del stack.Metadata

        # Exercise
        output = stack.export("yaml")

        # Verify
        assert output == dedent("""
            ---
            AWSTemplateFormatVersion: '2010-09-09'
            Resources:
              SomeResource:
                one:
                  Fn::ImportValue: !Sub '${AWS::Region}-SharedLogBucket'
            """)
 def test_nonstring_variable_name_is_rejected_immediately(self, input):
     with pytest.raises(TypeError):
         _ = Sub("Something something", **{input: "bar"})
 def test_nonstring_input_is_rejected_immediately(self, input):
     with pytest.raises(TypeError):
         _ = Sub(input, foo="bar")