Search code examples
amazon-web-servicesyamlaws-cloudformation

AWS CloudFormation: Combining ImportValue and Sub functions causes error


When uploading my template to CloudFormation I am receiving the following validation error:

Template validation error: Template error: the attribute in Fn::ImportValue must not depend on any resources, imported values, or Fn::GetAZs

I have a test template below that reproduces the issue:

Resources:
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      ImageId: ami-3bfab942
      InstanceType: t2.micro
      KeyName: mykeypair
      UserData:
        "Fn::Base64":
          !Sub |
            #!/bin/bash
            yum update -y aws-cfn-bootstrap
            /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2Instance --configsets testset --region ${AWS::Region}
            yum -y update
    Metadata:
      AWS::CloudFormation::Init:
        configSets:
          testset:
            - "testConfiguration"
        testConfiguration:
          commands: 
            CreateTestFile:
              cwd: "~"
              command: 
                "Fn::ImportValue": 
                  !Sub | 
                    touch ${myexport}

To keep things as simple as I can I'm basically trying to create a bash command using the export. So in the above example I want to create a file named based on what the export value is. I don't understand the error message in the context of what I'm trying to do. I've validated that the export exists in another stack that I've created.


Solution

  • The problem is not Sub, but you are not using ImportValue correctly. The thing you are actually importing in your code is not myexport, but touch ${myexport} as a whole. You should put your ImportValue inside Sub.

    Also, if the export value is literally called myexport, you don't put it inside ${}; you only do this if it is a parameter you defined in the template.

    You could change that last few lines to this:

    command: !Sub
        - "touch ${filename}"
        - filename: !ImportValue myexport