Skip to main content

Adding New Services and Routes

Overview

In this tutorial, we'll show you how to take a Klotho-annotated Express.js application and expand on it by adding a new service and route. When Klotho is invoked on the annotated code, it will identify the routing changes and update your topology like we see here: image showcasing topology transition from 2 to 3 exec units In this example, we can see that Klotho understood that we defined a new function, and it needed to configure a new route in the existing API Gateway. The infrastructure-as-code (IaC) is updated to reflect that, and the changes will be applied on the next deploy.

Why?

Klotho lets you quickly and seamlessly add new endpoints to existing services.

Getting Started

We're going to start by cloning the ts-serverless-quickstart app which has already been Klotho-annotated. This sample app showcases multiple execution units which will be deployed as Lambdas and routed through an API Gateway. We will then add a new execution unit to show how Klotho handles updating the routing for your gateway.

Prerequisites

Repository

Clone our sample apps git repo and install the npm packages for the ts-serverless-quickstart app.

git clone https://github.com/klothoplatform/sample-apps.git
cd sample-apps/ts-serverless-quickstart
npm install

App Overview

The ts-serverless-quickstart application utilizes the following annotations

/* @klotho::expose {
* id = "app"
* target = "public"
* }
*/
app.listen(3000, async () => {
console.log(`App listening locally`)
})
...

Klotho compile the application

Let's start by compiling our TypeScript application into JavaScript.

npx tsc

Next, log in to Klotho. This will allow us to support you if you run into any issues, and give you the opportunity to shape the product in this early development stage.

klotho --login # if you haven't already

Then, compile the the app with Klotho.

klotho . --app ts-sq --provider aws

The output will be similar to:

██╗  ██╗██╗      ██████╗ ████████╗██╗  ██╗ ██████╗
██║ ██╔╝██║ ██╔═══██╗╚══██╔══╝██║ ██║██╔═══██╗
█████╔╝ ██║ ██║ ██║ ██║ ███████║██║ ██║
██╔═██╗ ██║ ██║ ██║ ██║ ██╔══██║██║ ██║
██║ ██╗███████╗╚██████╔╝ ██║ ██║ ██║╚██████╔╝
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝

Adding resource input_file_dependencies:
Adding resource exec_unit:cats
Adding resource exec_unit:dogs
index.js:26:0: Found 1 route(s) for middleware 'router'
index.js:27:0: Found 1 route(s) for middleware 'cats'
Adding resource gateway:app
index.js:26:0: Found 1 route(s) for middleware 'router'
index.js:28:0: Found 1 route(s) for middleware 'dogs'
Not adding duplicate route / for dogs. Exists in cats
Adding resource topology:ts-sq
Adding resource infra_as_code:Pulumi (AWS)

In the ./compiled folder, you'll find the IaC for your cloud-native application ready for deployment. You'll also find a file called ts-sq.png, visualizing the topology output of your compiled application:

2 exec unit topology image

At this point, if you'd like to see the initial infrastructure actually deployed, simply follow the Deploying guide.

Adding a new execution unit and route

We have currently have two Lambdas for our Pets service, one for Dogs and one for Cats. Let's expand on that and add Fish.

Open the fish.ts file, which only contains a comment, and copy in the following code snippet to add a basic endpoint GET /v1/fish:

fish.ts
export const router = require("express").Router();

function getFish(event, res) {
res.send("[Goldfish, Betta, Angelfish]");
}

router.get("/v1/fish", getFish);

Since we want Fish to be a separate service handling only Fish related requests, annotate the top of the file with the @klotho::execution_unit annotation

fish.ts
/**
* @klotho::execution_unit {
* id = "fish"
* }
*/

export const router = require("express").Router();

function getFish(event, res) {
res.send("[Goldfish, Betta, Angelfish]");
}

router.get("/v1/fish", getFish);

Now let's update the index.ts file so our application is aware of the new route we created.

index.ts
import * as cats from './pets/cats';
import * as dogs from './pets/dogs';
import * as fish from './pets/fish'; // Import the fish.ts file
...

app.use(cats.router)
app.use(dogs.router)
app.use(fish.router) // Include the fish router in the app
...

Recompile the application

Run the following:

npx tsc && klotho . --app ts-sq --provider aws

In the ./compiled folder, you'll find the updated IaC for your cloud-native application ready for deployment. You'll also find the topology file ts-sq.png has been updated to reflect the changes:

3 exec unit topology image

Just like that, on your next deploy, your API Gateway will be configured with the new GET /v1/fish route. Klotho has handeled updating the API Gateway resources, methods, integrations and more. 3 exec unit console image