projen
Version:
CDK for software projects
386 lines • 45.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CiConfiguration = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const path = __importStar(require("path"));
const case_1 = require("case");
const component_1 = require("../component");
const yaml_1 = require("../yaml");
/**
* CI for GitLab.
* A CI is a configurable automated process made up of one or more stages/jobs.
* @see https://docs.gitlab.com/ee/ci/yaml/
*/
class CiConfiguration extends component_1.Component {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.gitlab.CiConfiguration", version: "0.103.12" };
/**
* The name of the configuration.
*/
name;
/**
* Path to CI file generated by the configuration.
*/
path;
/**
* The workflow YAML file.
*/
file;
/**
* Defines default scripts that should run *after* all jobs. Can be overriden by the job level `afterScript`.
*/
defaultAfterScript = [];
/**
* Default list of files and directories that should be attached to the job if it succeeds. Artifacts are sent to Gitlab where they can be downloaded.
*/
defaultArtifacts;
/**
* Defines default scripts that should run *before* all jobs. Can be overriden by the job level `afterScript`.
*/
defaultBeforeScript = [];
/**
* A default list of cache definitions (máx. 4) with the files and directories to cache between jobs. You can only use paths that are in the local working copy.
*/
_defaultCache;
get defaultCache() {
return this._defaultCache;
}
/**
* Specifies the default docker image to use globally for all jobs.
*/
defaultImage;
/**
* The default behavior for whether a job should be canceled when a newer pipeline starts before the job completes (Default: false).
*/
defaultInterruptible;
/**
* How many times a job is retried if it fails. If not defined, defaults to 0 and jobs do not retry.
*/
defaultRetry;
/**
* A default list of additional Docker images to run scripts in. The service image is linked to the image specified in the image parameter.
*/
defaultServices = [];
/**
* Used to select a specific runner from the list of all runners that are available for the project.
*/
defaultTags = [];
/**
* A default timeout job written in natural language (Ex. one hour, 3600 seconds, 60 minutes).
*/
defaultTimeout;
/**
* Default ID tokens (JSON Web Tokens) that are used for CI/CD authentication to use globally for all jobs.
*/
defaultIdTokens;
/**
* Specify a list of commands to execute on the runner before cloning the Git repository and any submodules https://docs.gitlab.com/ci/yaml/#hookspre_get_sources_script
*/
defaultHooks;
/**
* Can be `Include` or `Include[]`. Each `Include` will be a string, or an
* object with properties for the method if including external YAML file. The external
* content will be fetched, included and evaluated along the `.gitlab-ci.yml`.
*/
include = [];
/**
* A special job used to upload static sites to Gitlab pages. Requires a `public/` directory
* with `artifacts.path` pointing to it.
*/
pages;
/**
* Groups jobs into stages. All jobs in one stage must complete before next stage is
* executed. Defaults to ['build', 'test', 'deploy'].
*/
stages = [];
/**
* Global variables that are passed to jobs.
* If the job already has that variable defined, the job-level variable takes precedence.
*/
variables = {};
/**
* Used to control pipeline behavior.
*/
workflow;
/**
* The jobs in the CI configuration.
*/
jobs = {};
constructor(project, name, options) {
super(project);
this.name = path.parse(name).name;
const derivedPath = this.name === "gitlab-ci"
? ".gitlab-ci.yml"
: `.gitlab/ci-templates/${name.toLocaleLowerCase()}.yml`;
this.path = options?.path ?? derivedPath;
this.file = new yaml_1.YamlFile(this.project, this.path, {
obj: () => this.renderCI(),
// GitLab needs to read the file from the repository in order to work.
committed: true,
});
const defaults = options?.default;
if (defaults) {
this.defaultAfterScript.push(...(defaults.afterScript ?? []));
this.defaultArtifacts = defaults.artifacts;
defaults.beforeScript &&
this.defaultBeforeScript.push(...defaults.beforeScript);
defaults.cache && this.addDefaultCaches(defaults.cache);
this.defaultIdTokens = defaults.idTokens;
this.defaultImage = defaults.image;
this.defaultInterruptible = defaults.interruptible;
this.defaultRetry = defaults.retry;
defaults.services && this.addServices(...defaults.services);
defaults.tags && this.defaultTags.push(...defaults.tags);
this.defaultTimeout = defaults.timeout;
}
this.pages = options?.pages;
this.workflow = options?.workflow;
if (options?.stages) {
this.addStages(...options.stages);
}
if (options?.variables) {
this.addGlobalVariables(options.variables);
}
if (options?.jobs) {
this.addJobs(options.jobs);
}
}
/**
* Add additional yml/yaml files to the CI includes
* @param includes The includes to add.
*/
addIncludes(...includes) {
for (const additional of includes) {
this.assertIsValidInclude(additional);
for (const existing of this.include) {
if (this.areEqualIncludes(existing, additional)) {
throw new Error(`${this.name}: GitLab CI ${existing} already contains one or more templates specified in ${additional}.`);
}
}
this.include.push(additional);
}
}
/**
* Throw an error if the provided Include is invalid.
* @see https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/config/external/mapper.rb
* @param include the Include to validate.
*/
assertIsValidInclude(include) {
const combos = [
include.local,
include.file && include.project,
include.remote,
include.template,
];
const len = combos.filter((x) => Boolean(x)).length;
if (len !== 1) {
throw new Error(`${this.name}: GitLab CI include ${include} contains ${len} property combination(s).
A valid include configuration specifies *one* of the following property combinations.
* local
* file, project
* remote
* template
`);
}
}
/**
* Check if the equality of Includes.
* @see https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/config/external/mapper.rb
* @param x First include to compare.
* @param y Second include to compare.
* @returns Whether the includes are equal.
*/
areEqualIncludes(x, y) {
if (x.local === y.local && x.local !== undefined) {
return true;
}
else if (x.template === y.template && x.template !== undefined) {
return true;
}
else if (x.remote === y.remote && x.remote !== undefined) {
return true;
}
else if (x.project === y.project && x.ref === y.ref) {
const xFiles = x.file ? x.file : [];
const yFiles = y.file ? y.file : [];
const allFiles = xFiles.concat(yFiles);
return new Set(allFiles).size !== allFiles.length;
}
return false;
}
/**
* Add additional services.
* @param services The services to add.
*/
addServices(...services) {
for (const additional of services) {
for (const existing of this.defaultServices) {
if (additional.name === existing.name &&
additional.alias === existing.alias) {
throw new Error(`${this.name}: GitLab CI already contains service ${additional}.`);
}
}
this.defaultServices.push(additional);
}
}
/**
* Add a globally defined variable to the CI configuration.
* @param variables The variables to add.
*/
addGlobalVariables(variables) {
for (const [key, value] of Object.entries(variables)) {
if (this.variables[key] !== undefined) {
throw new Error(`${this.name}: GitLab CI already contains variable ${key}.`);
}
this.variables[key] = value;
}
}
/**
* Add stages to the CI configuration if not already present.
* @param stages stages to add.
*/
addStages(...stages) {
for (const stage of stages) {
if (!this.stages.includes(stage)) {
this.stages.push(stage);
}
}
}
/**
* Add jobs and their stages to the CI configuration.
* @param jobs Jobs to add.
*/
addJobs(jobs) {
for (const [key, value] of Object.entries(jobs)) {
if (this.jobs[key] !== undefined) {
throw new Error(`${this.name}: GitLab CI already contains job ${key}.`);
}
this.jobs[key] = value;
if (value.stage) {
this.addStages(value.stage);
}
if (value.cache) {
this.assertIsValidCacheSetup(value.cache);
}
}
}
isValidCacheSetup(caches) {
const MAX_CONFIGURABLE_CACHES = 4;
return caches.length <= MAX_CONFIGURABLE_CACHES;
}
assertIsValidCacheSetup(caches) {
if (!this.isValidCacheSetup(caches)) {
throw new Error(`${this.name}: GitLab CI can only define up to 4 caches, got: ${caches.length}`);
}
}
/**
* Adds up to 4 default caches configuration to the CI configuration.
* @param caches Caches to add.
*/
addDefaultCaches(caches) {
this.assertIsValidCacheSetup(caches);
this._defaultCache = caches;
}
/**
* Specify a list of commands to execute on the runner before cloning the Git repository and any submodules
* https://docs.gitlab.com/ci/yaml/#hookspre_get_sources_script
* @param hooks
*/
addDefaultHooks(hooks) {
this.defaultHooks = hooks;
}
renderCI() {
return {
default: this.renderDefault(),
include: this.include.length > 0 ? snakeCaseKeys(this.include) : undefined,
pages: snakeCaseKeys(this.pages),
services: this.defaultServices.length > 0
? snakeCaseKeys(this.defaultServices)
: undefined,
variables: Object.entries(this.variables).length > 0 ? this.variables : undefined,
workflow: snakeCaseKeys(this.workflow),
stages: this.stages.length > 0 ? this.stages : undefined,
// we do not want to change job names
// as they can be hidden (https://docs.gitlab.com/ee/ci/jobs/index.html#hide-jobs)
// or referenced in extends
...snakeCaseKeys(this.jobs, true),
};
}
renderDefault() {
const defaults = {
afterScript: this.defaultAfterScript.length > 0
? this.defaultAfterScript
: undefined,
artifacts: this.defaultArtifacts,
beforeScript: this.defaultBeforeScript.length > 0
? this.defaultBeforeScript
: undefined,
cache: this.defaultCache,
idTokens: this.defaultIdTokens,
image: this.defaultImage,
interruptible: this.defaultInterruptible,
retry: this.defaultRetry,
services: this.defaultServices.length > 0 ? this.defaultServices : undefined,
tags: this.defaultTags.length > 0 ? this.defaultTags : undefined,
timeout: this.defaultTimeout,
hooks: this.defaultHooks,
};
return Object.values(defaults).filter((x) => x).length
? snakeCaseKeys(defaults)
: undefined;
}
}
exports.CiConfiguration = CiConfiguration;
function snakeCaseKeys(obj, skipTopLevel = false) {
if (typeof obj !== "object" || obj == null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((o) => snakeCaseKeys(o));
}
const result = {};
for (let [k, v] of Object.entries(obj)) {
if (typeof v === "object" &&
v != null &&
k !== "variables" &&
k !== "idTokens" &&
k !== "inputs") {
v = snakeCaseKeys(v);
}
result[skipTopLevel ? k : (0, case_1.snake)(k)] = v;
}
return result;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlndXJhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9naXRsYWIvY29uZmlndXJhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkNBQTZCO0FBQzdCLCtCQUE2QjtBQWU3Qiw0Q0FBeUM7QUFFekMsa0NBQW1DO0FBdUNuQzs7OztHQUlHO0FBQ0gsTUFBYSxlQUFnQixTQUFRLHFCQUFTOztJQUM1Qzs7T0FFRztJQUNhLElBQUksQ0FBUztJQUM3Qjs7T0FFRztJQUNhLElBQUksQ0FBUztJQUM3Qjs7T0FFRztJQUNhLElBQUksQ0FBVztJQUMvQjs7T0FFRztJQUNhLGtCQUFrQixHQUFhLEVBQUUsQ0FBQztJQUNsRDs7T0FFRztJQUNhLGdCQUFnQixDQUFhO0lBQzdDOztPQUVHO0lBQ2EsbUJBQW1CLEdBQWEsRUFBRSxDQUFDO0lBQ25EOztPQUVHO0lBQ0ssYUFBYSxDQUFXO0lBRWhDLElBQVcsWUFBWTtRQUNyQixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUM7SUFDNUIsQ0FBQztJQUNEOztPQUVHO0lBQ2EsWUFBWSxDQUFTO0lBQ3JDOztPQUVHO0lBQ2Esb0JBQW9CLENBQVc7SUFDL0M7O09BRUc7SUFDYSxZQUFZLENBQVM7SUFDckM7O09BRUc7SUFDSyxlQUFlLEdBQWMsRUFBRSxDQUFDO0lBQ3hDOztPQUVHO0lBQ00sV0FBVyxHQUFhLEVBQUUsQ0FBQztJQUNwQzs7T0FFRztJQUNNLGNBQWMsQ0FBVTtJQUNqQzs7T0FFRztJQUNNLGVBQWUsQ0FBMkI7SUFDbkQ7O09BRUc7SUFDSyxZQUFZLENBQW9CO0lBQ3hDOzs7O09BSUc7SUFDSyxPQUFPLEdBQWMsRUFBRSxDQUFDO0lBQ2hDOzs7T0FHRztJQUNhLEtBQUssQ0FBTztJQUM1Qjs7O09BR0c7SUFDYSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQ3RDOzs7T0FHRztJQUNhLFNBQVMsR0FD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RyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBUSxDQUFDO0lBQ2pELENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBNEIsRUFBRSxDQUFDO0lBQzNDLEtBQUssSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDdkMsSUFDRSxPQUFPLENBQUMsS0FBSyxRQUFRO1lBQ3JCLENBQUMsSUFBSSxJQUFJO1lBQ1QsQ0FBQyxLQUFLLFdBQVc7WUFDakIsQ0FBQyxLQUFLLFVBQVU7WUFDaEIsQ0FBQyxLQUFLLFFBQVEsRUFDZCxDQUFDO1lBQ0QsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixDQUFDO1FBQ0QsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFBLFlBQUssRUFBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBQ0QsT0FBTyxNQUFhLENBQUM7QUFDdkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IHNuYWtlIH0gZnJvbSBcImNhc2VcIjtcbmltcG9ydCB0eXBlIHtcbiAgQXJ0aWZhY3RzLFxuICBDYWNoZSxcbiAgRGVmYXVsdCxcbiAgRGVmYXVsdEhvb2tzLFxuICBJRFRva2VuLFxuICBJbWFnZSxcbiAgSW5jbHVkZSxcbiAgSm9iLFxuICBSZXRyeSxcbiAgU2VydmljZSxcbiAgVmFyaWFibGVDb25maWcsXG4gIFdvcmtmbG93LFxufSBmcm9tIFwiLi9jb25maWd1cmF0aW9uLW1vZGVsXCI7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50XCI7XG5pbXBvcnQgdHlwZSB7IFByb2plY3QgfSBmcm9tIFwiLi4vcHJvamVjdFwiO1xuaW1wb3J0IHsgWWFtbEZpbGUgfSBmcm9tIFwiLi4veWFtbFwiO1xuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBDaUNvbmZpZ3VyYXRpb25gLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENpQ29uZmlndXJhdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogRGVmYXVsdCBzZXR0aW5ncyBmb3IgdGhlIENJIENvbmZpZ3VyYXRpb24uIEpvYnMgdGhhdCBkbyBub3QgZGVmaW5lIG9uZSBvciBtb3JlIG9mIHRoZSBsaXN0ZWQga2V5d29yZHMgdXNlIHRoZSB2YWx1ZSBkZWZpbmVkIGluIHRoZSBkZWZhdWx0IHNlY3Rpb24uXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0PzogRGVmYXVsdDtcbiAgLyoqXG4gICAqIEEgc3BlY2lhbCBqb2IgdXNlZCB0byB1cGxvYWQgc3RhdGljIHNpdGVzIHRvIEdpdGxhYiBwYWdlcy4gUmVxdWlyZXMgYSBgcHVibGljL2AgZGlyZWN0b3J5XG4gICAqIHdpdGggYGFydGlmYWN0cy5wYXRoYCBwb2ludGluZyB0byBpdC5cbiAgICovXG4gIHJlYWRvbmx5IHBhZ2VzPzogSm9iO1xuICAvKipcbiAgICogVXNlZCB0byBjb250cm9sIHBpcGVsaW5lIGJlaGF2aW9yLlxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2Zsb3c/OiBXb3JrZmxvdztcbiAgLyoqXG4gICAqIEdyb3VwcyBqb2JzIGludG8gc3RhZ2VzLiBBbGwgam9icyBpbiBvbmUgc3RhZ2UgbXVzdCBjb21wbGV0ZSBiZWZvcmUgbmV4dCBzdGFnZSBpc1xuICAgKiBleGVjdXRlZC4gSWYgbm8gc3RhZ2VzIGFyZSBzcGVjaWZpZWQuIERlZmF1bHRzIHRvIFsnYnVpbGQnLCAndGVzdCcsICdkZXBsb3knXS5cbiAgICovXG4gIHJlYWRvbmx5IHN0YWdlcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogR2xvYmFsIHZhcmlhYmxlcyB0aGF0IGFyZSBwYXNzZWQgdG8gam9icy5cbiAgICogSWYgdGhlIGpvYiBhbHJlYWR5IGhhcyB0aGF0IHZhcmlhYmxlIGRlZmluZWQsIHRoZSBqb2ItbGV2ZWwgdmFyaWFibGUgdGFrZXMgcHJlY2VkZW5jZS5cbiAgICovXG4gIHJlYWRvbmx5IHZhcmlhYmxlcz86IFJlY29yZDxzdHJpbmcsIGFueT47XG4gIC8qKlxuICAgKiBBbiBpbml0aWFsIHNldCBvZiBqb2JzIHRvIGFkZCB0byB0aGUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IGpvYnM/OiBSZWNvcmQ8c3RyaW5nLCBKb2I+O1xuICAvKipcbiAgICogVGhlIHBhdGggb2YgdGhlIGZpbGUgdG8gZ2VuZXJhdGUuXG4gICAqL1xuICByZWFkb25seSBwYXRoPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIENJIGZvciBHaXRMYWIuXG4gKiBBIENJIGlzIGEgY29uZmlndXJhYmxlIGF1dG9tYXRlZCBwcm9jZXNzIG1hZGUgdXAgb2Ygb25lIG9yIG1vcmUgc3RhZ2VzL2pvYnMuXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2VlL2NpL3lhbWwvXG4gKi9cbmV4cG9ydCBjbGFzcyBDaUNvbmZpZ3VyYXRpb24gZXh0ZW5kcyBDb21wb25lbnQge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogUGF0aCB0byBDSSBmaWxlIGdlbmVyYXRlZCBieSB0aGUgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwYXRoOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgd29ya2Zsb3cgWUFNTCBmaWxlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGZpbGU6IFlhbWxGaWxlO1xuICAvKipcbiAgICogRGVmaW5lcyBkZWZhdWx0IHNjcmlwdHMgdGhhdCBzaG91bGQgcnVuICphZnRlciogYWxsIGpvYnMuIENhbiBiZSBvdmVycmlkZW4gYnkgdGhlIGpvYiBsZXZlbCBgYWZ0ZXJTY3JpcHRgLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRBZnRlclNjcmlwdDogc3RyaW5nW10gPSBbXTtcbiAgLyoqXG4gICAqIERlZmF1bHQgbGlzdCBvZiBmaWxlcyBhbmQgZGlyZWN0b3JpZXMgdGhhdCBzaG91bGQgYmUgYXR0YWNoZWQgdG8gdGhlIGpvYiBpZiBpdCBzdWNjZWVkcy4gQXJ0aWZhY3RzIGFyZSBzZW50IHRvIEdpdGxhYiB3aGVyZSB0aGV5IGNhbiBiZSBkb3dubG9hZGVkLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRBcnRpZmFjdHM/OiBBcnRpZmFjdHM7XG4gIC8qKlxuICAgKiBEZWZpbmVzIGRlZmF1bHQgc2NyaXB0cyB0aGF0IHNob3VsZCBydW4gKmJlZm9yZSogYWxsIGpvYnMuIENhbiBiZSBvdmVycmlkZW4gYnkgdGhlIGpvYiBsZXZlbCBgYWZ0ZXJTY3JpcHRgLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRCZWZvcmVTY3JpcHQ6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBBIGRlZmF1bHQgbGlzdCBvZiBjYWNoZSBkZWZpbml0aW9ucyAobcOheC4gNCkgd2l0aCB0aGUgZmlsZXMgYW5kIGRpcmVjdG9yaWVzIHRvIGNhY2hlIGJldHdlZW4gam9icy4gWW91IGNhbiBvbmx5IHVzZSBwYXRocyB0aGF0IGFyZSBpbiB0aGUgbG9jYWwgd29ya2luZyBjb3B5LlxuICAgKi9cbiAgcHJpdmF0ZSBfZGVmYXVsdENhY2hlPzogQ2FjaGVbXTtcblxuICBwdWJsaWMgZ2V0IGRlZmF1bHRDYWNoZSgpOiBDYWNoZVtdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fZGVmYXVsdENhY2hlO1xuICB9XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIGRlZmF1bHQgZG9ja2VyIGltYWdlIHRvIHVzZSBnbG9iYWxseSBmb3IgYWxsIGpvYnMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdEltYWdlPzogSW1hZ2U7XG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBiZWhhdmlvciBmb3Igd2hldGhlciBhIGpvYiBzaG91bGQgYmUgY2FuY2VsZWQgd2hlbiBhIG5ld2VyIHBpcGVsaW5lIHN0YXJ0cyBiZWZvcmUgdGhlIGpvYiBjb21wbGV0ZXMgKERlZmF1bHQ6IGZhbHNlKS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBkZWZhdWx0SW50ZXJydXB0aWJsZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBIb3cgbWFueSB0aW1lcyBhIGpvYiBpcyByZXRyaWVkIGlmIGl0IGZhaWxzLiBJZiBub3QgZGVmaW5lZCwgZGVmYXVsdHMgdG8gMCBhbmQgam9icyBkbyBub3QgcmV0cnkuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdFJldHJ5PzogUmV0cnk7XG4gIC8qKlxuICAgKiBBIGRlZmF1bHQgbGlzdCBvZiBhZGRpdGlvbmFsIERvY2tlciBpbWFnZXMgdG8gcnVuIHNjcmlwdHMgaW4uIFRoZSBzZXJ2aWNlIGltYWdlIGlzIGxpbmtlZCB0byB0aGUgaW1hZ2Ugc3BlY2lmaWVkIGluIHRoZSAgaW1hZ2UgcGFyYW1ldGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBkZWZhdWx0U2VydmljZXM6IFNlcnZpY2VbXSA9IFtdO1xuICAvKipcbiAgICogVXNlZCB0byBzZWxlY3QgYSBzcGVjaWZpYyBydW5uZXIgZnJvbSB0aGUgbGlzdCBvZiBhbGwgcnVubmVycyB0aGF0IGFyZSBhdmFpbGFibGUgZm9yIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdFRhZ3M6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBBIGRlZmF1bHQgdGltZW91dCBqb2Igd3JpdHRlbiBpbiBuYXR1cmFsIGxhbmd1YWdlIChFeC4gb25lIGhvdXIsIDM2MDAgc2Vjb25kcywgNjAgbWludXRlcykuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0VGltZW91dD86IHN0cmluZztcbiAgLyoqXG4gICAqIERlZmF1bHQgSUQgdG9rZW5zIChKU09OIFdlYiBUb2tlbnMpIHRoYXQgYXJlIHVzZWQgZm9yIENJL0NEIGF1dGhlbnRpY2F0aW9uIHRvIHVzZSBnbG9iYWxseSBmb3IgYWxsIGpvYnMuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0SWRUb2tlbnM/OiBSZWNvcmQ8c3RyaW5nLCBJRFRva2VuPjtcbiAgLyoqXG4gICAqIFNwZWNpZnkgYSBsaXN0IG9mIGNvbW1hbmRzIHRvIGV4ZWN1dGUgb24gdGhlIHJ1bm5lciBiZWZvcmUgY2xvbmluZyB0aGUgR2l0IHJlcG9zaXRvcnkgYW5kIGFueSBzdWJtb2R1bGVzIGh0dHBzOi8vZG9jcy5naXRsYWIuY29tL2NpL3lhbWwvI2hvb2tzcHJlX2dldF9zb3VyY2VzX3NjcmlwdFxuICAgKi9cbiAgcHJpdmF0ZSBkZWZhdWx0SG9va3M/OiBEZWZhdWx0W1wiaG9va3NcIl07XG4gIC8qKlxuICAgKiBDYW4gYmUgYEluY2x1ZGVgIG9yIGBJbmNsdWRlW11gLiBFYWNoIGBJbmNsdWRlYCB3aWxsIGJlIGEgc3RyaW5nLCBvciBhblxuICAgKiBvYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIGZvciB0aGUgbWV0aG9kIGlmIGluY2x1ZGluZyBleHRlcm5hbCBZQU1MIGZpbGUuIFRoZSBleHRlcm5hbFxuICAgKiBjb250ZW50IHdpbGwgYmUgZmV0Y2hlZCwgaW5jbHVkZWQgYW5kIGV2YWx1YXRlZCBhbG9uZyB0aGUgYC5naXRsYWItY2kueW1sYC5cbiAgICovXG4gIHByaXZhdGUgaW5jbHVkZTogSW5jbHVkZVtdID0gW107XG4gIC8qKlxuICAgKiBBIHNwZWNpYWwgam9iIHVzZWQgdG8gdXBsb2FkIHN0YXRpYyBzaXRlcyB0byBHaXRsYWIgcGFnZXMuIFJlcXVpcmVzIGEgYHB1YmxpYy9gIGRpcmVjdG9yeVxuICAgKiB3aXRoIGBhcnRpZmFjdHMucGF0aGAgcG9pbnRpbmcgdG8gaXQuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcGFnZXM/OiBKb2I7XG4gIC8qKlxuICAgKiBHcm91cHMgam9icyBpbnRvIHN0YWdlcy4gQWxsIGpvYnMgaW4gb25lIHN0YWdlIG11c3QgY29tcGxldGUgYmVmb3JlIG5leHQgc3RhZ2UgaXNcbiAgICogZXhlY3V0ZWQuIERlZmF1bHRzIHRvIFsnYnVpbGQnLCAndGVzdCcsICdkZXBsb3knXS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzdGFnZXM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBHbG9iYWwgdmFyaWFibGVzIHRoYXQgYXJlIHBhc3NlZCB0byBqb2JzLlxuICAgKiBJZiB0aGUgam9iIGFscmVhZHkgaGFzIHRoYXQgdmFyaWFibGUgZGVmaW5lZCwgdGhlIGpvYi1sZXZlbCB2YXJpYWJsZSB0YWtlcyBwcmVjZWRlbmNlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZhcmlhYmxlczogUmVjb3JkPHN0cmluZywgbnVtYmVyIHwgVmFyaWFibGVDb25maWcgfCBzdHJpbmc+ID1cbiAgICB7fTtcbiAgLyoqXG4gICAqIFVzZWQgdG8gY29udHJvbCBwaXBlbGluZSBiZWhhdmlvci5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB3b3JrZmxvdz86IFdvcmtmbG93O1xuICAvKipcbiAgICogVGhlIGpvYnMgaW4gdGhlIENJIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgam9iczogUmVjb3JkPHN0cmluZywgSm9iPiA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb2plY3Q6IFByb2plY3QsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBDaUNvbmZpZ3VyYXRpb25PcHRpb25zLFxuICApIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcbiAgICB0aGlzLm5hbWUgPSBwYXRoLnBhcnNlKG5hbWUpLm5hbWU7XG4gICAgY29uc3QgZGVyaXZlZFBhdGggPVxuICAgICAgdGhpcy5uYW1lID09PSBcImdpdGxhYi1jaVwiXG4gICAgICAgID8gXCIuZ2l0bGFiLWNpLnltbFwiXG4gICAgICAgIDogYC5naXRsYWIvY2ktdGVtcGxhdGVzLyR7bmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpfS55bWxgO1xuICAgIHRoaXMucGF0aCA9IG9wdGlvbnM/LnBhdGggPz8gZGVyaXZlZFBhdGg7XG4gICAgdGhpcy5maWxlID0gbmV3IFlhbWxGaWxlKHRoaXMucHJvamVjdCwgdGhpcy5wYXRoLCB7XG4gICAgICBvYmo6ICgpID0+IHRoaXMucmVuZGVyQ0koKSxcbiAgICAgIC8vIEdpdExhYiBuZWVkcyB0byByZWFkIHRoZSBmaWxlIGZyb20gdGhlIHJlcG9zaXRvcnkgaW4gb3JkZXIgdG8gd29yay5cbiAgICAgIGNvbW1pdHRlZDogdHJ1ZSxcbiAgICB9KTtcbiAgICBjb25zdCBkZWZhdWx0cyA9IG9wdGlvbnM/LmRlZmF1bHQ7XG4gICAgaWYgKGRlZmF1bHRzKSB7XG4gICAgICB0aGlzLmRlZmF1bHRBZnRlclNjcmlwdC5wdXNoKC4uLihkZWZhdWx0cy5hZnRlclNjcmlwdCA/PyBbXSkpO1xuICAgICAgdGhpcy5kZWZhdWx0QXJ0aWZhY3RzID0gZGVmYXVsdHMuYXJ0aWZhY3RzO1xuICAgICAgZGVmYXVsdHMuYmVmb3JlU2NyaXB0ICYmXG4gICAgICAgIHRoaXMuZGVmYXVsdEJlZm9yZVNjcmlwdC5wdXNoKC4uLmRlZmF1bHRzLmJlZm9yZVNjcmlwdCk7XG4gICAgICBkZWZhdWx0cy5jYWNoZSAmJiB0aGlzLmFkZERlZmF1bHRDYWNoZXMoZGVmYXVsdHMuY2FjaGUpO1xuICAgICAgdGhpcy5kZWZhdWx0SWRUb2tlbnMgPSBkZWZhdWx0cy5pZFRva2VucztcbiAgICAgIHRoaXMuZGVmYXVsdEltYWdlID0gZGVmYXVsdHMuaW1hZ2U7XG4gICAgICB0aGlzLmRlZmF1bHRJbnRlcnJ1cHRpYmxlID0gZGVmYXVsdHMuaW50ZXJydXB0aWJsZTtcbiAgICAgIHRoaXMuZGVmYXVsdFJldHJ5ID0gZGVmYXVsdHMucmV0cnk7XG4gICAgICBkZWZhdWx0cy5zZXJ2aWNlcyAmJiB0aGlzLmFkZFNlcnZpY2VzKC4uLmRlZmF1bHRzLnNlcnZpY2VzKTtcbiAgICAgIGRlZmF1bHRzLnRhZ3MgJiYgdGhpcy5kZWZhdWx0VGFncy5wdXNoKC4uLmRlZmF1bHRzLnRhZ3MpO1xuICAgICAgdGhpcy5kZWZhdWx0VGltZW91dCA9IGRlZmF1bHRzLnRpbWVvdXQ7XG4gICAgfVxuICAgIHRoaXMucGFnZXMgPSBvcHRpb25zPy5wYWdlcztcbiAgICB0aGlzLndvcmtmbG93ID0gb3B0aW9ucz8ud29ya2Zsb3c7XG4gICAgaWYgKG9wdGlvbnM/LnN0YWdlcykge1xuICAgICAgdGhpcy5hZGRTdGFnZXMoLi4ub3B0aW9ucy5zdGFnZXMpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucz8udmFyaWFibGVzKSB7XG4gICAgICB0aGlzLmFkZEdsb2JhbFZhcmlhYmxlcyhvcHRpb25zLnZhcmlhYmxlcyk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zPy5qb2JzKSB7XG4gICAgICB0aGlzLmFkZEpvYnMob3B0aW9ucy5qb2JzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFkZGl0aW9uYWwgeW1sL3lhbWwgZmlsZXMgdG8gdGhlIENJIGluY2x1ZGVzXG4gICAqIEBwYXJhbSBpbmNsdWRlcyBUaGUgaW5jbHVkZXMgdG8gYWRkLlxuICAgKi9cbiAgcHVibGljIGFkZEluY2x1ZGVzKC4uLmluY2x1ZGVzOiBJbmNsdWRlW10pIHtcbiAgICBmb3IgKGNvbnN0IGFkZGl0aW9uYWwgb2YgaW5jbHVkZXMpIHtcbiAgICAgIHRoaXMuYXNzZXJ0SXNWYWxpZEluY2x1ZGUoYWRkaXRpb25hbCk7XG4gICAgICBmb3IgKGNvbnN0IGV4aXN0aW5nIG9mIHRoaXMuaW5jbHVkZSkge1xuICAgICAgICBpZiAodGhpcy5hcmVFcXVhbEluY2x1ZGVzKGV4aXN0aW5nLCBhZGRpdGlvbmFsKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGAke3RoaXMubmFtZX06IEdpdExhYiBDSSAke2V4aXN0aW5nfSBhbHJlYWR5IGNvbnRhaW5zIG9uZSBvciBtb3JlIHRlbXBsYXRlcyBzcGVjaWZpZWQgaW4gJHthZGRpdGlvbmFsfS5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuaW5jbHVkZS5wdXNoKGFkZGl0aW9uYWwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaHJvdyBhbiBlcnJvciBpZiB0aGUgcHJvdmlkZWQgSW5jbHVkZSBpcyBpbnZhbGlkLlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0bGFiLmNvbS9naXRsYWItb3JnL2dpdGxhYi8tL2Jsb2IvbWFzdGVyL2xpYi9naXRsYWIvY2kvY29uZmlnL2V4dGVybmFsL21hcHBlci5yYlxuICAgKiBAcGFyYW0gaW5jbHVkZSB0aGUgSW5jbHVkZSB0byB2YWxpZGF0ZS5cbiAgICovXG4gIHByaXZhdGUgYXNzZXJ0SXNWYWxpZEluY2x1ZGUoaW5jbHVkZTogSW5jbHVkZSkge1xuICAgIGNvbnN0IGNvbWJvcyA9IFtcbiAgICAgIGluY2x1ZGUubG9jYWwsXG4gICAgICBpbmNsdWRlLmZpbGUgJiYgaW5jbHVkZS5wcm9qZWN0LFxuICAgICAgaW5jbHVkZS5yZW1vdGUsXG4gICAgICBpbmNsdWRlLnRlbXBsYXRlLFxuICAgIF07XG4gICAgY29uc3QgbGVuID0gY29tYm9zLmZpbHRlcigoeCkgPT4gQm9vbGVhbih4KSkubGVuZ3RoO1xuICAgIGlmIChsZW4gIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy5uYW1lfTogR2l0TGFiIENJIGluY2x1ZGUgJHtpbmNsdWRlfSBjb250YWlucyAke2xlbn0gcHJvcGVydHkgY29tYmluYXRpb24ocykuXG4gICAgICAgIEEgdmFsaWQgaW5jbHVkZSBjb25maWd1cmF0aW9uIHNwZWNpZmllcyAqb25lKiBvZiB0aGUgZm9sbG93aW5nIHByb3BlcnR5IGNvbWJpbmF0aW9ucy5cbiAgICAgICAgKiBsb2NhbFxuICAgICAgICAqIGZpbGUsIHByb2plY3RcbiAgICAgICAgKiByZW1vdGVcbiAgICAgICAgKiB0ZW1wbGF0ZVxuICAgICAgICBgLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGVxdWFsaXR5IG9mIEluY2x1ZGVzLlxuICAgKiBAc2VlIGh0dHBzOi8vZ2l0bGFiLmNvbS9naXRsYWItb3JnL2dpdGxhYi8tL2Jsb2IvbWFzdGVyL2xpYi9naXRsYWIvY2kvY29uZmlnL2V4dGVybmFsL21hcHBlci5yYlxuICAgKiBAcGFyYW0geCBGaXJzdCBpbmNsdWRlIHRvIGNvbXBhcmUuXG4gICAqIEBwYXJhbSB5IFNlY29uZCBpbmNsdWRlIHRvIGNvbXBhcmUuXG4gICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIGluY2x1ZGVzIGFyZSBlcXVhbC5cbiAgICovXG4gIHByaXZhdGUgYXJlRXF1YWxJbmNsdWRlcyh4OiBJbmNsdWRlLCB5OiBJbmNsdWRlKTogYm9vbGVhbiB7XG4gICAgaWYgKHgubG9jYWwgPT09IHkubG9jYWwgJiYgeC5sb2NhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHgudGVtcGxhdGUgPT09IHkudGVtcGxhdGUgJiYgeC50ZW1wbGF0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHgucmVtb3RlID09PSB5LnJlbW90ZSAmJiB4LnJlbW90ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHgucHJvamVjdCA9PT0geS5wcm9qZWN0ICYmIHgucmVmID09PSB5LnJlZikge1xuICAgICAgY29uc3QgeEZpbGVzID0geC5maWxlID8geC5maWxlIDogW107XG4gICAgICBjb25zdCB5RmlsZXMgPSB5LmZpbGUgPyB5LmZpbGUgOiBbXTtcbiAgICAgIGNvbnN0IGFsbEZpbGVzID0geEZpbGVzLmNvbmNhdCh5RmlsZXMpO1xuICAgICAgcmV0dXJuIG5ldyBTZXQoYWxsRmlsZXMpLnNpemUgIT09IGFsbEZpbGVzLmxlbmd0aDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhZGRpdGlvbmFsIHNlcnZpY2VzLlxuICAgKiBAcGFyYW0gc2VydmljZXMgVGhlIHNlcnZpY2VzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBhZGRTZXJ2aWNlcyguLi5zZXJ2aWNlczogU2VydmljZVtdKSB7XG4gICAgZm9yIChjb25zdCBhZGRpdGlvbmFsIG9mIHNlcnZpY2VzKSB7XG4gICAgICBmb3IgKGNvbnN0IGV4aXN0aW5nIG9mIHRoaXMuZGVmYXVsdFNlcnZpY2VzKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBhZGRpdGlvbmFsLm5hbWUgPT09IGV4aXN0aW5nLm5hbWUgJiZcbiAgICAgICAgICBhZGRpdGlvbmFsLmFsaWFzID09PSBleGlzdGluZy5hbGlhc1xuICAgICAgICApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgJHt0aGlzLm5hbWV9OiBHaXRMYWIgQ0kgYWxyZWFkeSBjb250YWlucyBzZXJ2aWNlICR7YWRkaXRpb25hbH0uYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmRlZmF1bHRTZXJ2aWNlcy5wdXNoKGFkZGl0aW9uYWwpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBnbG9iYWxseSBkZWZpbmVkIHZhcmlhYmxlIHRvIHRoZSBDSSBjb25maWd1cmF0aW9uLlxuICAgKiBAcGFyYW0gdmFyaWFibGVzIFRoZSB2YXJpYWJsZXMgdG8gYWRkLlxuICAgKi9cbiAgcHVibGljIGFkZEdsb2JhbFZhcmlhYmxlcyh2YXJpYWJsZXM6IFJlY29yZDxzdHJpbmcsIGFueT4pIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh2YXJpYWJsZXMpKSB7XG4gICAgICBpZiAodGhpcy52YXJpYWJsZXNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgJHt0aGlzLm5hbWV9OiBHaXRMYWIgQ0kgYWxyZWFkeSBjb250YWlucyB2YXJpYWJsZSAke2tleX0uYCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMudmFyaWFibGVzW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIHN0YWdlcyB0byB0aGUgQ0kgY29uZmlndXJhdGlvbiBpZiBub3QgYWxyZWFkeSBwcmVzZW50LlxuICAgKiBAcGFyYW0gc3RhZ2VzIHN0YWdlcyB0byBhZGQuXG4gICAqL1xuICBwdWJsaWMgYWRkU3RhZ2VzKC4uLnN0YWdlczogc3RyaW5nW10pIHtcbiAgICBmb3IgKGNvbnN0IHN0YWdlIG9mIHN0YWdlcykge1xuICAgICAgaWYgKCF0aGlzLnN0YWdlcy5pbmNsdWRlcyhzdGFnZSkpIHtcbiAgICAgICAgdGhpcy5zdGFnZXMucHVzaChzdGFnZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBqb2JzIGFuZCB0aGVpciBzdGFnZXMgdG8gdGhlIENJIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSBqb2JzIEpvYnMgdG8gYWRkLlxuICAgKi9cbiAgcHVibGljIGFkZEpvYnMoam9iczogUmVjb3JkPHN0cmluZywgSm9iPikge1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGpvYnMpKSB7XG4gICAgICBpZiAodGhpcy5qb2JzW2tleV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5uYW1lfTogR2l0TGFiIENJIGFscmVhZHkgY29udGFpbnMgam9iICR7a2V5fS5gKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuam9ic1trZXldID0gdmFsdWU7XG4gICAgICBpZiAodmFsdWUuc3RhZ2UpIHtcbiAgICAgICAgdGhpcy5hZGRTdGFnZXModmFsdWUuc3RhZ2UpO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlLmNhY2hlKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0SXNWYWxpZENhY2hlU2V0dXAodmFsdWUuY2FjaGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaXNWYWxpZENhY2hlU2V0dXAoY2FjaGVzOiBDYWNoZVtdKTogQm9vbGVhbiB7XG4gICAgY29uc3QgTUFYX0NPTkZJR1VSQUJMRV9DQUNIRVMgPSA0O1xuICAgIHJldHVybiBjYWNoZXMubGVuZ3RoIDw9IE1BWF9DT05GSUdVUkFCTEVfQ0FDSEVTO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnRJc1ZhbGlkQ2FjaGVTZXR1cChjYWNoZXM6IENhY2hlW10pIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZENhY2hlU2V0dXAoY2FjaGVzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHt0aGlzLm5hbWV9OiBHaXRMYWIgQ0kgY2FuIG9ubHkgZGVmaW5lIHVwIHRvIDQgY2FjaGVzLCBnb3Q6ICR7Y2FjaGVzLmxlbmd0aH1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkcyB1cCB0byA0IGRlZmF1bHQgY2FjaGVzIGNvbmZpZ3VyYXRpb24gdG8gdGhlIENJIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSBjYWNoZXMgQ2FjaGVzIHRvIGFkZC5cbiAgICovXG4gIHB1YmxpYyBhZGREZWZhdWx0Q2FjaGVzKGNhY2hlczogQ2FjaGVbXSkge1xuICAgIHRoaXMuYXNzZXJ0SXNWYWxpZENhY2hlU2V0dXAoY2FjaGVzKTtcbiAgICB0aGlzLl9kZWZhdWx0Q2FjaGUgPSBjYWNoZXM7XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmeSBhIGxpc3Qgb2YgY29tbWFuZHMgdG8gZXhlY3V0ZSBvbiB0aGUgcnVubmVyIGJlZm9yZSBjbG9uaW5nIHRoZSBHaXQgcmVwb3NpdG9yeSBhbmQgYW55IHN1Ym1vZHVsZXNcbiAgICogaHR0cHM6Ly9kb2NzLmdpdGxhYi5jb20vY2kveWFtbC8jaG9va3NwcmVfZ2V0X3NvdXJjZXNfc2NyaXB0XG4gICAqIEBwYXJhbSBob29rc1xuICAgKi9cbiAgcHVibGljIGFkZERlZmF1bHRIb29rcyhob29rczogRGVmYXVsdEhvb2tzKSB7XG4gICAgdGhpcy5kZWZhdWx0SG9va3MgPSBob29rcztcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyQ0koKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlZmF1bHQ6IHRoaXMucmVuZGVyRGVmYXVsdCgpLFxuICAgICAgaW5jbHVkZTpcbiAgICAgICAgdGhpcy5pbmNsdWRlLmxlbmd0aCA+IDAgPyBzbmFrZUNhc2VLZXlzKHRoaXMuaW5jbHVkZSkgOiB1bmRlZmluZWQsXG4gICAgICBwYWdlczogc25ha2VDYXNlS2V5cyh0aGlzLnBhZ2VzKSxcbiAgICAgIHNlcnZpY2VzOlxuICAgICAgICB0aGlzLmRlZmF1bHRTZXJ2aWNlcy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBzbmFrZUNhc2VLZXlzKHRoaXMuZGVmYXVsdFNlcnZpY2VzKVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgdmFyaWFibGVzOlxuICAgICAgICBPYmplY3QuZW50cmllcyh0aGlzLnZhcmlhYmxlcykubGVuZ3RoID4gMCA/IHRoaXMudmFyaWFibGVzIDogdW5kZWZpbmVkLFxuICAgICAgd29ya2Zsb3c6IHNuYWtlQ2FzZUtleXModGhpcy53b3JrZmxvdyksXG4gICAgICBzdGFnZXM6IHRoaXMuc3RhZ2VzLmxlbmd0aCA+IDAgPyB0aGlzLnN0YWdlcyA6IHVuZGVmaW5lZCxcbiAgICAgIC8vIHdlIGRvIG5vdCB3YW50IHRvIGNoYW5nZSBqb2IgbmFtZXNcbiAgICAgIC8vIGFzIHRoZXkgY2FuIGJlIGhpZGRlbiAoaHR0cHM6Ly9kb2NzLmdpdGxhYi5jb20vZWUvY2kvam9icy9pbmRleC5odG1sI2hpZGUtam9icylcbiAgICAgIC8vIG9yIHJlZmVyZW5jZWQgaW4gZXh0ZW5kc1xuICAgICAgLi4uc25ha2VDYXNlS2V5cyh0aGlzLmpvYnMsIHRydWUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHJlbmRlckRlZmF1bHQoKSB7XG4gICAgY29uc3QgZGVmYXVsdHM6IERlZmF1bHQgPSB7XG4gICAgICBhZnRlclNjcmlwdDpcbiAgICAgICAgdGhpcy5kZWZhdWx0QWZ0ZXJTY3JpcHQubGVuZ3RoID4gMFxuICAgICAgICAgID8gdGhpcy5kZWZhdWx0QWZ0ZXJTY3JpcHRcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIGFydGlmYWN0czogdGhpcy5kZWZhdWx0QXJ0aWZhY3RzLFxuICAgICAgYmVmb3JlU2NyaXB0OlxuICAgICAgICB0aGlzLmRlZmF1bHRCZWZvcmVTY3JpcHQubGVuZ3RoID4gMFxuICAgICAgICAgID8gdGhpcy5kZWZhdWx0QmVmb3JlU2NyaXB0XG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBjYWNoZTogdGhpcy5kZWZhdWx0Q2FjaGUsXG4gICAgICBpZFRva2VuczogdGhpcy5kZWZhdWx0SWRUb2tlbnMsXG4gICAgICBpbWFnZTogdGhpcy5kZWZhdWx0SW1hZ2UsXG4gICAgICBpbnRlcnJ1cHRpYmxlOiB0aGlzLmRlZmF1bHRJbnRlcnJ1cHRpYmxlLFxuICAgICAgcmV0cnk6IHRoaXMuZGVmYXVsdFJldHJ5LFxuICAgICAgc2VydmljZXM6XG4gICAgICAgIHRoaXMuZGVmYXVsdFNlcnZpY2VzLmxlbmd0aCA+IDAgPyB0aGlzLmRlZmF1bHRTZXJ2aWNlcyA6IHVuZGVmaW5lZCxcbiAgICAgIHRhZ3M6IHRoaXMuZGVmYXVsdFRhZ3MubGVuZ3RoID4gMCA/IHRoaXMuZGVmYXVsdFRhZ3MgOiB1bmRlZmluZWQsXG4gICAgICB0aW1lb3V0OiB0aGlzLmRlZmF1bHRUaW1lb3V0LFxuICAgICAgaG9va3M6IHRoaXMuZGVmYXVsdEhvb2tzLFxuICAgIH07XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoZGVmYXVsdHMpLmZpbHRlcigoeCkgPT4geCkubGVuZ3RoXG4gICAgICA/IHNuYWtlQ2FzZUtleXMoZGVmYXVsdHMpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBzbmFrZUNhc2VLZXlzPFQgPSB1bmtub3duPihvYmo6IFQsIHNraXBUb3BMZXZlbDogYm9vbGVhbiA9IGZhbHNlKTogVCB7XG4gIGlmICh0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiIHx8IG9iaiA9PSBudWxsKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gb2JqLm1hcCgobykgPT4gc25ha2VDYXNlS2V5cyhvKSkgYXMgYW55O1xuICB9XG5cbiAgY29uc3QgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICBmb3IgKGxldCBbaywgdl0gb2YgT2JqZWN0LmVudHJpZXMob2JqKSkge1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiB2ID09PSBcIm9iamVjdFwiICYmXG4gICAgICB2ICE9IG51bGwgJiZcbiAgICAgIGsgIT09IFwidmFyaWFibGVzXCIgJiZcbiAgICAgIGsgIT09IFwiaWRUb2tlbnNcIiAmJlxuICAgICAgayAhPT0gXCJpbnB1dHNcIlxuICAgICkge1xuICAgICAgdiA9IHNuYWtlQ2FzZUtleXModik7XG4gICAgfVxuICAgIHJlc3VsdFtza2lwVG9wTGV2ZWwgPyBrIDogc25ha2UoayldID0gdjtcbiAgfVxuICByZXR1cm4gcmVzdWx0IGFzIGFueTtcbn1cbiJdfQ==