in packages/aws-cdk/lib/cli/cdk-toolkit.ts [1125:1211]
public async migrate(options: MigrateOptions): Promise<void> {
warning('This command is an experimental feature.');
const language = options.language?.toLowerCase() ?? 'typescript';
const environment = setEnvironment(options.account, options.region);
let generateTemplateOutput: GenerateTemplateOutput | undefined;
let cfn: CfnTemplateGeneratorProvider | undefined;
let templateToDelete: string | undefined;
try {
// if neither fromPath nor fromStack is provided, generate a template using cloudformation
const scanType = parseSourceOptions(options.fromPath, options.fromStack, options.stackName).source;
if (scanType == TemplateSourceOptions.SCAN) {
generateTemplateOutput = await generateTemplate({
stackName: options.stackName,
filters: options.filter,
fromScan: options.fromScan,
sdkProvider: this.props.sdkProvider,
environment: environment,
});
templateToDelete = generateTemplateOutput.templateId;
} else if (scanType == TemplateSourceOptions.PATH) {
const templateBody = readFromPath(options.fromPath!);
const parsedTemplate = deserializeStructure(templateBody);
const templateId = parsedTemplate.Metadata?.TemplateId?.toString();
if (templateId) {
// if we have a template id, we can call describe generated template to get the resource identifiers
// resource metadata, and template source to generate the template
cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment));
const generatedTemplateSummary = await cfn.describeGeneratedTemplate(templateId);
generateTemplateOutput = buildGenertedTemplateOutput(
generatedTemplateSummary,
templateBody,
generatedTemplateSummary.GeneratedTemplateId!,
);
} else {
generateTemplateOutput = {
migrateJson: {
templateBody: templateBody,
source: 'localfile',
},
};
}
} else if (scanType == TemplateSourceOptions.STACK) {
const template = await readFromStack(options.stackName, this.props.sdkProvider, environment);
if (!template) {
throw new ToolkitError(`No template found for stack-name: ${options.stackName}`);
}
generateTemplateOutput = {
migrateJson: {
templateBody: template,
source: options.stackName,
},
};
} else {
// We shouldn't ever get here, but just in case.
throw new ToolkitError(`Invalid source option provided: ${scanType}`);
}
const stack = generateStack(generateTemplateOutput.migrateJson.templateBody, options.stackName, language);
success(' ⏳ Generating CDK app for %s...', chalk.blue(options.stackName));
await generateCdkApp(options.stackName, stack!, language, options.outputPath, options.compress);
if (generateTemplateOutput) {
writeMigrateJsonFile(options.outputPath, options.stackName, generateTemplateOutput.migrateJson);
}
if (isThereAWarning(generateTemplateOutput)) {
warning(
' ⚠️ Some resources could not be migrated completely. Please review the README.md file for more information.',
);
appendWarningsToReadme(
`${path.join(options.outputPath ?? process.cwd(), options.stackName)}/README.md`,
generateTemplateOutput.resources!,
);
}
} catch (e) {
error(' ❌ Migrate failed for `%s`: %s', options.stackName, (e as Error).message);
throw e;
} finally {
if (templateToDelete) {
if (!cfn) {
cfn = new CfnTemplateGeneratorProvider(await buildCfnClient(this.props.sdkProvider, environment));
}
if (!process.env.MIGRATE_INTEG_TEST) {
await cfn.deleteGeneratedTemplate(templateToDelete);
}
}
}
}