pepr 0.1.26 → 0.1.27

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/pepr-cli.js CHANGED
@@ -18,7 +18,7 @@ var util = require('util');
18
18
  var uuid = require('uuid');
19
19
  var commander = require('commander');
20
20
 
21
- var version = "0.1.26";
21
+ var version = "0.1.27";
22
22
 
23
23
  // SPDX-License-Identifier: Apache-2.0
24
24
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
@@ -1117,9 +1117,9 @@ const capabilitySnippet = {
1117
1117
  "import { Capability, a } from 'pepr';",
1118
1118
  "",
1119
1119
  "export const $\{TM_FILENAME_BASE/(.*)/$\{1:/pascalcase}/} = new Capability({",
1120
- "\tname: '$\{TM_FILENAME_BASE}',",
1121
- "\tdescription: '$\{1:A brief description of this capability.}',",
1122
- "\tnamespaces: [$\{2:}],",
1120
+ "\\tname: '$\{TM_FILENAME_BASE}',",
1121
+ "\\tdescription: '$\{1:A brief description of this capability.}',",
1122
+ "\\tnamespaces: [$\{2:}],",
1123
1123
  "});",
1124
1124
  "",
1125
1125
  "// Use the 'When' function to create a new Capability Action",
package/dist/pepr-core.js CHANGED
@@ -42,7 +42,6 @@ var upstream = /*#__PURE__*/Object.freeze({
42
42
  CustomResourceDefinition: dist.V1CustomResourceDefinition,
43
43
  DaemonSet: dist.V1DaemonSet,
44
44
  Deployment: dist.V1Deployment,
45
- Endpoint: dist.V1Endpoint,
46
45
  EndpointSlice: dist.V1EndpointSlice,
47
46
  HorizontalPodAutoscaler: dist.V1HorizontalPodAutoscaler,
48
47
  Ingress: dist.V1Ingress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pepr",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "Kubernetes application engine",
5
5
  "author": "Defense Unicorns",
6
6
  "homepage": "https://github.com/defenseunicorns/pepr",
package/tsconfig.json CHANGED
@@ -1,6 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "baseUrl": ".",
4
+ "declaration": true,
5
+ "declarationDir": "dist",
4
6
  "esModuleInterop": true,
5
7
  "lib": ["ES2020"],
6
8
  "moduleResolution": "node",
package/CODEOWNERS DELETED
@@ -1,6 +0,0 @@
1
- * @jeff-mccoy @bdw617
2
-
3
- # Additional privileged files
4
- /CODEOWNERS @jeff-mccoy @runyontr
5
- /cosign.pub @jeff-mccoy @runyontr
6
- /LICENSE @jeff-mccoy @runyontr
package/index.ts DELETED
@@ -1,7 +0,0 @@
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
-
6
- export { a, PeprModule, Capability, Log };
7
-
@@ -1,150 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import { modelToGroupVersionKind } from "./k8s";
5
- import logger from "./logger";
6
- import {
7
- BindToAction,
8
- Binding,
9
- BindingFilter,
10
- BindingWithName,
11
- CapabilityAction,
12
- CapabilityCfg,
13
- DeepPartial,
14
- Event,
15
- GenericClass,
16
- HookPhase,
17
- WhenSelector,
18
- } from "./types";
19
-
20
- /**
21
- * A capability is a unit of functionality that can be registered with the Pepr runtime.
22
- */
23
- export class Capability implements CapabilityCfg {
24
- private _name: string;
25
- private _description: string;
26
- private _namespaces?: string[] | undefined;
27
-
28
- // Currently everything is considered a mutation
29
- private _mutateOrValidate = HookPhase.mutate;
30
-
31
- private _bindings: Binding[] = [];
32
-
33
- get bindings(): Binding[] {
34
- return this._bindings;
35
- }
36
-
37
- get name() {
38
- return this._name;
39
- }
40
-
41
- get description() {
42
- return this._description;
43
- }
44
-
45
- get namespaces() {
46
- return this._namespaces || [];
47
- }
48
-
49
- get mutateOrValidate() {
50
- return this._mutateOrValidate;
51
- }
52
-
53
- constructor(cfg: CapabilityCfg) {
54
- this._name = cfg.name;
55
- this._description = cfg.description;
56
- this._namespaces = cfg.namespaces;
57
- logger.info(`Capability ${this._name} registered`);
58
- logger.debug(cfg);
59
- }
60
-
61
- /**
62
- * The When method is used to register a capability action to be executed when a Kubernetes resource is
63
- * processed by Pepr. The action will be executed if the resource matches the specified kind and any
64
- * filters that are applied.
65
- *
66
- * @param model if using a custom KubernetesObject not available in `a.*`, specify the GroupVersionKind
67
- * @returns
68
- */
69
- When = <T extends GenericClass>(model: T): WhenSelector<T> => {
70
- const binding: Binding = {
71
- // If the kind is not specified, use the default KubernetesObject
72
- kind: modelToGroupVersionKind(model.name),
73
- filters: {
74
- name: "",
75
- namespaces: [],
76
- labels: {},
77
- annotations: {},
78
- },
79
- callback: () => null,
80
- };
81
-
82
- const prefix = `${this._name}: ${model.name}`;
83
-
84
- logger.info(`Binding created`, prefix);
85
-
86
- const Then = (cb: CapabilityAction<T>): BindToAction<T> => {
87
- logger.info(`Binding action created`, prefix);
88
- logger.debug(cb.toString(), prefix);
89
- // Push the binding to the list of bindings for this capability as a new BindingAction
90
- // with the callback function to preserve
91
- this._bindings.push({
92
- ...binding,
93
- callback: cb,
94
- });
95
-
96
- // Now only allow adding actions to the same binding
97
- return { Then };
98
- };
99
-
100
- const ThenSet = (merge: DeepPartial<InstanceType<T>>): BindToAction<T> => {
101
- // Add the new action to the binding
102
- Then(req => req.Merge(merge));
103
-
104
- return { Then };
105
- };
106
-
107
- function InNamespace(...namespaces: string[]): BindingWithName<T> {
108
- logger.debug(`Add namespaces filter ${namespaces}`, prefix);
109
- binding.filters.namespaces.push(...namespaces);
110
- return { WithLabel, WithAnnotation, WithName, Then, ThenSet };
111
- }
112
-
113
- function WithName(name: string): BindingFilter<T> {
114
- logger.debug(`Add name filter ${name}`, prefix);
115
- binding.filters.name = name;
116
- return { WithLabel, WithAnnotation, Then, ThenSet };
117
- }
118
-
119
- function WithLabel(key: string, value = ""): BindingFilter<T> {
120
- logger.debug(`Add label filter ${key}=${value}`, prefix);
121
- binding.filters.labels[key] = value;
122
- return { WithLabel, WithAnnotation, Then, ThenSet };
123
- }
124
-
125
- const WithAnnotation = (key: string, value = ""): BindingFilter<T> => {
126
- logger.debug(`Add annotation filter ${key}=${value}`, prefix);
127
- binding.filters.annotations[key] = value;
128
- return { WithLabel, WithAnnotation, Then, ThenSet };
129
- };
130
-
131
- const bindEvent = (event: Event) => {
132
- binding.event = event;
133
- return {
134
- InNamespace,
135
- Then,
136
- ThenSet,
137
- WithAnnotation,
138
- WithLabel,
139
- WithName,
140
- };
141
- };
142
-
143
- return {
144
- IsCreatedOrUpdated: () => bindEvent(Event.CreateOrUpdate),
145
- IsCreated: () => bindEvent(Event.Create),
146
- IsUpdated: () => bindEvent(Event.Update),
147
- IsDeleted: () => bindEvent(Event.Delete),
148
- };
149
- };
150
- }
@@ -1,92 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import express from "express";
5
- import fs from "fs";
6
- import https from "https";
7
- import { ModuleConfig } from "./types";
8
- import { Capability } from "./capability";
9
- import { processor } from "./processor";
10
-
11
- // Load SSL certificate and key
12
- const options = {
13
- key: fs.readFileSync(process.env.SSL_KEY_PATH || "/etc/certs/tls.key"),
14
- cert: fs.readFileSync(process.env.SSL_CERT_PATH || "/etc/certs/tls.crt"),
15
- };
16
-
17
- export class Controller {
18
- private readonly app = express();
19
-
20
- constructor(private readonly config: ModuleConfig, private readonly capabilities: Capability[]) {
21
- // Middleware for logging requests
22
- this.app.use(this.logger);
23
-
24
- // Middleware for parsing JSON
25
- this.app.use(express.json());
26
-
27
- // Health check endpoint
28
- this.app.get("/healthz", this.healthz);
29
-
30
- // Mutate endpoint
31
- this.app.post("/mutate", this.mutate);
32
- }
33
-
34
- /** Start the webhook server */
35
- public startServer = (port: number) => {
36
- // Create HTTPS server
37
- https.createServer(options, this.app).listen(port, () => {
38
- console.log(`Server listening on port ${port}`);
39
- });
40
- };
41
-
42
- private logger = (req: express.Request, res: express.Response, next: express.NextFunction) => {
43
- const startTime = Date.now();
44
-
45
- res.on("finish", () => {
46
- const now = new Date().toISOString();
47
- const elapsedTime = Date.now() - startTime;
48
- const message = `[${now}] ${req.method} ${req.originalUrl} - ${res.statusCode} - ${elapsedTime} ms\n`;
49
-
50
- res.statusCode >= 400 ? console.error(message) : console.info(message);
51
- });
52
-
53
- next();
54
- };
55
-
56
- private healthz = (req: express.Request, res: express.Response) => {
57
- try {
58
- res.send("OK");
59
- } catch (err) {
60
- console.error(err);
61
- res.status(500).send("Internal Server Error");
62
- }
63
- };
64
-
65
- private mutate = (req: express.Request, res: express.Response) => {
66
- try {
67
- const name = req.body?.request?.name || "";
68
- const namespace = req.body?.request?.namespace || "";
69
- const gvk = req.body?.request?.kind || { group: "", version: "", kind: "" };
70
-
71
- console.log(`Mutate request: ${gvk.group}/${gvk.version}/${gvk.kind}`);
72
- name && console.log(` ${namespace}/${name}\n`);
73
-
74
- // @todo: make this actually do something
75
- const response = processor(this.config, this.capabilities, req.body.request);
76
- console.debug(response);
77
-
78
- // Send a no prob bob response
79
- res.send({
80
- apiVersion: "admission.k8s.io/v1",
81
- kind: "AdmissionReview",
82
- response: {
83
- uid: req.body.request.uid,
84
- allowed: true,
85
- },
86
- });
87
- } catch (err) {
88
- console.error(err);
89
- res.status(500).send("Internal Server Error");
90
- }
91
- };
92
- }
package/src/lib/filter.ts DELETED
@@ -1,52 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- import { Request } from "./k8s";
5
- import logger from "./logger";
6
- import { Binding } from "./types";
7
-
8
- /**
9
- * shouldSkipRequest determines if a request should be skipped based on the binding filters.
10
- *
11
- * @param binding the capability action binding
12
- * @param req the incoming request
13
- * @returns
14
- */
15
- export function shouldSkipRequest(binding: Binding, req: Request) {
16
- const { group, kind, version } = binding.kind;
17
- const { namespaces, labels, annotations } = binding.filters;
18
- const { metadata } = req.object;
19
-
20
- if (kind !== req.kind.kind) {
21
- return true;
22
- }
23
-
24
- if (group && group !== req.kind.group) {
25
- return true;
26
- }
27
-
28
- if (version && version !== req.kind.version) {
29
- return true;
30
- }
31
-
32
- if (namespaces.length && !namespaces.includes(req.namespace || "")) {
33
- logger.debug("Namespace does not match");
34
- return true;
35
- }
36
-
37
- for (const [key, value] of Object.entries(labels)) {
38
- if (metadata?.labels?.[key] !== value) {
39
- logger.debug(`${metadata?.labels?.[key]} does not match ${value}`);
40
- return true;
41
- }
42
- }
43
-
44
- for (const [key, value] of Object.entries(annotations)) {
45
- if (metadata?.annotations?.[key] !== value) {
46
- logger.debug(`${metadata?.annotations?.[key]} does not match ${value}`);
47
- return true;
48
- }
49
- }
50
-
51
- return false;
52
- }
@@ -1,10 +0,0 @@
1
- // SPDX-License-Identifier: Apache-2.0
2
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
-
4
- // Export kinds as a single object
5
- import * as kind from "./upstream";
6
- export { kind as a };
7
-
8
- export { modelToGroupVersionKind, gvkMap } from "./kinds";
9
-
10
- export * from "./types";