@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
200 lines • 30.7 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NestedStack = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const crypto = require("crypto");
const cxapi = require("@aws-cdk/cx-api");
const constructs_1 = require("constructs");
const assets_1 = require("./assets");
const cfn_fn_1 = require("./cfn-fn");
const cfn_pseudo_1 = require("./cfn-pseudo");
const cloudformation_generated_1 = require("./cloudformation.generated");
const lazy_1 = require("./lazy");
const names_1 = require("./names");
const removal_policy_1 = require("./removal-policy");
const stack_1 = require("./stack");
const stack_synthesizers_1 = require("./stack-synthesizers");
const token_1 = require("./token");
// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
// eslint-disable-next-line
const construct_compat_1 = require("./construct-compat");
const NESTED_STACK_SYMBOL = Symbol.for('@aws-cdk/core.NestedStack');
/**
* A CloudFormation nested stack.
*
* When you apply template changes to update a top-level stack, CloudFormation
* updates the top-level stack and initiates an update to its nested stacks.
* CloudFormation updates the resources of modified nested stacks, but does not
* update the resources of unmodified nested stacks.
*
* Furthermore, this stack will not be treated as an independent deployment
* artifact (won't be listed in "cdk list" or deployable through "cdk deploy"),
* but rather only synthesized as a template and uploaded as an asset to S3.
*
* Cross references of resource attributes between the parent stack and the
* nested stack will automatically be translated to stack parameters and
* outputs.
*
*/
class NestedStack extends stack_1.Stack {
constructor(scope, id, props = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_core_NestedStackProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, NestedStack);
}
throw error;
}
const parentStack = findParentStack(scope);
super(scope, id, {
env: { account: parentStack.account, region: parentStack.region },
synthesizer: new stack_synthesizers_1.NestedStackSynthesizer(parentStack.synthesizer),
});
this._parentStack = parentStack;
// @deprecate: remove this in v2.0 (redundent)
const parentScope = new construct_compat_1.Construct(scope, id + '.NestedStack');
Object.defineProperty(this, NESTED_STACK_SYMBOL, { value: true });
// this is the file name of the synthesized template file within the cloud assembly
this.templateFile = `${names_1.Names.uniqueId(this)}.nested.template.json`;
this.parameters = props.parameters || {};
this.resource = new cloudformation_generated_1.CfnStack(parentScope, `${id}.NestedStackResource`, {
// This value cannot be cached since it changes during the synthesis phase
templateUrl: lazy_1.Lazy.uncachedString({ produce: () => this._templateUrl || '<unresolved>' }),
parameters: lazy_1.Lazy.any({ produce: () => Object.keys(this.parameters).length > 0 ? this.parameters : undefined }),
notificationArns: props.notificationArns,
timeoutInMinutes: props.timeout ? props.timeout.toMinutes() : undefined,
});
this.resource.applyRemovalPolicy(props.removalPolicy ?? removal_policy_1.RemovalPolicy.DESTROY);
this.nestedStackResource = this.resource;
this.node.defaultChild = this.resource;
// context-aware stack name: if resolved from within this stack, return AWS::StackName
// if resolved from the outer stack, use the { Ref } of the AWS::CloudFormation::Stack resource
// which resolves the ARN of the stack. We need to extract the stack name, which is the second
// component after splitting by "/"
this._contextualStackName = this.contextualAttribute(cfn_pseudo_1.Aws.STACK_NAME, cfn_fn_1.Fn.select(1, cfn_fn_1.Fn.split('/', this.resource.ref)));
this._contextualStackId = this.contextualAttribute(cfn_pseudo_1.Aws.STACK_ID, this.resource.ref);
}
/**
* Checks if `x` is an object of type `NestedStack`.
*/
static isNestedStack(x) {
return x != null && typeof (x) === 'object' && NESTED_STACK_SYMBOL in x;
}
/**
* An attribute that represents the name of the nested stack.
*
* This is a context aware attribute:
* - If this is referenced from the parent stack, it will return a token that parses the name from the stack ID.
* - If this is referenced from the context of the nested stack, it will return `{ "Ref": "AWS::StackName" }`
*
* Example value: `mystack-mynestedstack-sggfrhxhum7w`
* @attribute
*/
get stackName() {
return this._contextualStackName;
}
/**
* An attribute that represents the ID of the stack.
*
* This is a context aware attribute:
* - If this is referenced from the parent stack, it will return `{ "Ref": "LogicalIdOfNestedStackResource" }`.
* - If this is referenced from the context of the nested stack, it will return `{ "Ref": "AWS::StackId" }`
*
* Example value: `arn:aws:cloudformation:us-east-2:123456789012:stack/mystack-mynestedstack-sggfrhxhum7w/f449b250-b969-11e0-a185-5081d0136786`
* @attribute
*/
get stackId() {
return this._contextualStackId;
}
/**
* Assign a value to one of the nested stack parameters.
* @param name The parameter name (ID)
* @param value The value to assign
*/
setParameter(name, value) {
this.parameters[name] = value;
}
/**
* Defines an asset at the parent stack which represents the template of this
* nested stack.
*
* This private API is used by `App.prepare()` within a loop that rectifies
* references every time an asset is added. This is because (at the moment)
* assets are addressed using CloudFormation parameters.
*
* @returns `true` if a new asset was added or `false` if an asset was
* previously added. When this returns `true`, App will do another reference
* rectification cycle.
*
* @internal
*/
_prepareTemplateAsset() {
if (this._templateUrl) {
return false;
}
// When adding tags to nested stack, the tags need to be added to all the resources in
// in nested stack, which is handled by the `tags` property, But to tag the
// tags have to be added in the parent stack CfnStack resource. The CfnStack resource created
// by this class dont share the same TagManager as that of the one exposed by the `tag` property of the
// class, all the tags need to be copied to the CfnStack resource before synthesizing the resource.
// See https://github.com/aws/aws-cdk/pull/19128
Object.entries(this.tags.tagValues()).forEach(([key, value]) => {
this.resource.tags.setTag(key, value);
});
const cfn = JSON.stringify(this._toCloudFormation());
const templateHash = crypto.createHash('sha256').update(cfn).digest('hex');
const templateLocation = this._parentStack.synthesizer.addFileAsset({
packaging: assets_1.FileAssetPackaging.FILE,
sourceHash: templateHash,
fileName: this.templateFile,
});
this.addResourceMetadata(this.resource, 'TemplateURL');
// if bucketName/objectKey are cfn parameters from a stack other than the parent stack, they will
// be resolved as cross-stack references like any other (see "multi" tests).
this._templateUrl = `https://s3.${this._parentStack.region}.${this._parentStack.urlSuffix}/${templateLocation.bucketName}/${templateLocation.objectKey}`;
return true;
}
contextualAttribute(innerValue, outerValue) {
return token_1.Token.asString({
resolve: (context) => {
if (stack_1.Stack.of(context.scope) === this) {
return innerValue;
}
else {
return outerValue;
}
},
});
}
addResourceMetadata(resource, resourceProperty) {
if (!this.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) {
return; // not enabled
}
// tell tools such as SAM CLI that the "TemplateURL" property of this resource
// points to the nested stack template for local emulation
resource.cfnOptions.metadata = resource.cfnOptions.metadata || {};
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PATH_KEY] = this.templateFile;
resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty;
}
}
exports.NestedStack = NestedStack;
_a = JSII_RTTI_SYMBOL_1;
NestedStack[_a] = { fqn: "@aws-cdk/core.NestedStack", version: "1.204.0" };
/**
* Validates the scope for a nested stack. Nested stacks must be defined within the scope of another `Stack`.
*/
function findParentStack(scope) {
if (!scope) {
throw new Error('Nested stacks cannot be defined as a root construct');
}
const parentStack = constructs_1.Node.of(scope).scopes.reverse().find(p => stack_1.Stack.isStack(p));
if (!parentStack) {
throw new Error('Nested stacks must be defined within scope of another non-nested stack');
}
return parentStack;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVzdGVkLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibmVzdGVkLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGlDQUFpQztBQUNqQyx5Q0FBeUM7QUFDekMsMkNBQTZDO0FBQzdDLHFDQUE4QztBQUM5QyxxQ0FBOEI7QUFDOUIsNkNBQW1DO0FBRW5DLHlFQUFzRDtBQUV0RCxpQ0FBOEI7QUFDOUIsbUNBQWdDO0FBQ2hDLHFEQUFpRDtBQUVqRCxtQ0FBZ0M7QUFDaEMsNkRBQThEO0FBQzlELG1DQUFnQztBQUVoQyxnSEFBZ0g7QUFDaEgsMkJBQTJCO0FBQzNCLHlEQUFnRTtBQUVoRSxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUMsQ0FBQztBQXVEcEU7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFhLFdBQVksU0FBUSxhQUFLO0lBbUJwQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLFFBQTBCLEVBQUc7Ozs7OzsrQ0FuQjVELFdBQVc7Ozs7UUFvQnBCLE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUzQyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTSxFQUFFO1lBQ2pFLFdBQVcsRUFBRSxJQUFJLDJDQUFzQixDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7U0FDakUsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7UUFFaEMsOENBQThDO1FBQzlDLE1BQU0sV0FBVyxHQUFHLElBQUksNEJBQWEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFDO1FBRWxFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFLEVB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QU8sV0FBb0IsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBOb2RlIH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBGaWxlQXNzZXRQYWNrYWdpbmcgfSBmcm9tICcuL2Fzc2V0cyc7XG5pbXBvcnQgeyBGbiB9IGZyb20gJy4vY2ZuLWZuJztcbmltcG9ydCB7IEF3cyB9IGZyb20gJy4vY2ZuLXBzZXVkbyc7XG5pbXBvcnQgeyBDZm5SZXNvdXJjZSB9IGZyb20gJy4vY2ZuLXJlc291cmNlJztcbmltcG9ydCB7IENmblN0YWNrIH0gZnJvbSAnLi9jbG91ZGZvcm1hdGlvbi5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgRHVyYXRpb24gfSBmcm9tICcuL2R1cmF0aW9uJztcbmltcG9ydCB7IExhenkgfSBmcm9tICcuL2xhenknO1xuaW1wb3J0IHsgTmFtZXMgfSBmcm9tICcuL25hbWVzJztcbmltcG9ydCB7IFJlbW92YWxQb2xpY3kgfSBmcm9tICcuL3JlbW92YWwtcG9saWN5JztcbmltcG9ydCB7IElSZXNvbHZlQ29udGV4dCB9IGZyb20gJy4vcmVzb2x2YWJsZSc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJy4vc3RhY2snO1xuaW1wb3J0IHsgTmVzdGVkU3RhY2tTeW50aGVzaXplciB9IGZyb20gJy4vc3RhY2stc3ludGhlc2l6ZXJzJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbi8vIHYyIC0ga2VlcCB0aGlzIGltcG9ydCBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gdG8gcmVkdWNlIG1lcmdlIGNvbmZsaWN0IHdoZW4gZm9yd2FyZCBtZXJnaW5nIHdpdGggdGhlIHYyIGJyYW5jaC5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICcuL2NvbnN0cnVjdC1jb21wYXQnO1xuXG5jb25zdCBORVNURURfU1RBQ0tfU1lNQk9MID0gU3ltYm9sLmZvcignQGF3cy1jZGsvY29yZS5OZXN0ZWRTdGFjaycpO1xuXG4vKipcbiAqIEluaXRpYWxpemF0aW9uIHByb3BzIGZvciB0aGUgYE5lc3RlZFN0YWNrYCBjb25zdHJ1Y3QuXG4gKlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5lc3RlZFN0YWNrUHJvcHMge1xuICAvKipcbiAgICogVGhlIHNldCB2YWx1ZSBwYWlycyB0aGF0IHJlcHJlc2VudCB0aGUgcGFyYW1ldGVycyBwYXNzZWQgdG8gQ2xvdWRGb3JtYXRpb25cbiAgICogd2hlbiB0aGlzIG5lc3RlZCBzdGFjayBpcyBjcmVhdGVkLiBFYWNoIHBhcmFtZXRlciBoYXMgYSBuYW1lIGNvcnJlc3BvbmRpbmdcbiAgICogdG8gYSBwYXJhbWV0ZXIgZGVmaW5lZCBpbiB0aGUgZW1iZWRkZWQgdGVtcGxhdGUgYW5kIGEgdmFsdWUgcmVwcmVzZW50aW5nXG4gICAqIHRoZSB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIHNldCBmb3IgdGhlIHBhcmFtZXRlci5cbiAgICpcbiAgICogVGhlIG5lc3RlZCBzdGFjayBjb25zdHJ1Y3Qgd2lsbCBhdXRvbWF0aWNhbGx5IHN5bnRoZXNpemUgcGFyYW1ldGVycyBpbiBvcmRlclxuICAgKiB0byBiaW5kIHJlZmVyZW5jZXMgZnJvbSB0aGUgcGFyZW50IHN0YWNrKHMpIGludG8gdGhlIG5lc3RlZCBzdGFjay5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB1c2VyLWRlZmluZWQgcGFyYW1ldGVycyBhcmUgcGFzc2VkIHRvIHRoZSBuZXN0ZWQgc3RhY2tcbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgbGVuZ3RoIG9mIHRpbWUgdGhhdCBDbG91ZEZvcm1hdGlvbiB3YWl0cyBmb3IgdGhlIG5lc3RlZCBzdGFjayB0byByZWFjaFxuICAgKiB0aGUgQ1JFQVRFX0NPTVBMRVRFIHN0YXRlLlxuICAgKlxuICAgKiBXaGVuIENsb3VkRm9ybWF0aW9uIGRldGVjdHMgdGhhdCB0aGUgbmVzdGVkIHN0YWNrIGhhcyByZWFjaGVkIHRoZVxuICAgKiBDUkVBVEVfQ09NUExFVEUgc3RhdGUsIGl0IG1hcmtzIHRoZSBuZXN0ZWQgc3RhY2sgcmVzb3VyY2UgYXNcbiAgICogQ1JFQVRFX0NPTVBMRVRFIGluIHRoZSBwYXJlbnQgc3RhY2sgYW5kIHJlc3VtZXMgY3JlYXRpbmcgdGhlIHBhcmVudCBzdGFjay5cbiAgICogSWYgdGhlIHRpbWVvdXQgcGVyaW9kIGV4cGlyZXMgYmVmb3JlIHRoZSBuZXN0ZWQgc3RhY2sgcmVhY2hlc1xuICAgKiBDUkVBVEVfQ09NUExFVEUsIENsb3VkRm9ybWF0aW9uIG1hcmtzIHRoZSBuZXN0ZWQgc3RhY2sgYXMgZmFpbGVkIGFuZCByb2xsc1xuICAgKiBiYWNrIGJvdGggdGhlIG5lc3RlZCBzdGFjayBhbmQgcGFyZW50IHN0YWNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRpbWVvdXRcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogVGhlIFNpbXBsZSBOb3RpZmljYXRpb24gU2VydmljZSAoU05TKSB0b3BpY3MgdG8gcHVibGlzaCBzdGFjayByZWxhdGVkXG4gICAqIGV2ZW50cy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub3RpZmljYXRpb25zIGFyZSBub3Qgc2VudCBmb3IgdGhpcyBzdGFjay5cbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmaWNhdGlvbkFybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogUG9saWN5IHRvIGFwcGx5IHdoZW4gdGhlIG5lc3RlZCBzdGFjayBpcyByZW1vdmVkXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IGlzIGBEZXN0cm95YCwgYmVjYXVzZSBhbGwgUmVtb3ZhbCBQb2xpY2llcyBvZiByZXNvdXJjZXMgaW5zaWRlIHRoZVxuICAgKiBOZXN0ZWQgU3RhY2sgc2hvdWxkIGFscmVhZHkgaGF2ZSBiZWVuIHNldCBjb3JyZWN0bHkuIFlvdSBub3JtYWxseSBzaG91bGRcbiAgICogbm90IG5lZWQgdG8gc2V0IHRoaXMgdmFsdWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG59XG5cbi8qKlxuICogQSBDbG91ZEZvcm1hdGlvbiBuZXN0ZWQgc3RhY2suXG4gKlxuICogV2hlbiB5b3UgYXBwbHkgdGVtcGxhdGUgY2hhbmdlcyB0byB1cGRhdGUgYSB0b3AtbGV2ZWwgc3RhY2ssIENsb3VkRm9ybWF0aW9uXG4gKiB1cGRhdGVzIHRoZSB0b3AtbGV2ZWwgc3RhY2sgYW5kIGluaXRpYXRlcyBhbiB1cGRhdGUgdG8gaXRzIG5lc3RlZCBzdGFja3MuXG4gKiBDbG91ZEZvcm1hdGlvbiB1cGRhdGVzIHRoZSByZXNvdXJjZXMgb2YgbW9kaWZpZWQgbmVzdGVkIHN0YWNrcywgYnV0IGRvZXMgbm90XG4gKiB1cGRhdGUgdGhlIHJlc291cmNlcyBvZiB1bm1vZGlmaWVkIG5lc3RlZCBzdGFja3MuXG4gKlxuICogRnVydGhlcm1vcmUsIHRoaXMgc3RhY2sgd2lsbCBub3QgYmUgdHJlYXRlZCBhcyBhbiBpbmRlcGVuZGVudCBkZXBsb3ltZW50XG4gKiBhcnRpZmFjdCAod29uJ3QgYmUgbGlzdGVkIGluIFwiY2RrIGxpc3RcIiBvciBkZXBsb3lhYmxlIHRocm91Z2ggXCJjZGsgZGVwbG95XCIpLFxuICogYnV0IHJhdGhlciBvbmx5IHN5bnRoZXNpemVkIGFzIGEgdGVtcGxhdGUgYW5kIHVwbG9hZGVkIGFzIGFuIGFzc2V0IHRvIFMzLlxuICpcbiAqIENyb3NzIHJlZmVyZW5jZXMgb2YgcmVzb3VyY2UgYXR0cmlidXRlcyBiZXR3ZWVuIHRoZSBwYXJlbnQgc3RhY2sgYW5kIHRoZVxuICogbmVzdGVkIHN0YWNrIHdpbGwgYXV0b21hdGljYWxseSBiZSB0cmFuc2xhdGVkIHRvIHN0YWNrIHBhcmFtZXRlcnMgYW5kXG4gKiBvdXRwdXRzLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIE5lc3RlZFN0YWNrIGV4dGVuZHMgU3RhY2sge1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYHhgIGlzIGFuIG9iamVjdCBvZiB0eXBlIGBOZXN0ZWRTdGFja2AuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGlzTmVzdGVkU3RhY2soeDogYW55KTogeCBpcyBOZXN0ZWRTdGFjayB7XG4gICAgcmV0dXJuIHggIT0gbnVsbCAmJiB0eXBlb2YoeCkgPT09ICdvYmplY3QnICYmIE5FU1RFRF9TVEFDS19TWU1CT0wgaW4geDtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSB0ZW1wbGF0ZUZpbGU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IG5lc3RlZFN0YWNrUmVzb3VyY2U/OiBDZm5SZXNvdXJjZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtZXRlcnM6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlOiBDZm5TdGFjaztcbiAgcHJpdmF0ZSByZWFkb25seSBfY29udGV4dHVhbFN0YWNrSWQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBfY29udGV4dHVhbFN0YWNrTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIF90ZW1wbGF0ZVVybD86IHN0cmluZztcbiAgcHJpdmF0ZSBfcGFyZW50U3RhY2s6IFN0YWNrO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBOZXN0ZWRTdGFja1Byb3BzID0geyB9KSB7XG4gICAgY29uc3QgcGFyZW50U3RhY2sgPSBmaW5kUGFyZW50U3RhY2soc2NvcGUpO1xuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBlbnY6IHsgYWNjb3VudDogcGFyZW50U3RhY2suYWNjb3VudCwgcmVnaW9uOiBwYXJlbnRTdGFjay5yZWdpb24gfSxcbiAgICAgIHN5bnRoZXNpemVyOiBuZXcgTmVzdGVkU3RhY2tTeW50aGVzaXplcihwYXJlbnRTdGFjay5zeW50aGVzaXplciksXG4gICAgfSk7XG5cbiAgICB0aGlzLl9wYXJlbnRTdGFjayA9IHBhcmVudFN0YWNrO1xuXG4gICAgLy8gQGRlcHJlY2F0ZTogcmVtb3ZlIHRoaXMgaW4gdjIuMCAocmVkdW5kZW50KVxuICAgIGNvbnN0IHBhcmVudFNjb3BlID0gbmV3IENvcmVDb25zdHJ1Y3Qoc2NvcGUsIGlkICsgJy5OZXN0ZWRTdGFjaycpO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIE5FU1RFRF9TVEFDS19TWU1CT0wsIHsgdmFsdWU6IHRydWUgfSk7XG5cbiAgICAvLyB0aGlzIGlzIHRoZSBmaWxlIG5hbWUgb2YgdGhlIHN5bnRoZXNpemVkIHRlbXBsYXRlIGZpbGUgd2l0aGluIHRoZSBjbG91ZCBhc3NlbWJseVxuICAgIHRoaXMudGVtcGxhdGVGaWxlID0gYCR7TmFtZXMudW5pcXVlSWQodGhpcyl9Lm5lc3RlZC50ZW1wbGF0ZS5qc29uYDtcblxuICAgIHRoaXMucGFyYW1ldGVycyA9IHByb3BzLnBhcmFtZXRlcnMgfHwge307XG5cbiAgICB0aGlzLnJlc291cmNlID0gbmV3IENmblN0YWNrKHBhcmVudFNjb3BlLCBgJHtpZH0uTmVzdGVkU3RhY2tSZXNvdXJjZWAsIHtcbiAgICAgIC8vIFRoaXMgdmFsdWUgY2Fubm90IGJlIGNhY2hlZCBzaW5jZSBpdCBjaGFuZ2VzIGR1cmluZyB0aGUgc3ludGhlc2lzIHBoYXNlXG4gICAgICB0ZW1wbGF0ZVVybDogTGF6eS51bmNhY2hlZFN0cmluZyh7IHByb2R1Y2U6ICgpID0+IHRoaXMuX3RlbXBsYXRlVXJsIHx8ICc8dW5yZXNvbHZlZD4nIH0pLFxuICAgICAgcGFyYW1ldGVyczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiBPYmplY3Qua2V5cyh0aGlzLnBhcmFtZXRlcnMpLmxlbmd0aCA+IDAgPyB0aGlzLnBhcmFtZXRlcnMgOiB1bmRlZmluZWQgfSksXG4gICAgICBub3RpZmljYXRpb25Bcm5zOiBwcm9wcy5ub3RpZmljYXRpb25Bcm5zLFxuICAgICAgdGltZW91dEluTWludXRlczogcHJvcHMudGltZW91dCA/IHByb3BzLnRpbWVvdXQudG9NaW51dGVzKCkgOiB1bmRlZmluZWQsXG4gICAgfSk7XG4gICAgdGhpcy5yZXNvdXJjZS5hcHBseVJlbW92YWxQb2xpY3kocHJvcHMucmVtb3ZhbFBvbGljeSA/PyBSZW1vdmFsUG9saWN5LkRFU1RST1kpO1xuXG4gICAgdGhpcy5uZXN0ZWRTdGFja1Jlc291cmNlID0gdGhpcy5yZXNvdXJjZTtcbiAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkID0gdGhpcy5yZXNvdXJjZTtcblxuICAgIC8vIGNvbnRleHQtYXdhcmUgc3RhY2sgbmFtZTogaWYgcmVzb2x2ZWQgZnJvbSB3aXRoaW4gdGhpcyBzdGFjaywgcmV0dXJuIEFXUzo6U3RhY2tOYW1lXG4gICAgLy8gaWYgcmVzb2x2ZWQgZnJvbSB0aGUgb3V0ZXIgc3RhY2ssIHVzZSB0aGUgeyBSZWYgfSBvZiB0aGUgQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2sgcmVzb3VyY2VcbiAgICAvLyB3aGljaCByZXNvbHZlcyB0aGUgQVJOIG9mIHRoZSBzdGFjay4gV2UgbmVlZCB0byBleHRyYWN0IHRoZSBzdGFjayBuYW1lLCB3aGljaCBpcyB0aGUgc2Vjb25kXG4gICAgLy8gY29tcG9uZW50IGFmdGVyIHNwbGl0dGluZyBieSBcIi9cIlxuICAgIHRoaXMuX2NvbnRleHR1YWxTdGFja05hbWUgPSB0aGlzLmNvbnRleHR1YWxBdHRyaWJ1dGUoQXdzLlNUQUNLX05BTUUsIEZuLnNlbGVjdCgxLCBGbi5zcGxpdCgnLycsIHRoaXMucmVzb3VyY2UucmVmKSkpO1xuICAgIHRoaXMuX2NvbnRleHR1YWxTdGFja0lkID0gdGhpcy5jb250ZXh0dWFsQXR0cmlidXRlKEF3cy5TVEFDS19JRCwgdGhpcy5yZXNvdXJjZS5yZWYpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGF0dHJpYnV0ZSB0aGF0IHJlcHJlc2VudHMgdGhlIG5hbWUgb2YgdGhlIG5lc3RlZCBzdGFjay5cbiAgICpcbiAgICogVGhpcyBpcyBhIGNvbnRleHQgYXdhcmUgYXR0cmlidXRlOlxuICAgKiAtIElmIHRoaXMgaXMgcmVmZXJlbmNlZCBmcm9tIHRoZSBwYXJlbnQgc3RhY2ssIGl0IHdpbGwgcmV0dXJuIGEgdG9rZW4gdGhhdCBwYXJzZXMgdGhlIG5hbWUgZnJvbSB0aGUgc3RhY2sgSUQuXG4gICAqIC0gSWYgdGhpcyBpcyByZWZlcmVuY2VkIGZyb20gdGhlIGNvbnRleHQgb2YgdGhlIG5lc3RlZCBzdGFjaywgaXQgd2lsbCByZXR1cm4gYHsgXCJSZWZcIjogXCJBV1M6OlN0YWNrTmFtZVwiIH1gXG4gICAqXG4gICAqIEV4YW1wbGUgdmFsdWU6IGBteXN0YWNrLW15bmVzdGVkc3RhY2stc2dnZnJoeGh1bTd3YFxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWNrTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29udGV4dHVhbFN0YWNrTmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBhdHRyaWJ1dGUgdGhhdCByZXByZXNlbnRzIHRoZSBJRCBvZiB0aGUgc3RhY2suXG4gICAqXG4gICAqIFRoaXMgaXMgYSBjb250ZXh0IGF3YXJlIGF0dHJpYnV0ZTpcbiAgICogLSBJZiB0aGlzIGlzIHJlZmVyZW5jZWQgZnJvbSB0aGUgcGFyZW50IHN0YWNrLCBpdCB3aWxsIHJldHVybiBgeyBcIlJlZlwiOiBcIkxvZ2ljYWxJZE9mTmVzdGVkU3RhY2tSZXNvdXJjZVwiIH1gLlxuICAgKiAtIElmIHRoaXMgaXMgcmVmZXJlbmNlZCBmcm9tIHRoZSBjb250ZXh0IG9mIHRoZSBuZXN0ZWQgc3RhY2ssIGl0IHdpbGwgcmV0dXJuIGB7IFwiUmVmXCI6IFwiQVdTOjpTdGFja0lkXCIgfWBcbiAgICpcbiAgICogRXhhbXBsZSB2YWx1ZTogYGFybjphd3M6Y2xvdWRmb3JtYXRpb246dXMtZWFzdC0yOjEyMzQ1Njc4OTAxMjpzdGFjay9teXN0YWNrLW15bmVzdGVkc3RhY2stc2dnZnJoeGh1bTd3L2Y0NDliMjUwLWI5NjktMTFlMC1hMTg1LTUwODFkMDEzNjc4NmBcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGdldCBzdGFja0lkKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250ZXh0dWFsU3RhY2tJZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ24gYSB2YWx1ZSB0byBvbmUgb2YgdGhlIG5lc3RlZCBzdGFjayBwYXJhbWV0ZXJzLlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgcGFyYW1ldGVyIG5hbWUgKElEKVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnblxuICAgKi9cbiAgcHVibGljIHNldFBhcmFtZXRlcihuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLnBhcmFtZXRlcnNbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGFuIGFzc2V0IGF0IHRoZSBwYXJlbnQgc3RhY2sgd2hpY2ggcmVwcmVzZW50cyB0aGUgdGVtcGxhdGUgb2YgdGhpc1xuICAgKiBuZXN0ZWQgc3RhY2suXG4gICAqXG4gICAqIFRoaXMgcHJpdmF0ZSBBUEkgaXMgdXNlZCBieSBgQXBwLnByZXBhcmUoKWAgd2l0aGluIGEgbG9vcCB0aGF0IHJlY3RpZmllc1xuICAgKiByZWZlcmVuY2VzIGV2ZXJ5IHRpbWUgYW4gYXNzZXQgaXMgYWRkZWQuIFRoaXMgaXMgYmVjYXVzZSAoYXQgdGhlIG1vbWVudClcbiAgICogYXNzZXRzIGFyZSBhZGRyZXNzZWQgdXNpbmcgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVycy5cbiAgICpcbiAgICogQHJldHVybnMgYHRydWVgIGlmIGEgbmV3IGFzc2V0IHdhcyBhZGRlZCBvciBgZmFsc2VgIGlmIGFuIGFzc2V0IHdhc1xuICAgKiBwcmV2aW91c2x5IGFkZGVkLiBXaGVuIHRoaXMgcmV0dXJucyBgdHJ1ZWAsIEFwcCB3aWxsIGRvIGFub3RoZXIgcmVmZXJlbmNlXG4gICAqIHJlY3RpZmljYXRpb24gY3ljbGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9wcmVwYXJlVGVtcGxhdGVBc3NldCgpIHtcbiAgICBpZiAodGhpcy5fdGVtcGxhdGVVcmwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBXaGVuIGFkZGluZyB0YWdzIHRvIG5lc3RlZCBzdGFjaywgdGhlIHRhZ3MgbmVlZCB0byBiZSBhZGRlZCB0byBhbGwgdGhlIHJlc291cmNlcyBpblxuICAgIC8vIGluIG5lc3RlZCBzdGFjaywgd2hpY2ggaXMgaGFuZGxlZCBieSB0aGUgYHRhZ3NgIHByb3BlcnR5LCBCdXQgdG8gdGFnIHRoZVxuICAgIC8vICB0YWdzIGhhdmUgdG8gYmUgYWRkZWQgaW4gdGhlIHBhcmVudCBzdGFjayBDZm5TdGFjayByZXNvdXJjZS4gVGhlIENmblN0YWNrIHJlc291cmNlIGNyZWF0ZWRcbiAgICAvLyBieSB0aGlzIGNsYXNzIGRvbnQgc2hhcmUgdGhlIHNhbWUgVGFnTWFuYWdlciBhcyB0aGF0IG9mIHRoZSBvbmUgZXhwb3NlZCBieSB0aGUgYHRhZ2AgcHJvcGVydHkgb2YgdGhlXG4gICAgLy8gIGNsYXNzLCBhbGwgdGhlIHRhZ3MgbmVlZCB0byBiZSBjb3BpZWQgdG8gdGhlIENmblN0YWNrIHJlc291cmNlIGJlZm9yZSBzeW50aGVzaXppbmcgdGhlIHJlc291cmNlLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvcHVsbC8xOTEyOFxuICAgIE9iamVjdC5lbnRyaWVzKHRoaXMudGFncy50YWdWYWx1ZXMoKSkuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICB0aGlzLnJlc291cmNlLnRhZ3Muc2V0VGFnKGtleSwgdmFsdWUpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2ZuID0gSlNPTi5zdHJpbmdpZnkodGhpcy5fdG9DbG91ZEZvcm1hdGlvbigpKTtcbiAgICBjb25zdCB0ZW1wbGF0ZUhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGNmbikuZGlnZXN0KCdoZXgnKTtcblxuICAgIGNvbnN0IHRlbXBsYXRlTG9jYXRpb24gPSB0aGlzLl9wYXJlbnRTdGFjay5zeW50aGVzaXplci5hZGRGaWxlQXNzZXQoe1xuICAgICAgcGFja2FnaW5nOiBGaWxlQXNzZXRQYWNrYWdpbmcuRklMRSxcbiAgICAgIHNvdXJjZUhhc2g6IHRlbXBsYXRlSGFzaCxcbiAgICAgIGZpbGVOYW1lOiB0aGlzLnRlbXBsYXRlRmlsZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkUmVzb3VyY2VNZXRhZGF0YSh0aGlzLnJlc291cmNlLCAnVGVtcGxhdGVVUkwnKTtcblxuICAgIC8vIGlmIGJ1Y2tldE5hbWUvb2JqZWN0S2V5IGFyZSBjZm4gcGFyYW1ldGVycyBmcm9tIGEgc3RhY2sgb3RoZXIgdGhhbiB0aGUgcGFyZW50IHN0YWNrLCB0aGV5IHdpbGxcbiAgICAvLyBiZSByZXNvbHZlZCBhcyBjcm9zcy1zdGFjayByZWZlcmVuY2VzIGxpa2UgYW55IG90aGVyIChzZWUgXCJtdWx0aVwiIHRlc3RzKS5cbiAgICB0aGlzLl90ZW1wbGF0ZVVybCA9IGBodHRwczovL3MzLiR7dGhpcy5fcGFyZW50U3RhY2sucmVnaW9ufS4ke3RoaXMuX3BhcmVudFN0YWNrLnVybFN1ZmZpeH0vJHt0ZW1wbGF0ZUxvY2F0aW9uLmJ1Y2tldE5hbWV9LyR7dGVtcGxhdGVMb2NhdGlvbi5vYmplY3RLZXl9YDtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgY29udGV4dHVhbEF0dHJpYnV0ZShpbm5lclZhbHVlOiBzdHJpbmcsIG91dGVyVmFsdWU6IHN0cmluZykge1xuICAgIHJldHVybiBUb2tlbi5hc1N0cmluZyh7XG4gICAgICByZXNvbHZlOiAoY29udGV4dDogSVJlc29sdmVDb250ZXh0KSA9PiB7XG4gICAgICAgIGlmIChTdGFjay5vZihjb250ZXh0LnNjb3BlKSA9PT0gdGhpcykge1xuICAgICAgICAgIHJldHVybiBpbm5lclZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBvdXRlclZhbHVlO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRSZXNvdXJjZU1ldGFkYXRhKHJlc291cmNlOiBDZm5SZXNvdXJjZSwgcmVzb3VyY2VQcm9wZXJ0eTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLm5vZGUudHJ5R2V0Q29udGV4dChjeGFwaS5BU1NFVF9SRVNPVVJDRV9NRVRBREFUQV9FTkFCTEVEX0NPTlRFWFQpKSB7XG4gICAgICByZXR1cm47IC8vIG5vdCBlbmFibGVkXG4gICAgfVxuXG4gICAgLy8gdGVsbCB0b29scyBzdWNoIGFzIFNBTSBDTEkgdGhhdCB0aGUgXCJUZW1wbGF0ZVVSTFwiIHByb3BlcnR5IG9mIHRoaXMgcmVzb3VyY2VcbiAgICAvLyBwb2ludHMgdG8gdGhlIG5lc3RlZCBzdGFjayB0ZW1wbGF0ZSBmb3IgbG9jYWwgZW11bGF0aW9uXG4gICAgcmVzb3VyY2UuY2ZuT3B0aW9ucy5tZXRhZGF0YSA9IHJlc291cmNlLmNmbk9wdGlvbnMubWV0YWRhdGEgfHwgeyB9O1xuICAgIHJlc291cmNlLmNmbk9wdGlvbnMubWV0YWRhdGFbY3hhcGkuQVNTRVRfUkVTT1VSQ0VfTUVUQURBVEFfUEFUSF9LRVldID0gdGhpcy50ZW1wbGF0ZUZpbGU7XG4gICAgcmVzb3VyY2UuY2ZuT3B0aW9ucy5tZXRhZGF0YVtjeGFwaS5BU1NFVF9SRVNPVVJDRV9NRVRBREFUQV9QUk9QRVJUWV9LRVldID0gcmVzb3VyY2VQcm9wZXJ0eTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyB0aGUgc2NvcGUgZm9yIGEgbmVzdGVkIHN0YWNrLiBOZXN0ZWQgc3RhY2tzIG11c3QgYmUgZGVmaW5lZCB3aXRoaW4gdGhlIHNjb3BlIG9mIGFub3RoZXIgYFN0YWNrYC5cbiAqL1xuZnVuY3Rpb24gZmluZFBhcmVudFN0YWNrKHNjb3BlOiBDb25zdHJ1Y3QpOiBTdGFjayB7XG4gIGlmICghc2NvcGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05lc3RlZCBzdGFja3MgY2Fubm90IGJlIGRlZmluZWQgYXMgYSByb290IGNvbnN0cnVjdCcpO1xuICB9XG5cbiAgY29uc3QgcGFyZW50U3RhY2sgPSBOb2RlLm9mKHNjb3BlKS5zY29wZXMucmV2ZXJzZSgpLmZpbmQocCA9PiBTdGFjay5pc1N0YWNrKHApKTtcbiAgaWYgKCFwYXJlbnRTdGFjaykge1xuICAgIHRocm93IG5ldyBFcnJvcignTmVzdGVkIHN0YWNrcyBtdXN0IGJlIGRlZmluZWQgd2l0aGluIHNjb3BlIG9mIGFub3RoZXIgbm9uLW5lc3RlZCBzdGFjaycpO1xuICB9XG5cbiAgcmV0dXJuIHBhcmVudFN0YWNrIGFzIFN0YWNrO1xufVxuIl19