pepr 0.49.0 → 0.50.0-nightly.0
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/cli/crd/generate.d.ts.map +1 -1
- package/dist/cli/crd/messages.d.ts +11 -0
- package/dist/cli/crd/messages.d.ts.map +1 -0
- package/dist/cli/deploy.d.ts.map +1 -1
- package/dist/cli/docs/cli.helper.d.ts +12 -0
- package/dist/cli/docs/cli.helper.d.ts.map +1 -0
- package/dist/cli/docs/markdown.helper.d.ts +8 -0
- package/dist/cli/docs/markdown.helper.d.ts.map +1 -0
- package/dist/cli/format/format.helpers.d.ts.map +1 -0
- package/dist/cli/{format.d.ts → format/index.d.ts} +2 -2
- package/dist/cli/format/index.d.ts.map +1 -0
- package/dist/cli/init/templates.d.ts +12 -18
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli/update/index.d.ts +3 -0
- package/dist/cli/update/index.d.ts.map +1 -0
- package/dist/cli.js +321 -231
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts.map +1 -1
- package/dist/lib/assets/helm.d.ts.map +1 -1
- package/dist/lib/assets/ignoredNamespaces.d.ts +2 -0
- package/dist/lib/assets/ignoredNamespaces.d.ts.map +1 -0
- package/dist/lib/assets/webhooks.d.ts +0 -1
- package/dist/lib/assets/webhooks.d.ts.map +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib/core/module.d.ts.map +1 -1
- package/dist/lib/helpers.d.ts +1 -1
- package/dist/lib/helpers.d.ts.map +1 -1
- package/dist/lib/processors/mutate-processor.d.ts.map +1 -1
- package/dist/lib/processors/validate-processor.d.ts.map +1 -1
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib.js +86 -83
- package/dist/lib.js.map +4 -4
- package/dist/sdk/sdk.d.ts +2 -0
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +12 -10
- package/src/cli/build.ts +1 -1
- package/src/cli/crd/generate.ts +8 -7
- package/src/cli/crd/messages.ts +15 -0
- package/src/cli/deploy.ts +12 -2
- package/src/cli/{format.ts → format/index.ts} +2 -2
- package/src/cli/init/templates.ts +29 -3
- package/src/cli/{update.ts → update/index.ts} +30 -3
- package/src/lib/assets/assets.ts +7 -0
- package/src/lib/assets/helm.ts +28 -1
- package/src/lib/assets/ignoredNamespaces.ts +17 -0
- package/src/lib/assets/webhooks.ts +6 -17
- package/src/lib/assets/yaml/overridesFile.ts +7 -2
- package/src/lib/controller/createHooks.ts +1 -1
- package/src/lib/core/module.ts +3 -1
- package/src/lib/helpers.ts +16 -6
- package/src/lib/processors/mutate-processor.ts +6 -2
- package/src/lib/processors/validate-processor.ts +9 -3
- package/src/lib/types.ts +8 -0
- package/src/sdk/sdk.ts +10 -7
- package/src/templates/capabilities/hello-pepr.ts +1 -1
- package/src/templates/eslint.config.mjs +45 -0
- package/src/templates/package.json +10 -0
- package/dist/cli/format.d.ts.map +0 -1
- package/dist/cli/format.helpers.d.ts.map +0 -1
- package/dist/cli/update.d.ts +0 -3
- package/dist/cli/update.d.ts.map +0 -1
- package/src/templates/.eslintrc.json +0 -6
- package/src/templates/.eslintrc.template.json +0 -18
- /package/dist/cli/{format.helpers.d.ts → format/format.helpers.d.ts} +0 -0
- /package/src/cli/{format.helpers.ts → format/format.helpers.ts} +0 -0
package/dist/cli.js
CHANGED
|
@@ -103,17 +103,17 @@ var require_visit = __commonJS({
|
|
|
103
103
|
visit.BREAK = BREAK;
|
|
104
104
|
visit.SKIP = SKIP;
|
|
105
105
|
visit.REMOVE = REMOVE;
|
|
106
|
-
function visit_(key, node, visitor,
|
|
107
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
106
|
+
function visit_(key, node, visitor, path4) {
|
|
107
|
+
const ctrl = callVisitor(key, node, visitor, path4);
|
|
108
108
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
109
|
-
replaceNode(key,
|
|
110
|
-
return visit_(key, ctrl, visitor,
|
|
109
|
+
replaceNode(key, path4, ctrl);
|
|
110
|
+
return visit_(key, ctrl, visitor, path4);
|
|
111
111
|
}
|
|
112
112
|
if (typeof ctrl !== "symbol") {
|
|
113
113
|
if (identity.isCollection(node)) {
|
|
114
|
-
|
|
114
|
+
path4 = Object.freeze(path4.concat(node));
|
|
115
115
|
for (let i = 0; i < node.items.length; ++i) {
|
|
116
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
116
|
+
const ci = visit_(i, node.items[i], visitor, path4);
|
|
117
117
|
if (typeof ci === "number")
|
|
118
118
|
i = ci - 1;
|
|
119
119
|
else if (ci === BREAK)
|
|
@@ -124,13 +124,13 @@ var require_visit = __commonJS({
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
} else if (identity.isPair(node)) {
|
|
127
|
-
|
|
128
|
-
const ck = visit_("key", node.key, visitor,
|
|
127
|
+
path4 = Object.freeze(path4.concat(node));
|
|
128
|
+
const ck = visit_("key", node.key, visitor, path4);
|
|
129
129
|
if (ck === BREAK)
|
|
130
130
|
return BREAK;
|
|
131
131
|
else if (ck === REMOVE)
|
|
132
132
|
node.key = null;
|
|
133
|
-
const cv = visit_("value", node.value, visitor,
|
|
133
|
+
const cv = visit_("value", node.value, visitor, path4);
|
|
134
134
|
if (cv === BREAK)
|
|
135
135
|
return BREAK;
|
|
136
136
|
else if (cv === REMOVE)
|
|
@@ -151,17 +151,17 @@ var require_visit = __commonJS({
|
|
|
151
151
|
visitAsync.BREAK = BREAK;
|
|
152
152
|
visitAsync.SKIP = SKIP;
|
|
153
153
|
visitAsync.REMOVE = REMOVE;
|
|
154
|
-
async function visitAsync_(key, node, visitor,
|
|
155
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
154
|
+
async function visitAsync_(key, node, visitor, path4) {
|
|
155
|
+
const ctrl = await callVisitor(key, node, visitor, path4);
|
|
156
156
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
157
|
-
replaceNode(key,
|
|
158
|
-
return visitAsync_(key, ctrl, visitor,
|
|
157
|
+
replaceNode(key, path4, ctrl);
|
|
158
|
+
return visitAsync_(key, ctrl, visitor, path4);
|
|
159
159
|
}
|
|
160
160
|
if (typeof ctrl !== "symbol") {
|
|
161
161
|
if (identity.isCollection(node)) {
|
|
162
|
-
|
|
162
|
+
path4 = Object.freeze(path4.concat(node));
|
|
163
163
|
for (let i = 0; i < node.items.length; ++i) {
|
|
164
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
164
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path4);
|
|
165
165
|
if (typeof ci === "number")
|
|
166
166
|
i = ci - 1;
|
|
167
167
|
else if (ci === BREAK)
|
|
@@ -172,13 +172,13 @@ var require_visit = __commonJS({
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
} else if (identity.isPair(node)) {
|
|
175
|
-
|
|
176
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
175
|
+
path4 = Object.freeze(path4.concat(node));
|
|
176
|
+
const ck = await visitAsync_("key", node.key, visitor, path4);
|
|
177
177
|
if (ck === BREAK)
|
|
178
178
|
return BREAK;
|
|
179
179
|
else if (ck === REMOVE)
|
|
180
180
|
node.key = null;
|
|
181
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
181
|
+
const cv = await visitAsync_("value", node.value, visitor, path4);
|
|
182
182
|
if (cv === BREAK)
|
|
183
183
|
return BREAK;
|
|
184
184
|
else if (cv === REMOVE)
|
|
@@ -205,23 +205,23 @@ var require_visit = __commonJS({
|
|
|
205
205
|
}
|
|
206
206
|
return visitor;
|
|
207
207
|
}
|
|
208
|
-
function callVisitor(key, node, visitor,
|
|
208
|
+
function callVisitor(key, node, visitor, path4) {
|
|
209
209
|
if (typeof visitor === "function")
|
|
210
|
-
return visitor(key, node,
|
|
210
|
+
return visitor(key, node, path4);
|
|
211
211
|
if (identity.isMap(node))
|
|
212
|
-
return visitor.Map?.(key, node,
|
|
212
|
+
return visitor.Map?.(key, node, path4);
|
|
213
213
|
if (identity.isSeq(node))
|
|
214
|
-
return visitor.Seq?.(key, node,
|
|
214
|
+
return visitor.Seq?.(key, node, path4);
|
|
215
215
|
if (identity.isPair(node))
|
|
216
|
-
return visitor.Pair?.(key, node,
|
|
216
|
+
return visitor.Pair?.(key, node, path4);
|
|
217
217
|
if (identity.isScalar(node))
|
|
218
|
-
return visitor.Scalar?.(key, node,
|
|
218
|
+
return visitor.Scalar?.(key, node, path4);
|
|
219
219
|
if (identity.isAlias(node))
|
|
220
|
-
return visitor.Alias?.(key, node,
|
|
220
|
+
return visitor.Alias?.(key, node, path4);
|
|
221
221
|
return void 0;
|
|
222
222
|
}
|
|
223
|
-
function replaceNode(key,
|
|
224
|
-
const parent =
|
|
223
|
+
function replaceNode(key, path4, node) {
|
|
224
|
+
const parent = path4[path4.length - 1];
|
|
225
225
|
if (identity.isCollection(parent)) {
|
|
226
226
|
parent.items[key] = node;
|
|
227
227
|
} else if (identity.isPair(parent)) {
|
|
@@ -819,10 +819,10 @@ var require_Collection = __commonJS({
|
|
|
819
819
|
var createNode = require_createNode();
|
|
820
820
|
var identity = require_identity();
|
|
821
821
|
var Node2 = require_Node();
|
|
822
|
-
function collectionFromPath(schema,
|
|
822
|
+
function collectionFromPath(schema, path4, value) {
|
|
823
823
|
let v = value;
|
|
824
|
-
for (let i =
|
|
825
|
-
const k =
|
|
824
|
+
for (let i = path4.length - 1; i >= 0; --i) {
|
|
825
|
+
const k = path4[i];
|
|
826
826
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
827
827
|
const a = [];
|
|
828
828
|
a[k] = v;
|
|
@@ -841,7 +841,7 @@ var require_Collection = __commonJS({
|
|
|
841
841
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
842
842
|
});
|
|
843
843
|
}
|
|
844
|
-
var isEmptyPath = (
|
|
844
|
+
var isEmptyPath = (path4) => path4 == null || typeof path4 === "object" && !!path4[Symbol.iterator]().next().done;
|
|
845
845
|
var Collection = class extends Node2.NodeBase {
|
|
846
846
|
constructor(type, schema) {
|
|
847
847
|
super(type);
|
|
@@ -871,11 +871,11 @@ var require_Collection = __commonJS({
|
|
|
871
871
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
872
872
|
* that already exists in the map.
|
|
873
873
|
*/
|
|
874
|
-
addIn(
|
|
875
|
-
if (isEmptyPath(
|
|
874
|
+
addIn(path4, value) {
|
|
875
|
+
if (isEmptyPath(path4))
|
|
876
876
|
this.add(value);
|
|
877
877
|
else {
|
|
878
|
-
const [key, ...rest] =
|
|
878
|
+
const [key, ...rest] = path4;
|
|
879
879
|
const node = this.get(key, true);
|
|
880
880
|
if (identity.isCollection(node))
|
|
881
881
|
node.addIn(rest, value);
|
|
@@ -889,8 +889,8 @@ var require_Collection = __commonJS({
|
|
|
889
889
|
* Removes a value from the collection.
|
|
890
890
|
* @returns `true` if the item was found and removed.
|
|
891
891
|
*/
|
|
892
|
-
deleteIn(
|
|
893
|
-
const [key, ...rest] =
|
|
892
|
+
deleteIn(path4) {
|
|
893
|
+
const [key, ...rest] = path4;
|
|
894
894
|
if (rest.length === 0)
|
|
895
895
|
return this.delete(key);
|
|
896
896
|
const node = this.get(key, true);
|
|
@@ -904,8 +904,8 @@ var require_Collection = __commonJS({
|
|
|
904
904
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
905
905
|
* `true` (collections are always returned intact).
|
|
906
906
|
*/
|
|
907
|
-
getIn(
|
|
908
|
-
const [key, ...rest] =
|
|
907
|
+
getIn(path4, keepScalar) {
|
|
908
|
+
const [key, ...rest] = path4;
|
|
909
909
|
const node = this.get(key, true);
|
|
910
910
|
if (rest.length === 0)
|
|
911
911
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -923,8 +923,8 @@ var require_Collection = __commonJS({
|
|
|
923
923
|
/**
|
|
924
924
|
* Checks if the collection includes a value with the key `key`.
|
|
925
925
|
*/
|
|
926
|
-
hasIn(
|
|
927
|
-
const [key, ...rest] =
|
|
926
|
+
hasIn(path4) {
|
|
927
|
+
const [key, ...rest] = path4;
|
|
928
928
|
if (rest.length === 0)
|
|
929
929
|
return this.has(key);
|
|
930
930
|
const node = this.get(key, true);
|
|
@@ -934,8 +934,8 @@ var require_Collection = __commonJS({
|
|
|
934
934
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
935
935
|
* boolean to add/remove the item from the set.
|
|
936
936
|
*/
|
|
937
|
-
setIn(
|
|
938
|
-
const [key, ...rest] =
|
|
937
|
+
setIn(path4, value) {
|
|
938
|
+
const [key, ...rest] = path4;
|
|
939
939
|
if (rest.length === 0) {
|
|
940
940
|
this.set(key, value);
|
|
941
941
|
} else {
|
|
@@ -1481,7 +1481,7 @@ var require_stringify = __commonJS({
|
|
|
1481
1481
|
props.push(doc.directives.tagString(tag));
|
|
1482
1482
|
return props.join(" ");
|
|
1483
1483
|
}
|
|
1484
|
-
function
|
|
1484
|
+
function stringify2(item, ctx, onComment, onChompKeep) {
|
|
1485
1485
|
if (identity.isPair(item))
|
|
1486
1486
|
return item.toString(ctx, onComment, onChompKeep);
|
|
1487
1487
|
if (identity.isAlias(item)) {
|
|
@@ -1511,7 +1511,7 @@ var require_stringify = __commonJS({
|
|
|
1511
1511
|
${ctx.indent}${str}`;
|
|
1512
1512
|
}
|
|
1513
1513
|
exports2.createStringifyContext = createStringifyContext;
|
|
1514
|
-
exports2.stringify =
|
|
1514
|
+
exports2.stringify = stringify2;
|
|
1515
1515
|
}
|
|
1516
1516
|
});
|
|
1517
1517
|
|
|
@@ -1521,7 +1521,7 @@ var require_stringifyPair = __commonJS({
|
|
|
1521
1521
|
"use strict";
|
|
1522
1522
|
var identity = require_identity();
|
|
1523
1523
|
var Scalar = require_Scalar();
|
|
1524
|
-
var
|
|
1524
|
+
var stringify2 = require_stringify();
|
|
1525
1525
|
var stringifyComment = require_stringifyComment();
|
|
1526
1526
|
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
1527
1527
|
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
@@ -1543,7 +1543,7 @@ var require_stringifyPair = __commonJS({
|
|
|
1543
1543
|
});
|
|
1544
1544
|
let keyCommentDone = false;
|
|
1545
1545
|
let chompKeep = false;
|
|
1546
|
-
let str =
|
|
1546
|
+
let str = stringify2.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
1547
1547
|
if (!explicitKey && !ctx.inFlow && str.length > 1024) {
|
|
1548
1548
|
if (simpleKeys)
|
|
1549
1549
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
@@ -1595,7 +1595,7 @@ ${indent}:`;
|
|
|
1595
1595
|
ctx.indent = ctx.indent.substring(2);
|
|
1596
1596
|
}
|
|
1597
1597
|
let valueCommentDone = false;
|
|
1598
|
-
const valueStr =
|
|
1598
|
+
const valueStr = stringify2.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
1599
1599
|
let ws = " ";
|
|
1600
1600
|
if (keyComment || vsb || vcb) {
|
|
1601
1601
|
ws = vsb ? "\n" : "";
|
|
@@ -1733,7 +1733,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
1733
1733
|
"use strict";
|
|
1734
1734
|
var log = require_log();
|
|
1735
1735
|
var merge = require_merge();
|
|
1736
|
-
var
|
|
1736
|
+
var stringify2 = require_stringify();
|
|
1737
1737
|
var identity = require_identity();
|
|
1738
1738
|
var toJS = require_toJS();
|
|
1739
1739
|
function addPairToJSMap(ctx, map, { key, value }) {
|
|
@@ -1769,7 +1769,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
1769
1769
|
if (typeof jsKey !== "object")
|
|
1770
1770
|
return String(jsKey);
|
|
1771
1771
|
if (identity.isNode(key) && ctx?.doc) {
|
|
1772
|
-
const strCtx =
|
|
1772
|
+
const strCtx = stringify2.createStringifyContext(ctx.doc, {});
|
|
1773
1773
|
strCtx.anchors = /* @__PURE__ */ new Set();
|
|
1774
1774
|
for (const node of ctx.anchors.keys())
|
|
1775
1775
|
strCtx.anchors.add(node.anchor);
|
|
@@ -1836,12 +1836,12 @@ var require_stringifyCollection = __commonJS({
|
|
|
1836
1836
|
"node_modules/yaml/dist/stringify/stringifyCollection.js"(exports2) {
|
|
1837
1837
|
"use strict";
|
|
1838
1838
|
var identity = require_identity();
|
|
1839
|
-
var
|
|
1839
|
+
var stringify2 = require_stringify();
|
|
1840
1840
|
var stringifyComment = require_stringifyComment();
|
|
1841
1841
|
function stringifyCollection(collection, ctx, options) {
|
|
1842
1842
|
const flow = ctx.inFlow ?? collection.flow;
|
|
1843
|
-
const
|
|
1844
|
-
return
|
|
1843
|
+
const stringify3 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
1844
|
+
return stringify3(collection, ctx, options);
|
|
1845
1845
|
}
|
|
1846
1846
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
1847
1847
|
const { indent, options: { commentString } } = ctx;
|
|
@@ -1866,7 +1866,7 @@ var require_stringifyCollection = __commonJS({
|
|
|
1866
1866
|
}
|
|
1867
1867
|
}
|
|
1868
1868
|
chompKeep = false;
|
|
1869
|
-
let str2 =
|
|
1869
|
+
let str2 = stringify2.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
1870
1870
|
if (comment2)
|
|
1871
1871
|
str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2));
|
|
1872
1872
|
if (chompKeep && comment2)
|
|
@@ -1933,7 +1933,7 @@ ${indent}${line}` : "\n";
|
|
|
1933
1933
|
}
|
|
1934
1934
|
if (comment)
|
|
1935
1935
|
reqNewline = true;
|
|
1936
|
-
let str =
|
|
1936
|
+
let str = stringify2.stringify(item, itemCtx, () => comment = null);
|
|
1937
1937
|
if (i < items.length - 1)
|
|
1938
1938
|
str += ",";
|
|
1939
1939
|
if (comment)
|
|
@@ -3288,7 +3288,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3288
3288
|
"node_modules/yaml/dist/stringify/stringifyDocument.js"(exports2) {
|
|
3289
3289
|
"use strict";
|
|
3290
3290
|
var identity = require_identity();
|
|
3291
|
-
var
|
|
3291
|
+
var stringify2 = require_stringify();
|
|
3292
3292
|
var stringifyComment = require_stringifyComment();
|
|
3293
3293
|
function stringifyDocument(doc, options) {
|
|
3294
3294
|
const lines = [];
|
|
@@ -3303,7 +3303,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3303
3303
|
}
|
|
3304
3304
|
if (hasDirectives)
|
|
3305
3305
|
lines.push("---");
|
|
3306
|
-
const ctx =
|
|
3306
|
+
const ctx = stringify2.createStringifyContext(doc, options);
|
|
3307
3307
|
const { commentString } = ctx.options;
|
|
3308
3308
|
if (doc.commentBefore) {
|
|
3309
3309
|
if (lines.length !== 1)
|
|
@@ -3325,7 +3325,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3325
3325
|
contentComment = doc.contents.comment;
|
|
3326
3326
|
}
|
|
3327
3327
|
const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
|
|
3328
|
-
let body =
|
|
3328
|
+
let body = stringify2.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
|
|
3329
3329
|
if (contentComment)
|
|
3330
3330
|
body += stringifyComment.lineComment(body, "", commentString(contentComment));
|
|
3331
3331
|
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
|
|
@@ -3333,7 +3333,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3333
3333
|
} else
|
|
3334
3334
|
lines.push(body);
|
|
3335
3335
|
} else {
|
|
3336
|
-
lines.push(
|
|
3336
|
+
lines.push(stringify2.stringify(doc.contents, ctx));
|
|
3337
3337
|
}
|
|
3338
3338
|
if (doc.directives?.docEnd) {
|
|
3339
3339
|
if (doc.comment) {
|
|
@@ -3441,9 +3441,9 @@ var require_Document = __commonJS({
|
|
|
3441
3441
|
this.contents.add(value);
|
|
3442
3442
|
}
|
|
3443
3443
|
/** Adds a value to the document. */
|
|
3444
|
-
addIn(
|
|
3444
|
+
addIn(path4, value) {
|
|
3445
3445
|
if (assertCollection(this.contents))
|
|
3446
|
-
this.contents.addIn(
|
|
3446
|
+
this.contents.addIn(path4, value);
|
|
3447
3447
|
}
|
|
3448
3448
|
/**
|
|
3449
3449
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -3518,14 +3518,14 @@ var require_Document = __commonJS({
|
|
|
3518
3518
|
* Removes a value from the document.
|
|
3519
3519
|
* @returns `true` if the item was found and removed.
|
|
3520
3520
|
*/
|
|
3521
|
-
deleteIn(
|
|
3522
|
-
if (Collection.isEmptyPath(
|
|
3521
|
+
deleteIn(path4) {
|
|
3522
|
+
if (Collection.isEmptyPath(path4)) {
|
|
3523
3523
|
if (this.contents == null)
|
|
3524
3524
|
return false;
|
|
3525
3525
|
this.contents = null;
|
|
3526
3526
|
return true;
|
|
3527
3527
|
}
|
|
3528
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3528
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path4) : false;
|
|
3529
3529
|
}
|
|
3530
3530
|
/**
|
|
3531
3531
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -3540,10 +3540,10 @@ var require_Document = __commonJS({
|
|
|
3540
3540
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
3541
3541
|
* `true` (collections are always returned intact).
|
|
3542
3542
|
*/
|
|
3543
|
-
getIn(
|
|
3544
|
-
if (Collection.isEmptyPath(
|
|
3543
|
+
getIn(path4, keepScalar) {
|
|
3544
|
+
if (Collection.isEmptyPath(path4))
|
|
3545
3545
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3546
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3546
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path4, keepScalar) : void 0;
|
|
3547
3547
|
}
|
|
3548
3548
|
/**
|
|
3549
3549
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -3554,10 +3554,10 @@ var require_Document = __commonJS({
|
|
|
3554
3554
|
/**
|
|
3555
3555
|
* Checks if the document includes a value at `path`.
|
|
3556
3556
|
*/
|
|
3557
|
-
hasIn(
|
|
3558
|
-
if (Collection.isEmptyPath(
|
|
3557
|
+
hasIn(path4) {
|
|
3558
|
+
if (Collection.isEmptyPath(path4))
|
|
3559
3559
|
return this.contents !== void 0;
|
|
3560
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3560
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path4) : false;
|
|
3561
3561
|
}
|
|
3562
3562
|
/**
|
|
3563
3563
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -3574,13 +3574,13 @@ var require_Document = __commonJS({
|
|
|
3574
3574
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
3575
3575
|
* boolean to add/remove the item from the set.
|
|
3576
3576
|
*/
|
|
3577
|
-
setIn(
|
|
3578
|
-
if (Collection.isEmptyPath(
|
|
3577
|
+
setIn(path4, value) {
|
|
3578
|
+
if (Collection.isEmptyPath(path4)) {
|
|
3579
3579
|
this.contents = value;
|
|
3580
3580
|
} else if (this.contents == null) {
|
|
3581
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3581
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path4), value);
|
|
3582
3582
|
} else if (assertCollection(this.contents)) {
|
|
3583
|
-
this.contents.setIn(
|
|
3583
|
+
this.contents.setIn(path4, value);
|
|
3584
3584
|
}
|
|
3585
3585
|
}
|
|
3586
3586
|
/**
|
|
@@ -5463,7 +5463,7 @@ var require_cst_scalar = __commonJS({
|
|
|
5463
5463
|
var require_cst_stringify = __commonJS({
|
|
5464
5464
|
"node_modules/yaml/dist/parse/cst-stringify.js"(exports2) {
|
|
5465
5465
|
"use strict";
|
|
5466
|
-
var
|
|
5466
|
+
var stringify2 = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
|
|
5467
5467
|
function stringifyToken(token) {
|
|
5468
5468
|
switch (token.type) {
|
|
5469
5469
|
case "block-scalar": {
|
|
@@ -5516,7 +5516,7 @@ var require_cst_stringify = __commonJS({
|
|
|
5516
5516
|
res += stringifyToken(value);
|
|
5517
5517
|
return res;
|
|
5518
5518
|
}
|
|
5519
|
-
exports2.stringify =
|
|
5519
|
+
exports2.stringify = stringify2;
|
|
5520
5520
|
}
|
|
5521
5521
|
});
|
|
5522
5522
|
|
|
@@ -5535,9 +5535,9 @@ var require_cst_visit = __commonJS({
|
|
|
5535
5535
|
visit.BREAK = BREAK;
|
|
5536
5536
|
visit.SKIP = SKIP;
|
|
5537
5537
|
visit.REMOVE = REMOVE;
|
|
5538
|
-
visit.itemAtPath = (cst,
|
|
5538
|
+
visit.itemAtPath = (cst, path4) => {
|
|
5539
5539
|
let item = cst;
|
|
5540
|
-
for (const [field, index] of
|
|
5540
|
+
for (const [field, index] of path4) {
|
|
5541
5541
|
const tok = item?.[field];
|
|
5542
5542
|
if (tok && "items" in tok) {
|
|
5543
5543
|
item = tok.items[index];
|
|
@@ -5546,23 +5546,23 @@ var require_cst_visit = __commonJS({
|
|
|
5546
5546
|
}
|
|
5547
5547
|
return item;
|
|
5548
5548
|
};
|
|
5549
|
-
visit.parentCollection = (cst,
|
|
5550
|
-
const parent = visit.itemAtPath(cst,
|
|
5551
|
-
const field =
|
|
5549
|
+
visit.parentCollection = (cst, path4) => {
|
|
5550
|
+
const parent = visit.itemAtPath(cst, path4.slice(0, -1));
|
|
5551
|
+
const field = path4[path4.length - 1][0];
|
|
5552
5552
|
const coll = parent?.[field];
|
|
5553
5553
|
if (coll && "items" in coll)
|
|
5554
5554
|
return coll;
|
|
5555
5555
|
throw new Error("Parent collection not found");
|
|
5556
5556
|
};
|
|
5557
|
-
function _visit(
|
|
5558
|
-
let ctrl = visitor(item,
|
|
5557
|
+
function _visit(path4, item, visitor) {
|
|
5558
|
+
let ctrl = visitor(item, path4);
|
|
5559
5559
|
if (typeof ctrl === "symbol")
|
|
5560
5560
|
return ctrl;
|
|
5561
5561
|
for (const field of ["key", "value"]) {
|
|
5562
5562
|
const token = item[field];
|
|
5563
5563
|
if (token && "items" in token) {
|
|
5564
5564
|
for (let i = 0; i < token.items.length; ++i) {
|
|
5565
|
-
const ci = _visit(Object.freeze(
|
|
5565
|
+
const ci = _visit(Object.freeze(path4.concat([[field, i]])), token.items[i], visitor);
|
|
5566
5566
|
if (typeof ci === "number")
|
|
5567
5567
|
i = ci - 1;
|
|
5568
5568
|
else if (ci === BREAK)
|
|
@@ -5573,10 +5573,10 @@ var require_cst_visit = __commonJS({
|
|
|
5573
5573
|
}
|
|
5574
5574
|
}
|
|
5575
5575
|
if (typeof ctrl === "function" && field === "key")
|
|
5576
|
-
ctrl = ctrl(item,
|
|
5576
|
+
ctrl = ctrl(item, path4);
|
|
5577
5577
|
}
|
|
5578
5578
|
}
|
|
5579
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5579
|
+
return typeof ctrl === "function" ? ctrl(item, path4) : ctrl;
|
|
5580
5580
|
}
|
|
5581
5581
|
exports2.visit = visit;
|
|
5582
5582
|
}
|
|
@@ -7229,7 +7229,7 @@ var require_public_api = __commonJS({
|
|
|
7229
7229
|
}
|
|
7230
7230
|
return doc.toJS(Object.assign({ reviver: _reviver }, options));
|
|
7231
7231
|
}
|
|
7232
|
-
function
|
|
7232
|
+
function stringify2(value, replacer, options) {
|
|
7233
7233
|
let _replacer = null;
|
|
7234
7234
|
if (typeof replacer === "function" || Array.isArray(replacer)) {
|
|
7235
7235
|
_replacer = replacer;
|
|
@@ -7254,7 +7254,7 @@ var require_public_api = __commonJS({
|
|
|
7254
7254
|
exports2.parse = parse;
|
|
7255
7255
|
exports2.parseAllDocuments = parseAllDocuments;
|
|
7256
7256
|
exports2.parseDocument = parseDocument;
|
|
7257
|
-
exports2.stringify =
|
|
7257
|
+
exports2.stringify = stringify2;
|
|
7258
7258
|
}
|
|
7259
7259
|
});
|
|
7260
7260
|
|
|
@@ -7375,8 +7375,8 @@ var banner = `\x1B[107;40m\x1B[38;5;m \x1B[38;5;m \x1B[38;5;m \x1B[38;5;m \x1B[3
|
|
|
7375
7375
|
// src/cli/build.ts
|
|
7376
7376
|
var import_child_process3 = require("child_process");
|
|
7377
7377
|
var import_esbuild2 = require("esbuild");
|
|
7378
|
-
var
|
|
7379
|
-
var
|
|
7378
|
+
var import_fs10 = require("fs");
|
|
7379
|
+
var import_path4 = require("path");
|
|
7380
7380
|
|
|
7381
7381
|
// src/lib/assets/assets.ts
|
|
7382
7382
|
var import_crypto = __toESM(require("crypto"));
|
|
@@ -7529,7 +7529,13 @@ function watcherDeployTemplate(buildTimestamp) {
|
|
|
7529
7529
|
terminationGracePeriodSeconds: {{ .Values.watcher.terminationGracePeriodSeconds }}
|
|
7530
7530
|
serviceAccountName: {{ .Values.uuid }}
|
|
7531
7531
|
securityContext:
|
|
7532
|
-
{{- toYaml .Values.
|
|
7532
|
+
{{- toYaml .Values.watcher.securityContext | nindent 8 }}
|
|
7533
|
+
nodeSelector:
|
|
7534
|
+
{{- toYaml .Values.watcher.nodeSelector | nindent 8 }}
|
|
7535
|
+
tolerations:
|
|
7536
|
+
{{- toYaml .Values.watcher.tolerations | nindent 8 }}
|
|
7537
|
+
affinity:
|
|
7538
|
+
{{- toYaml .Values.watcher.affinity | nindent 8 }}
|
|
7533
7539
|
containers:
|
|
7534
7540
|
- name: watcher
|
|
7535
7541
|
image: {{ .Values.watcher.image }}
|
|
@@ -7613,6 +7619,27 @@ function admissionDeployTemplate(buildTimestamp) {
|
|
|
7613
7619
|
app: {{ .Values.uuid }}
|
|
7614
7620
|
pepr.dev/controller: admission
|
|
7615
7621
|
spec:
|
|
7622
|
+
{{- if or .Values.admission.antiAffinity .Values.admission.affinity }}
|
|
7623
|
+
affinity:
|
|
7624
|
+
{{- if .Values.admission.antiAffinity }}
|
|
7625
|
+
podAntiAffinity:
|
|
7626
|
+
requiredDuringSchedulingIgnoredDuringExecution:
|
|
7627
|
+
- labelSelector:
|
|
7628
|
+
matchExpressions:
|
|
7629
|
+
- key: pepr.dev/controller
|
|
7630
|
+
operator: In
|
|
7631
|
+
values:
|
|
7632
|
+
- admission
|
|
7633
|
+
topologyKey: "kubernetes.io/hostname"
|
|
7634
|
+
{{- end }}
|
|
7635
|
+
{{- if .Values.admission.affinity }}
|
|
7636
|
+
{{- toYaml .Values.admission.affinity | nindent 8 }}
|
|
7637
|
+
{{- end }}
|
|
7638
|
+
{{- end }}
|
|
7639
|
+
nodeSelector:
|
|
7640
|
+
{{- toYaml .Values.admission.nodeSelector | nindent 8 }}
|
|
7641
|
+
tolerations:
|
|
7642
|
+
{{- toYaml .Values.admission.tolerations | nindent 8 }}
|
|
7616
7643
|
terminationGracePeriodSeconds: {{ .Values.admission.terminationGracePeriodSeconds }}
|
|
7617
7644
|
priorityClassName: system-node-critical
|
|
7618
7645
|
serviceAccountName: {{ .Values.uuid }}
|
|
@@ -7709,12 +7736,12 @@ function serviceMonitorTemplate(name2, type) {
|
|
|
7709
7736
|
|
|
7710
7737
|
// src/lib/filesystemService.ts
|
|
7711
7738
|
var import_fs = require("fs");
|
|
7712
|
-
async function createDirectoryIfNotExists(
|
|
7739
|
+
async function createDirectoryIfNotExists(path4) {
|
|
7713
7740
|
try {
|
|
7714
|
-
await import_fs.promises.access(
|
|
7741
|
+
await import_fs.promises.access(path4);
|
|
7715
7742
|
} catch (error) {
|
|
7716
7743
|
if (error.code === "ENOENT") {
|
|
7717
|
-
await import_fs.promises.mkdir(
|
|
7744
|
+
await import_fs.promises.mkdir(path4, { recursive: true });
|
|
7718
7745
|
} else {
|
|
7719
7746
|
throw error;
|
|
7720
7747
|
}
|
|
@@ -7764,7 +7791,7 @@ var logger_default = Log;
|
|
|
7764
7791
|
// src/sdk/sdk.ts
|
|
7765
7792
|
var import_kubernetes_fluent_client = require("kubernetes-fluent-client");
|
|
7766
7793
|
function sanitizeResourceName(name2) {
|
|
7767
|
-
return name2.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0,
|
|
7794
|
+
return name2.toLowerCase().replace(/[^a-z0-9-]+/g, "-").slice(0, 63).replace(/^[^a-z0-9]+/, "").replace(/[^a-z0-9]+$/, "");
|
|
7768
7795
|
}
|
|
7769
7796
|
|
|
7770
7797
|
// src/lib/helpers.ts
|
|
@@ -7847,18 +7874,23 @@ function generateWatchNamespaceError(ignoredNamespaces, bindingNamespaces, capab
|
|
|
7847
7874
|
}
|
|
7848
7875
|
return err.replace(/\.([^ ])/g, ". $1");
|
|
7849
7876
|
}
|
|
7850
|
-
function namespaceComplianceValidator(capability, ignoredNamespaces) {
|
|
7877
|
+
function namespaceComplianceValidator(capability, ignoredNamespaces, watch) {
|
|
7851
7878
|
const { namespaces: capabilityNamespaces, bindings, name: name2 } = capability;
|
|
7879
|
+
const shouldInclude = (binding) => {
|
|
7880
|
+
if (watch === true) return !!binding.isWatch;
|
|
7881
|
+
if (watch === false) return !!binding.isMutate;
|
|
7882
|
+
return true;
|
|
7883
|
+
};
|
|
7852
7884
|
const bindingNamespaces = bindings.flatMap(
|
|
7853
|
-
(binding) => binding.filters.namespaces
|
|
7885
|
+
(binding) => shouldInclude(binding) ? binding.filters.namespaces || [] : []
|
|
7854
7886
|
);
|
|
7855
7887
|
const bindingRegexNamespaces = bindings.flatMap(
|
|
7856
|
-
(binding) => binding.filters.regexNamespaces || []
|
|
7888
|
+
(binding) => shouldInclude(binding) ? binding.filters.regexNamespaces || [] : []
|
|
7857
7889
|
);
|
|
7858
7890
|
const namespaceError = generateWatchNamespaceError(
|
|
7859
|
-
ignoredNamespaces
|
|
7891
|
+
ignoredNamespaces ?? [],
|
|
7860
7892
|
bindingNamespaces,
|
|
7861
|
-
capabilityNamespaces
|
|
7893
|
+
capabilityNamespaces ?? []
|
|
7862
7894
|
);
|
|
7863
7895
|
if (namespaceError !== "") {
|
|
7864
7896
|
throw new Error(
|
|
@@ -8039,11 +8071,28 @@ function storeRoleBinding(name2) {
|
|
|
8039
8071
|
|
|
8040
8072
|
// src/lib/assets/yaml/overridesFile.ts
|
|
8041
8073
|
var import_fs2 = require("fs");
|
|
8042
|
-
|
|
8074
|
+
|
|
8075
|
+
// src/lib/assets/ignoredNamespaces.ts
|
|
8076
|
+
function resolveIgnoreNamespaces(ignoredNSConfig = []) {
|
|
8077
|
+
const ignoredNSEnv = process.env.PEPR_ADDITIONAL_IGNORED_NAMESPACES;
|
|
8078
|
+
if (!ignoredNSEnv) {
|
|
8079
|
+
return ignoredNSConfig;
|
|
8080
|
+
}
|
|
8081
|
+
const namespaces = ignoredNSEnv.split(",").map((ns) => ns.trim());
|
|
8082
|
+
if (ignoredNSConfig) {
|
|
8083
|
+
namespaces.push(...ignoredNSConfig);
|
|
8084
|
+
}
|
|
8085
|
+
return namespaces.filter((ns) => ns.length > 0);
|
|
8086
|
+
}
|
|
8087
|
+
|
|
8088
|
+
// src/lib/assets/yaml/overridesFile.ts
|
|
8089
|
+
async function overridesFile({ hash, name: name2, image, config, apiPath, capabilities }, path4, imagePullSecrets) {
|
|
8043
8090
|
const rbacOverrides = clusterRole(name2, capabilities, config.rbacMode, config.rbac).rules;
|
|
8044
8091
|
const overrides = {
|
|
8045
8092
|
imagePullSecrets,
|
|
8046
|
-
additionalIgnoredNamespaces:
|
|
8093
|
+
additionalIgnoredNamespaces: resolveIgnoreNamespaces(
|
|
8094
|
+
config?.alwaysIgnore?.namespaces?.length ? config?.alwaysIgnore?.namespaces : config?.admission?.alwaysIgnore?.namespaces
|
|
8095
|
+
),
|
|
8047
8096
|
rbac: rbacOverrides,
|
|
8048
8097
|
secrets: {
|
|
8049
8098
|
apiPath: Buffer.from(apiPath).toString("base64")
|
|
@@ -8057,6 +8106,7 @@ async function overridesFile({ hash, name: name2, image, config, apiPath, capabi
|
|
|
8057
8106
|
},
|
|
8058
8107
|
uuid: name2,
|
|
8059
8108
|
admission: {
|
|
8109
|
+
antiAffinity: false,
|
|
8060
8110
|
terminationGracePeriodSeconds: 5,
|
|
8061
8111
|
failurePolicy: config.onError === "reject" ? "Fail" : "Ignore",
|
|
8062
8112
|
webhookTimeout: config.webhookTimeout,
|
|
@@ -8191,7 +8241,7 @@ async function overridesFile({ hash, name: name2, image, config, apiPath, capabi
|
|
|
8191
8241
|
}
|
|
8192
8242
|
}
|
|
8193
8243
|
};
|
|
8194
|
-
await import_fs2.promises.writeFile(
|
|
8244
|
+
await import_fs2.promises.writeFile(path4, (0, import_client_node.dumpYaml)(overrides, { noRefs: true, forceQuotes: true }));
|
|
8195
8245
|
}
|
|
8196
8246
|
|
|
8197
8247
|
// src/lib/assets/index.ts
|
|
@@ -8276,9 +8326,9 @@ function helmLayout(basePath, unique) {
|
|
|
8276
8326
|
|
|
8277
8327
|
// src/lib/assets/loader.ts
|
|
8278
8328
|
var import_child_process = require("child_process");
|
|
8279
|
-
function loadCapabilities(
|
|
8329
|
+
function loadCapabilities(path4) {
|
|
8280
8330
|
return new Promise((resolve6, reject) => {
|
|
8281
|
-
const program2 = (0, import_child_process.fork)(
|
|
8331
|
+
const program2 = (0, import_child_process.fork)(path4, {
|
|
8282
8332
|
env: {
|
|
8283
8333
|
...process.env,
|
|
8284
8334
|
LOG_LEVEL: "warn",
|
|
@@ -8396,12 +8446,12 @@ var Assets = class {
|
|
|
8396
8446
|
image;
|
|
8397
8447
|
buildTimestamp;
|
|
8398
8448
|
host;
|
|
8399
|
-
constructor(config,
|
|
8449
|
+
constructor(config, path4, imagePullSecrets, host) {
|
|
8400
8450
|
this.name = `pepr-${config.uuid}`;
|
|
8401
8451
|
this.imagePullSecrets = imagePullSecrets;
|
|
8402
8452
|
this.buildTimestamp = `${Date.now()}`;
|
|
8403
8453
|
this.config = config;
|
|
8404
|
-
this.path =
|
|
8454
|
+
this.path = path4;
|
|
8405
8455
|
this.host = host;
|
|
8406
8456
|
this.alwaysIgnore = config.alwaysIgnore;
|
|
8407
8457
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:v${config.peprVersion}`;
|
|
@@ -8413,12 +8463,18 @@ var Assets = class {
|
|
|
8413
8463
|
const timeout = typeof webhookTimeout === "number" ? webhookTimeout : 10;
|
|
8414
8464
|
await deployFunction(this, force, timeout);
|
|
8415
8465
|
}
|
|
8416
|
-
zarfYaml = (zarfYamlGenerator,
|
|
8417
|
-
zarfYamlChart = (zarfYamlGenerator,
|
|
8466
|
+
zarfYaml = (zarfYamlGenerator, path4) => zarfYamlGenerator(this, path4, "manifests");
|
|
8467
|
+
zarfYamlChart = (zarfYamlGenerator, path4) => zarfYamlGenerator(this, path4, "charts");
|
|
8418
8468
|
allYaml = async (yamlGenerationFunction, getDeploymentFunction, getWatcherFunction, imagePullSecret) => {
|
|
8419
8469
|
this.capabilities = await loadCapabilities(this.path);
|
|
8420
8470
|
for (const capability of this.capabilities) {
|
|
8421
8471
|
namespaceComplianceValidator(capability, this.alwaysIgnore?.namespaces);
|
|
8472
|
+
namespaceComplianceValidator(
|
|
8473
|
+
capability,
|
|
8474
|
+
this.config.admission?.alwaysIgnore?.namespaces,
|
|
8475
|
+
false
|
|
8476
|
+
);
|
|
8477
|
+
namespaceComplianceValidator(capability, this.config.watch?.alwaysIgnore?.namespaces, true);
|
|
8422
8478
|
}
|
|
8423
8479
|
const code = await import_fs3.promises.readFile(this.path);
|
|
8424
8480
|
const moduleHash = import_crypto.default.createHash("sha256").update(code).digest("hex");
|
|
@@ -8538,26 +8594,8 @@ var Assets = class {
|
|
|
8538
8594
|
var import_client_node3 = require("@kubernetes/client-node");
|
|
8539
8595
|
var import_util = require("util");
|
|
8540
8596
|
var import_uuid = require("uuid");
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
var eslintrc_template_default = {
|
|
8544
|
-
env: {
|
|
8545
|
-
browser: false,
|
|
8546
|
-
es2021: true
|
|
8547
|
-
},
|
|
8548
|
-
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
|
8549
|
-
parser: "@typescript-eslint/parser",
|
|
8550
|
-
parserOptions: {
|
|
8551
|
-
project: ["./tsconfig.json"],
|
|
8552
|
-
ecmaVersion: 2022
|
|
8553
|
-
},
|
|
8554
|
-
plugins: ["@typescript-eslint"],
|
|
8555
|
-
ignorePatterns: ["node_modules", "dist"],
|
|
8556
|
-
root: true,
|
|
8557
|
-
rules: {
|
|
8558
|
-
"@typescript-eslint/no-floating-promises": ["error"]
|
|
8559
|
-
}
|
|
8560
|
-
};
|
|
8597
|
+
var import_fs5 = require("fs");
|
|
8598
|
+
var import_path2 = __toESM(require("path"));
|
|
8561
8599
|
|
|
8562
8600
|
// src/templates/pepr.code-snippets.json
|
|
8563
8601
|
var pepr_code_snippets_default = {
|
|
@@ -8797,8 +8835,8 @@ var tsconfig_module_default = {
|
|
|
8797
8835
|
var gitIgnore = "# Ignore node_modules and Pepr build artifacts\nnode_modules\ndist\ninsecure*\n";
|
|
8798
8836
|
var readmeMd = '# Pepr Module\n\nThis is a Pepr Module. [Pepr](https://github.com/defenseunicorns/pepr) is a type-safe Kubernetes middleware system.\n\nThe `capabilities` directory contains all the capabilities for this module. By default,\na capability is a single typescript file in the format of `capability-name.ts` that is\nimported in the root `pepr.ts` file as `import { HelloPepr } from "./capabilities/hello-pepr";`.\nBecause this is typescript, you can organize this however you choose, e.g. creating a sub-folder\nper-capability or common logic in shared files or folders.\n\nExample Structure:\n\n```\nModule Root\n\u251C\u2500\u2500 package.json\n\u251C\u2500\u2500 pepr.ts\n\u2514\u2500\u2500 capabilities\n \u251C\u2500\u2500 example-one.ts\n \u251C\u2500\u2500 example-three.ts\n \u2514\u2500\u2500 example-two.ts\n```\n';
|
|
8799
8837
|
var peprTS = 'import { PeprModule } from "pepr";\n// cfg loads your pepr configuration from package.json\nimport cfg from "./package.json";\n\n// HelloPepr is a demo capability that is included with Pepr. Comment or delete the line below to remove it.\nimport { HelloPepr } from "./capabilities/hello-pepr";\n\n/**\n * This is the main entrypoint for this Pepr module. It is run when the module is started.\n * This is where you register your Pepr configurations and capabilities.\n */\nnew PeprModule(cfg, [\n // "HelloPepr" is a demo capability that is included with Pepr. Comment or delete the line below to remove it.\n HelloPepr,\n\n // Your additional capabilities go here\n]);\n';
|
|
8800
|
-
var helloPeprTS = 'import {\n Capability,\n K8s,\n Log,\n PeprMutateRequest,\n RegisterKind,\n a,\n fetch,\n fetchStatus,\n kind,\n} from "pepr";\nimport { MockAgent, setGlobalDispatcher } from "undici";\n\n/**\n * The HelloPepr Capability is an example capability to demonstrate some general concepts of Pepr.\n * To test this capability you run `pepr dev`and then run the following command:\n * `kubectl apply -f capabilities/hello-pepr.samples.yaml`\n */\nexport const HelloPepr = new Capability({\n name: "hello-pepr",\n description: "A simple example capability to show how things work.",\n namespaces: ["pepr-demo", "pepr-demo-2"],\n});\n\n// Use the \'When\' function to create a new action, use \'Store\' to persist data\nconst { When, Store } = HelloPepr;\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action removes the label `remove-me` when a Namespace is created.\n * Note we don\'t need to specify the namespace here, because we\'ve already specified\n * it in the Capability definition above.\n */\nWhen(a.Namespace)\n .IsCreated()\n .Mutate(ns => ns.RemoveLabel("remove-me"));\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Watch Action with K8s SSA (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action watches for the `pepr-demo-2` namespace to be created, then creates a ConfigMap with\n * the name `pepr-ssa-demo` and adds the namespace UID to the ConfigMap data. Because Pepr uses\n * server-side apply for this operation, the ConfigMap will be created or updated if it already exists.\n */\nWhen(a.Namespace)\n .IsCreated()\n .WithName("pepr-demo-2")\n .Watch(async ns => {\n Log.info("Namespace pepr-demo-2 was created.");\n\n try {\n // Apply the ConfigMap using K8s server-side apply\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: "pepr-ssa-demo",\n namespace: "pepr-demo-2",\n },\n data: {\n "ns-uid": ns.metadata.uid,\n },\n });\n } catch (error) {\n // You can use the Log object to log messages to the Pepr controller pod\n Log.error(error, "Failed to apply ConfigMap using server-side apply.");\n }\n\n // You can share data between actions using the Store, including between different types of actions\n Store.setItem("watch-data", "This data was stored by a Watch Action.");\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 1) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is a single action. They can be in the same file or put imported from other files.\n * In this example, when a ConfigMap is created with the name `example-1`, then add a label and annotation.\n *\n * Equivalent to manually running:\n * `kubectl label configmap example-1 pepr=was-here`\n * `kubectl annotate configmap example-1 pepr.dev=annotations-work-too`\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request.SetLabel("pepr", "was-here").SetAnnotation("pepr.dev", "annotations-work-too");\n\n // Use the Store to persist data between requests and Pepr controller pods\n Store.setItem("example-1", "was-here");\n\n // This data is written asynchronously and can be read back via `Store.getItem()` or `Store.subscribe()`\n Store.setItem("example-1-data", JSON.stringify(request.Raw.data));\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate & Validate Actions (CM Example 2) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This combines 3 different types of actions: \'Mutate\', \'Validate\', and \'Watch\'. The order\n * of the actions is required, but each action is optional. In this example, when a ConfigMap is created\n * with the name `example-2`, then add a label and annotation, validate that the ConfigMap has the label\n * `pepr`, and log the request.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n // This Mutate Action will mutate the request before it is persisted to the cluster\n\n // Use `request.Merge()` to merge the new data with the existing data\n request.Merge({\n metadata: {\n labels: {\n pepr: "was-here",\n },\n annotations: {\n "pepr.dev": "annotations-work-too",\n },\n },\n });\n })\n .Validate(request => {\n // This Validate Action will validate the request before it is persisted to the cluster\n\n // Approve the request if the ConfigMap has the label \'pepr\'\n if (request.HasLabel("pepr")) {\n return request.Approve();\n }\n\n // Otherwise, deny the request with an error message (optional)\n return request.Deny("ConfigMap must have label \'pepr\'");\n })\n .Watch((cm, phase) => {\n // This Watch Action will watch the ConfigMap after it has been persisted to the cluster\n Log.info(cm, `ConfigMap was ${phase} with the name example-2`);\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 2a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action shows a simple validation that will deny any ConfigMap that has the\n * annotation `evil`. Note that the `Deny()` function takes an optional second parameter that is a\n * user-defined status code to return.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .Validate(request => {\n if (request.HasAnnotation("evil")) {\n return request.Deny("No evil CM annotations allowed.", 400);\n }\n\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 3) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action combines different styles. Unlike the previous actions, this one will look\n * for any ConfigMap in the `pepr-demo` namespace that has the label `change=by-label` during either\n * CREATE or UPDATE. Note that all conditions added such as `WithName()`, `WithLabel()`, `InNamespace()`,\n * are ANDs so all conditions must be true for the request to be processed.\n */\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("change", "by-label")\n .Mutate(request => {\n // The K8s object e are going to mutate\n const cm = request.Raw;\n\n // Get the username and uid of the K8s request\n const { username, uid } = request.Request.userInfo;\n\n // Store some data about the request in the configmap\n cm.data["username"] = username;\n cm.data["uid"] = uid;\n\n // You can still mix other ways of making changes too\n request.SetAnnotation("pepr.dev", "making-waves");\n });\n\n// This action validates the label `change=by-label` is deleted\nWhen(a.ConfigMap)\n .IsDeleted()\n .WithLabel("change", "by-label")\n .Validate(request => {\n // Log and then always approve the request\n Log.info("CM with label \'change=by-label\' was deleted.");\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action show how you can use the `Mutate()` function without an inline function.\n * This is useful if you want to keep your actions small and focused on a single task,\n * or if you want to reuse the same function in multiple actions.\n */\nWhen(a.ConfigMap).IsCreated().WithName("example-4").Mutate(example4Cb);\n\n// This function uses the complete type definition, but is not required.\nfunction example4Cb(cm: PeprMutateRequest<a.ConfigMap>) {\n cm.SetLabel("pepr.dev/first", "true");\n cm.SetLabel("pepr.dev/second", "true");\n cm.SetLabel("pepr.dev/third", "true");\n}\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is the same as Example 4, except this only operates on a CM in the `pepr-demo-2` namespace.\n * Note because the Capability defines namespaces, the namespace specified here must be one of those.\n * Alternatively, you can remove the namespace from the Capability definition and specify it here.\n */\nWhen(a.ConfigMap).IsCreated().InNamespace("pepr-demo-2").WithName("example-4a").Mutate(example4Cb);\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 5) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action is a bit more complex. It will look for any ConfigMap in the `pepr-demo`\n * namespace that has the label `chuck-norris` during CREATE. When it finds one, it will fetch a\n * random Chuck Norris joke from the API and add it to the ConfigMap. This is a great example of how\n * you can use Pepr to make changes to your K8s objects based on external data.\n *\n * Note the use of the `async` keyword. This is required for any action that uses `await` or `fetch()`.\n *\n * Also note we are passing a type to the `fetch()` function. This is optional, but it will help you\n * avoid mistakes when working with the data returned from the API. You can also use the `as` keyword to\n * cast the data returned from the API.\n *\n * These are equivalent:\n * ```ts\n * const joke = await fetch<TheChuckNorrisJoke>("https://icanhazdadjoke.com/");\n * const joke = await fetch("https://icanhazdadjoke.com/") as TheChuckNorrisJoke;\n * ```\n *\n * Alternatively, you can drop the type completely:\n *\n * ```ts\n * fetch("https://icanhazdadjoke.com")\n * ```\n */\ninterface TheChuckNorrisJoke {\n id: string;\n joke: string;\n status: number;\n}\n\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("chuck-norris")\n .Mutate(cm => cm.SetLabel("got-jokes", "true"))\n .Watch(async cm => {\n const jokeURL = "https://icanhazdadjoke.com";\n\n const mockAgent: MockAgent = new MockAgent();\n setGlobalDispatcher(mockAgent);\n const mockClient = mockAgent.get(jokeURL);\n mockClient.intercept({ path: "/", method: "GET" }).reply(\n 200,\n {\n id: "R7UfaahVfFd",\n joke: "Funny joke goes here.",\n status: 200,\n },\n {\n headers: {\n "Content-Type": "application/json; charset=utf-8",\n },\n },\n );\n\n // Try/catch is not needed as a response object will always be returned\n const response = await fetch<TheChuckNorrisJoke>(jokeURL, {\n headers: {\n Accept: "application/json",\n },\n });\n\n // Instead, check the `response.ok` field\n if (response.ok) {\n const { joke } = response.data;\n // Add Joke to the Store\n await Store.setItemAndWait(jokeURL, joke);\n // Add the Chuck Norris joke to the configmap\n try {\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: cm.metadata.name,\n namespace: cm.metadata.namespace,\n },\n data: {\n "chuck-says": Store.getItem(jokeURL),\n },\n });\n } catch (error) {\n Log.error(error, "Failed to apply ConfigMap using server-side apply.", {\n cm,\n });\n }\n }\n\n // You can also assert on different HTTP response codes\n if (response.status === fetchStatus.NOT_FOUND) {\n // Do something else\n return;\n }\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Secret Base64 Handling) *\n * ---------------------------------------------------------------------------------------------------\n *\n * The K8s JS client provides incomplete support for base64 encoding/decoding handling for secrets,\n * unlike the GO client. To make this less painful, Pepr automatically handles base64 encoding/decoding\n * secret data before and after the action is executed.\n */\nWhen(a.Secret)\n .IsCreated()\n .WithName("secret-1")\n .Mutate(request => {\n const secret = request.Raw;\n\n // This will be encoded at the end of all processing back to base64: "Y2hhbmdlLXdpdGhvdXQtZW5jb2Rpbmc="\n secret.data.magic = "change-without-encoding";\n\n // You can modify the data directly, and it will be encoded at the end of all processing\n secret.data.example += " - modified by Pepr";\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Untyped Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * Out of the box, Pepr supports all the standard Kubernetes objects. However, you can also create\n * your own types. This is useful if you are working with an Operator that creates custom resources.\n * There are two ways to do this, the first is to use the `When()` function with a `GenericKind`,\n * the second is to create a new class that extends `GenericKind` and use the `RegisterKind()` function.\n *\n * This example shows how to use the `When()` function with a `GenericKind`. Note that you\n * must specify the `group`, `version`, and `kind` of the object (if applicable). This is how Pepr knows\n * if the action should be triggered or not. Since we are using a `GenericKind`,\n * Pepr will not be able to provide any intellisense for the object, so you will need to refer to the\n * Kubernetes API documentation for the object you are working with.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-1\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```\n */\nWhen(a.GenericKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n})\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr without type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Typed Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This example shows how to use the `RegisterKind()` function to create a new type. This is useful\n * if you are working with an Operator that creates custom resources and you want to have intellisense\n * for the object. Note that you must specify the `group`, `version`, and `kind` of the object (if applicable)\n * as this is how Pepr knows if the action should be triggered or not.\n *\n * Once you register a new Kind with Pepr, you can use the `When()` function with the new Kind. Ideally,\n * you should register custom Kinds at the top of your Capability file or Pepr Module so they are available\n * to all actions, but we are putting it here for demonstration purposes.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-2\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```*\n */\nclass UnicornKind extends a.GenericKind {\n spec: {\n /**\n * JSDoc comments can be added to explain more details about the field.\n *\n * @example\n * ```ts\n * request.Raw.spec.message = "Hello Pepr!";\n * ```\n * */\n message: string;\n counter: number;\n };\n}\n\nRegisterKind(UnicornKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n});\n\nWhen(UnicornKind)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr with type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * A callback function that is called once the Pepr Store is fully loaded.\n */\nStore.onReady(data => {\n Log.info(data, "Pepr Store Ready");\n});\n';
|
|
8801
|
-
var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!src/fixtures/**", "!dist/**/*.test.d.ts*"], version: "0.
|
|
8838
|
+
var helloPeprTS = 'import {\n Capability,\n K8s,\n Log,\n PeprMutateRequest,\n RegisterKind,\n a,\n fetch,\n fetchStatus,\n kind,\n} from "pepr";\nimport { MockAgent, setGlobalDispatcher } from "undici";\n\n/**\n * The HelloPepr Capability is an example capability to demonstrate some general concepts of Pepr.\n * To test this capability you run `pepr dev`and then run the following command:\n * `kubectl apply -f capabilities/hello-pepr.samples.yaml`\n */\nexport const HelloPepr = new Capability({\n name: "hello-pepr",\n description: "A simple example capability to show how things work.",\n namespaces: ["pepr-demo", "pepr-demo-2"],\n});\n\n// Use the \'When\' function to create a new action, use \'Store\' to persist data\nconst { When, Store } = HelloPepr;\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action removes the label `remove-me` when a Namespace is created.\n * Note we don\'t need to specify the namespace here, because we\'ve already specified\n * it in the Capability definition above.\n */\nWhen(a.Namespace)\n .IsCreated()\n .Mutate(ns => ns.RemoveLabel("remove-me"));\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Watch Action with K8s SSA (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action watches for the `pepr-demo-2` namespace to be created, then creates a ConfigMap with\n * the name `pepr-ssa-demo` and adds the namespace UID to the ConfigMap data. Because Pepr uses\n * server-side apply for this operation, the ConfigMap will be created or updated if it already exists.\n */\nWhen(a.Namespace)\n .IsCreated()\n .WithName("pepr-demo-2")\n .Watch(async ns => {\n Log.info("Namespace pepr-demo-2 was created.");\n\n try {\n // Apply the ConfigMap using K8s server-side apply\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: "pepr-ssa-demo",\n namespace: "pepr-demo-2",\n },\n data: {\n "ns-uid": ns.metadata.uid,\n },\n });\n } catch (error) {\n // You can use the Log object to log messages to the Pepr controller pod\n Log.error(error, "Failed to apply ConfigMap using server-side apply.");\n }\n\n // You can share data between actions using the Store, including between different types of actions\n Store.setItem("watch-data", "This data was stored by a Watch Action.");\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 1) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is a single action. They can be in the same file or put imported from other files.\n * In this example, when a ConfigMap is created with the name `example-1`, then add a label and annotation.\n *\n * Equivalent to manually running:\n * `kubectl label configmap example-1 pepr=was-here`\n * `kubectl annotate configmap example-1 pepr.dev=annotations-work-too`\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request.SetLabel("pepr", "was-here").SetAnnotation("pepr.dev", "annotations-work-too");\n\n // Use the Store to persist data between requests and Pepr controller pods\n Store.setItem("example-1", "was-here");\n\n // This data is written asynchronously and can be read back via `Store.getItem()` or `Store.subscribe()`\n Store.setItem("example-1-data", JSON.stringify(request.Raw.data));\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate & Validate Actions (CM Example 2) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This combines 3 different types of actions: \'Mutate\', \'Validate\', and \'Watch\'. The order\n * of the actions is required, but each action is optional. In this example, when a ConfigMap is created\n * with the name `example-2`, then add a label and annotation, validate that the ConfigMap has the label\n * `pepr`, and log the request.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n // This Mutate Action will mutate the request before it is persisted to the cluster\n\n // Use `request.Merge()` to merge the new data with the existing data\n request.Merge({\n metadata: {\n labels: {\n pepr: "was-here",\n },\n annotations: {\n "pepr.dev": "annotations-work-too",\n },\n },\n });\n })\n .Validate(request => {\n // This Validate Action will validate the request before it is persisted to the cluster\n\n // Approve the request if the ConfigMap has the label \'pepr\'\n if (request.HasLabel("pepr")) {\n return request.Approve();\n }\n\n // Otherwise, deny the request with an error message (optional)\n return request.Deny("ConfigMap must have label \'pepr\'");\n })\n .Watch((cm, phase) => {\n // This Watch Action will watch the ConfigMap after it has been persisted to the cluster\n Log.info(cm, `ConfigMap was ${phase} with the name example-2`);\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 2a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action shows a simple validation that will deny any ConfigMap that has the\n * annotation `evil`. Note that the `Deny()` function takes an optional second parameter that is a\n * user-defined status code to return.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .Validate(request => {\n if (request.HasAnnotation("evil")) {\n return request.Deny("No evil CM annotations allowed.", 400);\n }\n\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 3) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action combines different styles. Unlike the previous actions, this one will look\n * for any ConfigMap in the `pepr-demo` namespace that has the label `change=by-label` during either\n * CREATE or UPDATE. Note that all conditions added such as `WithName()`, `WithLabel()`, `InNamespace()`,\n * are ANDs so all conditions must be true for the request to be processed.\n */\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("change", "by-label")\n .Mutate(request => {\n // The K8s object e are going to mutate\n const cm = request.Raw;\n\n // Get the username and uid of the K8s request\n const { username, uid } = request.Request.userInfo;\n\n // Store some data about the request in the configmap\n cm.data["username"] = username;\n cm.data["uid"] = uid;\n\n // You can still mix other ways of making changes too\n request.SetAnnotation("pepr.dev", "making-waves");\n });\n\n// This action validates the label `change=by-label` is deleted\nWhen(a.ConfigMap)\n .IsDeleted()\n .WithLabel("change", "by-label")\n .Validate(request => {\n // Log and then always approve the request\n Log.info("CM with label \'change=by-label\' was deleted.");\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action show how you can use the `Mutate()` function without an inline function.\n * This is useful if you want to keep your actions small and focused on a single task,\n * or if you want to reuse the same function in multiple actions.\n */\nWhen(a.ConfigMap).IsCreated().WithName("example-4").Mutate(example4Cb);\n\n// This function uses the complete type definition, but is not required.\nfunction example4Cb(cm: PeprMutateRequest<a.ConfigMap>): void {\n cm.SetLabel("pepr.dev/first", "true");\n cm.SetLabel("pepr.dev/second", "true");\n cm.SetLabel("pepr.dev/third", "true");\n}\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is the same as Example 4, except this only operates on a CM in the `pepr-demo-2` namespace.\n * Note because the Capability defines namespaces, the namespace specified here must be one of those.\n * Alternatively, you can remove the namespace from the Capability definition and specify it here.\n */\nWhen(a.ConfigMap).IsCreated().InNamespace("pepr-demo-2").WithName("example-4a").Mutate(example4Cb);\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 5) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action is a bit more complex. It will look for any ConfigMap in the `pepr-demo`\n * namespace that has the label `chuck-norris` during CREATE. When it finds one, it will fetch a\n * random Chuck Norris joke from the API and add it to the ConfigMap. This is a great example of how\n * you can use Pepr to make changes to your K8s objects based on external data.\n *\n * Note the use of the `async` keyword. This is required for any action that uses `await` or `fetch()`.\n *\n * Also note we are passing a type to the `fetch()` function. This is optional, but it will help you\n * avoid mistakes when working with the data returned from the API. You can also use the `as` keyword to\n * cast the data returned from the API.\n *\n * These are equivalent:\n * ```ts\n * const joke = await fetch<TheChuckNorrisJoke>("https://icanhazdadjoke.com/");\n * const joke = await fetch("https://icanhazdadjoke.com/") as TheChuckNorrisJoke;\n * ```\n *\n * Alternatively, you can drop the type completely:\n *\n * ```ts\n * fetch("https://icanhazdadjoke.com")\n * ```\n */\ninterface TheChuckNorrisJoke {\n id: string;\n joke: string;\n status: number;\n}\n\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("chuck-norris")\n .Mutate(cm => cm.SetLabel("got-jokes", "true"))\n .Watch(async cm => {\n const jokeURL = "https://icanhazdadjoke.com";\n\n const mockAgent: MockAgent = new MockAgent();\n setGlobalDispatcher(mockAgent);\n const mockClient = mockAgent.get(jokeURL);\n mockClient.intercept({ path: "/", method: "GET" }).reply(\n 200,\n {\n id: "R7UfaahVfFd",\n joke: "Funny joke goes here.",\n status: 200,\n },\n {\n headers: {\n "Content-Type": "application/json; charset=utf-8",\n },\n },\n );\n\n // Try/catch is not needed as a response object will always be returned\n const response = await fetch<TheChuckNorrisJoke>(jokeURL, {\n headers: {\n Accept: "application/json",\n },\n });\n\n // Instead, check the `response.ok` field\n if (response.ok) {\n const { joke } = response.data;\n // Add Joke to the Store\n await Store.setItemAndWait(jokeURL, joke);\n // Add the Chuck Norris joke to the configmap\n try {\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: cm.metadata.name,\n namespace: cm.metadata.namespace,\n },\n data: {\n "chuck-says": Store.getItem(jokeURL),\n },\n });\n } catch (error) {\n Log.error(error, "Failed to apply ConfigMap using server-side apply.", {\n cm,\n });\n }\n }\n\n // You can also assert on different HTTP response codes\n if (response.status === fetchStatus.NOT_FOUND) {\n // Do something else\n return;\n }\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Secret Base64 Handling) *\n * ---------------------------------------------------------------------------------------------------\n *\n * The K8s JS client provides incomplete support for base64 encoding/decoding handling for secrets,\n * unlike the GO client. To make this less painful, Pepr automatically handles base64 encoding/decoding\n * secret data before and after the action is executed.\n */\nWhen(a.Secret)\n .IsCreated()\n .WithName("secret-1")\n .Mutate(request => {\n const secret = request.Raw;\n\n // This will be encoded at the end of all processing back to base64: "Y2hhbmdlLXdpdGhvdXQtZW5jb2Rpbmc="\n secret.data.magic = "change-without-encoding";\n\n // You can modify the data directly, and it will be encoded at the end of all processing\n secret.data.example += " - modified by Pepr";\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Untyped Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * Out of the box, Pepr supports all the standard Kubernetes objects. However, you can also create\n * your own types. This is useful if you are working with an Operator that creates custom resources.\n * There are two ways to do this, the first is to use the `When()` function with a `GenericKind`,\n * the second is to create a new class that extends `GenericKind` and use the `RegisterKind()` function.\n *\n * This example shows how to use the `When()` function with a `GenericKind`. Note that you\n * must specify the `group`, `version`, and `kind` of the object (if applicable). This is how Pepr knows\n * if the action should be triggered or not. Since we are using a `GenericKind`,\n * Pepr will not be able to provide any intellisense for the object, so you will need to refer to the\n * Kubernetes API documentation for the object you are working with.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-1\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```\n */\nWhen(a.GenericKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n})\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr without type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Typed Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This example shows how to use the `RegisterKind()` function to create a new type. This is useful\n * if you are working with an Operator that creates custom resources and you want to have intellisense\n * for the object. Note that you must specify the `group`, `version`, and `kind` of the object (if applicable)\n * as this is how Pepr knows if the action should be triggered or not.\n *\n * Once you register a new Kind with Pepr, you can use the `When()` function with the new Kind. Ideally,\n * you should register custom Kinds at the top of your Capability file or Pepr Module so they are available\n * to all actions, but we are putting it here for demonstration purposes.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-2\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```*\n */\nclass UnicornKind extends a.GenericKind {\n spec: {\n /**\n * JSDoc comments can be added to explain more details about the field.\n *\n * @example\n * ```ts\n * request.Raw.spec.message = "Hello Pepr!";\n * ```\n * */\n message: string;\n counter: number;\n };\n}\n\nRegisterKind(UnicornKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n});\n\nWhen(UnicornKind)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr with type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * A callback function that is called once the Pepr Store is fully loaded.\n */\nStore.onReady(data => {\n Log.info(data, "Pepr Store Ready");\n});\n';
|
|
8839
|
+
var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!src/fixtures/**", "!dist/**/*.test.d.ts*", "!src/cli/docs/**"], version: "0.50.0-nightly.0", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { ci: "npm ci", "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs && npm pack", "build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .", "build:image:unicorn": "npm run build && docker buildx build --output type=docker --tag pepr:dev $(node scripts/read-unicorn-build-args.mjs) .", "set:version": "node scripts/set-version.js", test: "npm run test:unit && npm run test:journey && npm run test:journey-wasm", "test:artifacts": "npm run build && jest src/build-artifact.test.ts", "test:docs": "jest --verbose src/cli/docs/*.test.ts", "test:integration": "npm run test:integration:prep && npm run test:integration:run", "test:integration:prep": "./integration/prep.sh", "test:integration:run": "jest --maxWorkers=4 integration", "test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run", "test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm", "test:journey-wasm:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run-wasm", "test:journey:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:image:unicorn": "npm run build && docker buildx build --output type=docker --tag pepr:dev $(node scripts/read-unicorn-build-args.mjs) . && k3d image import pepr:dev -c pepr-dev", "test:journey:k3d": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0' --wait && kubectl rollout status deployment -n kube-system", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:upgrade", "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts", "test:journey:unicorn": "npm run test:journey:k3d && npm run test:journey:image:unicorn && npm run test:journey:run", "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts", "test:unit": 'npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns="build-artifact.test.ts|src/cli/docs/.*\\.test\\.ts"', "format:check": "eslint --ignore-pattern src/templates/eslint.config.mjs src && prettier --config .prettierrc src --check", "format:fix": "eslint --fix --ignore-pattern src/templates/eslint.config.mjs src && prettier --config .prettierrc src --write", prepare: `if [ "$NODE_ENV" != 'production' ]; then husky; fi` }, dependencies: { "@types/ramda": "0.30.2", express: "5.1.0", "fast-json-patch": "3.1.1", heredoc: "^1.3.1", "http-status-codes": "^2.3.0", "json-pointer": "^0.6.2", "kubernetes-fluent-client": "3.5.3", pino: "9.6.0", "pino-pretty": "13.0.0", "prom-client": "15.1.3", ramda: "0.30.1", sigstore: "3.1.0", "ts-morph": "^25.0.1" }, devDependencies: { "@commitlint/cli": "19.8.1", "@commitlint/config-conventional": "19.8.1", "@fast-check/jest": "^2.0.1", "@jest/globals": "29.7.0", "@types/eslint": "9.6.1", "@types/express": "5.0.1", "@types/json-pointer": "^1.0.34", "@types/node": "22.x.x", "@types/node-forge": "1.3.11", "@types/uuid": "10.0.0", "fast-check": "^4.0.0", globals: "^16.0.0", husky: "^9.1.6", jest: "29.7.0", "js-yaml": "^4.1.0", shellcheck: "^3.0.0", "ts-jest": "29.3.2", undici: "^7.0.1" }, overrides: { glob: "^9.0.0" }, peerDependencies: { "@types/prompts": "2.4.9", "@typescript-eslint/eslint-plugin": "8.23.0", "@typescript-eslint/parser": "8.23.0", commander: "13.1.0", esbuild: "0.25.0", eslint: "^9.26.0", "node-forge": "1.3.1", prettier: "3.4.2", prompts: "2.4.2", typescript: "5.7.3", uuid: "11.0.5" } };
|
|
8802
8840
|
|
|
8803
8841
|
// src/cli/init/utils.ts
|
|
8804
8842
|
var import_fs4 = require("fs");
|
|
@@ -8824,11 +8862,11 @@ async function createDir(dir) {
|
|
|
8824
8862
|
}
|
|
8825
8863
|
}
|
|
8826
8864
|
}
|
|
8827
|
-
function write(
|
|
8865
|
+
function write(path4, data) {
|
|
8828
8866
|
if (typeof data !== "string") {
|
|
8829
8867
|
data = JSON.stringify(data, null, 2);
|
|
8830
8868
|
}
|
|
8831
|
-
return import_fs4.promises.writeFile(
|
|
8869
|
+
return import_fs4.promises.writeFile(path4, data);
|
|
8832
8870
|
}
|
|
8833
8871
|
|
|
8834
8872
|
// src/cli/init/templates.ts
|
|
@@ -8861,6 +8899,16 @@ function genPkgJSON(opts, pgkVerOverride) {
|
|
|
8861
8899
|
alwaysIgnore: {
|
|
8862
8900
|
namespaces: []
|
|
8863
8901
|
},
|
|
8902
|
+
admission: {
|
|
8903
|
+
alwaysIgnore: {
|
|
8904
|
+
namespaces: []
|
|
8905
|
+
}
|
|
8906
|
+
},
|
|
8907
|
+
watch: {
|
|
8908
|
+
alwaysIgnore: {
|
|
8909
|
+
namespaces: []
|
|
8910
|
+
}
|
|
8911
|
+
},
|
|
8864
8912
|
includedFiles: [],
|
|
8865
8913
|
env: pgkVerOverride ? testEnv : {}
|
|
8866
8914
|
},
|
|
@@ -8918,38 +8966,49 @@ var prettier = {
|
|
|
8918
8966
|
data: prettierrc_default
|
|
8919
8967
|
};
|
|
8920
8968
|
var eslint = {
|
|
8921
|
-
path: ".
|
|
8922
|
-
data:
|
|
8969
|
+
path: "eslint.config.mjs",
|
|
8970
|
+
data: (0, import_fs5.readFileSync)(
|
|
8971
|
+
import_path2.default.resolve(
|
|
8972
|
+
(() => {
|
|
8973
|
+
const fullPath = __dirname;
|
|
8974
|
+
const lengthOfSuffix = "pepr/".length;
|
|
8975
|
+
const lastPeprIndex = fullPath.lastIndexOf("pepr/");
|
|
8976
|
+
return fullPath.substring(0, lastPeprIndex + lengthOfSuffix);
|
|
8977
|
+
})(),
|
|
8978
|
+
"src/templates/eslint.config.mjs"
|
|
8979
|
+
),
|
|
8980
|
+
"utf-8"
|
|
8981
|
+
)
|
|
8923
8982
|
};
|
|
8924
8983
|
|
|
8925
8984
|
// src/cli/build.ts
|
|
8926
8985
|
var import_commander = require("commander");
|
|
8927
8986
|
|
|
8928
|
-
// src/cli/format.ts
|
|
8987
|
+
// src/cli/format/index.ts
|
|
8929
8988
|
var import_eslint = require("eslint");
|
|
8930
8989
|
|
|
8931
|
-
// src/cli/format.helpers.ts
|
|
8932
|
-
var
|
|
8990
|
+
// src/cli/format/format.helpers.ts
|
|
8991
|
+
var import_fs6 = require("fs");
|
|
8933
8992
|
var import_prettier = require("prettier");
|
|
8934
8993
|
async function formatWithPrettier(results, validateOnly) {
|
|
8935
8994
|
let hasFailure = false;
|
|
8936
8995
|
for (const { filePath } of results) {
|
|
8937
|
-
const content = await
|
|
8996
|
+
const content = await import_fs6.promises.readFile(filePath, "utf8");
|
|
8938
8997
|
const cfg = await (0, import_prettier.resolveConfig)(filePath);
|
|
8939
8998
|
const formatted = await (0, import_prettier.format)(content, { filepath: filePath, ...cfg });
|
|
8940
8999
|
if (validateOnly && formatted !== content) {
|
|
8941
9000
|
hasFailure = true;
|
|
8942
9001
|
console.error(`File ${filePath} is not formatted correctly`);
|
|
8943
9002
|
} else {
|
|
8944
|
-
await
|
|
9003
|
+
await import_fs6.promises.writeFile(filePath, formatted);
|
|
8945
9004
|
}
|
|
8946
9005
|
}
|
|
8947
9006
|
return hasFailure;
|
|
8948
9007
|
}
|
|
8949
9008
|
|
|
8950
|
-
// src/cli/format.ts
|
|
9009
|
+
// src/cli/format/index.ts
|
|
8951
9010
|
function format_default(program2) {
|
|
8952
|
-
program2.command("format").description("Lint and format this Pepr module").option("-v, --validate-only", "Do not modify files, only validate formatting").action(async (opts) => {
|
|
9011
|
+
program2.command("format").description("Lint and format this Pepr module").option("-v, --validate-only", "Do not modify files, only validate formatting.").action(async (opts) => {
|
|
8953
9012
|
const success = await peprFormat(opts.validateOnly);
|
|
8954
9013
|
if (success) {
|
|
8955
9014
|
console.info("\u2705 Module formatted");
|
|
@@ -8988,7 +9047,7 @@ async function peprFormat(validateOnly) {
|
|
|
8988
9047
|
}
|
|
8989
9048
|
|
|
8990
9049
|
// src/lib/included-files.ts
|
|
8991
|
-
var
|
|
9050
|
+
var import_fs7 = require("fs");
|
|
8992
9051
|
async function createDockerfile(version3, description, includedFiles) {
|
|
8993
9052
|
const file = `
|
|
8994
9053
|
# Use an official Node.js runtime as the base image
|
|
@@ -9000,14 +9059,14 @@ async function createDockerfile(version3, description, includedFiles) {
|
|
|
9000
9059
|
${includedFiles.map((f) => `ADD ${f} ${f}`).join("\n")}
|
|
9001
9060
|
|
|
9002
9061
|
`;
|
|
9003
|
-
await
|
|
9062
|
+
await import_fs7.promises.writeFile("Dockerfile.controller", file, { encoding: "utf-8" });
|
|
9004
9063
|
}
|
|
9005
9064
|
|
|
9006
9065
|
// src/cli/build.helpers.ts
|
|
9007
9066
|
var import_child_process2 = require("child_process");
|
|
9008
9067
|
var import_esbuild = require("esbuild");
|
|
9009
|
-
var
|
|
9010
|
-
var
|
|
9068
|
+
var import_path3 = require("path");
|
|
9069
|
+
var import_fs9 = require("fs");
|
|
9011
9070
|
|
|
9012
9071
|
// src/lib/assets/yaml/generateAllYaml.ts
|
|
9013
9072
|
var import_crypto2 = __toESM(require("crypto"));
|
|
@@ -9322,7 +9381,7 @@ function getDeployment(assets, hash, buildTimestamp, imagePullSecret) {
|
|
|
9322
9381
|
}
|
|
9323
9382
|
function getModuleSecret(name2, data, hash) {
|
|
9324
9383
|
const compressed = (0, import_zlib.gzipSync)(data);
|
|
9325
|
-
const
|
|
9384
|
+
const path4 = `module-${hash}.js.gz`;
|
|
9326
9385
|
const compressedData = compressed.toString("base64");
|
|
9327
9386
|
if (secretOverLimit(compressedData)) {
|
|
9328
9387
|
const error = new Error(`Module secret for ${name2} is over the 1MB limit`);
|
|
@@ -9337,14 +9396,14 @@ function getModuleSecret(name2, data, hash) {
|
|
|
9337
9396
|
},
|
|
9338
9397
|
type: "Opaque",
|
|
9339
9398
|
data: {
|
|
9340
|
-
[
|
|
9399
|
+
[path4]: compressed.toString("base64")
|
|
9341
9400
|
}
|
|
9342
9401
|
};
|
|
9343
9402
|
}
|
|
9344
9403
|
}
|
|
9345
9404
|
|
|
9346
9405
|
// src/lib/assets/yaml/generateAllYaml.ts
|
|
9347
|
-
var
|
|
9406
|
+
var import_fs8 = require("fs");
|
|
9348
9407
|
|
|
9349
9408
|
// src/lib/assets/webhooks.ts
|
|
9350
9409
|
var import_ramda = require("ramda");
|
|
@@ -9364,17 +9423,6 @@ var validateRule = (binding, isMutateWebhook) => {
|
|
|
9364
9423
|
};
|
|
9365
9424
|
return ruleObject;
|
|
9366
9425
|
};
|
|
9367
|
-
function resolveIgnoreNamespaces(ignoredNSConfig = []) {
|
|
9368
|
-
const ignoredNSEnv = process.env.PEPR_ADDITIONAL_IGNORED_NAMESPACES;
|
|
9369
|
-
if (!ignoredNSEnv) {
|
|
9370
|
-
return ignoredNSConfig;
|
|
9371
|
-
}
|
|
9372
|
-
const namespaces = ignoredNSEnv.split(",").map((ns) => ns.trim());
|
|
9373
|
-
if (ignoredNSConfig) {
|
|
9374
|
-
namespaces.push(...ignoredNSConfig);
|
|
9375
|
-
}
|
|
9376
|
-
return namespaces.filter((ns) => ns.length > 0);
|
|
9377
|
-
}
|
|
9378
9426
|
async function generateWebhookRules(assets, isMutateWebhook) {
|
|
9379
9427
|
const { config, capabilities } = assets;
|
|
9380
9428
|
const rules = capabilities.flatMap((capability) => {
|
|
@@ -9388,7 +9436,9 @@ async function webhookConfigGenerator(assets, mutateOrValidate, timeoutSeconds =
|
|
|
9388
9436
|
const { name: name2, tls, config, apiPath, host } = assets;
|
|
9389
9437
|
const ignoreNS = (0, import_ramda.concat)(
|
|
9390
9438
|
peprIgnoreNamespaces,
|
|
9391
|
-
resolveIgnoreNamespaces(
|
|
9439
|
+
resolveIgnoreNamespaces(
|
|
9440
|
+
config?.alwaysIgnore?.namespaces?.length ? config?.alwaysIgnore?.namespaces : config?.admission?.alwaysIgnore?.namespaces
|
|
9441
|
+
)
|
|
9392
9442
|
);
|
|
9393
9443
|
if (ignoreNS) {
|
|
9394
9444
|
ignore.push({
|
|
@@ -9440,8 +9490,8 @@ async function webhookConfigGenerator(assets, mutateOrValidate, timeoutSeconds =
|
|
|
9440
9490
|
|
|
9441
9491
|
// src/lib/assets/yaml/generateAllYaml.ts
|
|
9442
9492
|
async function generateAllYaml(assets, deployments) {
|
|
9443
|
-
const { name: name2, tls, apiPath, path:
|
|
9444
|
-
const code = await
|
|
9493
|
+
const { name: name2, tls, apiPath, path: path4, config } = assets;
|
|
9494
|
+
const code = await import_fs8.promises.readFile(path4);
|
|
9445
9495
|
const hash = import_crypto2.default.createHash("sha256").update(code).digest("hex");
|
|
9446
9496
|
const resources = [
|
|
9447
9497
|
getNamespace(assets.config.customLabels?.namespace),
|
|
@@ -9474,18 +9524,18 @@ async function generateAllYaml(assets, deployments) {
|
|
|
9474
9524
|
|
|
9475
9525
|
// src/lib/assets/yaml/generateZarfYaml.ts
|
|
9476
9526
|
var import_client_node5 = require("@kubernetes/client-node");
|
|
9477
|
-
function generateZarfYamlGeneric(assets,
|
|
9527
|
+
function generateZarfYamlGeneric(assets, path4, type) {
|
|
9478
9528
|
const zarfComponentName = process.env.PEPR_CUSTOM_BUILD_NAME ?? "module";
|
|
9479
9529
|
const manifestSettings = {
|
|
9480
9530
|
name: zarfComponentName,
|
|
9481
9531
|
namespace: "pepr-system",
|
|
9482
|
-
files: [
|
|
9532
|
+
files: [path4]
|
|
9483
9533
|
};
|
|
9484
9534
|
const chartSettings = {
|
|
9485
9535
|
name: zarfComponentName,
|
|
9486
9536
|
namespace: "pepr-system",
|
|
9487
9537
|
version: `${assets.config.appVersion || "0.0.1"}`,
|
|
9488
|
-
localPath:
|
|
9538
|
+
localPath: path4
|
|
9489
9539
|
};
|
|
9490
9540
|
const component = {
|
|
9491
9541
|
name: zarfComponentName,
|
|
@@ -9585,18 +9635,18 @@ async function generateYamlAndWriteToDisk(obj) {
|
|
|
9585
9635
|
const { uuid, imagePullSecret, outputDir: outputDir2, assets, zarf } = obj;
|
|
9586
9636
|
const yamlFile = `pepr-module-${uuid}.yaml`;
|
|
9587
9637
|
const chartPath = `${uuid}-chart`;
|
|
9588
|
-
const yamlPath = (0,
|
|
9638
|
+
const yamlPath = (0, import_path3.resolve)(outputDir2, yamlFile);
|
|
9589
9639
|
try {
|
|
9590
9640
|
const yaml = await assets.allYaml(generateAllYaml, getDeployment, getWatcher, imagePullSecret);
|
|
9591
|
-
const zarfPath = (0,
|
|
9641
|
+
const zarfPath = (0, import_path3.resolve)(outputDir2, "zarf.yaml");
|
|
9592
9642
|
let localZarf = "";
|
|
9593
9643
|
if (zarf === "chart") {
|
|
9594
9644
|
localZarf = assets.zarfYamlChart(generateZarfYamlGeneric, chartPath);
|
|
9595
9645
|
} else {
|
|
9596
9646
|
localZarf = assets.zarfYaml(generateZarfYamlGeneric, yamlFile);
|
|
9597
9647
|
}
|
|
9598
|
-
await
|
|
9599
|
-
await
|
|
9648
|
+
await import_fs9.promises.writeFile(yamlPath, yaml);
|
|
9649
|
+
await import_fs9.promises.writeFile(zarfPath, localZarf);
|
|
9600
9650
|
await assets.generateHelmChart(webhookConfigGenerator, getWatcher, getModuleSecret, outputDir2);
|
|
9601
9651
|
console.info(`\u2705 K8s resource for the module saved to ${yamlPath}`);
|
|
9602
9652
|
} catch (error) {
|
|
@@ -9611,7 +9661,7 @@ var outputDir = "dist";
|
|
|
9611
9661
|
function build_default(program2) {
|
|
9612
9662
|
program2.command("build").description("Build a Pepr Module for deployment").option("-e, --entry-point [file]", "Specify the entry point file to build with.", peprTS2).option(
|
|
9613
9663
|
"-n, --no-embed",
|
|
9614
|
-
"Disables embedding of deployment files into output module.
|
|
9664
|
+
"Disables embedding of deployment files into output module. Useful when creating library modules intended solely for reuse/distribution via NPM."
|
|
9615
9665
|
).addOption(
|
|
9616
9666
|
new import_commander.Option(
|
|
9617
9667
|
"-i, --custom-image <custom-image>",
|
|
@@ -9652,7 +9702,7 @@ function build_default(program2) {
|
|
|
9652
9702
|
).action(async (opts) => {
|
|
9653
9703
|
outputDir = await handleCustomOutputDir(opts.outputDir);
|
|
9654
9704
|
const buildModuleResult = await buildModule(void 0, opts.entryPoint, opts.embed);
|
|
9655
|
-
const { cfg, path:
|
|
9705
|
+
const { cfg, path: path4 } = buildModuleResult;
|
|
9656
9706
|
if (opts.customName) {
|
|
9657
9707
|
process.env.PEPR_CUSTOM_BUILD_NAME = opts.customName;
|
|
9658
9708
|
}
|
|
@@ -9675,7 +9725,7 @@ function build_default(program2) {
|
|
|
9675
9725
|
);
|
|
9676
9726
|
}
|
|
9677
9727
|
if (!opts.embed) {
|
|
9678
|
-
console.info(`\u2705 Module built successfully at ${
|
|
9728
|
+
console.info(`\u2705 Module built successfully at ${path4}`);
|
|
9679
9729
|
return;
|
|
9680
9730
|
}
|
|
9681
9731
|
const assets = new Assets(
|
|
@@ -9689,7 +9739,7 @@ function build_default(program2) {
|
|
|
9689
9739
|
// Can override the rbacMode with the CLI option
|
|
9690
9740
|
rbacMode: determineRbacMode(opts, cfg)
|
|
9691
9741
|
},
|
|
9692
|
-
|
|
9742
|
+
path4,
|
|
9693
9743
|
opts.withPullSecret === "" ? [] : [opts.withPullSecret]
|
|
9694
9744
|
);
|
|
9695
9745
|
if (image !== "") assets.image = image;
|
|
@@ -9708,19 +9758,19 @@ var externalLibs = Object.keys(dependencies);
|
|
|
9708
9758
|
externalLibs.push("pepr");
|
|
9709
9759
|
externalLibs.push("@kubernetes/client-node");
|
|
9710
9760
|
async function loadModule(entryPoint = peprTS2) {
|
|
9711
|
-
const entryPointPath = (0,
|
|
9712
|
-
const modulePath = (0,
|
|
9713
|
-
const cfgPath = (0,
|
|
9761
|
+
const entryPointPath = (0, import_path4.resolve)(".", entryPoint);
|
|
9762
|
+
const modulePath = (0, import_path4.dirname)(entryPointPath);
|
|
9763
|
+
const cfgPath = (0, import_path4.resolve)(modulePath, "package.json");
|
|
9714
9764
|
try {
|
|
9715
|
-
await
|
|
9716
|
-
await
|
|
9765
|
+
await import_fs10.promises.access(cfgPath);
|
|
9766
|
+
await import_fs10.promises.access(entryPointPath);
|
|
9717
9767
|
} catch {
|
|
9718
9768
|
console.error(
|
|
9719
9769
|
`Could not find ${cfgPath} or ${entryPointPath} in the current directory. Please run this command from the root of your module's directory.`
|
|
9720
9770
|
);
|
|
9721
9771
|
process.exit(1);
|
|
9722
9772
|
}
|
|
9723
|
-
const moduleText = await
|
|
9773
|
+
const moduleText = await import_fs10.promises.readFile(cfgPath, { encoding: "utf-8" });
|
|
9724
9774
|
const cfg = JSON.parse(moduleText);
|
|
9725
9775
|
const { uuid } = cfg.pepr;
|
|
9726
9776
|
const name2 = `pepr-${uuid}.js`;
|
|
@@ -9733,13 +9783,13 @@ async function loadModule(entryPoint = peprTS2) {
|
|
|
9733
9783
|
entryPointPath,
|
|
9734
9784
|
modulePath,
|
|
9735
9785
|
name: name2,
|
|
9736
|
-
path: (0,
|
|
9786
|
+
path: (0, import_path4.resolve)(outputDir, name2),
|
|
9737
9787
|
uuid
|
|
9738
9788
|
};
|
|
9739
9789
|
}
|
|
9740
9790
|
async function buildModule(reloader, entryPoint = peprTS2, embed = true) {
|
|
9741
9791
|
try {
|
|
9742
|
-
const { cfg, modulePath, path:
|
|
9792
|
+
const { cfg, modulePath, path: path4, uuid } = await loadModule(entryPoint);
|
|
9743
9793
|
await checkFormat();
|
|
9744
9794
|
const npmRoot = (0, import_child_process3.execFileSync)("npm", ["root"]).toString().trim();
|
|
9745
9795
|
const args = ["--project", `${modulePath}/tsconfig.json`, "--outdir", outputDir];
|
|
@@ -9753,7 +9803,7 @@ async function buildModule(reloader, entryPoint = peprTS2, embed = true) {
|
|
|
9753
9803
|
legalComments: "external",
|
|
9754
9804
|
metafile: true,
|
|
9755
9805
|
minify: true,
|
|
9756
|
-
outfile:
|
|
9806
|
+
outfile: path4,
|
|
9757
9807
|
plugins: [
|
|
9758
9808
|
{
|
|
9759
9809
|
name: "reload-server",
|
|
@@ -9778,12 +9828,12 @@ async function buildModule(reloader, entryPoint = peprTS2, embed = true) {
|
|
|
9778
9828
|
}
|
|
9779
9829
|
if (!embed) {
|
|
9780
9830
|
ctxCfg.minify = false;
|
|
9781
|
-
ctxCfg.outfile = (0,
|
|
9831
|
+
ctxCfg.outfile = (0, import_path4.resolve)(outputDir, (0, import_path4.basename)(entryPoint, (0, import_path4.extname)(entryPoint))) + ".js";
|
|
9782
9832
|
ctxCfg.packages = "external";
|
|
9783
9833
|
ctxCfg.treeShaking = false;
|
|
9784
9834
|
}
|
|
9785
9835
|
const ctx = await watchForChanges(ctxCfg, reloader);
|
|
9786
|
-
return { ctx, path:
|
|
9836
|
+
return { ctx, path: path4, cfg, uuid };
|
|
9787
9837
|
} catch (e) {
|
|
9788
9838
|
handleModuleBuildError(e);
|
|
9789
9839
|
}
|
|
@@ -9832,7 +9882,7 @@ var import_prompts = __toESM(require("prompts"));
|
|
|
9832
9882
|
|
|
9833
9883
|
// src/lib/assets/deploy.ts
|
|
9834
9884
|
var import_crypto3 = __toESM(require("crypto"));
|
|
9835
|
-
var
|
|
9885
|
+
var import_fs11 = require("fs");
|
|
9836
9886
|
var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
|
|
9837
9887
|
|
|
9838
9888
|
// src/lib/k8s.ts
|
|
@@ -9941,7 +9991,7 @@ async function deployWebhook(assets, force, webhookTimeout) {
|
|
|
9941
9991
|
logger_default.info("Applying the Pepr Store CRD if it doesn't exist");
|
|
9942
9992
|
await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.CustomResourceDefinition).Apply(peprStoreCRD, { force });
|
|
9943
9993
|
if (assets.host) return;
|
|
9944
|
-
const code = await
|
|
9994
|
+
const code = await import_fs11.promises.readFile(assets.path);
|
|
9945
9995
|
if (!code.length) throw new Error("No code provided");
|
|
9946
9996
|
const hash = import_crypto3.default.createHash("sha256").update(code).digest("hex");
|
|
9947
9997
|
await setupRBAC(assets.name, assets.capabilities, force, assets.config);
|
|
@@ -10101,6 +10151,16 @@ async function buildAndDeployModule(image, force) {
|
|
|
10101
10151
|
[]
|
|
10102
10152
|
);
|
|
10103
10153
|
webhook.image = image ?? webhook.image;
|
|
10154
|
+
const capabilities = await loadCapabilities(webhook.path);
|
|
10155
|
+
for (const capability of capabilities) {
|
|
10156
|
+
namespaceComplianceValidator(capability, webhook.alwaysIgnore?.namespaces);
|
|
10157
|
+
namespaceComplianceValidator(
|
|
10158
|
+
capability,
|
|
10159
|
+
webhook.config.admission?.alwaysIgnore?.namespaces,
|
|
10160
|
+
false
|
|
10161
|
+
);
|
|
10162
|
+
namespaceComplianceValidator(capability, webhook.config.watch?.alwaysIgnore?.namespaces, true);
|
|
10163
|
+
}
|
|
10104
10164
|
try {
|
|
10105
10165
|
await webhook.deploy(deployWebhook, force, builtModule.cfg.pepr.webhookTimeout ?? 10);
|
|
10106
10166
|
validateCapabilityNames(webhook.capabilities);
|
|
@@ -10133,7 +10193,7 @@ function deploy_default(program2) {
|
|
|
10133
10193
|
var import_prompts2 = __toESM(require("prompts"));
|
|
10134
10194
|
var import_child_process4 = require("child_process");
|
|
10135
10195
|
var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
|
|
10136
|
-
var
|
|
10196
|
+
var import_fs12 = require("fs");
|
|
10137
10197
|
function dev_default(program2) {
|
|
10138
10198
|
program2.command("dev").description("Setup a local webhook development environment").option("-h, --host [host]", "Host to listen on", "host.k3d.internal").option("--confirm", "Skip confirmation prompt").action(async (opts) => {
|
|
10139
10199
|
if (!opts.confirm) {
|
|
@@ -10146,25 +10206,25 @@ function dev_default(program2) {
|
|
|
10146
10206
|
process.exit(0);
|
|
10147
10207
|
}
|
|
10148
10208
|
}
|
|
10149
|
-
const { cfg, path:
|
|
10209
|
+
const { cfg, path: path4 } = await loadModule();
|
|
10150
10210
|
const webhook = new Assets(
|
|
10151
10211
|
{
|
|
10152
10212
|
...cfg.pepr,
|
|
10153
10213
|
description: cfg.description
|
|
10154
10214
|
},
|
|
10155
|
-
|
|
10215
|
+
path4,
|
|
10156
10216
|
[],
|
|
10157
10217
|
opts.host
|
|
10158
10218
|
);
|
|
10159
|
-
await
|
|
10160
|
-
await
|
|
10219
|
+
await import_fs12.promises.writeFile("insecure-tls.crt", webhook.tls.pem.crt);
|
|
10220
|
+
await import_fs12.promises.writeFile("insecure-tls.key", webhook.tls.pem.key);
|
|
10161
10221
|
try {
|
|
10162
10222
|
let program3;
|
|
10163
10223
|
const name2 = `pepr-${cfg.pepr.uuid}`;
|
|
10164
10224
|
const scheduleStore = `pepr-${cfg.pepr.uuid}-schedule`;
|
|
10165
10225
|
const store = `pepr-${cfg.pepr.uuid}-store`;
|
|
10166
10226
|
const runFork = async () => {
|
|
10167
|
-
console.info(`Running module ${
|
|
10227
|
+
console.info(`Running module ${path4}`);
|
|
10168
10228
|
await webhook.deploy(deployWebhook, false, 30);
|
|
10169
10229
|
try {
|
|
10170
10230
|
validateCapabilityNames(webhook.capabilities);
|
|
@@ -10172,7 +10232,7 @@ function dev_default(program2) {
|
|
|
10172
10232
|
console.error(`Error validating capability names:`, e);
|
|
10173
10233
|
process.exit(1);
|
|
10174
10234
|
}
|
|
10175
|
-
program3 = (0, import_child_process4.fork)(
|
|
10235
|
+
program3 = (0, import_child_process4.fork)(path4, {
|
|
10176
10236
|
env: {
|
|
10177
10237
|
...process.env,
|
|
10178
10238
|
LOG_LEVEL: process.env.LOG_LEVEL ?? "debug",
|
|
@@ -10306,11 +10366,11 @@ ${filteredFailures.length > 0 ? "\u274C" : "\u2705"} VALIDATE ${name2} (${uid
|
|
|
10306
10366
|
|
|
10307
10367
|
// src/cli/init/index.ts
|
|
10308
10368
|
var import_child_process5 = require("child_process");
|
|
10309
|
-
var
|
|
10369
|
+
var import_path5 = require("path");
|
|
10310
10370
|
var import_prompts4 = __toESM(require("prompts"));
|
|
10311
10371
|
|
|
10312
10372
|
// src/cli/init/walkthrough.ts
|
|
10313
|
-
var
|
|
10373
|
+
var import_fs13 = require("fs");
|
|
10314
10374
|
var import_prompts3 = __toESM(require("prompts"));
|
|
10315
10375
|
|
|
10316
10376
|
// src/cli/init/enums.ts
|
|
@@ -10357,7 +10417,7 @@ async function setName(name2) {
|
|
|
10357
10417
|
validate: async (val) => {
|
|
10358
10418
|
try {
|
|
10359
10419
|
const name3 = sanitizeName(val);
|
|
10360
|
-
await
|
|
10420
|
+
await import_fs13.promises.access(name3, import_fs13.promises.constants.F_OK);
|
|
10361
10421
|
return "A directory with this name already exists";
|
|
10362
10422
|
} catch {
|
|
10363
10423
|
return val.length > 2 || "The name must be at least 3 characters long";
|
|
@@ -10502,8 +10562,8 @@ function init_default(program2) {
|
|
|
10502
10562
|
}
|
|
10503
10563
|
async function setupProjectStructure(dirName) {
|
|
10504
10564
|
await createDir(dirName);
|
|
10505
|
-
await createDir((0,
|
|
10506
|
-
await createDir((0,
|
|
10565
|
+
await createDir((0, import_path5.resolve)(dirName, ".vscode"));
|
|
10566
|
+
await createDir((0, import_path5.resolve)(dirName, "capabilities"));
|
|
10507
10567
|
}
|
|
10508
10568
|
async function createProjectFiles(dirName, packageJSON2) {
|
|
10509
10569
|
const files = [
|
|
@@ -10522,10 +10582,10 @@ async function createProjectFiles(dirName, packageJSON2) {
|
|
|
10522
10582
|
{ dir: "capabilities", path: helloPepr.path, data: helloPepr.data }
|
|
10523
10583
|
];
|
|
10524
10584
|
for (const file of files) {
|
|
10525
|
-
await write((0,
|
|
10585
|
+
await write((0, import_path5.resolve)(dirName, file.path), file.data);
|
|
10526
10586
|
}
|
|
10527
10587
|
for (const file of nestedFiles) {
|
|
10528
|
-
await write((0,
|
|
10588
|
+
await write((0, import_path5.resolve)(dirName, file.dir, file.path), file.data);
|
|
10529
10589
|
}
|
|
10530
10590
|
}
|
|
10531
10591
|
var doPostInitActions = (dirName) => {
|
|
@@ -10581,10 +10641,10 @@ var RootCmd = class extends import_commander2.Command {
|
|
|
10581
10641
|
}
|
|
10582
10642
|
};
|
|
10583
10643
|
|
|
10584
|
-
// src/cli/update.ts
|
|
10644
|
+
// src/cli/update/index.ts
|
|
10585
10645
|
var import_child_process6 = require("child_process");
|
|
10586
|
-
var
|
|
10587
|
-
var
|
|
10646
|
+
var import_fs14 = __toESM(require("fs"));
|
|
10647
|
+
var import_path6 = require("path");
|
|
10588
10648
|
var import_prompts5 = __toESM(require("prompts"));
|
|
10589
10649
|
function update_default(program2) {
|
|
10590
10650
|
program2.command("update").description("Update this Pepr module. Not recommended for prod as it may change files.").option("--skip-template-update", "Skip updating the template files").action(async (opts) => {
|
|
@@ -10600,6 +10660,22 @@ function update_default(program2) {
|
|
|
10600
10660
|
}
|
|
10601
10661
|
console.log("Updating the Pepr module...");
|
|
10602
10662
|
try {
|
|
10663
|
+
let packageLockContent = "";
|
|
10664
|
+
let foundPackageLock = false;
|
|
10665
|
+
try {
|
|
10666
|
+
if (import_fs14.default.existsSync("./package-lock.json")) {
|
|
10667
|
+
packageLockContent = import_fs14.default.readFileSync("./package-lock.json", "utf-8");
|
|
10668
|
+
foundPackageLock = true;
|
|
10669
|
+
}
|
|
10670
|
+
} catch {
|
|
10671
|
+
}
|
|
10672
|
+
if (foundPackageLock && packageLockContent) {
|
|
10673
|
+
if (packageLockContent.indexOf('"eslint":') >= 0 && packageLockContent.match(/"eslint":\s*"[~^]?8\.[0-9]+\.[0-9]+"/)) {
|
|
10674
|
+
console.warn(
|
|
10675
|
+
"\nWarning: This Pepr module uses ESLint v8. Pepr will be upgraded to use v9 in a future release.\nSee eslint@9.0.0 release notes for more details: https://eslint.org/blog/2024/04/eslint-v9.0.0-released/"
|
|
10676
|
+
);
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10603
10679
|
(0, import_child_process6.execSync)("npm install pepr@latest", {
|
|
10604
10680
|
stdio: "inherit"
|
|
10605
10681
|
});
|
|
@@ -10618,17 +10694,17 @@ function update_default(program2) {
|
|
|
10618
10694
|
console.log("Updating Pepr config and template tiles...");
|
|
10619
10695
|
try {
|
|
10620
10696
|
if (!opts.skipTemplateUpdate) {
|
|
10621
|
-
await write((0,
|
|
10622
|
-
await write((0,
|
|
10623
|
-
await write((0,
|
|
10624
|
-
await write((0,
|
|
10625
|
-
const samplePath = (0,
|
|
10626
|
-
if (
|
|
10627
|
-
|
|
10697
|
+
await write((0, import_path6.resolve)(prettier.path), prettier.data);
|
|
10698
|
+
await write((0, import_path6.resolve)(tsConfig.path), tsConfig.data);
|
|
10699
|
+
await write((0, import_path6.resolve)(".vscode", snippet.path), snippet.data);
|
|
10700
|
+
await write((0, import_path6.resolve)(".vscode", codeSettings.path), codeSettings.data);
|
|
10701
|
+
const samplePath = (0, import_path6.resolve)("capabilities", samplesYaml.path);
|
|
10702
|
+
if (import_fs14.default.existsSync(samplePath)) {
|
|
10703
|
+
import_fs14.default.unlinkSync(samplePath);
|
|
10628
10704
|
await write(samplePath, samplesYaml.data);
|
|
10629
10705
|
}
|
|
10630
|
-
const tsPath = (0,
|
|
10631
|
-
if (
|
|
10706
|
+
const tsPath = (0, import_path6.resolve)("capabilities", helloPepr.path);
|
|
10707
|
+
if (import_fs14.default.existsSync(tsPath)) {
|
|
10632
10708
|
await write(tsPath, helloPepr.data);
|
|
10633
10709
|
}
|
|
10634
10710
|
}
|
|
@@ -10669,8 +10745,8 @@ function kfc_default(program2) {
|
|
|
10669
10745
|
|
|
10670
10746
|
// src/cli/crd/create.ts
|
|
10671
10747
|
var import_commander3 = require("commander");
|
|
10672
|
-
var
|
|
10673
|
-
var
|
|
10748
|
+
var import_fs15 = require("fs");
|
|
10749
|
+
var import_path7 = __toESM(require("path"));
|
|
10674
10750
|
var create = new import_commander3.Command("create").description("Create a new CRD TypeScript definition").requiredOption("--group <group>", "API group (e.g. cache)").requiredOption("--version <version>", "API version (e.g. v1alpha1)").requiredOption("--kind <kind>", "Kind name (e.g. Memcached)").option("--domain <domain>", "Optional domain (e.g. pepr.dev)", "pepr.dev").option(
|
|
10675
10751
|
"--scope <Namespaced | Cluster>",
|
|
10676
10752
|
"Whether the resulting custom resource is cluster- or namespace-scoped",
|
|
@@ -10678,9 +10754,9 @@ var create = new import_commander3.Command("create").description("Create a new C
|
|
|
10678
10754
|
"Namespaced"
|
|
10679
10755
|
).option("--plural <plural>", "Plural name (e.g. memcacheds)", "").option("--shortName <shortName>", "Short name (e.g. mc)", "").action(async ({ group: group2, version: version3, kind: kind8, domain, scope, plural: plural2, shortName }) => {
|
|
10680
10756
|
console.log("This feature is currently in alpha.\n");
|
|
10681
|
-
const outputDir2 =
|
|
10757
|
+
const outputDir2 = import_path7.default.resolve(`./api/${version3}`);
|
|
10682
10758
|
await createDirectoryIfNotExists(outputDir2);
|
|
10683
|
-
await
|
|
10759
|
+
await import_fs15.promises.writeFile(
|
|
10684
10760
|
`./api/${version3}/${kind8.toLowerCase()}_types.ts`,
|
|
10685
10761
|
generateCRDScaffold(group2, version3, kind8, { domain, scope, plural: plural2, shortName })
|
|
10686
10762
|
);
|
|
@@ -10775,10 +10851,24 @@ function validateScope(value) {
|
|
|
10775
10851
|
|
|
10776
10852
|
// src/cli/crd/generate.ts
|
|
10777
10853
|
var import_commander4 = require("commander");
|
|
10778
|
-
var
|
|
10779
|
-
var
|
|
10854
|
+
var import_fs16 = __toESM(require("fs"));
|
|
10855
|
+
var import_path8 = __toESM(require("path"));
|
|
10780
10856
|
var import_yaml = __toESM(require_dist());
|
|
10781
10857
|
var import_ts_morph = require("ts-morph");
|
|
10858
|
+
|
|
10859
|
+
// src/cli/crd/messages.ts
|
|
10860
|
+
var ErrorMessages = {
|
|
10861
|
+
MISSING_DETAILS: "Missing 'details' variable declaration.",
|
|
10862
|
+
INVALID_SCOPE: (scope) => `'scope' must be either "Cluster" or "Namespaced", got "${scope}"`,
|
|
10863
|
+
MISSING_OR_INVALID_KEY: (key) => `Missing or invalid value for required key: '${key}'`
|
|
10864
|
+
};
|
|
10865
|
+
var WarningMessages = {
|
|
10866
|
+
MISSING_DETAILS: "Missing 'details' variable declaration.",
|
|
10867
|
+
MISSING_KIND_COMMENT: (fileName) => `Skipping ${fileName}: missing '// Kind: <KindName>' comment`,
|
|
10868
|
+
MISSING_INTERFACE: (fileName, kind8) => `Skipping ${fileName}: missing interface ${kind8}Spec`
|
|
10869
|
+
};
|
|
10870
|
+
|
|
10871
|
+
// src/cli/crd/generate.ts
|
|
10782
10872
|
var generate_default = new import_commander4.Command("generate").description("Generate CRD manifests from TypeScript definitions").option("--output <output>", "Output directory for generated CRDs", "./crds").action(generateCRDs);
|
|
10783
10873
|
function extractCRDDetails(content, sourceFile) {
|
|
10784
10874
|
const kind8 = extractSingleLineComment(content, "Kind");
|
|
@@ -10792,36 +10882,36 @@ function extractCRDDetails(content, sourceFile) {
|
|
|
10792
10882
|
}
|
|
10793
10883
|
async function generateCRDs(options) {
|
|
10794
10884
|
console.log("This feature is currently in alpha.\n");
|
|
10795
|
-
const outputDir2 =
|
|
10885
|
+
const outputDir2 = import_path8.default.resolve(options.output);
|
|
10796
10886
|
await createDirectoryIfNotExists(outputDir2);
|
|
10797
10887
|
const project = new import_ts_morph.Project();
|
|
10798
|
-
const apiRoot =
|
|
10888
|
+
const apiRoot = import_path8.default.resolve("api");
|
|
10799
10889
|
const versions = getAPIVersions(apiRoot);
|
|
10800
10890
|
for (const version3 of versions) {
|
|
10801
|
-
const sourceFiles = loadVersionFiles(project,
|
|
10891
|
+
const sourceFiles = loadVersionFiles(project, import_path8.default.join(apiRoot, version3));
|
|
10802
10892
|
for (const sourceFile of sourceFiles) {
|
|
10803
10893
|
processSourceFile(sourceFile, version3, outputDir2);
|
|
10804
10894
|
}
|
|
10805
10895
|
}
|
|
10806
10896
|
}
|
|
10807
10897
|
function getAPIVersions(apiRoot) {
|
|
10808
|
-
return
|
|
10898
|
+
return import_fs16.default.readdirSync(apiRoot).filter((v) => import_fs16.default.statSync(import_path8.default.join(apiRoot, v)).isDirectory());
|
|
10809
10899
|
}
|
|
10810
10900
|
function loadVersionFiles(project, versionDir) {
|
|
10811
|
-
const files =
|
|
10812
|
-
const filePaths = files.map((f) =>
|
|
10901
|
+
const files = import_fs16.default.readdirSync(versionDir).filter((f) => f.endsWith(".ts"));
|
|
10902
|
+
const filePaths = files.map((f) => import_path8.default.join(versionDir, f));
|
|
10813
10903
|
return project.addSourceFilesAtPaths(filePaths);
|
|
10814
10904
|
}
|
|
10815
10905
|
function processSourceFile(sourceFile, version3, outputDir2) {
|
|
10816
10906
|
const content = sourceFile.getFullText();
|
|
10817
10907
|
const { kind: kind8, fqdn, scope, plural: plural2, shortNames } = extractCRDDetails(content, sourceFile);
|
|
10818
10908
|
if (!kind8) {
|
|
10819
|
-
console.warn(
|
|
10909
|
+
console.warn(WarningMessages.MISSING_KIND_COMMENT(sourceFile.getBaseName()));
|
|
10820
10910
|
return;
|
|
10821
10911
|
}
|
|
10822
10912
|
const spec = sourceFile.getInterface(`${kind8}Spec`);
|
|
10823
10913
|
if (!spec) {
|
|
10824
|
-
console.warn(
|
|
10914
|
+
console.warn(WarningMessages.MISSING_INTERFACE(sourceFile.getBaseName(), kind8));
|
|
10825
10915
|
return;
|
|
10826
10916
|
}
|
|
10827
10917
|
const condition = sourceFile.getTypeAlias(`${kind8}StatusCondition`);
|
|
@@ -10837,8 +10927,8 @@ function processSourceFile(sourceFile, version3, outputDir2) {
|
|
|
10837
10927
|
specSchema,
|
|
10838
10928
|
conditionSchema
|
|
10839
10929
|
});
|
|
10840
|
-
const outPath =
|
|
10841
|
-
|
|
10930
|
+
const outPath = import_path8.default.join(outputDir2, `${kind8.toLowerCase()}.yaml`);
|
|
10931
|
+
import_fs16.default.writeFileSync(outPath, (0, import_yaml.stringify)(crd), "utf8");
|
|
10842
10932
|
console.log(`\u2714 Created ${outPath}`);
|
|
10843
10933
|
}
|
|
10844
10934
|
function extractSingleLineComment(content, label) {
|
|
@@ -10848,14 +10938,14 @@ function extractSingleLineComment(content, label) {
|
|
|
10848
10938
|
function extractDetails(sourceFile) {
|
|
10849
10939
|
const decl = sourceFile.getVariableDeclaration("details");
|
|
10850
10940
|
if (!decl) {
|
|
10851
|
-
throw new Error(
|
|
10941
|
+
throw new Error(ErrorMessages.MISSING_DETAILS);
|
|
10852
10942
|
}
|
|
10853
10943
|
const init = decl.getInitializerIfKindOrThrow(import_ts_morph.SyntaxKind.ObjectLiteralExpression);
|
|
10854
10944
|
const getStr = (key) => {
|
|
10855
10945
|
const prop = init.getProperty(key);
|
|
10856
10946
|
const value = prop?.getFirstChildByKind(import_ts_morph.SyntaxKind.StringLiteral)?.getLiteralText();
|
|
10857
10947
|
if (!value) {
|
|
10858
|
-
throw new Error(
|
|
10948
|
+
throw new Error(ErrorMessages.MISSING_OR_INVALID_KEY(key));
|
|
10859
10949
|
}
|
|
10860
10950
|
return value;
|
|
10861
10951
|
};
|
|
@@ -10867,7 +10957,7 @@ function extractDetails(sourceFile) {
|
|
|
10867
10957
|
shortName: getStr("shortName")
|
|
10868
10958
|
};
|
|
10869
10959
|
}
|
|
10870
|
-
throw new Error(
|
|
10960
|
+
throw new Error(ErrorMessages.INVALID_SCOPE(scope));
|
|
10871
10961
|
}
|
|
10872
10962
|
function getJsDocDescription(node) {
|
|
10873
10963
|
if (!import_ts_morph.Node.isPropertySignature(node) && !import_ts_morph.Node.isPropertyDeclaration(node)) return "";
|