@firestartr/cli 1.54.0 → 1.55.0-snapshot-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
@@ -359664,6 +359664,13 @@ var ajv_default = /*#__PURE__*/__nccwpck_require__.n(dist_ajv);
359664
359664
  },
359665
359665
  },
359666
359666
  },
359667
+ filesTemplates: {
359668
+ type: 'array',
359669
+ description: 'a list of references to a different file where files key is filled by an expanded template',
359670
+ items: {
359671
+ type: 'string',
359672
+ },
359673
+ },
359667
359674
  },
359668
359675
  required: ['args', 'feature_name', 'files', 'patches'],
359669
359676
  title: 'root',
@@ -359683,7 +359690,7 @@ var ajv_default = /*#__PURE__*/__nccwpck_require__.n(dist_ajv);
359683
359690
  additionalProperties: false,
359684
359691
  properties: {
359685
359692
  $lit: {
359686
- type: 'string',
359693
+ type: ['string', 'boolean'],
359687
359694
  },
359688
359695
  $ref: {
359689
359696
  type: 'array',
@@ -359695,7 +359702,7 @@ var ajv_default = /*#__PURE__*/__nccwpck_require__.n(dist_ajv);
359695
359702
  type: 'string',
359696
359703
  },
359697
359704
  $default: {
359698
- type: ['string', 'array'],
359705
+ type: ['string', 'array', 'boolean'],
359699
359706
  },
359700
359707
  },
359701
359708
  },
@@ -359775,7 +359782,9 @@ function __validateFeatureConfig(featurePath) {
359775
359782
  }
359776
359783
  }
359777
359784
  function __validateFeatureConfigData(configData) {
359778
- const ajv = new (ajv_default())();
359785
+ const ajv = new (ajv_default())({
359786
+ allowUnionTypes: true,
359787
+ });
359779
359788
  const validate = ajv.compile(src_schema);
359780
359789
  const valid = validate(configData);
359781
359790
  if (!valid) {
@@ -360609,10 +360618,14 @@ function addTraceabilityStamp(context, content) {
360609
360618
 
360610
360619
 
360611
360620
 
360621
+
360612
360622
  function render(featurePath, featureRenderPath, entity, firestartrConfig = {}, featureArgs = {}) {
360613
360623
  const configData = validate_validate(featurePath);
360614
360624
  const context = buildContext(entity, configData.args, firestartrConfig, featureArgs);
360615
360625
  context.config = JSON.parse(renderContent(JSON.stringify(configData), context));
360626
+ if ('filesTemplates' in context.config) {
360627
+ expandFiles(featurePath, configData, context);
360628
+ }
360616
360629
  const output = { files: [] };
360617
360630
  context.config.files.forEach((file) => {
360618
360631
  const { src, dest } = file;
@@ -360670,6 +360683,22 @@ function buildContext(entity, args, firestartrConfig, featureArgs) {
360670
360683
  context.traceability = featureArgs['traceability'] || {};
360671
360684
  return context;
360672
360685
  }
360686
+ function expandFiles(featurePath, configData, context) {
360687
+ let files = [];
360688
+ for (const tpl of configData.filesTemplates) {
360689
+ const addToFiles = expandFilesTemplate(featurePath, tpl, context);
360690
+ files = files.concat(addToFiles).flat(Infinity);
360691
+ }
360692
+ context.config.files = context.config.files.concat(files).flat(Infinity);
360693
+ }
360694
+ function expandFilesTemplate(featurePath, tplPath, context) {
360695
+ const template = external_fs_default().readFileSync(external_path_default().join(featurePath, tplPath)).toString();
360696
+ const renderedTemplate = renderContent(template, context);
360697
+ const data = catalog_common.io.fromYaml(renderedTemplate) || { files: [] };
360698
+ if (!data.files)
360699
+ data.files = [];
360700
+ return data.files.filter((file) => file);
360701
+ }
360673
360702
  function renderContent(template, ctx) {
360674
360703
  return mustache_mustache.render(template, ctx, {}, ['{{|', '|}}']);
360675
360704
  }
@@ -360739,7 +360768,7 @@ function loadAndValidateRenderTests(featurePath) {
360739
360768
  throw new Error(`render_tests.yaml is required but not found at ${file}`);
360740
360769
  }
360741
360770
  const raw = loadYaml(file);
360742
- const ajv = new (ajv_default())({ allErrors: true, strict: true });
360771
+ const ajv = new (ajv_default())({ allErrors: true, strict: true, allowUnionTypes: true });
360743
360772
  const validate = ajv.compile(renderTestsSchema);
360744
360773
  const ok = validate(raw);
360745
360774
  if (!ok) {
@@ -368565,6 +368594,11 @@ const kindsWithFinalizer = [
368565
368594
  'FirestartrGithubOrgWebhook',
368566
368595
  'FirestartrGithubRepositorySecretsSection',
368567
368596
  ];
368597
+ const kindsWithDependants = [
368598
+ 'FirestartrDummyA',
368599
+ 'FirestartrDummyB',
368600
+ 'FirestartrGithubRepository',
368601
+ ];
368568
368602
  /**
368569
368603
  * Observe whenever a new item is added, modified or deleted in a given kind
368570
368604
  * @param {string} pluralKind - Kind to observe
@@ -368675,6 +368709,28 @@ function enqueue(pluralKind, workItem, queue, compute, syncCtl, retryCtl) {
368675
368709
  itemPath: () => informer_itemPath(pluralKind, workItem.item),
368676
368710
  error: () => retryCtl.errorReconciling(informer_itemPath(pluralKind, workItem.item)),
368677
368711
  success: () => retryCtl.successReconciling(informer_itemPath(pluralKind, workItem.item)),
368712
+ needsBlocking: (item) => {
368713
+ if (kindsWithDependants.indexOf(item.kind) === -1) {
368714
+ return false;
368715
+ }
368716
+ if (item.metadata.finalizers &&
368717
+ item.metadata.finalizers.indexOf('foregroundDeletion') !== -1) {
368718
+ // it will block for five seconds
368719
+ workItem.isBlocked = true;
368720
+ const tTimeout = setTimeout(() => {
368721
+ workItem.isBlocked = false;
368722
+ }, 1000 * 5);
368723
+ workItem.fUnblock = () => {
368724
+ clearTimeout(tTimeout);
368725
+ workItem.isBlocked = false;
368726
+ };
368727
+ return true;
368728
+ }
368729
+ else {
368730
+ workItem.isBlocked = false;
368731
+ return false;
368732
+ }
368733
+ },
368678
368734
  };
368679
368735
  workItem.process = async function* (item, operation, handler) {
368680
368736
  const needsUpdateSyncConditions = operation === OperationType.RENAMED ||
@@ -368703,6 +368759,7 @@ function enqueue(pluralKind, workItem, queue, compute, syncCtl, retryCtl) {
368703
368759
  operator_src_logger.debug(`The informer received an item with an operation type of '${operation}', which is not a specific operation.`);
368704
368760
  }
368705
368761
  };
368762
+ workItem.isBlocked = false;
368706
368763
  queue(workItem);
368707
368764
  }
368708
368765
  function informer_itemPath(kind, item) {
@@ -368926,10 +368983,72 @@ function dummy_fWait(ms) {
368926
368983
  });
368927
368984
  }
368928
368985
 
368986
+ ;// CONCATENATED MODULE: ../operator/src/ownership.ts
368987
+
368988
+
368989
+
368990
+ async function getOwnerReferences(item) {
368991
+ return item.metadata?.ownerReferences || [];
368992
+ }
368993
+ async function setOwnerReference(itemPath, namespace, ownerKind, ownerName, blockOwnerDeletion = true) {
368994
+ let item = null;
368995
+ try {
368996
+ // we need to search for the owner's uuid
368997
+ const owner = await getItemByItemPath(`${namespace}/${ownerKind}/${ownerName}`);
368998
+ const ownerReference = {
368999
+ apiVersion: owner.apiVersion,
369000
+ kind: owner.kind,
369001
+ name: ownerName,
369002
+ controller: true,
369003
+ blockOwnerDeletion,
369004
+ uid: owner.metadata.uid,
369005
+ };
369006
+ // we get the item (to prevent race conditions)
369007
+ item = await getItemByItemPath(itemPath);
369008
+ const ownerReferences = item.metadata.ownerReferences ?? [];
369009
+ const existingRefIndex = ownerReferences.findIndex((ref) => ref.uid === ownerReference.uid);
369010
+ if (existingRefIndex === -1) {
369011
+ // Reference does not exist, add it
369012
+ ownerReferences.push(ownerReference);
369013
+ }
369014
+ else {
369015
+ ownerReferences[existingRefIndex] = ownerReference;
369016
+ }
369017
+ await writeOwnerReferences(definitions_getPluralFromKind(item.kind), item.metadata.namespace, item, ownerReferences);
369018
+ }
369019
+ catch (err) {
369020
+ operator_src_logger.error(err);
369021
+ throw `Setting OwnerReferences to ${item.kind}/${item.metadata.name}: ${err}`;
369022
+ }
369023
+ }
369024
+ async function writeOwnerReferences(kind, namespace, item, ownerReferences) {
369025
+ operator_src_logger.debug(`The ctl is setting the ownerReferences for '${kind}/${item.metadata.name}' in namespace '${namespace}'.`);
369026
+ const { kc, opts } = await ctl_getConnection();
369027
+ const url = `${kc.getCurrentCluster().server}/apis/firestartr.dev/v1/namespaces/${namespace}/${kind}/${item.metadata.name}`;
369028
+ opts.headers['Content-Type'] = 'application/json-patch+json';
369029
+ opts.headers['Accept'] = '*';
369030
+ const patch = {
369031
+ op: 'replace',
369032
+ path: '/metadata/ownerReferences',
369033
+ value: ownerReferences,
369034
+ };
369035
+ const r = await fetch(url, {
369036
+ method: 'PATCH',
369037
+ headers: opts.headers,
369038
+ body: JSON.stringify([patch]),
369039
+ });
369040
+ if (!r.ok) {
369041
+ throw `Error on setOwnerReferences: ${namespace}/${kind}/${item['metadata']['name']}: ${r.statusText}`;
369042
+ }
369043
+ return r.json();
369044
+ }
369045
+
368929
369046
  ;// CONCATENATED MODULE: ../operator/fdummies/index.ts
368930
369047
 
368931
369048
 
368932
369049
 
369050
+
369051
+
368933
369052
  function processFirestartrDummies(item, op, handler) {
368934
369053
  operator_src_logger.info(`FirestartrDummies Processor: ${op}`);
368935
369054
  try {
@@ -368960,11 +369079,19 @@ async function* updated(item, op, handler) {
368960
369079
  for await (const transition of doRun(item, op, handler)) {
368961
369080
  yield transition;
368962
369081
  }
369082
+ await handleOwnerReferences(item, handler);
368963
369083
  }
368964
369084
  async function* created(item, op, handler) {
368965
369085
  for await (const transition of doRun(item, op, handler)) {
368966
369086
  yield transition;
368967
369087
  }
369088
+ await handleOwnerReferences(item, handler);
369089
+ }
369090
+ async function handleOwnerReferences(item, handler) {
369091
+ if ('needs' in item.spec) {
369092
+ const needs = item.spec.needs;
369093
+ await setOwnerReference(handler.itemPath(), item.metadata.namespace, definitions_getPluralFromKind(needs.kind), needs.name);
369094
+ }
368968
369095
  }
368969
369096
  async function renamed() {
368970
369097
  throw new Error('Renamed operation not prepared');
@@ -369035,7 +369162,7 @@ async function* markedToDeletion(item, op, handler) {
369035
369162
  message: 'Destroying process started',
369036
369163
  };
369037
369164
  await handler.resolveReferences();
369038
- await processDummy(item);
369165
+ await processDummy(item, op);
369039
369166
  yield {
369040
369167
  item,
369041
369168
  reason: op,
@@ -369104,7 +369231,7 @@ async function* doRun(item, op, handler) {
369104
369231
  };
369105
369232
  const deps = await handler.resolveReferences();
369106
369233
  operator_src_logger.info(`The dummy processor is applying and assessing dependencies for item '${item.kind}/${item.metadata.name}' with dependencies: '${deps}'.`);
369107
- await processDummy(item);
369234
+ await processDummy(item, op);
369108
369235
  yield {
369109
369236
  item,
369110
369237
  reason: op,
@@ -369160,11 +369287,13 @@ async function* doRun(item, op, handler) {
369160
369287
  }
369161
369288
  }
369162
369289
  }
369163
- async function processDummy(item) {
369164
- const s = item.spec?.computation?.numberOfSeconds;
369165
- operator_src_logger.info(`Processing dummy ${item.kind}/${item.metadata.name}: computing for ${s} seconds`);
369290
+ async function processDummy(item, op) {
369291
+ const s = op === OperationType.MARKED_TO_DELETION
369292
+ ? item.spec?.computation?.numberOfSecondsToDestroy
369293
+ : item.spec?.computation?.numberOfSeconds;
369294
+ operator_src_logger.info(`Processing dummy (op = ${op}) ${item.kind}/${item.metadata.name}: computing for ${s} seconds`);
369166
369295
  if (!s)
369167
- throw new Error('Unprocessable dummy: missing seconds section');
369296
+ throw new Error('Unprocessable dummy: no seconds section');
369168
369297
  await fdummies_fWait(s * 1000);
369169
369298
  }
369170
369299
  function fdummies_fWait(ms) {
@@ -369197,7 +369326,8 @@ async function writeDownQueueStatus(queue) {
369197
369326
  let output = '';
369198
369327
  for (const workItem of queue) {
369199
369328
  const item = workItem.item;
369200
- output += `${item.kind}/${item.metadata.name} - ${workItem.workStatus} - ${workItem.operation} - (upsert ${formatElapsedTimeWithDate(workItem.upsertTime)})\n`;
369329
+ const blockedText = workItem.isBlocked ? '[BLOCKED]' : '';
369330
+ output += `${item.kind}/${item.metadata.name} - ${workItem.workStatus} - ${workItem.operation} ${blockedText} - (upsert ${formatElapsedTimeWithDate(workItem.upsertTime)})\n`;
369201
369331
  }
369202
369332
  return new Promise((ok, ko) => {
369203
369333
  external_fs_.writeFile('/tmp/queue', output, (err) => {
@@ -369390,7 +369520,9 @@ async function processItem(workItem) {
369390
369520
  * @returns {void}
369391
369521
  */
369392
369522
  async function processItem_loop() {
369393
- const nextWorkItem = () => sortQueue(queue).find((w) => w.workStatus === WorkStatus.PENDING);
369523
+ const nextWorkItem = () => sortQueue(queue)
369524
+ .filter((w) => !w.isBlocked)
369525
+ .find((w) => w.workStatus === WorkStatus.PENDING);
369394
369526
  loopWorkItemDebug(queue);
369395
369527
  while (1) {
369396
369528
  const w = nextWorkItem();
@@ -369454,6 +369586,14 @@ async function runWorkItem(workItem) {
369454
369586
  return;
369455
369587
  try {
369456
369588
  const item = await workItem.getItem();
369589
+ // we check if the workItem needs blocking
369590
+ // if it does need it we return because we cannot
369591
+ // process this item
369592
+ if ('needsBlocking' in workItem.handler &&
369593
+ workItem.handler.needsBlocking(item)) {
369594
+ operator_src_logger.debug(`Item ${item.kind}/${item.metadata.namespace} needs blocking`);
369595
+ return;
369596
+ }
369457
369597
  workItem.workStatus = WorkStatus.PROCESSING;
369458
369598
  for await (const condition of workItem.process(item, workItem.operation, workItem.handler)) {
369459
369599
  if (workItem.handler === undefined)
@@ -371663,6 +371803,33 @@ function helperCreateCheckRunName(cmd, item) {
371663
371803
  return `${item.kind} - ${cmd}`;
371664
371804
  }
371665
371805
 
371806
+ ;// CONCATENATED MODULE: ../operator/src/cdktf/ownership.ts
371807
+
371808
+
371809
+
371810
+ const kindsWithFirestartrGithubRepositoryDependence = [
371811
+ 'FirestartrGithubRepositorySecretsSection',
371812
+ 'FirestartrGithubRepositoryFeature',
371813
+ ];
371814
+ async function manageOwnershipReferences(item, handler, op) {
371815
+ if (kindsWithFirestartrGithubRepositoryDependence.indexOf(item.kind) !== -1) {
371816
+ await manageOwnershipReferencesForRepo(item, handler, op);
371817
+ }
371818
+ }
371819
+ async function manageOwnershipReferencesForRepo(item, handler, op) {
371820
+ try {
371821
+ const repositoryTarget = item.spec?.repositoryTarget?.ref;
371822
+ if (!repositoryTarget) {
371823
+ throw `Item ${item.kind}/${item.metadata.namespace} is not correct: it does not have a repositoryTarget`;
371824
+ }
371825
+ await setOwnerReference(handler.itemPath(), item.metadata.namespace, definitions_getPluralFromKind(repositoryTarget.kind), repositoryTarget.name);
371826
+ }
371827
+ catch (err) {
371828
+ operator_src_logger.error(`Handling ownership for ${item.kind}/${item.metadata.name}: ${err}`);
371829
+ throw new Error(`Handling ownership for ${item.kind}/${item.metadata.name}: ${err}`);
371830
+ }
371831
+ }
371832
+
371666
371833
  ;// CONCATENATED MODULE: ../operator/cdktf.ts
371667
371834
 
371668
371835
 
@@ -371673,6 +371840,7 @@ function helperCreateCheckRunName(cmd, item) {
371673
371840
 
371674
371841
 
371675
371842
 
371843
+
371676
371844
  function processOperation(item, op, handler) {
371677
371845
  operator_src_logger.info(`Processing operation ${op} on ${item.kind}/${item.metadata?.name}`);
371678
371846
  try {
@@ -371704,16 +371872,19 @@ async function* cdktf_created(item, op, handler) {
371704
371872
  for await (const transition of doApply(item, op, handler)) {
371705
371873
  yield transition;
371706
371874
  }
371875
+ await manageOwnershipReferences(item, handler, op);
371707
371876
  }
371708
371877
  async function* cdktf_renamed(item, op, handler) {
371709
371878
  for await (const transition of doApply(item, op, handler)) {
371710
371879
  yield transition;
371711
371880
  }
371881
+ await manageOwnershipReferences(item, handler, op);
371712
371882
  }
371713
371883
  async function* cdktf_updated(item, op, handler) {
371714
371884
  for await (const transition of doApply(item, op, handler)) {
371715
371885
  yield transition;
371716
371886
  }
371887
+ await manageOwnershipReferences(item, handler, op);
371717
371888
  }
371718
371889
  async function* cdktf_retry(item, op, handler) {
371719
371890
  if ('deletionTimestamp' in item.metadata) {
@@ -1,3 +1,4 @@
1
1
  export default function render(featurePath: string, featureRenderPath: string, entity: any, firestartrConfig?: any, featureArgs?: any): any;
2
2
  export declare function buildContext(entity: any, args: any, firestartrConfig: any, featureArgs: any): any;
3
+ export declare function expandFiles(featurePath: string, configData: any, context: any): void;
3
4
  export declare function renderContent(template: string, ctx: any): string;
@@ -29,6 +29,13 @@ declare const _default: {
29
29
  };
30
30
  };
31
31
  };
32
+ filesTemplates: {
33
+ type: string;
34
+ description: string;
35
+ items: {
36
+ type: string;
37
+ };
38
+ };
32
39
  };
33
40
  required: string[];
34
41
  title: string;
@@ -48,7 +55,7 @@ declare const _default: {
48
55
  additionalProperties: boolean;
49
56
  properties: {
50
57
  $lit: {
51
- type: string;
58
+ type: string[];
52
59
  };
53
60
  $ref: {
54
61
  type: string;
@@ -0,0 +1,2 @@
1
+ import { OperationType } from '../informer';
2
+ export declare function manageOwnershipReferences(item: any, handler: any, op: OperationType): Promise<void>;
@@ -23,6 +23,8 @@ export type WorkItem = {
23
23
  process?: Function;
24
24
  upsertTime?: number;
25
25
  isDeadLetter?: boolean;
26
+ isBlocked?: boolean;
27
+ fUnblock?: Function;
26
28
  };
27
29
  type HandlerFinalizerFn = (kind: string, namespace: string, item: any | string, finalizer: string) => Promise<any>;
28
30
  type HandlerInformPlanFn = (prUrl: string, planText: string) => Promise<void>;
@@ -44,6 +46,9 @@ export type WorkItemHandler = {
44
46
  itemPath: ItemPathFn;
45
47
  error: ErrorFn;
46
48
  success: SuccessFn;
49
+ isBlocked?: boolean;
50
+ needsBlocking?: (item: any) => boolean;
51
+ fUnblock?: Function;
47
52
  };
48
53
  /**
49
54
  * Observe whenever a new item is added, modified or deleted in a given kind
@@ -0,0 +1,4 @@
1
+ import { OwnerReference } from './types';
2
+ export declare function getOwnerReferences(item: any): Promise<OwnerReference[]>;
3
+ export declare function setOwnerReference(itemPath: string, namespace: string, ownerKind: string, ownerName: string, blockOwnerDeletion?: boolean): Promise<void>;
4
+ export declare function writeOwnerReferences(kind: string, namespace: string, item: any, ownerReferences: OwnerReference[]): Promise<any>;
@@ -0,0 +1,8 @@
1
+ export interface OwnerReference {
2
+ apiVersion: string;
3
+ kind: string;
4
+ name: string;
5
+ uid: string;
6
+ controller?: boolean;
7
+ blockOwnerDeletion?: boolean;
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firestartr/cli",
3
- "version": "1.54.0",
3
+ "version": "1.55.0-snapshot-0",
4
4
  "private": false,
5
5
  "description": "Commandline tool",
6
6
  "main": "build/main.js",