@firestartr/cli 2.7.0-snapshot-21 → 2.7.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/build/index.js CHANGED
@@ -330867,6 +330867,138 @@ function getOperatorEnvSnapshot() {
330867
330867
  return { ...snapshot };
330868
330868
  }
330869
330869
 
330870
+ ;// CONCATENATED MODULE: ../operator/src/connection.ts
330871
+
330872
+
330873
+ async function connection_getConnection() {
330874
+ try {
330875
+ const kc = new client_node_dist.KubeConfig();
330876
+ kc.loadFromDefault();
330877
+ const opts = {};
330878
+ await kc.applyToHTTPSOptions(opts);
330879
+ return { kc, opts };
330880
+ }
330881
+ catch (err) {
330882
+ operator_src_logger.error(`getConnection: ${err}`);
330883
+ throw err;
330884
+ }
330885
+ }
330886
+
330887
+ ;// CONCATENATED MODULE: ../operator/src/utils/semaphore.ts
330888
+ class Semaphore {
330889
+ constructor(max) {
330890
+ this._current = 0;
330891
+ this._queue = [];
330892
+ this._totalAcquisitions = 0;
330893
+ this._timesSaturated = 0;
330894
+ if (!Number.isFinite(max) || Number.isNaN(max) || max < 1) {
330895
+ throw new Error(`Semaphore max must be a finite number >= 1: ${max}`);
330896
+ }
330897
+ this._max = Math.floor(max);
330898
+ }
330899
+ get max() {
330900
+ return this._max;
330901
+ }
330902
+ get current() {
330903
+ return this._current;
330904
+ }
330905
+ get waiting() {
330906
+ return this._queue.length;
330907
+ }
330908
+ get totalAcquisitions() {
330909
+ return this._totalAcquisitions;
330910
+ }
330911
+ get timesSaturated() {
330912
+ return this._timesSaturated;
330913
+ }
330914
+ async acquire() {
330915
+ if (this._current < this._max) {
330916
+ this._current++;
330917
+ this._totalAcquisitions++;
330918
+ return;
330919
+ }
330920
+ this._timesSaturated++;
330921
+ await new Promise((resolve) => {
330922
+ this._queue.push(() => {
330923
+ this._current++;
330924
+ this._totalAcquisitions++;
330925
+ resolve();
330926
+ });
330927
+ });
330928
+ }
330929
+ release() {
330930
+ if (this._current <= 0) {
330931
+ this._current = 0;
330932
+ return;
330933
+ }
330934
+ this._current--;
330935
+ const next = this._queue.shift();
330936
+ if (next) {
330937
+ next();
330938
+ }
330939
+ }
330940
+ }
330941
+
330942
+ ;// CONCATENATED MODULE: ../operator/src/utils/api-read-limiter.ts
330943
+
330944
+ const DEFAULT_MAX_CONCURRENT_API_CALLS = 50;
330945
+ const MIN_CONCURRENT_API_CALLS_PER_SLOT = 4;
330946
+ function parseMaxSlots(value) {
330947
+ if (value === undefined)
330948
+ return 1;
330949
+ const parsed = Number(value);
330950
+ const floored = Math.floor(parsed);
330951
+ if (!Number.isFinite(parsed) || Number.isNaN(parsed) || floored < 1)
330952
+ return 1;
330953
+ return floored;
330954
+ }
330955
+ function computeMaxConcurrentApiCalls(rawMaxConcurrent, rawMaxSlots) {
330956
+ const maxSlots = parseMaxSlots(rawMaxSlots);
330957
+ const minRequired = maxSlots * MIN_CONCURRENT_API_CALLS_PER_SLOT;
330958
+ if (rawMaxConcurrent === undefined) {
330959
+ return Math.max(DEFAULT_MAX_CONCURRENT_API_CALLS, minRequired);
330960
+ }
330961
+ const parsed = Number(rawMaxConcurrent);
330962
+ const floored = Math.floor(parsed);
330963
+ if (!Number.isFinite(parsed) || Number.isNaN(parsed) || floored < 1) {
330964
+ return Math.max(DEFAULT_MAX_CONCURRENT_API_CALLS, minRequired);
330965
+ }
330966
+ return Math.max(floored, minRequired);
330967
+ }
330968
+ const apiReadSemaphore = new Semaphore(computeMaxConcurrentApiCalls(process.env.OPERATOR_MAX_CONCURRENT_API_CALLS, process.env.OPERATOR_NUMBER_OF_MAX_SLOTS));
330969
+ let _peakConcurrentApiCalls = 0;
330970
+ async function withApiReadSlot(read) {
330971
+ await apiReadSemaphore.acquire();
330972
+ const current = apiReadSemaphore.current;
330973
+ if (current > _peakConcurrentApiCalls) {
330974
+ _peakConcurrentApiCalls = current;
330975
+ }
330976
+ try {
330977
+ return await read();
330978
+ }
330979
+ finally {
330980
+ apiReadSemaphore.release();
330981
+ }
330982
+ }
330983
+ function getPeakConcurrentApiCalls() {
330984
+ return _peakConcurrentApiCalls;
330985
+ }
330986
+ function getCurrentConcurrentApiCalls() {
330987
+ return apiReadSemaphore.current;
330988
+ }
330989
+ function getPendingApiCalls() {
330990
+ return apiReadSemaphore.waiting;
330991
+ }
330992
+ function getMaxConcurrentApiCalls() {
330993
+ return apiReadSemaphore.max;
330994
+ }
330995
+ function getTotalApiAcquisitions() {
330996
+ return apiReadSemaphore.totalAcquisitions;
330997
+ }
330998
+ function getTimesSemaphoreSaturated() {
330999
+ return apiReadSemaphore.timesSaturated;
331000
+ }
331001
+
330870
331002
  ;// CONCATENATED MODULE: ../operator/src/ctl.ts
330871
331003
 
330872
331004
 
@@ -330876,6 +331008,8 @@ function getOperatorEnvSnapshot() {
330876
331008
 
330877
331009
 
330878
331010
 
331011
+
331012
+
330879
331013
  const MAX_CHARS_OUPUT_PLAN = 20000;
330880
331014
  function getOperatorProfile() {
330881
331015
  github["default"].createProfile('operator', {
@@ -330888,29 +331022,33 @@ async function getItem(kind, namespace, item) {
330888
331022
  const itemPath = `${namespace}/${kind}/${item.metadata.name}`;
330889
331023
  return await ctl_getItemByItemPath(itemPath);
330890
331024
  }
331025
+ async function fetchItemByItemPathResponse(itemPath, apiGroup = catalog_common/* default.types.controller.FirestartrApiGroup */.Z.types.controller.FirestartrApiGroup, apiVersion = 'v1') {
331026
+ operator_src_logger.debug(`The ctl is getting the item at '${itemPath}'.`);
331027
+ const { kc, opts } = await connection_getConnection();
331028
+ opts.headers['Content-Type'] = 'application/json';
331029
+ opts.headers['Accept'] = 'application/json';
331030
+ const url = apiGroup === catalog_common/* default.types.controller.KubernetesApiGroup */.Z.types.controller.KubernetesApiGroup
331031
+ ? `${kc.getCurrentCluster().server}/api/v1/namespaces/${itemPath}`
331032
+ : `${kc.getCurrentCluster().server}/apis/${apiGroup}/${apiVersion}/namespaces/${itemPath}`;
331033
+ operator_src_logger.silly(`Sending request ${url}`);
331034
+ return await fetch(url, { method: 'get', headers: opts.headers });
331035
+ }
330891
331036
  async function ctl_getItemByItemPath(itemPath, apiGroup = catalog_common/* default.types.controller.FirestartrApiGroup */.Z.types.controller.FirestartrApiGroup, apiVersion = 'v1') {
330892
- try {
330893
- operator_src_logger.debug(`The ctl is getting the item at '${itemPath}'.`);
330894
- const { kc, opts } = await ctl_getConnection();
330895
- opts.headers['Content-Type'] = 'application/json';
330896
- opts.headers['Accept'] = 'application/json';
330897
- const url = apiGroup === catalog_common/* default.types.controller.KubernetesApiGroup */.Z.types.controller.KubernetesApiGroup
330898
- ? `${kc.getCurrentCluster().server}/api/v1/namespaces/${itemPath}`
330899
- : `${kc.getCurrentCluster().server}/apis/${apiGroup}/${apiVersion}/namespaces/${itemPath}`;
330900
- operator_src_logger.silly(`Sending request ${url}`);
330901
- const r = await fetch(url, { method: 'get', headers: opts.headers });
330902
- if (!r.ok) {
330903
- const err = new Error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
330904
- operator_src_logger.error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
330905
- throw err;
331037
+ return await withApiReadSlot(async () => {
331038
+ try {
331039
+ const r = await fetchItemByItemPathResponse(itemPath, apiGroup, apiVersion);
331040
+ if (!r.ok) {
331041
+ const err = new Error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
331042
+ operator_src_logger.error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
331043
+ throw err;
331044
+ }
331045
+ return await r.json();
330906
331046
  }
330907
- const jsonResponse = await r.json();
330908
- return jsonResponse;
330909
- }
330910
- catch (e) {
330911
- operator_src_logger.error(`Error on getItemByItemPath: ${e}`);
330912
- throw e;
330913
- }
331047
+ catch (e) {
331048
+ operator_src_logger.error(`Error on getItemByItemPath: ${e}`);
331049
+ throw e;
331050
+ }
331051
+ });
330914
331052
  }
330915
331053
  /**
330916
331054
  * Like getItemByItemPath but returns null when the resource is not found
@@ -330919,34 +331057,28 @@ async function ctl_getItemByItemPath(itemPath, apiGroup = catalog_common/* defau
330919
331057
  * whether a parent CR has been provisioned before its children arrive).
330920
331058
  */
330921
331059
  async function getItemByItemPathOrNull(itemPath, apiGroup = catalog_common/* default.types.controller.FirestartrApiGroup */.Z.types.controller.FirestartrApiGroup, apiVersion = 'v1') {
330922
- try {
330923
- operator_src_logger.debug(`The ctl is getting the item at '${itemPath}'.`);
330924
- const { kc, opts } = await ctl_getConnection();
330925
- opts.headers['Content-Type'] = 'application/json';
330926
- opts.headers['Accept'] = 'application/json';
330927
- const url = apiGroup === catalog_common/* default.types.controller.KubernetesApiGroup */.Z.types.controller.KubernetesApiGroup
330928
- ? `${kc.getCurrentCluster().server}/api/v1/namespaces/${itemPath}`
330929
- : `${kc.getCurrentCluster().server}/apis/${apiGroup}/${apiVersion}/namespaces/${itemPath}`;
330930
- operator_src_logger.silly(`Sending request ${url}`);
330931
- const r = await fetch(url, { method: 'get', headers: opts.headers });
330932
- if (r.status === 404 || r.status === 409) {
330933
- operator_src_logger.debug(`Item at '${itemPath}' returned ${r.status} (expected), returning null.`);
330934
- return null;
331060
+ return await withApiReadSlot(async () => {
331061
+ try {
331062
+ const r = await fetchItemByItemPathResponse(itemPath, apiGroup, apiVersion);
331063
+ if (r.status === 404 || r.status === 409) {
331064
+ operator_src_logger.debug(`Item at '${itemPath}' returned ${r.status} (expected), returning null.`);
331065
+ return null;
331066
+ }
331067
+ if (!r.ok) {
331068
+ const err = new Error(`Error on getItemByItemPathOrNull: ${itemPath}: ${r.statusText}`);
331069
+ operator_src_logger.error(`Error on getItemByItemPathOrNull: ${itemPath}: ${r.statusText}`);
331070
+ throw err;
331071
+ }
331072
+ return await r.json();
330935
331073
  }
330936
- if (!r.ok) {
330937
- const err = new Error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
330938
- operator_src_logger.error(`Error on getItemByItemPath: ${itemPath}: ${r.statusText}`);
330939
- throw err;
331074
+ catch (e) {
331075
+ operator_src_logger.error(`Error on getItemByItemPathOrNull: ${e}`);
331076
+ throw e;
330940
331077
  }
330941
- return await r.json();
330942
- }
330943
- catch (e) {
330944
- operator_src_logger.error(`Error on getItemByItemPath: ${e}`);
330945
- throw e;
330946
- }
331078
+ });
330947
331079
  }
330948
331080
  async function writeManifest(kind, namespace, item, apiSlug) {
330949
- const { kc, opts } = await ctl_getConnection();
331081
+ const { kc, opts } = await connection_getConnection();
330950
331082
  opts.headers['Content-Type'] = 'application/json';
330951
331083
  opts.headers['Accept'] = 'application/json';
330952
331084
  const r = await fetch(`${kc.getCurrentCluster().server}/${apiSlug}`, {
@@ -331028,19 +331160,8 @@ function helperIsValidJSON(part) {
331028
331160
  return false;
331029
331161
  }
331030
331162
  }
331031
- async function ctl_getConnection() {
331032
- try {
331033
- const kc = new client_node_dist.KubeConfig();
331034
- kc.loadFromDefault();
331035
- const opts = {};
331036
- await kc.applyToHTTPSOptions(opts);
331037
- return { kc, opts };
331038
- }
331039
- catch (err) {
331040
- operator_src_logger.error(`getConnection: ${err}`);
331041
- throw err;
331042
- }
331043
- }
331163
+
331164
+
331044
331165
  function buildTFResultStatusUpdate(namespace, tfResultName, resourceVersion, exitCode, retryCount) {
331045
331166
  const status = {
331046
331167
  exitCode: exitCode,
@@ -331074,7 +331195,7 @@ async function tryWriteTFResultStatus(namespace, tfResultName, resourceVersion,
331074
331195
  }
331075
331196
  }
331076
331197
  async function upsertResult(namespace, item, result, exitCode = 0, existingRetryCount) {
331077
- const { kc, opts } = await ctl_getConnection();
331198
+ const { kc, opts } = await connection_getConnection();
331078
331199
  kc.makeApiClient(client_node_dist.CoreV1Api);
331079
331200
  const exists = await getTFResult(namespace, item);
331080
331201
  const currentRetryCount = existingRetryCount !== undefined
@@ -331129,7 +331250,7 @@ async function upsertResult(namespace, item, result, exitCode = 0, existingRetry
331129
331250
  }
331130
331251
  }
331131
331252
  async function deleteSecret(secretName, namespace) {
331132
- const { kc } = await ctl_getConnection();
331253
+ const { kc } = await connection_getConnection();
331133
331254
  const k8sApi = kc.makeApiClient(client_node_dist.CoreV1Api);
331134
331255
  try {
331135
331256
  await k8sApi.deleteNamespacedSecret(secretName, namespace);
@@ -331145,7 +331266,7 @@ async function deleteSecret(secretName, namespace) {
331145
331266
  }
331146
331267
  }
331147
331268
  async function upsertSecret(namespace, secret) {
331148
- const { kc } = await ctl_getConnection();
331269
+ const { kc } = await connection_getConnection();
331149
331270
  const k8sApi = kc.makeApiClient(client_node_dist.CoreV1Api);
331150
331271
  secret.metadata.name = secret.metadata.name.toLowerCase();
331151
331272
  try {
@@ -331162,7 +331283,7 @@ async function upsertSecret(namespace, secret) {
331162
331283
  }
331163
331284
  }
331164
331285
  async function getSecret(namespace, secretName) {
331165
- const { kc } = await ctl_getConnection();
331286
+ const { kc } = await connection_getConnection();
331166
331287
  const k8sApi = kc.makeApiClient(client_node_dist.CoreV1Api);
331167
331288
  try {
331168
331289
  const secret = await k8sApi.readNamespacedSecret(secretName, namespace);
@@ -331179,7 +331300,7 @@ async function getSecret(namespace, secretName) {
331179
331300
  }
331180
331301
  }
331181
331302
  async function getTFResult(namespace, item) {
331182
- const { kc, opts } = await ctl_getConnection();
331303
+ const { kc, opts } = await connection_getConnection();
331183
331304
  opts.headers['Content-Type'] = 'application/json';
331184
331305
  opts.headers['Accept'] = 'application/json';
331185
331306
  const r = await fetch(`${kc.getCurrentCluster().server}/apis/firestartr.dev/v1/namespaces/${namespace}/tfresults/${item.kind}-${item.metadata.name}`.toLowerCase(), {
@@ -331209,7 +331330,7 @@ async function checkIfRenamed(namespace, item) {
331209
331330
  try {
331210
331331
  // Check that the old item still exists
331211
331332
  const plural = getPluralFromKind(item.kind);
331212
- const { kc, opts } = await ctl_getConnection();
331333
+ const { kc, opts } = await getCtlConnection();
331213
331334
  const url = `${kc.getCurrentCluster().server}/apis/firestartr.dev/v1/namespaces/${namespace}/${plural}/${item.metadata.name}`;
331214
331335
  const r = await fetch(url, {
331215
331336
  method: 'GET',
@@ -331230,7 +331351,7 @@ async function checkIfRenamed(namespace, item) {
331230
331351
  }
331231
331352
  }
331232
331353
  async function upsertFinalizer(kind, namespace, item, finalizer) {
331233
- const { kc, opts } = await ctl_getConnection();
331354
+ const { kc, opts } = await connection_getConnection();
331234
331355
  const url = `${kc.getCurrentCluster().server}/apis/firestartr.dev/v1/namespaces/${namespace}/${kind}/${item.metadata.name}`;
331235
331356
  for (let attempt = 0; attempt < 5; attempt++) {
331236
331357
  // Fresh GET to get current finalizers and resourceVersion
@@ -331286,7 +331407,7 @@ async function upsertFinalizer(kind, namespace, item, finalizer) {
331286
331407
  * @returns {void}
331287
331408
  */
331288
331409
  async function unsetFinalizer(kind, namespace, item, finalizer) {
331289
- const { kc, opts } = await ctl_getConnection();
331410
+ const { kc, opts } = await connection_getConnection();
331290
331411
  let itemObj;
331291
331412
  if (typeof item === 'string') {
331292
331413
  itemObj = await ctl_getItemByItemPath([namespace, kind, item].join('/'));
@@ -331457,7 +331578,7 @@ async function addCommitStatusToPrMergeCommit(prAnnotationValue, state, targetUR
331457
331578
  await getOperatorProfile().repo.addCommitStatus(state, branchSha, repo, owner, targetURL, description, context);
331458
331579
  }
331459
331580
  async function createDryRun(manifest, namespace) {
331460
- const { kc } = await ctl_getConnection();
331581
+ const { kc } = await connection_getConnection();
331461
331582
  const k8sApi = kc.makeApiClient(client_node_dist.CustomObjectsApi);
331462
331583
  const plural = definitions_getPluralFromKind(manifest.kind);
331463
331584
  if (!plural)
@@ -331465,7 +331586,7 @@ async function createDryRun(manifest, namespace) {
331465
331586
  await k8sApi.createNamespacedCustomObject('firestartr.dev', 'v1', namespace, plural, manifest, undefined, 'All');
331466
331587
  }
331467
331588
  async function updateDryRun(manifest, namespace) {
331468
- const { kc } = await ctl_getConnection();
331589
+ const { kc } = await connection_getConnection();
331469
331590
  const k8sApi = kc.makeApiClient(client_node_dist.CustomObjectsApi);
331470
331591
  const plural = definitions_getPluralFromKind(manifest.kind);
331471
331592
  if (!plural)
@@ -331489,7 +331610,7 @@ async function updateDryRun(manifest, namespace) {
331489
331610
  */
331490
331611
  async function observe(plural, namespace, onAdd, onChange, onDelete, _onRename) {
331491
331612
  const store = new Store(plural);
331492
- const { kc } = await ctl_getConnection();
331613
+ const { kc } = await connection_getConnection();
331493
331614
  try {
331494
331615
  const k8sApi = kc.makeApiClient(client_node_dist.CustomObjectsApi);
331495
331616
  const apiGroup = 'firestartr.dev';
@@ -331870,10 +331991,10 @@ async function getSyncSpecs(itemPath, itemCR) {
331870
331991
  return {
331871
331992
  item,
331872
331993
  syncable: helperIsSyncable(item),
331873
- period: item.metadata.annotations['firestartr.dev/sync-period'] ||
331994
+ period: item.metadata.annotations?.['firestartr.dev/sync-period'] ||
331874
331995
  DEFAULT_REVISION_TIME,
331875
- schedule: item.metadata.annotations['firestartr.dev/sync-schedule'] || false,
331876
- scheduleTZ: item.metadata.annotations['firestartr.dev/sync-schedule-timezone'] ||
331996
+ schedule: item.metadata.annotations?.['firestartr.dev/sync-schedule'] || false,
331997
+ scheduleTZ: item.metadata.annotations?.['firestartr.dev/sync-schedule-timezone'] ||
331877
331998
  'Europe/Madrid',
331878
331999
  };
331879
332000
  }
@@ -331924,7 +332045,7 @@ function assessSyncCalculationMachinery(item) {
331924
332045
  if (!helperIsSyncable(item)) {
331925
332046
  return processNotSyncable;
331926
332047
  }
331927
- else if (item.metadata.annotations['firestartr.dev/sync-schedule'] ??
332048
+ else if (item.metadata.annotations?.['firestartr.dev/sync-schedule'] ??
331928
332049
  false) {
331929
332050
  return processScheduledSync;
331930
332051
  }
@@ -331953,7 +332074,8 @@ async function processNotSyncable(item, reason, status, message) {
331953
332074
  };
331954
332075
  }
331955
332076
  async function processPeriodSync(item, reason, status, message) {
331956
- const period = item.metadata.annotations['firestartr.dev/sync-period'];
332077
+ const period = item.metadata.annotations?.['firestartr.dev/sync-period'] ||
332078
+ DEFAULT_REVISION_TIME;
331957
332079
  const periodMS = helperCalculateRevisionTime(period);
331958
332080
  return {
331959
332081
  syncMode: 'Period',
@@ -331983,7 +332105,7 @@ function helperCalculateRevisionTime(period) {
331983
332105
  return Number(scalar) * multiplier * 1000;
331984
332106
  }
331985
332107
  async function processScheduledSync(item, reason, status, message) {
331986
- const nextPeriod = catalog_common/* default.cron.getCronNextInterval */.Z.cron.getCronNextInterval(item.metadata.annotations['firestartr.dev/sync-schedule'], item.metadata.annotations['firestartr.dev/sync-schedule-timezone'] ||
332108
+ const nextPeriod = catalog_common/* default.cron.getCronNextInterval */.Z.cron.getCronNextInterval(item.metadata.annotations?.['firestartr.dev/sync-schedule'], item.metadata.annotations?.['firestartr.dev/sync-schedule-timezone'] ||
331987
332109
  undefined);
331988
332110
  const nextPeriodDate = new Date(nextPeriod);
331989
332111
  return {
@@ -332888,7 +333010,7 @@ async function* traverseCRCollection(pluralKind, namespace, options = {}, apiGro
332888
333010
  const { limit = 300 } = options; // between 250-300
332889
333011
  try {
332890
333012
  let continueToken = undefined;
332891
- const { kc, opts } = await ctl_getConnection();
333013
+ const { kc, opts } = await connection_getConnection();
332892
333014
  const k8sApi = kc.makeApiClient(client_node_dist.CustomObjectsApi);
332893
333015
  const apiGroup = 'firestartr.dev';
332894
333016
  const apiVersion = 'v1';
@@ -333462,6 +333584,165 @@ function formatElapsedTimeWithDate(upsertTime) {
333462
333584
  return `${parts.slice(0, 2).join(', ')} ago`;
333463
333585
  }
333464
333586
 
333587
+ ;// CONCATENATED MODULE: ../operator/src/diagnosticErrors.ts
333588
+ /**
333589
+ * Global error counter for the diagnostic file.
333590
+ * Increment-only; never reset during the operator lifetime.
333591
+ */
333592
+ let _errorCount = 0;
333593
+ function incrementDiagnosticErrorCount() {
333594
+ _errorCount++;
333595
+ }
333596
+ function getDiagnosticErrorCount() {
333597
+ return _errorCount;
333598
+ }
333599
+
333600
+ ;// CONCATENATED MODULE: ../operator/src/processItem.diagnostic.ts
333601
+
333602
+
333603
+
333604
+
333605
+
333606
+ const DIAGNOSTIC_FILE = '/tmp/diagnostic';
333607
+ const DIAGNOSTIC_INTERVAL_MS = 10 * 1000;
333608
+ let _diagnosticTimer;
333609
+ function clearTimer() {
333610
+ if (_diagnosticTimer !== undefined) {
333611
+ clearInterval(_diagnosticTimer);
333612
+ _diagnosticTimer = undefined;
333613
+ }
333614
+ }
333615
+ function loopDiagnosticFile(queue, maxSlots) {
333616
+ if (process.env.DISABLE_DIAGNOSTIC_FILE) {
333617
+ operator_src_logger.info('Diagnostic file disabled by DISABLE_DIAGNOSTIC_FILE');
333618
+ return;
333619
+ }
333620
+ let running = false;
333621
+ _diagnosticTimer = setInterval(() => {
333622
+ if (running)
333623
+ return;
333624
+ running = true;
333625
+ writeDiagnosticSnapshot(queue, maxSlots)
333626
+ .then(() => {
333627
+ running = false;
333628
+ })
333629
+ .catch((err) => {
333630
+ running = false;
333631
+ operator_src_logger.error(`Error writing diagnostic file: ${err}`);
333632
+ });
333633
+ }, DIAGNOSTIC_INTERVAL_MS);
333634
+ // Clear the interval on termination signals so the process can exit cleanly
333635
+ const onSignal = () => clearTimer();
333636
+ process.on('SIGTERM', onSignal);
333637
+ process.on('SIGINT', onSignal);
333638
+ }
333639
+ /** @internal for testing */
333640
+ function getDiagnosticTimer() {
333641
+ return _diagnosticTimer;
333642
+ }
333643
+ async function writeDiagnosticSnapshot(queue, maxSlots) {
333644
+ const now = new Date().toISOString();
333645
+ // Queue counts
333646
+ let pending = 0;
333647
+ let processing = 0;
333648
+ let finished = 0;
333649
+ let blocked = 0;
333650
+ let deadLetter = 0;
333651
+ // Per-slot items
333652
+ const slotsMap = {};
333653
+ for (const wi of queue) {
333654
+ switch (wi.workStatus) {
333655
+ case WorkStatus.PENDING:
333656
+ pending++;
333657
+ break;
333658
+ case WorkStatus.PROCESSING:
333659
+ processing++;
333660
+ break;
333661
+ case WorkStatus.FINISHED:
333662
+ finished++;
333663
+ break;
333664
+ }
333665
+ if (wi.isBlocked) {
333666
+ blocked++;
333667
+ }
333668
+ if (wi.isDeadLetter) {
333669
+ deadLetter++;
333670
+ }
333671
+ if (wi.workStatus === WorkStatus.PROCESSING && wi.slotId !== undefined) {
333672
+ slotsMap[`slot-${wi.slotId}`] =
333673
+ `${wi.item.kind}/${wi.item.metadata.name}`;
333674
+ }
333675
+ }
333676
+ // Fill empty slots with null
333677
+ for (let i = 0; i < maxSlots; i++) {
333678
+ if (!slotsMap[`slot-${i}`]) {
333679
+ slotsMap[`slot-${i}`] = 'null';
333680
+ }
333681
+ }
333682
+ // Semaphore stats
333683
+ const semaphoreCurrent = getCurrentConcurrentApiCalls();
333684
+ const semaphoreMax = getMaxConcurrentApiCalls();
333685
+ const semaphorePeak = getPeakConcurrentApiCalls();
333686
+ const semaphorePending = getPendingApiCalls();
333687
+ const semaphoreTotalAcquisitions = getTotalApiAcquisitions();
333688
+ const semaphoreTimesSaturated = getTimesSemaphoreSaturated();
333689
+ // Environment
333690
+ const envMaxSlots = process.env.OPERATOR_NUMBER_OF_MAX_SLOTS || '1';
333691
+ const envMaxConcurrentApi = process.env.OPERATOR_MAX_CONCURRENT_API_CALLS || '25';
333692
+ const envKindList = process.env.OPERATOR_KIND_LIST || '';
333693
+ const envTfmMirrorDisable = process.env.TFM_MIRROR_DISABLE || '0';
333694
+ const envTfmMirrorList = process.env.TFM_MIRROR_LIST || '';
333695
+ const envTfmMirrorRefreshInterval = process.env.TFM_MIRROR_REFRESH_INTERVAL || '900';
333696
+ const envBackendProvider = process.env.BACKEND_PROVIDER_NAME || 'kubernetes-provider';
333697
+ const envGithubAppId = process.env.GITHUB_APP_ID || '';
333698
+ // Build YAML output
333699
+ let output = '';
333700
+ output += `timestamp: "${now}"\n`;
333701
+ output += 'env:\n';
333702
+ output += ` OPERATOR_NUMBER_OF_MAX_SLOTS: ${envMaxSlots}\n`;
333703
+ output += ` OPERATOR_MAX_CONCURRENT_API_CALLS: ${envMaxConcurrentApi}\n`;
333704
+ output += ` OPERATOR_KIND_LIST: ${envKindList}\n`;
333705
+ output += ` TFM_MIRROR_DISABLE: ${envTfmMirrorDisable}\n`;
333706
+ output += ` TFM_MIRROR_LIST: ${envTfmMirrorList}\n`;
333707
+ output += ` TFM_MIRROR_REFRESH_INTERVAL: ${envTfmMirrorRefreshInterval}\n`;
333708
+ output += ` BACKEND_PROVIDER_NAME: ${envBackendProvider}\n`;
333709
+ output += ` GITHUB_APP_ID: ${envGithubAppId}\n`;
333710
+ output += 'queue:\n';
333711
+ output += ` total: ${queue.length}\n`;
333712
+ output += ` pending: ${pending}\n`;
333713
+ output += ` processing: ${processing}\n`;
333714
+ output += ` finished: ${finished}\n`;
333715
+ output += ` blocked: ${blocked}\n`;
333716
+ output += ` dead_letter: ${deadLetter}\n`;
333717
+ output += 'slots:\n';
333718
+ output += ` max: ${maxSlots}\n`;
333719
+ output += ` active: ${processing}\n`;
333720
+ output += ' items_per_slot:\n';
333721
+ for (let i = 0; i < maxSlots; i++) {
333722
+ const key = `slot-${i}`;
333723
+ const val = slotsMap[key];
333724
+ output += ` ${key}: ${val === 'null' ? 'null' : `"${val}"`}\n`;
333725
+ }
333726
+ output += 'semaphore:\n';
333727
+ output += ` max: ${semaphoreMax}\n`;
333728
+ output += ` in_use: ${semaphoreCurrent}\n`;
333729
+ output += ` available: ${semaphoreMax - semaphoreCurrent}\n`;
333730
+ output += ` pending: ${semaphorePending}\n`;
333731
+ output += ` peak: ${semaphorePeak}\n`;
333732
+ output += ` total_acquisitions: ${semaphoreTotalAcquisitions}\n`;
333733
+ output += ` times_saturated: ${semaphoreTimesSaturated}\n`;
333734
+ output += 'errors:\n';
333735
+ output += ` total: ${getDiagnosticErrorCount()}\n`;
333736
+ return new Promise((resolve, reject) => {
333737
+ external_fs_.writeFile(DIAGNOSTIC_FILE, output, (err) => {
333738
+ if (err)
333739
+ reject(`Writing ${DIAGNOSTIC_FILE}: ${err}`);
333740
+ else
333741
+ resolve();
333742
+ });
333743
+ });
333744
+ }
333745
+
333465
333746
  ;// CONCATENATED MODULE: ../operator/src/signals.ts
333466
333747
 
333467
333748
  function initSignalsHandler(Mapper) {
@@ -333484,6 +333765,7 @@ function initSignalsHandler(Mapper) {
333484
333765
 
333485
333766
 
333486
333767
 
333768
+
333487
333769
  /*
333488
333770
  * Dead-Letter Handler
333489
333771
  *
@@ -333495,6 +333777,7 @@ async function deadLetterHandler(workItem) {
333495
333777
  const itemPath = workItem.handler.itemPath();
333496
333778
  workItem.workStatus = WorkStatus.FINISHED;
333497
333779
  workItem.isDeadLetter = true;
333780
+ incrementDiagnosticErrorCount();
333498
333781
  // we try to put the CR in a correct state
333499
333782
  try {
333500
333783
  await updateTransition(itemPath, operation, 'ERROR', 'True', 'Uncontrolled error (DLH)');
@@ -333639,7 +333922,7 @@ class CRStateMetrics {
333639
333922
  this.onUpdate = false;
333640
333923
  }
333641
333924
  async __prepareConnection() {
333642
- const { kc, opts } = await ctl_getConnection();
333925
+ const { kc, opts } = await connection_getConnection();
333643
333926
  const k8sApi = kc.makeApiClient(client_node_dist.CustomObjectsApi);
333644
333927
  this.fListCRs = async () => {
333645
333928
  try {
@@ -333783,6 +334066,7 @@ ProcessorGlobalMetrics._instance = null;
333783
334066
 
333784
334067
 
333785
334068
 
334069
+
333786
334070
  let processMetricsSlotProvider = null;
333787
334071
  /* harmony default export */ async function metricsServer(kindList, namespace) {
333788
334072
  const portFromEnv = process.env.METRICS_PORT;
@@ -333801,6 +334085,7 @@ async function startMetrics(exporter, attributes, kindList, namespace) {
333801
334085
  });
333802
334086
  const meter = meterProvider.getMeter('firestartr');
333803
334087
  void startQueueMetrics(meter, attributes);
334088
+ void startApiCallMetrics(meter, attributes);
333804
334089
  void startMemoryMetrics(meter, attributes);
333805
334090
  void startCRStates(meter, kindList, namespace);
333806
334091
  processMetricsSlotProvider = (slotId) => {
@@ -333862,6 +334147,14 @@ async function startQueueMetrics(meter, attributes) {
333862
334147
  nDeferred = queueMetrics.nItemsDeferred || 0;
333863
334148
  }, 1000);
333864
334149
  }
334150
+ async function startApiCallMetrics(meter, attributes) {
334151
+ const concurrentGauge = meter.createObservableGauge('firestartr_api_calls_concurrent', { description: 'Current number of in-flight Kubernetes API read calls' });
334152
+ const awaitingGauge = meter.createObservableGauge('firestartr_api_calls_awaiting', {
334153
+ description: 'Current number of Kubernetes API read calls waiting for a slot',
334154
+ });
334155
+ concurrentGauge.addCallback((observer) => observer.observe(getCurrentConcurrentApiCalls(), attributes));
334156
+ awaitingGauge.addCallback((observer) => observer.observe(getPendingApiCalls(), attributes));
334157
+ }
333865
334158
  async function startMemoryMetrics(meter, attributes) {
333866
334159
  const usedMemoryCounter = meter.createObservableGauge('firestartr_used_memory', { description: 'Used memory in bytes' });
333867
334160
  let heapUsage = process.memoryUsage().heapUsed;
@@ -334010,7 +334303,15 @@ class ProcessItemSlot {
334010
334303
  async __run(workItem) {
334011
334304
  if (!workItem.getItem || !workItem.process || !workItem.operation)
334012
334305
  return;
334306
+ const raceDelayMs = process.env.RACE_DELAY_MS
334307
+ ? Number.parseInt(process.env.RACE_DELAY_MS, 10)
334308
+ : 0;
334309
+ if (raceDelayMs > 0) {
334310
+ const jitter = Math.floor(Math.random() * raceDelayMs);
334311
+ await new Promise((r) => setTimeout(r, jitter));
334312
+ }
334013
334313
  const item = await workItem.getItem();
334314
+ workItem.item = item;
334014
334315
  // we check if the workItem needs blocking
334015
334316
  // if it does need it we return because we cannot
334016
334317
  // process this item
@@ -334231,6 +334532,7 @@ function sortQueue(queue) {
334231
334532
 
334232
334533
 
334233
334534
 
334535
+
334234
334536
  const queue = [];
334235
334537
  let _deferredBookkeeper = null;
334236
334538
  let _activeParentKeys = new Set();
@@ -334340,6 +334642,7 @@ async function processItem(workItem) {
334340
334642
  */
334341
334643
  async function processItem_loop() {
334342
334644
  loopWorkItemDebug(queue);
334645
+ loopDiagnosticFile(queue, MAX_SLOTS);
334343
334646
  const deferredBookkeeper = new DeferredSchedulingBookkeeper();
334344
334647
  _deferredBookkeeper = deferredBookkeeper;
334345
334648
  const processItemSlotsManager = initProcessItemsSlots(MAX_SLOTS, true, (w) => deferredBookkeeper.incrementBlockedAttempt(w));
@@ -337804,7 +338107,7 @@ var external_os_default = /*#__PURE__*/__nccwpck_require__.n(external_os_);
337804
338107
 
337805
338108
 
337806
338109
  async function getCurrentPod(namespace = 'default') {
337807
- const { kc } = await ctl_getConnection();
338110
+ const { kc } = await connection_getConnection();
337808
338111
  const k8sApi = kc.makeApiClient(client_node_dist.CoreV1Api);
337809
338112
  const podName = (0,external_os_.hostname)();
337810
338113
  const pod = await k8sApi.readNamespacedPod(podName, namespace);
@@ -337826,7 +338129,7 @@ class LeaseAcquisitionError extends Error {
337826
338129
  * automatically after 30 seconds.
337827
338130
  */
337828
338131
  async function tryAcquireOrRenewLease(namespace, leaseDurationSeconds) {
337829
- const { kc } = await ctl_getConnection();
338132
+ const { kc } = await connection_getConnection();
337830
338133
  const k8sApi = kc.makeApiClient(client_node_dist.CoordinationV1Api);
337831
338134
  const name = 'firestartr-lease';
337832
338135
  const currentPod = await getCurrentPod(namespace);
@@ -338405,7 +338708,7 @@ class Ctx {
338405
338708
 
338406
338709
 
338407
338710
  async function getTFWorkspaceRefs(_claimKind, claimName, namespace) {
338408
- const { kc, opts } = await ctl_getConnection();
338711
+ const { kc, opts } = await connection_getConnection();
338409
338712
  await kc.makeApiClient(client_node_dist.CustomObjectsApi);
338410
338713
  const normalizedClaimName = catalog_common/* default.generic.normalizeLabel */.Z.generic.normalizeLabel(claimName);
338411
338714
  console.log('💡', normalizedClaimName);
@@ -338659,8 +338962,8 @@ const MODULES = {
338659
338962
  },
338660
338963
  FirestartrGithubOrganizationSettings: {
338661
338964
  module: 'git::https://github.com/prefapp/tfm.git//modules/github-org-settings',
338662
- // feat/org-settings-module at 2026-06-16
338663
- ref: '0e3f3f897ffff35a52285d0c681c0d81026d6d8a',
338965
+ // org settings module merged to main (prefapp/tfm#1253)
338966
+ ref: 'cf2e2ae487b6cc3f7b208f46a92f5b5f97f8fef2',
338664
338967
  },
338665
338968
  };
338666
338969
  function getFirestartrDefaultTFM(kind) {
@@ -339777,11 +340080,14 @@ async function provisionManagedFiles(ghFeature) {
339777
340080
  // the repo if available so the seed commit preserves the current state.
339778
340081
  newlyProvisionedAddresses.push(address);
339779
340082
  try {
339780
- const content = await ghFeature.getFileContentFromProvider(cr.spec.org, `/${cr.spec.org}/${repoRef.getDepName()}/${branch}/${file.path}`);
340083
+ const content = await ghFeature.getFileContentFromProvider(cr.spec.org, repoRef.getDepName(), branch, file.path);
339781
340084
  file.content = Buffer.from(content, 'binary').toString('base64');
339782
340085
  }
339783
340086
  catch (e) {
339784
- gh_provisioner_src_logger.error(`File ${file.path} not found in repo ${repoInfo.ref?.name} on branch ${branch}. File content not updated`);
340087
+ if (e?.status !== 404) {
340088
+ throw e;
340089
+ }
340090
+ gh_provisioner_src_logger.info(`File ${file.path} not found in repo ${repoInfo.ref?.name} on branch ${branch}. Using declared content`);
339785
340091
  }
339786
340092
  createFileProvision(ghFeature, file);
339787
340093
  }
@@ -339965,6 +340271,7 @@ async function endDebug(entity) {
339965
340271
 
339966
340272
 
339967
340273
  const tp_bridge_TF_PROJECTS_PATH = '/tmp/gh-workspaces';
340274
+ const KUBERNETES_LABEL_VALUE_MAX_LENGTH = 63;
339968
340275
  async function runOnTerraform(entity, command, customArgs, opts = {}) {
339969
340276
  if (!entity || typeof entity !== 'object')
339970
340277
  throw new Error('[BUG] entity is invalid in runOnTerraform');
@@ -340054,11 +340361,27 @@ function calculateTFStatePath(entity, backend) {
340054
340361
  tfStatePath = `grss/${entity.cr.spec.firestartr.tfStateKey}`.substring(0, 63);
340055
340362
  }
340056
340363
  else {
340057
- tfStatePath = `${entity.cr.kind.toLowerCase()}/${entity.cr.spec.firestartr.tfStateKey}`;
340364
+ const kind = entity.cr.kind.toLowerCase();
340365
+ const tfStateKey = entity.cr.spec.firestartr.tfStateKey;
340366
+ tfStatePath = `${kind}/${tfStateKey}`;
340367
+ if ('kubernetes' in backend) {
340368
+ tfStatePath = fitKubernetesBackendLabel(tfStatePath, kind, tfStateKey);
340369
+ }
340058
340370
  }
340059
340371
  gh_provisioner_src_logger.debug(`[gh-provisioner] tfStateKey for ${entity.k8sId} = '${tfStatePath}'`);
340060
340372
  return tfStatePath;
340061
340373
  }
340374
+ function fitKubernetesBackendLabel(tfStatePath, kind, tfStateKey) {
340375
+ if (tfStatePath.split('/').join('-').length <= KUBERNETES_LABEL_VALUE_MAX_LENGTH) {
340376
+ return tfStatePath;
340377
+ }
340378
+ const tfStateKeyLabelLength = tfStateKey.split('/').join('-').length;
340379
+ const maxKindLength = KUBERNETES_LABEL_VALUE_MAX_LENGTH - tfStateKeyLabelLength - 1;
340380
+ if (maxKindLength < 1) {
340381
+ return tfStateKey.substring(0, KUBERNETES_LABEL_VALUE_MAX_LENGTH);
340382
+ }
340383
+ return `${kind.substring(0, maxKindLength)}/${tfStateKey}`;
340384
+ }
340062
340385
 
340063
340386
  ;// CONCATENATED MODULE: ../gh_provisioner/src/entities/ghfeature/index.ts
340064
340387
 
@@ -340219,15 +340542,9 @@ class EntityGHFeature extends base_Entity {
340219
340542
  throw new Error(`[gh-provisioner] ${this.k8sId} on untracking files: ${err}`);
340220
340543
  }
340221
340544
  }
340222
- async getFileContentFromProvider(org, url) {
340223
- const v = await this.runWithGithubProvider(async () => {
340224
- const octokit = await github["default"].getOctokitForOrg(org);
340225
- const response = await octokit.request(`GET ${url}`, {
340226
- baseUrl: 'https://raw.githubusercontent.com',
340227
- });
340228
- return response.data;
340229
- });
340230
- return v;
340545
+ async getFileContentFromProvider(org, repo, branch, path) {
340546
+ const content = await this.runWithGithubProvider(() => github["default"].repo.getContent(path, repo, org, branch));
340547
+ return content;
340231
340548
  }
340232
340549
  }
340233
340550
  function parseStateList(output) {
@@ -342173,6 +342490,7 @@ function isObserveModeActive() {
342173
342490
  // (warmup and legacy provisioner code replaced by TFM mirror system)
342174
342491
  function runOperator(opts) {
342175
342492
  const { ignoreLease, dummyExec, namespace, kindList, importMode, importModeSkipPlan, observeMode, withMetrics, } = opts;
342493
+ const implementedKinds = filterImplementedKinds(kindList);
342176
342494
  if (observeMode)
342177
342495
  observeModeActive = true;
342178
342496
  if (withMetrics)
@@ -342206,7 +342524,7 @@ function runOperator(opts) {
342206
342524
  await leasePromise;
342207
342525
  };
342208
342526
  if (withMetricsMode) {
342209
- void metricsServer(kindList, namespace);
342527
+ void metricsServer(implementedKinds, namespace);
342210
342528
  }
342211
342529
  void (async () => {
342212
342530
  await run(namespace, () => {
@@ -342214,7 +342532,7 @@ function runOperator(opts) {
342214
342532
  void observeKind('githubgroups', namespace, processItem, dummy);
342215
342533
  }
342216
342534
  else {
342217
- for (const kind of kindList) {
342535
+ for (const kind of implementedKinds) {
342218
342536
  observeKind(kind, namespace, processItem, getProvisionImplementation(kind))
342219
342537
  .then((res) => {
342220
342538
  console.log('exit kind', kind);
@@ -342236,30 +342554,31 @@ function runOperator(opts) {
342236
342554
  });
342237
342555
  })();
342238
342556
  }
342557
+ const provisionImplementations = {
342558
+ terraformworkspaces: processOperation,
342559
+ terraformworkspaceplans: processOperationPlan,
342560
+ githubgroups: process_operation_processOperation,
342561
+ githubrepositories: process_operation_processOperation,
342562
+ githubrepositorysecretssections: process_operation_processOperation,
342563
+ githubrepositoryfeatures: process_operation_processOperation,
342564
+ githubmemberships: process_operation_processOperation,
342565
+ githuborgwebhooks: process_operation_processOperation,
342566
+ githuborganizationsettings: process_operation_processOperation,
342567
+ fsdummiesa: processFirestartrDummies,
342568
+ fsdummiesb: processFirestartrDummies,
342569
+ fsdummiesc: processFirestartrDummies,
342570
+ };
342571
+ function filterImplementedKinds(kindList) {
342572
+ return kindList.filter((kind) => {
342573
+ if (Object.prototype.hasOwnProperty.call(provisionImplementations, kind)) {
342574
+ return true;
342575
+ }
342576
+ operator_src_logger.warn(`Ignoring configured kind '${kind}': no implementation found`);
342577
+ return false;
342578
+ });
342579
+ }
342239
342580
  function getProvisionImplementation(plural) {
342240
- let implementation = undefined;
342241
- switch (plural) {
342242
- case 'terraformworkspaces':
342243
- implementation = processOperation;
342244
- break;
342245
- case 'terraformworkspaceplans':
342246
- implementation = processOperationPlan;
342247
- break;
342248
- case 'githubgroups':
342249
- case 'githubrepositories':
342250
- case 'githubrepositorysecretssections':
342251
- case 'githubrepositoryfeatures':
342252
- case 'githubmemberships':
342253
- case 'githuborgwebhooks':
342254
- case 'githuborganizationsettings':
342255
- implementation = process_operation_processOperation;
342256
- break;
342257
- case 'fsdummiesa':
342258
- case 'fsdummiesb':
342259
- case 'fsdummiesc':
342260
- implementation = processFirestartrDummies;
342261
- break;
342262
- }
342581
+ const implementation = provisionImplementations[plural];
342263
342582
  if (!implementation)
342264
342583
  throw new Error(`No implementation found for ${plural}`);
342265
342584
  operator_src_logger.info(`Retrieved the provision implementation for the kind '${plural}'`);
@@ -521050,7 +521369,7 @@ const crsStatusSubcommand = {
521050
521369
  };
521051
521370
 
521052
521371
  ;// CONCATENATED MODULE: ./package.json
521053
- const package_namespaceObject = JSON.parse('{"i8":"2.7.0-snapshot-21"}');
521372
+ const package_namespaceObject = {"i8":"2.7.0"};
521054
521373
  ;// CONCATENATED MODULE: ../../package.json
521055
521374
  const package_namespaceObject_1 = {"i8":"2.7.0"};
521056
521375
  ;// CONCATENATED MODULE: ./src/subcommands/index.ts
@@ -35,5 +35,5 @@ export declare class EntityGHFeature extends Entity {
35
35
  * provisioned with old or new code.
36
36
  */
37
37
  keepUntrackedFiles(_tfOp: string): Promise<void>;
38
- getFileContentFromProvider(org: string, url: string): Promise<string>;
38
+ getFileContentFromProvider(org: string, repo: string, branch: string, path: string): Promise<string>;
39
39
  }
@@ -15,3 +15,4 @@ export declare function buildContext(entity: Entity, reuseExistingProjectOverrid
15
15
  reuseExistingProject: boolean;
16
16
  importMode: boolean;
17
17
  };
18
+ export declare function calculateTFStatePath(entity: Entity, backend: any): string;
@@ -5,3 +5,4 @@ export declare function isImportMode(): boolean;
5
5
  export declare function isImportModeSkipPlan(): boolean;
6
6
  export declare function isObserveModeActive(): boolean;
7
7
  export declare function runOperator(opts: any): void;
8
+ export declare function filterImplementedKinds(kindList: string[]): string[];
@@ -0,0 +1,5 @@
1
+ import * as client from '@kubernetes/client-node';
2
+ export declare function getConnection(): Promise<{
3
+ kc: client.KubeConfig;
4
+ opts: any;
5
+ }>;
@@ -13,10 +13,8 @@ export declare function writeStatus(kind: string, namespace: string, item: any):
13
13
  export declare function writeFinalizer(kind: string, namespace: string, item: any): Promise<any>;
14
14
  export declare function listItems(kind: string, namespace: string, kc: any, opts: any): Promise<Array<any>>;
15
15
  export declare function observeList(kind: string, namespace: string, revision: string, kc: any, opts: any): AsyncGenerator<any, void, unknown>;
16
- export declare function getConnection(): Promise<{
17
- kc: client.KubeConfig;
18
- opts: any;
19
- }>;
16
+ export { getConnection } from './connection';
17
+ export { getCurrentConcurrentApiCalls, getPendingApiCalls, getPeakConcurrentApiCalls, } from './utils/api-read-limiter';
20
18
  export declare function upsertResult(namespace: string, item: any, result: string, exitCode?: number, existingRetryCount?: number): Promise<any>;
21
19
  export declare function deleteSecret(secretName: string, namespace: string): Promise<any>;
22
20
  export declare function upsertSecret(namespace: string, secret: any): Promise<void>;
@@ -0,0 +1,2 @@
1
+ export declare function incrementDiagnosticErrorCount(): void;
2
+ export declare function getDiagnosticErrorCount(): number;
@@ -0,0 +1,5 @@
1
+ /// <reference types="node" />
2
+ import { WorkItem } from './definitions';
3
+ export declare function loopDiagnosticFile(queue: WorkItem[], maxSlots: number): void;
4
+ /** @internal for testing */
5
+ export declare function getDiagnosticTimer(): NodeJS.Timeout | undefined;
@@ -0,0 +1,10 @@
1
+ import { Semaphore } from './semaphore';
2
+ export declare function computeMaxConcurrentApiCalls(rawMaxConcurrent: string | undefined, rawMaxSlots: string | undefined): number;
3
+ export declare const apiReadSemaphore: Semaphore;
4
+ export declare function withApiReadSlot<T>(read: () => Promise<T>): Promise<T>;
5
+ export declare function getPeakConcurrentApiCalls(): number;
6
+ export declare function getCurrentConcurrentApiCalls(): number;
7
+ export declare function getPendingApiCalls(): number;
8
+ export declare function getMaxConcurrentApiCalls(): number;
9
+ export declare function getTotalApiAcquisitions(): number;
10
+ export declare function getTimesSemaphoreSaturated(): number;
@@ -0,0 +1,15 @@
1
+ export declare class Semaphore {
2
+ private readonly _max;
3
+ private _current;
4
+ private readonly _queue;
5
+ private _totalAcquisitions;
6
+ private _timesSaturated;
7
+ constructor(max: number);
8
+ get max(): number;
9
+ get current(): number;
10
+ get waiting(): number;
11
+ get totalAcquisitions(): number;
12
+ get timesSaturated(): number;
13
+ acquire(): Promise<void>;
14
+ release(): void;
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firestartr/cli",
3
- "version": "2.7.0-snapshot-21",
3
+ "version": "2.7.0",
4
4
  "private": false,
5
5
  "description": "Commandline tool",
6
6
  "main": "build/main.js",