How to get resource logical id cloudformation template? - amazon-web-services

Is it possible to get a resource's logical ID inside itself like we do with "Ref" : "logicalName". I just want to get the resource logical id (here Instance1) in its own properties section dynamically. Till now i have to hard code resource name.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Mappings": {
"Para" : {
"Layer" : { "Instance1" : "Testing", "Instance2" : "Staging", "Instance3" : "Production" }
}
},
"Resources": {
"Instance1": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-5fb8c835",
"Tags": [
{ "Key": "Name", "Value": { "Fn::FindInMap" : [ "Para", "Name", "Instance1" ]} }
]
}
},
"Instance2": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-5fb8c835",
"Tags": [
{ "Key": "Name", "Value": { "Fn::FindInMap" : [ "Para", "Name", "Instance2" ]} }
]
}
}
}
I just want to get resource name (eg Instance1 or instance 2) in key, value tag lines.

It is not possible to retrieve the logical name itself within a custom tag, but CloudFormation does automatically tag every Instance with an aws:cloudformation:logical-id tag.
In addition to any tags you define, AWS CloudFormation automatically
creates the following stack-level tags with the prefix aws::
aws:cloudformation:logical-id
aws:cloudformation:stack-id
aws:cloudformation:stack-name
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html

Related

AWS Cloudformation: ImageId cannot be empty

I am using cloud formation to create:
load balancer + target-group w/ instance(from custom AMI)
I used create template in designer and edited their default configs:
I chose Elastic Loadbalancer V2 >> target group
{
"Resources": {
"ELBV3LB29NC1": {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"IpAddressType" : "ipv4",
"Name" : "quest-loadbalancer2",
"SecurityGroups" : [ "sg-036a1a54caee05af5"],
"Subnets" : [ "subnet-795d4435", "subnet-7d5a5a07" ],
}
}
}
}
// **********************
{
"Resources": {
"ELBTV1G4J8KH": {
"Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
"Properties": {
"Name": "quest-target-group-2",
"Port": 80,
"Protocol": "HTTP",
"Targets": [
{
"Id" : "i-0f5c5714bed60786b",
"Port" : 80
}
],
"TargetType": "i-0f5c5714bed60786b",
"VpcId": "vpc-a28dece9"
}
}
}
}
An EC2 Instance
{
"Resources": {
"EC2I5QYZC": {
"Type": "AWS::EC2::Instance",
"Properties": {
"AvailabilityZone" : "us-east-2",
"InstanceType" : "t2.micro",
"ImageId" :"ami-034e6c68f4dy6d449", // <------------ AMI ID
"SecurityGroups" : [ "sg-036a1a54caee05af5" ],
}
}
}
}
ERROR : (after clicking create stack) ImageId cannot be empty and it stops right there.
The target Instance id is an Instance Id. It should be an AMI ID instead.
You're trying to connect to an already existing instance instead of creating a new one.

Invalid template resource property "Tags"

For the below cloudformation template:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Some Stack",
"Parameters":{
"VpcId":{
"Type": "AWS::EC2::VPC::Id",
"Description": "The target VPC Id"
},
"SubnetId":{
"Type": "AWS::EC2::Subnet::Id",
"Description": "The target subnet Id"
},
"KeyName": {
"Type": "String",
"Description": "The key pair that is allowed SSH access"
}
},
"Resources":{
"EcsCluster":{
"Type": "AWS::ECS::Cluster",
"Tags": [
{
"Key": "Name",
"Value": { "Fn::Join": ["", [ { "Ref": "AWS::StackName" }, "-ecs-cluster" ] ] }
},
{
"Key": "workenv",
"Value": "dev"
},
{
"Key": "abc",
"Value": "some_value"
},
{
"Key": "function",
"Value": "someapp"
},
{
"Key": "owner",
"Value": "email#abc.com"
}
]
}
},
"Outputs":{
"ElbDomainName":{
"Description": "Public DNS name of Elastic Load Balancer",
"Value": {
"Fn::GetAtt": [
"ElasticLoadBalancer",
"DNSName"
]
}
}
}
}
Below is the error:
Invalid template resource property 'Tags'
Am following the below documentation to add tags:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html
Why CloudFormation service does not accept Tags defined on every resource? something to do with indentation?
It is because the Tags are not defined correctly for EcsCluster resource. The Tags property should be defined inside the Properties section as how you defined Tags for other resources.
"EcsCluster": {
"Type": "AWS::ECS::Cluster",
"Properties": {
"Tags": []
}
}
Hope this helps.
Not all resource types support tags. Check the documentation for each resource type.

How to create AWS Elasticbeanstalk application with integrated RDS using CloudFormation?

I am trying to setup the AWS environment for my SpringBoot application which uses Postgres.
I decided to use CloudFormation to configure all the AWS components needed for my application.
Following is the cloud formation template app.json:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"S3BucketName": {
"Description": "S3 BucketName",
"Type": "String"
},
"S3FileName": {
"Description": "Name of the jar/war file",
"Type": "String"
},
"DBName":{
"Default":"mytododb",
"Description":"The database name",
"Type":"String",
"MinLength":"1",
"MaxLength":"64",
"AllowedPattern":"[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription":"must begin with a letter and contain only alphanumeric characters."
},
"DBUser":{
"Description":"The database admin account username",
"Type":"String",
"MinLength":"1",
"MaxLength":"16",
"AllowedPattern":"[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription":"must begin with a letter and contain only alphanumeric characters."
},
"DBPassword":{
"NoEcho":"true",
"Description":"The database admin account password",
"Type":"String",
"MinLength":"8",
"MaxLength":"41",
"AllowedPattern":"[a-zA-Z0-9]*",
"ConstraintDescription":"must contain only alphanumeric characters."
},
"DBAllocatedStorage":{
"Default":"5",
"Description":"The size of the database (Gb)",
"Type":"Number",
"MinValue":"5",
"MaxValue":"1024",
"ConstraintDescription":"must be between 5 and 1024Gb."
},
"DBInstanceClass":{
"Default":"db.t2.micro",
"Description":"The database instance type",
"Type":"String",
"ConstraintDescription":"must select a valid database instance type."
},
"MultiAZDatabase":{
"Default":"false",
"Description":"Create a multi-AZ RDS database instance",
"Type":"String",
"AllowedValues":[
"true",
"false"
],
"ConstraintDescription":"must be either true or false."
}
},
"Resources": {
"SpringBootApplication": {
"Type": "AWS::ElasticBeanstalk::Application",
"Properties": {
"Description":"Spring boot and elastic beanstalk"
}
},
"SpringBootApplicationVersion": {
"Type": "AWS::ElasticBeanstalk::ApplicationVersion",
"Properties": {
"ApplicationName":{"Ref":"SpringBootApplication"},
"SourceBundle": {
"S3Bucket": {
"Ref": "S3BucketName"
},
"S3Key": {
"Ref": "S3FileName"
}
}
}
},
"SpringBootBeanStalkConfigurationTemplate": {
"Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
"Properties": {
"ApplicationName": {"Ref":"SpringBootApplication"},
"Description":"A display of speed boot application",
"OptionSettings": [
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBAllocatedStorage",
"Value": {
"Ref": "DBAllocatedStorage"
}
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBDeletionPolicy",
"Value": "Delete"
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBEngine",
"Value": "postgres"
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBEngineVersion",
"Value": "10.4"
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBInstanceClass",
"Value": { "Ref": "DBInstanceClass" }
},
{
"OptionName": "DBPassword",
"Namespace": "aws:rds:dbinstance",
"Value": { "Ref": "DBPassword" }
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "DBUser",
"Value": { "Ref": "DBUser" }
},
{
"Namespace": "aws:rds:dbinstance",
"OptionName": "MultiAZDatabase",
"Value": { "Ref": "MultiAZDatabase" }
}
],
"SolutionStackName": "64bit Amazon Linux 2018.03 v2.9.2 running Java 8"
}
},
"SpringBootBeanstalkEnvironment": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"ApplicationName": {"Ref":"SpringBootApplication"},
"EnvironmentName":"TodoAppEnvironment",
"TemplateName": {"Ref":"SpringBootBeanStalkConfigurationTemplate"},
"VersionLabel": {"Ref": "SpringBootApplicationVersion"}
}
}
},
"Outputs": {
"DevURL": {
"Description": "The URL of the DEV Elastic Beanstalk environment",
"Value": {
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"SpringBootBeanstalkEnvironment",
"EndpointURL"
]
}
]
]
},
"Export": {
"Name": {
"Fn::Sub": "${AWS::StackName}-EndpointURL"
}
}
}
}
}
And the parameters file parameters.json is:
[
{
"ParameterKey": "DBUser",
"ParameterValue": "myuser"
},
{
"ParameterKey": "DBPassword",
"ParameterValue": "secret"
},
{
"ParameterKey": "S3BucketName",
"ParameterValue": "todoapp"
},
{
"ParameterKey": "S3FileName",
"ParameterValue": "todo-api-spring-boot-0.0.1.jar"
}
]
I am creating the CloudFormation stack using
aws cloudformation create-stack --template-body file://app.json --parameters file://parameters.json --stack-name=todo-stack
Problem:
The stack is getting created, however the database (RDS) instance is not getting created and when I see in ElasticBeanstalk configuration for the app in Management Console there is no Database configuration associated with the application.
My expectation/assumption is by configuring various aws:rds:dbinstance properties in OptionSettings an RDS instance will be provisioned and associates with ElasticBeanstalk application.
Is my understanding wrong or am I missing any other setting?
PS:
The idea is to use integrated RDS so that I can use RDS_HOST, RDS_PORT etc properties in my application to connect to database.
I am able to configure a separate RDS Resource and connect to it by specifying the connection parameters. But I am expecting aws:rds:dbinstance properties in OptionSettings would create the RDS and associate it to Elasticbeanstalk application. If that is not the case then what is the purpose of configuring those parameters in OptionSettings?
Ref:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-rdsdbinstance
https://github.com/metabase/metabase/blob/master/bin/aws-eb-docker/cloudformation-elasticbeanstalk.json.template
RDS creation is not done due to the Namespace Approach. Basically Namespace is used to override the default properties of the resources which you have created.
So the solution is to include the RDS creation template before your "SpringBootBeanStalkConfigurationTemplate"
"Resources": {
"RDS Creation": {
{
"Type" : "AWS::RDS::DBInstance",
"Properties" : {
"AllocatedStorage" : String,
"AllowMajorVersionUpgrade" : Boolean,
"AssociatedRoles" : [ DBInstanceRole, ... ],
"AutoMinorVersionUpgrade" : Boolean,
"AvailabilityZone" : String,
"BackupRetentionPeriod" : Integer,
"CharacterSetName" : String,
"CopyTagsToSnapshot" : Boolean,
"DBClusterIdentifier" : String,
"DBInstanceClass" : String,
"DBInstanceIdentifier" : String,
"DBName" : String,
"DBParameterGroupName" : String,
"DBSecurityGroups" : [ String, ... ],
"DBSnapshotIdentifier" : String,
"DBSubnetGroupName" : String,
"DeleteAutomatedBackups" : Boolean,
"DeletionProtection" : Boolean,
"Domain" : String,
"DomainIAMRoleName" : String,
"EnableCloudwatchLogsExports" : [ String, ... ],
"EnableIAMDatabaseAuthentication" : Boolean,
"EnablePerformanceInsights" : Boolean,
"Engine" : String,
"EngineVersion" : String,
"Iops" : Integer,
"KmsKeyId" : String,
"LicenseModel" : String,
"MasterUsername" : String,
"MasterUserPassword" : String,
"MonitoringInterval" : Integer,
"MonitoringRoleArn" : String,
"MultiAZ" : Boolean,
"OptionGroupName" : String,
"PerformanceInsightsKMSKeyId" : String,
"PerformanceInsightsRetentionPeriod" : Integer,
"Port" : String,
"PreferredBackupWindow" : String,
"PreferredMaintenanceWindow" : String,
"ProcessorFeatures" : [ ProcessorFeature, ... ],
"PromotionTier" : Integer,
"PubliclyAccessible" : Boolean,
"SourceDBInstanceIdentifier" : String,
"SourceRegion" : String,
"StorageEncrypted" : Boolean,
"StorageType" : String,
"Tags" : [ Tag, ... ],
"Timezone" : String,
"UseDefaultProcessorFeatures" : Boolean,
"VPCSecurityGroups" : [ String, ... ]
}
}
}
}
After this, you can include the RDS parameters in your other Resources as it will be created first.
I was stumbling across the same question and found some sort of an answer here: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.managing.db.html
In that document they say:
You can configure your environment's database instance using configuration files. Use the options in the aws:rds:dbinstance namespace. The following example modifies the allocated database storage size to 100 GB.
So the aws:rds:dbinstance properties in OptionSettings are only meant to modify an existing database instance, not to create one in the first place.

Cloud Formation function doesn't assign value to value for key within a Tag

I have the following Cloud Formation template to create a VPC. The VPC name is generated based off of the region and the environment that the template was created in. The VPC creates without any issues, and running aws cloud formation validate-template --template-url https://foo.template doesn't complaing about any of the syntax.
I would expect the VPC to be named:
vpc-uw1-d-fs
What happens instead is the VPC is left with an empty name and the Name tag has an empty value. Am I not using the function correctly? If I remove the Fn::FindInMap function usage, I get the name generated - it's just missing the environment mapped value.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "VPC for a new environment to use.",
"Parameters": {
"EnvironmentName": {
"Description": "Name of the environment that this VPC will be used for.",
"Type": "String",
"MinLength": "2",
"MaxLength": "20",
"AllowedPattern": "[a-zA-Z]*",
"AllowedValues": [
"Development",
"QA",
"Test",
"Production"
]
}
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"EnableDnsSupport": false,
"EnableDnsHostnames": false,
"InstanceTenancy": "default",
"Tags": [ {
"Key": "Name",
"Value": {
"Fn::Join": [
"-",
[
"vpc",
{ "Ref": "AWS::Region" },
{ "Fn::FindInMap": [
"EnvironmentMap", { "Ref": "EnvironmentName" }, "AbbreviatedName"
]},
"fs"
]
]
}
}]
}
}
},
"Mappings": {
"RegionMap": {
"us-east-1": {
"regionName": "ue1"
},
"us-west-1": {
"regionName": "uw1"
}
},
"EnvironmentMap": {
"Development": {
"AbbreviatedName": "d"
},
"QA": {
"AbbreviatedName": "qa"
},
"Test": {
"AbbreviatedName": "t"
},
"Production": {
"AbbreviatedName": "p"
}
}
},
"Outputs": {
}
}
Your template is working perfectly fine for me.
I ran it in the ap-southeast-2 region and it produced the tag:
Name: vpc-ap-southeast-2-d-fs
(The RegionMap is not used in the template given.)

How we can create Geolocation through AWS:cloudfromation template?

I have implemented this but it says invalid request. It may totally wrong.
I want to create geolocation for particular country
"Geolocation": {
"Type": "AWS::Route53::RecordSet",
"Properties": {
"HostedZoneName": {
"Ref": "Route53Domain"
},
"Name": {
"Fn::Join": [
"$",
[
{
"Ref": "javadns"
},
{
"Ref": "Route53Domain"
}
]
]
},
"Type": "CNAME",
"TTL": "60",
"GeoLocation": {"CountryCode" : "*"},
"ResourceRecords": [
{ "Fn::Join" : [".", ["geoip", { "Ref" : "javadns" }]]}
]
}
},
To create a Geo Location record you must specify the SetIdentifier property in CloudFormation.
i see you are missing that property in your CloudFormation and probably that is why it is throwing you an error.
Also here are the code countries identifiers that are supported by Route53, you must not specify the wildcard in that parameter, countries and continent codes consist of two letters.
Documentation here.