{
  "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-zA-Z][0-9a-zA-Z-_.]{2,62}",
      "ConstraintDescription" : "S3 bucket name must be between 3 and 63 characters and and must start with a letter."
    },
    "ServerLicenseFile": {
      "Description": "ArcGIS Image Server authorization file (must be uploaded to DeploymentBucket)",
      "Type": "String",
      "AllowedPattern": "[^\"]{1,1024}",
      "ConstraintDescription": "S3 object key name must be between 1 and 1024 characters."
    },
    "SiteAdmin": {
        "Description": "User name for ArcGIS Server site admin and Portal initial admin accounts",
        "Type": "String",
        "Default": "admin",
        "AllowedPattern": "[0-9a-zA-Z.]{4,24}",
        "ConstraintDescription": "User name must be between 4 and 24 characters and can only contain digits 0 through 9, ASCII letters A through Z (uppercase and lowercase), and a dot (.)."
    },
    "SiteAdminPassword": {
        "Description": "Password for the site admin account",
        "Type": "String",
        "NoEcho": "true",
        "AllowedPattern": "[0-9a-zA-Z.]{4,24}",
        "ConstraintDescription": "Password must be between 4 and 24 characters and can only contain digits 0 through 9, ASCII letters A through Z (uppercase and lowercase), and a dot (.)."
    },
    "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<AWS::EC2::Subnet::Id>",
      "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":[
        "t2.large",
        "m3.large", "m3.xlarge", "m3.2xlarge",
        "m4.large",  "m4.xlarge", "m4.2xlarge", "m4.4xlarge", "m4.10xlarge",
        "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge",
        "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge",
        "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge",
        "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge" ],
      "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:<region>:<account-id>:certificate/<resource>"
    }
  },
  "Mappings":{
    "AWSRegionToAMI":{
      "us-east-1":{
        "AMIID":"ami-644a431b"
      },
      "us-east-2":{
        "AMIID":"ami-79d8e21c"
      },
      "us-west-1":{
        "AMIID":"ami-4351bc20"
      },
      "us-west-2":{
        "AMIID":"ami-f189d189"
      },
      "eu-west-1":{
        "AMIID":"ami-39d530d4"
      },
      "eu-west-2":{
        "AMIID":"ami-2e9866c5"
      },
      "eu-central-1":{
        "AMIID":"ami-9fe2e074"
      },
      "ap-northeast-1":{
        "AMIID":"ami-7d0c7a90"
      },
      "ap-southeast-1":{
        "AMIID":"ami-ae1b5a44"
      },
      "ap-southeast-2":{
        "AMIID":"ami-706cca12"
      },
      "ca-central-1":{
        "AMIID":"ami-c1b63ba5"
      }
    }
  },
  "Resources":{
    "ValidateParametersFunction": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Join" : ["", ["arcgisstore1051", "-", {"Ref": "AWS::Region"}]]},
          "S3Key": "7333/lambda/arcgis-cfn-lambda-python3.zip"
        },
        "Handler": "parameters.handler",
        "Runtime": "python3.8",
        "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": "arn:aws:logs:*:*:*"
            },
            {
              "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":"248675906072.dkr.ecr.us-west-2.amazonaws.com/arcgis-server:1051",
            "Memory":"6000",
            "LogConfiguration":{
              "LogDriver":"awslogs",
              "Options":{
                "awslogs-group":{ "Ref": "CloudwatchLogsGroup" },
                "awslogs-region":{ "Ref":"AWS::Region" },
                "awslogs-stream-prefix":"ecs-server-primary"
              }
            },
            "VolumesFrom" : [
              {
                 "SourceContainer" : "chef-client",
                 "ReadOnly" : false
              }
            ], 
            "MountPoints":[
              {
                "ContainerPath":"/gisdata",
                "SourceVolume":"gisdata-vol"
              },
              {
                "ContainerPath":"/tmp/data",
                "SourceVolume":"tmp-vol"
              }
            ],
            "PortMappings":[
              {
                "ContainerPort":6080,
                "HostPort":6080
              },
              {
                "ContainerPort":6443,
                "HostPort":6443
              }
            ]
          },
          {
            "Name":"chef-client",
            "EntryPoint": [
              "/bin/bash", "-c",
              "/usr/bin/tail -f /tmp/chef/zero.rb"
            ],
            "Cpu":"512",
            "Essential":"true",
            "Image":"248675906072.dkr.ecr.us-west-2.amazonaws.com/chef-client:12",
            "Memory":"1000"
          }
        ],
        "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":"248675906072.dkr.ecr.us-west-2.amazonaws.com/arcgis-server:1051",
            "Memory":"6000",
            "LogConfiguration":{
              "LogDriver":"awslogs",
              "Options":{
                "awslogs-group":{ "Ref": "CloudwatchLogsGroup" },
                "awslogs-region":{ "Ref":"AWS::Region" },
                "awslogs-stream-prefix":"ecs-server-node"
              }
            },
            "VolumesFrom" : [
              {
                 "SourceContainer" : "chef-client",
                 "ReadOnly" : false
              }
            ], 
            "MountPoints":[
              {
                "ContainerPath":"/gisdata",
                "SourceVolume":"gisdata-vol"
              },
              {
                "ContainerPath":"/tmp/data",
                "SourceVolume":"tmp-vol"
              }
            ],
            "PortMappings":[
              {
                "ContainerPort":6080,
                "HostPort":6080
              },
              {
                "ContainerPort":6443,
                "HostPort":6443
              }
            ]
          },
          {
            "Name":"chef-client",
            "EntryPoint": [
              "/bin/bash", "-c",
              "/usr/bin/tail -f /tmp/chef/zero.rb"
            ],
            "Cpu":"512",
            "Essential":"true",
            "Image":"248675906072.dkr.ecr.us-west-2.amazonaws.com/chef-client:12",
            "Memory":"1000"
          }
        ],
        "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",
                "groupadd ubuntu -g 1000\n",
                "useradd -m -u 1000 -g 1000 ubuntu\n",
                "chown -R 1000:1000 /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://arcgisstore1051.s3.amazonaws.com/7333/cookbooks/arcgis-3.1.0-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" ] } ] ] }
    }
  }
}