pepr 0.1.34 → 0.1.36

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/README.md CHANGED
@@ -10,6 +10,22 @@ Pepr is on a mission to save Kubernetes from the tyranny of YAML, intimidating g
10
10
  - Write capabilities in TypeScript and bundle them for in-cluster processing in [NodeJS](https://nodejs.org/).
11
11
  - React to cluster resources by mutating them, creating new Kubernetes resources, or performing arbitrary exec/API operations.
12
12
 
13
+ ## Wow too many words! tl;dr;
14
+ ```bash
15
+ # Install Pepr (you can also use npx)
16
+ npm i -g pepr
17
+
18
+ # Initialize a new Pepr Module
19
+ pepr init
20
+
21
+ # Follow the prompts...
22
+
23
+ # Within the new project dir, start playing with things
24
+ pepr dev
25
+
26
+ # Be amazed and ⭐️ this repo
27
+ ```
28
+
13
29
  Pepr is an open-source project that helps IT Ops teams of all skill levels manage and modify resources in a Kubernetes (K8s) cluster using TypeScript. Kubernetes simplifies the management of multiple computers working together to run and scale applications. Pepr acts as a smart assistant, automatically changing or validating parts of the system as needed.
14
30
 
15
31
  TypeScript is used to create Pepr capabilities, benefiting from its error-catching and clean code features, but without requiring specialized software engineering experience or prior Typescript knowledge. Pepr also provides a user-friendly interface for writing commands in plain English in a [Fluent Interface](https://en.wikipedia.org/wiki/Fluent_interface) style.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,12 @@
1
- import { Capability } from './src/lib/capability';
2
- import { a } from './src/lib/k8s';
3
- import Log from './src/lib/logger';
4
- import { PeprModule } from './src/lib/module';
5
- export { a, PeprModule, Capability, Log };
1
+ import k8s from "@kubernetes/client-node";
2
+ import utils from "ramda";
3
+ import { fetch, fetchRaw } from "src/lib/fetch";
4
+ import { Capability } from "./src/lib/capability";
5
+ import { a } from "./src/lib/k8s";
6
+ import Log from "./src/lib/logger";
7
+ import { PeprModule } from "./src/lib/module";
8
+ import type * as KubernetesClientNode from "@kubernetes/client-node";
9
+ import type * as RamdaUtils from "ramda";
10
+ export { a,
11
+ /** PeprModule is used to setup a complete Pepr Module: `new PeprModule(cfg, {...capabilities})` */
12
+ PeprModule, Capability, Log, utils, fetch, fetchRaw, k8s, RamdaUtils, KubernetesClientNode, };
package/dist/index.js CHANGED
@@ -3,7 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Log = exports.Capability = exports.PeprModule = exports.a = void 0;
6
+ exports.k8s = exports.fetchRaw = exports.fetch = exports.utils = exports.Log = exports.Capability = exports.PeprModule = exports.a = void 0;
7
+ const client_node_1 = __importDefault(require("@kubernetes/client-node"));
8
+ exports.k8s = client_node_1.default;
9
+ const ramda_1 = __importDefault(require("ramda"));
10
+ exports.utils = ramda_1.default;
11
+ const fetch_1 = require("src/lib/fetch");
12
+ Object.defineProperty(exports, "fetch", { enumerable: true, get: function () { return fetch_1.fetch; } });
13
+ Object.defineProperty(exports, "fetchRaw", { enumerable: true, get: function () { return fetch_1.fetchRaw; } });
7
14
  const capability_1 = require("./src/lib/capability");
8
15
  Object.defineProperty(exports, "Capability", { enumerable: true, get: function () { return capability_1.Capability; } });
9
16
  const k8s_1 = require("./src/lib/k8s");
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pepr",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Kubernetes application engine",
5
5
  "author": "Defense Unicorns",
6
6
  "homepage": "https://github.com/defenseunicorns/pepr",
@@ -25,13 +25,13 @@
25
25
  },
26
26
  "scripts": {
27
27
  "preversion": "npm run prepublishOnly",
28
- "build": "tsc -p tsconfig.build.json",
28
+ "build": "rm -fr dist/* && tsc -p tsconfig.build.json",
29
29
  "test": "ava",
30
30
  "lint": "npx eslint src",
31
31
  "lint:fix": "npm run lint -- --fix",
32
32
  "prettier": "npx prettier src --check",
33
33
  "prettier:fix": "npm run prettier -- --write",
34
- "prepublishOnly": "rm -fr dist/* && npm run lint:fix && npm run prettier:fix && npm run test && npm run build",
34
+ "prepublishOnly": "npm run lint:fix && npm run prettier:fix && npm run test && npm run build",
35
35
  "e2e-dev-setup": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0'",
36
36
  "e2e-dev": "npm run build && docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev && node dist/pepr-cli.js deploy -f -i pepr:dev"
37
37
  },
@@ -45,25 +45,28 @@
45
45
  "commander": "^10.0.0",
46
46
  "express": "^4.18.2",
47
47
  "fast-json-patch": "^3.1.1",
48
+ "node-fetch": "^2.6.9",
48
49
  "node-forge": "^1.3.1",
49
50
  "prettier": "^2.8.7",
50
51
  "prompts": "^2.4.2",
51
52
  "ramda": "^0.29.0",
52
53
  "rollup": "^3.20.2",
54
+ "ts-node": "^10.9.1",
53
55
  "tslib": "^2.5.0",
54
56
  "typescript": "^5.0.2",
55
- "ts-node": "^10.9.1",
56
57
  "uuid": "^9.0.0"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@types/express": "^4.17.17",
61
+ "@types/node-fetch": "^2.6.3",
60
62
  "@types/node-forge": "^1.3.2",
61
63
  "@types/prompts": "^2.4.4",
62
64
  "@types/uuid": "^9.0.1",
63
65
  "@typescript-eslint/eslint-plugin": "^5.57.0",
64
66
  "@typescript-eslint/parser": "^5.57.0",
65
67
  "ava": "^5.2.0",
66
- "eslint": "^8.37.0"
68
+ "eslint": "^8.37.0",
69
+ "nock": "^13.3.0"
67
70
  },
68
71
  "ava": {
69
72
  "extensions": [
@@ -68,7 +68,7 @@ class Capability {
68
68
  };
69
69
  const ThenSet = (merge) => {
70
70
  // Add the new action to the binding
71
- Then(req => req.Merge(merge));
71
+ Then(async (req) => req.Merge(merge));
72
72
  return { Then };
73
73
  };
74
74
  function InNamespace(...namespaces) {
@@ -46,14 +46,14 @@ class Controller {
46
46
  res.status(500).send("Internal Server Error");
47
47
  }
48
48
  };
49
- this.mutate = (req, res) => {
49
+ this.mutate = async (req, res) => {
50
50
  try {
51
51
  const name = req.body?.request?.name || "";
52
52
  const namespace = req.body?.request?.namespace || "";
53
53
  const gvk = req.body?.request?.kind || { group: "", version: "", kind: "" };
54
54
  console.log(`Mutate request: ${gvk.group}/${gvk.version}/${gvk.kind}`);
55
55
  name && console.log(` ${namespace}/${name}\n`);
56
- const response = (0, processor_1.processor)(this.config, this.capabilities, req.body.request);
56
+ const response = await (0, processor_1.processor)(this.config, this.capabilities, req.body.request);
57
57
  console.debug(response);
58
58
  // Send a no prob bob response
59
59
  res.send({
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" />
2
+ import f, { RequestInfo, RequestInit } from "node-fetch";
3
+ export { f as fetchRaw };
4
+ /**
5
+ * Perform an async HTTP call and return the parsed JSON response, optionally
6
+ * as a specific type.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * fetch<string[]>("https://example.com/api/foo");
11
+ * ```
12
+ *
13
+ * @param url The URL or Request object to fetch
14
+ * @param init Additional options for the request
15
+ * @returns
16
+ */
17
+ export declare function fetch<T>(url: URL | RequestInfo, init?: RequestInit): Promise<T>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.fetch = exports.fetchRaw = void 0;
9
+ const node_fetch_1 = __importDefault(require("node-fetch"));
10
+ exports.fetchRaw = node_fetch_1.default;
11
+ /**
12
+ * Perform an async HTTP call and return the parsed JSON response, optionally
13
+ * as a specific type.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * fetch<string[]>("https://example.com/api/foo");
18
+ * ```
19
+ *
20
+ * @param url The URL or Request object to fetch
21
+ * @param init Additional options for the request
22
+ * @returns
23
+ */
24
+ async function fetch(url, init) {
25
+ const resp = await (0, node_fetch_1.default)(url, init);
26
+ const data = await resp.json();
27
+ return data;
28
+ }
29
+ exports.fetch = fetch;
@@ -1,4 +1,5 @@
1
1
  import * as kind from "./upstream";
2
+ /** a is a colleciton of K8s types to be used within a CapabilityAction: `When(a.Configmap)` */
2
3
  export { kind as a };
3
4
  export { modelToGroupVersionKind, gvkMap } from "./kinds";
4
5
  export * from "./types";
@@ -1 +1,2 @@
1
+ /** a is a colleciton of K8s types to be used within a CapabilityAction: `When(a.Configmap)` */
1
2
  export { V1APIService as APIService, V1CertificateSigningRequest as CertificateSigningRequest, V1ConfigMap as ConfigMap, V1ControllerRevision as ControllerRevision, V1CronJob as CronJob, V1CSIDriver as CSIDriver, V1CSIStorageCapacity as CSIStorageCapacity, V1CustomResourceDefinition as CustomResourceDefinition, V1DaemonSet as DaemonSet, V1Deployment as Deployment, V1EndpointSlice as EndpointSlice, V1HorizontalPodAutoscaler as HorizontalPodAutoscaler, V1Ingress as Ingress, V1IngressClass as IngressClass, V1Job as Job, V1LimitRange as LimitRange, V1LocalSubjectAccessReview as LocalSubjectAccessReview, V1MutatingWebhookConfiguration as MutatingWebhookConfiguration, V1Namespace as Namespace, V1NetworkPolicy as NetworkPolicy, V1Node as Node, V1PersistentVolume as PersistentVolume, V1PersistentVolumeClaim as PersistentVolumeClaim, V1Pod as Pod, V1PodDisruptionBudget as PodDisruptionBudget, V1PodTemplate as PodTemplate, V1ReplicaSet as ReplicaSet, V1ReplicationController as ReplicationController, V1ResourceQuota as ResourceQuota, V1RuntimeClass as RuntimeClass, V1Secret as Secret, V1SelfSubjectAccessReview as SelfSubjectAccessReview, V1SelfSubjectRulesReview as SelfSubjectRulesReview, V1Service as Service, V1ServiceAccount as ServiceAccount, V1StatefulSet as StatefulSet, V1StorageClass as StorageClass, V1SubjectAccessReview as SubjectAccessReview, V1TokenReview as TokenReview, V1ValidatingWebhookConfiguration as ValidatingWebhookConfiguration, V1VolumeAttachment as VolumeAttachment, } from "@kubernetes/client-node/dist";
@@ -3,6 +3,7 @@
3
3
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.VolumeAttachment = exports.ValidatingWebhookConfiguration = exports.TokenReview = exports.SubjectAccessReview = exports.StorageClass = exports.StatefulSet = exports.ServiceAccount = exports.Service = exports.SelfSubjectRulesReview = exports.SelfSubjectAccessReview = exports.Secret = exports.RuntimeClass = exports.ResourceQuota = exports.ReplicationController = exports.ReplicaSet = exports.PodTemplate = exports.PodDisruptionBudget = exports.Pod = exports.PersistentVolumeClaim = exports.PersistentVolume = exports.Node = exports.NetworkPolicy = exports.Namespace = exports.MutatingWebhookConfiguration = exports.LocalSubjectAccessReview = exports.LimitRange = exports.Job = exports.IngressClass = exports.Ingress = exports.HorizontalPodAutoscaler = exports.EndpointSlice = exports.Deployment = exports.DaemonSet = exports.CustomResourceDefinition = exports.CSIStorageCapacity = exports.CSIDriver = exports.CronJob = exports.ControllerRevision = exports.ConfigMap = exports.CertificateSigningRequest = exports.APIService = void 0;
6
+ /** a is a colleciton of K8s types to be used within a CapabilityAction: `When(a.Configmap)` */
6
7
  var dist_1 = require("@kubernetes/client-node/dist");
7
8
  Object.defineProperty(exports, "APIService", { enumerable: true, get: function () { return dist_1.V1APIService; } });
8
9
  Object.defineProperty(exports, "CertificateSigningRequest", { enumerable: true, get: function () { return dist_1.V1CertificateSigningRequest; } });
@@ -50,5 +50,6 @@ export declare class Logger {
50
50
  private log;
51
51
  private colorize;
52
52
  }
53
- declare const _default: Logger;
54
- export default _default;
53
+ /** Log is an instance of Logger used to generate log entries. */
54
+ declare const Log: Logger;
55
+ export default Log;
@@ -117,4 +117,6 @@ class Logger {
117
117
  }
118
118
  }
119
119
  exports.Logger = Logger;
120
- exports.default = new Logger(LogLevel.info);
120
+ /** Log is an instance of Logger used to generate log entries. */
121
+ const Log = new Logger(LogLevel.info);
122
+ exports.default = Log;
@@ -1,12 +1,9 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
4
- var __importDefault = (this && this.__importDefault) || function (mod) {
5
- return (mod && mod.__esModule) ? mod : { "default": mod };
6
- };
7
4
  Object.defineProperty(exports, "__esModule", { value: true });
8
5
  exports.PeprModule = void 0;
9
- const ramda_1 = __importDefault(require("ramda"));
6
+ const index_1 = require("index");
10
7
  const controller_1 = require("./controller");
11
8
  const alwaysIgnore = {
12
9
  namespaces: ["kube-system", "pepr-system"],
@@ -19,7 +16,7 @@ class PeprModule {
19
16
  * @param config The configuration for the Pepr runtime
20
17
  */
21
18
  constructor({ description, pepr }, capabilities = [], deferStart = false) {
22
- const config = ramda_1.default.mergeDeepWith(ramda_1.default.concat, pepr, alwaysIgnore);
19
+ const config = index_1.utils.mergeDeepWith(index_1.utils.concat, pepr, alwaysIgnore);
23
20
  config.description = description;
24
21
  this._controller = new controller_1.Controller(config, capabilities);
25
22
  if (!deferStart) {
@@ -1,4 +1,4 @@
1
1
  import { Capability } from "./capability";
2
2
  import { Request, Response } from "./k8s/types";
3
3
  import { ModuleConfig } from "./types";
4
- export declare function processor(config: ModuleConfig, capabilities: Capability[], req: Request): Response;
4
+ export declare function processor(config: ModuleConfig, capabilities: Capability[], req: Request): Promise<Response>;
@@ -10,7 +10,7 @@ const fast_json_patch_1 = require("fast-json-patch");
10
10
  const filter_1 = require("./filter");
11
11
  const logger_1 = __importDefault(require("./logger"));
12
12
  const request_1 = require("./request");
13
- function processor(config, capabilities, req) {
13
+ async function processor(config, capabilities, req) {
14
14
  const wrapped = new request_1.RequestWrapper(req);
15
15
  const response = {
16
16
  uid: req.uid,
@@ -35,7 +35,7 @@ function processor(config, capabilities, req) {
35
35
  metadata.annotations[identifier] = "started";
36
36
  try {
37
37
  // Run the action
38
- action.callback(wrapped);
38
+ await action.callback(wrapped);
39
39
  // Add annotations to the request to indicate that the capability succeeded
40
40
  metadata.annotations[identifier] = "succeeded";
41
41
  }
@@ -1,32 +1,9 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
4
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
- if (k2 === undefined) k2 = k;
6
- var desc = Object.getOwnPropertyDescriptor(m, k);
7
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
- desc = { enumerable: true, get: function() { return m[k]; } };
9
- }
10
- Object.defineProperty(o, k2, desc);
11
- }) : (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- o[k2] = m[k];
14
- }));
15
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
- Object.defineProperty(o, "default", { enumerable: true, value: v });
17
- }) : function(o, v) {
18
- o["default"] = v;
19
- });
20
- var __importStar = (this && this.__importStar) || function (mod) {
21
- if (mod && mod.__esModule) return mod;
22
- var result = {};
23
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24
- __setModuleDefault(result, mod);
25
- return result;
26
- };
27
4
  Object.defineProperty(exports, "__esModule", { value: true });
28
5
  exports.RequestWrapper = void 0;
29
- const R = __importStar(require("ramda"));
6
+ const index_1 = require("index");
30
7
  /**
31
8
  * The RequestWrapper class provides methods to modify Kubernetes objects in the context
32
9
  * of a mutating webhook request.
@@ -62,7 +39,7 @@ class RequestWrapper {
62
39
  */
63
40
  constructor(input) {
64
41
  // Deep clone the object to prevent mutation of the original object
65
- this.Raw = R.clone(input.object);
42
+ this.Raw = index_1.utils.clone(input.object);
66
43
  // Store the input
67
44
  this._input = input;
68
45
  }
@@ -72,7 +49,7 @@ class RequestWrapper {
72
49
  * @param obj - The object to merge with the current resource.
73
50
  */
74
51
  Merge(obj) {
75
- this.Raw = R.mergeDeepRight(this.Raw, obj);
52
+ this.Raw = index_1.utils.mergeDeepRight(this.Raw, obj);
76
53
  }
77
54
  /**
78
55
  * Updates a label on the Kubernetes resource.
@@ -184,4 +184,4 @@ export type BindToActionOrSet<T extends GenericClass> = BindToAction<T> & {
184
184
  */
185
185
  ThenSet: (val: DeepPartial<InstanceType<T>>) => BindToAction<T>;
186
186
  };
187
- export type CapabilityAction<T extends GenericClass, K extends KubernetesObject = InstanceType<T>> = (req: RequestWrapper<K>) => void;
187
+ export type CapabilityAction<T extends GenericClass, K extends KubernetesObject = InstanceType<T>> = (req: RequestWrapper<K>) => Promise<void> | void | Promise<RequestWrapper<K>> | RequestWrapper<K>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pepr",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Kubernetes application engine",
5
5
  "author": "Defense Unicorns",
6
6
  "homepage": "https://github.com/defenseunicorns/pepr",
@@ -25,13 +25,13 @@
25
25
  },
26
26
  "scripts": {
27
27
  "preversion": "npm run prepublishOnly",
28
- "build": "tsc -p tsconfig.build.json",
28
+ "build": "rm -fr dist/* && tsc -p tsconfig.build.json",
29
29
  "test": "ava",
30
30
  "lint": "npx eslint src",
31
31
  "lint:fix": "npm run lint -- --fix",
32
32
  "prettier": "npx prettier src --check",
33
33
  "prettier:fix": "npm run prettier -- --write",
34
- "prepublishOnly": "rm -fr dist/* && npm run lint:fix && npm run prettier:fix && npm run test && npm run build",
34
+ "prepublishOnly": "npm run lint:fix && npm run prettier:fix && npm run test && npm run build",
35
35
  "e2e-dev-setup": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0'",
36
36
  "e2e-dev": "npm run build && docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev && node dist/pepr-cli.js deploy -f -i pepr:dev"
37
37
  },
@@ -45,25 +45,28 @@
45
45
  "commander": "^10.0.0",
46
46
  "express": "^4.18.2",
47
47
  "fast-json-patch": "^3.1.1",
48
+ "node-fetch": "^2.6.9",
48
49
  "node-forge": "^1.3.1",
49
50
  "prettier": "^2.8.7",
50
51
  "prompts": "^2.4.2",
51
52
  "ramda": "^0.29.0",
52
53
  "rollup": "^3.20.2",
54
+ "ts-node": "^10.9.1",
53
55
  "tslib": "^2.5.0",
54
56
  "typescript": "^5.0.2",
55
- "ts-node": "^10.9.1",
56
57
  "uuid": "^9.0.0"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@types/express": "^4.17.17",
61
+ "@types/node-fetch": "^2.6.3",
60
62
  "@types/node-forge": "^1.3.2",
61
63
  "@types/prompts": "^2.4.4",
62
64
  "@types/uuid": "^9.0.1",
63
65
  "@typescript-eslint/eslint-plugin": "^5.57.0",
64
66
  "@typescript-eslint/parser": "^5.57.0",
65
67
  "ava": "^5.2.0",
66
- "eslint": "^8.37.0"
68
+ "eslint": "^8.37.0",
69
+ "nock": "^13.3.0"
67
70
  },
68
71
  "ava": {
69
72
  "extensions": [