How to Combine Terraform with Typescript

How to Combine Terraform with Typescript

Learn how to combine Terraform with Typescript and push Infrastructure as Code to the next level. Terraform is an open-source infrastructure as code software tool created by HashiCorp. Hashicorp introduced new languages for CDK (Cloud Development Kit — which is still under development) supporting Typescript, Python, and Java.

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 [email protected]

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.

Image for post

.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:

import { Construct } from 'constructs';
import { App, TerraformStack } from 'cdktf';

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

    // define resources here

  }
}

const app = new App();
new MyStack(app, 'typescript-k8s');
app.synth();

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):

import { Construct } from 'constructs';
import { App, TerraformStack } from 'cdktf';
import { Deployment,
         KubernetesProvider,
         Namespace,
         Service
} from "./.gen/providers/kubernetes";

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

    new KubernetesProvider(this, 'kind', {});

    this.gatherResources();
  }
  gatherResources(this: MyStack) {
    const app = 'nginx-example-tf'
    const namespace = 'tf-cdk-nginx'
    new Namespace(this, 'tf-cdk-example', {
      metadata: [{
        name: namespace
      }]
    });

    new Deployment(this, 'nginx-deployment', {
      metadata: [{
        name: app,
        namespace,
        labels: {
          app
        }
      }],
      spec: [{
        replicas: 2,
        selector: [{
          matchLabels: {
            app
          }
        }],
        template: [{
          metadata: [{
            labels: {
              app
            }
          }],
          spec: [{
            container: [{
              image: 'nginx:1.7.8',
              name: 'nginx',
              port: [{
                containerPort: 80
              }],
              resources: [{
                limits: [{
                  cpu: '0.5',
                  memory: '512Mi'
                }],
                requests: [{
                  cpu: '250m',
                  memory: '50Mi'
                }]
              }]
            }]
          }]
        }]
      }]
    });

    new Service(this, 'nginx-service', {
      metadata: [{
        name: app,
        namespace,
      }],
      spec: [{
        selector: {
          app
        },
        port: [{
          nodePort: 30201,
          port: 80,
          targetPort: '80'
        }],
        type: 'NodePort'
      }]
    });
  }
}

const app = new App();
new MyStack(app, 'typescript-k8s');
app.synth();

typescript javascript terraform programming developer

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

What is TypeScript? Why TypeScript? and Why Not TypeScript?

TypeScript extends JavaScript by adding Types. There are many great reasons to switch to TypeScript. Especially if your team uses JavaScript. There are some reasons to not use TypeScript as there are with any language or framework.

Learning JavaScript: Development Environments for JavaScript Programming

One of the nice things about learning JavaScript these days is that there is a plethora of choices for writing and running JavaScript code. In this article, I’m going to describe a few of these environments and show you the environment I’ll be using in this series of articles.

TypeScript vs. JavaScript Comparison – Pros, Cons, Trends

We'll look at the pros, cons and trends of TypeScript compared to JavaScript. What has driven so many developers away from JavaScript and into TypeScript? Let’s make a side-by-side TypeScript vs JavaScript comparison.

Write Safer JavaScript Applications With TypeScript!

You'll learn how TypeScript can help you build safer and more resilient JavaScript applications. Expect some demos, some code and a lot of fun!

Create TypeScript Declarations from JavaScript and JSDoc

TypeScript allows you to generate type declaration files directly from JavaScript files and will use information in JSDoc comments to assign the appropriate types. Today’s smart code editors, like Visual Studio Code, are able to read type information from JSDoc and provide Intellisense options as you code.