CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-cdktf

Cloud Development Kit for Terraform - programmatic infrastructure as code using familiar programming languages

Overview
Eval results
Files

provisioners.mddocs/

Provisioners

Resource provisioning capabilities for executing scripts, transferring files, and performing custom actions during resource lifecycle events.

Capabilities

Provisioner Types

Terraform supports three main provisioner types for executing actions during resource creation and destruction.

/**
 * File provisioner for transferring files to resources
 */
interface FileProvisioner {
  readonly type: "file";
  readonly source: string;
  readonly destination: string;
  readonly connection?: SSHProvisionerConnection | WinrmProvisionerConnection;
}

/**
 * Local execution provisioner for running commands locally
 */
interface LocalExecProvisioner {
  readonly type: "local-exec";
  readonly command: string;
  readonly workingDir?: string;
  readonly interpreter?: string[];
  readonly environment?: {[key: string]: string};
  readonly when?: "create" | "destroy";
}

/**
 * Remote execution provisioner for running commands on resources
 */
interface RemoteExecProvisioner {
  readonly type: "remote-exec";
  readonly inline?: string[];
  readonly script?: string;
  readonly scripts?: string[];
  readonly connection: SSHProvisionerConnection | WinrmProvisionerConnection;
  readonly when?: "create" | "destroy";
}

Usage Examples:

import { AwsInstance } from "cdktf";

// Instance with multiple provisioners
new AwsInstance(this, "web-server", {
  ami: "ami-12345678",
  instanceType: "t2.micro",
  keyName: "my-key",

  provisioners: [
    // Upload configuration file
    {
      type: "file",
      source: "./config/app.conf",
      destination: "/tmp/app.conf",
      connection: {
        type: "ssh",
        user: "ubuntu",
        privateKey: "${file(var.private_key_path)}"
      }
    },

    // Run setup script locally
    {
      type: "local-exec",
      command: "echo 'Instance ${self.id} is being created'"
    },

    // Configure the server remotely
    {
      type: "remote-exec",
      inline: [
        "sudo apt-get update",
        "sudo apt-get install -y nginx",
        "sudo cp /tmp/app.conf /etc/nginx/sites-available/",
        "sudo systemctl enable nginx",
        "sudo systemctl start nginx"
      ],
      connection: {
        type: "ssh",
        user: "ubuntu",
        privateKey: "${file(var.private_key_path)}",
        host: "${self.public_ip}"
      }
    }
  ]
});

Connection Configuration

Provisioners require connection configurations to access remote resources.

/**
 * SSH connection configuration
 */
interface SSHProvisionerConnection {
  readonly type: "ssh";
  readonly user: string;
  readonly password?: string;
  readonly privateKey?: string;
  readonly certificate?: string;
  readonly host?: string;
  readonly port?: number;
  readonly timeout?: string;
  readonly scriptPath?: string;
  readonly bastionHost?: string;
  readonly bastionHostKey?: string;
  readonly bastionPort?: number;
  readonly bastionUser?: string;
  readonly bastionPassword?: string;
  readonly bastionPrivateKey?: string;
  readonly bastionCertificate?: string;
  readonly agentIdentity?: string;
  readonly agent?: boolean;
  readonly hostKey?: string;
}

/**
 * Windows Remote Management connection configuration
 */
interface WinrmProvisionerConnection {
  readonly type: "winrm";
  readonly user: string;
  readonly password: string;
  readonly host?: string;
  readonly port?: number;
  readonly timeout?: string;
  readonly https?: boolean;
  readonly insecure?: boolean;
  readonly useNtlm?: boolean;
  readonly cacert?: string;
  readonly cert?: string;
  readonly key?: string;
}

Usage Examples:

// SSH with private key
const sshConnection: SSHProvisionerConnection = {
  type: "ssh",
  user: "ubuntu",
  privateKey: "${file(var.private_key_path)}",
  host: "${self.public_ip}",
  timeout: "2m"
};

// SSH with bastion host
const bastionConnection: SSHProvisionerConnection = {
  type: "ssh",
  user: "ubuntu",
  privateKey: "${file(var.private_key_path)}",
  host: "${self.private_ip}",
  bastionHost: "bastion.example.com",
  bastionUser: "ubuntu",
  bastionPrivateKey: "${file(var.bastion_key_path)}"
};

// WinRM connection
const winrmConnection: WinrmProvisionerConnection = {
  type: "winrm",
  user: "Administrator",
  password: "${var.admin_password}",
  host: "${self.public_ip}",
  port: 5985,
  timeout: "10m"
};

TerraformSelf Class

Utility class for self-references within provisioners and resources.

/**
 * Self-reference utilities for provisioners
 */
class TerraformSelf {
  /**
   * Get string attribute from the current resource
   * @param key - Attribute name
   * @returns String value
   */
  static getString(key: string): string;

  /**
   * Get number attribute from the current resource
   * @param key - Attribute name
   * @returns Number value
   */
  static getNumber(key: string): number;

  /**
   * Get any attribute from the current resource
   * @param key - Attribute name
   * @returns Any value
   */
  static getAny(key: string): any;
}

Usage Examples:

import { TerraformSelf } from "cdktf";

new AwsInstance(this, "web", {
  ami: "ami-12345678",
  instanceType: "t2.micro",

  provisioners: [
    {
      type: "local-exec",
      command: `echo 'Instance IP: ${TerraformSelf.getString("public_ip")}'`
    },
    {
      type: "remote-exec",
      inline: [
        `echo 'My ID is ${TerraformSelf.getString("id")}'`,
        `echo 'My private IP is ${TerraformSelf.getString("private_ip")}'`
      ],
      connection: {
        type: "ssh",
        user: "ubuntu",
        privateKey: "${file(var.key_path)}",
        host: TerraformSelf.getString("public_ip")
      }
    }
  ]
});

Advanced Provisioner Patterns

Conditional Provisioning

import { Fn } from "cdktf";

const enableMonitoring = new TerraformVariable(this, "enable_monitoring", {
  type: "bool",
  default: false
});

new AwsInstance(this, "app-server", {
  ami: "ami-12345678",
  instanceType: "t2.micro",

  provisioners: [
    // Always run basic setup
    {
      type: "remote-exec",
      inline: [
        "sudo apt-get update",
        "sudo apt-get install -y nginx"
      ],
      connection: sshConnection
    },

    // Conditionally install monitoring
    ...(enableMonitoring.booleanValue ? [{
      type: "remote-exec",
      inline: [
        "curl -sSL https://agent.datadoghq.com/install.sh | bash",
        "sudo systemctl enable datadog-agent",
        "sudo systemctl start datadog-agent"
      ],
      connection: sshConnection
    }] : [])
  ]
});

Multi-Stage Provisioning

new AwsInstance(this, "database-server", {
  ami: "ami-12345678",
  instanceType: "t3.large",

  provisioners: [
    // Stage 1: Upload files
    {
      type: "file",
      source: "./scripts/setup-database.sh",
      destination: "/tmp/setup-database.sh",
      connection: sshConnection
    },
    {
      type: "file",
      source: "./config/database.conf",
      destination: "/tmp/database.conf",
      connection: sshConnection
    },

    // Stage 2: Setup system
    {
      type: "remote-exec",
      inline: [
        "chmod +x /tmp/setup-database.sh",
        "sudo /tmp/setup-database.sh"
      ],
      connection: sshConnection
    },

    // Stage 3: Configure application
    {
      type: "remote-exec",
      script: "./scripts/configure-app.sh",
      connection: sshConnection
    },

    // Stage 4: Local notification
    {
      type: "local-exec",
      command: "curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Database server ${self.id} is ready\"}' ${var.slack_webhook_url}"
    }
  ]
});

Destroy-Time Provisioning

new AwsInstance(this, "app-server", {
  ami: "ami-12345678",
  instanceType: "t2.micro",

  provisioners: [
    // Creation-time provisioner
    {
      type: "remote-exec",
      inline: [
        "sudo systemctl start myapp"
      ],
      connection: sshConnection
    },

    // Destroy-time provisioner for cleanup
    {
      type: "remote-exec",
      when: "destroy",
      inline: [
        "sudo systemctl stop myapp",
        "sudo rm -rf /var/lib/myapp/data",
        "sudo userdel myapp"
      ],
      connection: sshConnection
    },

    // Local cleanup
    {
      type: "local-exec",
      when: "destroy",
      command: "rm -f ./generated-config-${self.id}.json"
    }
  ]
});

Error Handling and Retries

new AwsInstance(this, "web-server", {
  ami: "ami-12345678",
  instanceType: "t2.micro",

  provisioners: [
    {
      type: "remote-exec",
      inline: [
        // Wait for cloud-init to complete
        "while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 2; done",

        // Retry package installation
        "for i in {1..5}; do sudo apt-get update && break || sleep 5; done",
        "for i in {1..5}; do sudo apt-get install -y nginx && break || sleep 5; done",

        // Verify installation
        "systemctl is-active nginx || exit 1"
      ],
      connection: {
        type: "ssh",
        user: "ubuntu",
        privateKey: "${file(var.private_key_path)}",
        host: "${self.public_ip}",
        timeout: "5m"
      }
    }
  ]
});

Install with Tessl CLI

npx tessl i tessl/npm-cdktf

docs

annotations-aspects.md

backend-configuration.md

core-infrastructure.md

index.md

iterators-dynamic.md

providers-modules.md

provisioners.md

resources-data-sources.md

terraform-functions.md

testing.md

tokens-expressions.md

variables-outputs.md

tile.json