1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.NestedStack = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const crypto = require("crypto");
|
8 | const cxapi = require("@aws-cdk/cx-api");
|
9 | const constructs_1 = require("constructs");
|
10 | const assets_1 = require("./assets");
|
11 | const cfn_fn_1 = require("./cfn-fn");
|
12 | const cfn_pseudo_1 = require("./cfn-pseudo");
|
13 | const cloudformation_generated_1 = require("./cloudformation.generated");
|
14 | const lazy_1 = require("./lazy");
|
15 | const names_1 = require("./names");
|
16 | const removal_policy_1 = require("./removal-policy");
|
17 | const stack_1 = require("./stack");
|
18 | const stack_synthesizers_1 = require("./stack-synthesizers");
|
19 | const token_1 = require("./token");
|
20 | // v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
|
21 | // eslint-disable-next-line
|
22 | const construct_compat_1 = require("./construct-compat");
|
23 | const NESTED_STACK_SYMBOL = Symbol.for('@aws-cdk/core.NestedStack');
|
24 | /**
|
25 | * A CloudFormation nested stack.
|
26 | *
|
27 | * When you apply template changes to update a top-level stack, CloudFormation
|
28 | * updates the top-level stack and initiates an update to its nested stacks.
|
29 | * CloudFormation updates the resources of modified nested stacks, but does not
|
30 | * update the resources of unmodified nested stacks.
|
31 | *
|
32 | * Furthermore, this stack will not be treated as an independent deployment
|
33 | * artifact (won't be listed in "cdk list" or deployable through "cdk deploy"),
|
34 | * but rather only synthesized as a template and uploaded as an asset to S3.
|
35 | *
|
36 | * Cross references of resource attributes between the parent stack and the
|
37 | * nested stack will automatically be translated to stack parameters and
|
38 | * outputs.
|
39 | *
|
40 | */
|
41 | class NestedStack extends stack_1.Stack {
|
42 | constructor(scope, id, props = {}) {
|
43 | try {
|
44 | jsiiDeprecationWarnings._aws_cdk_core_NestedStackProps(props);
|
45 | }
|
46 | catch (error) {
|
47 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
48 | Error.captureStackTrace(error, NestedStack);
|
49 | }
|
50 | throw error;
|
51 | }
|
52 | const parentStack = findParentStack(scope);
|
53 | super(scope, id, {
|
54 | env: { account: parentStack.account, region: parentStack.region },
|
55 | synthesizer: new stack_synthesizers_1.NestedStackSynthesizer(parentStack.synthesizer),
|
56 | });
|
57 | this._parentStack = parentStack;
|
58 | // @deprecate: remove this in v2.0 (redundent)
|
59 | const parentScope = new construct_compat_1.Construct(scope, id + '.NestedStack');
|
60 | Object.defineProperty(this, NESTED_STACK_SYMBOL, { value: true });
|
61 | // this is the file name of the synthesized template file within the cloud assembly
|
62 | this.templateFile = `${names_1.Names.uniqueId(this)}.nested.template.json`;
|
63 | this.parameters = props.parameters || {};
|
64 | this.resource = new cloudformation_generated_1.CfnStack(parentScope, `${id}.NestedStackResource`, {
|
65 | // This value cannot be cached since it changes during the synthesis phase
|
66 | templateUrl: lazy_1.Lazy.uncachedString({ produce: () => this._templateUrl || '<unresolved>' }),
|
67 | parameters: lazy_1.Lazy.any({ produce: () => Object.keys(this.parameters).length > 0 ? this.parameters : undefined }),
|
68 | notificationArns: props.notificationArns,
|
69 | timeoutInMinutes: props.timeout ? props.timeout.toMinutes() : undefined,
|
70 | });
|
71 | this.resource.applyRemovalPolicy(props.removalPolicy ?? removal_policy_1.RemovalPolicy.DESTROY);
|
72 | this.nestedStackResource = this.resource;
|
73 | this.node.defaultChild = this.resource;
|
74 | // context-aware stack name: if resolved from within this stack, return AWS::StackName
|
75 | // if resolved from the outer stack, use the { Ref } of the AWS::CloudFormation::Stack resource
|
76 | // which resolves the ARN of the stack. We need to extract the stack name, which is the second
|
77 | // component after splitting by "/"
|
78 | this._contextualStackName = this.contextualAttribute(cfn_pseudo_1.Aws.STACK_NAME, cfn_fn_1.Fn.select(1, cfn_fn_1.Fn.split('/', this.resource.ref)));
|
79 | this._contextualStackId = this.contextualAttribute(cfn_pseudo_1.Aws.STACK_ID, this.resource.ref);
|
80 | }
|
81 | /**
|
82 | * Checks if `x` is an object of type `NestedStack`.
|
83 | */
|
84 | static isNestedStack(x) {
|
85 | return x != null && typeof (x) === 'object' && NESTED_STACK_SYMBOL in x;
|
86 | }
|
87 | /**
|
88 | * An attribute that represents the name of the nested stack.
|
89 | *
|
90 | * This is a context aware attribute:
|
91 | * - If this is referenced from the parent stack, it will return a token that parses the name from the stack ID.
|
92 | * - If this is referenced from the context of the nested stack, it will return `{ "Ref": "AWS::StackName" }`
|
93 | *
|
94 | * Example value: `mystack-mynestedstack-sggfrhxhum7w`
|
95 | * @attribute
|
96 | */
|
97 | get stackName() {
|
98 | return this._contextualStackName;
|
99 | }
|
100 | /**
|
101 | * An attribute that represents the ID of the stack.
|
102 | *
|
103 | * This is a context aware attribute:
|
104 | * - If this is referenced from the parent stack, it will return `{ "Ref": "LogicalIdOfNestedStackResource" }`.
|
105 | * - If this is referenced from the context of the nested stack, it will return `{ "Ref": "AWS::StackId" }`
|
106 | *
|
107 | * Example value: `arn:aws:cloudformation:us-east-2:123456789012:stack/mystack-mynestedstack-sggfrhxhum7w/f449b250-b969-11e0-a185-5081d0136786`
|
108 | * @attribute
|
109 | */
|
110 | get stackId() {
|
111 | return this._contextualStackId;
|
112 | }
|
113 | /**
|
114 | * Assign a value to one of the nested stack parameters.
|
115 | * @param name The parameter name (ID)
|
116 | * @param value The value to assign
|
117 | */
|
118 | setParameter(name, value) {
|
119 | this.parameters[name] = value;
|
120 | }
|
121 | /**
|
122 | * Defines an asset at the parent stack which represents the template of this
|
123 | * nested stack.
|
124 | *
|
125 | * This private API is used by `App.prepare()` within a loop that rectifies
|
126 | * references every time an asset is added. This is because (at the moment)
|
127 | * assets are addressed using CloudFormation parameters.
|
128 | *
|
129 | * @returns `true` if a new asset was added or `false` if an asset was
|
130 | * previously added. When this returns `true`, App will do another reference
|
131 | * rectification cycle.
|
132 | *
|
133 | * @internal
|
134 | */
|
135 | _prepareTemplateAsset() {
|
136 | if (this._templateUrl) {
|
137 | return false;
|
138 | }
|
139 | // When adding tags to nested stack, the tags need to be added to all the resources in
|
140 | // in nested stack, which is handled by the `tags` property, But to tag the
|
141 | // tags have to be added in the parent stack CfnStack resource. The CfnStack resource created
|
142 | // by this class dont share the same TagManager as that of the one exposed by the `tag` property of the
|
143 | // class, all the tags need to be copied to the CfnStack resource before synthesizing the resource.
|
144 | // See https://github.com/aws/aws-cdk/pull/19128
|
145 | Object.entries(this.tags.tagValues()).forEach(([key, value]) => {
|
146 | this.resource.tags.setTag(key, value);
|
147 | });
|
148 | const cfn = JSON.stringify(this._toCloudFormation());
|
149 | const templateHash = crypto.createHash('sha256').update(cfn).digest('hex');
|
150 | const templateLocation = this._parentStack.synthesizer.addFileAsset({
|
151 | packaging: assets_1.FileAssetPackaging.FILE,
|
152 | sourceHash: templateHash,
|
153 | fileName: this.templateFile,
|
154 | });
|
155 | this.addResourceMetadata(this.resource, 'TemplateURL');
|
156 | // if bucketName/objectKey are cfn parameters from a stack other than the parent stack, they will
|
157 | // be resolved as cross-stack references like any other (see "multi" tests).
|
158 | this._templateUrl = `https://s3.${this._parentStack.region}.${this._parentStack.urlSuffix}/${templateLocation.bucketName}/${templateLocation.objectKey}`;
|
159 | return true;
|
160 | }
|
161 | contextualAttribute(innerValue, outerValue) {
|
162 | return token_1.Token.asString({
|
163 | resolve: (context) => {
|
164 | if (stack_1.Stack.of(context.scope) === this) {
|
165 | return innerValue;
|
166 | }
|
167 | else {
|
168 | return outerValue;
|
169 | }
|
170 | },
|
171 | });
|
172 | }
|
173 | addResourceMetadata(resource, resourceProperty) {
|
174 | if (!this.node.tryGetContext(cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT)) {
|
175 | return; // not enabled
|
176 | }
|
177 | // tell tools such as SAM CLI that the "TemplateURL" property of this resource
|
178 | // points to the nested stack template for local emulation
|
179 | resource.cfnOptions.metadata = resource.cfnOptions.metadata || {};
|
180 | resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PATH_KEY] = this.templateFile;
|
181 | resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty;
|
182 | }
|
183 | }
|
184 | exports.NestedStack = NestedStack;
|
185 | _a = JSII_RTTI_SYMBOL_1;
|
186 | NestedStack[_a] = { fqn: "@aws-cdk/core.NestedStack", version: "1.204.0" };
|
187 | /**
|
188 | * Validates the scope for a nested stack. Nested stacks must be defined within the scope of another `Stack`.
|
189 | */
|
190 | function findParentStack(scope) {
|
191 | if (!scope) {
|
192 | throw new Error('Nested stacks cannot be defined as a root construct');
|
193 | }
|
194 | const parentStack = constructs_1.Node.of(scope).scopes.reverse().find(p => stack_1.Stack.isStack(p));
|
195 | if (!parentStack) {
|
196 | throw new Error('Nested stacks must be defined within scope of another non-nested stack');
|
197 | }
|
198 | return parentStack;
|
199 | }
|
200 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmVzdGVkLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibmVzdGVkLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGlDQUFpQztBQUNqQyx5Q0FBeUM7QUFDekMsMkNBQTZDO0FBQzdDLHFDQUE4QztBQUM5QyxxQ0FBOEI7QUFDOUIsNkNBQW1DO0FBRW5DLHlFQUFzRDtBQUV0RCxpQ0FBOEI7QUFDOUIsbUNBQWdDO0FBQ2hDLHFEQUFpRDtBQUVqRCxtQ0FBZ0M7QUFDaEMsNkRBQThEO0FBQzlELG1DQUFnQztBQUVoQyxnSEFBZ0g7QUFDaEgsMkJBQTJCO0FBQzNCLHlEQUFnRTtBQUVoRSxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUMsQ0FBQztBQXVEcEU7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFhLFdBQVksU0FBUSxhQUFLO0lBbUJwQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLFFBQTBCLEVBQUc7Ozs7OzsrQ0FuQjVELFdBQVc7Ozs7UUFvQnBCLE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUzQyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLENBQUMsTUFBTSxFQUFFO1lBQ2pFLFdBQVcsRUFBRSxJQUFJLDJDQUFzQixDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7U0FDakUsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7UUFFaEMsOENBQThDO1FBQzlDLE1BQU0sV0FBVyxHQUFHLElBQUksNEJBQWEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFDO1FBRWxFLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFLEVB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QU8sV0FBb0IsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBOb2RlIH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBGaWxlQXNzZXRQYWNrYWdpbmcgfSBmcm9tICcuL2Fzc2V0cyc7XG5pbXBvcnQgeyBGbiB9IGZyb20gJy4vY2ZuLWZuJztcbmltcG9ydCB7IEF3cyB9IGZyb20gJy4vY2ZuLXBzZXVkbyc7XG5pbXBvcnQgeyBDZm5SZXNvdXJjZSB9IGZyb20gJy4vY2ZuLXJlc291cmNlJztcbmltcG9ydCB7IENmblN0YWNrIH0gZnJvbSAnLi9jbG91ZGZvcm1hdGlvbi5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgRHVyYXRpb24gfSBmcm9tICcuL2R1cmF0aW9uJztcbmltcG9ydCB7IExhenkgfSBmcm9tICcuL2xhenknO1xuaW1wb3J0IHsgTmFtZXMgfSBmcm9tICcuL25hbWVzJztcbmltcG9ydCB7IFJlbW92YWxQb2xpY3kgfSBmcm9tICcuL3JlbW92YWwtcG9saWN5JztcbmltcG9ydCB7IElSZXNvbHZlQ29udGV4dCB9IGZyb20gJy4vcmVzb2x2YWJsZSc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJy4vc3RhY2snO1xuaW1wb3J0IHsgTmVzdGVkU3RhY2tTeW50aGVzaXplciB9IGZyb20gJy4vc3RhY2stc3ludGhlc2l6ZXJzJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbi8vIHYyIC0ga2VlcCB0aGlzIGltcG9ydCBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gdG8gcmVkdWNlIG1lcmdlIGNvbmZsaWN0IHdoZW4gZm9yd2FyZCBtZXJnaW5nIHdpdGggdGhlIHYyIGJyYW5jaC5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICcuL2NvbnN0cnVjdC1jb21wYXQnO1xuXG5jb25zdCBORVNURURfU1RBQ0tfU1lNQk9MID0gU3ltYm9sLmZvcignQGF3cy1jZGsvY29yZS5OZXN0ZWRTdGFjaycpO1xuXG4vKipcbiAqIEluaXRpYWxpemF0aW9uIHByb3BzIGZvciB0aGUgYE5lc3RlZFN0YWNrYCBjb25zdHJ1Y3QuXG4gKlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE5lc3RlZFN0YWNrUHJvcHMge1xuICAvKipcbiAgICogVGhlIHNldCB2YWx1ZSBwYWlycyB0aGF0IHJlcHJlc2VudCB0aGUgcGFyYW1ldGVycyBwYXNzZWQgdG8gQ2xvdWRGb3JtYXRpb25cbiAgICogd2hlbiB0aGlzIG5lc3RlZCBzdGFjayBpcyBjcmVhdGVkLiBFYWNoIHBhcmFtZXRlciBoYXMgYSBuYW1lIGNvcnJlc3BvbmRpbmdcbiAgICogdG8gYSBwYXJhbWV0ZXIgZGVmaW5lZCBpbiB0aGUgZW1iZWRkZWQgdGVtcGxhdGUgYW5kIGEgdmFsdWUgcmVwcmVzZW50aW5nXG4gICAqIHRoZSB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIHNldCBmb3IgdGhlIHBhcmFtZXRlci5cbiAgICpcbiAgICogVGhlIG5lc3RlZCBzdGFjayBjb25zdHJ1Y3Qgd2lsbCBhdXRvbWF0aWNhbGx5IHN5bnRoZXNpemUgcGFyYW1ldGVycyBpbiBvcmRlclxuICAgKiB0byBiaW5kIHJlZmVyZW5jZXMgZnJvbSB0aGUgcGFyZW50IHN0YWNrKHMpIGludG8gdGhlIG5lc3RlZCBzdGFjay5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB1c2VyLWRlZmluZWQgcGFyYW1ldGVycyBhcmUgcGFzc2VkIHRvIHRoZSBuZXN0ZWQgc3RhY2tcbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgbGVuZ3RoIG9mIHRpbWUgdGhhdCBDbG91ZEZvcm1hdGlvbiB3YWl0cyBmb3IgdGhlIG5lc3RlZCBzdGFjayB0byByZWFjaFxuICAgKiB0aGUgQ1JFQVRFX0NPTVBMRVRFIHN0YXRlLlxuICAgKlxuICAgKiBXaGVuIENsb3VkRm9ybWF0aW9uIGRldGVjdHMgdGhhdCB0aGUgbmVzdGVkIHN0YWNrIGhhcyByZWFjaGVkIHRoZVxuICAgKiBDUkVBVEVfQ09NUExFVEUgc3RhdGUsIGl0IG1hcmtzIHRoZSBuZXN0ZWQgc3RhY2sgcmVzb3VyY2UgYXNcbiAgICogQ1JFQVRFX0NPTVBMRVRFIGluIHRoZSBwYXJlbnQgc3RhY2sgYW5kIHJlc3VtZXMgY3JlYXRpbmcgdGhlIHBhcmVudCBzdGFjay5cbiAgICogSWYgdGhlIHRpbWVvdXQgcGVyaW9kIGV4cGlyZXMgYmVmb3JlIHRoZSBuZXN0ZWQgc3RhY2sgcmVhY2hlc1xuICAgKiBDUkVBVEVfQ09NUExFVEUsIENsb3VkRm9ybWF0aW9uIG1hcmtzIHRoZSBuZXN0ZWQgc3RhY2sgYXMgZmFpbGVkIGFuZCByb2xsc1xuICAgKiBiYWNrIGJvdGggdGhlIG5lc3RlZCBzdGFjayBhbmQgcGFyZW50IHN0YWNrLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRpbWVvdXRcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBEdXJhdGlvbjtcblxuICAvKipcbiAgICogVGhlIFNpbXBsZSBOb3RpZmljYXRpb24gU2VydmljZSAoU05TKSB0b3BpY3MgdG8gcHVibGlzaCBzdGFjayByZWxhdGVkXG4gICAqIGV2ZW50cy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub3RpZmljYXRpb25zIGFyZSBub3Qgc2VudCBmb3IgdGhpcyBzdGFjay5cbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmaWNhdGlvbkFybnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogUG9saWN5IHRvIGFwcGx5IHdoZW4gdGhlIG5lc3RlZCBzdGFjayBpcyByZW1vdmVkXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IGlzIGBEZXN0cm95YCwgYmVjYXVzZSBhbGwgUmVtb3ZhbCBQb2xpY2llcyBvZiByZXNvdXJjZXMgaW5zaWRlIHRoZVxuICAgKiBOZXN0ZWQgU3RhY2sgc2hvdWxkIGFscmVhZHkgaGF2ZSBiZWVuIHNldCBjb3JyZWN0bHkuIFlvdSBub3JtYWxseSBzaG91bGRcbiAgICogbm90IG5lZWQgdG8gc2V0IHRoaXMgdmFsdWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG59XG5cbi8qKlxuICogQSBDbG91ZEZvcm1hdGlvbiBuZXN0ZWQgc3RhY2suXG4gKlxuICogV2hlbiB5b3UgYXBwbHkgdGVtcGxhdGUgY2hhbmdlcyB0byB1cGRhdGUgYSB0b3AtbGV2ZWwgc3RhY2ssIENsb3VkRm9ybWF0aW9uXG4gKiB1cGRhdGVzIHRoZSB0b3AtbGV2ZWwgc3RhY2sgYW5kIGluaXRpYXRlcyBhbiB1cGRhdGUgdG8gaXRzIG5lc3RlZCBzdGFja3MuXG4gKiBDbG91ZEZvcm1hdGlvbiB1cGRhdGVzIHRoZSByZXNvdXJjZXMgb2YgbW9kaWZpZWQgbmVzdGVkIHN0YWNrcywgYnV0IGRvZXMgbm90XG4gKiB1cGRhdGUgdGhlIHJlc291cmNlcyBvZiB1bm1vZGlmaWVkIG5lc3RlZCBzdGFja3MuXG4gKlxuICogRnVydGhlcm1vcmUsIHRoaXMgc3RhY2sgd2lsbCBub3QgYmUgdHJlYXRlZCBhcyBhbiBpbmRlcGVuZGVudCBkZXBsb3ltZW50XG4gKiBhcnRpZmFjdCAod29uJ3QgYmUgbGlzdGVkIGluIFwiY2RrIGxpc3RcIiBvciBkZXBsb3lhYmxlIHRocm91Z2ggXCJjZGsgZGVwbG95XCIpLFxuICogYnV0IHJhdGhlciBvbmx5IHN5bnRoZXNpemVkIGFzIGEgdGVtcGxhdGUgYW5kIHVwbG9hZGVkIGFzIGFuIGFzc2V0IHRvIFMzLlxuICpcbiAqIENyb3NzIHJlZmVyZW5jZXMgb2YgcmVzb3VyY2UgYXR0cmlidXRlcyBiZXR3ZWVuIHRoZSBwYXJlbnQgc3RhY2sgYW5kIHRoZVxuICogbmVzdGVkIHN0YWNrIHdpbGwgYXV0b21hdGljYWxseSBiZSB0cmFuc2xhdGVkIHRvIHN0YWNrIHBhcmFtZXRlcnMgYW5kXG4gKiBvdXRwdXRzLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIE5lc3RlZFN0YWNrIGV4dGVuZHMgU3RhY2sge1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgYHhgIGlzIGFuIG9iamVjdCBvZiB0eXBlIGBOZXN0ZWRTdGFja2AuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGlzTmVzdGVkU3RhY2soeDogYW55KTogeCBpcyBOZXN0ZWRTdGFjayB7XG4gICAgcmV0dXJuIHggIT0gbnVsbCAmJiB0eXBlb2YoeCkgPT09ICdvYmplY3QnICYmIE5FU1RFRF9TVEFDS19TWU1CT0wgaW4geDtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSB0ZW1wbGF0ZUZpbGU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IG5lc3RlZFN0YWNrUmVzb3VyY2U/OiBDZm5SZXNvdXJjZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtZXRlcnM6IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlOiBDZm5TdGFjaztcbiAgcHJpdmF0ZSByZWFkb25seSBfY29udGV4dHVhbFN0YWNrSWQ6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBfY29udGV4dHVhbFN0YWNrTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIF90ZW1wbGF0ZVVybD86IHN0cmluZztcbiAgcHJpdmF0ZSBfcGFyZW50U3RhY2s6IFN0YWNrO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBOZXN0ZWRTdGFja1Byb3BzID0geyB9KSB7XG4gICAgY29uc3QgcGFyZW50U3RhY2sgPSBmaW5kUGFyZW50U3RhY2soc2NvcGUpO1xuXG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBlbnY6IHsgYWNjb3VudDogcGFyZW50U3RhY2suYWNjb3VudCwgcmVnaW9uOiBwYXJlbnRTdGFjay5yZWdpb24gfSxcbiAgICAgIHN5bnRoZXNpemVyOiBuZXcgTmVzdGVkU3RhY2tTeW50aGVzaXplcihwYXJlbnRTdGFjay5zeW50aGVzaXplciksXG4gICAgfSk7XG5cbiAgICB0aGlzLl9wYXJlbnRTdGFjayA9IHBhcmVudFN0YWNrO1xuXG4gICAgLy8gQGRlcHJlY2F0ZTogcmVtb3ZlIHRoaXMgaW4gdjIuMCAocmVkdW5kZW50KVxuICAgIGNvbnN0IHBhcmVudFNjb3BlID0gbmV3IENvcmVDb25zdHJ1Y3Qoc2NvcGUsIGlkICsgJy5OZXN0ZWRTdGFjaycpO1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIE5FU1RFRF9TVEFDS19TWU1CT0wsIHsgdmFsdWU6IHRydWUgfSk7XG5cbiAgICAvLyB0aGlzIGlzIHRoZSBmaWxlIG5hbWUgb2YgdGhlIHN5bnRoZXNpemVkIHRlbXBsYXRlIGZpbGUgd2l0aGluIHRoZSBjbG91ZCBhc3NlbWJseVxuICAgIHRoaXMudGVtcGxhdGVGaWxlID0gYCR7TmFtZXMudW5pcXVlSWQodGhpcyl9Lm5lc3RlZC50ZW1wbGF0ZS5qc29uYDtcblxuICAgIHRoaXMucGFyYW1ldGVycyA9IHByb3BzLnBhcmFtZXRlcnMgfHwge307XG5cbiAgICB0aGlzLnJlc291cmNlID0gbmV3IENmblN0YWNrKHBhcmVudFNjb3BlLCBgJHtpZH0uTmVzdGVkU3RhY2tSZXNvdXJjZWAsIHtcbiAgICAgIC8vIFRoaXMgdmFsdWUgY2Fubm90IGJlIGNhY2hlZCBzaW5jZSBpdCBjaGFuZ2VzIGR1cmluZyB0aGUgc3ludGhlc2lzIHBoYXNlXG4gICAgICB0ZW1wbGF0ZVVybDogTGF6eS51bmNhY2hlZFN0cmluZyh7IHByb2R1Y2U6ICgpID0+IHRoaXMuX3RlbXBsYXRlVXJsIHx8ICc8dW5yZXNvbHZlZD4nIH0pLFxuICAgICAgcGFyYW1ldGVyczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiBPYmplY3Qua2V5cyh0aGlzLnBhcmFtZXRlcnMpLmxlbmd0aCA+IDAgPyB0aGlzLnBhcmFtZXRlcnMgOiB1bmRlZmluZWQgfSksXG4gICAgICBub3RpZmljYXRpb25Bcm5zOiBwcm9wcy5ub3RpZmljYXRpb25Bcm5zLFxuICAgICAgdGltZW91dEluTWludXRlczogcHJvcHMudGltZW91dCA/IHByb3BzLnRpbWVvdXQudG9NaW51dGVzKCkgOiB1bmRlZmluZWQsXG4gICAgfSk7XG4gICAgdGhpcy5yZXNvdXJjZS5hcHBseVJlbW92YWxQb2xpY3kocHJvcHMucmVtb3ZhbFBvbGljeSA/PyBSZW1vdmFsUG9saWN5LkRFU1RST1kpO1xuXG4gICAgdGhpcy5uZXN0ZWRTdGFja1Jlc291cmNlID0gdGhpcy5yZXNvdXJjZTtcbiAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkID0gdGhpcy5yZXNvdXJjZTtcblxuICAgIC8vIGNvbnRleHQtYXdhcmUgc3RhY2sgbmFtZTogaWYgcmVzb2x2ZWQgZnJvbSB3aXRoaW4gdGhpcyBzdGFjaywgcmV0dXJuIEFXUzo6U3RhY2tOYW1lXG4gICAgLy8gaWYgcmVzb2x2ZWQgZnJvbSB0aGUgb3V0ZXIgc3RhY2ssIHVzZSB0aGUgeyBSZWYgfSBvZiB0aGUgQVdTOjpDbG91ZEZvcm1hdGlvbjo6U3RhY2sgcmVzb3VyY2VcbiAgICAvLyB3aGljaCByZXNvbHZlcyB0aGUgQVJOIG9mIHRoZSBzdGFjay4gV2UgbmVlZCB0byBleHRyYWN0IHRoZSBzdGFjayBuYW1lLCB3aGljaCBpcyB0aGUgc2Vjb25kXG4gICAgLy8gY29tcG9uZW50IGFmdGVyIHNwbGl0dGluZyBieSBcIi9cIlxuICAgIHRoaXMuX2NvbnRleHR1YWxTdGFja05hbWUgPSB0aGlzLmNvbnRleHR1YWxBdHRyaWJ1dGUoQXdzLlNUQUNLX05BTUUsIEZuLnNlbGVjdCgxLCBGbi5zcGxpdCgnLycsIHRoaXMucmVzb3VyY2UucmVmKSkpO1xuICAgIHRoaXMuX2NvbnRleHR1YWxTdGFja0lkID0gdGhpcy5jb250ZXh0dWFsQXR0cmlidXRlKEF3cy5TVEFDS19JRCwgdGhpcy5yZXNvdXJjZS5yZWYpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFuIGF0dHJpYnV0ZSB0aGF0IHJlcHJlc2VudHMgdGhlIG5hbWUgb2YgdGhlIG5lc3RlZCBzdGFjay5cbiAgICpcbiAgICogVGhpcyBpcyBhIGNvbnRleHQgYXdhcmUgYXR0cmlidXRlOlxuICAgKiAtIElmIHRoaXMgaXMgcmVmZXJlbmNlZCBmcm9tIHRoZSBwYXJlbnQgc3RhY2ssIGl0IHdpbGwgcmV0dXJuIGEgdG9rZW4gdGhhdCBwYXJzZXMgdGhlIG5hbWUgZnJvbSB0aGUgc3RhY2sgSUQuXG4gICAqIC0gSWYgdGhpcyBpcyByZWZlcmVuY2VkIGZyb20gdGhlIGNvbnRleHQgb2YgdGhlIG5lc3RlZCBzdGFjaywgaXQgd2lsbCByZXR1cm4gYHsgXCJSZWZcIjogXCJBV1M6OlN0YWNrTmFtZVwiIH1gXG4gICAqXG4gICAqIEV4YW1wbGUgdmFsdWU6IGBteXN0YWNrLW15bmVzdGVkc3RhY2stc2dnZnJoeGh1bTd3YFxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWNrTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29udGV4dHVhbFN0YWNrTmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbiBhdHRyaWJ1dGUgdGhhdCByZXByZXNlbnRzIHRoZSBJRCBvZiB0aGUgc3RhY2suXG4gICAqXG4gICAqIFRoaXMgaXMgYSBjb250ZXh0IGF3YXJlIGF0dHJpYnV0ZTpcbiAgICogLSBJZiB0aGlzIGlzIHJlZmVyZW5jZWQgZnJvbSB0aGUgcGFyZW50IHN0YWNrLCBpdCB3aWxsIHJldHVybiBgeyBcIlJlZlwiOiBcIkxvZ2ljYWxJZE9mTmVzdGVkU3RhY2tSZXNvdXJjZVwiIH1gLlxuICAgKiAtIElmIHRoaXMgaXMgcmVmZXJlbmNlZCBmcm9tIHRoZSBjb250ZXh0IG9mIHRoZSBuZXN0ZWQgc3RhY2ssIGl0IHdpbGwgcmV0dXJuIGB7IFwiUmVmXCI6IFwiQVdTOjpTdGFja0lkXCIgfWBcbiAgICpcbiAgICogRXhhbXBsZSB2YWx1ZTogYGFybjphd3M6Y2xvdWRmb3JtYXRpb246dXMtZWFzdC0yOjEyMzQ1Njc4OTAxMjpzdGFjay9teXN0YWNrLW15bmVzdGVkc3RhY2stc2dnZnJoeGh1bTd3L2Y0NDliMjUwLWI5NjktMTFlMC1hMTg1LTUwODFkMDEzNjc4NmBcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGdldCBzdGFja0lkKCkge1xuICAgIHJldHVybiB0aGlzLl9jb250ZXh0dWFsU3RhY2tJZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ24gYSB2YWx1ZSB0byBvbmUgb2YgdGhlIG5lc3RlZCBzdGFjayBwYXJhbWV0ZXJzLlxuICAgKiBAcGFyYW0gbmFtZSBUaGUgcGFyYW1ldGVyIG5hbWUgKElEKVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlIHRvIGFzc2lnblxuICAgKi9cbiAgcHVibGljIHNldFBhcmFtZXRlcihuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLnBhcmFtZXRlcnNbbmFtZV0gPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGFuIGFzc2V0IGF0IHRoZSBwYXJlbnQgc3RhY2sgd2hpY2ggcmVwcmVzZW50cyB0aGUgdGVtcGxhdGUgb2YgdGhpc1xuICAgKiBuZXN0ZWQgc3RhY2suXG4gICAqXG4gICAqIFRoaXMgcHJpdmF0ZSBBUEkgaXMgdXNlZCBieSBgQXBwLnByZXBhcmUoKWAgd2l0aGluIGEgbG9vcCB0aGF0IHJlY3RpZmllc1xuICAgKiByZWZlcmVuY2VzIGV2ZXJ5IHRpbWUgYW4gYXNzZXQgaXMgYWRkZWQuIFRoaXMgaXMgYmVjYXVzZSAoYXQgdGhlIG1vbWVudClcbiAgICogYXNzZXRzIGFyZSBhZGRyZXNzZWQgdXNpbmcgQ2xvdWRGb3JtYXRpb24gcGFyYW1ldGVycy5cbiAgICpcbiAgICogQHJldHVybnMgYHRydWVgIGlmIGEgbmV3IGFzc2V0IHdhcyBhZGRlZCBvciBgZmFsc2VgIGlmIGFuIGFzc2V0IHdhc1xuICAgKiBwcmV2aW91c2x5IGFkZGVkLiBXaGVuIHRoaXMgcmV0dXJucyBgdHJ1ZWAsIEFwcCB3aWxsIGRvIGFub3RoZXIgcmVmZXJlbmNlXG4gICAqIHJlY3RpZmljYXRpb24gY3ljbGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9wcmVwYXJlVGVtcGxhdGVBc3NldCgpIHtcbiAgICBpZiAodGhpcy5fdGVtcGxhdGVVcmwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBXaGVuIGFkZGluZyB0YWdzIHRvIG5lc3RlZCBzdGFjaywgdGhlIHRhZ3MgbmVlZCB0byBiZSBhZGRlZCB0byBhbGwgdGhlIHJlc291cmNlcyBpblxuICAgIC8vIGluIG5lc3RlZCBzdGFjaywgd2hpY2ggaXMgaGFuZGxlZCBieSB0aGUgYHRhZ3NgIHByb3BlcnR5LCBCdXQgdG8gdGFnIHRoZVxuICAgIC8vICB0YWdzIGhhdmUgdG8gYmUgYWRkZWQgaW4gdGhlIHBhcmVudCBzdGFjayBDZm5TdGFjayByZXNvdXJjZS4gVGhlIENmblN0YWNrIHJlc291cmNlIGNyZWF0ZWRcbiAgICAvLyBieSB0aGlzIGNsYXNzIGRvbnQgc2hhcmUgdGhlIHNhbWUgVGFnTWFuYWdlciBhcyB0aGF0IG9mIHRoZSBvbmUgZXhwb3NlZCBieSB0aGUgYHRhZ2AgcHJvcGVydHkgb2YgdGhlXG4gICAgLy8gIGNsYXNzLCBhbGwgdGhlIHRhZ3MgbmVlZCB0byBiZSBjb3BpZWQgdG8gdGhlIENmblN0YWNrIHJlc291cmNlIGJlZm9yZSBzeW50aGVzaXppbmcgdGhlIHJlc291cmNlLlxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvcHVsbC8xOTEyOFxuICAgIE9iamVjdC5lbnRyaWVzKHRoaXMudGFncy50YWdWYWx1ZXMoKSkuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICB0aGlzLnJlc291cmNlLnRhZ3Muc2V0VGFnKGtleSwgdmFsdWUpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2ZuID0gSlNPTi5zdHJpbmdpZnkodGhpcy5fdG9DbG91ZEZvcm1hdGlvbigpKTtcbiAgICBjb25zdCB0ZW1wbGF0ZUhhc2ggPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGNmbikuZGlnZXN0KCdoZXgnKTtcblxuICAgIGNvbnN0IHRlbXBsYXRlTG9jYXRpb24gPSB0aGlzLl9wYXJlbnRTdGFjay5zeW50aGVzaXplci5hZGRGaWxlQXNzZXQoe1xuICAgICAgcGFja2FnaW5nOiBGaWxlQXNzZXRQYWNrYWdpbmcuRklMRSxcbiAgICAgIHNvdXJjZUhhc2g6IHRlbXBsYXRlSGFzaCxcbiAgICAgIGZpbGVOYW1lOiB0aGlzLnRlbXBsYXRlRmlsZSxcbiAgICB9KTtcblxuICAgIHRoaXMuYWRkUmVzb3VyY2VNZXRhZGF0YSh0aGlzLnJlc291cmNlLCAnVGVtcGxhdGVVUkwnKTtcblxuICAgIC8vIGlmIGJ1Y2tldE5hbWUvb2JqZWN0S2V5IGFyZSBjZm4gcGFyYW1ldGVycyBmcm9tIGEgc3RhY2sgb3RoZXIgdGhhbiB0aGUgcGFyZW50IHN0YWNrLCB0aGV5IHdpbGxcbiAgICAvLyBiZSByZXNvbHZlZCBhcyBjcm9zcy1zdGFjayByZWZlcmVuY2VzIGxpa2UgYW55IG90aGVyIChzZWUgXCJtdWx0aVwiIHRlc3RzKS5cbiAgICB0aGlzLl90ZW1wbGF0ZVVybCA9IGBodHRwczovL3MzLiR7dGhpcy5fcGFyZW50U3RhY2sucmVnaW9ufS4ke3RoaXMuX3BhcmVudFN0YWNrLnVybFN1ZmZpeH0vJHt0ZW1wbGF0ZUxvY2F0aW9uLmJ1Y2tldE5hbWV9LyR7dGVtcGxhdGVMb2NhdGlvbi5vYmplY3RLZXl9YDtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgY29udGV4dHVhbEF0dHJpYnV0ZShpbm5lclZhbHVlOiBzdHJpbmcsIG91dGVyVmFsdWU6IHN0cmluZykge1xuICAgIHJldHVybiBUb2tlbi5hc1N0cmluZyh7XG4gICAgICByZXNvbHZlOiAoY29udGV4dDogSVJlc29sdmVDb250ZXh0KSA9PiB7XG4gICAgICAgIGlmIChTdGFjay5vZihjb250ZXh0LnNjb3BlKSA9PT0gdGhpcykge1xuICAgICAgICAgIHJldHVybiBpbm5lclZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBvdXRlclZhbHVlO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRSZXNvdXJjZU1ldGFkYXRhKHJlc291cmNlOiBDZm5SZXNvdXJjZSwgcmVzb3VyY2VQcm9wZXJ0eTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLm5vZGUudHJ5R2V0Q29udGV4dChjeGFwaS5BU1NFVF9SRVNPVVJDRV9NRVRBREFUQV9FTkFCTEVEX0NPTlRFWFQpKSB7XG4gICAgICByZXR1cm47IC8vIG5vdCBlbmFibGVkXG4gICAgfVxuXG4gICAgLy8gdGVsbCB0b29scyBzdWNoIGFzIFNBTSBDTEkgdGhhdCB0aGUgXCJUZW1wbGF0ZVVSTFwiIHByb3BlcnR5IG9mIHRoaXMgcmVzb3VyY2VcbiAgICAvLyBwb2ludHMgdG8gdGhlIG5lc3RlZCBzdGFjayB0ZW1wbGF0ZSBmb3IgbG9jYWwgZW11bGF0aW9uXG4gICAgcmVzb3VyY2UuY2ZuT3B0aW9ucy5tZXRhZGF0YSA9IHJlc291cmNlLmNmbk9wdGlvbnMubWV0YWRhdGEgfHwgeyB9O1xuICAgIHJlc291cmNlLmNmbk9wdGlvbnMubWV0YWRhdGFbY3hhcGkuQVNTRVRfUkVTT1VSQ0VfTUVUQURBVEFfUEFUSF9LRVldID0gdGhpcy50ZW1wbGF0ZUZpbGU7XG4gICAgcmVzb3VyY2UuY2ZuT3B0aW9ucy5tZXRhZGF0YVtjeGFwaS5BU1NFVF9SRVNPVVJDRV9NRVRBREFUQV9QUk9QRVJUWV9LRVldID0gcmVzb3VyY2VQcm9wZXJ0eTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyB0aGUgc2NvcGUgZm9yIGEgbmVzdGVkIHN0YWNrLiBOZXN0ZWQgc3RhY2tzIG11c3QgYmUgZGVmaW5lZCB3aXRoaW4gdGhlIHNjb3BlIG9mIGFub3RoZXIgYFN0YWNrYC5cbiAqL1xuZnVuY3Rpb24gZmluZFBhcmVudFN0YWNrKHNjb3BlOiBDb25zdHJ1Y3QpOiBTdGFjayB7XG4gIGlmICghc2NvcGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05lc3RlZCBzdGFja3MgY2Fubm90IGJlIGRlZmluZWQgYXMgYSByb290IGNvbnN0cnVjdCcpO1xuICB9XG5cbiAgY29uc3QgcGFyZW50U3RhY2sgPSBOb2RlLm9mKHNjb3BlKS5zY29wZXMucmV2ZXJzZSgpLmZpbmQocCA9PiBTdGFjay5pc1N0YWNrKHApKTtcbiAgaWYgKCFwYXJlbnRTdGFjaykge1xuICAgIHRocm93IG5ldyBFcnJvcignTmVzdGVkIHN0YWNrcyBtdXN0IGJlIGRlZmluZWQgd2l0aGluIHNjb3BlIG9mIGFub3RoZXIgbm9uLW5lc3RlZCBzdGFjaycpO1xuICB9XG5cbiAgcmV0dXJuIHBhcmVudFN0YWNrIGFzIFN0YWNrO1xufVxuIl19 |
\ | No newline at end of file |