• Overview
    • Enforce Policy as Code
    • Infrastructure as Code
    • Inject Secrets into Terraform
    • Integrate with Existing Workflows
    • Manage Kubernetes
    • Manage Virtual Machine Images
    • Multi-Cloud Deployment
    • Network Infrastructure Automation
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
  • Registry
  • Tutorials
    • About the Docs
    • Intro to Terraform
    • Configuration Language
    • Terraform CLI
    • Terraform Cloud
    • Terraform Enterprise
    • Provider Use
    • Plugin Development
    • Registry Publishing
    • Integration Program
    • Terraform Tools
    • CDK for Terraform
    • Glossary
  • Community
GitHubTerraform Cloud
Download

    CDK for Terraform

  • Overview
  • Get Started
    • Architecture
    • HCL Interoperability
    • Constructs
    • Providers and Resources
    • Modules
    • Data Sources
    • Variables and Outputs
    • Functions
    • Remote Backends
    • Aspects
    • Assets
    • Tokens
    • Stacks
  • Examples and Guides
    • Project Setup
    • Configuration File
    • Best Practices
    • Environment Variables
    • Remote Templates
    • AWS Adapter [preview]
    • Unit Tests
    • Debugging
    • CLI Configuration
    • Commands
    • Overview
    • Upgrading to Version 0.6
    • Upgrading to Version 0.7
    • Upgrading to Version 0.9
    • Upgrading to Version 0.10
    • Upgrading to Version 0.11
  • Community
  • Telemetry
  • Other Docs

  • Intro to Terraform
  • Configuration Language
  • Terraform CLI
  • Terraform Cloud
  • Terraform Enterprise
  • Provider Use
  • Plugin Development
  • Registry Publishing
  • Integration Program
  • Terraform Tools
  • CDK for Terraform
  • Glossary
Type '/' to Search

»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 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 { IConstruct } from "constructs";
import { Aspects, IAspect } from "cdktf";

// Not all constructs are taggable, so we need to filter it
type TaggableConstruct = IConstruct & {
  tags?: { [key: string]: string };
};
function isTaggableConstruct(x: IConstruct): x is TaggableConstruct {
  return "tags" in x;
}

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 (isTaggableConstruct(node)) {
      const currentTags = node.tags || {};
      node.tags = Fn.tomap(Fn.merge([currentTags, this.tagsToAdd]));
    }
  }
}

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

// Not all constructs are taggable, so we need to filter it
type TaggableConstruct = IConstruct & {
  tags?: { [key: string]: string };
};
function isTaggableConstruct(x: IConstruct): x is TaggableConstruct {
  return "tags" in x;
}

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 (isTaggableConstruct(node)) {
      const currentTags = node.tags || {};
      node.tags = Fn.tomap(Fn.merge([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 { IConstruct } from "constructs";
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"));
import { IConstruct } from "constructs";
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"));
github logoEdit this page
  • Overview
  • Docs
  • Extend
  • Privacy
  • Security
  • Press Kit
  • Consent Manager