» Aspects

Aspects allow you to apply an operation to all constructs within a given scope. You may want to use them in your CDK for Terraform (CDKTF) application to mutate elements (e.g., add tags to cloud resources) or for validation (e.g., ensure all S3 Buckets are encrypted).

» Define Aspects

To create an aspect, you must import the Aspects class and the IAspect interface and implement one or more methods for IAspect. Then, you can call the aspect one or more times on any construct within your application.

Everything within a CDKTF application descends from the Construct class, so you could call the construct on the any instantiated element. This includes the entire application, a particular stack, or all of the resources for a specific provider. When you call the aspect, CDKTF applies its methods to all of the the constructs that fall within the specified scope.

The TypeScript example below defines an aspect to add tags to resources.

import { Aspects, IAspect } from "cdktf";

export class TagsAddingAspect implements IAspect {
  constructor(private tagsToAdd: Record<string, string>) {}

  // This method is called on every Construct within the specified scope (resources, data sources, etc.).
  visit(node: IConstruct) {
    if (node.hasOwnProperty("tags")) {
      const currentTags = node.tags || {};
      node.tags = { ...currentTags, ...this.tagsToAdd };
    }
  }
}

// Add tags to every resource defined within `myStack`.
Aspects.of(myStack).add(new TagsAddingAspect({ createdBy: "cdktf" }));

You can also use aspects for validation. The TypeScript example below defines an aspect that checks whether all S3 Buckets start with the correct prefix.

import { Aspects, IAspect, Annotations } from "cdktf";
import { S3 } from "./.gen/providers/aws";

export class ValidateS3IsPrefixed implements IAspect {
  constructor(private prefix: string) {}

  // This method is called on every Construct within the defined scope (resource, data sources, etc.).
  visit(node: IConstruct) {
    if (node instanceof S3.S3Bucket) {
      if (node.bucket && !node.bucket.startsWith(this.prefix)) {
        // You can include `addInfo`, `addWarning`, and `addError`.
        // CDKTF prints these messages when the user runs `synth`, `plan`, or `deploy`.
        Annotations.of(node).addError(
          `Each S3 Bucket name needs to start with ${this.prefix}`
        );
      }
    }
  }
}

// Check the prefix for every resource within `myStack`.
Aspects.of(myStack).add(new ValidateS3IsPrefixed("myPrefix"));