@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
598 lines • 86.9 kB
JavaScript
"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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