pepr 0.1.27 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/package.json +76 -0
- package/dist/src/cli/banner.d.ts +1 -0
- package/dist/{pepr-cli.js → src/cli/banner.js} +1 -1251
- package/dist/src/cli/build.d.ts +7 -0
- package/dist/src/cli/build.js +95 -0
- package/dist/src/cli/capability.d.ts +2 -0
- package/dist/src/cli/capability.js +12 -0
- package/dist/src/cli/deploy.d.ts +2 -0
- package/dist/src/cli/deploy.js +49 -0
- package/dist/src/cli/dev.d.ts +2 -0
- package/dist/src/cli/dev.js +90 -0
- package/dist/src/cli/index.d.ts +1 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/init/index.d.ts +2 -0
- package/dist/src/cli/init/index.js +48 -0
- package/dist/src/cli/init/templates.d.ts +82 -0
- package/dist/src/cli/init/templates.js +224 -0
- package/dist/src/cli/init/utils.d.ts +20 -0
- package/dist/src/cli/init/utils.js +50 -0
- package/dist/src/cli/init/walkthrough.d.ts +7 -0
- package/dist/src/cli/init/walkthrough.js +76 -0
- package/dist/src/cli/root.d.ts +4 -0
- package/dist/src/cli/root.js +14 -0
- package/dist/src/cli/test.d.ts +2 -0
- package/dist/src/cli/test.js +45 -0
- package/dist/src/lib/capability.d.ts +26 -0
- package/dist/src/lib/capability.js +112 -0
- package/dist/src/lib/controller.d.ts +13 -0
- package/dist/src/lib/controller.js +77 -0
- package/dist/src/lib/filter.d.ts +10 -0
- package/dist/src/lib/filter.js +41 -0
- package/dist/src/lib/k8s/index.d.ts +4 -0
- package/dist/src/lib/k8s/index.js +7 -0
- package/dist/src/lib/k8s/kinds.d.ts +3 -0
- package/dist/src/lib/k8s/kinds.js +427 -0
- package/dist/src/lib/k8s/tls.d.ts +17 -0
- package/dist/src/lib/k8s/tls.js +67 -0
- package/dist/src/lib/k8s/types.d.ts +136 -0
- package/dist/src/lib/k8s/types.js +9 -0
- package/dist/src/lib/k8s/upstream.d.ts +1 -0
- package/dist/src/lib/k8s/upstream.js +3 -0
- package/dist/src/lib/k8s/webhook.d.ts +33 -0
- package/dist/src/lib/k8s/webhook.js +490 -0
- package/dist/src/lib/logger.d.ts +54 -0
- package/dist/{types-1709b44f.js → src/lib/logger.js} +3 -40
- package/dist/src/lib/module.d.ts +22 -0
- package/dist/src/lib/module.js +32 -0
- package/dist/src/lib/processor.d.ts +4 -0
- package/dist/src/lib/processor.js +66 -0
- package/dist/src/lib/request.d.ts +77 -0
- package/dist/src/lib/request.js +117 -0
- package/dist/src/lib/types.d.ts +187 -0
- package/dist/src/lib/types.js +31 -0
- package/package.json +8 -11
- package/tsconfig.build.json +4 -0
- package/dist/pepr-core.js +0 -949
- package/tsconfig.json +0 -17
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import json from "@rollup/plugin-json";
|
|
4
|
+
import nodeResolve from "@rollup/plugin-node-resolve";
|
|
5
|
+
import typescript from "@rollup/plugin-typescript";
|
|
6
|
+
import { promises as fs } from "fs";
|
|
7
|
+
import { resolve } from "path";
|
|
8
|
+
import { rollup } from "rollup";
|
|
9
|
+
import Log from "../lib/logger";
|
|
10
|
+
import { Webhook } from "../lib/k8s/webhook";
|
|
11
|
+
export default function (program) {
|
|
12
|
+
program
|
|
13
|
+
.command("build")
|
|
14
|
+
.description("Build a Pepr Module for deployment")
|
|
15
|
+
.option("-d, --dir [directory]", "Pepr module directory", ".")
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
// Build the module
|
|
18
|
+
const { cfg, path, uuid } = await buildModule(opts.dir);
|
|
19
|
+
// Read the compiled module code
|
|
20
|
+
const code = await fs.readFile(path, { encoding: "utf-8" });
|
|
21
|
+
// Generate a secret for the module
|
|
22
|
+
const webhook = new Webhook({
|
|
23
|
+
...cfg.pepr,
|
|
24
|
+
description: cfg.description,
|
|
25
|
+
});
|
|
26
|
+
const yamlFile = `pepr-module-${uuid}.yaml`;
|
|
27
|
+
const yamlPath = resolve("dist", yamlFile);
|
|
28
|
+
const yaml = webhook.allYaml(code);
|
|
29
|
+
const zarfPath = resolve("dist", "zarf.yaml");
|
|
30
|
+
const zarf = webhook.zarfYaml(yamlFile);
|
|
31
|
+
await fs.writeFile(yamlPath, yaml);
|
|
32
|
+
await fs.writeFile(zarfPath, zarf);
|
|
33
|
+
Log.debug(`Module compiled successfully at ${path}`);
|
|
34
|
+
Log.info(`K8s resource for the module saved to ${yamlPath}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const externalLibs = [
|
|
38
|
+
/@kubernetes\/client-node(\/.*)?/,
|
|
39
|
+
"express",
|
|
40
|
+
"fast-json-patch",
|
|
41
|
+
"ramda",
|
|
42
|
+
];
|
|
43
|
+
export async function buildModule(moduleDir) {
|
|
44
|
+
try {
|
|
45
|
+
// Resolve the path to the module's package.json file
|
|
46
|
+
const cfgPath = resolve(moduleDir, "package.json");
|
|
47
|
+
const input = resolve(moduleDir, "pepr.ts");
|
|
48
|
+
// Read the module's UUID from the package.json filel
|
|
49
|
+
const moduleText = await fs.readFile(cfgPath, { encoding: "utf-8" });
|
|
50
|
+
const cfg = JSON.parse(moduleText);
|
|
51
|
+
const { uuid } = cfg.pepr;
|
|
52
|
+
const name = `pepr-${uuid}.js`;
|
|
53
|
+
// Exit if the module's UUID could not be found
|
|
54
|
+
if (!uuid) {
|
|
55
|
+
throw new Error("Could not load the uuid in package.json");
|
|
56
|
+
}
|
|
57
|
+
const plugins = [
|
|
58
|
+
nodeResolve({
|
|
59
|
+
preferBuiltins: true,
|
|
60
|
+
}),
|
|
61
|
+
json(),
|
|
62
|
+
typescript({
|
|
63
|
+
tsconfig: "./tsconfig.json",
|
|
64
|
+
declaration: false,
|
|
65
|
+
removeComments: true,
|
|
66
|
+
sourceMap: false,
|
|
67
|
+
include: ["**/*.ts"],
|
|
68
|
+
}),
|
|
69
|
+
];
|
|
70
|
+
// Build the module using Rollup
|
|
71
|
+
const bundle = await rollup({
|
|
72
|
+
plugins,
|
|
73
|
+
external: externalLibs,
|
|
74
|
+
treeshake: true,
|
|
75
|
+
input,
|
|
76
|
+
});
|
|
77
|
+
// Write the module to the dist directory
|
|
78
|
+
await bundle.write({
|
|
79
|
+
dir: "dist",
|
|
80
|
+
format: "cjs",
|
|
81
|
+
entryFileNames: name,
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
path: resolve("dist", name),
|
|
85
|
+
cfg,
|
|
86
|
+
uuid,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
// On any other error, exit with a non-zero exit code
|
|
91
|
+
Log.debug(e);
|
|
92
|
+
Log.error(e.message);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
export default function (program) {
|
|
4
|
+
program
|
|
5
|
+
.command("new")
|
|
6
|
+
.description("Create a new Pepr Capability")
|
|
7
|
+
.option("-d, --dir [directory]", "Pepr module directory", ".")
|
|
8
|
+
.action(() => {
|
|
9
|
+
// TODO: Create a new capability
|
|
10
|
+
console.log("new");
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import { promises as fs } from "fs";
|
|
4
|
+
import { Webhook } from "../lib/k8s/webhook";
|
|
5
|
+
import Log from "../lib/logger";
|
|
6
|
+
import { buildModule } from "./build";
|
|
7
|
+
import { prompt } from "prompts";
|
|
8
|
+
export default function (program) {
|
|
9
|
+
program
|
|
10
|
+
.command("deploy")
|
|
11
|
+
.description("Deploy a Pepr Module")
|
|
12
|
+
.option("-d, --dir [directory]", "Pepr module directory", ".")
|
|
13
|
+
.option("-i, --image [image]", "Override the image tag")
|
|
14
|
+
.option("-f, --force", "Force redeployment")
|
|
15
|
+
.action(async (opts) => {
|
|
16
|
+
if (!opts.force) {
|
|
17
|
+
// Prompt the user to confirm
|
|
18
|
+
const confirm = await prompt({
|
|
19
|
+
type: "confirm",
|
|
20
|
+
name: "confirm",
|
|
21
|
+
message: "This will remove and redeploy the module. Continue?",
|
|
22
|
+
});
|
|
23
|
+
// Exit if the user doesn't confirm
|
|
24
|
+
if (!confirm.confirm) {
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Build the module
|
|
29
|
+
const { cfg, path } = await buildModule(opts.dir);
|
|
30
|
+
// Read the compiled module code
|
|
31
|
+
const code = await fs.readFile(path, { encoding: "utf-8" });
|
|
32
|
+
// Generate a secret for the module
|
|
33
|
+
const webhook = new Webhook({
|
|
34
|
+
...cfg.pepr,
|
|
35
|
+
description: cfg.description,
|
|
36
|
+
});
|
|
37
|
+
if (opts.image) {
|
|
38
|
+
webhook.image = opts.image;
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await webhook.deploy(code);
|
|
42
|
+
Log.info(`Module deployed successfully`);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
Log.error(`Error deploying module: ${e}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { watch } from "chokidar";
|
|
5
|
+
import { promises as fs } from "fs";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
import { prompt } from "prompts";
|
|
8
|
+
import { Webhook } from "../lib/k8s/webhook";
|
|
9
|
+
import Log from "../lib/logger";
|
|
10
|
+
import { buildModule } from "./build";
|
|
11
|
+
export default function (program) {
|
|
12
|
+
program
|
|
13
|
+
.command("dev")
|
|
14
|
+
.description("Setup a local webhook development environment")
|
|
15
|
+
.option("-d, --dir [directory]", "Pepr module directory", ".")
|
|
16
|
+
.option("-h, --host [host]", "Host to listen on", "host.docker.internal")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
// Prompt the user to confirm
|
|
19
|
+
const confirm = await prompt({
|
|
20
|
+
type: "confirm",
|
|
21
|
+
name: "confirm",
|
|
22
|
+
message: "This will remove and redeploy the module. Continue?",
|
|
23
|
+
});
|
|
24
|
+
// Exit if the user doesn't confirm
|
|
25
|
+
if (!confirm.confirm) {
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
// Build the module
|
|
29
|
+
const { cfg, path } = await buildModule(opts.dir);
|
|
30
|
+
// Read the compiled module code
|
|
31
|
+
const code = await fs.readFile(path, { encoding: "utf-8" });
|
|
32
|
+
// Generate a secret for the module
|
|
33
|
+
const webhook = new Webhook({
|
|
34
|
+
...cfg.pepr,
|
|
35
|
+
description: cfg.description,
|
|
36
|
+
}, opts.host);
|
|
37
|
+
// Write the TLS cert and key to disk
|
|
38
|
+
await fs.writeFile("insecure-tls.crt", webhook.tls.pem.crt);
|
|
39
|
+
await fs.writeFile("insecure-tls.key", webhook.tls.pem.key);
|
|
40
|
+
try {
|
|
41
|
+
await webhook.deploy(code);
|
|
42
|
+
Log.info(`Module deployed successfully`);
|
|
43
|
+
const moduleFiles = resolve(opts.dir, "**", "*.ts");
|
|
44
|
+
const watcher = watch(moduleFiles);
|
|
45
|
+
const peprTS = resolve(opts.dir, "pepr.ts");
|
|
46
|
+
let program;
|
|
47
|
+
// Run the module once to start the server
|
|
48
|
+
runDev(peprTS);
|
|
49
|
+
// Watch for changes
|
|
50
|
+
watcher.on("ready", () => {
|
|
51
|
+
Log.info(`Watching for changes in ${moduleFiles}`);
|
|
52
|
+
watcher.on("all", async (event, path) => {
|
|
53
|
+
Log.debug({ event, path }, "File changed");
|
|
54
|
+
// Kill the running process
|
|
55
|
+
if (program) {
|
|
56
|
+
program.kill("SIGKILL");
|
|
57
|
+
}
|
|
58
|
+
// Start the process again
|
|
59
|
+
program = runDev(peprTS);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
Log.error(`Error deploying module: ${e}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function runDev(path) {
|
|
70
|
+
try {
|
|
71
|
+
const program = spawn("./node_modules/.bin/ts-node", [path], {
|
|
72
|
+
env: {
|
|
73
|
+
...process.env,
|
|
74
|
+
SSL_KEY_PATH: "insecure-tls.key",
|
|
75
|
+
SSL_CERT_PATH: "insecure-tls.crt",
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
program.stdout.on("data", data => console.log(data.toString()));
|
|
79
|
+
program.stderr.on("data", data => console.error(data.toString()));
|
|
80
|
+
program.on("close", code => {
|
|
81
|
+
Log.info(`Process exited with code ${code}`);
|
|
82
|
+
});
|
|
83
|
+
return program;
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
Log.debug(e);
|
|
87
|
+
Log.error(`Error running module: ${e}`);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import { version } from "../../package.json";
|
|
4
|
+
import { banner } from "./banner";
|
|
5
|
+
import build from "./build";
|
|
6
|
+
import capability from "./capability";
|
|
7
|
+
import deploy from "./deploy";
|
|
8
|
+
import dev from "./dev";
|
|
9
|
+
import init from "./init";
|
|
10
|
+
import { RootCmd } from "./root";
|
|
11
|
+
import test from "./test";
|
|
12
|
+
const program = new RootCmd();
|
|
13
|
+
program
|
|
14
|
+
.version(version)
|
|
15
|
+
.description(`Pepr Kubernetes Thingy (v${version})`)
|
|
16
|
+
.action(() => {
|
|
17
|
+
if (program.args.length < 1) {
|
|
18
|
+
console.log(banner);
|
|
19
|
+
program.help();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
init(program);
|
|
23
|
+
build(program);
|
|
24
|
+
capability(program);
|
|
25
|
+
test(program);
|
|
26
|
+
deploy(program);
|
|
27
|
+
dev(program);
|
|
28
|
+
program.parse();
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import Log from "../../lib/logger";
|
|
6
|
+
import { capabilityHelloPeprTS, capabilitySnippet, genPeprTS, genPkgJSON, gitIgnore, prettierRC, readme, tsConfig, } from "./templates";
|
|
7
|
+
import { createDir, sanitizeName, write } from "./utils";
|
|
8
|
+
import { confirm, walkthrough } from "./walkthrough";
|
|
9
|
+
export default function (program) {
|
|
10
|
+
program
|
|
11
|
+
.command("init")
|
|
12
|
+
.description("Initialize a new Pepr Module")
|
|
13
|
+
.action(async () => {
|
|
14
|
+
const response = await walkthrough();
|
|
15
|
+
const dirName = sanitizeName(response.name);
|
|
16
|
+
const packageJSON = genPkgJSON(response);
|
|
17
|
+
const peprTS = genPeprTS();
|
|
18
|
+
const confirmed = await confirm(dirName, packageJSON, peprTS.path);
|
|
19
|
+
if (confirmed) {
|
|
20
|
+
console.log("Creating new Pepr module...");
|
|
21
|
+
try {
|
|
22
|
+
await createDir(dirName);
|
|
23
|
+
await createDir(resolve(dirName, ".vscode"));
|
|
24
|
+
await createDir(resolve(dirName, "capabilities"));
|
|
25
|
+
await write(resolve(dirName, gitIgnore.path), gitIgnore.data);
|
|
26
|
+
await write(resolve(dirName, prettierRC.path), prettierRC.data);
|
|
27
|
+
await write(resolve(dirName, packageJSON.path), packageJSON.data);
|
|
28
|
+
await write(resolve(dirName, readme.path), readme.data);
|
|
29
|
+
await write(resolve(dirName, tsConfig.path), tsConfig.data);
|
|
30
|
+
await write(resolve(dirName, peprTS.path), peprTS.data);
|
|
31
|
+
await write(resolve(dirName, ".vscode", capabilitySnippet.path), capabilitySnippet.data);
|
|
32
|
+
await write(resolve(dirName, "capabilities", capabilityHelloPeprTS.path), capabilityHelloPeprTS.data);
|
|
33
|
+
// run npm install from the new directory
|
|
34
|
+
process.chdir(dirName);
|
|
35
|
+
execSync("npm install", {
|
|
36
|
+
stdio: "inherit",
|
|
37
|
+
});
|
|
38
|
+
console.log(`New Pepr module created at ${dirName}`);
|
|
39
|
+
console.log(`Open VSCode or your editor of choice in ${dirName} to get started!`);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
Log.debug(e);
|
|
43
|
+
Log.error(e.message);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { InitOptions } from "./walkthrough";
|
|
2
|
+
export declare function genPeprTS(): {
|
|
3
|
+
path: string;
|
|
4
|
+
data: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function genPkgJSON(opts: InitOptions): {
|
|
7
|
+
data: {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string;
|
|
10
|
+
description: any;
|
|
11
|
+
keywords: string[];
|
|
12
|
+
pepr: {
|
|
13
|
+
name: any;
|
|
14
|
+
version: string;
|
|
15
|
+
uuid: string;
|
|
16
|
+
onError: any;
|
|
17
|
+
alwaysIgnore: {
|
|
18
|
+
namespaces: any[];
|
|
19
|
+
labels: any[];
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
scripts: {
|
|
23
|
+
build: string;
|
|
24
|
+
start: string;
|
|
25
|
+
};
|
|
26
|
+
dependencies: {
|
|
27
|
+
pepr: string;
|
|
28
|
+
};
|
|
29
|
+
devDependencies: {
|
|
30
|
+
typescript: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
path: string;
|
|
34
|
+
print: string;
|
|
35
|
+
};
|
|
36
|
+
export declare const tsConfig: {
|
|
37
|
+
path: string;
|
|
38
|
+
data: {
|
|
39
|
+
compilerOptions: {
|
|
40
|
+
esModuleInterop: boolean;
|
|
41
|
+
lib: string[];
|
|
42
|
+
moduleResolution: string;
|
|
43
|
+
resolveJsonModule: boolean;
|
|
44
|
+
rootDir: string;
|
|
45
|
+
strict: boolean;
|
|
46
|
+
target: string;
|
|
47
|
+
};
|
|
48
|
+
include: string[];
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
export declare const gitIgnore: {
|
|
52
|
+
path: string;
|
|
53
|
+
data: string;
|
|
54
|
+
};
|
|
55
|
+
export declare const prettierRC: {
|
|
56
|
+
path: string;
|
|
57
|
+
data: {
|
|
58
|
+
arrowParens: string;
|
|
59
|
+
bracketSameLine: boolean;
|
|
60
|
+
bracketSpacing: boolean;
|
|
61
|
+
embeddedLanguageFormatting: string;
|
|
62
|
+
insertPragma: boolean;
|
|
63
|
+
printWidth: number;
|
|
64
|
+
quoteProps: string;
|
|
65
|
+
requirePragma: boolean;
|
|
66
|
+
semi: boolean;
|
|
67
|
+
tabWidth: number;
|
|
68
|
+
useTabs: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export declare const readme: {
|
|
72
|
+
path: string;
|
|
73
|
+
data: string;
|
|
74
|
+
};
|
|
75
|
+
export declare const capabilityHelloPeprTS: {
|
|
76
|
+
path: string;
|
|
77
|
+
data: string;
|
|
78
|
+
};
|
|
79
|
+
export declare const capabilitySnippet: {
|
|
80
|
+
path: string;
|
|
81
|
+
data: string;
|
|
82
|
+
};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
import { inspect } from "util";
|
|
4
|
+
import { v4 as uuidv4, v5 as uuidv5 } from "uuid";
|
|
5
|
+
import { dependencies, version } from "../../../package.json";
|
|
6
|
+
import { sanitizeName } from "./utils";
|
|
7
|
+
export function genPeprTS() {
|
|
8
|
+
return {
|
|
9
|
+
path: "pepr.ts",
|
|
10
|
+
data: `import { PeprModule } from "pepr";
|
|
11
|
+
import cfg from "./package.json";
|
|
12
|
+
import { HelloPepr } from "./capabilities/hello-pepr";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This is the main entrypoint for the Pepr module. It is the file that is run when the module is started.
|
|
16
|
+
* This is where you register your configurations and capabilities with the module.
|
|
17
|
+
*/
|
|
18
|
+
new PeprModule(cfg, [
|
|
19
|
+
// "HelloPepr" is a demo capability that is included with Pepr. You can remove it if you want.
|
|
20
|
+
HelloPepr,
|
|
21
|
+
|
|
22
|
+
// Your additional capabilities go here
|
|
23
|
+
]);
|
|
24
|
+
`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function genPkgJSON(opts) {
|
|
28
|
+
// Generate a random UUID for the module based on the module name
|
|
29
|
+
const uuid = uuidv5(opts.name, uuidv4());
|
|
30
|
+
// Generate a name for the module based on the module name
|
|
31
|
+
const name = sanitizeName(opts.name);
|
|
32
|
+
// Make typescript a dev dependency
|
|
33
|
+
const { typescript } = dependencies;
|
|
34
|
+
const data = {
|
|
35
|
+
name,
|
|
36
|
+
version: "0.0.1",
|
|
37
|
+
description: opts.description,
|
|
38
|
+
keywords: ["pepr", "k8s", "policy-engine", "pepr-module", "security"],
|
|
39
|
+
pepr: {
|
|
40
|
+
name: opts.name.trim(),
|
|
41
|
+
version,
|
|
42
|
+
uuid,
|
|
43
|
+
onError: opts.errorBehavior,
|
|
44
|
+
alwaysIgnore: {
|
|
45
|
+
namespaces: [],
|
|
46
|
+
labels: [],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
scripts: {
|
|
50
|
+
build: "pepr build",
|
|
51
|
+
start: "pepr dev",
|
|
52
|
+
},
|
|
53
|
+
dependencies: {
|
|
54
|
+
pepr: `^${version}`,
|
|
55
|
+
},
|
|
56
|
+
devDependencies: {
|
|
57
|
+
typescript,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
data,
|
|
62
|
+
path: "package.json",
|
|
63
|
+
print: inspect(data, false, 5, true),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export const tsConfig = {
|
|
67
|
+
path: "tsconfig.json",
|
|
68
|
+
data: {
|
|
69
|
+
compilerOptions: {
|
|
70
|
+
esModuleInterop: true,
|
|
71
|
+
lib: ["ES2020"],
|
|
72
|
+
moduleResolution: "node",
|
|
73
|
+
resolveJsonModule: true,
|
|
74
|
+
rootDir: ".",
|
|
75
|
+
strict: false,
|
|
76
|
+
target: "ES2020",
|
|
77
|
+
},
|
|
78
|
+
include: ["**/*.ts"],
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
export const gitIgnore = {
|
|
82
|
+
path: ".gitignore",
|
|
83
|
+
data: `# Ignore node_modules
|
|
84
|
+
node_modules
|
|
85
|
+
dist
|
|
86
|
+
`,
|
|
87
|
+
};
|
|
88
|
+
export const prettierRC = {
|
|
89
|
+
path: ".prettierrc",
|
|
90
|
+
data: {
|
|
91
|
+
arrowParens: "avoid",
|
|
92
|
+
bracketSameLine: false,
|
|
93
|
+
bracketSpacing: true,
|
|
94
|
+
embeddedLanguageFormatting: "auto",
|
|
95
|
+
insertPragma: false,
|
|
96
|
+
printWidth: 80,
|
|
97
|
+
quoteProps: "as-needed",
|
|
98
|
+
requirePragma: false,
|
|
99
|
+
semi: true,
|
|
100
|
+
tabWidth: 2,
|
|
101
|
+
useTabs: false,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
export const readme = {
|
|
105
|
+
path: "README.md",
|
|
106
|
+
data: `# Pepr Module
|
|
107
|
+
|
|
108
|
+
This is a Pepr module. It is a module that can be used with the [Pepr]() framework.
|
|
109
|
+
|
|
110
|
+
The \`capabilities\` directory contains all the capabilities for this module. By default,
|
|
111
|
+
a capability is a single typescript file in the format of \`capability-name.ts\` that is
|
|
112
|
+
imported in the root \`pepr.ts\` file as \`import { HelloPepr } from "./capabilities/hello-pepr";\`.
|
|
113
|
+
Because this is typescript, you can organize this however you choose, e.g. creating a sub-folder
|
|
114
|
+
per-capability or common logic in shared files or folders.
|
|
115
|
+
|
|
116
|
+
Example Structure:
|
|
117
|
+
|
|
118
|
+
\`\`\`
|
|
119
|
+
Module Root
|
|
120
|
+
├── package.json
|
|
121
|
+
├── pepr.ts
|
|
122
|
+
└── capabilities
|
|
123
|
+
├── example-one.ts
|
|
124
|
+
├── example-three.ts
|
|
125
|
+
└── example-two.ts
|
|
126
|
+
\`\`\`
|
|
127
|
+
`,
|
|
128
|
+
};
|
|
129
|
+
export const capabilityHelloPeprTS = {
|
|
130
|
+
path: "hello-pepr.ts",
|
|
131
|
+
data: `import { Capability, a } from "pepr";
|
|
132
|
+
|
|
133
|
+
export const HelloPepr = new Capability({
|
|
134
|
+
name: "hello-pepr",
|
|
135
|
+
description: "A simple example capability to show how things work.",
|
|
136
|
+
namespaces: ["pepr-demo"],
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Use the 'When' function to create a new Capability Action
|
|
140
|
+
const { When } = HelloPepr;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* This is a single Capability Action. They can be in the same file or put imported from other files.
|
|
144
|
+
* In this exmaple, when a ConfigMap is created with the name \`example-1\`, then add a label and annotation.
|
|
145
|
+
*
|
|
146
|
+
* Equivelant to manually running:
|
|
147
|
+
* \`kubectl label configmap example-1 pepr=was-here\`
|
|
148
|
+
* \`kubectl annotate configmap example-1 pepr.dev=annotations-work-too\`
|
|
149
|
+
*/
|
|
150
|
+
When(a.ConfigMap)
|
|
151
|
+
.IsCreated()
|
|
152
|
+
.WithName("example-1")
|
|
153
|
+
.Then(request =>
|
|
154
|
+
request
|
|
155
|
+
.SetLabel("pepr", "was-here")
|
|
156
|
+
.SetAnnotation("pepr.dev", "annotations-work-too")
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* This Capabiility Action does the exact same changes for example-2, except this time it uses the \`.ThenSet()\` feature.
|
|
161
|
+
* You can stack multiple \`.Then()\` calls, but only a single \`.ThenSet()\`
|
|
162
|
+
*/
|
|
163
|
+
When(a.ConfigMap)
|
|
164
|
+
.IsCreated()
|
|
165
|
+
.WithName("example-2")
|
|
166
|
+
.ThenSet({
|
|
167
|
+
metadata: {
|
|
168
|
+
labels: {
|
|
169
|
+
pepr: "was-here",
|
|
170
|
+
},
|
|
171
|
+
annotations: {
|
|
172
|
+
"pepr.dev": "annotations-work-too",
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* This Capability Action combines different styles. Unlike the previous actions, this one will look for any ConfigMap
|
|
179
|
+
* in the \`pepr-demo\` namespace that has the label \`change=by-label\`. Note that all conditions added such as \`WithName()\`,
|
|
180
|
+
* \`WithLabel()\`, \`InNamespace()\`, are ANDs so all conditions must be true for the request to be procssed.
|
|
181
|
+
*/
|
|
182
|
+
When(a.ConfigMap)
|
|
183
|
+
.IsCreated()
|
|
184
|
+
.WithLabel("change", "by-label")
|
|
185
|
+
.Then(request => {
|
|
186
|
+
// The K8s object e are going to mutate
|
|
187
|
+
const cm = request.Raw;
|
|
188
|
+
|
|
189
|
+
// Get the username and uid of the K8s reuest
|
|
190
|
+
const { username, uid } = request.Request.userInfo;
|
|
191
|
+
|
|
192
|
+
// Store some data about the request in the configmap
|
|
193
|
+
cm.data["username"] = username;
|
|
194
|
+
cm.data["uid"] = uid;
|
|
195
|
+
|
|
196
|
+
// You can still mix other ways of making changes too
|
|
197
|
+
request.SetAnnotation("pepr.dev", "making-waves");
|
|
198
|
+
});
|
|
199
|
+
`,
|
|
200
|
+
};
|
|
201
|
+
export const capabilitySnippet = {
|
|
202
|
+
path: "pepr.code-snippets",
|
|
203
|
+
data: `{
|
|
204
|
+
"Create a new Pepr capability": {
|
|
205
|
+
"prefix": "create pepr capability",
|
|
206
|
+
"body": [
|
|
207
|
+
"import { Capability, a } from 'pepr';",
|
|
208
|
+
"",
|
|
209
|
+
"export const $\{TM_FILENAME_BASE/(.*)/$\{1:/pascalcase}/} = new Capability({",
|
|
210
|
+
"\\tname: '$\{TM_FILENAME_BASE}',",
|
|
211
|
+
"\\tdescription: '$\{1:A brief description of this capability.}',",
|
|
212
|
+
"\\tnamespaces: [$\{2:}],",
|
|
213
|
+
"});",
|
|
214
|
+
"",
|
|
215
|
+
"// Use the 'When' function to create a new Capability Action",
|
|
216
|
+
"const { When } = $\{TM_FILENAME_BASE/(.*)/$\{1:/pascalcase}/};",
|
|
217
|
+
"",
|
|
218
|
+
"// When(a.<Kind>).Is<Event>().Then(change => change.<changes>",
|
|
219
|
+
"When($\{3:})"
|
|
220
|
+
],
|
|
221
|
+
"description": "Creates a new Pepr capability with a specified description, and optional namespaces, and adds a When statement for the specified value."
|
|
222
|
+
}
|
|
223
|
+
}`,
|
|
224
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize a user input name to be used as a pepr module directory name
|
|
3
|
+
*
|
|
4
|
+
* @param name the user input name
|
|
5
|
+
* @returns the sanitized name
|
|
6
|
+
*/
|
|
7
|
+
export declare function sanitizeName(name: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a directory and throws an error if it already exists
|
|
10
|
+
*
|
|
11
|
+
* @param dir - The directory to create
|
|
12
|
+
*/
|
|
13
|
+
export declare function createDir(dir: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Write data to a file on disk
|
|
16
|
+
* @param path - The path to the file
|
|
17
|
+
* @param data - The data to write
|
|
18
|
+
* @returns A promise that resolves when the file has been written
|
|
19
|
+
*/
|
|
20
|
+
export declare function write(path: string, data: unknown): Promise<void>;
|