UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

598 lines 86.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CfnParser = exports.CfnParsingContext = exports.FromCloudFormation = void 0; const cfn_fn_1 = require("./cfn-fn"); const cfn_pseudo_1 = require("./cfn-pseudo"); const cfn_resource_policy_1 = require("./cfn-resource-policy"); const lazy_1 = require("./lazy"); const cfn_reference_1 = require("./private/cfn-reference"); const token_1 = require("./token"); const util_1 = require("./util"); /** * This class contains static methods called when going from * translated values received from {@link CfnParser.parseValue} * to the actual L1 properties - * things like changing IResolvable to the appropriate type * (string, string array, or number), etc. * * While this file not exported from the module * (to not make it part of the public API), * it is directly referenced in the generated L1 code. * * @experimental */ class FromCloudFormation { // nothing to for any but return it static getAny(value) { return value; } static getBoolean(value) { if (typeof value === 'string') { // CloudFormation allows passing strings as boolean switch (value) { case 'true': return true; case 'false': return false; default: throw new Error(`Expected 'true' or 'false' for boolean value, got: '${value}'`); } } // in all other cases, just return the value, // and let a validator handle if it's not a boolean return value; } static getDate(value) { // if the date is a deploy-time value, just return it if (token_1.isResolvableObject(value)) { return value; } // if the date has been given as a string, convert it if (typeof value === 'string') { return new Date(value); } // all other cases - just return the value, // if it's not a Date, a validator should catch it return value; } // won't always return a string; if the input can't be resolved to a string, // the input will be returned. static getString(value) { // if the string is a deploy-time value, serialize it to a Token if (token_1.isResolvableObject(value)) { return value.toString(); } // CloudFormation treats numbers and strings interchangeably; // so, if we get a number here, convert it to a string if (typeof value === 'number') { return value.toString(); } // in all other cases, just return the input, // and let a validator handle it if it's not a string return value; } // won't always return a number; if the input can't be parsed to a number, // the input will be returned. static getNumber(value) { // if the string is a deploy-time value, serialize it to a Token if (token_1.isResolvableObject(value)) { return token_1.Token.asNumber(value); } // return a number, if the input can be parsed as one if (typeof value === 'string') { const parsedValue = parseFloat(value); if (!isNaN(parsedValue)) { return parsedValue; } } // otherwise return the input, // and let a validator handle it if it's not a number return value; } static getStringArray(value) { // if the array is a deploy-time value, serialize it to a Token if (token_1.isResolvableObject(value)) { return token_1.Token.asList(value); } // in all other cases, delegate to the standard mapping logic return this.getArray(this.getString)(value); } static getArray(mapper) { return (value) => { if (!Array.isArray(value)) { // break the type system, and just return the given value, // which hopefully will be reported as invalid by the validator // of the property we're transforming // (unless it's a deploy-time value, // which we can't map over at build time anyway) return value; } return value.map(mapper); }; } static getMap(mapper) { return (value) => { if (typeof value !== 'object') { // if the input is not a map (= object in JS land), // just return it, and let the validator of this property handle it // (unless it's a deploy-time value, // which we can't map over at build time anyway) return value; } const ret = {}; for (const [key, val] of Object.entries(value)) { ret[key] = mapper(val); } return ret; }; } static getCfnTag(tag) { return tag == null ? {} // break the type system - this should be detected at runtime by a tag validator : { key: tag.Key, value: tag.Value, }; } /** * Return a function that, when applied to a value, will return the first validly deserialized one */ static getTypeUnion(validators, mappers) { return (value) => { for (let i = 0; i < validators.length; i++) { const candidate = mappers[i](value); if (validators[i](candidate).isSuccess) { return candidate; } } // if nothing matches, just return the input unchanged, and let validators catch it return value; }; } } exports.FromCloudFormation = FromCloudFormation; /** * The context in which the parsing is taking place. * * Some fragments of CloudFormation templates behave differently than others * (for example, the 'Conditions' sections treats { "Condition": "NameOfCond" } * differently than the 'Resources' section). * This enum can be used to change the created {@link CfnParser} behavior, * based on the template context. */ var CfnParsingContext; (function (CfnParsingContext) { /** We're currently parsing the 'Conditions' section. */ CfnParsingContext[CfnParsingContext["CONDITIONS"] = 0] = "CONDITIONS"; /** We're currently parsing the 'Rules' section. */ CfnParsingContext[CfnParsingContext["RULES"] = 1] = "RULES"; })(CfnParsingContext = exports.CfnParsingContext || (exports.CfnParsingContext = {})); /** * This class contains methods for translating from a pure CFN value * (like a JS object { "Ref": "Bucket" }) * to a form CDK understands * (like Fn.ref('Bucket')). * * While this file not exported from the module * (to not make it part of the public API), * it is directly referenced in the generated L1 code, * so any renames of it need to be reflected in cfn2ts/codegen.ts as well. * * @experimental */ class CfnParser { constructor(options) { this.options = options; } handleAttributes(resource, resourceAttributes, logicalId) { var _a; const cfnOptions = resource.cfnOptions; cfnOptions.creationPolicy = this.parseCreationPolicy(resourceAttributes.CreationPolicy); cfnOptions.updatePolicy = this.parseUpdatePolicy(resourceAttributes.UpdatePolicy); cfnOptions.deletionPolicy = this.parseDeletionPolicy(resourceAttributes.DeletionPolicy); cfnOptions.updateReplacePolicy = this.parseDeletionPolicy(resourceAttributes.UpdateReplacePolicy); cfnOptions.version = this.parseValue(resourceAttributes.Version); cfnOptions.description = this.parseValue(resourceAttributes.Description); cfnOptions.metadata = this.parseValue(resourceAttributes.Metadata); // handle Condition if (resourceAttributes.Condition) { const condition = this.finder.findCondition(resourceAttributes.Condition); if (!condition) { throw new Error(`Resource '${logicalId}' uses Condition '${resourceAttributes.Condition}' that doesn't exist`); } cfnOptions.condition = condition; } // handle DependsOn resourceAttributes.DependsOn = (_a = resourceAttributes.DependsOn) !== null && _a !== void 0 ? _a : []; const dependencies = Array.isArray(resourceAttributes.DependsOn) ? resourceAttributes.DependsOn : [resourceAttributes.DependsOn]; for (const dep of dependencies) { const depResource = this.finder.findResource(dep); if (!depResource) { throw new Error(`Resource '${logicalId}' depends on '${dep}' that doesn't exist`); } resource.node.addDependency(depResource); } } parseCreationPolicy(policy) { if (typeof policy !== 'object') { return undefined; } // change simple JS values to their CDK equivalents policy = this.parseValue(policy); return util_1.undefinedIfAllValuesAreEmpty({ autoScalingCreationPolicy: parseAutoScalingCreationPolicy(policy.AutoScalingCreationPolicy), resourceSignal: parseResourceSignal(policy.ResourceSignal), }); function parseAutoScalingCreationPolicy(p) { if (typeof p !== 'object') { return undefined; } return util_1.undefinedIfAllValuesAreEmpty({ minSuccessfulInstancesPercent: FromCloudFormation.getNumber(p.MinSuccessfulInstancesPercent), }); } function parseResourceSignal(p) { if (typeof p !== 'object') { return undefined; } return util_1.undefinedIfAllValuesAreEmpty({ count: FromCloudFormation.getNumber(p.Count), timeout: FromCloudFormation.getString(p.Timeout), }); } } parseUpdatePolicy(policy) { if (typeof policy !== 'object') { return undefined; } // change simple JS values to their CDK equivalents policy = this.parseValue(policy); return util_1.undefinedIfAllValuesAreEmpty({ autoScalingReplacingUpdate: parseAutoScalingReplacingUpdate(policy.AutoScalingReplacingUpdate), autoScalingRollingUpdate: parseAutoScalingRollingUpdate(policy.AutoScalingRollingUpdate), autoScalingScheduledAction: parseAutoScalingScheduledAction(policy.AutoScalingScheduledAction), codeDeployLambdaAliasUpdate: parseCodeDeployLambdaAliasUpdate(policy.CodeDeployLambdaAliasUpdate), enableVersionUpgrade: FromCloudFormation.getBoolean(policy.EnableVersionUpgrade), useOnlineResharding: FromCloudFormation.getBoolean(policy.UseOnlineResharding), }); function parseAutoScalingReplacingUpdate(p) { if (typeof p !== 'object') { return undefined; } return util_1.undefinedIfAllValuesAreEmpty({ willReplace: p.WillReplace, }); } function parseAutoScalingRollingUpdate(p) { if (typeof p !== 'object') { return undefined; } return util_1.undefinedIfAllValuesAreEmpty({ maxBatchSize: FromCloudFormation.getNumber(p.MaxBatchSize), minInstancesInService: FromCloudFormation.getNumber(p.MinInstancesInService), minSuccessfulInstancesPercent: FromCloudFormation.getNumber(p.MinSuccessfulInstancesPercent), pauseTime: FromCloudFormation.getString(p.PauseTime), suspendProcesses: FromCloudFormation.getStringArray(p.SuspendProcesses), waitOnResourceSignals: FromCloudFormation.getBoolean(p.WaitOnResourceSignals), }); } function parseCodeDeployLambdaAliasUpdate(p) { if (typeof p !== 'object') { return undefined; } return { beforeAllowTrafficHook: FromCloudFormation.getString(p.BeforeAllowTrafficHook), afterAllowTrafficHook: FromCloudFormation.getString(p.AfterAllowTrafficHook), applicationName: FromCloudFormation.getString(p.ApplicationName), deploymentGroupName: FromCloudFormation.getString(p.DeploymentGroupName), }; } function parseAutoScalingScheduledAction(p) { if (typeof p !== 'object') { return undefined; } return util_1.undefinedIfAllValuesAreEmpty({ ignoreUnmodifiedGroupSizeProperties: p.IgnoreUnmodifiedGroupSizeProperties, }); } } parseDeletionPolicy(policy) { switch (policy) { case null: return undefined; case undefined: return undefined; case 'Delete': return cfn_resource_policy_1.CfnDeletionPolicy.DELETE; case 'Retain': return cfn_resource_policy_1.CfnDeletionPolicy.RETAIN; case 'Snapshot': return cfn_resource_policy_1.CfnDeletionPolicy.SNAPSHOT; default: throw new Error(`Unrecognized DeletionPolicy '${policy}'`); } } parseValue(cfnValue) { // == null captures undefined as well if (cfnValue == null) { return undefined; } // if we have any late-bound values, // just return them if (token_1.isResolvableObject(cfnValue)) { return cfnValue; } if (Array.isArray(cfnValue)) { return cfnValue.map(el => this.parseValue(el)); } if (typeof cfnValue === 'object') { // an object can be either a CFN intrinsic, or an actual object const cfnIntrinsic = this.parseIfCfnIntrinsic(cfnValue); if (cfnIntrinsic !== undefined) { return cfnIntrinsic; } const ret = {}; for (const [key, val] of Object.entries(cfnValue)) { ret[key] = this.parseValue(val); } return ret; } // in all other cases, just return the input return cfnValue; } get finder() { return this.options.finder; } parseIfCfnIntrinsic(object) { const key = this.looksLikeCfnIntrinsic(object); switch (key) { case undefined: return undefined; case 'Ref': { const refTarget = object[key]; const specialRef = this.specialCaseRefs(refTarget); if (specialRef !== undefined) { return specialRef; } else { const refElement = this.finder.findRefTarget(refTarget); if (!refElement) { throw new Error(`Element used in Ref expression with logical ID: '${refTarget}' not found`); } return cfn_reference_1.CfnReference.for(refElement, 'Ref'); } } case 'Fn::GetAtt': { const value = object[key]; let logicalId, attributeName, stringForm; // Fn::GetAtt takes as arguments either a string... if (typeof value === 'string') { // ...in which case the logical ID and the attribute name are separated with '.' const dotIndex = value.indexOf('.'); if (dotIndex === -1) { throw new Error(`Short-form Fn::GetAtt must contain a '.' in its string argument, got: '${value}'`); } logicalId = value.substr(0, dotIndex); attributeName = value.substr(dotIndex + 1); // the +1 is to skip the actual '.' stringForm = true; } else { // ...or a 2-element list logicalId = value[0]; attributeName = value[1]; stringForm = false; } const target = this.finder.findResource(logicalId); if (!target) { throw new Error(`Resource used in GetAtt expression with logical ID: '${logicalId}' not found`); } return cfn_reference_1.CfnReference.for(target, attributeName, stringForm ? cfn_reference_1.ReferenceRendering.GET_ATT_STRING : undefined); } case 'Fn::Join': { // Fn::Join takes a 2-element list as its argument, // where the first element is the delimiter, // and the second is the list of elements to join const value = this.parseValue(object[key]); // wrap the array as a Token, // as otherwise Fn.join() will try to concatenate // the non-token parts, // causing a diff with the original template return cfn_fn_1.Fn.join(value[0], lazy_1.Lazy.listValue({ produce: () => value[1] })); } case 'Fn::Cidr': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.cidr(value[0], value[1], value[2]); } case 'Fn::FindInMap': { const value = this.parseValue(object[key]); // the first argument to FindInMap is the mapping name const mapping = this.finder.findMapping(value[0]); if (!mapping) { throw new Error(`Mapping used in FindInMap expression with name '${value[0]}' was not found in the template`); } return cfn_fn_1.Fn.findInMap(mapping.logicalId, value[1], value[2]); } case 'Fn::Select': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.select(value[0], value[1]); } case 'Fn::GetAZs': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.getAzs(value); } case 'Fn::ImportValue': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.importValue(value); } case 'Fn::Split': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.split(value[0], value[1]); } case 'Fn::Transform': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.transform(value.Name, value.Parameters); } case 'Fn::Base64': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.base64(value); } case 'Fn::If': { // Fn::If takes a 3-element list as its argument, // where the first element is the name of a Condition const value = this.parseValue(object[key]); const condition = this.finder.findCondition(value[0]); if (!condition) { throw new Error(`Condition '${value[0]}' used in an Fn::If expression does not exist in the template`); } return cfn_fn_1.Fn.conditionIf(condition.logicalId, value[1], value[2]); } case 'Fn::Equals': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.conditionEquals(value[0], value[1]); } case 'Fn::And': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.conditionAnd(...value); } case 'Fn::Not': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.conditionNot(value[0]); } case 'Fn::Or': { const value = this.parseValue(object[key]); return cfn_fn_1.Fn.conditionOr(...value); } case 'Fn::Sub': { const value = this.parseValue(object[key]); let fnSubString; let map; if (typeof value === 'string') { fnSubString = value; map = undefined; } else { fnSubString = value[0]; map = value[1]; } return cfn_fn_1.Fn.sub(this.parseFnSubString(fnSubString, map), map); } case 'Condition': { // a reference to a Condition from another Condition const condition = this.finder.findCondition(object[key]); if (!condition) { throw new Error(`Referenced Condition with name '${object[key]}' was not found in the template`); } return { Condition: condition.logicalId }; } default: if (this.options.context === CfnParsingContext.RULES) { return this.handleRulesIntrinsic(key, object); } else { throw new Error(`Unsupported CloudFormation function '${key}'`); } } } looksLikeCfnIntrinsic(object) { const objectKeys = Object.keys(object); // a CFN intrinsic is always an object with a single key if (objectKeys.length !== 1) { return undefined; } const key = objectKeys[0]; return key === 'Ref' || key.startsWith('Fn::') || // special intrinsic only available in the 'Conditions' section (this.options.context === CfnParsingContext.CONDITIONS && key === 'Condition') ? key : undefined; } parseFnSubString(value, map = {}) { const leftBrace = value.indexOf('${'); const rightBrace = value.indexOf('}') + 1; // don't include left and right braces when searching for the target of the reference if (leftBrace === -1 || leftBrace >= rightBrace) { return value; } const leftHalf = value.substring(0, leftBrace); const rightHalf = value.substring(rightBrace); const refTarget = value.substring(leftBrace + 2, rightBrace - 1).trim(); if (refTarget[0] === '!') { return value.substring(0, rightBrace) + this.parseFnSubString(rightHalf, map); } // lookup in map if (refTarget in map) { return leftHalf + '${' + refTarget + '}' + this.parseFnSubString(rightHalf, map); } // since it's not in the map, check if it's a pseudo parameter const specialRef = this.specialCaseSubRefs(refTarget); if (specialRef !== undefined) { return leftHalf + specialRef + this.parseFnSubString(rightHalf, map); } const dotIndex = refTarget.indexOf('.'); const isRef = dotIndex === -1; if (isRef) { const refElement = this.finder.findRefTarget(refTarget); if (!refElement) { throw new Error(`Element referenced in Fn::Sub expression with logical ID: '${refTarget}' was not found in the template`); } return leftHalf + cfn_reference_1.CfnReference.for(refElement, 'Ref', cfn_reference_1.ReferenceRendering.FN_SUB).toString() + this.parseFnSubString(rightHalf, map); } else { const targetId = refTarget.substring(0, dotIndex); const refResource = this.finder.findResource(targetId); if (!refResource) { throw new Error(`Resource referenced in Fn::Sub expression with logical ID: '${targetId}' was not found in the template`); } const attribute = refTarget.substring(dotIndex + 1); return leftHalf + cfn_reference_1.CfnReference.for(refResource, attribute, cfn_reference_1.ReferenceRendering.FN_SUB).toString() + this.parseFnSubString(rightHalf, map); } } handleRulesIntrinsic(key, object) { // Rules have their own set of intrinsics: // https://docs.aws.amazon.com/servicecatalog/latest/adminguide/intrinsic-function-reference-rules.html switch (key) { case 'Fn::ValueOf': { // ValueOf is special, // as it takes the name of a Parameter as its first argument const value = this.parseValue(object[key]); const parameterName = value[0]; if (parameterName in this.parameters) { // since ValueOf returns the value of a specific attribute, // fail here - this substitution is not allowed throw new Error(`Cannot substitute parameter '${parameterName}' used in Fn::ValueOf expression with attribute '${value[1]}'`); } const param = this.finder.findRefTarget(parameterName); if (!param) { throw new Error(`Rule references parameter '${parameterName}' which was not found in the template`); } // create an explicit IResolvable, // as Fn.valueOf() returns a string, // which is incorrect // (Fn::ValueOf can also return an array) return lazy_1.Lazy.anyValue({ produce: () => ({ 'Fn::ValueOf': [param.logicalId, value[1]] }) }); } default: // I don't want to hard-code the list of supported Rules-specific intrinsics in this function; // so, just return undefined here, // and they will be treated as a regular JSON object return undefined; } } specialCaseRefs(value) { if (value in this.parameters) { return this.parameters[value]; } switch (value) { case 'AWS::AccountId': return cfn_pseudo_1.Aws.ACCOUNT_ID; case 'AWS::Region': return cfn_pseudo_1.Aws.REGION; case 'AWS::Partition': return cfn_pseudo_1.Aws.PARTITION; case 'AWS::URLSuffix': return cfn_pseudo_1.Aws.URL_SUFFIX; case 'AWS::NotificationARNs': return cfn_pseudo_1.Aws.NOTIFICATION_ARNS; case 'AWS::StackId': return cfn_pseudo_1.Aws.STACK_ID; case 'AWS::StackName': return cfn_pseudo_1.Aws.STACK_NAME; case 'AWS::NoValue': return cfn_pseudo_1.Aws.NO_VALUE; default: return undefined; } } specialCaseSubRefs(value) { if (value in this.parameters) { return this.parameters[value]; } return value.indexOf('::') === -1 ? undefined : '${' + value + '}'; } get parameters() { return this.options.parameters || {}; } } exports.CfnParser = CfnParser; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ZuLXBhcnNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2ZuLXBhcnNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLHFDQUE4QjtBQUU5Qiw2Q0FBbUM7QUFFbkMsK0RBRytCO0FBRS9CLGlDQUE4QjtBQUM5QiwyREFBMkU7QUFHM0UsbUNBQW9EO0FBQ3BELGlDQUFzRDtBQUV0RDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFhLGtCQUFrQjtJQUM3QixtQ0FBbUM7SUFDNUIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFVLElBQUksT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBRTNDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBVTtRQUNqQyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixtREFBbUQ7WUFDbkQsUUFBUSxLQUFLLEVBQUU7Z0JBQ2IsS0FBSyxNQUFNLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQztnQkFDekIsS0FBSyxPQUFPLENBQUMsQ0FBQyxPQUFPLEtBQUssQ0FBQztnQkFDM0IsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyx1REFBdUQsS0FBSyxHQUFHLENBQUMsQ0FBQzthQUMzRjtTQUNGO1FBRUQsNkNBQTZDO1FBQzdDLG1EQUFtRDtRQUNuRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFTSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQVU7UUFDOUIscURBQXFEO1FBQ3JELElBQUksMEJBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDN0IsT0FBTyxLQUFLLENBQUM7U0FDZDtRQUVELHFEQUFxRDtRQUNyRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3hCO1FBRUQsMkNBQTJDO1FBQzNDLGtEQUFrRDtRQUNsRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCw0RUFBNEU7SUFD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