Skip to main content

Generating Kubernetes Manifests

In Anemos, you can define all your Kubernetes manifests in a single file using JavaScript. You can import other local and remote files, use variables, and even create functions to generate complex manifests. You can also use NPM packages and a more structured approach to define your manifests, but that's not the focus of this tutorial.

Let's start with a simple index.js file that will generate a Kubernetes manifests for us and then we will inspect how it works.

index.js
const anemos = require("@ohayocorp/anemos");

const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

builder.addDocument(
`pod.yaml`,
`
apiVersion: v1
kind: Pod
metadata:
name: example-app
namespace: default
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
`);

builder.build();

Explaining the Code

index.js
const anemos = require("@ohayocorp/anemos");

This line imports the Anemos library. Although imported like any other JavaScript library, the core library is implemented in native code, eliminating the need for dependencies.

index.js
const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

Here, we instantiate the anemos.Builder class. The Builder takes information about the target Kubernetes cluster and the deployment environment (e.g., development, test, production). This context allows Anemos packages to tailor the generated manifests to the specific environment. For instance, packages can generate OpenShift Routes instead of Ingress definitions if the distribution is OpenShift, or adjust replica counts based on the environment type.

index.js
builder.addDocument(
`pod.yaml`,
`
apiVersion: v1
kind: Pod
metadata:
name: example-app
namespace: default
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
`);

This code snippet defines a Pod manifest using a YAML string. Documents that are added to the Builder are output as Kubernetes manifests. We will see how to customize these manifests below.

index.js
builder.build();

This line invokes the build method, which orchestrates the manifest generation process.

Generating the Manifests

To generate the Kubernetes manifests, run the following command in your terminal:

anemos build index.js

This command will execute the index.js file, and Anemos will generate the Kubernetes manifests based on the defined documents. The output will be written into the output directory by default. Our pod definition will be the same as the one defined in the index.js file, since we did not customize it further.

pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: example-app
namespace: default
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80

Customizing the Manifests

It is possible to customize the generated manifests in two ways: by using variables when defining the manifests or by modifying the document during the modify step.

Using Variables

You can use variables to define dynamic values in your manifests. For example, you can define variables for name, namespace, and image and use it in your Pod definition. JavaScript template literals, text enclosed in backticks (``), allow you to embed expressions within strings (${expression}), making it easy to use variables in your manifests.

pod.yaml
const anemos = require("@ohayocorp/anemos");

const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

const name = "example-app";
const namespace = "default";
const image = "nginx";

builder.addDocument(
`pod.yaml`,
`
apiVersion: v1
kind: Pod
metadata:
name: ${name}
namespace: ${namespace}
spec:
containers:
- name: app
image: ${image}
ports:
- containerPort: 80
`);

builder.build();

Modifying the Document

You can also modify the document during the modify step. This allows you to change the manifest after it has been generated but before it is output. You can use the onModify method of the Builder to add a callback that will be executed during the modify step.

The callback receives a context object that you can use to access the generated documents. Here we get the Pod document we have defined earlier and add a label to it.

const anemos = require("@ohayocorp/anemos");

const builder = new anemos.Builder("1.31", anemos.KubernetesDistribution.Minikube, anemos.EnvironmentType.Development);

builder.addDocument(
`pod.yaml`,
`
apiVersion: v1
kind: Pod
metadata:
name: example-app
namespace: default
spec:
containers:
- name: app
image: nginx
ports:
- containerPort: 80
`);

builder.onModify((context) => {
// Add a label to the Pod.
context
.getDocument("pod.yaml")
.setLabel("app", "example-app");
});

builder.build();