Skip to content

Commit

Permalink
docs.yml
Browse files Browse the repository at this point in the history
  • Loading branch information
docs.yml committed Mar 8, 2024
1 parent f5763ec commit fe87e51
Show file tree
Hide file tree
Showing 37 changed files with 191 additions and 133 deletions.
2 changes: 1 addition & 1 deletion site/content/en/v0.27.0/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Pepr
linkTitle: v0.27.0
cascade:
type: docs
aliases: ["/current/"]
aliases: []
---


Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
---
title: Pepr
linkTitle: v0.25.0
linkTitle: v0.28.0
cascade:
type: docs
aliases: []
aliases: ["/current/"]
---


[![Pepr Documentation](https://img.shields.io/badge/docs--d25ba1)](.)
[![Pepr Documentation](https://img.shields.io/badge/docs--d25ba1)](https://docs.pepr.dev)
[![Npm package license](https://badgen.net/npm/license/pepr)](https://npmjs.com/package/pepr)
[![Known Vulnerabilities](https://snyk.io/test/npm/pepr/badge.svg)](https://snyk.io/advisor/npm-package/pepr)
[![Npm package version](https://badgen.net/npm/v/pepr)](https://npmjs.com/package/pepr)
[![Npm package total downloads](https://badgen.net/npm/dt/pepr)](https://npmjs.com/package/pepr)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/defenseunicorns/pepr/badge)](https://securityscorecards.dev/viewer/?uri=github.com/defenseunicorns/pepr)

#### **_Type safe Kubernetes middleware for humans_**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ It is suggested to lint and format your modules using `npx pepr format`.

## Monitoring

Pepr can monitor Mutations and Validations from Admission Controller the through the `npx pepr monitor [module-uuid]` command. This command will display neatly formatted log showing approved and rejected Validations as well as the Mutations. If `[module-uuid]` is not supplied, then it uses all Pepr admission controller logs as the data source.
Pepr can monitor Mutations and Validations from Admission Controller the through the `npx pepr monitor [module-uuid]` command. This command will display neatly formatted log showing approved and rejected Validations as well as the Mutations. If `[module-uuid]` is not supplied, then it uses all Pepr admission controller logs as the data source. If you are unsure of what modules are currently deployed, issue `npx pepr uuid` to display the modules and their descriptions.

```plaintext
✅ MUTATE pepr-demo/pepr-demo (50c5d836-335e-4aa5-8b56-adecb72d4b17)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Pepr is a community-driven project. We welcome contributions of all kinds, from

You can find all the details on contributing to Pepr at:

* [Contributing to Pepr](../../contribute)
* [Contributing to Pepr](../contribute)

### Reporting Bugs

Expand All @@ -24,4 +24,4 @@ Information on reporting bugs can be found at:

Information on reporting security issues can be found at:

* [Reporting Security Issues](../../contribute/report-security-issue/)
* [Reporting Security Issues](../contribute/report-security-issue/)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,40 @@ weight: 80
---


## My Pepr version is not latest

## How do I add custom labels to Pepr's Kubernetes manifests?

During the build process, custom labels can be added the Kubernetes manifests that Pepr generates based on the Pepr section of the `package.json`. Currently, adding custom labels to `namespace` is supported.

The following example shows how to add custom namespace labels.

```json
"pepr": {
"name": "new-release",
...
"customLabels": {
"namespace": {
"istio-injection": "enabled",
"app.kubernetes.io/name": "new-release"
}
},
...
}
```

The resulting namespace will be generated after `npx pepr build`.

```yaml
apiVersion: v1
kind: Namespace
metadata:
name: pepr-system
labels:
istio-injection: enabled
app.kubernetes.io/name: new-release
```
## My Pepr version is not the latest
If you notice your Pepr version does not correspond to the latest release in GitHub after doing `npx pepr -V`, clearing the NPX cache can often resolve the issue.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This tutorial will walk you through the process of building a Kubernetes Operato
## Background


The WebApp Operator deploys the `CustomResourceDefinition` for WebApp, then watches and reconciles against instances of WebApps to ensure the desired state meets the actual cluster state.
The WebApp Operator deploys the WebApp `CustomResourceDefinition`, then watches and reconciles against instances of WebApps to ensure the desired state meets the actual cluster state.

The WebApp instance represents a `Deployment` object with configurable replicas, a `Service`, and a `ConfigMap` that has a `index.html` file that can be configured to a specific language, and theme. The resources the Operator deploys contain `ownerReferences`, causing a cascading delete effect when the WebApp instance is deleted.

Expand All @@ -22,7 +22,7 @@ If any object deployed by the Operator is deleted for any reason, the Operator w
- [Create a new Pepr Module](#create-a-new-pepr-module)
- [Create CRD](#create-crd)
- [Create Helpers](#create-helpers)
- [Create Queue and Reconciler](#create-queue-and-reconciler)
- [Create Reconciler](#create-reconciler)
- [Build and Deploy](#build-and-deploy)

## Create a new Pepr Module
Expand All @@ -43,9 +43,7 @@ npx pepr init

## Create CRD

Now, it is time to structure the CRD. The CRD is the definition of the WebApp resource. It is a Kubernetes object that defines the WebApp resource and its schema.

A CRD is created and has the following attributes: `theme`, `language`, and `replicas`. The `status` is also defined in the CRD, which is used to track the status of the WebApp resource.
The WebApp CRD has the following properties: `theme`, `language`, and `replicas` with a `status` section used to track the status of the WebApp resource.

```yaml
apiVersion: apiextensions.k8s.io/v1
Expand Down Expand Up @@ -112,24 +110,15 @@ spec:
- wa
```
Make sure the CRD has a `status` listed under `subresources` and it is a good idea to provide descriptions under the properties to help users understand what the property is used for. Enums are useful to limit the values that can be used for a property.


Status should also be listed under `subresources` to make it writable. We provide descriptions under the properties for clarity around what the property is used for. Enums are useful to limit the values that can be used for a property.

Go to the `capabilities` directory, create a new directory called `crd` with two child folders, generated and source.

```bash
mkdir -p capabilities/crd/generated capabilities/crd/source
```

Lets go ahead and install the node modules for the project.

```bash
npm ci
```


Generate a typescript class from the using `kubernetes-fluent-client` in the `generated` directory.
Generate a class based on the WebApp CRD using `kubernetes-fluent-client` and store it in the generated directory.

```bash
npx kubernetes-fluent-client crd https://gist.githubusercontent.com/cmwylie19/69b765af5ab25af62696f3337df13687/raw/72f53db7ddc06fc8891dc81136a7c190bc70f41b/WebApp.yaml .
Expand Down Expand Up @@ -300,7 +289,7 @@ export async function validator(req: PeprValidateRequest<WebApp>) {
}
```

In this section we generated scaffolded the CRD class, created a function to add ownerReferences to the manifests that will be deployed by the Operator, registered the CRD, and added a validator to the CRD.
In this section we generated the CRD class for WebApp, created a function to add `ownerReferences` to the manifests that will be deployed by the Operator to handle deletion of Kubernetes objects, registered the CRD, and added a validator to validate that instances of WebApp are in valid namespaces.

## Create Helpers

Expand Down Expand Up @@ -643,9 +632,9 @@ function configmap(instance: WebApp) {
}
```

In this section we created a `generators.ts` file that contains functions that generate the manifests that will be deployed by the Operator with the ownerReferences added to them. We decide which `ConfigMap` to deploy based on the language and theme specified in the WebApp resource and how many replicas to deploy based on the replicas specified in the WebApp resource.
We decide which `ConfigMap` to deploy based on the language and theme specified in the WebApp resource and how many replicas to deploy based on the replicas specified in the WebApp resource.

## Create Queue and Reconciler
## Create Reconciler

In the base of the `capabilities` folder, create a `reconciler.ts` file and add the following:

Expand Down Expand Up @@ -716,89 +705,15 @@ async function updateStatus(instance: WebApp, status: Status) {
}
```

Create another file in the `capabilities` folder called `enqueue.ts` and add the following:

```typescript
import { Log } from "pepr";

import { WebApp } from "./crd";
import { reconciler } from "./reconciler";

type QueueItem = {
instance: WebApp;
resolve: (value: void | PromiseLike<void>) => void;
reject: (reason?: string) => void;
};

/**
* Queue is a FIFO queue for reconciling webapps
*/
export class Queue {
#queue: QueueItem[] = [];
#pendingPromise = false;

/**
* Enqueue adds a webapp to the queue and returns a promise that resolves when the webapp is
* reconciled.
*
* @param pkg The webapp to reconcile
* @returns A promise that resolves when the instance is reconciled
*/
enqueue(instance: WebApp) {
Log.debug(
`Enqueueing ${instance.metadata!.namespace}/${instance.metadata!.name}`,
);
return new Promise<void>((resolve, reject) => {
this.#queue.push({ instance, resolve, reject });
return this.#dequeue();
});
}

/**
* Dequeue reconciles the next webapp in the queue
*
* @returns A promise that resolves when the webapp is reconciled
*/
async #dequeue() {
// If there is a pending promise, do nothing
if (this.#pendingPromise) return false;

// Take the next item from the queue
const item = this.#queue.shift();

// If there is no item, do nothing
if (!item) return false;

try {
// Set the pending promise flag to avoid concurrent reconciliations
this.#pendingPromise = true;

// Reconcile the webapp
await reconciler(item.instance);

item.resolve();
} catch (e) {
item.reject(e);
} finally {
// Reset the pending promise flag
this.#pendingPromise = false;

// After the webapp is reconciled, dequeue the next webapp
await this.#dequeue();
}
}
}
```

Finally create the `index.ts` file in the `capabilities` folder and add the following:

```typescript
import { Capability, a, Log } from "pepr";
import { WebApp } from "./crd";
import { validator } from "./crd/validator";
import { Queue } from "./enqueue";
import { WebAppCRD } from "./crd/source/webapp.crd";
import { RegisterCRD } from "./crd/register";
import { reconciler } from "./reconciler";
import "./crd/register";
import Deploy from "./controller/generators";

Expand All @@ -810,18 +725,16 @@ export const WebAppController = new Capability({

const { When, Store } = WebAppController;

const queue = new Queue();

// When instance is created or updated, validate it and enqueue it for processing
When(WebApp)
.IsCreatedOrUpdated()
.Validate(validator)
.Watch(async instance => {
.Reconcile(async instance => {
try {
Store.setItem(instance.metadata.name, JSON.stringify(instance));
await queue.enqueue(instance);
await reconciler(instance);
} catch (error) {
Log.info(`Error enqueing instance of WebApp`);
Log.info(`Error reconciling instance of WebApp`);
}
});

Expand Down Expand Up @@ -870,32 +783,18 @@ When(a.ConfigMap)

```

In this section we created a `reconciler.ts` file that contains the reconciler function that is called from the queue and is responsible for reconciling the state of the instance with the cluster and updating the status of the instance. We also created a `enqueue.ts` file that contains the queue class that is used to enqueue instances of the WebApp resource. Finally, we created the `index.ts` file that contains the WebAppController capability and the functions that are used to watch for changes to the WebApp resource and the resources that are deployed by the Operator.


## Build and Deploy

# WebApp Operator

The WebApp Operator deploys the `CustomResourceDefinition` for WebApp, then watches and reconciles against instances of WebApps to ensure the desired state meets the actual cluster state.

The WebApp instance represents a `Deployment` object with confirgurable replicas, a `Service`, and a `ConfigMap` that has a `index.html` file that can be configured to a specific language, and theme. The resources the Operator deploys contain `ownerReferences`, causing a cascading delete effect when the WebApp instance is deleted.

If any object deployed by the Operator is deleted for any reason, other than through the `ownerReference` mechanism, the Operator will abruptly redeploy the object.
In this section we created a `reconciler.ts` file that contains the function that is responsible for reconciling the state of the instance with the cluster based on CustomResource and updating the status of the instance. The `index.ts` file that contains the WebAppController capability and the functions that are used to watch for changes to the WebApp resource and corresponding Kubernetes resources. The `Reconcile` action processes the callback in a queue guaranteeing ordered and synchronous processing of events

## Demo

# WebApp Operator

The WebApp Operator deploys the `CustomResourceDefinition` for WebApp, then watches and reconciles against instances of WebApps to ensure the desired state meets the actual cluster state.

The WebApp instance represents a `Deployment` object with confirgurable replicas, a `Service`, and a `ConfigMap` that has a `index.html` file that can be configured to a specific language, and theme. The resources the Operator deploys contain `ownerReferences`, causing a cascading delete effect when the WebApp instance is deleted.

If any object deployed by the Operator is deleted for any reason, other than through the `ownerReference` mechanism, the Operator will abruptly redeploy the object.
_Create an ephemeral cluster. (Kind or k3d will work)_

## Demo
Clone the Operator

_Create an ephemeral cluster. (Kind or k3d will work)_
```bash
git clone https://github.com/defenseunicorns/pepr-excellent-examples.git
cd pepr-operator
```

Make sure Pepr is update to date

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ weight: 30
---


- [Overview](#overview)
- [Mutate](#mutate)
- [Validate](#validate)
- [Watch](#watch)
- [Reconcile](#reconcile)

## Overview

An action is a discrete set of behaviors defined in a single function that acts on a given Kubernetes GroupVersionKind (GVK) passed in during the admission controller lifecycle. Actions are the atomic operations that are performed on Kubernetes resources by Pepr.

For example, an action could be responsible for adding a specific label to a Kubernetes resource, or for modifying a specific field in a resource's metadata. Actions can be grouped together within a Capability to provide a more comprehensive set of operations that can be performed on Kubernetes resources.
Expand All @@ -14,7 +22,7 @@ Let's look at some example actions that are included in the `HelloPepr` capabili

---

In this first example, Pepr is adding a label and annotation to a ConfigMap with tne name `example-1` when it is created. Comments are added to each line to explain in more detail what is happening.
In this first example, Pepr is adding a label and annotation to a ConfigMap with the name `example-1` when it is created. Comments are added to each line to explain in more detail what is happening.

```ts
// When(a.<Kind>) filters which GroupVersionKind (GVK) this action should act on.
Expand Down Expand Up @@ -122,4 +130,22 @@ When(WebApp)
});
```

There are many more examples in the `HelloPepr` capability that you can use as a reference when creating your own actions. Note that each time you run [`npx pepr update`](../pepr-cli#pepr-update), Pepr will automatically update the `HelloPepr` capability with the latest examples and best practices for you to reference and test directly in your Pepr Module.
## Mutate

Mutating admission webhooks are invoked first and can modify objects sent to the API server to enforce custom defaults. After an object is sent to Pepr's Mutating Admission Webhook, Pepr will [annotate the object](https://github.com/defenseunicorns/pepr/blob/f01f5eeda16c13ecd0d51b26b8a16ed7e4c1b080/src/lib/mutate-processor.ts#l64) to indicate the status.

After a successful mutation of an object in a module with UUID static-test, and capability name hello-pepr, expect to see this annotation: `static-test.pepr.dev/hello-pepr: succeeded`.

## Validate

After the Mutation phase, after all object modifications are complete, and after the incoming object is validated by the API server, validating admission webhooks are invoked and can reject requests to enforce custom policies.

Validate does not annotate the objects that are allowed into the cluster, but the validation webhook can be audited with `npx pepr monitor`. Read the [monitoring docs](https://docs.pepr.dev/main/best-practices/#monitoring) for more information.

## Watch

[Kubernetes](https://kubernetes.io/docs/reference/using-api/api-concepts) supports efficient change notifications on resources via watches. Pepr uses the Watch action for monitoring resources that previously existed in the cluster and for performing long-running asynchronous events upon receiving change notifications on resources, as watches are not limited by [timeouts](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#timeouts).

## Reconcile

Reconcile functions the same as Watch but is tailored for building Kubernetes Controllers and Operators because it processes callback operations in a [Queue](https://github.com/defenseunicorns/pepr/blob/f01f5eeda16c13ecd0d51b26b8a16ed7e4c1b080/src/lib/watch-processor.ts#l86), guaranteeing ordered and synchronous processing of events, even when the system may be under heavy load.
Loading

0 comments on commit fe87e51

Please sign in to comment.