@ibm-cloud/cd-tools 1.15.15 → 1.15.17

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.
@@ -86,7 +86,11 @@ async function main(options) {
86
86
 
87
87
  logger.setVerbosity(verbosity);
88
88
  if (LOG_DUMP) logger.createLogStream(`${LOGS_DIR}/copy-toolchain-${TIME_SUFFIX}.log`);
89
- logger.dump(`Options: ${JSON.stringify(options)}\n`);
89
+
90
+ // redact apikey option in logs
91
+ const printOptions = options;
92
+ printOptions.apikey ? printOptions.apikey = '<API KEY>' : delete printOptions.apikey;
93
+ logger.dump(`Options: ${JSON.stringify(printOptions)}\n`);
90
94
 
91
95
  let bearer;
92
96
  let sourceToolchainId;
@@ -14,7 +14,7 @@ import { jsonToTf } from 'json-to-tf';
14
14
 
15
15
  import { getPipelineData, getToolchainTools } from './requests.js';
16
16
  import { runTerraformPlanGenerate, setTerraformEnv } from './terraform.js';
17
- import { getRandChars, isSecretReference, normalizeName } from './utils.js';
17
+ import { escapeReservedChars, getRandChars, isSecretReference, normalizeName } from './utils.js';
18
18
  import { logger } from './logger.js';
19
19
 
20
20
  import { SECRET_KEYS_MAP, SUPPORTED_TOOLS_MAP } from '../../config.js';
@@ -213,22 +213,14 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
213
213
  try {
214
214
  if (Object.keys(v[0]['parameters'][0]).length > 0) {
215
215
  for (const [k2, v2] of Object.entries(v[0]['parameters'][0])) {
216
- if (v2 === null) delete newTfFileObj['resource'][key][k]['parameters'][0][k2];
216
+ if (v2 === null && k2 != 'name') delete newTfFileObj['resource'][key][k]['parameters'][0][k2];
217
+ // don't delete name, just leave it as null if it is already null
217
218
  }
218
219
  }
219
220
  } catch {
220
221
  // do nothing
221
222
  }
222
223
 
223
- // if parameters is now empty after removing null values, remove parameters entirely
224
- try {
225
- if (Object.keys(v[0]['parameters'][0]).length === 0) {
226
- newTfFileObj['resource'][key][k]['parameters'] = [];
227
- }
228
- } catch {
229
- // do nothing
230
- }
231
-
232
224
  // ignore null values (if it exists) in source properties
233
225
  try {
234
226
  if (Object.keys(v[0]['source'][0]['properties'][0]).length > 0) {
@@ -271,7 +263,7 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
271
263
  if (propValue.startsWith(START_INDICATOR) && propValue.endsWith(END_INDICATOR)) {
272
264
  // skip substitution for jsonencode case, don't want to mangle it
273
265
  } else {
274
- newValue = newValue.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/"/g, '\\"');
266
+ newValue = escapeReservedChars(propValue);
275
267
  }
276
268
  newTfFileObj['resource'][key][k]['value'] = newValue;
277
269
  }
@@ -322,7 +314,12 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
322
314
  for (const [key, value] of Object.entries(generatedFileJson['resource'])) {
323
315
  for (const [k, v] of Object.entries(value)) {
324
316
  if (key === 'ibm_cd_tekton_pipeline_definition' || key === 'ibm_cd_tekton_pipeline_trigger') {
325
- if (key === 'ibm_cd_tekton_pipeline_trigger' && !v['source']) continue; // skip triggers without source, which aren't tied to a repo
317
+ // escape filter, which may contain reserved characters
318
+ if (key === 'ibm_cd_tekton_pipeline_trigger' && v[0]['filter']) {
319
+ newTfFileObj['resource'][key][k]['filter'] = escapeReservedChars(v[0]['filter']);
320
+ }
321
+
322
+ if (key === 'ibm_cd_tekton_pipeline_trigger' && !v[0]['source']) continue; // skip triggers without source, which aren't tied to a repo
326
323
  try {
327
324
  const thisUrl = newTfFileObj['resource'][key][k]['source'][0]['properties'][0]['url'];
328
325
 
@@ -16,7 +16,7 @@ import { jsonToTf } from 'json-to-tf';
16
16
 
17
17
  import { validateToolchainId, validateGritUrl } from './validate.js';
18
18
  import { logger, LOG_STAGES } from './logger.js';
19
- import { getRandChars, promptUserInput, replaceUrlRegion } from './utils.js';
19
+ import { escapeReservedChars, getRandChars, promptUserInput, replaceUrlRegion } from './utils.js';
20
20
 
21
21
  const CLOUD_PLATFORM = process.env['IBMCLOUD_PLATFORM_DOMAIN'] || 'cloud.ibm.com';
22
22
  const DEV_MODE = CLOUD_PLATFORM !== 'cloud.ibm.com';
@@ -31,7 +31,7 @@ const writeFilePromise = promisify(fs.writeFile)
31
31
  async function execPromise(command, options) {
32
32
  try {
33
33
  const exec = promisify(child_process.exec);
34
- const { stdout, _ } = await exec(command, options);
34
+ const { stdout, _ } = await exec(command, {...options, maxBuffer: 10 * 1024 * 1024}); // set max buffer to 10MB
35
35
  return stdout.trim();
36
36
  } catch (err) {
37
37
  throw new Error(`Command failed: ${command} \n${err.stderr || err.stdout}`);
@@ -258,8 +258,16 @@ async function setupTerraformFiles(config) {
258
258
  // by default, disable triggers
259
259
  if (disableTriggers && newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger']) {
260
260
  for (const key of Object.keys(newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'])) {
261
- if (newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['type'] === 'manual') continue; // skip manual triggers
262
- newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['enabled'] = false;
261
+ // escape filter, which may contain reserved characters
262
+ const filterVal = newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['filter'];
263
+ if (filterVal) {
264
+ newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['filter'] = escapeReservedChars(filterVal);
265
+ }
266
+
267
+ // disable all triggers (timed, git, webhooks) except manual triggers
268
+ if (newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['type'] != 'manual') {
269
+ newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger'][key]['enabled'] = false;
270
+ }
263
271
  }
264
272
  }
265
273
 
@@ -360,7 +368,7 @@ async function setupTerraformFiles(config) {
360
368
  if (thisValue.startsWith(START_INDICATOR) && thisValue.endsWith(END_INDICATOR)) {
361
369
  // skip newline substitution for jsonencode case, don't want to mangle it
362
370
  } else {
363
- newTfFileObj['resource']['ibm_cd_tekton_pipeline_property'][k]['value'] = thisValue.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/"/g, '\\"');
371
+ newTfFileObj['resource']['ibm_cd_tekton_pipeline_property'][k]['value'] = escapeReservedChars(thisValue);
364
372
  }
365
373
  }
366
374
  } catch (err) {
@@ -388,7 +396,7 @@ async function setupTerraformFiles(config) {
388
396
  if (thisValue.startsWith(START_INDICATOR) && thisValue.endsWith(END_INDICATOR)) {
389
397
  // skip newline substitution for jsonencode case, don't want to mangle it
390
398
  } else {
391
- newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger_property'][k]['value'] = thisValue.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/"/g, '\\"');
399
+ newTfFileObj['resource']['ibm_cd_tekton_pipeline_trigger_property'][k]['value'] = escapeReservedChars(thisValue);
392
400
  }
393
401
  }
394
402
  } catch (err) {
@@ -223,4 +223,11 @@ export function normalizeName(str) {
223
223
  }
224
224
 
225
225
  return newStr.toLowerCase();
226
+ };
227
+
228
+ export function escapeReservedChars(str) {
229
+ if (!str || typeof str !== 'string') {
230
+ return str;
231
+ }
232
+ return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/"/g, '\\"');
226
233
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibm-cloud/cd-tools",
3
- "version": "1.15.15",
3
+ "version": "1.15.17",
4
4
  "description": "Tools and utilities for the IBM Cloud Continuous Delivery service and resources",
5
5
  "repository": {
6
6
  "type": "git",