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 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
- This will create a new directory tree called `demo/hello-world` with the following structure:
43
+ https://user-images.githubusercontent.com/882485/230897379-0bb57dff-9832-479f-8733-79e103703135.mp4
46
44
 
47
- ### demo/hello-world/index.ts
45
+ Alternatively, you can use the `pepr new <capability-name>` command to this:
48
46
 
49
- ```typescript
50
- import "./test-mutations";
47
+ ```
48
+ pepr new hello-world
51
49
  ```
52
50
 
53
- ### demo/hello-world/index.ts
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 { When } = new Capability({
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pepr",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Kubernetes application engine",
5
5
  "author": "Defense Unicorns",
6
6
  "homepage": "https://github.com/defenseunicorns/pepr",
@@ -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
- .action(async () => {
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.capabilitySnippet.path), templates_1.capabilitySnippet.data);
37
- await (0, utils_1.write)((0, path_1.resolve)(dirName, "capabilities", templates_1.capabilityHelloPeprTS.path), templates_1.capabilityHelloPeprTS.data);
38
- // run npm install from the new directory
39
- process.chdir(dirName);
40
- (0, child_process_1.execSync)("npm install", {
41
- stdio: "inherit",
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 capabilityHelloPeprTS: {
75
+ export declare const samplesYaml: {
76
76
  path: string;
77
77
  data: string;
78
78
  };
79
- export declare const capabilitySnippet: {
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.capabilitySnippet = exports.capabilityHelloPeprTS = exports.readme = exports.prettierRC = exports.gitIgnore = exports.tsConfig = exports.genPkgJSON = exports.genPeprTS = void 0;
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
- node_modules
90
- dist
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.capabilityHelloPeprTS = {
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\`. Note that all conditions added such as \`WithName()\`,
185
- * \`WithLabel()\`, \`InNamespace()\`, are ANDs so all conditions must be true for the request to be procssed.
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
- .IsCreated()
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.capabilitySnippet = {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pepr",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Kubernetes application engine",
5
5
  "author": "Defense Unicorns",
6
6
  "homepage": "https://github.com/defenseunicorns/pepr",
package/cli.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import "./src/cli";