DEV Community

Cover image for Getting started with CDK for Terraform
Abhishek Anand Amralkar
Abhishek Anand Amralkar

Posted on • Updated on

Getting started with CDK for Terraform

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
Enter fullscreen mode Exit fullscreen mode

To get up to date with the cutting edge development version

npm install --global cdktf-cli@next
Enter fullscreen mode Exit fullscreen mode

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")
Enter fullscreen mode Exit fullscreen mode

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 $_
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

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

Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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

cdktf get
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)

Enter fullscreen mode Exit fullscreen mode

Add the dependencies in Pipenv file in our case

[packages]
constructs="3.0.4"
cdktf="0.0.12"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Now compile and generate Terraform configuration

cdktf synth
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

OR

We can deploy

cdktf deploy
Enter fullscreen mode Exit fullscreen mode

Lets see a demo

asciicast

Top comments (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

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 }