@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
615 lines • 90.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestFixture = exports.EXTENDED_TEST_TIMEOUT_S = exports.DEFAULT_TEST_TIMEOUT_S = void 0;
exports.withSpecificCdkApp = withSpecificCdkApp;
exports.withCdkApp = withCdkApp;
exports.withCdkMigrateApp = withCdkMigrateApp;
exports.withDefaultFixture = withDefaultFixture;
exports.withSpecificFixture = withSpecificFixture;
exports.withExtendedTimeoutFixture = withExtendedTimeoutFixture;
exports.withCDKMigrateFixture = withCDKMigrateFixture;
exports.withoutBootstrap = withoutBootstrap;
exports.cloneDirectory = cloneDirectory;
exports.ensureBootstrapped = ensureBootstrapped;
exports.installNpmPackages = installNpmPackages;
/* eslint-disable no-console */
const assert = require("assert");
const fs = require("fs");
const os = require("os");
const path = require("path");
const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
const client_ecr_public_1 = require("@aws-sdk/client-ecr-public");
const aws_1 = require("./aws");
const subprocess_1 = require("./package-sources/subprocess");
const resources_1 = require("./resources");
const shell_1 = require("./shell");
const with_aws_1 = require("./with-aws");
const with_timeout_1 = require("./with-timeout");
const yarn_1 = require("./yarn");
exports.DEFAULT_TEST_TIMEOUT_S = 20 * 60;
exports.EXTENDED_TEST_TIMEOUT_S = 30 * 60;
/**
* Higher order function to execute a block with a CDK app fixture
*
* Requires an AWS client to be passed in.
*
* For backwards compatibility with existing tests (so we don't have to change
* too much) the inner block is expected to take a `TestFixture` object.
*/
function withSpecificCdkApp(appName, block) {
return async (context) => {
const randy = context.randomString;
const stackNamePrefix = `cdktest-${randy}`;
const integTestDir = path.join(os.tmpdir(), `cdk-integ-${randy}`);
context.output.write(` Stack prefix: ${stackNamePrefix}\n`);
context.output.write(` Test directory: ${integTestDir}\n`);
context.output.write(` Region: ${context.aws.region}\n`);
await cloneDirectory(path.join(resources_1.RESOURCES_DIR, 'cdk-apps', appName), integTestDir, context.output);
const fixture = new TestFixture(integTestDir, stackNamePrefix, context.output, context.aws, context.randomString);
await fixture.ecrPublicLogin();
let success = true;
try {
const installationVersion = fixture.library.requestedVersion();
await installNpmPackages(fixture, {
'aws-cdk-lib': installationVersion,
'constructs': '^10',
});
if (!context.disableBootstrap) {
await ensureBootstrapped(fixture);
}
await block(fixture);
}
catch (e) {
success = false;
throw e;
}
finally {
if (process.env.INTEG_NO_CLEAN) {
context.log(`Left test directory in '${integTestDir}' ($INTEG_NO_CLEAN)\n`);
}
else {
await fixture.dispose(success);
}
}
};
}
/**
* Like `withSpecificCdkApp`, but uses the default integration testing app with a million stacks in it
*/
function withCdkApp(block) {
// 'app' is the name of the default integration app in the `cdk-apps` directory
return withSpecificCdkApp('app', block);
}
function withCdkMigrateApp(language, block) {
return async (context) => {
const stackName = `cdk-migrate-${language}-integ-${context.randomString}`;
const integTestDir = path.join(os.tmpdir(), `cdk-migrate-${language}-integ-${context.randomString}`);
context.output.write(` Stack name: ${stackName}\n`);
context.output.write(` Test directory: ${integTestDir}\n`);
fs.mkdirSync(integTestDir);
const fixture = new TestFixture(integTestDir, stackName, context.output, context.aws, context.randomString);
await fixture.ecrPublicLogin();
await ensureBootstrapped(fixture);
await fixture.cdkMigrate(language, stackName);
const testFixture = new TestFixture(path.join(integTestDir, stackName), stackName, context.output, context.aws, context.randomString);
let success = true;
try {
await block(testFixture);
}
catch (e) {
success = false;
throw e;
}
finally {
if (process.env.INTEG_NO_CLEAN) {
context.log(`Left test directory in '${integTestDir}' ($INTEG_NO_CLEAN)`);
}
else {
await fixture.dispose(success);
}
}
};
}
/**
* Default test fixture for most (all?) integ tests
*
* It's a composition of withAws/withCdkApp, expecting the test block to take a `TestFixture`
* object.
*
* We could have put `withAws(withCdkApp(fixture => { /... actual test here.../ }))` in every
* test declaration but centralizing it is going to make it convenient to modify in the future.
*/
function withDefaultFixture(block) {
return (0, with_aws_1.withAws)((0, with_timeout_1.withTimeout)(exports.DEFAULT_TEST_TIMEOUT_S, withCdkApp(block)));
}
function withSpecificFixture(appName, block) {
return (0, with_aws_1.withAws)((0, with_timeout_1.withTimeout)(exports.DEFAULT_TEST_TIMEOUT_S, withSpecificCdkApp(appName, block)));
}
function withExtendedTimeoutFixture(block) {
return (0, with_aws_1.withAws)((0, with_timeout_1.withTimeout)(exports.EXTENDED_TEST_TIMEOUT_S, withCdkApp(block)));
}
function withCDKMigrateFixture(language, block) {
return (0, with_aws_1.withAws)((0, with_timeout_1.withTimeout)(exports.DEFAULT_TEST_TIMEOUT_S, withCdkMigrateApp(language, block)));
}
/**
* To be used in place of `withDefaultFixture` when the test
* should not create the default bootstrap stack
*/
function withoutBootstrap(block) {
return (0, with_aws_1.withAws)(withCdkApp(block), true);
}
/**
* Prepare a target dir byreplicating a source directory
*/
async function cloneDirectory(source, target, output) {
await (0, shell_1.shell)(['rm', '-rf', target], { outputs: output ? [output] : [] });
await (0, shell_1.shell)(['mkdir', '-p', target], { outputs: output ? [output] : [] });
await (0, shell_1.shell)(['cp', '-R', source + '/*', target], { outputs: output ? [output] : [] });
}
class TestFixture extends shell_1.ShellHelper {
integTestDir;
stackNamePrefix;
output;
aws;
randomString;
qualifier;
bucketsToDelete = new Array();
cli;
library;
constructor(integTestDir, stackNamePrefix, output, aws, randomString) {
super(integTestDir, output);
this.integTestDir = integTestDir;
this.stackNamePrefix = stackNamePrefix;
this.output = output;
this.aws = aws;
this.randomString = randomString;
this.qualifier = this.randomString.slice(0, 10);
this.cli = (0, subprocess_1.testSource)('cli');
this.library = (0, subprocess_1.testSource)('library');
}
log(s) {
this.output.write(`${s}\n`);
}
/**
* Login to the public ECR gallery using the current AWS credentials.
* Use this if your test needs to directly pull images outside of a `cdk` or `cdk-assets` command.
*/
async ecrPublicLogin() {
const tokenResponse = await this.aws.ecrPublic.send(new client_ecr_public_1.GetAuthorizationTokenCommand({}));
const authData = tokenResponse.authorizationData?.authorizationToken;
const docker = process.env.CDK_DOCKER ?? 'docker';
if (!authData) {
throw new Error('Could not retrieve ECR public auth token.');
}
const decoded = Buffer.from(authData, 'base64').toString('utf-8');
const [username, password] = decoded.split(':');
await this.shell([docker, 'login',
'--username', username,
'--password', '${ECR_PASSWORD}',
'public.ecr.aws'], {
shell: true,
modEnv: {
ECR_PASSWORD: password,
},
});
}
async cdkDeploy(stackNames, options = {}, skipStackRename) {
return this.cdk(this.cdkDeployCommandLine(stackNames, options, skipStackRename), options);
}
cdkDeployCommandLine(stackNames, options = {}, skipStackRename) {
stackNames = typeof stackNames === 'string' ? [stackNames] : stackNames;
const neverRequireApproval = options.neverRequireApproval ?? true;
return [
'deploy',
...(neverRequireApproval ? ['--require-approval=never'] : []), // Default to no approval in an unattended test
...(options.options ?? []),
// use events because bar renders bad in tests
'--progress', 'events',
...(skipStackRename ? stackNames : this.fullStackName(stackNames)),
];
}
async cdkSynth(options = {}) {
return this.cdk([
'synth',
...(options.options ?? []),
], options);
}
async cdkRefactor(options = {}) {
return this.cdk([
'refactor',
...(options.options ?? []),
], options);
}
async cdkDestroy(stackNames, options = {}) {
stackNames = typeof stackNames === 'string' ? [stackNames] : stackNames;
// default to true because most tests don't test user interaction
const force = options.force ?? true;
return this.cdk(['destroy',
...(force ? ['-f'] : []), // pass -f if user interaction is not desired
...(options.options ?? []),
...this.fullStackName(stackNames)], options);
}
async cdkBootstrapLegacy(options) {
const args = ['bootstrap'];
if (options.verbose) {
args.push('-v');
}
args.push('--toolkit-stack-name', options.toolkitStackName);
if (options.bootstrapBucketName) {
args.push('--bootstrap-bucket-name', options.bootstrapBucketName);
}
if (options.noExecute) {
args.push('--no-execute');
}
if (options.publicAccessBlockConfiguration !== undefined) {
args.push('--public-access-block-configuration', options.publicAccessBlockConfiguration.toString());
}
if (options.tags) {
args.push('--tags', options.tags);
}
return this.cdk(args, {
...options.cliOptions,
modEnv: {
...options.cliOptions?.modEnv,
// so that this works for V2,
// where the "new" bootstrap is the default
CDK_LEGACY_BOOTSTRAP: '1',
},
});
}
async cdkBootstrapModern(options) {
const args = ['bootstrap'];
if (options.verbose) {
args.push('-v');
}
if (options.showTemplate) {
args.push('--show-template');
}
if (options.template) {
args.push('--template', options.template);
}
args.push('--toolkit-stack-name', options.toolkitStackName);
if (options.bootstrapBucketName) {
args.push('--bootstrap-bucket-name', options.bootstrapBucketName);
}
args.push('--qualifier', options.qualifier ?? this.qualifier);
if (options.cfnExecutionPolicy) {
args.push('--cloudformation-execution-policies', options.cfnExecutionPolicy);
}
if (options.terminationProtection !== undefined) {
args.push('--termination-protection', options.terminationProtection.toString());
}
if (options.force) {
args.push('--force');
}
if (options.tags) {
args.push('--tags', options.tags);
}
if (options.customPermissionsBoundary !== undefined) {
args.push('--custom-permissions-boundary', options.customPermissionsBoundary);
}
else if (options.examplePermissionsBoundary !== undefined) {
args.push('--example-permissions-boundary');
}
if (options.usePreviousParameters === false) {
args.push('--no-previous-parameters');
}
if (options.bootstrapTemplate) {
args.push('--template', options.bootstrapTemplate);
}
if (options.trust != null) {
args.push('--trust', options.trust.join(','));
}
if (options.untrust != null) {
args.push('--untrust', options.untrust.join(','));
}
return this.cdk(args, {
...options.cliOptions,
modEnv: {
...options.cliOptions?.modEnv,
// so that this works for V1,
// where the "old" bootstrap is the default
CDK_NEW_BOOTSTRAP: '1',
},
});
}
async cdkGarbageCollect(options) {
const args = [
'gc',
'--unstable=gc', // TODO: remove when stabilizing
'--confirm=false',
'--created-buffer-days=0', // Otherwise all assets created during integ tests are too young
];
if (options.rollbackBufferDays) {
args.push('--rollback-buffer-days', String(options.rollbackBufferDays));
}
if (options.type) {
args.push('--type', options.type);
}
if (options.bootstrapStackName) {
args.push('--bootstrapStackName', options.bootstrapStackName);
}
return this.cdk(args);
}
async cdkMigrate(language, stackName, inputPath, options) {
return this.cdk([
'migrate',
'--language',
language,
'--stack-name',
stackName,
'--from-path',
inputPath ?? path.join(__dirname, '..', 'resources', 'templates', 'sqs-template.json').toString(),
...(options?.options ?? []),
], options);
}
async cdk(args, options = {}) {
const verbose = options.verbose ?? true;
await this.cli.makeCliAvailable();
return this.shell(['cdk', ...(verbose ? ['-v'] : []), ...args], {
...options,
modEnv: {
...this.cdkShellEnv(),
...options.modEnv,
},
});
}
/**
* Return the environment variables with which to execute CDK
*/
cdkShellEnv() {
// if tests are using an explicit aws identity already (i.e creds)
// force every cdk command to use the same identity.
const awsCreds = this.aws.identityEnv() ?? {};
return {
AWS_REGION: this.aws.region,
AWS_DEFAULT_REGION: this.aws.region,
STACK_NAME_PREFIX: this.stackNamePrefix,
PACKAGE_LAYOUT_VERSION: '2',
// In these tests we want to make a distinction between stdout and sterr
CI: 'false',
...awsCreds,
};
}
template(stackName) {
const fullStackName = this.fullStackName(stackName);
const templatePath = path.join(this.integTestDir, 'cdk.out', `${fullStackName}.template.json`);
return JSON.parse(fs.readFileSync(templatePath, { encoding: 'utf-8' }).toString());
}
async bootstrapRepoName() {
await ensureBootstrapped(this);
const response = await this.aws.cloudFormation.send(new client_cloudformation_1.DescribeStacksCommand({}));
const stack = (response.Stacks ?? [])
.filter((s) => s.StackName && s.StackName == this.bootstrapStackName);
assert(stack.length == 1);
return (0, aws_1.outputFromStack)('ImageRepositoryName', stack[0]) ?? '';
}
get bootstrapStackName() {
return this.fullStackName('bootstrap-stack');
}
fullStackName(stackNames) {
if (typeof stackNames === 'string') {
return `${this.stackNamePrefix}-${stackNames}`;
}
else {
return stackNames.map(s => `${this.stackNamePrefix}-${s}`);
}
}
/**
* Append this to the list of buckets to potentially delete
*
* At the end of a test, we clean up buckets that may not have gotten destroyed
* (for whatever reason).
*/
rememberToDeleteBucket(bucketName) {
this.bucketsToDelete.push(bucketName);
}
/**
* Cleanup leftover stacks and bootstrapped resources
*/
async dispose(success) {
// when using the atmosphere service, it does resource cleanup on our behalf
// so we don't have to wait for it.
if (!(0, with_aws_1.atmosphereEnabled)()) {
const stacksToDelete = await this.deleteableStacks(this.stackNamePrefix);
this.sortBootstrapStacksToTheEnd(stacksToDelete);
// Bootstrap stacks have buckets that need to be cleaned
const bucketNames = stacksToDelete.map(stack => (0, aws_1.outputFromStack)('BucketName', stack)).filter(defined);
// Parallelism will be reasonable
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
await Promise.all(bucketNames.map(b => this.aws.emptyBucket(b)));
// The bootstrap bucket has a removal policy of RETAIN by default, so add it to the buckets to be cleaned up.
this.bucketsToDelete.push(...bucketNames);
// Bootstrap stacks have ECR repositories with images which should be deleted
const imageRepositoryNames = stacksToDelete.map(stack => (0, aws_1.outputFromStack)('ImageRepositoryName', stack)).filter(defined);
// Parallelism will be reasonable
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
await Promise.all(imageRepositoryNames.map(r => this.aws.deleteImageRepository(r)));
await this.aws.deleteStacks(...stacksToDelete.map((s) => {
if (!s.StackName) {
throw new Error('Stack name is required to delete a stack.');
}
return s.StackName;
}));
// We might have leaked some buckets by upgrading the bootstrap stack. Be
// sure to clean everything.
for (const bucket of this.bucketsToDelete) {
await this.aws.deleteBucket(bucket);
}
}
// If the tests completed successfully, happily delete the fixture
// (otherwise leave it for humans to inspect)
if (success) {
const cleaned = (0, shell_1.rimraf)(this.integTestDir);
if (!cleaned) {
console.error(`Failed to clean up ${this.integTestDir} due to permissions issues (Docker running as root?)`);
}
}
}
/**
* Return the stacks starting with our testing prefix that should be deleted
*/
async deleteableStacks(prefix) {
const statusFilter = [
'CREATE_IN_PROGRESS', 'CREATE_FAILED', 'CREATE_COMPLETE',
'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'ROLLBACK_COMPLETE',
'DELETE_FAILED',
'UPDATE_IN_PROGRESS', 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS',
'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_IN_PROGRESS',
'UPDATE_ROLLBACK_FAILED',
'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS',
'UPDATE_ROLLBACK_COMPLETE', 'REVIEW_IN_PROGRESS',
'IMPORT_IN_PROGRESS', 'IMPORT_COMPLETE',
'IMPORT_ROLLBACK_IN_PROGRESS', 'IMPORT_ROLLBACK_FAILED',
'IMPORT_ROLLBACK_COMPLETE',
];
const response = await this.aws.cloudFormation.send(new client_cloudformation_1.DescribeStacksCommand({}));
return (response.Stacks ?? [])
.filter((s) => s.StackName && s.StackName.startsWith(prefix))
.filter((s) => s.StackStatus && statusFilter.includes(s.StackStatus))
.filter((s) => s.RootId === undefined); // Only delete parent stacks. Nested stacks are deleted in the process
}
sortBootstrapStacksToTheEnd(stacks) {
stacks.sort((a, b) => {
if (!a.StackName || !b.StackName) {
throw new Error('Stack names do not exists. These are required for sorting the bootstrap stacks.');
}
const aBs = a.StackName.startsWith(this.bootstrapStackName);
const bBs = b.StackName.startsWith(this.bootstrapStackName);
return aBs != bBs
// '+' converts a boolean to 0 or 1
? (+aBs) - (+bBs)
: a.StackName.localeCompare(b.StackName);
});
}
}
exports.TestFixture = TestFixture;
/**
* Make sure that the given environment is bootstrapped
*
* Since we go striping across regions, it's going to suck doing this
* by hand so let's just mass-automate it.
*/
async function ensureBootstrapped(fixture) {
// Always use the modern bootstrap stack, otherwise we may get the error
// "refusing to downgrade from version 7 to version 0" when bootstrapping with default
// settings using a v1 CLI.
//
// It doesn't matter for tests: when they want to test something about an actual legacy
// bootstrap stack, they'll create a bootstrap stack with a non-default name to test that exact property.
const envSpecifier = `aws://${await fixture.aws.account()}/${fixture.aws.region}`;
if (ALREADY_BOOTSTRAPPED_IN_THIS_RUN.has(envSpecifier)) {
return;
}
if ((0, with_aws_1.atmosphereEnabled)()) {
// when atmosphere is enabled, each test starts with an empty environment
// and needs to deploy the bootstrap stack. in case environments are recylced too quickly,
// cloudformation may think the bootstrap bucket still exists even though it doesnt (because of s3 eventual consistency).
// so we retry on the specific error for a while.
await bootstrapWithRetryOnBucketExists(envSpecifier, fixture);
}
else {
await doBootstrap(envSpecifier, fixture, false);
}
// when using the atmosphere service, every test needs to bootstrap
// its own environment.
if (!(0, with_aws_1.atmosphereEnabled)()) {
ALREADY_BOOTSTRAPPED_IN_THIS_RUN.add(envSpecifier);
}
}
async function doBootstrap(envSpecifier, fixture, allowErrExit) {
return fixture.cdk(['bootstrap', '--bootstrap-kms-key-id', 'AWS_MANAGED_KEY', envSpecifier], {
modEnv: {
// Even for v1, use new bootstrap
CDK_NEW_BOOTSTRAP: '1',
// when allowing error exit, we probably want to inspect
// and compare output, which is better done without color characters.
...(allowErrExit ? { FORCE_COLOR: '0' } : {}),
},
allowErrExit,
});
}
async function bootstrapWithRetryOnBucketExists(envSpecifier, fixture) {
const account = await fixture.aws.account();
const retryAfterSeconds = 30;
const bootstrapBucket = `cdk-hnb659fds-assets-${account}-${fixture.aws.region}`;
// s3 says that a bucket deletion can take up to an hour to be fully visible.
// empirically we see that a few minutes is enough though. lets give 10 to be on the safe(r) side.
const timeoutMinutes = 10;
const timeoutDate = new Date(Date.now() + timeoutMinutes * 60 * 1000);
while (true) {
const out = await doBootstrap(envSpecifier, fixture, true);
if (out.includes(`Environment ${envSpecifier} bootstrapped`)) {
break;
}
if (out.includes(`${bootstrapBucket} already exists`)) {
// might be an s3 eventualy consistency issue due to recycled environments.
if (Date.now() < timeoutDate.getTime()) {
fixture.log(`Bootstrap of ${envSpecifier} failed due to bucket existence check. Retrying in ${retryAfterSeconds} seconds...`);
await (0, aws_1.sleep)(retryAfterSeconds * 1000);
continue;
}
}
throw new Error(`Failed bootstrapping ${envSpecifier}`);
}
}
function defined(x) {
return x !== undefined;
}
/**
* Install the given NPM packages, identified by their names and versions
*
* Works by writing the packages to a `package.json` file, and
* then running NPM7's "install" on it. The use of NPM7 will automatically
* install required peerDependencies.
*
* If we're running in REPO mode and we find the package in the set of local
* packages in the repository, we'll write the directory name to `package.json`
* so that NPM will create a symlink (this allows running tests against
* built-but-unpackaged modules, and saves dev cycle time).
*
* Be aware you MUST install all the packages you directly depend upon! In the case
* of a repo/symlinking install, transitive dependencies WILL NOT be installed in the
* current directory's `node_modules` directory, because they will already have been
* symlinked from the TARGET directory's `node_modules` directory (which is sufficient
* for Node's dependency lookup mechanism).
*/
async function installNpmPackages(fixture, packages) {
if (process.env.REPO_ROOT) {
const monoRepo = await (0, yarn_1.findYarnPackages)(process.env.REPO_ROOT);
// Replace the install target with the physical location of this package
for (const key of Object.keys(packages)) {
if (key in monoRepo) {
packages[key] = monoRepo[key];
}
}
}
fs.writeFileSync(path.join(fixture.integTestDir, 'package.json'), JSON.stringify({
name: 'cdk-integ-tests',
private: true,
version: '0.0.1',
devDependencies: packages,
}, undefined, 2), { encoding: 'utf-8' });
// we often ECONNRESET from NPM so lets retry. this might be because of high concurrency
// which overwhelmes system resources.
const timeoutMinutes = 10;
const timeoutDate = new Date(Date.now() + timeoutMinutes * 60 * 1000);
const retryAfterSeconds = 30;
while (true) {
try {
// Now install that `package.json` using NPM7
await fixture.shell(['node', require.resolve('npm'), 'install']);
break;
}
catch (e) {
if (Date.now() < timeoutDate.getTime() && fixture.output.toString().includes('ECONNRESET')) {
fixture.log(`npm install failed due to ECONNRESET. Retrying in ${retryAfterSeconds} seconds...`);
await (0, aws_1.sleep)(retryAfterSeconds * 1000);
continue;
}
throw e;
}
}
}
const ALREADY_BOOTSTRAPPED_IN_THIS_RUN = new Set();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l0aC1jZGstYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2l0aC1jZGstYXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWdDQSxnREErQ0M7QUFLRCxnQ0FLQztBQUVELDhDQStDQztBQVdELGdEQUVDO0FBRUQsa0RBRUM7QUFFRCxnRUFFQztBQUVELHNEQUVDO0FBbUJELDRDQUVDO0FBZUQsd0NBSUM7QUEwZkQsZ0RBMkJDO0FBZ0VELGdEQXVDQztBQXYwQkQsK0JBQStCO0FBQy9CLGlDQUFpQztBQUNqQyx5QkFBeUI7QUFDekIseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUU3QiwwRUFBdUU7QUFDdkUsa0VBQTBFO0FBRTFFLCtCQUErQztBQUcvQyw2REFBMEQ7QUFDMUQsMkNBQTRDO0FBRTVDLG1DQUFxRDtBQUVyRCx5Q0FBd0Q7QUFDeEQsaURBQTZDO0FBQzdDLGlDQUEwQztBQUU3QixRQUFBLHNCQUFzQixHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFDakMsUUFBQSx1QkFBdUIsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDO0FBRS9DOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixrQkFBa0IsQ0FDaEMsT0FBZSxFQUNmLEtBQThDO0lBRTlDLE9BQU8sS0FBSyxFQUFFLE9BQTJELEVBQUUsRUFBRTtRQUMzRSxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO1FBQ25DLE1BQU0sZUFBZSxHQUFHLFdBQVcsS0FBSyxFQUFFLENBQUM7UUFDM0MsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUUsYUFBYSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBRWxFLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixlQUFlLElBQUksQ0FBQyxDQUFDO1FBQzlELE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixZQUFZLElBQUksQ0FBQyxDQUFD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