CloudFormation Joining List of Strings with FindInMap - amazon-web-services

I am facing issue with Cloudformation on joining a list of strings after getting it from a map.
Error caused is Security Group expects a list of string.
"123456":
us-east-1:
#VPC1
VpcId: vpc-xxxx
VpcCidr: 10.78.160.0/20
SecurityGroups: sg-123
AvailabilityZones: us-east-1a,us-east-1b,us-east-1c
"123457":
us-east-1:
#VPC
VpcId: vpc-xxxx
VpcCidr: 10.78.160.0/20
SecurityGroups: sg-123,sg-124
AvailabilityZones: us-east-1a,us-east-1b,us-east-1c
LaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Metadata:
AWS::CloudFormation::Init:
config:
Properties:
InstanceType:
Ref: InstanceType
SecurityGroups: !Join [ ",", [!FindInMap [!Ref "AWS::AccountId", !Ref "AWS::Region", SecurityGroups], !Ref EC2SG ]]
IamInstanceProfile:
please let me know how to get the list for securitygroups and adding it to another resource
Solved by using this question
How do I use nested lists or append to a list in Cloudformation?

Lets take mappings:
Mappings:
"111222333444":
us-east-1:
SecurityGroups:
- sg-abc
- sg-xyz
us-west-2:
SecurityGroups:
- sg-1234
- sg-3456
Security groups can be referred as
SecurityGroupIds:
"Fn::FindInMap":
[!Ref AWS::AccountId, !Ref AWS::Region, SecurityGroups]
Define as array in mappings and pass the full array, this way we can avoid splitting and joining.
Full Template , tested on a Lambda
AWSTemplateFormatVersion: "2010-09-09"
Description: "Test"
Mappings:
"111222333444":
us-east-1:
SecurityGroups:
- sg-abc
- sg-xyz
us-west-2:
SecurityGroups:
- sg-1234
- sg-3456
Resources:
TestLambda:
Type: "AWS::Lambda::Function"
Properties:
Handler: com.test.MainClass::handleRequest
Runtime: java8
FunctionName: "Test-Lambda"
Code:
S3Bucket: code-bucket
S3Key: !Sub "artifacts/test.jar"
Description: "Test Lambda"
MemorySize: 512
Timeout: 60
Role: !Ref my-role-arn
VpcConfig:
SecurityGroupIds:
"Fn::FindInMap":
[!Ref AWS::AccountId, !Ref AWS::Region, SecurityGroups]
SubnetIds:
- subnet-1
- subnet-2

Related

Aws batch : choose compute environnement on launch

I have a aws cloudformation template for my batch definition. I have 2 compute environnement définition, a on demand and a spot.
DragenComputeEnvironmentSpot:
Type: AWS::Batch::ComputeEnvironment
Properties:
ComputeEnvironmentName: dragen-spot
ServiceRole: !Ref BatchServiceRole
Type: MANAGED
State: ENABLED
ComputeResources:
BidPercentage: !Ref BidPercentage
Ec2KeyPair: !Ref Ec2KeyPair
ImageId: !Ref ImageId
InstanceRole: !Ref DragenInstanceRole
InstanceTypes: [!Ref InstanceType]
MinvCpus: !Ref MinvCpus
DesiredvCpus: !Ref DesiredvCpus
MaxvCpus: !Ref MaxvCpus
SecurityGroupIds:
- !Ref BatchSecurityGroup
SpotIamFleetRole: !Ref SpotFleetRole
Subnets: !Ref SubnetIds
Type: SPOT
LaunchTemplate:
LaunchTemplateId: !Ref DragenLaunchTemplate
DragenComputeEnvironmentOnDemand:
Type: AWS::Batch::ComputeEnvironment
Properties:
ComputeEnvironmentName: dragen-ondemand
ServiceRole: !Ref BatchServiceRole
Type: MANAGED
State: ENABLED
ComputeResources:
Ec2KeyPair: !Ref Ec2KeyPair
ImageId: !Ref ImageId
InstanceRole: !Ref DragenInstanceRole
InstanceTypes: [!Ref InstanceType]
MinvCpus: !Ref MinvCpus
DesiredvCpus: !Ref DesiredvCpus
MaxvCpus: !Ref MaxvCpus
SecurityGroupIds:
- !Ref BatchSecurityGroup
Subnets: !Ref SubnetIds
Type: EC2
LaunchTemplate:
LaunchTemplateId: !Ref DragenLaunchTemplate
Then in the jobqueue définition i have :
DragenJobQueue:
Type: AWS::Batch::JobQueue
Properties:
JobQueueName: dragen-queue
Priority: 100
State: ENABLED
ComputeEnvironmentOrder:
- Order: 1
ComputeEnvironment: !Ref DragenComputeEnvironmentOnDemand
- Order: 2
ComputeEnvironment: !Ref DragenComputeEnvironmentSpot
So if i understand well the on demand has the priority (so spot will never be use). But i would like to know if there is a way to override during the job launch ? Some job fit well with on demand but others are better on spot.

Cloudformation's condition statement (Glue's subnet)

I need my Glue job to use specific subnet based on environment it is ran in. Below line SubnetId throws syntax error. I read in aws' doc that true/false evaluation can be addressed with !Ref, issue seems to be with syntax for condition.
SubnetId: !If [!Ref UseProdCondition, !Ref PrivateSubnetAz2, !Ref PrivateSubnetAz3]
GlueJDBCConnection:
Type: AWS::Glue::Connection
UseProdCondition: !Equals [!Ref "${AppEnv}", "production"]
Properties:
CatalogId: !Ref AWS::AccountId
ConnectionInput:
ConnectionType: "JDBC"
ConnectionProperties:
USERNAME: !Ref Username
PASSWORD: !Ref Password
JDBC_CONNECTION_URL: !Ref GlueJDBCStringTarget
sslMode: 'REQUIRED'
PhysicalConnectionRequirements:
AvailabilityZone:
Ref: AvailabilityZone2
SecurityGroupIdList:
- Fn::GetAtt: GlueJobSecurityGroup.GroupId
SubnetId: !If [!Ref UseProdCondition, !Ref PrivateSubnetAz2, !Ref PrivateSubnetAz3]
Name: !Ref JDBCConnectionName
Condition needs to be defined as a separate resource, later referenced in specific resource.
Thanks #MisterSmith!
AWSTemplateFormatVersion: 2010-09-09
Description: AWS Glue Spark Job
Conditions:
UseProdCondition: !Equals [!Ref AppEnv, "production"]
GlueJDBCConnection:
Type: AWS::Glue::Connection
Properties:
CatalogId: !Ref AWS::AccountId
ConnectionInput:
ConnectionType: "JDBC"
ConnectionProperties:
USERNAME: !Ref Username
PASSWORD: !Ref Password
JDBC_CONNECTION_URL: !Ref GlueJDBCStringTarget
sslMode: 'REQUIRED'
PhysicalConnectionRequirements:
AvailabilityZone:
Ref: AvailabilityZone2
SecurityGroupIdList:
- Fn::GetAtt: GlueJobSecurityGroup.GroupId
#SubnetId: !Ref PrivateSubnetAz2
SubnetId: !If [UseProdCondition, !Ref PrivateSubnetAz2, !Ref PrivateSubnetAz3]
Name: !Ref RTMIJDBCConnectionName

AWS CloudFormation Template format error: Unresolved resource dependencies <s3 bucket> in the Resources block of the template

All that I am trying to do is follow this guide to get Atlassian services (Jira/JSM/Confluence) up and running on AWS https://aws-quickstart.github.io/quickstart-atlassian-jira/
I have followed all the details precisely and am currently at the point where I need to create the stack on cloudformation. When I paste in the .yaml url I get the error in the title, pointing me to an issue with the resources. I have looked through it and I'm not sure what the problem is, help would be appreciated.
Resources:
VPCStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub
- https://${QSS3BucketName}.${QSS3Region}.amazonaws.com/${QSS3KeyPrefix}submodules/quickstart-atlassian-services/templates/quickstart-vpc-for-atlassian-services.yaml
- QSS3Region: !If
- GovCloudCondition
- s3-us-gov-west-1
- s3
Parameters:
AccessCIDR: !Ref 'AccessCIDR'
AvailabilityZones: !Join
- ','
- !Ref 'AvailabilityZones'
ExportPrefix: !Ref 'ExportPrefix'
KeyPairName: !Ref 'KeyPairName'
PrivateSubnet1CIDR: !Ref 'PrivateSubnet1CIDR'
PrivateSubnet2CIDR: !Ref 'PrivateSubnet2CIDR'
PublicSubnet1CIDR: !Ref 'PublicSubnet1CIDR'
PublicSubnet2CIDR: !Ref 'PublicSubnet2CIDR'
VPCCIDR: !Ref 'VPCCIDR'
BastionHostRequired: !Ref 'BastionHostRequired'
JiraDCStack:
DependsOn: VPCStack
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub
- https://${QSS3BucketName}.${QSS3Region}.amazonaws.com/${QSS3KeyPrefix}templates/quickstart-jira-dc.template.yaml
- QSS3Region: !If ["GovCloudCondition", "s3-us-gov-west-1", "s3"]
Parameters:
CatalinaOpts: !Ref 'CatalinaOpts'
CidrBlock: !Ref 'AccessCIDR'
CloudWatchIntegration: !Ref 'CloudWatchIntegration'
ClusterNodeInstanceType: !Ref 'ClusterNodeInstanceType'
ClusterNodeMax: !Ref 'ClusterNodeMax'
ClusterNodeMin: !Ref 'ClusterNodeMin'
ClusterNodeVolumeSize: !Ref 'ClusterNodeVolumeSize'
CustomDnsName: !Ref 'CustomDnsName'
DBEngine: !Ref DBEngine
DBEngineVersion: !Ref DBEngineVersion
DBInstanceClass: !Ref 'DBInstanceClass'
DBIops: !Ref 'DBIops'
DBMasterUserPassword: !Ref 'DBMasterUserPassword'
DBMaxIdle: !Ref 'DBMaxIdle'
DBMaxWaitMillis: !Ref 'DBMaxWaitMillis'
DBMinEvictableIdleTimeMillis: !Ref 'DBMinEvictableIdleTimeMillis'
DBMinIdle: !Ref 'DBMinIdle'
DBMultiAZ: !Ref 'DBMultiAZ'
DBPassword: !Ref 'DBPassword'
DBPoolMaxSize: !Ref 'DBPoolMaxSize'
DBPoolMinSize: !Ref 'DBPoolMinSize'
DBRemoveAbandoned: !Ref 'DBRemoveAbandoned'
DBRemoveAbandonedTimeout: !Ref 'DBRemoveAbandonedTimeout'
DBStorage: !Ref 'DBStorage'
DBStorageEncrypted: !Ref 'DBStorageEncrypted'
DBStorageType: !Ref 'DBStorageType'
DBTestOnBorrow: !Ref 'DBTestOnBorrow'
DBTestWhileIdle: !Ref 'DBTestWhileIdle'
DBTimeBetweenEvictionRunsMillis: !Ref 'DBTimeBetweenEvictionRunsMillis'
DeploymentAutomationRepository: !Ref 'DeploymentAutomationRepository'
DeploymentAutomationBranch: !Ref 'DeploymentAutomationBranch'
DeploymentAutomationKeyName: !Ref 'DeploymentAutomationKeyName'
DeploymentAutomationPlaybook: !Ref 'DeploymentAutomationPlaybook'
DeploymentAutomationCustomParams: !Ref 'DeploymentAutomationCustomParams'
ExportPrefix: !Ref 'ExportPrefix'
HostedZone: !Ref 'HostedZone'
InternetFacingLoadBalancer: !Ref 'InternetFacingLoadBalancer'
JiraProduct: !Ref 'JiraProduct'
JiraVersion: !Ref 'JiraVersion'
JvmHeapOverride: !Ref 'JvmHeapOverride'
KeyPairName: !Ref 'KeyPairName'
MailEnabled: !Ref 'MailEnabled'
QSS3BucketName: !Ref 'jira-bucket-aws'
QSS3KeyPrefix: !Ref 'QSS3KeyPrefix'
SSLCertificateARN: !Ref 'SSLCertificateARN'
TomcatAcceptCount: !Ref 'TomcatAcceptCount'
TomcatContextPath: !Ref 'TomcatContextPath'
TomcatDefaultConnectorPort: !Ref 'TomcatDefaultConnectorPort'
TomcatEnableLookups: !Ref 'TomcatEnableLookups'
TomcatMaxThreads: !Ref 'TomcatMaxThreads'
TomcatMinSpareThreads: !Ref 'TomcatMinSpareThreads'
TomcatProtocol: !Ref 'TomcatProtocol'
TomcatRedirectPort: !Ref 'TomcatRedirectPort'
BastionHostRequired: !Ref 'BastionHostRequired'
Your missing the template parameters section. If you have the AWS CLI installed you can run aws cloudformation validate-template with either --template-body file://jira-cfn.yaml or --template-url https://path.to/your/cfn/template.yaml to check for template errors. You can also run the validation from the CloudFront console if you go to the editor and load/paste in the template.
Running the below command to validate the template produced this output (i saved your template as jira-cfn.yaml in the current working directory):
aws cloudformation validate-template --template-body file://jira-cfn.yaml
An error occurred (ValidationError) when calling the ValidateTemplate operation: Template format error: Unresolved resource dependencies
[
TomcatEnableLookups,
DBIops,
SSLCertificateARN,
QSS3KeyPrefix,
JiraProduct,
TomcatMinSpareThreads,
DBMaxWaitMillis,
DBStorageEncrypted,
BastionHostRequired,
DBTestOnBorrow,
DeploymentAutomationPlaybook,
MailEnabled,
DBMultiAZ,
JiraVersion,
QSS3BucketName,
JvmHeapOverride,
DBRemoveAbandoned,
DBInstanceClass,
DBMasterUserPassword,
jira-bucket-aws,
CloudWatchIntegration,
ClusterNodeInstanceType,
DBMinIdle,
DBPassword,
ClusterNodeMin,
DeploymentAutomationCustomParams,
DBStorage,
TomcatMaxThreads,
InternetFacingLoadBalancer,
DeploymentAutomationBranch,
ClusterNodeMax,
DBMaxIdle,
TomcatAcceptCount,
DBStorageType,
DBEngine,
AccessCIDR,
TomcatDefaultConnectorPort,
DBMinEvictableIdleTimeMillis,
DeploymentAutomationKeyName,
TomcatRedirectPort,
DBTestWhileIdle,
HostedZone,
CatalinaOpts,
KeyPairName,
CustomDnsName,
TomcatContextPath,
DBRemoveAbandonedTimeout,
ClusterNodeVolumeSize,
DBPoolMinSize,
DBTimeBetweenEvictionRunsMillis,
DBEngineVersion,
ExportPrefix,
DBPoolMaxSize,
DeploymentAutomationRepository,
TomcatProtocol
] in the Resources block of the template

Define auto-scaling policy for AWS EKS Nodegroups in cloudformation

I approached with managed node groups (https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) option. It was working. But how to define the autoscaling policy. It just allows giving max and min node counts not even name.
BatchJobNodeGroup:
Type: 'AWS::EKS::Nodegroup'
Properties:
ClusterName: !Ref EksCluster
CapacityType: !Ref NodeCapacityType
DiskSize: !Ref NodeVolumeSize
AmiType: !Ref AmiType
InstanceTypes: [!Ref NodeInstanceType]
NodeRole:
"Fn::GetAtt": ["EKSIAMRole", "Arn"]
ScalingConfig:
MinSize: !Ref NodeAutoScalingGroupMinSize
DesiredSize: !Ref NodeAutoScalingGroupDesiredCapacity
MaxSize: !Ref NodeAutoScalingGroupMaxSize
Labels:
NodeGroup: BatchJobNodeGroup
Subnets:
- !Ref PrivateSubnet01
- !Ref PrivateSubnet02
In ScalingConfig also I'm not able to pass any extra args.

error CloudFormation template removing instead of creating new elements

I am new to AWS Cloud Formation, well I am reusing 2 templates, the first one works totally fine, it creates a Network Stack for AWS Fargate, please see template #1 below, but the second one (which is failing) supposed to creates the services, instead it is trying to delete most of the elements of the Network Stack, please see template #2 below.
I can see in the "Changes Preview" how it is marking to "remove" almost everything that I created before with the Network Stack template, please see image below #3.
Does somebody can advise what is wrong with the second template?, thank you.
1) Network Stack
AWSTemplateFormatVersion: '2010-09-09'
Description: Create a network stack with a public vpc, fargate cluster and load balancer as a parent stack.
Mappings:
SubnetConfig:
VPC:
CIDR: '10.0.0.0/16'
PublicOne:
CIDR: '10.0.0.0/24'
PublicTwo:
CIDR: '10.0.1.0/24'
Resources:
FargateVpc:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR']
PublicSubnetOne:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 0
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref FargateVpc
CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR']
MapPublicIpOnLaunch: true
PublicSubnetTwo:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone:
Fn::Select:
- 1
- Fn::GetAZs: {Ref: 'AWS::Region'}
VpcId: !Ref FargateVpc
CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR']
MapPublicIpOnLaunch: true
InternetGateway:
Type: AWS::EC2::InternetGateway
GatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref FargateVpc
InternetGatewayId: !Ref InternetGateway
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref FargateVpc
PublicRoute:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: '0.0.0.0/0'
GatewayId: !Ref InternetGateway
PublicSubnetOneRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetOne
RouteTableId: !Ref PublicRouteTable
PublicSubnetTwoRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnetTwo
RouteTableId: !Ref PublicRouteTable
# ECS Cluster
ECSCluster:
Type: AWS::ECS::Cluster
# ECS Roles
# ECS Roles
# This role is used by the ECS tasks themselves.
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs-tasks.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: AmazonECSTaskExecutionRolePolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
# Allow the ECS Tasks to download images from ECR
- 'ecr:GetAuthorizationToken'
- 'ecr:BatchCheckLayerAvailability'
- 'ecr:GetDownloadUrlForLayer'
- 'ecr:BatchGetImage'
# Allow the ECS tasks to upload logs to CloudWatch
- 'logs:CreateLogStream'
- 'logs:PutLogEvents'
Resource: '*'
# This is an IAM role which authorizes ECS to manage resources on our
# account on our behalf, such as updating our load balancer with the
# details of where our containers are, so that traffic can reach your
# containers.
ECSRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action:
# Rules which allow ECS to attach network interfaces to instances
# on our behalf in order for awsvpc networking mode to work right
- 'ec2:AttachNetworkInterface'
- 'ec2:CreateNetworkInterface'
- 'ec2:CreateNetworkInterfacePermission'
- 'ec2:DeleteNetworkInterface'
- 'ec2:DeleteNetworkInterfacePermission'
- 'ec2:Describe*'
- 'ec2:DetachNetworkInterface'
# Rules which allow ECS to update load balancers on our behalf
# with the information about how to send traffic to our containers
- 'elasticloadbalancing:DeregisterInstancesFromLoadBalancer'
- 'elasticloadbalancing:DeregisterTargets'
- 'elasticloadbalancing:Describe*'
- 'elasticloadbalancing:RegisterInstancesWithLoadBalancer'
- 'elasticloadbalancing:RegisterTargets'
Resource: '*'
# Load Balancer Security group
PublicLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to the public facing load balancer from entire internet range
VpcId: !Ref FargateVpc
SecurityGroupIngress:
- CidrIp: 0.0.0.0/0
IpProtocol: -1
# Fargate Container Security Group
FargateContainerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Access to fargate containers
VpcId: !Ref FargateVpc
EcsSecurityGroupIngressFromPublicALB:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress from the public ALB
GroupId: !Ref FargateContainerSecurityGroup
IpProtocol: -1
SourceSecurityGroupId: !Ref PublicLoadBalancerSG
EcsSecurityGroupIngressFromSelf:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: Ingress from other containers in the same security group
GroupId: !Ref FargateContainerSecurityGroup
IpProtocol: -1
SourceSecurityGroupId: !Ref FargateContainerSecurityGroup
# Load Balancer
PublicLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Scheme: internet-facing
LoadBalancerAttributes:
- Key: idle_timeout.timeout_seconds
Value: '30'
Subnets:
- !Ref PublicSubnetOne
- !Ref PublicSubnetTwo
SecurityGroups: [!Ref 'PublicLoadBalancerSG']
# Target Group
DummyTargetGroupPublic:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
Name: !Join ['-', [!Ref 'AWS::StackName', 'drop-1']]
Port: 80
Protocol: HTTP
UnhealthyThresholdCount: 2
VpcId: !Ref 'FargateVpc'
# Listener
PublicLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
DependsOn:
- PublicLoadBalancer
Properties:
DefaultActions:
- TargetGroupArn: !Ref 'DummyTargetGroupPublic'
Type: 'forward'
LoadBalancerArn: !Ref 'PublicLoadBalancer'
Port: 80
Protocol: HTTP
Outputs:
VPCId:
Description: The ID of the vpc that this stack is deployed on
Value: !Ref FargateVpc
Export:
Name: !Join [':', [!Ref 'AWS::StackName', 'VPCId']]
PublicSubnetOne:
Description: Public subnet one
Value: !Ref 'PublicSubnetOne'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetOne' ] ]
PublicSubnetTwo:
Description: Public subnet two
Value: !Ref 'PublicSubnetTwo'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicSubnetTwo' ] ]
FargateContainerSecurityGroup:
Description: A security group used to allow Fargate containers to receive traffic
Value: !Ref 'FargateContainerSecurityGroup'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'FargateContainerSecurityGroup' ] ]
# ECS Outputs
ClusterName:
Description: The name of the ECS cluster
Value: !Ref 'ECSCluster'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ClusterName' ] ]
ECSRole:
Description: The ARN of the ECS role
Value: !GetAtt 'ECSRole.Arn'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ECSRole' ] ]
ECSTaskExecutionRole:
Description: The ARN of the ECS role
Value: !GetAtt 'ECSTaskExecutionRole.Arn'
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ECSTaskExecutionRole' ] ]
PublicListener:
Description: The ARN of the public load balancer's Listener
Value: !Ref PublicLoadBalancerListener
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'PublicListener' ] ]
ExternalUrl:
Description: The url of the external load balancer
Value: !Join ['', ['http://', !GetAtt 'PublicLoadBalancer.DNSName']]
Export:
Name: !Join [ ':', [ !Ref 'AWS::StackName', 'ExternalUrl' ] ]
2) Service Stack
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy a service on AWS Fargate, hosted in a public subnet of a VPC, and accessible via a public load balancer
# Input Paramters
Parameters:
StackName:
Type: String
Default: test-fargate
Description: The name of the parent fargate networking stack
ServiceName:
Type: String
Default: nginx
Description: Name of the ECS service
ImageUrl:
Type: String
Default: nginx
Description: The url of a docker image that contains the application process that
will handle the traffic for this service
ContainerPort:
Type: Number
Default: 80
Description: What port number the application inside the docker container is binding to
ContainerCpu:
Type: Number
Default: 256
Description: How much CPU to give the container. 1024 is 1 CPU
ContainerMemory:
Type: Number
Default: 512
Description: How much memory in megabytes to give the container
Path:
Type: String
Default: "*"
Description: A path on the public load balancer that this service
should be connected to. Use * to send all load balancer
traffic to this service.
Priority:
Type: Number
Default: 1
Description: The priority for the routing rule added to the load balancer.
This only applies if your have multiple services which have been
assigned to different paths on the load balancer.
DesiredCount:
Type: Number
Default: 2
Description: How many copies of the service task to run
Role:
Type: String
Default: ""
Description: (Optional) An IAM role to give the service's containers if the code within needs to
access other AWS resources like S3 buckets, DynamoDB tables, etc
Conditions:
HasCustomRole: !Not [!Equals [!Ref 'Role', '']]
# Task Definition
Resources:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: !Ref 'ServiceName'
Cpu: !Ref 'ContainerCpu'
Memory: !Ref 'ContainerMemory'
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
ExecutionRoleArn:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'ECSTaskExecutionRole']]
TaskRoleArn:
Fn::If:
- 'HasCustomRole'
- !Ref 'Role'
- !Ref "AWS::NoValue"
ContainerDefinitions:
- Name: !Ref 'ServiceName'
Cpu: !Ref 'ContainerCpu'
Memory: !Ref 'ContainerMemory'
Image: !Ref 'ImageUrl'
PortMappings:
- ContainerPort: !Ref 'ContainerPort'
# ALB Target Group
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckIntervalSeconds: 6
HealthCheckPath: /
HealthCheckProtocol: HTTP
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
TargetType: ip
Name: !Ref 'ServiceName'
Port: !Ref 'ContainerPort'
Protocol: HTTP
UnhealthyThresholdCount: 2
VpcId:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'VPCId']]
# ALB Rule
LoadBalancerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- TargetGroupArn: !Ref 'TargetGroup'
Type: 'forward'
Conditions:
- Field: path-pattern
Values: [!Ref 'Path']
ListenerArn:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'PublicListener']]
Priority: !Ref 'Priority'
# ECS or Fargate Service
Service:
Type: AWS::ECS::Service
DependsOn: LoadBalancerRule
Properties:
ServiceName: !Ref 'ServiceName'
Cluster:
Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'ClusterName']]
LaunchType: FARGATE
DeploymentConfiguration:
MaximumPercent: 200
MinimumHealthyPercent: 75
DesiredCount: !Ref 'DesiredCount'
NetworkConfiguration:
AwsvpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'FargateContainerSecurityGroup']]
Subnets:
- Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'PublicSubnetOne']]
- Fn::ImportValue:
!Join [':', [!Ref 'StackName', 'PublicSubnetTwo']]
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: !Ref 'ServiceName'
ContainerPort: !Ref 'ContainerPort'
TargetGroupArn: !Ref 'TargetGroup'
Based on the comments.
The issue was that the first and second templates were being deployed into one stack. The solution was to deploy the second template as a separate stack.