cfn-language-discussion icon indicating copy to clipboard operation
cfn-language-discussion copied to clipboard

[Feature] Fn::If - Array support

Open pedrorgomes opened this issue 4 years ago • 2 comments

1. Title

Fn::If - Array support

I was trying to apply a condition where either the values were arrays. I did this because I had a Resource (check section 4) that receives an array (List of String). As far as I understood, this is not possible with the Fn::If condition.

2. Scope of request

So, at the moment, it is possible to use the if condition with a simple string, like the following:

!If [Condition, 'bananas', 'apples']

However, it is not possible to use the if condition with arrays:

!If [Condition, ["/bin/bash", "-c", "script.sh"], ["bundle", "exec", "rails", "db:migrate"]]

3. Expected behavior

If you try so, the cloudformation stack rollback with the error:

"Resource handler returned message: "Model validation failed (
  #/ContainerDefinitions/0/Memory: expected type: Number, found: String
  #/ContainerDefinitions/0/Cpu: expected type: Number, found: String
  #/ContainerDefinitions/0/Essential: expected type: Boolean, found: String
  #/ContainerDefinitions/0/MemoryReservation: expected type: Number, found: String
  #/ContainerDefinitions/0/Command/0: expected type: String, found: JSONArray
)" (RequestToken: 7e7030e5-6dda-3825-9b0e-5d635d26400e, HandlerErrorCode: InvalidRequest)"

The expected behavior is to be able to do so.

4. Suggest specific test cases

So I have one cloudformation stack with an AWS::ECS::TaskDefinition resource. This resource has a ContainerDefinitions property and inside that property we have other properties such as Command, where the accepted data type is a List of String. With this in mind, I tried the following:

Conditions:
  IsCartax: !Equals [!Ref ApplicationDomainName, 'cartax']

  TaskDefinition:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      ContainerDefinitions:
        - Name: 'schema'
          Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ApplicationDomainName}:${ApplicationDockerImageVersion}"
          Command:
            - !If
              - IsCartax
              - - "/bin/bash"
                - "-c"
                - ".ecs/services/migrate.sh"
              - - "bundle"
                - "exec"
                - "rails"
                - "db:migrate"

The cloudformation stack rolled back with the error:

"Resource handler returned message: "Model validation failed (
  #/ContainerDefinitions/0/Memory: expected type: Number, found: String
  #/ContainerDefinitions/0/Cpu: expected type: Number, found: String
  #/ContainerDefinitions/0/Essential: expected type: Boolean, found: String
  #/ContainerDefinitions/0/MemoryReservation: expected type: Number, found: String
  #/ContainerDefinitions/0/Command/0: expected type: String, found: JSONArray
)" (RequestToken: 7e7030e5-6dda-3825-9b0e-5d635d26400e, HandlerErrorCode: InvalidRequest)"

pedrorgomes avatar Jul 20 '21 15:07 pedrorgomes

I haven't tested but this should work

Fn::Split:

  • " "
  • !If [Condition, "/bin/bash -c script.sh", "bundle exec rails db:migrate"]

jk2l avatar Jul 22 '21 06:07 jk2l

@pedrorgomes Thank you very much for your feedback! Since this repository is focused on resource coverage, I'm transferring this issue over to a new GitHub repository dedicated to CloudFormation template language issues.

lejiati avatar May 10 '22 02:05 lejiati