@ibm-cloud/cd-tools 1.2.0 → 1.2.2
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/cmd/copy-toolchain.js
CHANGED
|
@@ -16,7 +16,7 @@ import { Command, Option } from 'commander';
|
|
|
16
16
|
import { parseEnvVar } from './utils/utils.js';
|
|
17
17
|
import { logger, LOG_STAGES } from './utils/logger.js';
|
|
18
18
|
import { setTerraformEnv, initProviderFile, setupTerraformFiles, runTerraformInit, getNumResourcesPlanned, runTerraformApply, getNumResourcesCreated, getNewToolchainId } from './utils/terraform.js';
|
|
19
|
-
import { getAccountId, getBearerToken, getIamAuthPolicies, getResourceGroupIdAndName, getToolchain } from './utils/requests.js';
|
|
19
|
+
import { getAccountId, getBearerToken, getCdInstanceByRegion, getIamAuthPolicies, getResourceGroupIdAndName, getToolchain } from './utils/requests.js';
|
|
20
20
|
import { validatePrereqsVersions, validateTag, validateToolchainId, validateToolchainName, validateTools, validateOAuth, warnDuplicateName, validateGritUrl } from './utils/validate.js';
|
|
21
21
|
import { importTerraform } from './utils/import-terraform.js';
|
|
22
22
|
|
|
@@ -26,11 +26,12 @@ process.on('exit', (code) => {
|
|
|
26
26
|
if (code !== 0) logger.print(`Need help? Visit ${MIGRATION_DOC_URL} for more troubleshooting information.`);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
const TIME_SUFFIX = new Date().getTime();
|
|
29
30
|
const LOGS_DIR = '.logs';
|
|
30
|
-
const TEMP_DIR = '.migration-temp'
|
|
31
|
+
const TEMP_DIR = '.migration-temp-' + TIME_SUFFIX;
|
|
31
32
|
const LOG_DUMP = process.env['LOG_DUMP'] === 'false' ? false : true; // when true or not specified, logs are also written to a log file in LOGS_DIR
|
|
32
33
|
const DEBUG_MODE = process.env['DEBUG_MODE'] === 'true' ? true : false; // when true, temp folder is preserved
|
|
33
|
-
const OUTPUT_DIR = 'output-' +
|
|
34
|
+
const OUTPUT_DIR = 'output-' + TIME_SUFFIX;
|
|
34
35
|
const DRY_RUN = false; // when true, terraform apply does not run
|
|
35
36
|
|
|
36
37
|
|
|
@@ -100,6 +101,16 @@ async function main(options) {
|
|
|
100
101
|
bearer = await getBearerToken(apiKey);
|
|
101
102
|
const accountId = await getAccountId(bearer, apiKey);
|
|
102
103
|
|
|
104
|
+
// check for continuous delivery instance in target region
|
|
105
|
+
if (!await getCdInstanceByRegion(bearer, accountId, targetRegion)) throw Error(`Could not find a Continuous Delivery instance in the target region '${targetRegion}', please create one before proceeding.`);
|
|
106
|
+
|
|
107
|
+
// check for existing .tf files in output directory
|
|
108
|
+
if (fs.existsSync(outputDir)) {
|
|
109
|
+
let files = readdirSync(outputDir, { recursive: true });
|
|
110
|
+
files = files.filter((f) => f.endsWith('.tf'));
|
|
111
|
+
if (files.length > 0) throw Error(`Output directory already has ${files.length} '.tf' files, please specify a different output directory`);
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
if (options.gritMappingFile) {
|
|
104
115
|
gritMapping = JSON.parse(fs.readFileSync(resolve(options.gritMappingFile)));
|
|
105
116
|
const gritPromises = [];
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import fs from 'node:fs';
|
|
11
|
-
import { promisify } from 'node:util';
|
|
12
11
|
|
|
13
12
|
import { parse as tfToJson } from '@cdktf/hcl2json'
|
|
14
13
|
import { jsonToTf } from 'json-to-tf';
|
|
@@ -19,8 +18,6 @@ import { getRandChars, isSecretReference, normalizeName } from './utils.js';
|
|
|
19
18
|
|
|
20
19
|
import { SECRET_KEYS_MAP, SUPPORTED_TOOLS_MAP } from '../../config.js';
|
|
21
20
|
|
|
22
|
-
const writeFilePromise = promisify(fs.writeFile);
|
|
23
|
-
|
|
24
21
|
export async function importTerraform(token, apiKey, region, toolchainId, toolchainName, policyIds, dir, isCompact, verbosity) {
|
|
25
22
|
// STEP 1/2: set up terraform file with import blocks
|
|
26
23
|
const importBlocks = []; // an array of objects representing import blocks, used in importBlocksToTf
|
|
@@ -150,7 +147,7 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
|
|
|
150
147
|
}
|
|
151
148
|
}
|
|
152
149
|
|
|
153
|
-
|
|
150
|
+
importBlocksToTf(importBlocks, dir);
|
|
154
151
|
|
|
155
152
|
if (!fs.existsSync(`${dir}/generated`)) fs.mkdirSync(`${dir}/generated`);
|
|
156
153
|
|
|
@@ -296,7 +293,7 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
|
|
|
296
293
|
}
|
|
297
294
|
} else {
|
|
298
295
|
const generatedFileNew = jsonToTf(JSON.stringify(newTfFileObj));
|
|
299
|
-
fs.writeFileSync(`${dir}/generated/
|
|
296
|
+
fs.writeFileSync(`${dir}/generated/resources.tf`, generatedFileNew);
|
|
300
297
|
}
|
|
301
298
|
|
|
302
299
|
// remove draft
|
|
@@ -318,7 +315,7 @@ function importBlock(id, name, resourceType) {
|
|
|
318
315
|
}
|
|
319
316
|
|
|
320
317
|
// importBlocks array to tf file
|
|
321
|
-
|
|
318
|
+
function importBlocksToTf(blocks, dir) {
|
|
322
319
|
let fileContent = '';
|
|
323
320
|
|
|
324
321
|
blocks.forEach((block) => {
|
|
@@ -329,5 +326,5 @@ async function importBlocksToTf(blocks, dir) {
|
|
|
329
326
|
fileContent += template;
|
|
330
327
|
});
|
|
331
328
|
|
|
332
|
-
return
|
|
329
|
+
return fs.writeFileSync(`${dir}/import.tf`, fileContent);
|
|
333
330
|
}
|
package/cmd/utils/requests.js
CHANGED
|
@@ -141,6 +141,31 @@ async function getToolchainsByName(bearer, accountId, toolchainName) {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
async function getCdInstanceByRegion(bearer, accountId, region) {
|
|
145
|
+
const apiBaseUrl = 'https://api.global-search-tagging.cloud.ibm.com/v3';
|
|
146
|
+
const options = {
|
|
147
|
+
url: apiBaseUrl + '/resources/search',
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: {
|
|
150
|
+
'Authorization': `Bearer ${bearer}`,
|
|
151
|
+
'Content-Type': 'application/json',
|
|
152
|
+
},
|
|
153
|
+
data: {
|
|
154
|
+
'query': `service_name:continuous-delivery AND region:"${region}" AND doc.state:ACTIVE`,
|
|
155
|
+
'fields': ['doc.resource_group_id', 'doc.region_id']
|
|
156
|
+
},
|
|
157
|
+
params: { account_id: accountId },
|
|
158
|
+
validateStatus: () => true
|
|
159
|
+
};
|
|
160
|
+
const response = await axios(options);
|
|
161
|
+
switch (response.status) {
|
|
162
|
+
case 200:
|
|
163
|
+
return response.data.items.length > 0;
|
|
164
|
+
default:
|
|
165
|
+
throw Error('Get CD instance failed');
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
144
169
|
async function getToolchainTools(bearer, toolchainId, region) {
|
|
145
170
|
const apiBaseUrl = `https://api.${region}.devops.cloud.ibm.com/toolchain/v2`;
|
|
146
171
|
const options = {
|
|
@@ -388,6 +413,7 @@ async function deleteToolchain(bearer, toolchainId, region) {
|
|
|
388
413
|
export {
|
|
389
414
|
getBearerToken,
|
|
390
415
|
getAccountId,
|
|
416
|
+
getCdInstanceByRegion,
|
|
391
417
|
getToolchain,
|
|
392
418
|
getToolchainsByName,
|
|
393
419
|
getToolchainTools,
|
package/cmd/utils/terraform.js
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
import child_process from 'node:child_process';
|
|
11
11
|
import fs from 'node:fs';
|
|
12
|
-
import { randomInt } from 'node:crypto';
|
|
13
12
|
import { promisify } from 'node:util';
|
|
14
13
|
|
|
15
14
|
import { parse as tfToJson } from '@cdktf/hcl2json'
|
|
@@ -302,7 +301,7 @@ async function setupTerraformFiles({ token, srcRegion, targetRegion, targetTag,
|
|
|
302
301
|
}
|
|
303
302
|
|
|
304
303
|
async function runTerraformPlanGenerate(dir, fileName) {
|
|
305
|
-
return await execPromise(`terraform plan -generate-config-out
|
|
304
|
+
return await execPromise(`terraform plan -generate-config-out="${fileName}"`, { cwd: dir });
|
|
306
305
|
}
|
|
307
306
|
|
|
308
307
|
async function runTerraformInit(dir) {
|
package/cmd/utils/validate.js
CHANGED
|
@@ -372,7 +372,7 @@ async function validateOAuth(token, tools, targetRegion, skipPrompt) {
|
|
|
372
372
|
|
|
373
373
|
let hasFailedLink = false;
|
|
374
374
|
|
|
375
|
-
logger.print('Authorize using the following links
|
|
375
|
+
if (oauthLinks.length > 0) logger.print('Authorize using the following links:\n');
|
|
376
376
|
oauthLinks.forEach((o) => {
|
|
377
377
|
if (o.link === 'Could not get OAuth link') hasFailedLink = true;
|
|
378
378
|
logger.print(`${o.type}: \x1b[36m${o.link}\x1b[0m\n`);
|