Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(migrate): add migrate information to AWS::CDK::Metadata #28958

Merged
merged 2 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions packages/aws-cdk-lib/core/lib/private/metadata-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { Token } from '../token';
export class MetadataResource extends Construct {
constructor(scope: Stack, id: string) {
super(scope, id);

const metadataServiceExists = Token.isUnresolved(scope.region) || RegionInfo.get(scope.region).cdkMetadataResourceAvailable;
if (metadataServiceExists) {
const resource = new CfnResource(this, 'Default', {
Expand Down Expand Up @@ -51,22 +50,30 @@ function makeCdkMetadataAvailableCondition() {
class Trie extends Map<string, Trie> { }

/**
* Formats a list of construct fully-qualified names (FQNs) and versions into a (possibly compressed) prefix-encoded string.
* Formats the analytics string which has 3 or 4 sections separated by colons (:)
*
* version:encoding:constructinfo OR version:encoding:constructinfo:appinfo
*
* The list of ConstructInfos is logically formatted into:
* ${version}!${fqn} (e.g., "1.90.0!aws-cdk-lib.Stack")
* and then all of the construct-versions are grouped with common prefixes together, grouping common parts in '{}' and separating items with ','.
* The constructinfo section is a list of construct fully-qualified names (FQNs)
* and versions into a (possibly compressed) prefix-encoded string.
*
* The list of ConstructInfos is logically formatted into: ${version}!${fqn}
* (e.g., "1.90.0!aws-cdk-lib.Stack") and then all of the construct-versions are
* grouped with common prefixes together, grouping common parts in '{}' and
* separating items with ','.
*
* Example:
* [1.90.0!aws-cdk-lib.Stack, 1.90.0!aws-cdk-lib.Construct, 1.90.0!aws-cdk-lib.service.Resource, 0.42.1!aws-cdk-lib-experiments.NewStuff]
* Becomes:
* 1.90.0!aws-cdk-lib.{Stack,Construct,service.Resource},0.42.1!aws-cdk-lib-experiments.NewStuff
*
* The whole thing is then either included directly as plaintext as:
* v2:plaintext:{prefixEncodedList}
* Or is compressed and base64-encoded, and then formatted as:
* The whole thing is then compressed and base64-encoded, and then formatted as:
* v2:deflate64:{prefixEncodedListCompressedAndEncoded}
*
* The appinfo section is optional, and currently only added if the app was generated using `cdk migrate`
* It is also compressed and base64-encoded. In this case, the string will be formatted as:
* v2:deflate64:{prefixEncodedListCompressedAndEncoded}:{'cdk-migrate'CompressedAndEncoded}
*
* Exported/visible for ease of testing.
*/
export function formatAnalytics(infos: ConstructInfo[]) {
Expand All @@ -81,7 +88,15 @@ export function formatAnalytics(infos: ConstructInfo[]) {
setGzipOperatingSystemToUnknown(compressedConstructsBuffer);

const compressedConstructs = compressedConstructsBuffer.toString('base64');
return `v2:deflate64:${compressedConstructs}`;
const analyticsString = `v2:deflate64:${compressedConstructs}`;

if (process.env.CDK_CONTEXT_JSON && JSON.parse(process.env.CDK_CONTEXT_JSON)['cdk-migrate']) {
const compressedAppInfoBuffer = zlib.gzipSync(Buffer.from('cdk-migrate'));
const compressedAppInfo = compressedAppInfoBuffer.toString('base64');
analyticsString.concat(':', compressedAppInfo);
}

return analyticsString;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/aws-cdk/lib/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export async function generateCdkApp(stackName: string, stack: string, language:
generateOnly,
workDir: resolvedOutputPath,
stackName,
migrate: true,
});

let stackFileName: string;
Expand Down
22 changes: 21 additions & 1 deletion packages/aws-cdk/lib/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface CliInitOptions {
readonly generateOnly?: boolean;
readonly workDir?: string;
readonly stackName?: string;
readonly migrate?: boolean;
}

/**
Expand Down Expand Up @@ -51,7 +52,7 @@ export async function cliInit(options: CliInitOptions) {
throw new Error('No language was selected');
}

await initializeProject(template, options.language, canUseNetwork, generateOnly, workDir, options.stackName);
await initializeProject(template, options.language, canUseNetwork, generateOnly, workDir, options.stackName, options.migrate);
}

/**
Expand Down Expand Up @@ -203,6 +204,21 @@ export class InitTemplate {

await fs.writeJson(cdkJson, config, { spaces: 2 });
}

public async addMigrateContext(projectDir: string) {
const cdkJson = path.join(projectDir, 'cdk.json');
if (!await fs.pathExists(cdkJson)) {
return;
}

const config = await fs.readJson(cdkJson);
config.context = {
...config.context,
'cdk-migrate': true,
};

await fs.writeJson(cdkJson, config, { spaces: 2 });
}
}

interface ProjectInfo {
Expand Down Expand Up @@ -271,10 +287,14 @@ async function initializeProject(
generateOnly: boolean,
workDir: string,
stackName?: string,
migrate?: boolean,
) {
await assertIsEmptyDirectory(workDir);
print(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`);
await template.install(language, workDir, stackName);
if (migrate) {
await template.addMigrateContext(workDir);
}
if (await fs.pathExists('README.md')) {
print(chalk.green(await fs.readFile('README.md', { encoding: 'utf-8' })));
}
Expand Down
12 changes: 12 additions & 0 deletions packages/aws-cdk/test/commands/migrate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ describe('Migrate Function Tests', () => {
expect(replacedStack).toEqual(fs.readFileSync(path.join(...stackPath, 's3-stack.ts'), 'utf8'));
});

cliTest('generateCdkApp adds cdk-migrate key in context', async (workDir) => {
const stack = generateStack(validTemplate, 'GoodTypeScript', 'typescript');
await generateCdkApp('GoodTypeScript', stack, 'typescript', workDir);

// cdk.json exist in the correct spot
expect(fs.pathExistsSync(path.join(workDir, 'GoodTypeScript', 'cdk.json'))).toBeTruthy();

// cdk.json has "cdk-migrate" : true in context
const cdkJson = fs.readJsonSync(path.join(workDir, 'GoodTypeScript', 'cdk.json'), 'utf8');
expect(cdkJson.context['cdk-migrate']).toBeTruthy();
});

cliTest('generateCdkApp generates the expected cdk app when called for python', async (workDir) => {
const stack = generateStack(validTemplate, 'GoodPython', 'python');
await generateCdkApp('GoodPython', stack, 'python', workDir);
Expand Down
Loading