Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 467
fizzer Avatar asked Mar 27 '18 08:03

fizzer


People also ask

What is FN :: ImportValue?

The intrinsic function Fn::ImportValue returns the value of an output exported by another stack. You typically use this function to create cross-stack references. In the following example template snippets, Stack A exports VPC security group values and Stack B imports them.

What is FN :: join in CloudFormation?

The intrinsic function Fn::Join appends a set of values into a single value, separated by the specified delimiter. If a delimiter is the empty string, the set of values are concatenated with no delimiter.

How do you troubleshoot CloudFormation stack?

Troubleshooting guide Use the CloudFormation console to view the status of your stack. In the console, you can view a list of stack events while your stack is being created, updated, or deleted. From this list, find the failure event and then view the status reason for that event.

What happens when CloudFormation stack creation fails?

If stack creation fails, go to the CloudFormation Resources list in the AWS Management Console to find the log group. Note that if stack creation fails before any instances are launched, a log group might not be created. By default, AWS deletes CloudWatch log groups if stack creation fails.


3 Answers

I was looking to do the same thing but, with a different syntax as I had multi-line sub function content. Below, is the code-snippet that worked for me.

UserData:
  Fn::Base64:
    !Sub
    - |
      #!/bin/bash -xe
      echo ${VpcId}
    - VpcId: !ImportValue MyVPCId
       
like image 187
prasun Avatar answered Sep 22 '22 19:09

prasun


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
like image 12
tianz Avatar answered Oct 16 '22 11:10

tianz


Just as a syntax alternative to the accepted answer, one might prefer to do:

command: !Sub ['touch ${filename}', filename: !ImportValue myexport]
like image 10
joakim Avatar answered Oct 16 '22 09:10

joakim