aws-cloudformation / rain

A development workflow tool for working with AWS CloudFormation.
Apache License 2.0
757 stars 69 forks source link

Parameter configured with Allowed Values "Yes" "No" is rejected #316

Closed Zeethulhu closed 1 month ago

Zeethulhu commented 4 months ago

When using the rain to deploy AWS CloudFormation templates that contain parameters with AllowedValues set to strings other than boolean-like values (e.g., "Yes", "No"), the tool fails with an error indicating that the parameter value must be one of the allowed values, despite the value being correctly specified. However, when the allowed values are boolean-like strings ("true", "false"), the deployment proceeds without issues.

This Cloudformation template using "true" and "false" for Allowed values deploys with no errors;

AWSTemplateFormatVersion: "2010-09-09"

Description: A simple demo to reproduce the rain CLI tool issue with boolean-like string parameters using WaitConditionHandle.

Parameters:
  CreateThing:
    Description: Should this Thing be created?
    Type: String
    # ✅ - Working Allowed Values
    AllowedValues:
      - true
      - false
    Default: false

Conditions:
  ShouldCreateThing: !Equals
    - !Ref CreateThing
    - "true"

Resources:
  SimpleResource:
    Type: AWS::CloudFormation::WaitConditionHandle
    Condition: ShouldCreateThing

This Cloudformation template using "Yes" and "No" for Allowed values results in will return ;

"panic: error creating changeset: Parameter 'CreateThing' must be one of AllowedValues [recovered] panic: error creating changeset: Parameter 'CreateThing' must be one of AllowedValues"

AWSTemplateFormatVersion: "2010-09-09"

Description: A simple demo to reproduce the rain CLI tool issue with string parameters using WaitConditionHandle.

Parameters:
  CreateThing:
    Description: Should this Thing be created?
    Type: String
    # ❌ - Broken Allowed Values
    AllowedValues:
      - Yes
      - No
    Default: No

Conditions:
  ShouldCreateThing: !Equals
    - !Ref CreateThing
    - Yes

Resources:
  Thing:
    Type: AWS::CloudFormation::WaitConditionHandle
    Condition: ShouldCreateThing

Rain version

rain --version 
Rain v1.8.1 darwin/arm64

Debug Output

rain deploy yes_no_AllowedValues.yaml testing-rain-yesno --debug
DEBUG: Preparing template 'yes_no_AllowedValues.yaml'
DEBUG: Loading AWS config
DEBUG: Artifact bucket: rain-artifacts-123456789012-ap-southeast-3
DEBUG: No changes this pass: 1
DEBUG: Checking current status of stack 'testing-rain-yesno'
DEBUG: Handling parameters
Enter a value for parameter 'CreateThing' "Should this Thing be created?" (default value: No): 
DEBUG:   CreateThing: No
DEBUG: Creating change set
panic: error creating changeset: Parameter 'CreateThing' must be one of AllowedValues [recovered]
    panic: error creating changeset: Parameter 'CreateThing' must be one of AllowedValues

goroutine 1 [running]:
github.com/aws-cloudformation/rain/internal/cmd.execute.func1()
    github.com/aws-cloudformation/rain/internal/cmd/wrap.go:77 +0x168
panic({0x10514f2e0?, 0x1400038f530?})
    runtime/panic.go:770 +0x124
github.com/aws-cloudformation/rain/internal/cmd/deploy.init.func1(0x140001a4900?, {0x140002577d0, 0x2, 0x104ec133e?})
    github.com/aws-cloudformation/rain/internal/cmd/deploy/deploy.go:139 +0x1248
github.com/spf13/cobra.(*Command).execute(0x1057a8d80, {0x14000257770, 0x3, 0x3})
    github.com/spf13/cobra@v1.8.0/command.go:987 +0x828
github.com/spf13/cobra.(*Command).ExecuteC(0x1057a70c0)
    github.com/spf13/cobra@v1.8.0/command.go:1115 +0x344
github.com/spf13/cobra.(*Command).Execute(...)
    github.com/spf13/cobra@v1.8.0/command.go:1039
github.com/aws-cloudformation/rain/internal/cmd.execute(0x10461d45c?)
    github.com/aws-cloudformation/rain/internal/cmd/wrap.go:86 +0x50
github.com/aws-cloudformation/rain/internal/cmd.Execute(0x105745f48?)
    github.com/aws-cloudformation/rain/internal/cmd/wrap.go:95 +0x1c
main.main()
    ./main.go:23 +0x24
ericzbeard commented 3 months ago

I think this will be fixed by #329

ericzbeard commented 3 months ago

The PR I referenced above won't fix this. It's due to YAML parsing that considers all of those values to be booleans. The aws cli fails with the same error.

aws cloudformation deploy \
    --template-file test/templates/allowed-values.yaml \
    --stack-name allowed \
    --parameter-overrides CreateThing=No

An error occurred (ValidationError) when calling the CreateChangeSet operation: 
Parameter 'CreateThing' must be one of AllowedValues

The following succeeds:

aws cloudformation deploy \
    --template-file test/templates/allowed-values.yaml \
    --stack-name allowed \
    --parameter-overrides CreateThing=false

I'm not sure if there is a way to make a parameter that accepts the actual strings "Yes" and "No". For resource properties I added a new flag called --node-style that will retain quotation marks around strings from the original template during formatting, but that won't work here.