Skip to content

Commit

Permalink
chore: update component-webhooks example to use new Pepr k8s fluent c…
Browse files Browse the repository at this point in the history
…lient (#2090)

## Description

Update Pepr to `v0.15.0` and use new k8s fluent client

- adds types for parsing zarf package secret data
- adds a `zarf internal gen-types-schema` command to generate a JSON
schema from Zarf types (DeployedPackage, ZarfPackage, ZarfState). This
command was used to auto-generate the typescript interfaces in
`examples/component-webhook/capabilities/zarf-types.ts`

## Related Issue

Fixes #2030

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Other (security config, docs update, etc)

## Checklist before merging

- [x] Test, docs, adr added or updated as needed
- [x] [Contributor Guide
Steps](https://github.com/defenseunicorns/zarf/blob/main/CONTRIBUTING.md#developer-workflow)
followed

---------

Co-authored-by: Wayne Starr <[email protected]>
  • Loading branch information
lucasrod16 and Racer159 authored Nov 27, 2023
1 parent 06c8e53 commit 03fea70
Show file tree
Hide file tree
Showing 12 changed files with 1,798 additions and 3,184 deletions.
10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ repos:
- id: go-fmt
- repo: local
hooks:
- id: generate-zarf-schema
name: Check for outdated Zarf schema
entry: ./hack/verify-zarf-schema.sh
- id: check-docs-and-schema
name: Check for outdated docs and Zarf schema
entry: ./hack/check-zarf-docs-and-schema.sh
files: "src/types/types.go"
types: [go]
language: script
description:
"Runs `zarf internal config-schema > zarf.schema.json` to ensure
schema is up to date"
"Checks if there have been changes
made to the docs and schema"
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.14.0
hooks:
Expand Down
3 changes: 2 additions & 1 deletion examples/component-webhooks/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"ignorePatterns": [
"node_modules",
"dist",
"hack"
"hack",
"capabilities/zarf-types.ts"
],
"root": true
}
89 changes: 52 additions & 37 deletions examples/component-webhooks/capabilities/hook.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Capability, a, Log, k8s } from "pepr";
import { Capability, a, Log, K8s, kind } from "pepr";
import { DeployedPackage } from "./zarf-types";

/**
* The Webhook Capability is an example capability to demonstrate using webhooks to interact with Zarf package deployments.
Expand All @@ -11,6 +12,8 @@ export const Webhook = new Capability({
namespaces: ["zarf"],
});

const webhookName = "test-webhook";

const { When } = Webhook;

When(a.Secret)
Expand All @@ -19,7 +22,7 @@ When(a.Secret)
.WithLabel("package-deploy-info")
.Mutate(request => {
const secret = request.Raw;
let secretData;
let secretData: DeployedPackage;
let secretString: string;
let manuallyDecoded = false;

Expand All @@ -46,7 +49,7 @@ When(a.Secret)

const componentWebhook =
secretData.componentWebhooks?.[deployedComponent?.name]?.[
"test-webhook"
webhookName
];

// Check if the component has a webhook running for the current package generation
Expand All @@ -63,9 +66,9 @@ When(a.Secret)
// Update the secret noting that the webhook is running for this component
secretData.componentWebhooks[deployedComponent.name] = {
"test-webhook": {
"name": "test-webhook",
"status": "Running",
"observedGeneration": secretData.generation,
name: webhookName,
status: "Running",
observedGeneration: secretData.generation,
},
};

Expand All @@ -86,46 +89,58 @@ When(a.Secret)
async function sleepAndChangeStatus(secretName: string, componentName: string) {
await sleep(10);

// Configure the k8s api client
const kc = new k8s.KubeConfig();
kc.loadFromDefault();
const k8sCoreApi = kc.makeApiClient(k8s.CoreV1Api);
const ns = "zarf";

let secret: a.Secret;

// Fetch the package secret
try {
const response = await k8sCoreApi.readNamespacedSecret(secretName, "zarf");
const v1Secret = response.body;
secret = await K8s(kind.Secret).InNamespace(ns).Get(secretName);
} catch (err) {
Log.error(
`Error: Failed to get package secret '${secretName}' in namespace '${ns}': ${JSON.stringify(
err,
)}`,
);
}

const secretString = atob(v1Secret.data.data);
const secretData = JSON.parse(secretString);
const secretString = atob(secret.data.data);
const secretData: DeployedPackage = JSON.parse(secretString);

// Update the webhook status if the observedGeneration matches
const componentWebhook =
secretData.componentWebhooks[componentName]?.["test-webhook"];
// Update the webhook status if the observedGeneration matches
const componentWebhook =
secretData.componentWebhooks[componentName]?.[webhookName];

if (componentWebhook?.observedGeneration === secretData.generation) {
componentWebhook.status = "Succeeded";
if (componentWebhook?.observedGeneration === secretData.generation) {
componentWebhook.status = "Succeeded";

secretData.componentWebhooks[componentName]["test-webhook"] =
componentWebhook;
}
secretData.componentWebhooks[componentName][webhookName] = componentWebhook;
}

secret.data.data = btoa(JSON.stringify(secretData));

v1Secret.data.data = btoa(JSON.stringify(secretData));

// Patch the secret back to the cluster
await k8sCoreApi.patchNamespacedSecret(
secretName,
"zarf",
v1Secret,
undefined,
undefined,
undefined,
undefined,
undefined,
{ headers: { "Content-Type": "application/strategic-merge-patch+json" } },
// Update the status in the package secret
// Use Server-Side force apply to forcefully take ownership of the package secret data.data field
// Doing a Server-Side apply without the force option will result in a FieldManagerConflict error due to Zarf owning the object.
try {
await K8s(kind.Secret).Apply(
{
metadata: {
name: secretName,
namespace: ns,
},
data: {
data: secret.data.data,
},
},
{ force: true },
);
} catch (err) {
Log.error(`Unable to update the package secret: ${JSON.stringify(err)}`);
return err;
Log.error(
`Error: Failed to update package secret '${secretName}' in namespace '${ns}': ${JSON.stringify(
err,
)}`,
);
}
}

Expand Down
Loading

0 comments on commit 03fea70

Please sign in to comment.