@aws-cdk-testing/cli-integ
Version:
Integration tests for the AWS CDK CLI
280 lines • 35.8 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 {
repositoryName;
static DEFAULT_DOMAIN = 'test-cdk';
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() {
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 page.repositories ?? []) {
const tags = await codeArtifact.send(new client_codeartifact_1.ListTagsForResourceCommand({
resourceArn: repo.arn,
}));
const collectable = tags?.tags?.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);
}
npmUpstream = 'npm-upstream';
pypiUpstream = 'pypi-upstream';
nugetUpstream = 'nuget-upstream';
mavenUpstream = 'maven-upstream';
domain = TestRepository.DEFAULT_DOMAIN;
codeArtifact = new client_codeartifact_1.CodeartifactClient();
_loginInformation;
constructor(repositoryName) {
this.repositoryName = repositoryName;
}
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) {
if (await this.repositoryExists(name)) {
return;
}
await this.codeArtifact.send(new client_codeartifact_1.CreateRepositoryCommand({
domain: this.domain,
repository: name,
description: options?.description,
upstreams: options?.upstreams?.map((repositoryName) => ({ repositoryName })),
tags: options?.tags ? Object.entries(options.tags).map(([key, value]) => ({ key, value })) : undefined,
}));
if (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 = {}) {
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 response.packages ?? []) {
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;
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWFydGlmYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29kZWFydGlmYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHNFQWNzQztBQUN0QyxnQ0FBK0I7QUFFL0IsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDO0FBQ3BDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVO0FBRXJELE1BQWEsY0FBYztJQTBFVztJQXpFN0IsTUFBTSxDQUFVLGNBQWMsR0FBRyxVQUFVLENBQUM7SUFFNUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTO1FBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUU7YUFDNUIsUUFBUSxDQUFDLEVBQUUsQ0FBQzthQUNaLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFOUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxjQUFjLENBQUMsUUFBUSxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVNLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQVk7UUFDMUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEMsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDckIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sTUFBTSxDQUFDLFFBQVEsQ0FBQyxjQUFzQjtRQUMzQyxPQUFPLElBQUksY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUNwQixJQUFJLENBQUMsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsWUFB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QyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBcUIsRUFBRSxDQUFDO2dCQUNyQyxNQUFNLENBQUMsQ0FBQztZQUNWLENBQUM7WUFDRCxJQUFJLFFBQVEsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUNyQixNQUFNLENBQUMsQ0FBQztZQUNWLENBQUM7WUFDRCxNQUFNLElBQUEsV0FBSyxFQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDOUMsSUFBSSxJQUFJLENBQUMsQ0FBQztRQUNaLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgTGlzdFBhY2thZ2VzUmVxdWVzdCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb2RlYXJ0aWZhY3QnO1xuaW1wb3J0IHtcbiAgQXNzb2NpYXRlRXh0ZXJuYWxDb25uZWN0aW9uQ29tbWFuZCxcbiAgQ29kZWFydGlmYWN0Q2xpZW50LFxuICBDcmVhdGVEb21haW5Db21tYW5kLFxuICBDcmVhdGVSZXBvc2l0b3J5Q29tbWFuZCxcbiAgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQsXG4gIERlc2NyaWJlRG9tYWluQ29tbWFuZCxcbiAgRGVzY3JpYmVSZXBvc2l0b3J5Q29tbWFuZCxcbiAgR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZCxcbiAgR2V0UmVwb3NpdG9yeUVuZHBvaW50Q29tbWFuZCxcbiAgTGlzdFBhY2thZ2VzQ29tbWFuZCxcbiAgTGlzdFJlcG9zaXRvcmllc0NvbW1hbmQsXG4gIExpc3RUYWdzRm9yUmVzb3VyY2VDb21tYW5kLFxuICBQdXRQYWNrYWdlT3JpZ2luQ29uZmlndXJhdGlvbkNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb2RlYXJ0aWZhY3QnO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tICcuLi9hd3MnO1xuXG5jb25zdCBDT0xMRUNUX0JZX1RBRyA9ICdjb2xsZWN0LWJ5JztcbmNvbnN0IFJFUE9fTElGRVRJTUVfTVMgPSAyNCAqIDM2MDAgKiAxMDAwOyAvLyBPbmUgZGF5XG5cbmV4cG9ydCBjbGFzcyBUZXN0UmVwb3NpdG9yeSB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9ET01BSU4gPSAndGVzdC1jZGsnO1xuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbmV3UmFuZG9tKCkge1xuICAgIGNvbnN0IHF1YWxpZmllciA9IE1hdGgucmFuZG9tKClcbiAgICAgIC50b1N0cmluZygzNilcbiAgICAgIC5yZXBsYWNlKC9bXmEtejAtOV0rL2csICcnKTtcblxuICAgIGNvbnN0IHJlcG8gPSBuZXcgVGVzdFJlcG9zaXRvcnkoYHRlc3QtJHtxdWFsaWZpZXJ9YCk7XG4gICAgYXdhaXQgcmVwby5wcmVwYXJlKCk7XG4gICAgcmV0dXJuIHJlcG87XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGFzeW5jIG5ld1dpdGhOYW1lKG5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IHJlcG8gPSBuZXcgVGVzdFJlcG9zaXRvcnkobmFtZSk7XG4gICAgYXdhaXQgcmVwby5wcmVwYXJlKCk7XG4gICAgcmV0dXJuIHJlcG87XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGV4aXN0aW5nKHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IFRlc3RSZXBvc2l0b3J5KHJlcG9zaXRvcnlOYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHYXJiYWdlIGNvbGxlY3QgcmVwb3NpdG9yaWVzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGdjKCkge1xuICAgIGlmICghKGF3YWl0IFRlc3RSZXBvc2l0b3J5LmV4aXN0aW5nKCcqZHVtbXkqJykuZG9tYWluRXhpc3RzKCkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY29kZUFydGlmYWN0ID0gbmV3IENvZGVhcnRpZmFjdENsaWVudCgpO1xuXG4gICAgbGV0IG5leHRUb2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGRvIHtcbiAgICAgIGNvbnN0IHBhZ2UgPSBhd2FpdCBjb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgbmV3IExpc3RSZXBvc2l0b3JpZXNDb21tYW5kKHtcbiAgICAgICAgICBuZXh0VG9rZW46IG5leHRUb2tlbixcbiAgICAgICAgfSksXG4gICAgICApO1xuXG4gICAgICBmb3IgKGNvbnN0IHJlcG8gb2YgcGFnZS5yZXBvc2l0b3JpZXMgPz8gW10pIHtcbiAgICAgICAgY29uc3QgdGFncyA9IGF3YWl0IGNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBMaXN0VGFnc0ZvclJlc291cmNlQ29tbWFuZCh7XG4gICAgICAgICAgICByZXNvdXJjZUFybjogcmVwby5hcm4hLFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjb2xsZWN0YWJsZSA9IHRhZ3M/LnRhZ3M/LmZpbmQoKHQpID0+IHQua2V5ID09PSBDT0xMRUNUX0JZX1RBRyAmJiBOdW1iZXIodC52YWx1ZSkgPCBEYXRlLm5vdygpKTtcbiAgICAgICAgaWYgKGNvbGxlY3RhYmxlKSB7XG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICBjb25zb2xlLmxvZygnRGVsZXRpbmcnLCByZXBvLm5hbWUpO1xuICAgICAgICAgIGF3YWl0IGNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgICAgbmV3IERlbGV0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgICAgICAgZG9tYWluOiByZXBvLmRvbWFpbk5hbWUhLFxuICAgICAgICAgICAgICByZXBvc2l0b3J5OiByZXBvLm5hbWUhLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBuZXh0VG9rZW4gPSBwYWdlLm5leHRUb2tlbjtcbiAgICB9IHdoaWxlIChuZXh0VG9rZW4pO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IG5wbVVwc3RyZWFtID0gJ25wbS11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBweXBpVXBzdHJlYW0gPSAncHlwaS11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBudWdldFVwc3RyZWFtID0gJ251Z2V0LXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IG1hdmVuVXBzdHJlYW0gPSAnbWF2ZW4tdXBzdHJlYW0nO1xuICBwdWJsaWMgcmVhZG9ubHkgZG9tYWluID0gVGVzdFJlcG9zaXRvcnkuREVGQVVMVF9ET01BSU47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb2RlQXJ0aWZhY3QgPSBuZXcgQ29kZWFydGlmYWN0Q2xpZW50KCk7XG5cbiAgcHJpdmF0ZSBfbG9naW5JbmZvcm1hdGlvbjogTG9naW5JbmZvcm1hdGlvbiB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSByZXBvc2l0b3J5TmFtZTogc3RyaW5nKSB7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcHJlcGFyZSgpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZURvbWFpbigpO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlVXBzdHJlYW1zKCk7XG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5yZXBvc2l0b3J5TmFtZSwge1xuICAgICAgZGVzY3JpcHRpb246ICdUZXN0aW5nIHJlcG9zaXRvcnknLFxuICAgICAgdXBzdHJlYW1zOiBbdGhpcy5ucG1VcHN0cmVhbSwgdGhpcy5weXBpVXBzdHJlYW0sIHRoaXMubnVnZXRVcHN0cmVhbSwgdGhpcy5tYXZlblVwc3RyZWFtXSxcbiAgICAgIHRhZ3M6IHtcbiAgICAgICAgW0NPTExFQ1RfQllfVEFHXTogYCR7RGF0ZS5ub3coKSArIFJFUE9fTElGRVRJTUVfTVN9YCxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgbG9naW5JbmZvcm1hdGlvbigpOiBQcm9taXNlPExvZ2luSW5mb3JtYXRpb24+IHtcbiAgICBpZiAodGhpcy5fbG9naW5JbmZvcm1hdGlvbikge1xuICAgICAgcmV0dXJuIHRoaXMuX2xvZ2luSW5mb3JtYXRpb247XG4gICAgfVxuXG4gICAgdGhpcy5fbG9naW5JbmZvcm1hdGlvbiA9IHtcbiAgICAgIGF1dGhUb2tlbjogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICBkdXJhdGlvblNlY29uZHM6IDEyICogMzYwMCxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5hdXRob3JpemF0aW9uVG9rZW4hLFxuICAgICAgcmVwb3NpdG9yeU5hbWU6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG5cbiAgICAgIG5wbUVuZHBvaW50OiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICBmb3JtYXQ6ICducG0nLFxuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICApLnJlcG9zaXRvcnlFbmRwb2ludCEsXG5cbiAgICAgIG1hdmVuRW5kcG9pbnQ6IChcbiAgICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgR2V0UmVwb3NpdG9yeUVuZHBvaW50Q29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcbiAgICAgICAgICAgIGZvcm1hdDogJ21hdmVuJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5yZXBvc2l0b3J5RW5kcG9pbnQhLFxuXG4gICAgICBudWdldEVuZHBvaW50OiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICBmb3JtYXQ6ICdudWdldCcsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkucmVwb3NpdG9yeUVuZHBvaW50ISxcblxuICAgICAgcHlwaUVuZHBvaW50OiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICBmb3JtYXQ6ICdweXBpJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5yZXBvc2l0b3J5RW5kcG9pbnQhLFxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuX2xvZ2luSW5mb3JtYXRpb247XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVsZXRlKCkge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICBuZXcgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQoe1xuICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcbiAgICAgICAgfSksXG4gICAgICApO1xuXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5sb2coJ0RlbGV0ZWQnLCB0aGlzLnJlcG9zaXRvcnlOYW1lKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChlLm5hbWUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgICAgLy8gT2theVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBwYWNrYWdlcyBhbmQgbWFyayB0aGVtIGFzIFwiYWxsb3cgdXBzdHJlYW0gdmVyc2lvbnNcIi5cbiAgICpcbiAgICogSWYgd2UgZG9uJ3QgZG8gdGhpcyBhbmQgd2UgcHVibGlzaCBgZm9vQDIuMy40LXJjLjBgLCB0aGVuIHdlIGNhbid0XG4gICAqIGRvd25sb2FkIGBmb29AMi4zLjBgIGFueW1vcmUgYmVjYXVzZSBieSBkZWZhdWx0IENvZGVBcnRpZmFjdCB3aWxsXG4gICAqIGJsb2NrIGRpZmZlcmVudCB2ZXJzaW9ucyBmcm9tIHRoZSBzYW1lIHBhY2thZ2UuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbWFya0FsbFVwc3RyZWFtQWxsb3coKSB7XG4gICAgZm9yIGF3YWl0IChjb25zdCBwa2cgb2YgdGhpcy5saXN0UGFja2FnZXMoeyB1cHN0cmVhbTogJ0JMT0NLJyB9KSkge1xuICAgICAgYXdhaXQgcmV0cnlUaHJvdHRsZWQoKCkgPT5cbiAgICAgICAgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgUHV0UGFja2FnZU9yaWdpbkNvbmZpZ3VyYXRpb25Db21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuXG4gICAgICAgICAgICBmb3JtYXQ6IHBrZy5mb3JtYXQhLFxuICAgICAgICAgICAgcGFja2FnZTogcGtnLnBhY2thZ2UhLFxuICAgICAgICAgICAgbmFtZXNwYWNlOiBwa2cubmFtZXNwYWNlISxcbiAgICAgICAgICAgIHJlc3RyaWN0aW9uczoge1xuICAgICAgICAgICAgICBwdWJsaXNoOiAnQUxMT1cnLFxuICAgICAgICAgICAgICB1cHN0cmVhbTogJ0FMTE9XJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlRG9tYWluKCkge1xuICAgIGlmIChhd2FpdCB0aGlzLmRvbWFpbkV4aXN0cygpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICBuZXcgQ3JlYXRlRG9tYWluQ29tbWFuZCh7XG4gICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgIHRhZ3M6IFt7IGtleTogJ3Rlc3RpbmcnLCB2YWx1ZTogJ3RydWUnIH1dLFxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlVXBzdHJlYW1zKCkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm5wbVVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBOUE0nLFxuICAgICAgZXh0ZXJuYWw6ICdwdWJsaWM6bnBtanMnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm1hdmVuVXBzdHJlYW0sIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHVwc3RyZWFtIHJlcG9zaXRvcnkgZm9yIE1hdmVuJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm1hdmVuLWNlbnRyYWwnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLm51Z2V0VXBzdHJlYW0sIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHVwc3RyZWFtIHJlcG9zaXRvcnkgZm9yIE51R2V0JyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm51Z2V0LW9yZycsXG4gICAgfSk7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZXBvc2l0b3J5KHRoaXMucHlwaVVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBQeVBJJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOnB5cGknLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVSZXBvc2l0b3J5KFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gICAgICByZWFkb25seSBleHRlcm5hbD86IHN0cmluZztcbiAgICAgIHJlYWRvbmx5IHVwc3RyZWFtcz86IHN0cmluZ1tdO1xuICAgICAgcmVhZG9ubHkgdGFncz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgfSxcbiAgKSB7XG4gICAgaWYgKGF3YWl0IHRoaXMucmVwb3NpdG9yeUV4aXN0cyhuYW1lKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICBuZXcgQ3JlYXRlUmVwb3NpdG9yeUNvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICByZXBvc2l0b3J5OiBuYW1lLFxuICAgICAgICBkZXNjcmlwdGlvbjogb3B0aW9ucz8uZGVzY3JpcHRpb24sXG4gICAgICAgIHVwc3RyZWFtczogb3B0aW9ucz8udXBzdHJlYW1zPy5tYXAoKHJlcG9zaXRvcnlOYW1lKSA9PiAoeyByZXBvc2l0b3J5TmFtZSB9KSksXG4gICAgICAgIHRhZ3M6IG9wdGlvbnM/LnRhZ3MgPyBPYmplY3QuZW50cmllcyhvcHRpb25zLnRhZ3MpLm1hcCgoW2tleSwgdmFsdWVdKSA9PiAoeyBrZXksIHZhbHVlIH0pKSA6IHVuZGVmaW5lZCxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBpZiAob3B0aW9ucz8uZXh0ZXJuYWwpIHtcbiAgICAgIGNvbnN0IGV4dGVybmFsQ29ubmVjdGlvbiA9IG9wdGlvbnMuZXh0ZXJuYWw7XG4gICAgICBhd2FpdCByZXRyeSgoKSA9PlxuICAgICAgICB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBBc3NvY2lhdGVFeHRlcm5hbENvbm5lY3Rpb25Db21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiBuYW1lLFxuICAgICAgICAgICAgZXh0ZXJuYWxDb25uZWN0aW9uLFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRvbWFpbkV4aXN0cygpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChuZXcgRGVzY3JpYmVEb21haW5Db21tYW5kKHsgZG9tYWluOiB0aGlzLmRvbWFpbiB9KSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChlLm5hbWUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVwb3NpdG9yeUV4aXN0cyhuYW1lOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChuZXcgRGVzY3JpYmVSZXBvc2l0b3J5Q29tbWFuZCh7IGRvbWFpbjogdGhpcy5kb21haW4sIHJlcG9zaXRvcnk6IG5hbWUgfSkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jICpsaXN0UGFja2FnZXMoZmlsdGVyOiBQaWNrPExpc3RQYWNrYWdlc1JlcXVlc3QsICd1cHN0cmVhbScgfCAncHVibGlzaCcgfCAnZm9ybWF0Jz4gPSB7fSkge1xuICAgIGxldCByZXNwb25zZSA9IGF3YWl0IHJldHJ5VGhyb3R0bGVkKCgpID0+XG4gICAgICB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICBuZXcgTGlzdFBhY2thZ2VzQ29tbWFuZCh7XG4gICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgIC4uLmZpbHRlcixcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICk7XG5cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgZm9yIChjb25zdCBwIG9mIHJlc3BvbnNlLnBhY2thZ2VzID8/IFtdKSB7XG4gICAgICAgIHlpZWxkIHA7XG4gICAgICB9XG5cbiAgICAgIGlmICghcmVzcG9uc2UubmV4dFRva2VuKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZXNwb25zZSA9IGF3YWl0IHJldHJ5VGhyb3R0bGVkKCgpID0+XG4gICAgICAgIHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IExpc3RQYWNrYWdlc0NvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICAuLi5maWx0ZXIsXG4gICAgICAgICAgICBuZXh0VG9rZW46IHJlc3BvbnNlLm5leHRUb2tlbixcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJldHJ5PEE+KGJsb2NrOiAoKSA9PiBQcm9taXNlPEE+KSB7XG4gIGxldCBhdHRlbXB0cyA9IDM7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBibG9jaygpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGF0dGVtcHRzLS0gPT09IDApIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmRlYnVnKGUubWVzc2FnZSk7XG4gICAgICBhd2FpdCBzbGVlcCg1MDApO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXRyeVRocm90dGxlZDxBPihibG9jazogKCkgPT4gUHJvbWlzZTxBPikge1xuICBsZXQgdGltZSA9IDEwMDtcbiAgbGV0IGF0dGVtcHRzID0gMTU7XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBibG9jaygpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUuZGVidWcoZS5tZXNzYWdlKTtcbiAgICAgIGlmIChlLm5hbWUgIT09ICdUaHJvdHRsaW5nRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgICAgaWYgKGF0dGVtcHRzLS0gPT09IDApIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHRpbWUpKTtcbiAgICAgIHRpbWUgKj0gMjtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBMb2dpbkluZm9ybWF0aW9uIHtcbiAgcmVhZG9ubHkgYXV0aFRva2VuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5wbUVuZHBvaW50OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1hdmVuRW5kcG9pbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgbnVnZXRFbmRwb2ludDogc3RyaW5nO1xuICByZWFkb25seSBweXBpRW5kcG9pbnQ6IHN0cmluZztcbn1cbiJdfQ==