Terraform CDK

Learn how to use the Doppler Terraform Provider with Terraform CDK.

This guide will show you how to get the Doppler Terraform Provider working with Terraform CDK.

Prerequisites

  • The Terraform CLI (1.1+).
  • Node.js and npm v16+.
  • A current version of Typescript, Python, Go, C#, or Java (this guide will be showing Typescript examples, but examples for other languages are available in Terraform's CDKTF tutorial).

📘

This guide follows the basic outline from Terraform's CDKTF tutorial. If something goes wrong or you need more details, please try checking out their full tutorial!

Install CDKTF

You can install the CDKTF CLI using npm on most operating systems. It's also available via Homebrew on MacOS systems.

npm install --global cdktf-cli@latest
brew install cdktf

Create a new project

Create a new directory for the test project and then switch to that directory:

mkdir doppler-terraform-cdk
cd doppler-terraform-cdk

Now initialize that project using the cdktf CLI tool:

# if you're using another language than Typescript, be sure
# to specify the one you're using here.
cdktf init --template=typescript --local

Finally, add the Doppler provider:

cdktf provider add dopplerhq/doppler

We don't currently have a pre-built provider, so the CLI will generate one based on our Terraform provider. You should see output similar to this:

Pre-built provider does not exist for the given constraints.
Adding local provider registry.terraform.io/dopplerhq/doppler with version constraint undefined to cdktf.json
Local providers have been updated. Running cdktf get to update...
⠋ starting...
[2023-01-11T14:04:51.335] [INFO] default - Could not find constraints.json file while filtering: Error: ENOENT: no such file or directory, open '/Users/watsonia
Generated typescript constructs in the output directory: .gen

Tweak Generated Provider

This step isn't strictly required, but will make using the provider easier. Open up the file at .gen/providers/doppler/index.ts and remove the as X from each import line. So, you're changing what looks like this:

// generated by cdktf get
export * as config from './config';
export * as environment from './environment';
export * as project from './project';
export * as secret from './secret';
export * as serviceToken from './service-token';
export * as dataDopplerSecrets from './data-doppler-secrets';
export * as provider from './provider';

to something like this:

// generated by cdktf get
export * from './config';
export * from './environment';
export * from './project';
export * from './secret';
export * from './service-token';
export * from './data-doppler-secrets';
export * from './provider';

Edit the Code

Open the main.ts file in the project and modify it so it looks like this:

import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import * as doppler from "./.gen/providers/doppler";

class MyStack extends TerraformStack {
  constructor(scope: Construct, name: string) {
    super(scope, name);

    new doppler.DopplerProvider(this, "doppler", {
      dopplerToken: `${process.env.DOPPLER_ACCESS_TOKEN}`,
    });

    const testProject = new doppler.Project(this, "terraform-cdk", {
      name: "terraform-cdk",
      description:
        "This is a project for testing terraform-cdk.",
    });

    new doppler.Environment(this, "test", {
      name: "test",
      project: testProject.name,
      slug: "test",
    });

    new doppler.Environment(this, "ci", {
      name: "ci",
      project: testProject.name,
      slug: "ci",
    });

    new doppler.Environment(this, "qa", {
      name: "qa",
      project: testProject.name,
      slug: "qa",
    });
  }
}

const app = new App();
new MyStack(app, "doppler");
app.synth();

Deploy using cdktf

After doing that, try deploying your changes by running the following:

DOPPLER_ACCESS_TOKEN=$(doppler configure get token --plain) cdktf deploy

This will execute the CLI command using the same token your local Doppler CLI uses. Before this does anything, you'll be presented with a terraform plan that shows what will happen with the option to proceed or not:

         Terraform will perform the following actions:
doppler    # doppler_environment.ci (ci) will be created
           + resource "doppler_environment" "ci" {
               + id      = (known after apply)
               + name    = "ci"
               + project = "terraform-cdk"
               + slug    = "ci"
             }

           # doppler_environment.qa (qa) will be created
           + resource "doppler_environment" "qa" {
               + id      = (known after apply)
               + name    = "qa"
               + project = "terraform-cdk"
               + slug    = "qa"
             }

           # doppler_environment.test (test) will be created
           + resource "doppler_environment" "test" {
               + id      = (known after apply)
               + name    = "test"
               + project = "terraform-cdk"
               + slug    = "test"
             }

           # doppler_project.terraform-cdk (terraform-cdk) will be created
           + resource "doppler_project" "terraform-cdk" {
               + description = "This is a project for testing terraform-cdk."
               + id          = (known after apply)
               + name        = "terraform-cdk"
             }

         Plan: 4 to add, 0 to change, 0 to destroy.

         ─────────────────────────────────────────────────────────────────────────────

         Saved the plan to: plan

         To perform exactly these actions, run the following command to apply:
             terraform apply "plan"

Please review the diff output above for doppler
❯ Approve  Applies the changes outlined in the plan.
  Dismiss
  Stop

After applying, you should see the project and associated environments in your Doppler dashboard!

📘

When you deploy this, it creates Terraform state files in the project directory. If you followed the above, then those files will be called terraform.doppler.tfstate and terraform.doppler.tfstate.backup. If you delete the project and want to re-apply from scratch, you would also need to delete these files.