Nagarjuna Arigapudi
Nagarjuna Arigapudi

Reputation: 171

AWS CloudFormation function call fails: Fn::ImportValue must not depend on any resources, imported values, or Fn::GetAZs

I have a cloud formation template (mainVPC) that creates few Subnets in a VPC and exports the subnets with names "PrivateSubnetA", "PrivateSubnetB" ... I have a different cloud formation template that creates DBSubnetGroup. I want to use "PrivateSubnetA", "PrivateSubnetB" as default values if user does not provide data. CloundFormation does not support imported values in parameters. So I put some default value (XXXX) and had a condition section to see if the user has provided some input

Conditions:
  userNotProvidedSubnetA: !Equals 
    - !Ref PrivateSubnetA
    - XXXX
  userNotProvidedSubnetB: !Equals 
    - !Ref PrivateSubnetB
    - XXXX

This helps me in figuring out if the user has provided data. Now I want to use default values, if the user has not provided values, else use user-provided values. below is code for that

 DBSubnetGroup:
    Type: 'AWS::RDS::DBSubnetGroup'
    Properties:
      DBSubnetGroupDescription: RDS Aurora Cluster Subnet Group
      SubnetIds:
        - !If 
          - userNotProvidedSubnetA
          - Fn::ImportValue:
                !Sub  '${fmMainVpc}-PrivateSubnetA'
          - !Ref PrivateSubnetA
        - !If 
          - userNotProvidedSubnetB
          - Fn::ImportValue:
                !Sub '${fmMainVpc}-PrivateSubnetB'
          - !Ref PrivateSubnetB

This fails with the error "Template error: the attribute in Fn::ImportValue must not depend on any resources, imported values, or Fn::GetAZs". ImportValue is not used anywhere else in the template.

Is there a way for using exported values as default values ( the default values cannot be hardcoded, they come as exported values from a run of another stack), while providing an option for the users to provide their own values (to create resources).

Thanks.

Upvotes: 17

Views: 26765

Answers (4)

Jason M.
Jason M.

Reputation: 653

I'm my case, I had the follow resource:

          # removed for brevity
          Subnets:
            - !ImportValue: parent-stack-subnet-a
            - !ImportValue: parent-stack-subnet-b

I forgot to remove the : when changing the syntax from Fn::ImportValue to the shorthand !ImportValue. Confusing error message, but removing the : resolved it because that was incorrect usage on my part.

Upvotes: 0

James Green
James Green

Reputation: 313

I had a problem where I needed to get my artifact bucket name from my prerequisite stack, I tried this:

Fn::ImportValue:
    - 'arn:aws:s3:::${ArtifactStore}/*'

turns out you can do this and it will work. Hope his helps someone out one day!

    - !Sub

        - 'arn:aws:s3:::${BucketName}/*'

        - BucketName : !ImportValue 'ArtifactStore'

Upvotes: 6

user1847
user1847

Reputation: 3799

This can also be caused by having a reference inside Fn::ImportValue to a parameter be misnamed. For example, if I have the following parameter NetworkStackName defined and I mis-reference it in the Fn::ImportValue statement (as NetworkName), I will get this error. I would need to change the NetworkName to match the value in Parameters, NetworkStackName to fix the error.

Parameters:
  NetworkStackName:
      Type: String
      Default: happy-network-topology
Resources:
  MySQLDatabase:
    Type: AWS::RDS::DBInstance
    Properties:
      Engine: MySQL
      DBSubnetGroupName:
        Fn::ImportValue:
          !Sub "${NetworkName}-DBSubnetGroup"

Upvotes: 36

sayboras
sayboras

Reputation: 5165

Currently, Cloudformation didn't support dynamic default value. It's not possible to have a dynamic default value for CloudFormation. As the template has not executed at the time all parameters are being collected. However, you can use SSM parameter for as the workaround, something like below.

Parameters
    PagerDutyUrl:
        Type: AWS::SSM::Parameter::Value<String>
        Description: The Pagerduty url

Going back to your current cloudformation, I am thinking that value ${fmMainVpc} might not be initialized correctly.

Upvotes: 3

Related Questions