I am deploying my infrastructure to AWS using the CloudFormation templates. I have two templates core.yaml and resources.yaml. The core.yaml file is using the resources from the core.yaml importing them into the template. The resources.yaml file is exporting the resources. But when I deployed my core.yaml file, it is failing. Below is my code.
resources.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Permanent resources to be imported"
Parameters:
SSHLocation:
Description: The IP address range that can be used to SSH to the EC2 instances
Type: String
MinLength: '9'
MaxLength: '18'
Default: 0.0.0.0/0
AllowedPattern: "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})"
ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x
DBInstanceIdentifier:
Type: String
Default: 'patheindbidentifier'
DBName:
Type: String
Default: 'patheindb'
DBUsername:
Type: String
Default: 'patheindbadmin'
DBClass:
Type: String
Default: 'db.t2.micro'
DBAllocatedStorage:
Type: String
Default: '5'
DBPassword:
Type: String
Resources:
StorageBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
BucketName: pathein-directory-storage
AccessControl: PublicRead
WebServerSecurityGroup:
Type: AWS::EC2::SecurityGroup
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
GroupDescription: Security Group for EC2 instances
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp:
Ref: SSHLocation
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
GroupDescription: Database security group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '3306'
ToPort: '3306'
SourceSecurityGroupId: !GetAtt WebServerSecurityGroup.GroupId
WebDatabase:
Type: AWS::RDS::DBInstance
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
DBInstanceIdentifier: !Ref DBInstanceIdentifier
DBName: !Ref DBName
DBInstanceClass: !Ref DBClass
AllocatedStorage: !Ref DBAllocatedStorage
Engine: MySQL
MasterUsername: !Ref DBUsername
MasterUserPassword: !Ref DBPassword
VPCSecurityGroups:
- !GetAtt DBSecurityGroup.GroupId
Outputs:
StorageBucket:
Description: "S3 storage bucket"
Value: !Ref StorageBucket
Export:
Name: PatheinStorageBucket
WebServerSecurityGroup:
Description: "Web server security group"
Value: !GetAtt WebServerSecurityGroup.GroupId
Export:
Name: PatheinWebServerSecurityGroup
DBSecurityGroup:
Description: "Database security group"
Value: !Ref DBSecurityGroup
Export:
Name: PatheinDBSecurityGroup
WebDatabase:
Description: "Web database"
Value: !Ref WebDatabase
Export:
Name: PatheinWebDatabases
SSHLocation:
Description: "SSH Location"
Value: !Ref SSHLocation
Export:
Name: PatheinSSHLocation
DatabaseHost:
Description: "Database host"
Value: !GetAtt WebDatabase.Endpoint.Address
DatabasePort:
Description: "Database port"
Value: !GetAtt WebDatabase.Endpoint.Port
As you can see in the template, I am exporting all the resources. I could successfully deploy the resources.yaml into the AWS.
This is my core.yaml file.
AWSTemplateFormatVersion: '2010-09-09'
Description: "Pathein Directory web application deployment template."
Parameters:
KeyName:
Default: 'PatheinDirectory'
Type: String
InstanceType:
Default: 't2.micro'
Type: String
Mappings:
Region2Principal:
us-east-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
us-west-2:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
us-west-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
eu-west-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
eu-west-2:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
eu-west-3:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-southeast-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-northeast-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-northeast-2:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-northeast-3:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-southeast-2:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ap-south-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
us-east-2:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
ca-central-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
sa-east-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
cn-north-1:
EC2Principal: ec2.amazonaws.com.cn
OpsWorksPrincipal: opsworks.amazonaws.com.cn
cn-northwest-1:
EC2Principal: ec2.amazonaws.com.cn
OpsWorksPrincipal: opsworks.amazonaws.com.cn
eu-central-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
eu-north-1:
EC2Principal: ec2.amazonaws.com
OpsWorksPrincipal: opsworks.amazonaws.com
Beanstalk2Route53HostedZoneId:
us-east-1:
HostedZoneId: Z3DZXE0Q79N41H
us-west-1:
HostedZoneId: Z1M58G0W56PQJA
us-west-2:
HostedZoneId: Z33MTJ483KN6FU
eu-west-1:
HostedZoneId: Z3NF1Z3NOM5OY2
ap-northeast-1:
HostedZoneId: Z2YN17T5R711GT
ap-southeast-1:
HostedZoneId: Z1WI8VXHPB1R38
sa-east-1:
HostedZoneId: Z2ES78Y61JGQKS
Resources:
WebServerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- Fn::FindInMap:
- Region2Principal
- Ref: AWS::Region
- EC2Principal
Action:
- sts:AssumeRole
Path: /
WebServerRolePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: WebServerRole
PolicyDocument:
Statement:
- Effect: Allow
NotAction: iam:*
Resource: '*'
Roles:
- Ref: WebServerRole
WebServerInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: WebServerRole
Application:
Type: AWS::ElasticBeanstalk::Application
Properties:
ApplicationName: PatheinDirectoryApplication
Description: AWS Elastic Beanstalk Pathein Directory Laravel application
ApplicationVersion:
Type: AWS::ElasticBeanstalk::ApplicationVersion
Properties:
Description: Version 1.0
ApplicationName:
Ref: Application
SourceBundle:
S3Bucket:
Fn::Join:
- '-'
- - elasticbeanstalk-samples
- Ref: AWS::Region
S3Key: php-sample.zip
ApplicationConfigurationTemplate:
Type: AWS::ElasticBeanstalk::ConfigurationTemplate
Properties:
ApplicationName:
Ref: Application
Description: SSH access to Pathein Directory Laravel application
SolutionStackName: 64bit Amazon Linux 2 v3.1.0 running PHP 7.3
OptionSettings:
- Namespace: aws:autoscaling:launchconfiguration
OptionName: EC2KeyName
Value:
Ref: KeyName
- Namespace: aws:autoscaling:launchconfiguration
OptionName: IamInstanceProfile
Value:
Ref: WebServerInstanceProfile
- Namespace: aws:autoscaling:launchconfiguration
OptionName: SecurityGroups
Value:
!ImportValue PatheinWebServerSecurityGroup
Environment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
Description: AWS Elastic Beanstalk Environment running Pathein Directory Laravel application
ApplicationName:
Ref: Application
EnvironmentName: PatheinDirectory
TemplateName:
Ref: ApplicationConfigurationTemplate
VersionLabel:
Ref: ApplicationVersion
OptionSettings:
- Namespace: aws:elasticbeanstalk:container:php:phpini
OptionName: document_root
Value: /public
ElasticCacheSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable TCP connection on port 6379
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '11211'
ToPort: '11211'
SourceSecurityGroupId: !ImportValue PatheinWebServerSecurityGroup
ElasticCacheCluster:
Type: AWS::ElastiCache::CacheCluster
Properties:
AZMode: cross-az
CacheNodeType: cache.t2.small
Engine: memcached
NumCacheNodes: '2'
VpcSecurityGroupIds:
- !GetAtt ElasticCacheSecurityGroup.GroupId
PreferredAvailabilityZones:
- !Select
- 0
- Fn::GetAZs: !Ref AWS::Region
- !Select
- 1
- Fn::GetAZs: !Ref AWS::Region
It is failing when I deployed the core.yaml file. The following is the error I got in the log.
{
"StackId": "arn:aws:cloudformation:eu-west-1:733553390213:stack/patheindirectory/5da3be20-ef6c-11ea-8dc6-0275bf88180c",
"EventId": "b7aa01e0-ef6c-11ea-b8c0-06e621efe3ec",
"StackName": "patheindirectory",
"LogicalResourceId": "patheindirectory",
"PhysicalResourceId": "arn:aws:cloudformation:eu-west-1:733553390213:stack/patheindirectory/5da3be20-ef6c-11ea-8dc6-0275bf88180c",
"ResourceType": "AWS::CloudFormation::Stack",
"Timestamp": "2020-09-05T11:41:20.498000+00:00",
"ResourceStatus": "ROLLBACK_IN_PROGRESS",
"ResourceStatusReason": "The following resource(s) failed to create: [ElasticCacheCluster, ApplicationConfigurationTemplate]. . Rollback requested by user."
},
2
Answers
Usually, you can find more detailed error messages when you take a look at the stack events in the CloudFormation console. In this case I got 2 errors for the
ApplicationConfigurationTemplate
resource:1
No Solution Stack named '64bit Amazon Linux 2 v3.1.0 running PHP 7.3' found
:The issue is that the version you specified was only valid until September 2, 2020. You can check the current platform versions here. So I had to update the SolutionStackName attribute:
SolutionStackName: 64bit Amazon Linux 2 v3.1.1 running PHP 7.3
2
Configuration validation exception: Invalid option value: 'sg-xxx' (Namespace: 'aws:autoscaling:launchconfiguration', OptionName: 'SecurityGroups'): The security group 'sg-xxx' does not exist
: This is related to the following code piece:The issue is that in this case not the logical ID (Security Group ID), but the physical ID (Security Group Name) of the Security Group is required. This means you have to add another export to the resources.yaml template like this:
Then you can import it to core.yaml:
Note that you still need to export the logical ID as it’s used by
ElasticCacheSecurityGroup
.You have interesting case showing inconsistencies in CloudFormation. In some cases Security Group (SG) ID (for
ElasticCacheCluster
) is required, in other cases SG Name (forApplicationConfigurationTemplate
) is needed. Thus in your case you need to export both fromresources.yaml
and respectively import them incore.yaml
. AlsoSolutionStackName
needed to be updated.The fixed templates are below. I verified that they work and deploy in
us-east-1
region. I only verified their deployment, not functionality of the resulting resources.resources.yaml
core.yaml