aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 54 forks source link

DependsOn should work with AWS::NoValue #1015

Open DanielEIlie opened 2 years ago

DanielEIlie commented 2 years ago

Name of the resource

Other

Resource name

Not resource specific

Description

Background

DependsOn is particularly useful in cases where a direct dependency cannot be determined and where the resource to be depended on takes a while to be created. It is the case for example, when an AWS::AppStream::Fleet is created with a dependency on AWS::AppStream::DirectoryConfig. The latter can take a while to create and is entirely optional.

Please note that there is no direct dependency between the two: you cannot use !Ref or !GetAtt in AWS::AppStream::Fleet to refer to AWS::AppStream::DirectoryConfig. Given that there is no dependency between these resources, and that AWS::AppStream::DirectoryConfig may not exist, the DependsOn: should be disabled from AWS::AppStream::Fleet by using AWS::NoValue.

Test example

The example below is simplified for testing purposes. The two security groups can be created:

The error that I am getting, when I try to execute the code is: Template format error: DependsOn must be a string or list of strings. If AWS::NoValue is a string or not is debatable, which is why I am raising this as an enhancement and not a bug

Parameters:
  VPC:
    Type: String
    Default: vpc-xxxx
  Flag:
    Type: String
Conditions:
  Available: !Equals
    - !Ref Flag
    - OK
Resources:
  SG1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SG1
      GroupDescription: SG1
      Tags:
        - Key: Name
          Value: SG1
      VpcId: !Ref VPC
  SG2:
    DependsOn: !If
      - Available
      - SG1
      - !Ref AWS::NoValue
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SG2
      GroupDescription: SG2
      Tags:
        - Key: Name
          Value: SG2
      VpcId: !Ref VPC

Other Details

The workaround to this issue would be to replace AWS::NoValue with a resource that is created in any circumstances as early as possible. Further tests revealed that this was not an workaround. It would seem that DependsOn cannot accept any functions.

benbridts commented 2 years ago

I believe this template might actually do what you want.

The Deployment of SG2 will always start after the Dummy SSM parameter, but if the Parallel option is chosen, it will not wait on SG1. If the Sequential option is chosen, the order will be SG1 -> Dummy -> SG2.

Parameters:
  VPC:
    Type: AWS::EC2::VPC::Id
  Deployment:
    Type: String
    AllowedValues: ['Sequential', 'Parallel']
Conditions:
  KeepOrder: !Equals
    - !Ref Deployment
    - Sequential
Resources:
  SG1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SG1
      GroupDescription: SG1
      Tags:
        - Key: Name
          Value: SG1
      VpcId: !Ref VPC
  Dummy:
    Type: AWS::SSM::Parameter
    Properties:
      Description: "Dummy Parameter that acts as a dependency"
      Type: "String"
      Value: !If [ KeepOrder, !Ref SG1, "NoDependency" ]
  SG2:
    DependsOn: Dummy
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: SG2
      GroupDescription: SG2
      Tags:
        - Key: Name
          Value: SG2
      VpcId: !Ref VPC
DanielEIlie commented 2 years ago

@benbridts Thank you I got something similar in the end. My concern was that DependsOn: must resolve to an actual string. In your case it resolves to a AWS::SSM::Parameter