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):
A .gen folder is created and it contains all the typings/implementation related to the desired providers.
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:
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:
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!
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:
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.