pepr 0.1.30 → 0.1.32
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 +13 -12
- package/dist/package.json +1 -1
- package/dist/src/cli/index.js +3 -2
- package/dist/src/cli/init/index.js +26 -8
- package/dist/src/cli/init/templates.d.ts +6 -2
- package/dist/src/cli/init/templates.js +68 -10
- package/dist/src/lib/controller.js +1 -5
- package/dist/src/lib/processor.js +1 -1
- package/package.json +1 -1
- package/cli.ts +0 -3
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ Capabilities are logical groupings of actions, which are the atomic units of cha
|
|
|
18
18
|
|
|
19
19
|
Imagine Pepr as a smart home system where different devices communicate with each other. Pepr provides instructions, simplifying the management of the smart home. The project enables both expert and novice capability authors to improve management and interactions within the Kubernetes environment, making its features accessible to everyone.
|
|
20
20
|
|
|
21
|
+
https://user-images.githubusercontent.com/882485/230895880-c5623077-f811-4870-bb9f-9bb8e5edc118.mp4
|
|
22
|
+
|
|
21
23
|
## Concepts
|
|
22
24
|
|
|
23
25
|
### Module
|
|
@@ -26,7 +28,7 @@ A module is the top-level collection of capabilities. It is a single, complete T
|
|
|
26
28
|
|
|
27
29
|
### Capability
|
|
28
30
|
|
|
29
|
-
A capability is set of related CapabilityActions that work together to achieve a specific transformation or operation on Kubernetes resources. Capabilities are user-defined and can include one or more CapabilityActions. They are defined within a Pepr module and can be used in both MutatingWebhookConfigurations and ValidatingWebhookConfigurations. A Capability can have a specific scope, such as mutating or validating, and can be reused in multiple Pepr modules.
|
|
31
|
+
A capability is set of related CapabilityActions that work together to achieve a specific transformation or operation on Kubernetes resources. Capabilities are user-defined and can include one or more CapabilityActions. They are defined within a Pepr module and can be used in both MutatingWebhookConfigurations and ValidatingWebhookConfigurations. A Capability can have a specific scope, such as mutating or validating, and can be reused in multiple Pepr modules.
|
|
30
32
|
|
|
31
33
|
### CapabilityAction
|
|
32
34
|
|
|
@@ -36,26 +38,22 @@ For example, a CapabilityAction could be responsible for adding a specific label
|
|
|
36
38
|
|
|
37
39
|
## Example
|
|
38
40
|
|
|
39
|
-
Define a new capability:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
pepr new hello-world -d demo
|
|
43
|
-
```
|
|
41
|
+
Define a new capability can be done via [VSCode Snippet](https://code.visualstudio.com/docs/editor/userdefinedsnippets): create a file `capabilities/your-capability-name.ts` and then type `create` in the file, a suggestion should prompt you to generate the content from there.
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
https://user-images.githubusercontent.com/882485/230897379-0bb57dff-9832-479f-8733-79e103703135.mp4
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
Alternatively, you can use the `pepr new <capability-name>` command to this:
|
|
48
46
|
|
|
49
|
-
```
|
|
50
|
-
|
|
47
|
+
```
|
|
48
|
+
pepr new hello-world
|
|
51
49
|
```
|
|
52
50
|
|
|
53
|
-
|
|
51
|
+
This will create a new file called `capabilities/hello-world.ts` with the following contents:
|
|
54
52
|
|
|
55
53
|
```typescript
|
|
56
54
|
import { Capability, a } from "pepr";
|
|
57
55
|
|
|
58
|
-
const
|
|
56
|
+
export const HelloWorld = new Capability({
|
|
59
57
|
// The unique name of the capability
|
|
60
58
|
name: "hello-world",
|
|
61
59
|
// A short description of the capability
|
|
@@ -63,6 +61,9 @@ const { When } = new Capability({
|
|
|
63
61
|
// Limit what namespaces the capability can be used in (optional)
|
|
64
62
|
namespaces: [],
|
|
65
63
|
});
|
|
64
|
+
|
|
65
|
+
// Use the 'When' function to create a new Capability Action
|
|
66
|
+
const { When } = HelloWorld;
|
|
66
67
|
```
|
|
67
68
|
|
|
68
69
|
Next, we need to define some actions to perform when specific Kubernetes resources are created, updated or deleted in the cluster. Pepr provides a set of actions that can be used to react to Kubernetes resources, such as `a.Pod`, `a.Deployment`, `a.CronJob`, etc. These actions can be chained together to create complex conditions, such as `a.Pod.IsCreated().InNamespace("default")` or `a.Deployment.IsUpdated().WithLabel("changeme=true")`. Below is an example of a capability that reacts to the creation of a Deployment resource:
|
package/dist/package.json
CHANGED
package/dist/src/cli/index.js
CHANGED
|
@@ -26,8 +26,9 @@ program
|
|
|
26
26
|
});
|
|
27
27
|
(0, init_1.default)(program);
|
|
28
28
|
(0, build_1.default)(program);
|
|
29
|
-
(0, capability_1.default)(program);
|
|
30
|
-
(0, test_1.default)(program);
|
|
31
29
|
(0, deploy_1.default)(program);
|
|
32
30
|
(0, dev_1.default)(program);
|
|
31
|
+
// @todo: finish/re-evaluate these commands
|
|
32
|
+
(0, test_1.default)(program);
|
|
33
|
+
(0, capability_1.default)(program);
|
|
33
34
|
program.parse();
|
|
@@ -15,7 +15,9 @@ function default_1(program) {
|
|
|
15
15
|
program
|
|
16
16
|
.command("init")
|
|
17
17
|
.description("Initialize a new Pepr Module")
|
|
18
|
-
|
|
18
|
+
// skip auto npm install and git init
|
|
19
|
+
.option("--skip-post-init", "Skip npm install, git init and VSCode launch")
|
|
20
|
+
.action(async (opts) => {
|
|
19
21
|
const response = await (0, walkthrough_1.walkthrough)();
|
|
20
22
|
const dirName = (0, utils_1.sanitizeName)(response.name);
|
|
21
23
|
const packageJSON = (0, templates_1.genPkgJSON)(response);
|
|
@@ -33,13 +35,29 @@ function default_1(program) {
|
|
|
33
35
|
await (0, utils_1.write)((0, path_1.resolve)(dirName, templates_1.readme.path), templates_1.readme.data);
|
|
34
36
|
await (0, utils_1.write)((0, path_1.resolve)(dirName, templates_1.tsConfig.path), templates_1.tsConfig.data);
|
|
35
37
|
await (0, utils_1.write)((0, path_1.resolve)(dirName, peprTS.path), peprTS.data);
|
|
36
|
-
await (0, utils_1.write)((0, path_1.resolve)(dirName, ".vscode", templates_1.
|
|
37
|
-
await (0, utils_1.write)((0, path_1.resolve)(dirName, "capabilities", templates_1.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
await (0, utils_1.write)((0, path_1.resolve)(dirName, ".vscode", templates_1.snippet.path), templates_1.snippet.data);
|
|
39
|
+
await (0, utils_1.write)((0, path_1.resolve)(dirName, "capabilities", templates_1.samplesYaml.path), templates_1.samplesYaml.data);
|
|
40
|
+
await (0, utils_1.write)((0, path_1.resolve)(dirName, "capabilities", templates_1.helloPeprTS.path), templates_1.helloPeprTS.data);
|
|
41
|
+
if (!opts.skipPostInit) {
|
|
42
|
+
// run npm install from the new directory
|
|
43
|
+
process.chdir(dirName);
|
|
44
|
+
(0, child_process_1.execSync)("npm install", {
|
|
45
|
+
stdio: "inherit",
|
|
46
|
+
});
|
|
47
|
+
// setup git
|
|
48
|
+
(0, child_process_1.execSync)("git init", {
|
|
49
|
+
stdio: "inherit",
|
|
50
|
+
});
|
|
51
|
+
// try to open vscode
|
|
52
|
+
try {
|
|
53
|
+
(0, child_process_1.execSync)("code .", {
|
|
54
|
+
stdio: "inherit",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
// vscode not found, do nothing
|
|
59
|
+
}
|
|
60
|
+
}
|
|
43
61
|
console.log(`New Pepr module created at ${dirName}`);
|
|
44
62
|
console.log(`Open VSCode or your editor of choice in ${dirName} to get started!`);
|
|
45
63
|
}
|
|
@@ -72,11 +72,15 @@ export declare const readme: {
|
|
|
72
72
|
path: string;
|
|
73
73
|
data: string;
|
|
74
74
|
};
|
|
75
|
-
export declare const
|
|
75
|
+
export declare const samplesYaml: {
|
|
76
76
|
path: string;
|
|
77
77
|
data: string;
|
|
78
78
|
};
|
|
79
|
-
export declare const
|
|
79
|
+
export declare const helloPeprTS: {
|
|
80
|
+
path: string;
|
|
81
|
+
data: string;
|
|
82
|
+
};
|
|
83
|
+
export declare const snippet: {
|
|
80
84
|
path: string;
|
|
81
85
|
data: string;
|
|
82
86
|
};
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.
|
|
5
|
+
exports.snippet = exports.helloPeprTS = exports.samplesYaml = exports.readme = exports.prettierRC = exports.gitIgnore = exports.tsConfig = exports.genPkgJSON = exports.genPeprTS = void 0;
|
|
6
6
|
const util_1 = require("util");
|
|
7
7
|
const uuid_1 = require("uuid");
|
|
8
8
|
const package_json_1 = require("../../../package.json");
|
|
9
9
|
const utils_1 = require("./utils");
|
|
10
|
+
const client_node_1 = require("@kubernetes/client-node");
|
|
10
11
|
function genPeprTS() {
|
|
11
12
|
return {
|
|
12
13
|
path: "pepr.ts",
|
|
@@ -23,7 +24,7 @@ new PeprModule(cfg, [
|
|
|
23
24
|
HelloPepr,
|
|
24
25
|
|
|
25
26
|
// Your additional capabilities go here
|
|
26
|
-
]);
|
|
27
|
+
]);
|
|
27
28
|
`,
|
|
28
29
|
};
|
|
29
30
|
}
|
|
@@ -85,9 +86,10 @@ exports.tsConfig = {
|
|
|
85
86
|
};
|
|
86
87
|
exports.gitIgnore = {
|
|
87
88
|
path: ".gitignore",
|
|
88
|
-
data: `# Ignore node_modules
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
data: `# Ignore node_modules and Pepr build artifacts
|
|
90
|
+
node_modules
|
|
91
|
+
dist
|
|
92
|
+
insecure*
|
|
91
93
|
`,
|
|
92
94
|
};
|
|
93
95
|
exports.prettierRC = {
|
|
@@ -131,10 +133,65 @@ Module Root
|
|
|
131
133
|
\`\`\`
|
|
132
134
|
`,
|
|
133
135
|
};
|
|
134
|
-
exports.
|
|
136
|
+
exports.samplesYaml = {
|
|
137
|
+
path: "hello-pepr.samples.yaml",
|
|
138
|
+
data: [
|
|
139
|
+
{
|
|
140
|
+
apiVersion: "v1",
|
|
141
|
+
kind: "Namespace",
|
|
142
|
+
metadata: {
|
|
143
|
+
name: "pepr-demo",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
apiVersion: "v1",
|
|
148
|
+
kind: "ConfigMap",
|
|
149
|
+
metadata: {
|
|
150
|
+
name: "example-1",
|
|
151
|
+
namespace: "pepr-demo",
|
|
152
|
+
},
|
|
153
|
+
data: {
|
|
154
|
+
key: "ex-1-val",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
apiVersion: "v1",
|
|
159
|
+
kind: "ConfigMap",
|
|
160
|
+
metadata: {
|
|
161
|
+
name: "example-2",
|
|
162
|
+
namespace: "pepr-demo",
|
|
163
|
+
},
|
|
164
|
+
data: {
|
|
165
|
+
key: "ex-2-val",
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
apiVersion: "v1",
|
|
170
|
+
kind: "ConfigMap",
|
|
171
|
+
metadata: {
|
|
172
|
+
name: "example-3",
|
|
173
|
+
namespace: "pepr-demo",
|
|
174
|
+
labels: {
|
|
175
|
+
change: "by-label",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
data: {
|
|
179
|
+
key: "ex-3-val",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
]
|
|
183
|
+
.map(r => (0, client_node_1.dumpYaml)(r, { noRefs: true }))
|
|
184
|
+
.join("---\n"),
|
|
185
|
+
};
|
|
186
|
+
exports.helloPeprTS = {
|
|
135
187
|
path: "hello-pepr.ts",
|
|
136
188
|
data: `import { Capability, a } from "pepr";
|
|
137
189
|
|
|
190
|
+
/**
|
|
191
|
+
* The HelloPepr is an example capability to demonstrate some general concepts of Pepr.
|
|
192
|
+
* To test this capability you can run \`pepr dev\` and then run the following command:
|
|
193
|
+
* \`kubectl apply -f capabilities/hello-pepr.samples.yaml\`
|
|
194
|
+
*/
|
|
138
195
|
export const HelloPepr = new Capability({
|
|
139
196
|
name: "hello-pepr",
|
|
140
197
|
description: "A simple example capability to show how things work.",
|
|
@@ -181,11 +238,12 @@ When(a.ConfigMap)
|
|
|
181
238
|
|
|
182
239
|
/**
|
|
183
240
|
* This Capability Action combines different styles. Unlike the previous actions, this one will look for any ConfigMap
|
|
184
|
-
* in the \`pepr-demo\` namespace that has the label \`change=by-label
|
|
185
|
-
* \`WithLabel()\`, \`InNamespace()\`, are ANDs so all conditions must be true
|
|
241
|
+
* in the \`pepr-demo\` namespace that has the label \`change=by-label\` during either CREATE or UPDATE. Note that all
|
|
242
|
+
* conditions added such as \`WithName()\`, \`WithLabel()\`, \`InNamespace()\`, are ANDs so all conditions must be true
|
|
243
|
+
* for the request to be procssed.
|
|
186
244
|
*/
|
|
187
245
|
When(a.ConfigMap)
|
|
188
|
-
.
|
|
246
|
+
.IsCreatedOrUpdated()
|
|
189
247
|
.WithLabel("change", "by-label")
|
|
190
248
|
.Then(request => {
|
|
191
249
|
// The K8s object e are going to mutate
|
|
@@ -203,7 +261,7 @@ When(a.ConfigMap)
|
|
|
203
261
|
});
|
|
204
262
|
`,
|
|
205
263
|
};
|
|
206
|
-
exports.
|
|
264
|
+
exports.snippet = {
|
|
207
265
|
path: "pepr.code-snippets",
|
|
208
266
|
data: `{
|
|
209
267
|
"Create a new Pepr capability": {
|
|
@@ -53,17 +53,13 @@ class Controller {
|
|
|
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
|
-
// @todo: make this actually do something
|
|
57
56
|
const response = (0, processor_1.processor)(this.config, this.capabilities, req.body.request);
|
|
58
57
|
console.debug(response);
|
|
59
58
|
// Send a no prob bob response
|
|
60
59
|
res.send({
|
|
61
60
|
apiVersion: "admission.k8s.io/v1",
|
|
62
61
|
kind: "AdmissionReview",
|
|
63
|
-
response
|
|
64
|
-
uid: req.body.request.uid,
|
|
65
|
-
allowed: true,
|
|
66
|
-
},
|
|
62
|
+
response,
|
|
67
63
|
});
|
|
68
64
|
}
|
|
69
65
|
catch (err) {
|
|
@@ -14,7 +14,6 @@ function processor(config, capabilities, req) {
|
|
|
14
14
|
const wrapped = new request_1.RequestWrapper(req);
|
|
15
15
|
const response = {
|
|
16
16
|
uid: req.uid,
|
|
17
|
-
patchType: "JSONPatch",
|
|
18
17
|
warnings: [],
|
|
19
18
|
allowed: false,
|
|
20
19
|
};
|
|
@@ -61,6 +60,7 @@ function processor(config, capabilities, req) {
|
|
|
61
60
|
const patches = (0, fast_json_patch_1.compare)(req.object, wrapped.Raw);
|
|
62
61
|
// Only add the patch if there are patches to apply
|
|
63
62
|
if (patches.length > 0) {
|
|
63
|
+
response.patchType = "JSONPatch";
|
|
64
64
|
response.patch = JSON.stringify(patches);
|
|
65
65
|
}
|
|
66
66
|
// Remove the warnings array if it's empty
|
package/package.json
CHANGED
package/cli.ts
DELETED