These ten questions turn on CloudFormation 24 behaviors that catch experienced developers: what Ref returns, escaping in Fn::Sub, secrets in outputs, conditional outputs, a failed first deploy, stale parameter values, the template size limit, named resources that cannot be replaced, locked exports and a rule that checks nothing. Every block ran on l1-localstack (LocalStack 4.13.1 63,725 , started as in Deploying the Network Stack, with the variables of awslocal), with cfn-lint 1.57.0 2,641 and cfn-guard 3.2.1 1,388 , in an empty ~/v5-ch7/ty folder. Where the emulator and AWS 24 disagree, the question asks what AWS does. Write down your answer, then check Appendix H: it gives LocalStack's real output, what AWS's documentation says, the reason and the section it comes from.
Setup
mkdir -p ~/v5-ch7/ty && cd ~/v5-ch7/ty
cat > q.yaml <<'EOF'
Parameters:
Stage: {Type: String, Default: dev}
IdType: {Type: String, Default: S}
ApiKey: {Type: String, NoEcho: true, Default: s3cr3t}
Resources:
Queue: {Type: AWS::SQS::Queue}
Table:
Type: AWS::DynamoDB::Table
Properties:
TableName: booknest-quiz-books
BillingMode: PAY_PER_REQUEST
AttributeDefinitions: [{AttributeName: id, AttributeType: !Ref IdType}]
KeySchema: [{AttributeName: id, KeyType: HASH}]
Outputs:
QueueRef: {Value: !Ref Queue}
TableRef: {Value: !Ref Table}
Secret: {Value: !Ref ApiKey}
Stage: {Value: !Ref Stage, Export: {Name: quiz-stage}}
EOF
cat > s.yaml <<'EOF'
Resources:
P:
Type: AWS::SSM::Parameter
Properties: {Type: String, Value: !Sub '${!AWS::Region} is ${AWS::Region}'}
EOF
cat > c.yaml <<'EOF'
Conditions: {InEurope: !Equals [!Ref 'AWS::Region', eu-west-1]}
Resources:
Logs: {Type: AWS::S3::Bucket, Condition: InEurope}
P: {Type: AWS::SSM::Parameter, Properties: {Type: String, Value: x}}
Outputs: {LogsBucket: {Value: !Ref Logs}}
EOF
printf '%s\n' 'Resources:' ' P: {Type: "AWS::SSM::Parameter", Properties:' \
' {Name: /quiz/imported, Type: String, Value: !ImportValue quiz-stage}}' > i.yaml
cat > v.guard <<'EOF'
let buckets = Resources.*[ Type == 'AWS::S3::Bucket' ]
rule versioned { %buckets.Properties.VersioningConfiguration.Status == 'Enabled' }
EOFQuestions
cfn-lint s.yaml q.yaml c.yaml; echo "lint exit $?" # for Questions 2-4
# 1. What does Ref return for each resource? (Section 7.4.1)
aws cloudformation deploy --stack-name booknest-quiz --template-file q.yaml >/dev/null
aws cloudformation describe-stacks --stack-name booknest-quiz --output text \
--query "Stacks[0].Outputs[?ends_with(OutputKey,'Ref')].[OutputKey,OutputValue]"
# 2. What value does AWS store in the parameter? (Section 7.4.2)
aws cloudformation create-stack --stack-name booknest-sub --template-body file://s.yaml
# 3. Where is the NoEcho key masked, and where not? (Sections 7.3.2 and 7.13.1)
aws cloudformation describe-stacks --stack-name booknest-quiz --output text --query \
"Stacks[0].[Parameters[?ParameterKey=='ApiKey'],Outputs[?OutputKey=='Secret']][]"
# 4. Logs exists only in eu-west-1. What does us-east-1 do? (Sections 7.3.4 and 7.13.1)
aws cloudformation deploy --stack-name booknest-cond --template-file c.yaml >/dev/null
aws cloudformation describe-stacks --stack-name booknest-cond --query 'Stacks[0].Outputs'# 5. Fix the bucket name after the failed create, redeploy. What would AWS do? (Section 7.2.6)
echo 'Resources: {B: {Type: AWS::S3::Bucket, Properties: {BucketName: Book_Nest}}}' > r.yaml
aws cloudformation deploy --stack-name booknest-rb --template-file r.yaml >/dev/null 2>&1
aws cloudformation describe-stacks --stack-name booknest-rb --query 'Stacks[0].StackStatus'
sed -i 's/Book_Nest/booknest-rb-fixed/' r.yaml
aws cloudformation deploy --stack-name booknest-rb --template-file r.yaml 2>&1 | tail -1
# 6. Change Stage's default to prod and deploy. Which Stage does the stack use? (Section 7.6.2)
sed -i 's/Default: dev/Default: prod/' q.yaml
aws cloudformation deploy --stack-name booknest-quiz --template-file q.yaml >/dev/null
aws cloudformation list-exports --query 'Exports[?Name==`quiz-stage`].Value' --output text
# 7. Pad the template past 60 KB. Does it lint, and does it deploy? (Sections 7.6.2 and 7.6.4)
{ cat r.yaml; echo Metadata:; seq 1200 | awk '{printf " N%d: %050d\n", $1, 0}'; } > big.yaml
wc -c < big.yaml && cfn-lint big.yaml && echo "lint ok"
aws cloudformation deploy --stack-name booknest-big --template-file big.yaml 2>&1 | grep -m1 ERROR# 8. Make the key id a number (N) instead of a string (S). What does AWS do? (Section 7.7.2)
aws cloudformation deploy --stack-name booknest-quiz --template-file q.yaml \
--parameter-overrides IdType=N 2>&1 | tail -1
aws dynamodb describe-table --table-name booknest-quiz-books --query Table.AttributeDefinitions
# 9. Another stack imports quiz-stage. Now change the exported value. (Section 7.8.3)
aws cloudformation deploy --stack-name booknest-importer --template-file i.yaml >/dev/null
aws cloudformation deploy --stack-name booknest-quiz --template-file q.yaml \
--parameter-overrides Stage=prod 2>&1 | tail -1
aws ssm get-parameter --name /quiz/imported --query Parameter.Value
# 10. The rule demands versioning on every bucket. Which templates pass? (Section 7.13.2)
for t in q.yaml r.yaml; do cfn-guard validate -r v.guard -d $t -S all | grep 'Status ='
echo "exit ${PIPESTATUS[0]}"; done