Package: aws-cdk.core
AWS Cloud Development Kit Core Library---AWS CDK v1 has reached End-of-Support on 2023-06-01.
This package is no longer being updated, and users should migrate to AWS CDK v2.For more information on how to migrate, see theMigrating to AWS CDK v2guide.This library includes the basic building blocks of theAWS Cloud Development Kit(AWS CDK). It defines the core classes that are used in the rest of the
AWS Construct Library.See theAWS CDK Developer
Guidefor
information of most of the capabilities of this library. The rest of this
README will only cover topics not already covered in the Developer Guide.Stacks and StagesAStackis the smallest physical unit of deployment, and maps directly onto
a CloudFormation Stack. You define a Stack by defining a subclass ofStack-- let's call itMyStack-- and instantiating the constructs that make up
your application inMyStack's constructor. You then instantiate this stack
one or more times to define different instances of your application. For example,
you can instantiate it once using few and cheap EC2 instances for testing,
and once again using more and bigger EC2 instances for production.When your application grows, you may decide that it makes more sense to split it
out across multipleStackclasses. This can happen for a number of reasons:You could be starting to reach the maximum number of resources allowed in a single
stack (this is currently 500).You could decide you want to separate out stateful resources and stateless resources
into separate stacks, so that it becomes easy to tear down and recreate the stacks
that don't have stateful resources.There could be a single stack with resources (like a VPC) that are shared
between multiple instances of other stacks containing your applications.As soon as your conceptual application starts to encompass multiple stacks,
it is convenient to wrap them in another construct that represents your
logical application. You can then treat that new unit the same way you used
to be able to treat a single stack: by instantiating it multiple times
for different instances of your application.You can define a custom subclass ofStage, holding one or moreStacks, to represent a single logical instance of your application.As a final note:Stacks are not a unit of reuse. They describe physical
deployment layouts, and as such are best left to application builders to
organize their deployments with. If you want to vend a reusable construct,
define it as a subclasses ofConstruct: the consumers of your construct
will decide where to place it in their own stacks.Stack SynthesizersEach Stack has asynthesizer, an object that determines how and where
the Stack should be synthesized and deployed. The synthesizer controls
aspects like:How does the stack reference assets? (Either through CloudFormation
parameters the CLI supplies, or because the Stack knows a predefined
location where assets will be uploaded).What roles are used to deploy the stack? These can be bootstrapped
roles, roles created in some other way, or just the CLI's current
credentials.The following synthesizers are available:DefaultStackSynthesizer: recommended. Uses predefined asset locations and
roles created by the modern bootstrap template. Access control is done by
controlling who can assume the deploy role. This is the default stack
synthesizer in CDKv2.LegacyStackSynthesizer: Uses CloudFormation parameters to communicate
asset locations, and the CLI's current permissions to deploy stacks. The
is the default stack synthesizer in CDKv1.CliCredentialsStackSynthesizer: Uses predefined asset locations, and the
CLI's current permissions.Each of these synthesizers takes configuration arguments. To configure
a stack with a synthesizer, pass it as one of its properties:MyStack(app,"MyStack",synthesizer=DefaultStackSynthesizer(file_assets_bucket_name="my-orgs-asset-bucket"))For more information on bootstrapping accounts and customizing synthesis,
seeBootstrapping in the CDK Developer Guide.Nested StacksNested stacksare stacks created as part of other stacks. You create a nested stack within another stack by using theNestedStackconstruct.As your infrastructure grows, common patterns can emerge in which you declare the same components in multiple templates. You can separate out these common components and create dedicated templates for them. Then use the resource in your template to reference other templates, creating nested stacks.For example, assume that you have a load balancer configuration that you use for most of your stacks. Instead of copying and pasting the same configurations into your templates, you can create a dedicated template for the load balancer. Then, you just use the resource to reference that template from within other templates.The following example will define a single top-level stack that contains two nested stacks: each one with a single Amazon S3 bucket:classMyNestedStack(cfn.NestedStack):def__init__(self,scope,id,*,parameters=None,timeout=None,notifications=None):super().__init__(scope,id,parameters=parameters,timeout=timeout,notifications=notifications)s3.Bucket(self,"NestedBucket")classMyParentStack(Stack):def__init__(self,scope,id,*,description=None,env=None,stackName=None,tags=None,synthesizer=None,terminationProtection=None,analyticsReporting=None):super().__init__(scope,id,description=description,env=env,stackName=stackName,tags=tags,synthesizer=synthesizer,terminationProtection=terminationProtection,analyticsReporting=analyticsReporting)MyNestedStack(self,"Nested1")MyNestedStack(self,"Nested2")Resources references across nested/parent boundaries (even with multiple levels of nesting) will be wired by the AWS CDK
through CloudFormation parameters and outputs. When a resource from a parent stack is referenced by a nested stack,
a CloudFormation parameter will automatically be added to the nested stack and assigned from the parent; when a resource
from a nested stack is referenced by a parent stack, a CloudFormation output will be automatically be added to the
nested stack and referenced usingFn::GetAtt "Outputs.Xxx"from the parent.Nested stacks also support the use of Docker image and file assets.Accessing resources in a different stackYou can access resources in a different stack, as long as they are in the
same account and AWS Region. The following example defines the stackstack1,
which defines an Amazon S3 bucket. Then it defines a second stack,stack2,
which takes the bucket from stack1 as a constructor property.prod={"account":"123456789012","region":"us-east-1"}stack1=StackThatProvidesABucket(app,"Stack1",env=prod)# stack2 will take a property { bucket: IBucket }stack2=StackThatExpectsABucket(app,"Stack2",bucket=stack1.bucket,env=prod)If the AWS CDK determines that the resource is in the same account and
Region, but in a different stack, it automatically synthesizes AWS
CloudFormationExportsin the producing stack and anFn::ImportValuein the consuming stack to transfer that information from one stack to the
other.Removing automatic cross-stack referencesThe automatic references created by CDK when you use resources across stacks
are convenient, but may block your deployments if you want to remove the
resources that are referenced in this way. You will see an error like:Export Stack1:ExportsOutputFnGetAtt-****** cannot be deleted as it is in use by Stack1Let's say there is a Bucket in thestack1, and thestack2references itsbucket.bucketName. You now want to remove the bucket and run into the error above.It's not safe to removestack1.bucketwhilestack2is still using it, so
unblocking yourself from this is a two-step process. This is how it works:DEPLOYMENT 1: break the relationshipMake surestack2no longer referencesbucket.bucketName(maybe the consumer
stack now uses its own bucket, or it writes to an AWS DynamoDB table, or maybe you just
remove the Lambda Function altogether).In thestack1class, callthis.exportValue(this.bucket.bucketName). This
will make sure the CloudFormation Export continues to exist while the relationship
between the two stacks is being broken.Deploy (this will effectively only change thestack2, but it's safe to deploy both).DEPLOYMENT 2: remove the resourceYou are now free to remove thebucketresource fromstack1.Don't forget to remove theexportValue()call as well.Deploy again (this time only thestack1will be changed -- the bucket will be deleted).DurationsTo make specifications of time intervals unambiguous, a single class calledDurationis used throughout the AWS Construct Library by all constructs
that that take a time interval as a parameter (be it for a timeout, a
rate, or something else).An instance of Duration is constructed by using one of the static factory
methods on it:Duration.seconds(300)# 5 minutesDuration.minutes(5)# 5 minutesDuration.hours(1)# 1 hourDuration.days(7)# 7 daysDuration.parse("PT5M")Durations can be added or subtracted together:Duration.minutes(1).plus(Duration.seconds(60))# 2 minutesDuration.minutes(5).minus(Duration.seconds(10))Size (Digital Information Quantity)To make specification of digital storage quantities unambiguous, a class calledSizeis available.An instance ofSizeis initialized through one of its static factory methods:Size.kibibytes(200)# 200 KiBSize.mebibytes(5)# 5 MiBSize.gibibytes(40)# 40 GiBSize.tebibytes(200)# 200 TiBSize.pebibytes(3)Instances ofSizecreated with one of the units can be converted into others.
By default, conversion to a higher unit will fail if the conversion does not produce
a whole number. This can be overridden by unsettingintegralproperty.Size.mebibytes(2).to_kibibytes()# yields 2048Size.kibibytes(2050).to_mebibytes(rounding=SizeRoundingBehavior.FLOOR)SecretsTo help avoid accidental storage of secrets as plain text, we use theSecretValuetype to
represent secrets. Any construct that takes a value that should be a secret (such as
a password or an access key) will take a parameter of typeSecretValue.The best practice is to store secrets in AWS Secrets Manager and reference them usingSecretValue.secretsManager:secret=SecretValue.secrets_manager("secretId",json_field="password",# optional: key of a JSON field to retrieve (defaults to all content),version_id="id",# optional: id of the version (default AWSCURRENT)version_stage="stage")Using AWS Secrets Manager is the recommended way to reference secrets in a CDK app.SecretValuealso supports the following secret sources:SecretValue.unsafePlainText(secret): stores the secret as plain text in your app and the resulting template (not recommended).SecretValue.secretsManager(secret): refers to a secret stored in Secrets ManagerSecretValue.ssmSecure(param, version): refers to a secret stored as a SecureString in the SSM
Parameter Store. If you don't specify the exact version, AWS CloudFormation uses the latest
version of the parameter.SecretValue.cfnParameter(param): refers to a secret passed through a CloudFormation parameter (must haveNoEcho: true).SecretValue.cfnDynamicReference(dynref): refers to a secret described by a CloudFormation dynamic reference (used byssmSecureandsecretsManager).SecretValue.resourceAttribute(attr): refers to a secret returned from a CloudFormation resource creation.SecretValues should only be passed to constructs that accept properties of typeSecretValue. These constructs are written to ensure your secrets will not be
exposed where they shouldn't be. If you try to use aSecretValuein a
different location, an error about unsafe secret usage will be thrown at
synthesis time.ARN manipulationSometimes you will need to put together or pick apart Amazon Resource Names
(ARNs). The functionsstack.formatArn()andstack.parseArn()exist for
this purpose.formatArn()can be used to build an ARN from components. It will automatically
use the region and account of the stack you're calling it on:# stack: Stack# Builds "arn:<PARTITION>:lambda:<REGION>:<ACCOUNT>:function:MyFunction"stack.format_arn(service="lambda",resource="function",sep=":",resource_name="MyFunction")parseArn()can be used to get a single component from an ARN.parseArn()will correctly deal with both literal ARNs and deploy-time values (tokens),
but in case of a deploy-time value be aware that the result will be another
deploy-time value which cannot be inspected in the CDK application.# stack: Stack# Extracts the function name out of an AWS Lambda Function ARNarn_components=stack.parse_arn(arn,":")function_name=arn_components.resource_nameNote that depending on the service, the resource separator can be either:or/, and the resource name can be either the 6th or 7th
component in the ARN. When using these functions, you will need to know
the format of the ARN you are dealing with.For an exhaustive list of ARN formats used in AWS, seeAWS ARNs and
Namespacesin the AWS General Reference.DependenciesConstruct DependenciesSometimes AWS resources depend on other resources, and the creation of one
resource must be completed before the next one can be started.In general, CloudFormation will correctly infer the dependency relationship
between resources based on the property values that are used. In the cases where
it doesn't, the AWS Construct Library will add the dependency relationship for
you.If you need to add an ordering dependency that is not automatically inferred,
you do so by adding a dependency relationship usingconstructA.node.addDependency(constructB). This will add a dependency
relationship between all resources in the scope ofconstructAand all
resources in the scope ofconstructB.If you want a single object to represent a set of constructs that are not
necessarily in the same scope, you can use aConcreteDependable. The
following creates a single object that represents a dependency on two
constructs,constructBandconstructC:# Declare the dependable objectb_and_c=ConcreteDependable()b_and_c.add(construct_b)b_and_c.add(construct_c)# Take the dependencyconstruct_a.node.add_dependency(b_and_c)Stack DependenciesTwo different stack instances can have a dependency on one another. This
happens when an resource from one stack is referenced in another stack. In
that case, CDK records the cross-stack referencing of resources,
automatically produces the right CloudFormation primitives, and adds a
dependency between the two stacks. You can also manually add a dependency
between two stacks by using thestackA.addDependency(stackB)method.A stack dependency has the following implications:Cyclic dependencies are not allowed, so ifstackAis using resources fromstackB, the reverse is not possible anymore.Stacks with dependencies between them are treated specially by the CDK
toolkit:IfstackAdepends onstackB, runningcdk deploy stackAwill also
automatically deploystackB.stackB's deployment will be performedbeforestackA's deployment.Custom ResourcesCustom Resources are CloudFormation resources that are implemented by arbitrary
user code. They can do arbitrary lookups or modifications during a
CloudFormation deployment.To define a custom resource, use theCustomResourceconstruct:CustomResource(self,"MyMagicalResource",resource_type="Custom::MyCustomResource",# must start with 'Custom::'# the resource propertiesproperties={"Property1":"foo","Property2":"bar"},# the ARN of the provider (SNS/Lambda) which handles# CREATE, UPDATE or DELETE events for this resource type# see next section for detailsservice_token="ARN")Custom Resource ProvidersCustom resources are backed by acustom resource providerwhich can be
implemented in one of the following ways. The following table compares the
various provider types (ordered from low-level to high-level):ProviderCompute TypeError HandlingSubmit to CloudFormationMax TimeoutLanguageFootprintsns.TopicSelf-managedManualManualUnlimitedAnyDependslambda.FunctionAWS LambdaManualManual15minAnySmallcore.CustomResourceProviderLambdaAutoAuto15minNode.jsSmallcustom-resources.ProviderLambdaAutoAutoUnlimited AsyncAnyLargeLegend:Compute type: which type of compute can is used to execute the handler.Error Handling: whether errors thrown by handler code are automatically
trapped and a FAILED response is submitted to CloudFormation. If this is
"Manual", developers must take care of trapping errors. Otherwise, events
could cause stacks to hang.Submit to CloudFormation: whether the framework takes care of submitting
SUCCESS/FAILED responses to CloudFormation through the event's response URL.Max Timeout: maximum allows/possible timeout.Language: which programming languages can be used to implement handlers.Footprint: how many resources are used by the provider framework itself.A NOTE ABOUT SINGLETONSWhen defining resources for a custom resource provider, you will likely want to
define them as astack singletonso that only a single instance of the
provider is created in your stack and which is used by all custom resources of
that type.Here is a basic pattern for defining stack singletons in the CDK. The following
examples ensures that only a single SNS topic is defined:defget_or_create(self,scope):stack=Stack.of(scope)uniqueid="GloballyUniqueIdForSingleton"# For example, a UUID from `uuidgen`existing=stack.node.try_find_child(uniqueid)ifexisting:returnexistingreturnsns.Topic(stack,uniqueid)Amazon SNS TopicEvery time a resource event occurs (CREATE/UPDATE/DELETE), an SNS notification
is sent to the SNS topic. Users must process these notifications (e.g. through a
fleet of worker hosts) and submit success/failure responses to the
CloudFormation service.SetserviceTokentotopic.topicArnin order to use this provider:topic=sns.Topic(self,"MyProvider")CustomResource(self,"MyResource",service_token=topic.topic_arn)AWS Lambda FunctionAn AWS lambda function is calleddirectlyby CloudFormation for all resource
events. The handler must take care of explicitly submitting a success/failure
response to the CloudFormation service and handle various error cases.SetserviceTokentolambda.functionArnto use this provider:fn=lambda_.Function(self,"MyProvider",function_props)CustomResource(self,"MyResource",service_token=fn.function_arn)Thecore.CustomResourceProviderclassThe class@aws-cdk/core.CustomResourceProvideroffers a basic low-level
framework designed to implement simple and slim custom resource providers. It
currently only supports Node.js-based user handlers, and it does not have
support for asynchronous waiting (handler cannot exceed the 15min lambda
timeout).The provider has a built-in singleton method which uses the resource type as a
stack-unique identifier and returns the service token:service_token=CustomResourceProvider.get_or_create(self,"Custom::MyCustomResourceType",code_directory=f"{__dirname}/my-handler",runtime=CustomResourceProviderRuntime.NODEJS_14_X,description="Lambda function created by the custom resource provider")CustomResource(self,"MyResource",resource_type="Custom::MyCustomResourceType",service_token=service_token)The directory (my-handlerin the above example) must include anindex.jsfile. It cannot import
external dependencies or files outside this directory. It must export an async
function namedhandler. This function accepts the CloudFormation resource
event object and returns an object with the following structure:exports.handler=asyncfunction(event){constid=event.PhysicalResourceId;// only for "Update" and "Delete"constprops=event.ResourceProperties;constoldProps=event.OldResourceProperties;// only for "Update"sswitch(event.RequestType){case"Create":// ...case"Update":// ...// if an error is thrown, a FAILED response will be submitted to CFNthrownewError('Failed!');case"Delete":// ...}return{// (optional) the value resolved from `resource.ref`// defaults to "event.PhysicalResourceId" or "event.RequestId"PhysicalResourceId:"REF",// (optional) calling `resource.getAtt("Att1")` on the custom resource in the CDK app// will return the value "BAR".Data:{Att1:"BAR",Att2:"BAZ"},// (optional) user-visible messageReason:"User-visible message",// (optional) hides values from the consoleNoEcho:true};}Here is an complete example of a custom resource that summarizes two numbers:sum-handler/index.js:exports.handler=async(e)=>{return{Data:{Result:e.ResourceProperties.lhs+e.ResourceProperties.rhs,},};};sum.ts:fromaws_cdk.coreimportConstruct,CustomResource,CustomResourceProvider,CustomResourceProviderRuntime,TokenclassSum(Construct):def__init__(self,scope,id,*,lhs,rhs):super().__init__(scope,id)resource_type="Custom::Sum"service_token=CustomResourceProvider.get_or_create(self,resource_type,code_directory=f"{__dirname}/sum-handler",runtime=CustomResourceProviderRuntime.NODEJS_14_X)resource=CustomResource(self,"Resource",resource_type=resource_type,service_token=service_token,properties={"lhs":lhs,"rhs":rhs})self.result=Token.as_number(resource.get_att("Result"))Usage will look like this:sum=Sum(self,"MySum",lhs=40,rhs=2)CfnOutput(self,"Result",value=Token.as_string(sum.result))To access the ARN of the provider's AWS Lambda function role, use thegetOrCreateProvider()built-in singleton method:provider=CustomResourceProvider.get_or_create_provider(self,"Custom::MyCustomResourceType",code_directory=f"{__dirname}/my-handler",runtime=CustomResourceProviderRuntime.NODEJS_14_X)role_arn=provider.role_arnThis role ARN can then be used in resource-based IAM policies.The Custom Resource Provider FrameworkThe@aws-cdk/custom-resourcesmodule includes an advanced framework for
implementing custom resource providers.Handlers are implemented as AWS Lambda functions, which means that they can be
implemented in any Lambda-supported runtime. Furthermore, this provider has an
asynchronous mode, which means that users can provide anisCompletelambda
function which is called periodically until the operation is complete. This
allows implementing providers that can take up to two hours to stabilize.SetserviceTokentoprovider.serviceTokento use this type of provider:provider=customresources.Provider(self,"MyProvider",on_event_handler=on_event_handler,is_complete_handler=is_complete_handler)CustomResource(self,"MyResource",service_token=provider.service_token)See thedocumentationfor more details.AWS CloudFormation featuresA CDK stack synthesizes to an AWS CloudFormation Template. This section
explains how this module allows users to access low-level CloudFormation
features when needed.Stack OutputsCloudFormationstack outputsand exports are created using
theCfnOutputclass:CfnOutput(self,"OutputName",value=my_bucket.bucket_name,description="The name of an S3 bucket",# Optionalexport_name="TheAwesomeBucket")ParametersCloudFormation templates support the use ofParametersto
customize a template. They enable CloudFormation users to input custom values to
a template each time a stack is created or updated. While the CDK design
philosophy favors using build-time parameterization, users may need to use
CloudFormation in a number of cases (for example, when migrating an existing
stack to the AWS CDK).Template parameters can be added to a stack by using theCfnParameterclass:CfnParameter(self,"MyParameter",type="Number",default=1337)The value of parameters can then be obtained using one of thevaluemethods.
As parameters are only resolved at deployment time, the values obtained are
placeholder tokens for the real value (Token.isUnresolved()would returntruefor those):param=CfnParameter(self,"ParameterName")# If the parameter is a Stringparam.value_as_string# If the parameter is a Numberparam.value_as_number# If the parameter is a Listparam.value_as_listPseudo ParametersCloudFormation supports a number ofpseudo parameters,
which resolve to useful values at deployment time. CloudFormation pseudo
parameters can be obtained from static members of theAwsclass.It is generally recommended to access pseudo parameters from the scope'sstackinstead, which guarantees the values produced are qualifying the designated
stack, which is essential in cases where resources are shared cross-stack:# "this" is the current constructstack=Stack.of(self)stack.account# Returns the AWS::AccountId for this stack (or the literal value if known)stack.region# Returns the AWS::Region for this stack (or the literal value if known)stack.partitionResource OptionsCloudFormation resources can also specifyresource
attributes. TheCfnResourceclass allows
accessing those through thecfnOptionsproperty:raw_bucket=s3.CfnBucket(self,"Bucket")# -or-raw_bucket_alt=my_bucket.node.default_child# thenraw_bucket.cfn_options.condition=CfnCondition(self,"EnableBucket")raw_bucket.cfn_options.metadata={"metadata_key":"MetadataValue"}Resource dependencies (theDependsOnattribute) is modified using thecfnResource.addDependsOnmethod:resource_a=CfnResource(self,"ResourceA",resource_props)resource_b=CfnResource(self,"ResourceB",resource_props)resource_b.add_depends_on(resource_a)Intrinsic Functions and Condition ExpressionsCloudFormation supportsintrinsic functions. These functions
can be accessed from theFnclass, which provides type-safe methods for each
intrinsic function as well as condition expressions:# To use Fn::Base64Fn.base64("SGVsbG8gQ0RLIQo=")# To compose condition expressions:environment_parameter=CfnParameter(self,"Environment")Fn.condition_and(# The "Environment" CloudFormation template parameter evaluates to "Production"Fn.condition_equals("Production",environment_parameter),# The AWS::Region pseudo-parameter value is NOT equal to "us-east-1"Fn.condition_not(Fn.condition_equals("us-east-1",Aws.REGION)))When working with deploy-time values (those for whichToken.isUnresolvedreturnstrue), idiomatic conditionals from the programming language cannot be
used (the value will not be known until deployment time). When conditional logic
needs to be expressed with un-resolved values, it is necessary to use
CloudFormation conditions by means of theCfnConditionclass:environment_parameter=CfnParameter(self,"Environment")is_prod=CfnCondition(self,"IsProduction",expression=Fn.condition_equals("Production",environment_parameter))# Configuration value that is a different string based on IsProductionstage=Fn.condition_if(is_prod.logical_id,"Beta","Prod").to_string()# Make Bucket creation condition to IsProduction by accessing# and overriding the CloudFormation resourcebucket=s3.Bucket(self,"Bucket")cfn_bucket=my_bucket.node.default_childcfn_bucket.cfn_options.condition=is_prodMappingsCloudFormationmappingsare created and queried using theCfnMappingsclass:region_table=CfnMapping(self,"RegionTable",mapping={"us-east-1":{"region_name":"US East (N. Virginia)"},"us-east-2":{"region_name":"US East (Ohio)"}})region_table.find_in_map(Aws.REGION,"regionName")This will yield the following template:Mappings:RegionTable:us-east-1:regionName:US East (N. Virginia)us-east-2:regionName:US East (Ohio)Mappings can also be synthesized "lazily"; lazy mappings will only render a "Mappings"
section in the synthesized CloudFormation template if somefindInMapcall is unable to
immediately return a concrete value due to one or both of the keys being unresolved tokens
(some value only available at deploy-time).For example, the following code will not produce anything in the "Mappings" section. The
call tofindInMapwill be able to resolve the value during synthesis and simply return'US East (Ohio)'.region_table=CfnMapping(self,"RegionTable",mapping={"us-east-1":{"region_name":"US East (N. Virginia)"},"us-east-2":{"region_name":"US East (Ohio)"}},lazy=True)region_table.find_in_map("us-east-2","regionName")On the other hand, the following code will produce the "Mappings" section shown above,
since the top-level key is an unresolved token. The call tofindInMapwill return a token that resolves to{ "Fn::FindInMap": [ "RegionTable", { "Ref": "AWS::Region" }, "regionName" ] }.# region_table: CfnMappingregion_table.find_in_map(Aws.REGION,"regionName")Dynamic ReferencesCloudFormation supportsdynamically resolvingvalues
for SSM parameters (including secure strings) and Secrets Manager. Encoding such
references is done using theCfnDynamicReferenceclass:CfnDynamicReference(CfnDynamicReferenceService.SECRETS_MANAGER,"secret-id:secret-string:json-key:version-stage:version-id")Template Options & TransformCloudFormation templates support a number of options, including which Macros orTransformsto use when deploying the stack. Those can be
configured using thestack.templateOptionsproperty:stack=Stack(app,"StackName")stack.template_options.description="This will appear in the AWS console"stack.template_options.transforms=["AWS::Serverless-2016-10-31"]stack.template_options.metadata={"metadata_key":"MetadataValue"}Emitting Raw ResourcesTheCfnResourceclass allows emitting arbitrary entries in theResourcessection of the CloudFormation template.CfnResource(self,"ResourceId",type="AWS::S3::Bucket",properties={"BucketName":"bucket-name"})As for any other resource, the logical ID in the CloudFormation template will be
generated by the AWS CDK, but the type and properties will be copied verbatim in
the synthesized template.Including raw CloudFormation template fragmentsWhen migrating a CloudFormation stack to the AWS CDK, it can be useful to
include fragments of an existing template verbatim in the synthesized template.
This can be achieved using theCfnIncludeclass.CfnInclude(self,"ID",template={"Resources":{"Bucket":{"Type":"AWS::S3::Bucket","Properties":{"BucketName":"my-shiny-bucket"}}}})Termination ProtectionYou can prevent a stack from being accidentally deleted by enabling termination
protection on the stack. If a user attempts to delete a stack with termination
protection enabled, the deletion fails and the stack--including its status--remains
unchanged. Enabling or disabling termination protection on a stack sets it for any
nested stacks belonging to that stack as well. You can enable termination protection
on a stack by setting theterminationProtectionprop totrue.stack=Stack(app,"StackName",termination_protection=True)By default, termination protection is disabled.CfnJsonCfnJsonallows you to postpone the resolution of a JSON blob from
deployment-time. This is useful in cases where the CloudFormation JSON template
cannot express a certain value.A common example is to useCfnJsonin order to render a JSON map which needs
to use intrinsic functions in keys. Since JSON map keys must be strings, it is
impossible to use intrinsics in keys andCfnJsoncan help.The following example defines an IAM role which can only be assumed by
principals that are tagged with a specific tag.tag_param=CfnParameter(self,"TagName")string_equals=CfnJson(self,"ConditionJson",value={"f"aws:PrincipalTag/{tagParam.valueAsString}"":True})principal=iam.AccountRootPrincipal().with_conditions({"StringEquals":string_equals})iam.Role(self,"MyRole",assumed_by=principal)Explanation: since in this example we pass the tag name through a parameter, it
can only be resolved during deployment. The resolved value can be represented in
the template through a{ "Ref": "TagName" }. However, since we want to use
this value inside aaws:PrincipalTag/TAG-NAMEIAM operator, we need it in thekeyof aStringEqualscondition. JSON keysmust bestrings, so to circumvent this limitation, we useCfnJsonto "delay" the rendition of this template section to deploy-time. This means
that the value ofStringEqualsin the template will be{ "Fn::GetAtt": [ "ConditionJson", "Value" ] }, and will only "expand" to the operator we synthesized during deployment.Stack Resource LimitWhen deploying to AWS CloudFormation, it needs to keep in check the amount of resources being added inside a Stack. Currently it's possible to check the limits in theAWS CloudFormation quotaspage.It's possible to synthesize the project with more Resources than the allowed (or even reduce the number of Resources).Set the context key@aws-cdk/core:stackResourceLimitwith the proper value, being 0 for disable the limit of resources.