@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
281 lines • 36.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestRepository = void 0;
const client_codeartifact_1 = require("@aws-sdk/client-codeartifact");
const aws_1 = require("../aws");
const COLLECT_BY_TAG = 'collect-by';
const REPO_LIFETIME_MS = 24 * 3600 * 1000; // One day
class TestRepository {
static async newRandom() {
const qualifier = Math.random()
.toString(36)
.replace(/[^a-z0-9]+/g, '');
const repo = new TestRepository(`test-${qualifier}`);
await repo.prepare();
return repo;
}
static async newWithName(name) {
const repo = new TestRepository(name);
await repo.prepare();
return repo;
}
static existing(repositoryName) {
return new TestRepository(repositoryName);
}
/**
* Garbage collect repositories
*/
static async gc() {
var _a, _b;
if (!(await TestRepository.existing('*dummy*').domainExists())) {
return;
}
const codeArtifact = new client_codeartifact_1.CodeartifactClient();
let nextToken;
do {
const page = await codeArtifact.send(new client_codeartifact_1.ListRepositoriesCommand({
nextToken: nextToken,
}));
for (const repo of (_a = page.repositories) !== null && _a !== void 0 ? _a : []) {
const tags = await codeArtifact.send(new client_codeartifact_1.ListTagsForResourceCommand({
resourceArn: repo.arn,
}));
const collectable = (_b = tags === null || tags === void 0 ? void 0 : tags.tags) === null || _b === void 0 ? void 0 : _b.find((t) => t.key === COLLECT_BY_TAG && Number(t.value) < Date.now());
if (collectable) {
// eslint-disable-next-line no-console
console.log('Deleting', repo.name);
await codeArtifact.send(new client_codeartifact_1.DeleteRepositoryCommand({
domain: repo.domainName,
repository: repo.name,
}));
}
}
nextToken = page.nextToken;
} while (nextToken);
}
constructor(repositoryName) {
this.repositoryName = repositoryName;
this.npmUpstream = 'npm-upstream';
this.pypiUpstream = 'pypi-upstream';
this.nugetUpstream = 'nuget-upstream';
this.mavenUpstream = 'maven-upstream';
this.domain = TestRepository.DEFAULT_DOMAIN;
this.codeArtifact = new client_codeartifact_1.CodeartifactClient();
}
async prepare() {
await this.ensureDomain();
await this.ensureUpstreams();
await this.ensureRepository(this.repositoryName, {
description: 'Testing repository',
upstreams: [this.npmUpstream, this.pypiUpstream, this.nugetUpstream, this.mavenUpstream],
tags: {
[COLLECT_BY_TAG]: `${Date.now() + REPO_LIFETIME_MS}`,
},
});
}
async loginInformation() {
if (this._loginInformation) {
return this._loginInformation;
}
this._loginInformation = {
authToken: (await this.codeArtifact.send(new client_codeartifact_1.GetAuthorizationTokenCommand({
domain: this.domain,
durationSeconds: 12 * 3600,
}))).authorizationToken,
repositoryName: this.repositoryName,
npmEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
domain: this.domain,
repository: this.repositoryName,
format: 'npm',
}))).repositoryEndpoint,
mavenEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
domain: this.domain,
repository: this.repositoryName,
format: 'maven',
}))).repositoryEndpoint,
nugetEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
domain: this.domain,
repository: this.repositoryName,
format: 'nuget',
}))).repositoryEndpoint,
pypiEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
domain: this.domain,
repository: this.repositoryName,
format: 'pypi',
}))).repositoryEndpoint,
};
return this._loginInformation;
}
async delete() {
try {
await this.codeArtifact.send(new client_codeartifact_1.DeleteRepositoryCommand({
domain: this.domain,
repository: this.repositoryName,
}));
// eslint-disable-next-line no-console
console.log('Deleted', this.repositoryName);
}
catch (e) {
if (e.name !== 'ResourceNotFoundException') {
throw e;
}
// Okay
}
}
/**
* List all packages and mark them as "allow upstream versions".
*
* If we don't do this and we publish `foo@2.3.4-rc.0`, then we can't
* download `foo@2.3.0` anymore because by default CodeArtifact will
* block different versions from the same package.
*/
async markAllUpstreamAllow() {
for await (const pkg of this.listPackages({ upstream: 'BLOCK' })) {
await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.PutPackageOriginConfigurationCommand({
domain: this.domain,
repository: this.repositoryName,
format: pkg.format,
package: pkg.package,
namespace: pkg.namespace,
restrictions: {
publish: 'ALLOW',
upstream: 'ALLOW',
},
})));
}
}
async ensureDomain() {
if (await this.domainExists()) {
return;
}
await this.codeArtifact.send(new client_codeartifact_1.CreateDomainCommand({
domain: this.domain,
tags: [{ key: 'testing', value: 'true' }],
}));
}
async ensureUpstreams() {
await this.ensureRepository(this.npmUpstream, {
description: 'The upstream repository for NPM',
external: 'public:npmjs',
});
await this.ensureRepository(this.mavenUpstream, {
description: 'The upstream repository for Maven',
external: 'public:maven-central',
});
await this.ensureRepository(this.nugetUpstream, {
description: 'The upstream repository for NuGet',
external: 'public:nuget-org',
});
await this.ensureRepository(this.pypiUpstream, {
description: 'The upstream repository for PyPI',
external: 'public:pypi',
});
}
async ensureRepository(name, options) {
var _a;
if (await this.repositoryExists(name)) {
return;
}
await this.codeArtifact.send(new client_codeartifact_1.CreateRepositoryCommand({
domain: this.domain,
repository: name,
description: options === null || options === void 0 ? void 0 : options.description,
upstreams: (_a = options === null || options === void 0 ? void 0 : options.upstreams) === null || _a === void 0 ? void 0 : _a.map((repositoryName) => ({ repositoryName })),
tags: (options === null || options === void 0 ? void 0 : options.tags) ? Object.entries(options.tags).map(([key, value]) => ({ key, value })) : undefined,
}));
if (options === null || options === void 0 ? void 0 : options.external) {
const externalConnection = options.external;
await retry(() => this.codeArtifact.send(new client_codeartifact_1.AssociateExternalConnectionCommand({
domain: this.domain,
repository: name,
externalConnection,
})));
}
}
async domainExists() {
try {
await this.codeArtifact.send(new client_codeartifact_1.DescribeDomainCommand({ domain: this.domain }));
return true;
}
catch (e) {
if (e.name !== 'ResourceNotFoundException') {
throw e;
}
return false;
}
}
async repositoryExists(name) {
try {
await this.codeArtifact.send(new client_codeartifact_1.DescribeRepositoryCommand({ domain: this.domain, repository: name }));
return true;
}
catch (e) {
if (e.name !== 'ResourceNotFoundException') {
throw e;
}
return false;
}
}
async *listPackages(filter = {}) {
var _a;
let response = await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.ListPackagesCommand({
domain: this.domain,
repository: this.repositoryName,
...filter,
})));
while (true) {
for (const p of (_a = response.packages) !== null && _a !== void 0 ? _a : []) {
yield p;
}
if (!response.nextToken) {
break;
}
response = await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.ListPackagesCommand({
domain: this.domain,
repository: this.repositoryName,
...filter,
nextToken: response.nextToken,
})));
}
}
}
exports.TestRepository = TestRepository;
TestRepository.DEFAULT_DOMAIN = 'test-cdk';
async function retry(block) {
let attempts = 3;
while (true) {
try {
return await block();
}
catch (e) {
if (attempts-- === 0) {
throw e;
}
// eslint-disable-next-line no-console
console.debug(e.message);
await (0, aws_1.sleep)(500);
}
}
}
async function retryThrottled(block) {
let time = 100;
let attempts = 15;
while (true) {
try {
return await block();
}
catch (e) {
// eslint-disable-next-line no-console
console.debug(e.message);
if (e.name !== 'ThrottlingException') {
throw e;
}
if (attempts-- === 0) {
throw e;
}
await (0, aws_1.sleep)(Math.floor(Math.random() * time));
time *= 2;
}
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWFydGlmYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29kZWFydGlmYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNFQWVzQztBQUN0QyxnQ0FBK0I7QUFFL0IsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDO0FBQ3BDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVO0FBRXJELE1BQWEsY0FBYztJQUdsQixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVM7UUFDM0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRTthQUM1QixRQUFRLENBQUMsRUFBRSxDQUFDO2FBQ1osT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU5QixNQUFNLElBQUksR0FBRyxJQUFJLGNBQWMsQ0FBQyxRQUFRLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDckQsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDckIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBWTtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTSxNQUFNLENBQUMsUUFBUSxDQUFDLGNBQXNCO1FBQzNDLE9BQU8sSUFBSSxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFOztRQUNwQixJQUFJLENBQUMsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQy9ELE9BQU87UUFDVCxDQUFD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SSxDQUFDO1lBQ0gsT0FBTyxNQUFNLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLHNDQUFzQztZQUN0QyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6QixJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQXFCLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxDQUFDLENBQUM7WUFDVixDQUFDO1lBQ0QsSUFBSSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxDQUFDLENBQUM7WUFDVixDQUFDO1lBQ0QsTUFBTSxJQUFBLFdBQUssRUFBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzlDLElBQUksSUFBSSxDQUFDLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBc3NvY2lhdGVFeHRlcm5hbENvbm5lY3Rpb25Db21tYW5kLFxuICBDb2RlYXJ0aWZhY3RDbGllbnQsXG4gIENyZWF0ZURvbWFpbkNvbW1hbmQsXG4gIENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kLFxuICBEZWxldGVSZXBvc2l0b3J5Q29tbWFuZCxcbiAgRGVzY3JpYmVEb21haW5Db21tYW5kLFxuICBEZXNjcmliZVJlcG9zaXRvcnlDb21tYW5kLFxuICBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kLFxuICBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kLFxuICBMaXN0UGFja2FnZXNDb21tYW5kLFxuICBMaXN0UGFja2FnZXNSZXF1ZXN0LFxuICBMaXN0UmVwb3NpdG9yaWVzQ29tbWFuZCxcbiAgTGlzdFRhZ3NGb3JSZXNvdXJjZUNvbW1hbmQsXG4gIFB1dFBhY2thZ2VPcmlnaW5Db25maWd1cmF0aW9uQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNvZGVhcnRpZmFjdCc7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJy4uL2F3cyc7XG5cbmNvbnN0IENPTExFQ1RfQllfVEFHID0gJ2NvbGxlY3QtYnknO1xuY29uc3QgUkVQT19MSUZFVElNRV9NUyA9IDI0ICogMzYwMCAqIDEwMDA7IC8vIE9uZSBkYXlcblxuZXhwb3J0IGNsYXNzIFRlc3RSZXBvc2l0b3J5IHtcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0RPTUFJTiA9ICd0ZXN0LWNkayc7XG5cbiAgcHVibGljIHN0YXRpYyBhc3luYyBuZXdSYW5kb20oKSB7XG4gICAgY29uc3QgcXVhbGlmaWVyID0gTWF0aC5yYW5kb20oKVxuICAgICAgLnRvU3RyaW5nKDM2KVxuICAgICAgLnJlcGxhY2UoL1teYS16MC05XSsvZywgJycpO1xuXG4gICAgY29uc3QgcmVwbyA9IG5ldyBUZXN0UmVwb3NpdG9yeShgdGVzdC0ke3F1YWxpZmllcn1gKTtcbiAgICBhd2FpdCByZXBvLnByZXBhcmUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbmV3V2l0aE5hbWUobmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcmVwbyA9IG5ldyBUZXN0UmVwb3NpdG9yeShuYW1lKTtcbiAgICBhd2FpdCByZXBvLnByZXBhcmUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZXhpc3RpbmcocmVwb3NpdG9yeU5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgVGVzdFJlcG9zaXRvcnkocmVwb3NpdG9yeU5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdhcmJhZ2UgY29sbGVjdCByZXBvc2l0b3JpZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZ2MoKSB7XG4gICAgaWYgKCEoYXdhaXQgVGVzdFJlcG9zaXRvcnkuZXhpc3RpbmcoJypkdW1teSonKS5kb21haW5FeGlzdHMoKSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlQXJ0aWZhY3QgPSBuZXcgQ29kZWFydGlmYWN0Q2xpZW50KCk7XG5cbiAgICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgZG8ge1xuICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICBuZXcgTGlzdFJlcG9zaXRvcmllc0NvbW1hbmQoe1xuICAgICAgICAgIG5leHRUb2tlbjogbmV4dFRva2VuLFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgcmVwbyBvZiBwYWdlLnJlcG9zaXRvcmllcyA/PyBbXSkge1xuICAgICAgICBjb25zdCB0YWdzID0gYXdhaXQgY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IExpc3RUYWdzRm9yUmVzb3VyY2VDb21tYW5kKHtcbiAgICAgICAgICAgIHJlc291cmNlQXJuOiByZXBvLmFybiEsXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGNvbGxlY3RhYmxlID0gdGFncz8udGFncz8uZmluZCgodCkgPT4gdC5rZXkgPT09IENPTExFQ1RfQllfVEFHICYmIE51bWJlcih0LnZhbHVlKSA8IERhdGUubm93KCkpO1xuICAgICAgICBpZiAoY29sbGVjdGFibGUpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgIGNvbnNvbGUubG9nKCdEZWxldGluZycsIHJlcG8ubmFtZSk7XG4gICAgICAgICAgYXdhaXQgY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgICBuZXcgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQoe1xuICAgICAgICAgICAgICBkb21haW46IHJlcG8uZG9tYWluTmFtZSEsXG4gICAgICAgICAgICAgIHJlcG9zaXRvcnk6IHJlcG8ubmFtZSEsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG5leHRUb2tlbiA9IHBhZ2UubmV4dFRva2VuO1xuICAgIH0gd2hpbGUgKG5leHRUb2tlbik7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgbnBtVXBzdHJlYW0gPSAnbnBtLXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IHB5cGlVcHN0cmVhbSA9ICdweXBpLXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IG51Z2V0VXBzdHJlYW0gPSAnbnVnZXQtdXBzdHJlYW0nO1xuICBwdWJsaWMgcmVhZG9ubHkgbWF2ZW5VcHN0cmVhbSA9ICdtYXZlbi11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBkb21haW4gPSBUZXN0UmVwb3NpdG9yeS5ERUZBVUxUX0RPTUFJTjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvZGVBcnRpZmFjdCA9IG5ldyBDb2RlYXJ0aWZhY3RDbGllbnQoKTtcblxuICBwcml2YXRlIF9sb2dpbkluZm9ybWF0aW9uOiBMb2dpbkluZm9ybWF0aW9uIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpIHt9XG5cbiAgcHVibGljIGFzeW5jIHByZXBhcmUoKSB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVEb21haW4oKTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVVwc3RyZWFtcygpO1xuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZXBvc2l0b3J5KHRoaXMucmVwb3NpdG9yeU5hbWUsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGVzdGluZyByZXBvc2l0b3J5JyxcbiAgICAgIHVwc3RyZWFtczogW3RoaXMubnBtVXBzdHJlYW0sIHRoaXMucHlwaVVwc3RyZWFtLCB0aGlzLm51Z2V0VXBzdHJlYW0sIHRoaXMubWF2ZW5VcHN0cmVhbV0sXG4gICAgICB0YWdzOiB7XG4gICAgICAgIFtDT0xMRUNUX0JZX1RBR106IGAke0RhdGUubm93KCkgKyBSRVBPX0xJRkVUSU1FX01TfWAsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGxvZ2luSW5mb3JtYXRpb24oKTogUHJvbWlzZTxMb2dpbkluZm9ybWF0aW9uPiB7XG4gICAgaWYgKHRoaXMuX2xvZ2luSW5mb3JtYXRpb24pIHtcbiAgICAgIHJldHVybiB0aGlzLl9sb2dpbkluZm9ybWF0aW9uO1xuICAgIH1cblxuICAgIHRoaXMuX2xvZ2luSW5mb3JtYXRpb24gPSB7XG4gICAgICBhdXRoVG9rZW46IChcbiAgICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgZHVyYXRpb25TZWNvbmRzOiAxMiAqIDM2MDAsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkuYXV0aG9yaXphdGlvblRva2VuISxcbiAgICAgIHJlcG9zaXRvcnlOYW1lOiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuXG4gICAgICBucG1FbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAnbnBtJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5yZXBvc2l0b3J5RW5kcG9pbnQhLFxuXG4gICAgICBtYXZlbkVuZHBvaW50OiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICBmb3JtYXQ6ICdtYXZlbicsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkucmVwb3NpdG9yeUVuZHBvaW50ISxcblxuICAgICAgbnVnZXRFbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAnbnVnZXQnLFxuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICApLnJlcG9zaXRvcnlFbmRwb2ludCEsXG5cbiAgICAgIHB5cGlFbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAncHlwaScsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkucmVwb3NpdG9yeUVuZHBvaW50ISxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9sb2dpbkluZm9ybWF0aW9uO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGRlbGV0ZSgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgbmV3IERlbGV0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUubG9nKCdEZWxldGVkJywgdGhpcy5yZXBvc2l0b3J5TmFtZSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIC8vIE9rYXlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGlzdCBhbGwgcGFja2FnZXMgYW5kIG1hcmsgdGhlbSBhcyBcImFsbG93IHVwc3RyZWFtIHZlcnNpb25zXCIuXG4gICAqXG4gICAqIElmIHdlIGRvbid0IGRvIHRoaXMgYW5kIHdlIHB1Ymxpc2ggYGZvb0AyLjMuNC1yYy4wYCwgdGhlbiB3ZSBjYW4ndFxuICAgKiBkb3dubG9hZCBgZm9vQDIuMy4wYCBhbnltb3JlIGJlY2F1c2UgYnkgZGVmYXVsdCBDb2RlQXJ0aWZhY3Qgd2lsbFxuICAgKiBibG9jayBkaWZmZXJlbnQgdmVyc2lvbnMgZnJvbSB0aGUgc2FtZSBwYWNrYWdlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIG1hcmtBbGxVcHN0cmVhbUFsbG93KCkge1xuICAgIGZvciBhd2FpdCAoY29uc3QgcGtnIG9mIHRoaXMubGlzdFBhY2thZ2VzKHsgdXBzdHJlYW06ICdCTE9DSycgfSkpIHtcbiAgICAgIGF3YWl0IHJldHJ5VGhyb3R0bGVkKCgpID0+XG4gICAgICAgIHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IFB1dFBhY2thZ2VPcmlnaW5Db25maWd1cmF0aW9uQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcblxuICAgICAgICAgICAgZm9ybWF0OiBwa2cuZm9ybWF0ISxcbiAgICAgICAgICAgIHBhY2thZ2U6IHBrZy5wYWNrYWdlISxcbiAgICAgICAgICAgIG5hbWVzcGFjZTogcGtnLm5hbWVzcGFjZSEsXG4gICAgICAgICAgICByZXN0cmljdGlvbnM6IHtcbiAgICAgICAgICAgICAgcHVibGlzaDogJ0FMTE9XJyxcbiAgICAgICAgICAgICAgdXBzdHJlYW06ICdBTExPVycsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZURvbWFpbigpIHtcbiAgICBpZiAoYXdhaXQgdGhpcy5kb21haW5FeGlzdHMoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgbmV3IENyZWF0ZURvbWFpbkNvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICB0YWdzOiBbeyBrZXk6ICd0ZXN0aW5nJywgdmFsdWU6ICd0cnVlJyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZVVwc3RyZWFtcygpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5ucG1VcHN0cmVhbSwge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgdXBzdHJlYW0gcmVwb3NpdG9yeSBmb3IgTlBNJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm5wbWpzJyxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5tYXZlblVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBNYXZlbicsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzptYXZlbi1jZW50cmFsJyxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5udWdldFVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBOdUdldCcsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzpudWdldC1vcmcnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLnB5cGlVcHN0cmVhbSwge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgdXBzdHJlYW0gcmVwb3NpdG9yeSBmb3IgUHlQSScsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzpweXBpJyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlUmVwb3NpdG9yeShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAgICAgcmVhZG9ubHkgZXh0ZXJuYWw/OiBzdHJpbmc7XG4gICAgICByZWFkb25seSB1cHN0cmVhbXM/OiBzdHJpbmdbXTtcbiAgICAgIHJlYWRvbmx5IHRhZ3M/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgIH0sXG4gICkge1xuICAgIGlmIChhd2FpdCB0aGlzLnJlcG9zaXRvcnlFeGlzdHMobmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgbmV3IENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgcmVwb3NpdG9yeTogbmFtZSxcbiAgICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnM/LmRlc2NyaXB0aW9uLFxuICAgICAgICB1cHN0cmVhbXM6IG9wdGlvbnM/LnVwc3RyZWFtcz8ubWFwKChyZXBvc2l0b3J5TmFtZSkgPT4gKHsgcmVwb3NpdG9yeU5hbWUgfSkpLFxuICAgICAgICB0YWdzOiBvcHRpb25zPy50YWdzID8gT2JqZWN0LmVudHJpZXMob3B0aW9ucy50YWdzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gKHsga2V5LCB2YWx1ZSB9KSkgOiB1bmRlZmluZWQsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKG9wdGlvbnM/LmV4dGVybmFsKSB7XG4gICAgICBjb25zdCBleHRlcm5hbENvbm5lY3Rpb24gPSBvcHRpb25zLmV4dGVybmFsO1xuICAgICAgYXdhaXQgcmV0cnkoKCkgPT5cbiAgICAgICAgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgQXNzb2NpYXRlRXh0ZXJuYWxDb25uZWN0aW9uQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgcmVwb3NpdG9yeTogbmFtZSxcbiAgICAgICAgICAgIGV4dGVybmFsQ29ubmVjdGlvbixcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkb21haW5FeGlzdHMoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQobmV3IERlc2NyaWJlRG9tYWluQ29tbWFuZCh7IGRvbWFpbjogdGhpcy5kb21haW4gfSkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlcG9zaXRvcnlFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQobmV3IERlc2NyaWJlUmVwb3NpdG9yeUNvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluLCByZXBvc2l0b3J5OiBuYW1lIH0pKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGUubmFtZSAhPT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyAqbGlzdFBhY2thZ2VzKGZpbHRlcjogUGljazxMaXN0UGFja2FnZXNSZXF1ZXN0LCAndXBzdHJlYW0nIHwgJ3B1Ymxpc2gnIHwgJ2Zvcm1hdCc+ID0ge30pIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PlxuICAgICAgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgbmV3IExpc3RQYWNrYWdlc0NvbW1hbmQoe1xuICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcbiAgICAgICAgICAuLi5maWx0ZXIsXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGZvciAoY29uc3QgcCBvZiByZXNwb25zZS5wYWNrYWdlcyA/PyBbXSkge1xuICAgICAgICB5aWVsZCBwO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXJlc3BvbnNlLm5leHRUb2tlbikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgcmVzcG9uc2UgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PlxuICAgICAgICB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBMaXN0UGFja2FnZXNDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgLi4uZmlsdGVyLFxuICAgICAgICAgICAgbmV4dFRva2VuOiByZXNwb25zZS5uZXh0VG9rZW4sXG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXRyeTxBPihibG9jazogKCkgPT4gUHJvbWlzZTxBPikge1xuICBsZXQgYXR0ZW1wdHMgPSAzO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgYmxvY2soKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChhdHRlbXB0cy0tID09PSAwKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5kZWJ1ZyhlLm1lc3NhZ2UpO1xuICAgICAgYXdhaXQgc2xlZXAoNTAwKTtcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmV0cnlUaHJvdHRsZWQ8QT4oYmxvY2s6ICgpID0+IFByb21pc2U8QT4pIHtcbiAgbGV0IHRpbWUgPSAxMDA7XG4gIGxldCBhdHRlbXB0cyA9IDE1O1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgYmxvY2soKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmRlYnVnKGUubWVzc2FnZSk7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnVGhyb3R0bGluZ0V4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmIChhdHRlbXB0cy0tID09PSAwKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICBhd2FpdCBzbGVlcChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB0aW1lKSk7XG4gICAgICB0aW1lICo9IDI7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9naW5JbmZvcm1hdGlvbiB7XG4gIHJlYWRvbmx5IGF1dGhUb2tlbjogc3RyaW5nO1xuICByZWFkb25seSByZXBvc2l0b3J5TmFtZTogc3RyaW5nO1xuICByZWFkb25seSBucG1FbmRwb2ludDogc3RyaW5nO1xuICByZWFkb25seSBtYXZlbkVuZHBvaW50OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG51Z2V0RW5kcG9pbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcHlwaUVuZHBvaW50OiBzdHJpbmc7XG59XG4iXX0=