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:
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
- Klotho CLI installed
curl
- Node.js 16.x+ (& NPM)
- TypeScript
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
- index.ts
- dogs.ts
- cats.ts
- fish.ts
/* @klotho::expose {
* id = "app"
* target = "public"
* }
*/
app.listen(3000, async () => {
console.log(`App listening locally`)
})
...
/**
* @klotho::execution_unit {
* id = "dogs"
* }
*/
export const router = require('express').Router();
...
/**
* @klotho::execution_unit {
* id = "cats"
* }
*/
export const router = require('express').Router();
...
// Empty, we'll fill this in later
...
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:
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
:
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
/**
* @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.
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:
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.