Terraform with TypeScript

Francesco Vitullo
ITNEXT
Published in
4 min readNov 3, 2020

--

Photo by Mike Kenneally on Unsplash

Infrastructure as Code is slowly rising and for good.

Nowadays, addressing Infrastructure orchestration with the popular manual approach is not acceptable any longer. While the shift to the Cloud brings an extensive toolbox, complexity exponentially increases and a management solution should be put in place.

Back in the days, Operations and Infrastructure management has always been a hidden area where the domain was completely scoped to few experts or teams.

Could this “challenge” be addressed from the Development point of view?

Of course. And there are a lot of solutions which face it. Terraform is one of them.

Why not including Developers in the scope?

Here we come.

Recently Hashicorp introduced new languages for CDK (Cloud Development Kit — which is still under development) supporting Typescript, Python, and Java. Amazing!

In this article, I would like to focus on how to combine Terraform with Typescript and push Infrastructure as Code to the next level.

CDKTF

CDKTF provided by Hashicorp makes it simple to create a Typescript environment with Terraform utilities and its related implemented providers.

At the time of writing, there are lots of official providers and community providers, both usable in the Typescript ecosystem.

Getting started with CDKTF is pretty easy and it requires Terraform (> 0.12) and NPM/YARN:

npm install --global cdktf-cli@next

or with brew:

brew install cdktf

Create and Deploy resources with Terraform

Thanks to the CLI, it is possible to create a basic boilerplate:

mkdir typescript-k8s && cd $_cdktf init --template=typescript --local

The cdktf init command is generating the necessary files to get started with:

  • cdktf.json: containing the CDKTF configuration stating explicitly the providers to use as well (they can be both official or community provided ones — last ones need to be manually installed though).
  • typescript related files: package.json, main.ts, etc…

What we could do for demonstration, it’s a simple deployment of Kubernetes resources into an already created cluster (e.g. local Kind instance). Following code is re-using an official example stated at on the official CDK Github Page or if you want to learn more, head toward the official page tutorials.

First thing, let’s add Kubernetes provider to our cdktf.json as our main provider (and replace the one coming with the boilerplate):

The beauty of CDKTF is that we can download missing providers (listed in the official providers' list) and automatically generate typings/implementation with the following command (which works also as initial bootstraping):

cdktf get

A .gen folder is created and it contains all the typings/implementation related to the desired providers.

.gen folder with created typings and Typescript files

Now it’s time to edit the “main.ts” which includes a minimalistic approach to help at the beginning:

This sample code does nothing, it is just instantiating MyStack (which extends TerraformStack) and calls the “synth” method, doing the init-plan-apply under the hood.

For instance, we can deploy the Nginx controller on our cluster (namespace, deployment, and related service):

The code embedded in the main.ts file, it creates 3 things:

  • The Namespace which will hold our resources
  • The Deployment with the specified Nginx Image
  • The Service to expose Nginx

If we want to deploy these resources, let’s invoke the following command:

cdktf deploy

And below you can see the related output:

If we run basic commands with kubectl, such as:

+ kubectl get namespaces
NAME STATUS AGE
default Active 3d5h
kube-node-lease Active 3d5h
kube-public Active 3d5h
kube-system Active 3d5h
local-path-storage Active 3d5h
tf-cdk-nginx Active 1m
+ kubectl get deployments -n tf-cdk-nginx
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-example-tf 2/2 2 2 1m

Everything has been created correctly!

We could even destroy the created resources if we wish, by only invoking the following command:

cdktf destroy

Or, if we are getting crazy, we can exactly deploy resources back executing the deploy command again. Unbelievable!!!

Thanks to these tools provided by HashiCorp, a new world opens up!

Introducing (finally) Unit Testing

What does make IaC even stronger? Yes, Unit Tests!

Now, with a Typescript environment, we could wire in our preferred testing tools.

In this article (and for my personal choice), I’d recommend Jest!

Let’s start installing the dependencies and setup the testing environment:

npm install --save-dev jest babel-jest @babel/core @babel/preset-env @babel/preset-typescript @types/jest

And create the babel.config.js:

To invoke the tests, we can actually replace the existing “test” script in the package.json:

{
"name": "typescript-k8s",
...
"scripts": {
...
"test": "jest",
...
},
...
}

After this, let’s add a simple test for our Cluster Stack and implement some small refactorings to the actual code we wrote:

And if “npm run test” is executed, the output is the following:

Disclaimer: this is for demonstration only and it might test configuration only (which is not a very cool practice). But, this shows how easy it is now to actually write some tests for the logic which prepares and bakes the desired cloud resources.

If you want to play with it, you can find this example codebase on Github.

These new tools, introduced lately, are opening new horizons to the IaaC professionals and passionate.

Managing Infrastructure has been a painful point in the past and combining Cloud to the Dev world is actually improving the overall experience.

I hope you learned something new with this article and feel free to share any feedback.

Cheers!!

--

--

Senior Front End Engineer @IBM — thoughts are my own / I’m a passionate developer and kitesurfer