Writing Macros

Writing and Registering a Template Macro

BookNest wants every table and bucket tagged with the application and stage. This macro adds app and stage tags to each AWS 24 ::DynamoDB 24 ::Table and AWS::S3 24 ::Bucket, keeping tags the author set, and takes the stage from templateParameterValues, already resolved. The code is an inline ZipFile in infra/macro.yaml, whose first 20 lines declare the function and its basic execution role; AWS::CloudFormation 24 ::Macro registers the name:

infra/macro.yaml (end): the macro's code and registrationYAML
      Code:
        ZipFile: |
          exports.handler = async ({ requestId, fragment, templateParameterValues: p }) => {
            const tags = [{ Key: "app", Value: "booknest" }, { Key: "stage", Value: p.Stage }];
            for (const r of Object.values(fragment.Resources ?? {})) {
              if (!["AWS::DynamoDB::Table", "AWS::S3::Bucket"].includes(r.Type)) continue;
              r.Properties ??= {};
              const own = r.Properties.Tags ?? [];
              const missing = tags.filter((t) => !own.some((o) => o.Key === t.Key));
              r.Properties.Tags = [...own, ...missing];
            }
            return { requestId, status: "success", fragment };
          };
  TagsMacro:
    Type: AWS::CloudFormation::Macro
    Properties:
      Name: BookNestTags
      FunctionName: !GetAtt TagsFunction.Arn

infra/tagged.yaml opts in with Transform: BookNestTags and declares a table, booknest-${Stage}-reviews, with one tag of its own (owner), and a bucket with none:

Registering the macro, deploying a template that uses it, and reading the tagsShell
aws cloudformation deploy --stack-name booknest-macro --template-file macro.yaml \
  --capabilities CAPABILITY_IAM
aws cloudformation deploy --stack-name booknest-tagged --template-file tagged.yaml \
  --parameter-overrides Stage=prod --capabilities CAPABILITY_AUTO_EXPAND
aws dynamodb list-tags-of-resource --output text --query 'Tags[].[Key,Value]' \
  --resource-arn arn:aws:dynamodb:us-east-1:000000000000:table/booknest-prod-reviews
Output
...
Successfully created/updated stack - booknest-macro
...
Successfully created/updated stack - booknest-tagged
owner   catalog-team
app   booknest
stage   prod

The live table carries its owner tag plus the macro's two, and get-template --template-stage Processed shows them. Keep the macro's stack while templates use it, since every update calls the function again. More macros, such as string functions and a resource-count multiplier, are in github.com/aws-cloudformation/aws-cloudformation-templates (https://github.com/aws-cloudformation/aws-cloudformation-templates 5,218 ) under CloudFormation/MacrosExamples.