{ "AWSTemplateFormatVersion":"2010-09-09", "Description" : "ArcGIS CloudFormation Template: Provisions an ArcGIS Server site using EC2 Container Service", "Parameters":{ "DeploymentBucket" : { "Description" : "S3 bucket with ArcGIS Server authorization file", "Type" : "String", "AllowedPattern" : "^([a-z]|(\\d(?!\\d{0,2}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})))([a-z\\d]|(\\.(?!(\\.|-)))|(-(?!\\.))){1,61}[a-z\\d\\.]$", "ConstraintDescription" : "A Bucket's name can be between 6 and 63 characters long, containing lowercase characters, numbers, periods, and dashes and it must start with a lowercase letter or number." }, "ServerLicenseFile": { "Description": "ArcGIS Image Server authorization file (must be uploaded to DeploymentBucket)", "Type": "String", "AllowedPattern": "^([\\w\\-\\.]+)+\\.(ecp|prvc)$", "ConstraintDescription": "License file name must be alphanumeric. It can contain dash ('-'), dot ('.'), and underscore ('_') characters. The file name must end with '.ecp' or '.prvc'." }, "SiteAdmin": { "Description": "User name for ArcGIS Server site admin and Portal initial admin accounts", "Type": "String", "Default": "admin", "AllowedPattern": "^[a-zA-Z][a-zA-Z0-9_]{4,}$", "ConstraintDescription": "User name must be 4 or more alphanumeric or underscore (_) characters and must start with a letter." }, "SiteAdminPassword": { "Description": "Password for the site admin account", "Type": "String", "NoEcho": "true", "AllowedPattern": "^[a-zA-Z0-9_\\.@]{8,}$", "ConstraintDescription": "Password must be 8 or more alphanumeric, underscore (_), at ('@'), or dot (.) characters." }, "KeyName":{ "Type":"AWS::EC2::KeyPair::KeyName", "Description":"Name of an existing EC2 KeyPair to enable SSH access to the ECS instances." }, "VPCId":{ "Type":"AWS::EC2::VPC::Id", "Description":"Select a VPC that allows instances to access the Internet." }, "SubnetID":{ "Type":"List", "Description":"Select two subnets in your selected VPC." }, "DesiredCapacity":{ "Type":"Number", "Default":"1", "MinValue" : "1", "Description":"Number of instances to launch in your ECS cluster." }, "InstanceType":{ "Description":"EC2 instance type", "Type":"String", "Default":"m4.large", "AllowedValues":[ "m3.large", "m3.xlarge", "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "c5.large", "c5.xlarge", "c5.2xlarge", "c5.4xlarge", "c5.9xlarge", "c5.18xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "r4.large", "r4.xlarge", "r4.2xlarge", "r4.4xlarge", "r4.8xlarge","r4.16xlarge", "i3.large", "i3.xlarge", "i3.2xlarge", "i3.4xlarge", "i3.8xlarge","i3.16xlarge", "d2.large", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "t2.large", "t2.xlarge", "t2.2xlarge", "p2.xlarge", "p2.8xlarge", "p2.16xlarge", "g3.4xlarge", "g3.8xlarge", "g3.16xlarge", "x1.16xlarge", "x1.32xlarge" ], "ConstraintDescription":"Please choose a valid instance type." }, "SSLCertificateARN": { "Description": "ARN of the SSL certificate issued to the site domain", "Type": "String", "AllowedPattern": "[^\"]{1,1024}", "ConstraintDescription": "arn:aws:acm:::certificate/" } }, "Mappings":{ "AWSRegionToAMI":{ "us-east-1":{ "AMIID":"ami-04351e12" }, "us-east-2":{ "AMIID":"ami-207b5a45" }, "us-west-1":{ "AMIID":"ami-7d664a1d" }, "us-west-2":{ "AMIID":"ami-57d9cd2e" }, "eu-west-1":{ "AMIID":"ami-809f84e6" }, "eu-west-2":{ "AMIID":"ami-ff15039b" }, "eu-central-1":{ "AMIID":"ami-a3a006cc" }, "ap-northeast-1":{ "AMIID":"ami-e4657283" }, "ap-southeast-1":{ "AMIID":"ami-19f7787a" }, "ap-southeast-2":{ "AMIID":"ami-42e9f921" }, "ca-central-1":{ "AMIID":"ami-3da81759" } } }, "Resources":{ "ValidateParametersFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Code": { "S3Bucket": {"Fn::Join" : ["", ["pavel-deploymentbucket", "-", {"Ref": "AWS::Region"}]]}, "S3Key": "6491/8321/lambda/arcgis-cfn-lambda.zip" }, "Handler": "parameters.handler", "Runtime": "python2.7", "Timeout": "300", "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] } } }, "DecrementFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Handler": "index.handler", "Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }, "Runtime": "nodejs6.10", "Code": { "ZipFile" : { "Fn::Join":["", [ "var response = require('cfn-response');\n", "exports.handler = function(event, context) {\n", "var result = parseInt(event.ResourceProperties.Op) - 1;\n", "response.send(event, context, response.SUCCESS, {Value: result});\n", "};\n" ]] } } } }, "LambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com"]}, "Action": ["sts:AssumeRole"] }] }, "Path": "/", "Policies": [{ "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"], "Resource": "*" }, { "Effect": "Allow", "Action": ["dynamodb:*"], "Resource": "*" }, { "Effect": "Allow", "Action": ["s3:*"], "Resource": "*" }] } }] } }, "ValidateServerLicenseFile": { "Type": "Custom::ValidateParameters", "Properties": { "ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]}, "DeploymentBucket": {"Ref": "DeploymentBucket"}, "S3Key": {"Ref": "ServerLicenseFile"} } }, "DecrementDesiredCapacity": { "Type": "Custom::DecrementDesiredCapacity", "Properties": { "ServiceToken": {"Fn::GetAtt": ["DecrementFunction", "Arn"]}, "Op": {"Ref": "DesiredCapacity"} } }, "ECSCluster":{ "Type":"AWS::ECS::Cluster" }, "EcsSecurityGroup":{ "Type":"AWS::EC2::SecurityGroup", "Properties":{ "GroupDescription":"ECS Security Group", "VpcId":{ "Ref":"VPCId" } } }, "EcsSecurityGroupHTTPinbound":{ "Type":"AWS::EC2::SecurityGroupIngress", "Properties":{ "GroupId":{ "Ref":"EcsSecurityGroup" }, "IpProtocol":"tcp", "FromPort":"80", "ToPort":"80", "CidrIp":"0.0.0.0/0" } }, "EcsSecurityGroupHTTPSinbound":{ "Type":"AWS::EC2::SecurityGroupIngress", "Properties":{ "GroupId":{ "Ref":"EcsSecurityGroup" }, "IpProtocol":"tcp", "FromPort":"443", "ToPort":"443", "CidrIp":"0.0.0.0/0" } }, "EcsSecurityGroupSSHinbound":{ "Type":"AWS::EC2::SecurityGroupIngress", "Properties":{ "GroupId":{ "Ref":"EcsSecurityGroup" }, "IpProtocol":"tcp", "FromPort":"22", "ToPort":"22", "CidrIp":"0.0.0.0/0" } }, "EcsSecurityGroupALBports":{ "Type":"AWS::EC2::SecurityGroupIngress", "Properties":{ "GroupId":{ "Ref":"EcsSecurityGroup" }, "IpProtocol":"tcp", "FromPort":"3100", "ToPort":"61000", "SourceSecurityGroupId":{ "Ref":"EcsSecurityGroup" } } }, "CloudwatchLogsGroup":{ "Type":"AWS::Logs::LogGroup", "Properties":{ "LogGroupName":{ "Fn::Join":[ "-", [ "ECSLogGroup", { "Ref":"AWS::StackName" } ] ] }, "RetentionInDays":14 } }, "PrimaryServerTask":{ "Type":"AWS::ECS::TaskDefinition", "Properties":{ "Family":{ "Fn::Join":[ "", [ { "Ref":"AWS::StackName" }, "-site" ] ] }, "NetworkMode" : "host", "ContainerDefinitions":[ { "Name":"server-primary", "EntryPoint": [ "/bin/bash", "-c", "/opt/chef/bin/chef-client -c /tmp/chef/zero.rb -z -j /tmp/data/arcgis-server-ecs-primary.json -l info -L /tmp/chef/chef-run.log \u0026\u0026 /usr/bin/tail -f /tmp/chef/chef-run.log" ], "Cpu":"512", "Essential":"true", "Image":"685115441969.dkr.ecr.us-west-2.amazonaws.com/arcgis-server-with-chef:1051", "Memory":"6000", "LogConfiguration":{ "LogDriver":"awslogs", "Options":{ "awslogs-group":{ "Ref": "CloudwatchLogsGroup" }, "awslogs-region":{ "Ref":"AWS::Region" }, "awslogs-stream-prefix":"ecs-server-primary" } }, "MountPoints":[ { "ContainerPath":"/gisdata", "SourceVolume":"gisdata-vol" }, { "ContainerPath":"/tmp/data", "SourceVolume":"tmp-vol" } ], "PortMappings":[ { "ContainerPort":6080, "HostPort":6080 }, { "ContainerPort":6443, "HostPort":6443 } ] } ], "Volumes":[ { "Name":"gisdata-vol", "Host": { "SourcePath":"/mnt/efs" } }, { "Name":"tmp-vol", "Host": { "SourcePath":"/tmp" } } ] } }, "NodeServerTask":{ "Type":"AWS::ECS::TaskDefinition", "Properties":{ "Family":{ "Fn::Join":[ "", [ { "Ref":"AWS::StackName" }, "-node" ] ] }, "NetworkMode" : "host", "ContainerDefinitions":[ { "Name":"server-node", "EntryPoint": [ "/bin/bash", "-c", "/opt/chef/bin/chef-client -c /tmp/chef/zero.rb -z -j /tmp/data/arcgis-server-ecs-node.json -l info -L /tmp/chef/chef-run.log \u0026\u0026 /usr/bin/tail -f /tmp/chef/chef-run.log" ], "Cpu":"512", "Essential":"true", "Image":"685115441969.dkr.ecr.us-west-2.amazonaws.com/arcgis-server-with-chef:1051", "Memory":"6000", "LogConfiguration":{ "LogDriver":"awslogs", "Options":{ "awslogs-group":{ "Ref": "CloudwatchLogsGroup" }, "awslogs-region":{ "Ref":"AWS::Region" }, "awslogs-stream-prefix":"ecs-server-node" } }, "MountPoints":[ { "ContainerPath":"/gisdata", "SourceVolume":"gisdata-vol" }, { "ContainerPath":"/tmp/data", "SourceVolume":"tmp-vol" } ], "PortMappings":[ { "ContainerPort":6080, "HostPort":6080 }, { "ContainerPort":6443, "HostPort":6443 } ] } ], "Volumes":[ { "Name":"gisdata-vol", "Host": { "SourcePath":"/mnt/efs" } }, { "Name":"tmp-vol", "Host": { "SourcePath":"/tmp" } } ] } }, "ECSALB":{ "Type":"AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties":{ "Name":{ "Ref":"AWS::StackName" }, "Scheme":"internet-facing", "LoadBalancerAttributes":[ { "Key":"idle_timeout.timeout_seconds", "Value":"300" } ], "Subnets":{ "Ref":"SubnetID" }, "SecurityGroups":[ { "Ref":"EcsSecurityGroup" } ] } }, "ALBListener":{ "Type":"AWS::ElasticLoadBalancingV2::Listener", "DependsOn":"ECSServiceRole", "Properties":{ "DefaultActions":[ { "Type":"forward", "TargetGroupArn": { "Ref":"ECSTGHTTPS" } } ], "LoadBalancerArn":{ "Ref":"ECSALB" }, "Port":"80", "Protocol":"HTTP" } }, "ECSALBListenerRule":{ "Type":"AWS::ElasticLoadBalancingV2::ListenerRule", "DependsOn":"ALBListener", "Properties":{ "Actions":[ { "Type":"forward", "TargetGroupArn":{ "Ref":"ECSTGHTTPS" } } ], "Conditions":[ { "Field":"path-pattern", "Values":[ "/" ] } ], "ListenerArn":{ "Ref":"ALBListener" }, "Priority":1 } }, "ALBHTTPSListener":{ "Type":"AWS::ElasticLoadBalancingV2::Listener", "DependsOn":"ECSServiceRole", "Properties":{ "DefaultActions":[ { "Type":"forward", "TargetGroupArn": { "Ref":"ECSTGHTTPS" } } ], "LoadBalancerArn":{ "Ref":"ECSALB" }, "Port":"443", "Protocol":"HTTPS", "Certificates": [ { "CertificateArn" : { "Ref" : "SSLCertificateARN"} } ] } }, "ECSALBHTTPSListenerRule":{ "Type":"AWS::ElasticLoadBalancingV2::ListenerRule", "DependsOn":"ALBHTTPSListener", "Properties":{ "Actions":[ { "Type":"forward", "TargetGroupArn":{ "Ref":"ECSTGHTTPS" } } ], "Conditions":[ { "Field":"path-pattern", "Values":[ "/" ] } ], "ListenerArn":{ "Ref":"ALBHTTPSListener" }, "Priority":1 } }, "ECSTG":{ "Type":"AWS::ElasticLoadBalancingV2::TargetGroup", "DependsOn":"ECSALB", "Properties":{ "HealthCheckIntervalSeconds":10, "HealthCheckPath":"/arcgis/", "HealthCheckProtocol":"HTTP", "HealthCheckTimeoutSeconds":5, "HealthyThresholdCount":2, "Name":{ "Fn::Join":[ "-", [ { "Ref":"AWS::StackName" }, "HTTP" ] ] }, "Port":80, "Protocol":"HTTP", "UnhealthyThresholdCount":2, "VpcId":{ "Ref":"VPCId" } } }, "ECSTGHTTPS":{ "Type":"AWS::ElasticLoadBalancingV2::TargetGroup", "DependsOn":"ECSALB", "Properties":{ "HealthCheckIntervalSeconds":60, "HealthCheckPath":"/arcgis/", "HealthCheckProtocol":"HTTPS", "HealthCheckTimeoutSeconds":5, "HealthyThresholdCount":2, "Name":{ "Fn::Join":[ "-", [ { "Ref":"AWS::StackName" }, "HTTPS" ] ] }, "Port":443, "Protocol":"HTTPS", "UnhealthyThresholdCount":10, "VpcId":{ "Ref":"VPCId" } } }, "ECSAutoScalingGroup":{ "Type":"AWS::AutoScaling::AutoScalingGroup", "DependsOn" : [ "MountTarget1", "MountTarget2" ], "Properties":{ "VPCZoneIdentifier":{ "Ref":"SubnetID" }, "LaunchConfigurationName":{ "Ref":"ContainerInstances" }, "MinSize":"1", "MaxSize":{ "Ref":"DesiredCapacity" }, "DesiredCapacity":{ "Ref":"DesiredCapacity" }, "Tags" : [ { "Key" : "Name", "Value" : {"Ref" : "AWS::StackName"}, "PropagateAtLaunch" : true } ] }, "CreationPolicy":{ "ResourceSignal":{ "Count": { "Ref":"DesiredCapacity" }, "Timeout":"PT30M" } }, "UpdatePolicy":{ "AutoScalingReplacingUpdate":{ "WillReplace":"true" } } }, "ContainerInstances":{ "Type":"AWS::AutoScaling::LaunchConfiguration", "Properties":{ "AssociatePublicIpAddress" : true, "ImageId":{ "Fn::FindInMap":[ "AWSRegionToAMI", { "Ref":"AWS::Region" }, "AMIID" ] }, "SecurityGroups":[ { "Ref":"EcsSecurityGroup" } ], "InstanceType":{ "Ref":"InstanceType" }, "IamInstanceProfile":{ "Ref":"EC2InstanceProfile" }, "KeyName":{ "Ref":"KeyName" }, "UserData":{ "Fn::Base64":{ "Fn::Join":[ "", [ "#!/bin/bash -xe\n", "echo ECS_CLUSTER=", { "Ref":"ECSCluster" }, " >> /etc/ecs/ecs.config\n", "yum install -y aws-cfn-bootstrap\n", "/opt/aws/bin/cfn-init -v -s ", {"Ref": "AWS::StackName"}, " -r ContainerInstances", " --region ", {"Ref": "AWS::Region"}, "\n", "yum install -y nfs-utils\n", "mkdir /mnt/efs\n", "mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 ", { "Ref" : "FileSystem" }, ".efs.", { "Ref": "AWS::Region" }, ".amazonaws.com:/ /mnt/efs\n", "chmod -R 777 /mnt/efs\n", "service docker stop\n", "service docker start\n", "/opt/aws/bin/cfn-signal -e $? --stack ", { "Ref":"AWS::StackName" }, " --resource ECSAutoScalingGroup --region ", { "Ref":"AWS::Region" }, "\n" ] ] } } }, "Metadata": { "AWS::CloudFormation::Authentication": { "S3AccessCreds": { "type": "S3", "buckets": [ {"Ref": "DeploymentBucket"} ], "roleName": {"Ref": "EC2Role"} } }, "AWS::CloudFormation::Init": { "config": { "commands":{ "rename-server-license": { "command": {"Fn::Join": ["", ["mv /tmp/server_license.tmp /tmp/", {"Ref": "ServerLicenseFile"}]]} } }, "sources": { "/var/chef": "https://s3-us-west-2.amazonaws.com/pavel-deploymentbucket/6491/cookbooks/arcgis-2.3.2-cookbooks.tar.gz" }, "files":{ "/tmp/server_license.tmp": { "source": {"Fn::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]}, "authentication": "S3AccessCreds", "mode" : "000755" }, "/tmp/arcgis-server-ecs-primary.json": { "content": { "Fn::Join": [ "", [ "{\n", " \"arcgis\" : {\n", " \"run_as_user\": \"ubuntu\",\n", " \"version\": \"10.5.1\",\n", " \"server\" : {\n", " \"install_dir\":\"/home/ubuntu\",\n", " \"admin_username\" : \"", {"Ref": "SiteAdmin"}, "\",\n", " \"admin_password\" : \"", {"Ref": "SiteAdminPassword"}, "\",\n", " \"directories_root\" : \"/gisdata/arcgisserver\",\n", " \"authorization_file\" : \"/tmp/data/", {"Ref": "ServerLicenseFile"}, "\",\n", " \"install_system_requirements\" : false,\n", " \"configure_autostart\":false\n", " }\n", " },\n", " \"run_list\" : [\n", " \"recipe[arcgis-enterprise::server]\"\n", " ]\n", "}\n" ] ] } }, "/tmp/arcgis-server-ecs-node.json": { "content": { "Fn::Join": [ "", [ "{\n", " \"arcgis\" : {\n", " \"run_as_user\": \"ubuntu\",\n", " \"version\": \"10.5.1\",\n", " \"server\" : {\n", " \"install_dir\":\"/home/ubuntu\",\n", " \"authorization_file\" : \"/tmp/data/", {"Ref": "ServerLicenseFile"}, "\",\n", " \"install_system_requirements\" : false,\n", " \"configure_autostart\":false,\n", " \"config_store_connection_string\":\"/gisdata/arcgisserver/config-store\",\n", " \"use_join_site_tool\":true\n", " }\n", " },\n", " \"run_list\" : [\n", " \"recipe[arcgis-enterprise::server_node]\"\n", " ]\n", "}\n" ] ] } } } } } } }, "PrimaryServerService":{ "Type":"AWS::ECS::Service", "DependsOn":"ALBListener", "Properties":{ "Cluster":{ "Ref":"ECSCluster" }, "DesiredCount":"1", "LoadBalancers":[ { "ContainerName":"server-primary", "ContainerPort":"6443", "TargetGroupArn":{ "Ref": "ECSTGHTTPS" } } ], "Role":{ "Ref":"ECSServiceRole" }, "TaskDefinition":{ "Ref":"PrimaryServerTask" } } }, "NodeServerService":{ "Type":"AWS::ECS::Service", "DependsOn":"PrimaryServerService", "Properties":{ "Cluster":{ "Ref":"ECSCluster" }, "DesiredCount": {"Fn::GetAtt": [ "DecrementDesiredCapacity", "Value" ]}, "LoadBalancers":[ { "ContainerName":"server-node", "ContainerPort":"6443", "TargetGroupArn":{ "Ref": "ECSTGHTTPS" } } ], "Role":{ "Ref":"ECSServiceRole" }, "TaskDefinition":{ "Ref":"NodeServerTask" } } }, "ECSServiceRole":{ "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":[ "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:Describe*", "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:RegisterTargets", "ec2:Describe*", "ec2:AuthorizeSecurityGroupIngress" ], "Resource":"*" } ] } } ] } }, "ServiceScalingTarget":{ "Type":"AWS::ApplicationAutoScaling::ScalableTarget", "DependsOn":"PrimaryServerService", "Properties":{ "MaxCapacity":{ "Ref":"DesiredCapacity" }, "MinCapacity":1, "ResourceId":{ "Fn::Join":[ "", [ "service/", { "Ref":"ECSCluster" }, "/", { "Fn::GetAtt":[ "PrimaryServerService", "Name" ] } ] ] }, "RoleARN":{ "Fn::GetAtt":[ "AutoScalingRole", "Arn" ] }, "ScalableDimension":"ecs:service:DesiredCount", "ServiceNamespace":"ecs" } }, "ServiceScalingPolicy":{ "Type":"AWS::ApplicationAutoScaling::ScalingPolicy", "Properties":{ "PolicyName":"AStepPolicy", "PolicyType":"StepScaling", "ScalingTargetId":{ "Ref":"ServiceScalingTarget" }, "StepScalingPolicyConfiguration":{ "AdjustmentType":"PercentChangeInCapacity", "Cooldown":60, "MetricAggregationType":"Average", "StepAdjustments":[ { "MetricIntervalLowerBound":0, "ScalingAdjustment":50 } ] } } }, "ALB500sAlarmScaleUp":{ "Type":"AWS::CloudWatch::Alarm", "Properties":{ "EvaluationPeriods":"1", "Statistic":"Average", "Threshold":"10", "AlarmDescription":"Alarm if our ALB generates too many HTTP 500s.", "Period":"60", "AlarmActions":[ { "Ref":"ServiceScalingPolicy" } ], "Namespace":"AWS/ApplicationELB", "Dimensions":[ { "Name":"ECSService", "Value":{ "Ref":"PrimaryServerService" } } ], "ComparisonOperator":"GreaterThanThreshold", "MetricName":"HTTPCode_ELB_5XX_Count" } }, "EC2Role":{ "Type":"AWS::IAM::Role", "Properties":{ "AssumeRolePolicyDocument":{ "Statement":[ { "Effect":"Allow", "Principal":{ "Service":[ "ec2.amazonaws.com" ] }, "Action":[ "sts:AssumeRole" ] } ] }, "Path":"/", "Policies":[ { "PolicyName":"ecs-service", "PolicyDocument":{ "Statement":[ { "Effect":"Allow", "Action":[ "ecs:CreateCluster", "ecs:DeregisterContainerInstance", "ecs:DiscoverPollEndpoint", "ecs:Poll", "ecs:RegisterContainerInstance", "ecs:StartTelemetrySession", "ecs:Submit*", "logs:CreateLogStream", "logs:PutLogEvents", "ecr:GetAuthorizationToken", "ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer", "s3:*" ], "Resource":"*" } ] } } ] } }, "AutoScalingRole":{ "Type":"AWS::IAM::Role", "Properties":{ "AssumeRolePolicyDocument":{ "Statement":[ { "Effect":"Allow", "Principal":{ "Service":[ "application-autoscaling.amazonaws.com" ] }, "Action":[ "sts:AssumeRole" ] } ] }, "Path":"/", "Policies":[ { "PolicyName":"service-autoscaling", "PolicyDocument":{ "Statement":[ { "Effect":"Allow", "Action":[ "application-autoscaling:*", "cloudwatch:DescribeAlarms", "cloudwatch:PutMetricAlarm", "ecs:DescribeServices", "ecs:UpdateService" ], "Resource":"*" } ] } } ] } }, "EC2InstanceProfile":{ "Type":"AWS::IAM::InstanceProfile", "Properties":{ "Path":"/", "Roles":[ { "Ref":"EC2Role" } ] } }, "MountTargetSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "VpcId": { "Ref": "VPCId" }, "GroupDescription": "Security group for mount target", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "2049", "ToPort": "2049", "SourceSecurityGroupId" : {"Ref" : "EcsSecurityGroup"} } ] } }, "FileSystem": { "Type": "AWS::EFS::FileSystem", "Properties": { "FileSystemTags": [ { "Key": "Name", "Value": {"Ref": "AWS::StackName"} } ] } }, "MountTarget1": { "Type": "AWS::EFS::MountTarget", "Properties": { "FileSystemId": { "Ref": "FileSystem" }, "SubnetId": { "Fn::Select" : [ "0", {"Ref": "SubnetID"} ] }, "SecurityGroups": [ { "Ref": "MountTargetSecurityGroup" } ] } }, "MountTarget2": { "Type": "AWS::EFS::MountTarget", "Properties": { "FileSystemId": { "Ref": "FileSystem" }, "SubnetId": { "Fn::Select" : [ "1", {"Ref": "SubnetID"} ] }, "SecurityGroups": [ { "Ref": "MountTargetSecurityGroup" } ] } } }, "Outputs":{ "ManagerURL" : { "Value" : {"Fn::Join" : [ "", [ "https://", {"Fn::GetAtt" : ["ECSALB", "DNSName"]}, "/arcgis/manager" ]]}, "Description" : "ArcGIS Server Manager URL" }, "RestURL" : { "Value" : {"Fn::Join" : [ "", [ "https://", {"Fn::GetAtt" : ["ECSALB", "DNSName"]}, "/arcgis/rest" ]]}, "Description" : "ArcGIS REST Services Directory URL" }, "ECSCluster":{ "Value":{ "Ref":"ECSCluster" } }, "ECSALB":{ "Description":"Application load balancer DNS", "Value":{ "Fn::Join":[ "", [ { "Fn::GetAtt":[ "ECSALB", "DNSName" ] } ] ] } } } }