{"id":4126,"date":"2021-03-07T16:05:08","date_gmt":"2021-03-07T15:05:08","guid":{"rendered":"http:\/\/miro.borodziuk.eu\/?p=4126"},"modified":"2021-06-28T11:23:52","modified_gmt":"2021-06-28T09:23:52","slug":"cloudformation","status":"publish","type":"post","link":"http:\/\/miro.borodziuk.eu\/index.php\/2021\/03\/07\/cloudformation\/","title":{"rendered":"CloudFormation &#8211; 1"},"content":{"rendered":"<p><!--more--><\/p>\n<p><span style=\"color: #3366ff;\">What is CloudFormation<\/span><\/p>\n<ul>\n<li>CloudFormation is a declarative way of outlining your AWS Infrastructure, for any resources (most of them are supported).<\/li>\n<li>For example, within a CloudFormation template, you say\n<ul>\n<li>I want a security group<\/li>\n<li>I want two EC2 machines using this security group<\/li>\n<li>I want two Elastic IPs for these EC2 machines<\/li>\n<li>I want an S3 bucket<\/li>\n<li>I want a load balancer (ELB) in front of these machines<\/li>\n<\/ul>\n<\/li>\n<li>Then CloudFormation creates those for you, in the right order, with the exact configuration that you specify.<\/li>\n<\/ul>\n<p>Benefits of AWS CloudFormation<\/p>\n<ul>\n<li>Infrastructure as code<\/li>\n<li>No resources are manually created, which is excellent for control<\/li>\n<li>The code can be version controlled for example using git<\/li>\n<li>Changes to the infrastructure are reviewed through code<\/li>\n<li>Cost\n<ul>\n<li>Each resources within the stack is stagged with an identifier so you can easily see how much a stack costs you<\/li>\n<li>You can estimate the costs of your resources using the CloudFormation template<\/li>\n<li>Savings strategy: In Dev, you could automation deletion of templates at 5 Pm and recreated at 8 Am, safely<\/li>\n<\/ul>\n<\/li>\n<li>Productivity\n<ul>\n<li>Ability to destroy and re-create an infrastructure on the cloud on the fly<\/li>\n<li>Automated generation of Diagram for your templates!<\/li>\n<li>Declarative programming (no need to figure out ordering and orchestration)<\/li>\n<\/ul>\n<\/li>\n<li>Separation of concern: create many stacks for many apps, and many layers. Ex:\n<ul>\n<li>VPC stacks<\/li>\n<li>Network stacks<\/li>\n<li>App stacks<\/li>\n<\/ul>\n<\/li>\n<li>Don&#8217;t re-invent the wheel\n<ul>\n<li>Leverage existing templates on the web!<\/li>\n<li>Leverage the documentation<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"color: #3366ff;\">How CloudFormation Works<\/span><\/p>\n<ul>\n<li>Templates have to be uploaded in S3 and then referenced in CloudFormation<\/li>\n<li>To update a template, we can&#8217;t edit previous ones. We have to re-upload a new version of the template to AWS<\/li>\n<li>Stacks are identified by a name<\/li>\n<li>Deleting a stack deletes every single artifact that was created by CloudFormation.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Deploying CloudFormation templates<\/span><\/p>\n<ul>\n<li>Manual way:\n<ul>\n<li>Editing templates in the CloudFormation Designer<\/li>\n<li>Using the console to input parameters, etc<\/li>\n<\/ul>\n<\/li>\n<li>Automated way:\n<ul>\n<li>Editing templates in aYAML file<\/li>\n<li>Using the AWS CLI (Command Line Interface) to deploy the templates<\/li>\n<li>Recommended way when you fully want to automate your flow<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">CloudFormation Building Blocks<\/span><\/p>\n<ul>\n<li>Templates components (one course section for each):\n<ol>\n<li>Resources: your AWS resources declared in the template (MANDATORY)<\/li>\n<li>Parameters: the dynamic inputs for your template<\/li>\n<li>Mappings:the static variables for your template<\/li>\n<li>Outputs: References to what has been created<\/li>\n<li>Conditionals: List of conditions to perform resource creation<\/li>\n<li>Metadata<\/li>\n<\/ol>\n<\/li>\n<li>Templates helpers:\n<ol>\n<li>References<\/li>\n<li>Functions<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Consider such an yaml file<\/p>\n<div>\n<pre class=\"lang:default decode:true\">---\r\nResources:\r\n  MyEC2Instance:\r\n    Type: AWS::EC2::Instance\r\n    Properties:\r\n      AvailabilityZone: eu-central-1a\r\n      ImageId: ami-00a205cb8e06c3c4e\r\n      InstanceType: t2.micro\r\n<\/pre>\n<p>Create a stack in North Virginia:<\/p>\n<\/div>\n<p><code>CloudFormation -&gt; Stacks -&gt; Create stack<\/code><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4129 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation01.jpg\" alt=\"\" width=\"723\" height=\"698\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation01.jpg 723w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation01-300x290.jpg 300w\" sizes=\"(max-width: 723px) 100vw, 723px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4131 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation02.jpg\" alt=\"\" width=\"721\" height=\"481\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation02.jpg 721w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation02-300x200.jpg 300w\" sizes=\"(max-width: 721px) 100vw, 721px\" \/><\/p>\n<p><code>Next -&gt; Create stack<\/code><\/p>\n<p>At the EC2 -&gt; Instances we can see that our EC2 instance has been created.<\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Update and delete the stack<\/span><\/p>\n<p>Now, let&#8217;s update the stack.<\/p>\n<p><code>CloudFormation -&gt; Stacks -&gt; MyFirstCloudFormationTemplate -&gt; Update stack -&gt; Upload a temple file<\/code><\/p>\n<pre class=\"lang:default decode:true \">---\r\nParameters:\r\n\u00a0\u00a0SecurityGroupDescription:\r\n\u00a0\u00a0\u00a0\u00a0Description: Security Group Description\r\n\u00a0\u00a0\u00a0\u00a0Type: String\r\n\r\n\r\nResources:\r\n\u00a0\u00a0MyEC2Instance:\r\n\u00a0\u00a0\u00a0\u00a0Type: AWS::EC2::Instance\r\n\u00a0\u00a0\u00a0\u00a0Properties:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0AvailabilityZone: eu-central-1a\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ImageId: ami-00a205cb8e06c3c4e\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0InstanceType: t2.micro\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SecurityGroups:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- !Ref SSHSecurityGroup\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- !Ref ServerSecurityGroup\r\n\r\n\r\n\u00a0\u00a0# an elastic IP for our instance\r\n\u00a0\u00a0MyEIP:\r\n\u00a0\u00a0\u00a0\u00a0Type: AWS::EC2::EIP\r\n\u00a0\u00a0\u00a0\u00a0Properties:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0InstanceId: !Ref MyEC2Instance\r\n\r\n\r\n\u00a0\u00a0# our EC2 security group\r\n\u00a0\u00a0SSHSecurityGroup:\r\n\u00a0\u00a0\u00a0\u00a0Type: AWS::EC2::SecurityGroup\r\n\u00a0\u00a0\u00a0\u00a0Properties:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0GroupDescription: Enable SSH access via port 22\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SecurityGroupIngress:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- CidrIp: 0.0.0.0\/0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FromPort: 22\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0IpProtocol: tcp\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ToPort: 22\r\n\r\n\r\n\u00a0\u00a0# our second EC2 security group\r\n\u00a0\u00a0ServerSecurityGroup:\r\n\u00a0\u00a0\u00a0\u00a0Type: AWS::EC2::SecurityGroup\r\n\u00a0\u00a0\u00a0\u00a0Properties:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0GroupDescription: !Ref SecurityGroupDescription\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SecurityGroupIngress:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- IpProtocol: tcp\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FromPort: 80\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ToPort: 80\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CidrIp: 0.0.0.0\/0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0- IpProtocol: tcp\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FromPort: 22\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ToPort: 22\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CidrIp: 192.168.1.1\/32\r\n\r\n<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-4135 aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation03.jpg\" alt=\"\" width=\"837\" height=\"291\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation03.jpg 837w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation03-300x104.jpg 300w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation03-768x267.jpg 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<p><code>Next -&gt; Next -&gt; Update Stack<\/code><\/p>\n<p>EC2 instance has been updated. Elastic IP and security group has been created.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-4138 size-full aligncenter\" src=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation05-1.jpg\" alt=\"\" width=\"651\" height=\"611\" srcset=\"http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation05-1.jpg 651w, http:\/\/miro.borodziuk.eu\/wp-content\/uploads\/CloudFormation05-1-300x282.jpg 300w\" sizes=\"(max-width: 651px) 100vw, 651px\" \/><\/p>\n<p>Now, we want to get rid off all resources we created.\u00a0 So we need to delete the stack.<\/p>\n<p><code>CloudFormation -&gt; Stacks -&gt; MyFirstCloudFormationTemplate -&gt; Delete -&gt; Delete stack<\/code><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Parameters.<\/span><\/p>\n<p>What are parameters?<\/p>\n<ul>\n<li>Parameters are a way to provide inputs to your AWS CloudFormation template<\/li>\n<li>They&#8217;re important to know about if:\n<ul>\n<li>You want to reuse your templates across the company<\/li>\n<li>Some inputs can not be determined ahead of time<\/li>\n<\/ul>\n<\/li>\n<li>Parameters are extremely powerful, controlled, and can prevent errors from happening in your templates thanks to types.<\/li>\n<\/ul>\n<p>When should you use a parameter?<\/p>\n<ul>\n<li>Ask yourself this:\n<ul>\n<li>Is this Cloud Formation resource configuration likely to change in the future?<\/li>\n<li>If so, make it a parameter.<\/li>\n<\/ul>\n<\/li>\n<li>You won&#8217;t have to re-upload a template to change its content<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">Parameters: \r\n  SecurityGroupDescription: \r\n    Description: Security Group Description (Simple parameter) \r\n    Type: String<\/pre>\n<p>&nbsp;<\/p>\n<p>Parameters Settings<\/p>\n<p>Parameters can be controlled by all these settings:<\/p>\n<ul>\n<li><code>Type:<\/code>\n<ul>\n<li><code>String<\/code><\/li>\n<li><code>Number<\/code><\/li>\n<li><code>CommaDelimitedList<\/code><\/li>\n<li><code>List&lt;Type&gt;<\/code><\/li>\n<li><code>AWS Parameter (to help catch invalid values \u2014 match against existing values in the AWS Account)<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>Description<\/code><\/li>\n<li><code>Constraints<\/code><\/li>\n<li><code>ConstraintDescription (String)<\/code><\/li>\n<li><code>Min\/MaxLength<\/code><\/li>\n<li><code>Min\/MaxValue<\/code><\/li>\n<li><code>Defaults<\/code><\/li>\n<li><code>AllowedValues (array)<\/code><\/li>\n<li><code>AllowedPattern (regexp)<\/code><\/li>\n<li><code>NoEcho (Boolean)<\/code><\/li>\n<\/ul>\n<p>How to Reference a Parameter<\/p>\n<ul>\n<li>The<code> Fn::Ref<\/code> function can be leveraged to reference parameters<\/li>\n<li>Parameters can be used anywhere in a template.<\/li>\n<li>The shorthand for this in YAML is !Ref<\/li>\n<li>The function can also reference other elements within the template<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">DbSubnetl: \r\n  Type: AWS::EC2::Subnet \r\n  Properties: \r\n    VpcId: !Ref MyVPC<\/pre>\n<p>&nbsp;<\/p>\n<p>Concept: Pseudo Parameters<\/p>\n<ul>\n<li>AWS offers us pseudo parameters in any CloudFormation template.<\/li>\n<li>These can be used at any time and are enabled by default<\/li>\n<\/ul>\n<table style=\"border-collapse: collapse; width: 100%;\">\n<tbody>\n<tr>\n<td style=\"width: 50%; text-align: center;\"><span style=\"color: #339966;\">Reference Value <\/span><\/td>\n<td style=\"width: 50%; text-align: center;\"><span style=\"color: #339966;\">Example Return Value <\/span><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::AccountId\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>1234567890 <\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::NotificationARNs\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>[arn:aws:sns:us-east-1:123456789012:MyTopic] <\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::NoValue\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>Does not return a value. <\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::Region\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>us-east-2 <\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::StackId\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>arn:aws:cloudformation:us-east-1:123456789012:stack\/MyStack\/lc2fa62 0-982a-11e3-aff7-50e2416294e0 <\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\"><strong><code>AWS::StackName\u00a0<\/code><\/strong><\/td>\n<td style=\"width: 50%;\"><code>MyStack <\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Resources<\/span><\/p>\n<ul>\n<li>Resources are the core of your CloudFormation template (MANDATORY)<\/li>\n<li>They represent the different AWS Components that will be created and configured<\/li>\n<li>Resources are declared and can reference each other<\/li>\n<li>AWS figures out creation, updates and deletes of resources for us<\/li>\n<li>There are over 224 types of resources (!)<\/li>\n<li>Resource types identifiers are of the form:<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">AWS::aws-product-name::data-type-name<\/pre>\n<ul>\n<li>All the resources can be found here:\u00a0 <a href=\"https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/aws-template-resource-type-ref.html\">https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/aws-template-resource-type-ref.html<\/a><\/li>\n<li>Example here (for an EC2 instance):\u00a0 <a href=\"https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/aws-properties-ec2-instance.html\">https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/aws-properties-ec2-instance.html<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Mappings<\/span><\/p>\n<ul>\n<li>Mappings are fixed variables within your CloudFormationTemplate.<\/li>\n<li>They&#8217;re very handy to differentiate between different environments (dev vs prod), regions (AWS regions), AMI types, etc<\/li>\n<li>All the values are hardcoded within the template<\/li>\n<li>Example:<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">Mappings: \r\n  Mapping01: \r\n    Key01: \r\n      Name: Value01\r\n    Key02: \r\n      Name: Value02\r\n    Key03: \r\n      Name: Value03\r\n<\/pre>\n<pre class=\"lang:default decode:true\">RegionMap: \r\n  us-east-1: \r\n    \"32\": \"ami-6411e20d\" \r\n    \"64\": \"ami-7a11e213\" \r\n  us-west-1: \r\n    \"32\": \"ami-c9c7978c\" \r\n    \"64\": \"ami-cfc7978a\" \r\n  eu-west-1: \r\n    \"32\": \"ami-37c2f643\" \r\n    \"64\": \"ami-31c2f645\"<\/pre>\n<p>&nbsp;<\/p>\n<p>When would you use mappings vs parameters ?<\/p>\n<ul>\n<li>Mappings are great when you know in advance all the values that can be taken and that they can be deduced from variables such as\n<ul>\n<li>Region<\/li>\n<li>Availability zone<\/li>\n<li>AWS Account<\/li>\n<li>Environment (dev vs prod)<\/li>\n<li>Etc &#8230;<\/li>\n<\/ul>\n<\/li>\n<li>They allow safer control over the template.<\/li>\n<li>Use parameters when the values are really user specific<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><code>Fn::FindlnMap<\/code> Accessing Mapping Values<\/p>\n<ul>\n<li>We use <code>Fn::FindInMap<\/code> to return a named value from a specific key<\/li>\n<li><code>FindInMap [ MapName, TopLevelKey, SecondLevelKey ]<\/code><\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">AWSTemplateFormatVersion: \"2010-09-09\" \r\nMappings: \r\n  RegionMap: \r\n    us-east-1: \r\n      \"32\": \"ami-6411e20d\" \r\n      \"64\": \"ami-7a11e213\" \r\n    us-west-1: \r\n      \"32\": \"ami-c9c7978c\" \r\n      \"64\": \"ami-cfc7978a\" \r\n    eu-west-1: \r\n      \"32\": \"ami-37c2f643\" \r\n      \"64\": \"ami-31c2f645\" \r\n    ap-southeast-1: \r\n      \"32\": \"ami-66f28c34\" \r\n      \"64\": \"ami-60f28c32\" \r\n    ap-northeast-1: \r\n      \"32\": \"ami-9c03a89d\" \r\n      \"64\": \"ami-a003a8a1\" \r\n\r\nResources: \r\n  myEC2Instance: \r\n    Type: \"AWS::EC2::Instance\" \r\n    Properties: \r\n      ImageId: !FindInMap [ RegionMap, !Ref \"AWS::Region\", 32 ]\r\n      InstanceType: m1.small\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Outputs<\/span><\/p>\n<ul>\n<li>The Outputs section declares optional outputs values that we can import into other stacks (if you export them first)!<\/li>\n<li>You can also view the outputs in the AWS Console or in using the AWS CLI<\/li>\n<li>They&#8217;re very useful for example if you define a network CloudFormation, and output the variables such as VPC ID and your Subnet IDs<\/li>\n<li>It&#8217;s the best way to perform some collaboration cross stack, as you let expert handle their own part of the stack<\/li>\n<li>You can&#8217;t delete a CloudFormation Stack if its outputs are being referenced by another CloudFormation stack<\/li>\n<\/ul>\n<p>Outputs Example<\/p>\n<ul>\n<li>Creating a SSH Security Group as part of one template<\/li>\n<li>We create an output that references that security group<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">Outputs: \r\n  StackSSHSecurityGroup: \r\n    Description: The SSH Security Group for our Company \r\n    Value: !Ref MyCompanyWideSSHSecurityGroup \r\n    Export: \r\n      Name: SSHSecurityGroup<\/pre>\n<p>Cross Stack Reference<\/p>\n<ul>\n<li>We then create a second template that leverages that security group<\/li>\n<li>For this, we use the <code>Fn::ImportValue<\/code> function<\/li>\n<li>You can&#8217;t delete the underlying stack until all the references are deleted too.<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true \">Resources: \r\n  MySecureInstance: \r\n    Type: AWS::EC2::Instance \r\n    Properties: \r\n      AvailabilityZone: us-east-la \r\n      Imageld: ami-a4c7edb2 \r\n      InstanceType: t2.micro \r\n      SecurityGroups: \r\n      - !ImportValue SSHSecurityGroup<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"color: #3366ff;\">Conditions<\/span><\/p>\n<ul>\n<li>Conditions are used to control the creation of resources or outputs based on a condition.<\/li>\n<li>Conditions can be whatever you want them to be, but common ones are:\n<ul>\n<li>Environment (dev \/ test \/ prod)<\/li>\n<li>AWS Region<\/li>\n<li>Any parameter value<\/li>\n<\/ul>\n<\/li>\n<li>Each condition can reference another condition, parameter value or mapping<\/li>\n<\/ul>\n<p>How to define a condition?<\/p>\n<pre class=\"lang:default decode:true\">Conditions: \r\n  CreateProdResources: !Equals [ !Ref EnvType, prod ]<\/pre>\n<ul>\n<li>The logical ID is for you to choose. It&#8217;s how you name condition<\/li>\n<li>The intrinsic function (logical) can be any of the following:\n<ul>\n<li><code>Fn::And<\/code><\/li>\n<li><code>Fn::Equals<\/code><\/li>\n<li><code>Fn::If<\/code><\/li>\n<li><code>Fn::Not<\/code><\/li>\n<li><code>Fn::Or<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Using a Condition<\/p>\n<ul>\n<li>Conditions can be applied to resources \/ outputs \/ etc&#8230;<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">Resources: \r\n  MountPoint: \r\n    Type: \"AWS::EC2::VolumeAttachment\" \r\n    Condition: CreateProdResources<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Stack status codes:<\/p>\n<p><a href=\"https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/using-cfn-describing-stacks.html\">https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/using-cfn-describing-stacks.html<\/a><\/p>\n<p>Troubleshooting:<\/p>\n<p><a href=\"https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/troubleshooting.html\">https:\/\/docs.aws.amazon.com\/AWSCloudFormation\/latest\/UserGuide\/troubleshooting.html<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":4125,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89],"tags":[],"_links":{"self":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4126"}],"collection":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/comments?post=4126"}],"version-history":[{"count":74,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4126\/revisions"}],"predecessor-version":[{"id":4423,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/posts\/4126\/revisions\/4423"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media\/4125"}],"wp:attachment":[{"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/media?parent=4126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/categories?post=4126"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/miro.borodziuk.eu\/index.php\/wp-json\/wp\/v2\/tags?post=4126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}