Skip to content

Commit

Permalink
Hotfix pepr controller image tag (#185)
Browse files Browse the repository at this point in the history
Various CLI fixes:

- fixes #184, generated yaml image tag regression 
- renames `utils` -> `R` for Ramda export: `import { R } from "pepr";`
- fixes error on `pepr update` if no capabilities folder present
- add complete E2E for `zarf.yaml` and image validation for generated
deployment yaml
- update CLI tagline
  • Loading branch information
jeff-mccoy authored Jul 12, 2023
1 parent deb075d commit 187ce72
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 27 deletions.
70 changes: 68 additions & 2 deletions hack/e2e.test.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { k8s } from "../dist/lib.js";
import test from "ava";
import { execSync, spawn } from "child_process";
import { promises as fs } from "fs";
import { resolve } from "path";

const { AppsV1Api, CoreV1Api, KubeConfig } = k8s;
import { k8s } from "../dist/lib.js";

const { AppsV1Api, CoreV1Api, KubeConfig, loadYaml } = k8s;

const kc = new KubeConfig();
kc.loadFromDefault();
Expand Down Expand Up @@ -61,6 +62,71 @@ test.serial("E2E: `pepr format`", t => {
}
});

test.serial("E2E: zarf.yaml validation", async t => {
try {
const pgkJSONPath = resolve(testDir, "package.json");
const pkgJSON = await fs.readFile(pgkJSONPath, "utf8");
const random = () => Math.floor(Math.random() * 10);
const randomSemver = `${random()}.${random()}.${random()}`;

t.log(`Testing with random semver: ${randomSemver}`);

// Replace the exact text
const updatedPkgJSON = pkgJSON.replace("file:../pepr-0.0.0-development.tgz", randomSemver);

// Write the modified string back to the file
await fs.writeFile(pgkJSONPath, updatedPkgJSON);

// Build the image
execSync("npx pepr build", { cwd: testDir, stdio: "inherit" });

const k8sYaml = await fs.readFile(
resolve(testDir, "dist", "pepr-module-static-test.yaml"),
"utf8"
);
const zarfYAML = await fs.readFile(resolve(testDir, "dist", "zarf.yaml"), "utf8");

const expectedImage = `ghcr.io/defenseunicorns/pepr/controller:v${randomSemver}`;

const expectedZarfYaml = {
kind: "ZarfPackageConfig",
metadata: {
name: "pepr-static-test",
description: "Pepr Module: A test module for Pepr",
url: "https://github.com/defenseunicorns/pepr",
version: "0.0.1",
},
components: [
{
name: "module",
required: true,
manifests: [
{
name: "module",
namespace: "pepr-system",
files: ["pepr-module-static-test.yaml"],
},
],
images: [expectedImage],
},
],
};

// Check the generated zarf yaml
t.deepEqual(loadYaml(zarfYAML), expectedZarfYaml);

// Check the generated k8s yaml
t.true(k8sYaml.includes(`image: ${expectedImage}`));

// Restore the original package.json
await fs.writeFile(pgkJSONPath, pkgJSON);

t.pass();
} catch (e) {
t.fail(e.message);
}
});

test.serial("E2E: `pepr build`", async t => {
try {
execSync("npx pepr build", { cwd: testDir, stdio: "inherit" });
Expand Down
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const program = new RootCmd();

program
.version(version)
.description(`Pepr Kubernetes Thingy (v${version})`)
.description(`Pepr (v${version}) - Type safe K8s middleware for humans`)
.action(() => {
if (program.args.length < 1) {
console.log(banner);
Expand Down
8 changes: 5 additions & 3 deletions src/cli/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function (program: RootCmd) {
// Generate a secret for the module
const webhook = new Webhook({
...cfg.pepr,
version: cfg.version,
appVersion: cfg.version,
description: cfg.description,
});
const yamlFile = `pepr-module-${uuid}.yaml`;
Expand Down Expand Up @@ -87,9 +87,11 @@ export async function loadModule(entryPoint = peprTS) {
if (cfg.dependencies.pepr && !cfg.dependencies.pepr.includes("file:")) {
const versionMatch = /(\d+\.\d+\.\d+)/.exec(cfg.dependencies.pepr);
if (!versionMatch || versionMatch.length < 2) {
throw new Error("Could not find the Pepr version in package.json");
throw new Error(
`Could not find the Pepr version in package.json, found: ${cfg.dependencies.pepr}`
);
}
cfg.pepr.version = versionMatch[1];
cfg.pepr.peprVersion = versionMatch[1];
}

// Exit if the module's UUID could not be found
Expand Down
3 changes: 0 additions & 3 deletions src/cli/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ export default function (program: RootCmd) {
.option("-v, --validate-only", "Do not modify files, only validate formatting")
.action(async opts => {
try {
// "format:check": "eslint src && prettier src --check",
// "format:fix": "eslint src --fix && prettier src --write"

const eslint = new ESLint();
const results = await eslint.lintFiles(["./**/*.ts"]);

Expand Down
50 changes: 42 additions & 8 deletions src/cli/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors

import { execSync } from "child_process";
import fs from "fs";
import { resolve } from "path";
import prompt from "prompts";

Expand Down Expand Up @@ -33,22 +34,55 @@ export default function (program: RootCmd) {

console.log("Updating the Pepr module...");

try {
// Update Pepr for the module
execSync("npm install pepr@latest", {
stdio: "inherit",
});

// Don't update the template files if the user specified the --skip-template-update flag
if (!opts.skipTemplateUpdate) {
execSync("npx pepr update-templates", {
stdio: "inherit",
});
}

console.log(`Module updated!`);
} catch (e) {
Log.debug(e);
if (e instanceof Error) {
Log.error(e.message);
}
process.exit(1);
}
});

program
.command("update-templates", { hidden: true })
.description("Perform template updates")
.action(async opts => {
console.log("Updating Pepr config and template tiles...");

try {
// Don't update the template files if the user specified the --skip-template-update flag
if (!opts.skipTemplateUpdate) {
await write(resolve(prettier.path), prettier.data);
await write(resolve(tsConfig.path), tsConfig.data);
await write(resolve(".vscode", snippet.path), snippet.data);
await write(resolve("capabilities", samplesYaml.path), samplesYaml.data);
await write(resolve("capabilities", helloPepr.path), helloPepr.data);
}

// Update Pepr for the module
execSync("npm install pepr@latest", {
stdio: "inherit",
});
// Update the samples.yaml file if it exists
const samplePath = resolve("capabilities", samplesYaml.path);
if (fs.existsSync(samplePath)) {
fs.unlinkSync(samplePath);
await write(samplePath, samplesYaml.data);
}

console.log(`Module updated!`);
// Update the HelloPepr.ts file if it exists
const tsPath = resolve("capabilities", helloPepr.path);
if (fs.existsSync(tsPath)) {
await write(tsPath, helloPepr.data);
}
}
} catch (e) {
Log.debug(e);
if (e instanceof Error) {
Expand Down
12 changes: 6 additions & 6 deletions src/lib.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as k8s from "@kubernetes/client-node";
import { StatusCodes as fetchStatus } from "http-status-codes";
import * as utils from "ramda";
import * as R from "ramda";
import { Capability } from "./lib/capability";
import { fetch, fetchRaw } from "./lib/fetch";
import { RegisterKind, a } from "./lib/k8s/index";
Expand All @@ -10,8 +10,8 @@ import { PeprRequest } from "./lib/request";
import * as PeprUtils from "./lib/utils";

// Import type information for external packages
import type * as KubernetesClientNode from "@kubernetes/client-node";
import type * as RamdaUtils from "ramda";
import type * as K8sTypes from "@kubernetes/client-node";
import type * as RTypes from "ramda";

export {
a,
Expand All @@ -22,13 +22,13 @@ export {
RegisterKind,
Capability,
Log,
utils,
R,
fetch,
fetchRaw,
fetchStatus,
k8s,

// Export the imported type information for external packages
RamdaUtils,
KubernetesClientNode,
RTypes,
K8sTypes,
};
4 changes: 2 additions & 2 deletions src/lib/k8s/webhook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class Webhook {
constructor(private readonly config: ModuleConfig, private readonly host?: string) {
this.name = `pepr-${config.uuid}`;

this.image = `ghcr.io/defenseunicorns/pepr/controller:v${config.version}`;
this.image = `ghcr.io/defenseunicorns/pepr/controller:v${config.peprVersion}`;

// Generate the ephemeral tls things
this._tls = genTLS(this.host || `${this.name}.pepr-system.svc`);
Expand Down Expand Up @@ -453,7 +453,7 @@ export class Webhook {
name: this.name,
description: `Pepr Module: ${this.config.description}`,
url: "https://github.com/defenseunicorns/pepr",
version: `${this.config.version}`,
version: `${this.config.appVersion || "0.0.1"}`,
},
components: [
{
Expand Down
6 changes: 4 additions & 2 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ export type ModuleSigning = {
export type ModuleConfig = {
/** The user-defined name for the module */
name: string;
/** The version of Pepr that the module was originally generated with */
version?: string;
/** The Pepr version this module uses */
peprVersion?: string;
/** The user-defined version of the module */
appVersion?: string;
/** A unique identifier for this Pepr module. This is automatically generated by Pepr. */
uuid: string;
/** A description of the Pepr module and what it does. */
Expand Down

0 comments on commit 187ce72

Please sign in to comment.