pepr 0.47.0 → 0.48.1

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/lib.js CHANGED
@@ -31,22 +31,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var lib_exports = {};
32
32
  __export(lib_exports, {
33
33
  Capability: () => Capability,
34
- K8s: () => import_kubernetes_fluent_client8.K8s,
34
+ K8s: () => import_kubernetes_fluent_client9.K8s,
35
35
  Log: () => logger_default,
36
36
  PeprModule: () => PeprModule,
37
37
  PeprMutateRequest: () => PeprMutateRequest,
38
38
  PeprUtils: () => utils_exports,
39
39
  PeprValidateRequest: () => PeprValidateRequest,
40
40
  R: () => R,
41
- RegisterKind: () => import_kubernetes_fluent_client8.RegisterKind,
42
- a: () => import_kubernetes_fluent_client8.kind,
43
- fetch: () => import_kubernetes_fluent_client8.fetch,
44
- fetchStatus: () => import_kubernetes_fluent_client8.fetchStatus,
45
- kind: () => import_kubernetes_fluent_client8.kind,
41
+ RegisterKind: () => import_kubernetes_fluent_client9.RegisterKind,
42
+ a: () => import_kubernetes_fluent_client9.kind,
43
+ fetch: () => import_kubernetes_fluent_client9.fetch,
44
+ fetchStatus: () => import_kubernetes_fluent_client9.fetchStatus,
45
+ kind: () => import_kubernetes_fluent_client9.kind,
46
46
  sdk: () => sdk_exports
47
47
  });
48
48
  module.exports = __toCommonJS(lib_exports);
49
- var import_kubernetes_fluent_client8 = require("kubernetes-fluent-client");
49
+ var import_kubernetes_fluent_client9 = require("kubernetes-fluent-client");
50
50
  var R = __toESM(require("ramda"));
51
51
 
52
52
  // src/lib/core/capability.ts
@@ -735,7 +735,7 @@ var Capability = class {
735
735
  };
736
736
 
737
737
  // src/lib/core/module.ts
738
- var import_ramda13 = require("ramda");
738
+ var import_ramda14 = require("ramda");
739
739
 
740
740
  // src/lib/controller/index.ts
741
741
  var import_express = __toESM(require("express"));
@@ -1621,9 +1621,10 @@ var PeprValidateRequest = class {
1621
1621
  *
1622
1622
  * @returns The validation response.
1623
1623
  */
1624
- Approve = () => {
1624
+ Approve = (warnings) => {
1625
1625
  return {
1626
- allowed: true
1626
+ allowed: true,
1627
+ warnings
1627
1628
  };
1628
1629
  };
1629
1630
  /**
@@ -1633,11 +1634,12 @@ var PeprValidateRequest = class {
1633
1634
  * @param statusCode Optional status code to return to the user.
1634
1635
  * @returns The validation response.
1635
1636
  */
1636
- Deny = (statusMessage, statusCode) => {
1637
+ Deny = (statusMessage, statusCode, warnings) => {
1637
1638
  return {
1638
1639
  allowed: false,
1639
1640
  statusCode,
1640
- statusMessage
1641
+ statusMessage,
1642
+ warnings
1641
1643
  };
1642
1644
  };
1643
1645
  };
@@ -1660,6 +1662,9 @@ async function processRequest2(binding, actionMetadata, peprValidateRequest) {
1660
1662
  message: callbackResp.statusMessage || `Validation failed for ${name}`
1661
1663
  };
1662
1664
  }
1665
+ if (callbackResp.warnings && callbackResp.warnings.length > 0) {
1666
+ valResp.warnings = callbackResp.warnings;
1667
+ }
1663
1668
  logger_default.info(
1664
1669
  actionMetadata,
1665
1670
  `Validation action complete (${label}): ${callbackResp.allowed ? "allowed" : "denied"}`
@@ -1709,8 +1714,8 @@ async function validateProcessor(config, capabilities, req, reqMetadata) {
1709
1714
  }
1710
1715
 
1711
1716
  // src/lib/controller/store.ts
1712
- var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
1713
- var import_ramda12 = require("ramda");
1717
+ var import_kubernetes_fluent_client6 = require("kubernetes-fluent-client");
1718
+ var import_ramda13 = require("ramda");
1714
1719
 
1715
1720
  // src/lib/k8s.ts
1716
1721
  var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
@@ -1772,6 +1777,41 @@ function updateCacheID(payload) {
1772
1777
  return payload;
1773
1778
  }
1774
1779
 
1780
+ // src/lib/controller/migrateStore.ts
1781
+ var import_ramda12 = require("ramda");
1782
+ var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
1783
+ async function migrateAndSetupWatch(storeData) {
1784
+ const { store, namespace: namespace2, name: name2, stores, setupWatch: setupWatch2 } = storeData;
1785
+ logger_default.debug(redactedStore(store), "Pepr Store migration");
1786
+ await (0, import_kubernetes_fluent_client5.K8s)(Store, { namespace: namespace2, name: name2 }).Patch([
1787
+ {
1788
+ op: "add",
1789
+ path: "/metadata/labels/pepr.dev-cacheID",
1790
+ value: `${Date.now()}`
1791
+ }
1792
+ ]);
1793
+ const data = store.data;
1794
+ let storeCache = {};
1795
+ for (const name3 of Object.keys(stores)) {
1796
+ const offset = `${name3}-`.length;
1797
+ for (const key of Object.keys(data)) {
1798
+ if ((0, import_ramda12.startsWith)(name3, key) && !(0, import_ramda12.startsWith)(`${name3}-v2`, key)) {
1799
+ storeCache = fillStoreCache(storeCache, name3, "remove", {
1800
+ key: [key.slice(offset)],
1801
+ value: data[key]
1802
+ });
1803
+ storeCache = fillStoreCache(storeCache, name3, "add", {
1804
+ key: [key.slice(offset)],
1805
+ value: data[key],
1806
+ version: "v2"
1807
+ });
1808
+ }
1809
+ }
1810
+ }
1811
+ storeCache = await sendUpdatesAndFlushCache(storeCache, namespace2, name2);
1812
+ setupWatch2();
1813
+ }
1814
+
1775
1815
  // src/lib/controller/store.ts
1776
1816
  var namespace = "pepr-system";
1777
1817
  var debounceBackoffReceive = 1e3;
@@ -1801,45 +1841,23 @@ var StoreController = class {
1801
1841
  }
1802
1842
  }
1803
1843
  setTimeout(
1804
- () => (0, import_kubernetes_fluent_client5.K8s)(Store).InNamespace(namespace).Get(this.#name).then(async (store) => await this.#migrateAndSetupWatch(store)).catch(this.#createStoreResource),
1844
+ () => (0, import_kubernetes_fluent_client6.K8s)(Store).InNamespace(namespace).Get(this.#name).then(
1845
+ async (store) => await migrateAndSetupWatch({
1846
+ name: name2,
1847
+ namespace,
1848
+ store,
1849
+ stores: this.#stores,
1850
+ setupWatch: this.#setupWatch
1851
+ })
1852
+ ).catch(this.#createStoreResource),
1805
1853
  Math.random() * 3e3
1806
1854
  // Add a jitter to the Store creation to avoid collisions
1807
1855
  );
1808
1856
  }
1809
1857
  #setupWatch = () => {
1810
- const watcher = (0, import_kubernetes_fluent_client5.K8s)(Store, { name: this.#name, namespace }).Watch(this.#receive);
1858
+ const watcher = (0, import_kubernetes_fluent_client6.K8s)(Store, { name: this.#name, namespace }).Watch(this.#receive);
1811
1859
  watcher.start().catch((e) => logger_default.error(e, "Error starting Pepr store watch"));
1812
1860
  };
1813
- #migrateAndSetupWatch = async (store) => {
1814
- logger_default.debug(redactedStore(store), "Pepr Store migration");
1815
- await (0, import_kubernetes_fluent_client5.K8s)(Store, { namespace, name: this.#name }).Patch([
1816
- {
1817
- op: "add",
1818
- path: "/metadata/labels/pepr.dev-cacheID",
1819
- value: `${Date.now()}`
1820
- }
1821
- ]);
1822
- const data = store.data || {};
1823
- let storeCache = {};
1824
- for (const name2 of Object.keys(this.#stores)) {
1825
- const offset = `${name2}-`.length;
1826
- for (const key of Object.keys(data)) {
1827
- if ((0, import_ramda12.startsWith)(name2, key) && !(0, import_ramda12.startsWith)(`${name2}-v2`, key)) {
1828
- storeCache = fillStoreCache(storeCache, name2, "remove", {
1829
- key: [key.slice(offset)],
1830
- value: data[key]
1831
- });
1832
- storeCache = fillStoreCache(storeCache, name2, "add", {
1833
- key: [key.slice(offset)],
1834
- value: data[key],
1835
- version: "v2"
1836
- });
1837
- }
1838
- }
1839
- }
1840
- storeCache = await sendUpdatesAndFlushCache(storeCache, namespace, this.#name);
1841
- this.#setupWatch();
1842
- };
1843
1861
  #receive = (store) => {
1844
1862
  logger_default.debug(redactedStore(store), "Pepr Store update");
1845
1863
  const debounced = () => {
@@ -1848,7 +1866,7 @@ var StoreController = class {
1848
1866
  const offset = `${name2}-`.length;
1849
1867
  const filtered = {};
1850
1868
  for (const key of Object.keys(data)) {
1851
- if ((0, import_ramda12.startsWith)(name2, key)) {
1869
+ if ((0, import_ramda13.startsWith)(name2, key)) {
1852
1870
  filtered[key.slice(offset)] = data[key];
1853
1871
  }
1854
1872
  }
@@ -1879,7 +1897,7 @@ var StoreController = class {
1879
1897
  logger_default.info(`Pepr store not found, creating...`);
1880
1898
  logger_default.debug(e);
1881
1899
  try {
1882
- await (0, import_kubernetes_fluent_client5.K8s)(Store).Apply({
1900
+ await (0, import_kubernetes_fluent_client6.K8s)(Store).Apply({
1883
1901
  metadata: {
1884
1902
  name: this.#name,
1885
1903
  namespace,
@@ -1909,17 +1927,25 @@ function karForMutate(mr) {
1909
1927
  }
1910
1928
  function karForValidate(ar, vr) {
1911
1929
  const isAllowed = vr.filter((r) => !r.allowed).length === 0;
1930
+ const warnings = vr.reduce((acc, curr) => {
1931
+ if (curr.warnings && curr.warnings.length > 0) {
1932
+ return [...acc, ...curr.warnings];
1933
+ }
1934
+ return acc;
1935
+ }, []);
1912
1936
  const resp = vr.length === 0 ? {
1913
1937
  uid: ar.uid,
1914
1938
  allowed: true,
1915
- status: { code: 200, message: "no in-scope validations -- allowed!" }
1939
+ status: { code: 200, message: "no in-scope validations -- allowed!" },
1940
+ warnings: warnings.length > 0 ? warnings : void 0
1916
1941
  } : {
1917
1942
  uid: vr[0].uid,
1918
1943
  allowed: isAllowed,
1919
1944
  status: {
1920
1945
  code: isAllowed ? 200 : 422,
1921
1946
  message: vr.filter((rl) => !rl.allowed).map((curr) => curr.status?.message).join("; ")
1922
- }
1947
+ },
1948
+ warnings: warnings.length > 0 ? warnings : void 0
1923
1949
  };
1924
1950
  return {
1925
1951
  apiVersion: "admission.k8s.io/v1",
@@ -2151,7 +2177,7 @@ function ValidateError(error = "") {
2151
2177
  }
2152
2178
 
2153
2179
  // src/lib/processors/watch-processor.ts
2154
- var import_kubernetes_fluent_client6 = require("kubernetes-fluent-client");
2180
+ var import_kubernetes_fluent_client7 = require("kubernetes-fluent-client");
2155
2181
 
2156
2182
  // src/lib/core/queue.ts
2157
2183
  var import_node_crypto = require("node:crypto");
@@ -2281,11 +2307,11 @@ var eventToPhaseMap = {
2281
2307
  ["*" /* ANY */]: [import_types.WatchPhase.Added, import_types.WatchPhase.Modified, import_types.WatchPhase.Deleted]
2282
2308
  };
2283
2309
  function setupWatch(capabilities, ignoredNamespaces) {
2284
- capabilities.map(
2285
- (capability) => capability.bindings.filter((binding) => binding.isWatch).forEach(
2286
- (bindingElement) => runBinding(bindingElement, capability.namespaces, ignoredNamespaces)
2287
- )
2288
- );
2310
+ for (const capability of capabilities) {
2311
+ for (const binding of capability.bindings.filter((b) => b.isWatch)) {
2312
+ runBinding(binding, capability.namespaces, ignoredNamespaces);
2313
+ }
2314
+ }
2289
2315
  }
2290
2316
  async function runBinding(binding, capabilityNamespaces, ignoredNamespaces) {
2291
2317
  const phaseMatch = eventToPhaseMap[binding.event] || eventToPhaseMap["*" /* ANY */];
@@ -2334,7 +2360,7 @@ async function runBinding(binding, capabilityNamespaces, ignoredNamespaces) {
2334
2360
  }
2335
2361
  }
2336
2362
  };
2337
- const watcher = (0, import_kubernetes_fluent_client6.K8s)(binding.model, { ...binding.filters, kindOverride: binding.kind }).Watch(
2363
+ const watcher = (0, import_kubernetes_fluent_client7.K8s)(binding.model, { ...binding.filters, kindOverride: binding.kind }).Watch(
2338
2364
  async (obj, phase) => {
2339
2365
  logger_default.debug(obj, `Watch event ${phase} received`);
2340
2366
  if (binding.isQueue) {
@@ -2346,12 +2372,18 @@ async function runBinding(binding, capabilityNamespaces, ignoredNamespaces) {
2346
2372
  },
2347
2373
  watchCfg
2348
2374
  );
2349
- registerWatchEventHandlers(watcher, logEvent, metricsCollector);
2375
+ try {
2376
+ registerWatchEventHandlers(watcher, logEvent, metricsCollector);
2377
+ } catch (err) {
2378
+ throw new Error(
2379
+ "WatchEventHandler Registration Error: Unable to register event watch handler.",
2380
+ { cause: err }
2381
+ );
2382
+ }
2350
2383
  try {
2351
2384
  await watcher.start();
2352
2385
  } catch (err) {
2353
- logger_default.error(err, "Error starting watch");
2354
- process.exit(1);
2386
+ throw new Error("WatchStart Error: Unable to start watch.", { cause: err });
2355
2387
  }
2356
2388
  }
2357
2389
  function logEvent(event, message = "", obj) {
@@ -2364,26 +2396,29 @@ function logEvent(event, message = "", obj) {
2364
2396
  }
2365
2397
  function registerWatchEventHandlers(watcher, logEvent2, metricsCollector2) {
2366
2398
  const eventHandlers = {
2367
- [import_kubernetes_fluent_client6.WatchEvent.DATA]: () => null,
2368
- [import_kubernetes_fluent_client6.WatchEvent.GIVE_UP]: (err) => {
2369
- logEvent2(import_kubernetes_fluent_client6.WatchEvent.GIVE_UP, err.message);
2370
- process.exit(1);
2399
+ [import_kubernetes_fluent_client7.WatchEvent.DATA]: () => null,
2400
+ [import_kubernetes_fluent_client7.WatchEvent.GIVE_UP]: (err) => {
2401
+ logEvent2(import_kubernetes_fluent_client7.WatchEvent.GIVE_UP, err.message);
2402
+ throw new Error(
2403
+ "WatchEvent GiveUp Error: The watch has failed to start after several attempts.",
2404
+ { cause: err }
2405
+ );
2371
2406
  },
2372
- [import_kubernetes_fluent_client6.WatchEvent.CONNECT]: (url) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.CONNECT, url),
2373
- [import_kubernetes_fluent_client6.WatchEvent.DATA_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.DATA_ERROR, err.message),
2374
- [import_kubernetes_fluent_client6.WatchEvent.RECONNECT]: (retryCount) => logEvent2(
2375
- import_kubernetes_fluent_client6.WatchEvent.RECONNECT,
2407
+ [import_kubernetes_fluent_client7.WatchEvent.CONNECT]: (url) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.CONNECT, url),
2408
+ [import_kubernetes_fluent_client7.WatchEvent.DATA_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.DATA_ERROR, err.message),
2409
+ [import_kubernetes_fluent_client7.WatchEvent.RECONNECT]: (retryCount) => logEvent2(
2410
+ import_kubernetes_fluent_client7.WatchEvent.RECONNECT,
2376
2411
  `Reconnecting after ${retryCount} attempt${retryCount === 1 ? "" : "s"}`
2377
2412
  ),
2378
- [import_kubernetes_fluent_client6.WatchEvent.RECONNECT_PENDING]: () => logEvent2(import_kubernetes_fluent_client6.WatchEvent.RECONNECT_PENDING),
2379
- [import_kubernetes_fluent_client6.WatchEvent.ABORT]: (err) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.ABORT, err.message),
2380
- [import_kubernetes_fluent_client6.WatchEvent.OLD_RESOURCE_VERSION]: (errMessage) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.OLD_RESOURCE_VERSION, errMessage),
2381
- [import_kubernetes_fluent_client6.WatchEvent.NETWORK_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.NETWORK_ERROR, err.message),
2382
- [import_kubernetes_fluent_client6.WatchEvent.LIST_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.LIST_ERROR, err.message),
2383
- [import_kubernetes_fluent_client6.WatchEvent.LIST]: (list) => logEvent2(import_kubernetes_fluent_client6.WatchEvent.LIST, JSON.stringify(list, void 0, 2)),
2384
- [import_kubernetes_fluent_client6.WatchEvent.CACHE_MISS]: (windowName) => metricsCollector2.incCacheMiss(windowName),
2385
- [import_kubernetes_fluent_client6.WatchEvent.INIT_CACHE_MISS]: (windowName) => metricsCollector2.initCacheMissWindow(windowName),
2386
- [import_kubernetes_fluent_client6.WatchEvent.INC_RESYNC_FAILURE_COUNT]: (retryCount) => metricsCollector2.incRetryCount(retryCount)
2413
+ [import_kubernetes_fluent_client7.WatchEvent.RECONNECT_PENDING]: () => logEvent2(import_kubernetes_fluent_client7.WatchEvent.RECONNECT_PENDING),
2414
+ [import_kubernetes_fluent_client7.WatchEvent.ABORT]: (err) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.ABORT, err.message),
2415
+ [import_kubernetes_fluent_client7.WatchEvent.OLD_RESOURCE_VERSION]: (errMessage) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.OLD_RESOURCE_VERSION, errMessage),
2416
+ [import_kubernetes_fluent_client7.WatchEvent.NETWORK_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.NETWORK_ERROR, err.message),
2417
+ [import_kubernetes_fluent_client7.WatchEvent.LIST_ERROR]: (err) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.LIST_ERROR, err.message),
2418
+ [import_kubernetes_fluent_client7.WatchEvent.LIST]: (list) => logEvent2(import_kubernetes_fluent_client7.WatchEvent.LIST, JSON.stringify(list, void 0, 2)),
2419
+ [import_kubernetes_fluent_client7.WatchEvent.CACHE_MISS]: (windowName) => metricsCollector2.incCacheMiss(windowName),
2420
+ [import_kubernetes_fluent_client7.WatchEvent.INIT_CACHE_MISS]: (windowName) => metricsCollector2.initCacheMissWindow(windowName),
2421
+ [import_kubernetes_fluent_client7.WatchEvent.INC_RESYNC_FAILURE_COUNT]: (retryCount) => metricsCollector2.incRetryCount(retryCount)
2387
2422
  };
2388
2423
  Object.entries(eventHandlers).forEach(([event, handler]) => {
2389
2424
  watcher.events.on(event, handler);
@@ -2401,7 +2436,7 @@ var PeprModule = class {
2401
2436
  * @param opts Options for the Pepr runtime
2402
2437
  */
2403
2438
  constructor({ description, pepr }, capabilities = [], opts = {}) {
2404
- const config = (0, import_ramda13.clone)(pepr);
2439
+ const config = (0, import_ramda14.clone)(pepr);
2405
2440
  config.description = description;
2406
2441
  ValidateError(config.onError);
2407
2442
  if (isBuildMode()) {
@@ -2424,7 +2459,7 @@ var PeprModule = class {
2424
2459
  const controllerHooks = {
2425
2460
  beforeHook: opts.beforeHook,
2426
2461
  afterHook: opts.afterHook,
2427
- onReady: () => {
2462
+ onReady: async () => {
2428
2463
  if (isWatchMode() || isDevMode()) {
2429
2464
  try {
2430
2465
  setupWatch(capabilities, resolveIgnoreNamespaces(pepr?.alwaysIgnore?.namespaces));
@@ -2460,7 +2495,7 @@ __export(sdk_exports, {
2460
2495
  sanitizeResourceName: () => sanitizeResourceName,
2461
2496
  writeEvent: () => writeEvent
2462
2497
  });
2463
- var import_kubernetes_fluent_client7 = require("kubernetes-fluent-client");
2498
+ var import_kubernetes_fluent_client8 = require("kubernetes-fluent-client");
2464
2499
  function containers(request, containerType) {
2465
2500
  const containers2 = request.Raw.spec?.containers || [];
2466
2501
  const initContainers = request.Raw.spec?.initContainers || [];
@@ -2478,7 +2513,7 @@ function containers(request, containerType) {
2478
2513
  }
2479
2514
  async function writeEvent(cr, event, options) {
2480
2515
  const { eventType, eventReason, reportingComponent, reportingInstance } = options;
2481
- await (0, import_kubernetes_fluent_client7.K8s)(import_kubernetes_fluent_client7.kind.CoreEvent).Create({
2516
+ await (0, import_kubernetes_fluent_client8.K8s)(import_kubernetes_fluent_client8.kind.CoreEvent).Create({
2482
2517
  type: eventType,
2483
2518
  reason: eventReason,
2484
2519
  ...event,