DEV Community

loading...
Cover image for Getting started with CDK for Terraform

Getting started with CDK for Terraform

Abhishek Anand Amralkar
Abhishek leads the Cloud Infrastructure / DevSecOps team where he designs the next generation of Cloud Infrastructure in a cost-effective and reliable manner without comprising
Updated on ・3 min read

CDK for Terraform

Hashicorp recently announced cdktf Cloud Development Kit for Terraform which currently supports Python3 and Typescript.

With cdktf we can write Terraform code in Python3 or Typescript instead of HCL which is the default language for Terraform.

Well, I thought of giving it a try and check out how it works out with Python3.

Install cdktf

To install the most recent stable release of cdktf, use npm.

npm install --global cdktf-cli

To get up to date with the cutting edge development version

npm install --global cdktf-cli@next

Once the installation is done you can check the cdktf installation via cdktf

Commands:
  cdktf deploy [OPTIONS]   Deploy the given stack
  cdktf destroy [OPTIONS]  Destroy the given stack
  cdktf diff [OPTIONS]     Perform a diff (terraform plan) for the given stack
  cdktf get [OPTIONS]      Generate CDK Constructs for Terraform providers and modules.
  cdktf init [OPTIONS]     Create a new cdktf project from a template.
  cdktf login              Retrieves an API token to connect to Terraform Cloud.
  cdktf synth [OPTIONS]    Synthesizes Terraform code for the given app in a directory.                                                                                                                                  [aliases: synthesize]

Options:
  --version          Show version number                                                                                                                                                                                             [boolean]
  --disable-logging  Dont write log files. Supported using the env CDKTF_DISABLE_LOGGING.                                                                                                                            [boolean] [default: true]
  --log-level        Which log level should be written. Only supported via setting the env CDKTF_LOG_LEVEL                                                                                                                            [string]
  -h, --help         Show help                                                                                                                                                                                                       [boolean]

Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")

Okay now, let's do some real work we will create a project where we will deploy Nginx on top of Docker using cdktf and Python3. For the Typescript example please check terraform-cdk.

Create a directory by any name in our case we will use below the python-docker

mkdir python-docker && cd $_

Initialize the project with the init command. We will use the --local flag so that the infrastructure state will be stored locally.

cdktf init --template=python --local

Make sure you pass python and not python3 else you will get below error

Invalid values:
  Argument: template, Given: "python3", Choices: "python", "typescript"

cdktf will generate the template for us, in our case, we will be using docker to get Nginx running so make sure to change the provider in cdktf.json

{
  "language": "python",
  "app": "pipenv run ./main.py",
  "terraformProviders": ["docker"],
  "codeMakerOutput": "imports"
}

Run the get command to download the dependencies for using Docker with Python.

cdktf get

Now add your code in main.py file for building Docker

First import the Docker provider, this means the imports is a local directory created by the above command

from imports.docker import Image, Container

and later add below code

docker_image = Image(self, 'nginx-latest', name='nginx:latest', keep_locally=False)

Container(self, 'nginx-cdktf', name='nginx-python-cdktf',
                  image=docker_image.name, ports=[
                      {
                          'internal': 80,
                          'external': 8000
                      }], privileged=False)

Add the dependencies in Pipenv file in our case

[packages]
constructs="3.0.4"
cdktf="0.0.12"

Pipenv will throw an error if you don't define the version for the packages

Run pipenv to get all the dependencies to install the pipenv check the official website pipenv

pipenv install

Now compile and generate Terraform configuration

cdktf synth

The above command will create a folder called cdktf.out that contains all Terraform JSON configuration that was generated.

We can run the regular Terraform commands

cd cdktf.out
terraform init
terraform plan
terraform apply

OR

We can deploy

cdktf deploy

Lets see a demo

asciicast

Discussion (3)

Collapse
skorfmann profile image
Sebastian Korfmann

Thanks for writing this!

Add the dependencies in Pipenv file in our case
[packages]
constructs="3.0.4"
cdktf="0.0.12"
Pipenv will throw an error if you don't define the version for the packages

This sounds like something which could be improved as part of the Python template, what do you think? If so, it'd fantastic if you could file a bug cdk.tf/bug

Collapse
abhishekamralkar profile image
Abhishek Anand Amralkar Author

Thanks! I will file a bug.

Collapse
khushil profile image
Khushil Dep

Oddly I get the following when running the cdktf command?

Adding cdktf~=0.1.0 to Pipfile's [packages]…
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/pipenv/project.py", line 527, in write_toml
formatted_data = contoml.dumps(data).rstrip()
File "/usr/lib/python3/dist-packages/pipenv/patched/contoml/init.py", line 36, in dumps
raise RuntimeError("Can only dump a TOMLFile instance loaded by load() or loads()")
RuntimeError: Can only dump a TOMLFile instance loaded by load() or loads()

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/usr/bin/pipenv", line 11, in
load_entry_point('pipenv==11.9.0', 'console_scripts', 'pipenv')()
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 722, in call
return self.main(*args, **kwargs)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3/dist-packages/pipenv/cli.py", line 349, in install
core.do_install(
File "/usr/lib/python3/dist-packages/pipenv/core.py", line 1979, in do_install
project.add_package_to_pipfile(package_name, dev)
File "/usr/lib/python3/dist-packages/pipenv/project.py", line 610, in add_package_to_pipfile
self.write_toml(p)
File "/usr/lib/python3/dist-packages/pipenv/project.py", line 530, in write_toml
for package in data[section]:
KeyError: 'dev-packages'
cdktf init [OPTIONS]

Create a new cdktf project from a template.

Options:
--version Show version number [boolean]
--disable-logging Dont write log files. Supported using the env CDKTF_DISABLE_LOGGING. [boolean] [default: true]
--disable-plugin-cache-env Dont set TF_PLUGIN_CACHE_DIR automatically. This is useful when the plugin cache is configured differently. Supported using the env CDKTF_DISABLE_PLUGIN_CACHE_ENV. [boolean] [default: false]
--log-level Which log level should be written. Only supported via setting the env CDKTF_LOG_LEVEL [string]
--template The template name to be used to create a new project. [string] [choices: "csharp", "java", "python", "python-pip", "typescript", "typescript-minimal"]
--project-name The name of the project. [string]
--project-description The description of the project. [string]
--dist Install dependencies from a "dist" directory (for development) [string]
--local Use local state storage for generated Terraform. [boolean] [default: false]
--cdktf-version The cdktf version to use while creating a new project. [string] [default: "0.1.0"]
-h, --help Show help [boolean]

{ Error: Command failed: pipenv install cdktf~=0.1.0
at checkExecSyncError (child_process.js:629:11)
at execSync (child_process.js:666:13)
at Object.exports.post.options as post
at executePostHook (/home/khushil/.npm-global/lib/node_modules/cdktf-cli/node_modules/sscaff/lib/sscaff.js:61:37)
at Object.sscaff (/home/khushil/.npm-global/lib/node_modules/cdktf-cli/node_modules/sscaff/lib/sscaff.js:28:15)
status: 1,
signal: null,
output: [ null, null, null ],
pid: 13295,
stdout: null,
stderr: null }