Bug: SAM Validate
Description:
SAM Validate returns no error for the below code but deployment reveals the error.
Steps to reproduce:
The two stacks only differs in indentation on the second line from the end.
Correct stack:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Batch Job Using EC2 OnDemand Instances with ECR Container
Parameters:
CustomerFilesStackName:
Type: String
Description: The name of the customer files stack
Resources:
StarAlignerLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
UserData:
Fn::Base64:
Fn::Sub:
- |
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0
--==BOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"
#cloud-config
repo_update: true
repo_upgrade: all
packages:
- amazon-ssm-agent
- nfs-utils
--==BOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"
#!/bin/bash
# Create mount point
mkdir -p /mnt/fsx
# Mount FSx for OpenZFS filesystem
mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${FsxEndpoint}:/fsx/ /mnt/fsx
# Add to fstab for persistence across reboots
echo "${FsxEndpoint}:/fsx/ /mnt/fsx nfs nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev 0 0" >> /etc/fstab
# Ensure Docker service is running with correct permissions
systemctl restart docker
--==BOUNDARY==
- FsxEndpoint: !ImportValue
'Fn::Sub': '${CustomerFilesStackName}-FsxEndpoint'
LaunchTemplateName: MountingFSx
Incorrect stack:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Batch Job Using EC2 OnDemand Instances with ECR Container
Parameters:
CustomerFilesStackName:
Type: String
Description: The name of the customer files stack
Resources:
StarAlignerLaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
UserData:
Fn::Base64:
Fn::Sub:
- |
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0
--==BOUNDARY==
Content-Type: text/cloud-config; charset="us-ascii"
#cloud-config
repo_update: true
repo_upgrade: all
packages:
- amazon-ssm-agent
- nfs-utils
--==BOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"
#!/bin/bash
# Create mount point
mkdir -p /mnt/fsx
# Mount FSx for OpenZFS filesystem
mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ${FsxEndpoint}:/fsx/ /mnt/fsx
# Add to fstab for persistence across reboots
echo "${FsxEndpoint}:/fsx/ /mnt/fsx nfs nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,_netdev 0 0" >> /etc/fstab
# Ensure Docker service is running with correct permissions
systemctl restart docker
--==BOUNDARY==
- FsxEndpoint: !ImportValue
'Fn::Sub': '${CustomerFilesStackName}-FsxEndpoint'
LaunchTemplateName: MountingFSx
Observed result:
No error returned by validator, only error on changeset deployment
Expected result:
Error expected to surface at validate.
Template error: every key of the context object of every Fn::Sub object must contain only alphanumeric characters and underscores`
The error comes because the "bad template" is understood like that 'Fn::Sub' string is another parameter to substitute inside the other big Fn::Sub .
sam validate doesn't do further checking on what are those parameters for a Fn:Sub, but CloudFormation when trying to deploy, actually tries to resolve it and it realizes that the value is invalid as a parameter for a Fn::Sub (throwing the error every key of the context object of every Fn::Sub object must contain only alphanumeric characters and underscores). So it's still a valid "YAML", but not valid for CFN in particular. It's interesting that this doesn't get caught by cfn-lint either (sam validate --lint).
Let me check if we consider this as something that should be checked as part of this, or if we should defer to cfn-lint only for this