{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Highly available configuration of ArcGIS Portal, Server, and DataStore (Windows)",
"Mappings" : {
"RegionMap" : {
"ap-northeast-1": {
"en": "ami-02de84cbdae7334c7"
},
"ap-northeast-2": {
"en": "ami-0bd9b7da24cf1c646"
},
"ap-south-1": {
"en": "ami-0c8f65f087a504e80"
},
"ap-southeast-1": {
"en": "ami-0fad524a2dfa324ea"
},
"ap-southeast-2": {
"en": "ami-0afa8b2d07967a13f"
},
"ca-central-1": {
"en": "ami-0ff8a19084e4d8b52"
},
"eu-central-1": {
"en": "ami-01bb24a57d94cd724"
},
"eu-west-1": {
"en": "ami-05321fd947594645a"
},
"eu-west-2": {
"en": "ami-07303a9067e64dcc3"
},
"sa-east-1": {
"en": "ami-01e49dadb5332903e"
},
"us-east-1": {
"en": "ami-0065f8d2ca53a067c"
},
"us-east-2": {
"en": "ami-0ac4bb96c160fc6db"
},
"us-west-1": {
"en": "ami-0285900137b0e8742"
},
"us-west-2": {
"en": "ami-0a16651b975b8dab3"
}
}
},
"Parameters" : {
"DeploymentBucket" : {
"Description" : "S3 bucket with authorization files and SSL certificates",
"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."
},
"DriveSizeRoot" : {
"Default" : "100",
"Description" : "The size of the C: Drive in GB.",
"Type" : "Number",
"MinValue" : "100",
"MaxValue" : "1024",
"ConstraintDescription" : "Must be between 100 and 1024 GB."
},
"DriveSizeData" : {
"Default" : "100",
"Description" : "The size of the D: Drive in GB.",
"Type" : "Number",
"MinValue" : "10",
"MaxValue" : "1024",
"ConstraintDescription" : "Must be between 10 and 1024 GB."
},
"FSInstanceType": {
"Description": "The file server EC2 instance type",
"Type": "String",
"AllowedValues": [
"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",
"t2.large", "t2.xlarge", "t2.2xlarge"
],
"Default": "m4.large"
},
"ASInstanceType": {
"Description": "The Web GIS EC2 instance type",
"Type": "String",
"AllowedValues": [
"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",
"t2.large", "t2.xlarge", "t2.2xlarge"
],
"Default": "m4.large"
},
"BDSInstanceType": {
"Description": "Spatio-temporal Big Data Store EC2 instance type",
"Type": "String",
"AllowedValues": [
"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"
],
"Default": "m4.large"
},
"BDSInstances" : {
"Description" : "Number of spatio-temporal Big Data Store EC2 instances",
"Type" : "Number",
"Default" : "0",
"AllowedValues" : [0, 1]
},
"KeyName" : {
"Description" : "EC2 Key Pair to allow RemoteDesktop access to the instances",
"Type" : "AWS::EC2::KeyPair::KeyName"
},
"StoreType": {
"Description": "ArcGIS Server config store type",
"Type": "String",
"AllowedValues": ["CloudStore", "FileSystem"],
"Default": "FileSystem"
},
"ServerLicenseFile": {
"Description": "ArcGIS for 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."
},
"PortalLicenseFile": {
"Description": "Portal for ArcGIS 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 administrator 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 ArcGIS Server site admin and Portal initial admin accounts",
"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 (.)."
},
"RunAsUserPassword" : {
"Description" : "Password for ArcGIS account",
"Type" : "String",
"NoEcho" : "true",
"AllowedPattern": "(?!.*arcgis)(?!.*Arc)(?!.*GIS)(?!.*user)(?!.*account)(?=[^\\\\\\\"]{8,})(?=.*?[^\\w\\s])(?=.*?[0-9])(?=.*?[A-Z]).*?[a-z].*",
"ConstraintDescription": "Password must be at least eight characters in length and must contain characters from three of the following four categories: English uppercase characters (A through Z), English lowercase characters (a through z), digits (0 through 9), non-alphabetic characters (for example, !, $, #, %). Password must not contain backslashes (\\) or quotation marks (\"). Password must not contain the user's account name (arcgis) or parts of the user's full name (ArcGIS user account) that exceed two consecutive characters."
},
"SiteDomain": {
"Description": "The domain name of your ArcGIS site",
"Type": "String",
"AllowedPattern": "[^\\\"]{1,253}",
"ConstraintDescription": "The domain name is invalid."
},
"SSLCertificateFile": {
"Description": "SSL certificate file issued to the site domain (must be uploaded to DeploymentBucket)",
"Type": "String",
"AllowedPattern": "[^\\\"]{1,1024}",
"ConstraintDescription": "S3 object key name must be between 1 and 1024 characters."
},
"SSLCertPassword": {
"Description": "SSL certificate file password",
"Type": "String",
"NoEcho": "true",
"AllowedPattern": "[^\\\"]{1,128}",
"ConstraintDescription": "Password must be between 1 and 128 characters and must not contain backslashes (\\) or quotation marks (\")."
},
"VPCId" : {
"Description" : "VPC ID",
"Type" : "AWS::EC2::VPC::Id"
},
"Subnet1" : {
"Description" : "VPC Subnet 1 ID",
"Type": "AWS::EC2::Subnet::Id"
},
"Subnet2" : {
"Description" : "VPC Subnet 2 ID",
"Type": "AWS::EC2::Subnet::Id"
},
"PostInstallationScript": {
"Description": "ZIP archive file with custom post installation script (must be uploaded to DeploymentBucket).",
"Type": "String",
"AllowedPattern": "[^\"]{1,1024}",
"ConstraintDescription": "S3 object key name must be between 1 and 1024 characters.",
"Default": "none"
}
},
"Metadata" : {
"AWS::CloudFormation::Interface" : {
"ParameterGroups" : [ {
"Label" : { "default" : "Network Configuration" },
"Parameters" : [ "VPCId", "Subnet1", "Subnet2", "SiteDomain" ]
},
{
"Label" : { "default":"Amazon EC2 Configuration" },
"Parameters" : [ "FSInstanceType", "ASInstanceType", "BDSInstanceType", "BDSInstances", "DriveSizeRoot", "DriveSizeData", "KeyName" ]
},
{
"Label" : { "default":"ArcGIS Enterprise Configuration" },
"Parameters" : [ "DeploymentBucket", "ServerLicenseFile", "PortalLicenseFile", "StoreType", "SiteAdmin", "SiteAdminPassword", "RunAsUserPassword", "SSLCertificateFile", "SSLCertPassword" ]
} ]
}
},
"Conditions" : {
"UseCloudStore" : {"Fn::Equals" : [{"Ref" : "StoreType"}, "CloudStore"]},
"RunPostInstall" : {"Fn::Not" : [{"Fn::Equals" : [{"Ref" : "PostInstallationScript"}, "none"]}]},
"SSMSupported" : {"Fn::Not" : [{"Fn::Or": [{"Fn::Equals" : [{"Ref" : "AWS::Region"}, "eu-west-2"]},
{"Fn::Equals" : [{"Ref" : "AWS::Region"}, "ap-south-1"]},
{"Fn::Equals" : [{"Ref" : "AWS::Region"}, "ca-central-1"]}]}]}
},
"Resources" : {
"ValidateParametersFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"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"] }
}
},
"StopStackFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"Properties": {
"Code": {
"S3Bucket": {"Fn::Join" : ["", ["arcgisstore1051", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "7333/lambda/arcgis-cfn-lambda-python3.zip"
},
"Environment" : {
"Variables" : {
"StackName" : {"Ref" : "AWS::StackName"}
}
},
"Handler": "stop_start.stop_webgis_ha_stack",
"Runtime": "python3.8",
"Timeout": "300",
"Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
"Description" : "Stops all EC2 instances of the CloudFormation stack"
}
},
"StartStackFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"Properties": {
"Code": {
"S3Bucket": {"Fn::Join" : ["", ["arcgisstore1051", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "7333/lambda/arcgis-cfn-lambda-python3.zip"
},
"Environment" : {
"Variables" : {
"StackName" : {"Ref" : "AWS::StackName"}
}
},
"Handler": "stop_start.start_webgis_ha_stack",
"Runtime": "python3.8",
"Timeout": "300",
"Role": {"Fn::GetAtt" : ["LambdaExecutionRole", "Arn"]},
"Description" : "Starts all EC2 instances of the CloudFormation stack"
}
},
"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": "*"
},
{
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["cloudformation:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["autoscaling:*"],
"Resource": "*"
}]
}
}]
}
},
"ValidateServerLicenseFile": {
"Type": "Custom::ValidateParameters",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "ServerLicenseFile"}
}
},
"ValidatePortalLicenseFile": {
"Type": "Custom::ValidateParameters",
"DependsOn": "ValidateServerLicenseFile",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "PortalLicenseFile"}
}
},
"ValidateSSLCertificateFile": {
"Type": "Custom::ValidateParameters",
"DependsOn": "ValidatePortalLicenseFile",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "SSLCertificateFile"}
}
},
"ValidatePostInstallationScript": {
"Type": "Custom::ValidateParameters",
"Condition": "RunPostInstall",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ValidateParametersFunction", "Arn"]},
"DeploymentBucket": {"Ref": "DeploymentBucket"},
"S3Key": {"Ref": "PostInstallationScript"}
}
},
"ServerConfigStoreFunction": {
"Type": "AWS::Lambda::Function",
"DependsOn": "IAMRole",
"Properties": {
"Code": {
"S3Bucket": {"Fn::Join" : ["", ["arcgisstore1051", "-", {"Ref": "AWS::Region"}]]},
"S3Key": "7333/lambda/arcgis-cfn-lambda-python3.zip"
},
"Handler": "server_config_store.handler",
"Runtime": "python3.8",
"Timeout": "30",
"Role": { "Fn::GetAtt" : ["LambdaExecutionRole", "Arn"] }
}
},
"ServerConfigStore": {
"Type": "Custom::ServerConfigStore",
"Properties": {
"ServiceToken": {"Fn::GetAtt": ["ServerConfigStoreFunction", "Arn"]},
"Namespace": {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}]]}
}
},
"DeploymentLogs": {
"Type": "AWS::Logs::LogGroup",
"DependsOn": "ValidateSSLCertificateFile",
"Properties": {
"RetentionInDays": 7
}
},
"ELB" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"Subnets" : [ {"Ref" : "Subnet1"}, {"Ref" : "Subnet2"} ],
"SecurityGroups" : [ {"Ref": "SecurityGroup"} ],
"Scheme" : "internet-facing",
"Listeners" : [ {
"LoadBalancerPort" : "80",
"InstancePort" : "80",
"Protocol" : "HTTP"
}, {
"LoadBalancerPort" : "443",
"InstancePort" : "443",
"Protocol" : "TCP",
"InstanceProtocol" : "TCP"
} ],
"HealthCheck" : {
"Target" : "HTTP:80/server/rest/info/healthcheck",
"HealthyThreshold" : "3",
"UnhealthyThreshold" : "5",
"Interval" : "30",
"Timeout" : "5"
},
"Instances" : [{"Ref" : "PrimaryServerEC2Instance"}, {"Ref" : "SecondaryServerEC2Instance"}]
}
},
"IAMRole" : {
"Type" : "AWS::IAM::Role",
"DependsOn": "LambdaExecutionRole",
"Properties" : {
"AssumeRolePolicyDocument" : {
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"Service" : [ "ec2.amazonaws.com" ]
},
"Action" : [ "sts:AssumeRole" ]
} ]
},
"Path" : "/"
}
},
"IAMPolicy" : {
"Type" : "AWS::IAM::Policy",
"Properties" : {
"PolicyName" : "IAMRole",
"PolicyDocument" : {
"Statement" : [ {
"Action" : [ "s3:*", "dynamodb:*", "cloudformation:*", "logs:*", "ssm:*", "ec2messages:*" ],
"Effect" : "Allow",
"Resource" : "*"
} ]
},
"Roles" : [ {
"Ref" : "IAMRole"
} ]
}
},
"IAMInstanceProfile" : {
"Type" : "AWS::IAM::InstanceProfile",
"Properties" : {
"Path" : "/",
"Roles" : [ {
"Ref" : "IAMRole"
} ]
}
},
"SecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : {"Ref" : "AWS::StackName"},
"VpcId" : {"Ref" : "VPCId"},
"SecurityGroupIngress" : [ {
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"
}, {
"IpProtocol" : "tcp",
"FromPort" : "443",
"ToPort" : "443",
"CidrIp" : "0.0.0.0/0"
} ]
}
},
"SecurityGroupIngress" : {
"Type" : "AWS::EC2::SecurityGroupIngress",
"Properties" : {
"GroupId" : {"Ref" : "SecurityGroup"},
"IpProtocol" : "tcp",
"FromPort" : "0",
"ToPort" : "65535",
"SourceSecurityGroupId" : {"Ref" : "SecurityGroup"}
}
},
"PortalContent": {
"Type": "AWS::S3::Bucket",
"Condition" : "UseCloudStore",
"DeletionPolicy": "Retain",
"Properties": {
"Tags": [ {
"Key": "Name",
"Value": {"Ref": "AWS::StackName"}
}, {
"Key": "Application",
"Value": "arcgis-allinone-windows"
}]
}
},
"FileServerEC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
"InstanceType" : {"Ref":"FSInstanceType"},
"KeyName" : {"Ref":"KeyName"},
"IamInstanceProfile" : {"Ref":"IAMInstanceProfile"},
"Monitoring" : true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
},
{"DeviceName": "xvdca", "NoDevice": {}}, {"DeviceName": "xvdcb", "NoDevice": {}},
{"DeviceName": "xvdcc", "NoDevice": {}}, {"DeviceName": "xvdcd", "NoDevice": {}},
{"DeviceName": "xvdce", "NoDevice": {}}, {"DeviceName": "xvdcf", "NoDevice": {}},
{"DeviceName": "xvdcg", "NoDevice": {}}, {"DeviceName": "xvdch", "NoDevice": {}},
{"DeviceName": "xvdci", "NoDevice": {}}, {"DeviceName": "xvdcj", "NoDevice": {}},
{"DeviceName": "xvdck", "NoDevice": {}}, {"DeviceName": "xvdcl", "NoDevice": {}},
{"DeviceName": "xvdcm", "NoDevice": {}}, {"DeviceName": "xvdcn", "NoDevice": {}},
{"DeviceName": "xvdco", "NoDevice": {}}, {"DeviceName": "xvdcp", "NoDevice": {}},
{"DeviceName": "xvdcq", "NoDevice": {}}, {"DeviceName": "xvdcr", "NoDevice": {}},
{"DeviceName": "xvdcs", "NoDevice": {}}, {"DeviceName": "xvdct", "NoDevice": {}},
{"DeviceName": "xvdcu", "NoDevice": {}}, {"DeviceName": "xvdcv", "NoDevice": {}},
{"DeviceName": "xvdcw", "NoDevice": {}}, {"DeviceName": "xvdcx", "NoDevice": {}},
{"DeviceName": "xvdcy", "NoDevice": {}}, {"DeviceName": "xvdcz", "NoDevice": {}}],
"Tags" : [{
"Key" : "Name",
"Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-fileserver"]]}
}],
"NetworkInterfaces" : [{
"GroupSet" : [{"Ref": "SecurityGroup"}],
"AssociatePublicIpAddress" : "true",
"DeviceIndex" : "0",
"DeleteOnTermination" : "true",
"SubnetId" : {"Ref" : "Subnet1"}}],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"",
[
"\r\n",
"try \r\n",
"{ \r\n",
" $stackName = '", {"Ref": "AWS::StackName"}, "' \r\n",
" $region = '", {"Ref": "AWS::Region"}, "' \r\n",
" $waitHandle = '", {"Ref": "FileServerWaitHandle"}, "' \r\n",
" $InstanceName = 'FileServerEC2Instance' \r\n",
" $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
" $ChefLogFile = 'C:\\\\chef\\\\chef-run.log' \r\n",
" $execName = \"cfn-init\" \r\n",
" $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process chef-solo -PassThru -Wait -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
"} \r\n",
"catch \r\n",
"{ \r\n",
" Write-Output \"ERROR: $($_.Exception.Message)\" \r\n",
" cfn-signal -e 1 -r \"$($_.Exception.Message)\" \"$WaitHandle\" \r\n",
"} \r\n",
"\r\n"
]
]
}
}
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"buckets" : [ {"Ref" : "DeploymentBucket"} ],
"roleName" : {"Ref" : "IAMRole" }
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"C:\\chef\\node.json" : {
"content" : {
"Fn::Join" : ["", [
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"fileserver\" : {\r\n",
" \"shares\" : []\r\n",
" },\r\n",
" \"server\" : {\r\n",
" \"local_directories_root\" : \"D:\\\\arcgisserver\"\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"local_backup_dir\" : \"D:\\\\data\\\\arcgisdatastore\\\\backup\"\r\n",
" },\r\n",
" \"portal\" : {\r\n",
" \"local_content_dir\" : \"D:\\\\data\\\\arcgisportal\\\\content\"\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\n",
" \"recipe[arcgis-enterprise::system]\",\r\n",
" \"recipe[arcgis-enterprise::fileserver]\"]\r\n",
"}\r\n"]]
}
}
}
}
}
}
},
"FileServerRecoveryAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmDescription" : "Trigger a recovery when instance status check fails for 5 consecutive minutes.",
"MetricName" : "StatusCheckFailed_System",
"Namespace" : "AWS/EC2",
"Statistic" : "Minimum",
"Period" : "60",
"EvaluationPeriods" : "5",
"Threshold" : "0",
"ComparisonOperator" : "GreaterThanThreshold",
"AlarmActions" : [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
"Dimensions" : [ {
"Name" : "InstanceId",
"Value" : {"Ref" : "FileServerEC2Instance"}
} ]
}
},
"FileServerWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
},
"FileServerWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Count" : "1",
"Handle" : {"Ref" : "FileServerWaitHandle"},
"Timeout" : "7200"
}
},
"PrimaryServerEC2Instance" : {
"Type" : "AWS::EC2::Instance",
"DependsOn" : "FileServerWaitCondition",
"Properties" : {
"ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
"InstanceType" : {"Ref":"ASInstanceType"},
"KeyName" : {"Ref":"KeyName"},
"IamInstanceProfile" : {"Ref":"IAMInstanceProfile"},
"Monitoring" : true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
},
{"DeviceName": "xvdca", "NoDevice": {}}, {"DeviceName": "xvdcb", "NoDevice": {}},
{"DeviceName": "xvdcc", "NoDevice": {}}, {"DeviceName": "xvdcd", "NoDevice": {}},
{"DeviceName": "xvdce", "NoDevice": {}}, {"DeviceName": "xvdcf", "NoDevice": {}},
{"DeviceName": "xvdcg", "NoDevice": {}}, {"DeviceName": "xvdch", "NoDevice": {}},
{"DeviceName": "xvdci", "NoDevice": {}}, {"DeviceName": "xvdcj", "NoDevice": {}},
{"DeviceName": "xvdck", "NoDevice": {}}, {"DeviceName": "xvdcl", "NoDevice": {}},
{"DeviceName": "xvdcm", "NoDevice": {}}, {"DeviceName": "xvdcn", "NoDevice": {}},
{"DeviceName": "xvdco", "NoDevice": {}}, {"DeviceName": "xvdcp", "NoDevice": {}},
{"DeviceName": "xvdcq", "NoDevice": {}}, {"DeviceName": "xvdcr", "NoDevice": {}},
{"DeviceName": "xvdcs", "NoDevice": {}}, {"DeviceName": "xvdct", "NoDevice": {}},
{"DeviceName": "xvdcu", "NoDevice": {}}, {"DeviceName": "xvdcv", "NoDevice": {}},
{"DeviceName": "xvdcw", "NoDevice": {}}, {"DeviceName": "xvdcx", "NoDevice": {}},
{"DeviceName": "xvdcy", "NoDevice": {}}, {"DeviceName": "xvdcz", "NoDevice": {}}],
"Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-primary"]]}}],
"NetworkInterfaces" : [{
"GroupSet" : [{"Ref": "SecurityGroup"}],
"AssociatePublicIpAddress" : "true",
"DeviceIndex" : "0",
"DeleteOnTermination" : "true",
"SubnetId" : {"Ref" : "Subnet1"}}],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"",
[
"\r\n",
"try \r\n",
"{ \r\n",
" if (", {"Fn::If": ["RunPostInstall", "$true", "$false"]}, ") {\r\n",
" cfn-init -v -c post-install-script -s ", {"Ref": "AWS::StackName"}, " -r CloudWatchSettings", " --region ", {"Ref": "AWS::Region"}, "\r\n",
" }\r\n",
" $stackName = '", {"Ref": "AWS::StackName"}, "' \r\n",
" $region = '", {"Ref": "AWS::Region"}, "' \r\n",
" $waitHandle = '", {"Ref": "PrimaryServerWaitHandle"}, "' \r\n",
" $InstanceName = 'PrimaryServerEC2Instance' \r\n",
" $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
" $ChefLogFile = 'C:\\\\chef\\\\chef-run.log' \r\n",
" $execName = \"cfn-init\" \r\n",
" $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process chef-solo -PassThru -Wait -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
"} \r\n",
"catch \r\n",
"{ \r\n",
" Write-Output \"ERROR: $($_.Exception.Message)\" \r\n",
" cfn-signal -e 1 -r \"$($_.Exception.Message)\" \"$WaitHandle\" \r\n",
"} \r\n",
"\r\n"
]
]
}
}
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"buckets" : [ {
"Ref" : "DeploymentBucket"
} ],
"roleName" : {
"Ref" : "IAMRole"
}
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"commands": {
"rename-server-license" : {
"command": {"Fn::Join": ["", ["move C:\\Temp\\server_license.tmp C:\\Temp\\", {"Ref": "ServerLicenseFile"}]]}
},
"rename-portal-license" : {
"command": {"Fn::Join": ["", ["move C:\\Temp\\portal_license.tmp C:\\Temp\\", {"Ref": "PortalLicenseFile"}]]}
}
},
"files" : {
"C:\\Temp\\server_license.tmp": {
"source": {"Fn::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\portal_license.tmp": {
"source": {"Fn::GetAtt": [ "ValidatePortalLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\keystore.pfx": {
"source": {"Fn::GetAtt": [ "ValidateSSLCertificateFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\chef\\node.json" : {
"content" : {
"Fn::Join" : ["", [
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"post_install_script\" : \"D:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
" \"hosts\" : {\r\n",
" \"", {"Ref": "SiteDomain"}, "\" : \"\",\r\n",
" \"FILESERVER\" : \"", {"Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ]}, "\"\r\n",
" },\r\n",
" \"iis\" : {\r\n",
" \"keystore_file\" : \"C:\\\\Temp\\\\keystore.pfx\",\r\n",
" \"keystore_password\" : \"", {"Ref": "SSLCertPassword"}, "\",\r\n",
" \"replace_https_binding\" : true\r\n",
" },\r\n",
" \"server\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "ServerLicenseFile"}, "\",\r\n",
" \"directories_root\" : \"\\\\\\\\FILESERVER\",\r\n",
" \"log_dir\" : \"D:\\\\arcgisserver\\\\logs\",\r\n",
" \"config_store_type\" : \"", {"Fn::If": ["UseCloudStore", "AMAZON", "FILESYSTEM"]}, "\",\r\n",
" \"config_store_connection_string\" : \"", {"Fn::If": ["UseCloudStore",
{"Fn::Join" : ["", ["NAMESPACE=", {"Ref" : "AWS::StackName"}, ";REGION=", { "Ref" : "AWS::Region" } ]]},
"\\\\\\\\FILESERVER\\\\config-store"]}, "\"\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"preferredidentifier\" : \"ip\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisdatastore\",\r\n",
" \"backup_dir\" : \"\\\\\\\\FILESERVER\\\\data\\\\arcgisdatastore\\\\backup\"\r\n",
" },\r\n",
" \"portal\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"private_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"web_context_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"admin_username\" : \"", {"Ref": "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref": "SiteAdminPassword"}, "\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisportal\",\r\n",
" \"content_store_type\" : \"", {"Fn::If": ["UseCloudStore", "cloudStore", "fileStore"]}, "\",\r\n",
" \"content_store_provider\" : \"", {"Fn::If": ["UseCloudStore", "Amazon", "FileSystem"]}, "\",\r\n",
" \"content_store_connection_string\" : ", {"Fn::If": ["UseCloudStore",
{"Fn::Join" : ["", ["{\"region\": \"", {"Ref" : "AWS::Region"}, "\", \"credentialType\": \"IAMRole\"}"]]},
"\"\\\\\\\\FILESERVER\\\\data\\\\arcgisportal\\\\content\""]}, ",\r\n",
" \"object_store\" : \"", {"Fn::If": ["UseCloudStore", {"Ref": "PortalContent"}, ""]}, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "PortalLicenseFile"}, "\"\r\n",
" },\r\n",
" \"web_adaptor\" : {\r\n",
" \"admin_access\" : true\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\r\n",
" \"recipe[arcgis-enterprise::system]\",\r\n",
" \"recipe[esri-iis]\",\r\n",
" \"recipe[arcgis-enterprise::server]\",\r\n",
" \"recipe[arcgis-enterprise::server_wa]\",\r\n",
" \"recipe[arcgis-enterprise::datastore]\",\r\n",
" \"recipe[arcgis-enterprise::portal]\",\r\n",
" \"recipe[arcgis-enterprise::portal_wa]\",\r\n",
" \"recipe[arcgis-enterprise::post_install]\"]\r\n",
"}\r\n"]]
}
}
}
}
}
}
},
"PrimaryServerRecoveryAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmDescription" : "Trigger a recovery when instance status check fails for 5 consecutive minutes.",
"MetricName" : "StatusCheckFailed_System",
"Namespace" : "AWS/EC2",
"Statistic" : "Minimum",
"Period" : "60",
"EvaluationPeriods" : "5",
"Threshold" : "0",
"ComparisonOperator" : "GreaterThanThreshold",
"AlarmActions" : [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
"Dimensions" : [ {
"Name" : "InstanceId",
"Value" : {"Ref" : "PrimaryServerEC2Instance"}
} ]
}
},
"PrimaryServerWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
},
"PrimaryServerWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Count" : "1",
"Handle" : {"Ref" : "PrimaryServerWaitHandle"},
"Timeout" : "7200"
}
},
"SecondaryServerEC2Instance" : {
"Type" : "AWS::EC2::Instance",
"DependsOn" : "PrimaryServerWaitCondition",
"Properties" : {
"ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
"InstanceType" : {"Ref":"ASInstanceType"},
"KeyName" : {"Ref":"KeyName"},
"IamInstanceProfile" : {"Ref":"IAMInstanceProfile"},
"Monitoring" : true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
},
{"DeviceName": "xvdca", "NoDevice": {}}, {"DeviceName": "xvdcb", "NoDevice": {}},
{"DeviceName": "xvdcc", "NoDevice": {}}, {"DeviceName": "xvdcd", "NoDevice": {}},
{"DeviceName": "xvdce", "NoDevice": {}}, {"DeviceName": "xvdcf", "NoDevice": {}},
{"DeviceName": "xvdcg", "NoDevice": {}}, {"DeviceName": "xvdch", "NoDevice": {}},
{"DeviceName": "xvdci", "NoDevice": {}}, {"DeviceName": "xvdcj", "NoDevice": {}},
{"DeviceName": "xvdck", "NoDevice": {}}, {"DeviceName": "xvdcl", "NoDevice": {}},
{"DeviceName": "xvdcm", "NoDevice": {}}, {"DeviceName": "xvdcn", "NoDevice": {}},
{"DeviceName": "xvdco", "NoDevice": {}}, {"DeviceName": "xvdcp", "NoDevice": {}},
{"DeviceName": "xvdcq", "NoDevice": {}}, {"DeviceName": "xvdcr", "NoDevice": {}},
{"DeviceName": "xvdcs", "NoDevice": {}}, {"DeviceName": "xvdct", "NoDevice": {}},
{"DeviceName": "xvdcu", "NoDevice": {}}, {"DeviceName": "xvdcv", "NoDevice": {}},
{"DeviceName": "xvdcw", "NoDevice": {}}, {"DeviceName": "xvdcx", "NoDevice": {}},
{"DeviceName": "xvdcy", "NoDevice": {}}, {"DeviceName": "xvdcz", "NoDevice": {}}],
"Tags" : [{"Key" : "Name", "Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-secondary"]]}}],
"NetworkInterfaces" : [{
"GroupSet" : [{"Ref": "SecurityGroup"}],
"AssociatePublicIpAddress" : "true",
"DeviceIndex" : "0",
"DeleteOnTermination" : "true",
"SubnetId" : {"Ref" : "Subnet2"}}],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"",
[
"\r\n",
"try \r\n",
"{ \r\n",
" if (", {"Fn::If": ["RunPostInstall", "$true", "$false"]}, ") {\r\n",
" cfn-init -v -c post-install-script -s ", {"Ref": "AWS::StackName"}, " -r CloudWatchSettings", " --region ", {"Ref": "AWS::Region"}, "\r\n",
" }\r\n",
" $stackName = '", {"Ref": "AWS::StackName"}, "' \r\n",
" $region = '", {"Ref": "AWS::Region"}, "' \r\n",
" $waitHandle = '", {"Ref": "SecondaryServerWaitHandle"}, "' \r\n",
" $InstanceName = 'SecondaryServerEC2Instance' \r\n",
" $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
" $ChefLogFile = 'C:\\\\chef\\\\chef-run.log' \r\n",
" $execName = \"cfn-init\" \r\n",
" $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process chef-solo -PassThru -Wait -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
"} \r\n",
"catch \r\n",
"{ \r\n",
" Write-Output \"ERROR: $($_.Exception.Message)\" \r\n",
" cfn-signal -e 1 -r \"$($_.Exception.Message)\" \"$WaitHandle\" \r\n",
"} \r\n",
"\r\n"
]
]
}
}
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"buckets" : [ {
"Ref" : "DeploymentBucket"
} ],
"roleName" : {
"Ref" : "IAMRole"
}
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"commands": {
"rename-server-license" : {
"command": {"Fn::Join": ["", ["move C:\\Temp\\server_license.tmp C:\\Temp\\", {"Ref": "ServerLicenseFile"}]]}
},
"rename-portal-license" : {
"command": {"Fn::Join": ["", ["move C:\\Temp\\portal_license.tmp C:\\Temp\\", {"Ref": "PortalLicenseFile"}]]}
}
},
"files" : {
"C:\\Temp\\server_license.tmp": {
"source": {"Fn::GetAtt": [ "ValidateServerLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\portal_license.tmp": {
"source": {"Fn::GetAtt": [ "ValidatePortalLicenseFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\Temp\\keystore.pfx": {
"source": {"Fn::GetAtt": [ "ValidateSSLCertificateFile", "S3ObjectURL" ]},
"authentication": "S3AccessCreds"
},
"C:\\chef\\node.json" : {
"content" : {
"Fn::Join" : ["", [
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"post_install_script\" : \"D:\\\\PostInstallScripts\\\\deploy.bat\",\r\n",
" \"hosts\" : {\r\n",
" \"", {"Ref": "SiteDomain"}, "\" : \"\",\r\n",
" \"FILESERVER\" : \"", {"Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ]}, "\"\r\n",
" },\r\n",
" \"iis\" : {\r\n",
" \"keystore_file\" : \"C:\\\\Temp\\\\keystore.pfx\",\r\n",
" \"keystore_password\" : \"", {"Ref": "SSLCertPassword"}, "\",\r\n",
" \"replace_https_binding\" : true\r\n",
" },\r\n",
" \"server\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "ServerLicenseFile"}, "\",\r\n",
" \"private_url\" : \"https://", {"Ref": "SiteDomain"}, "/server\",\r\n",
" \"primary_server_url\" : \"https://", { "Fn::GetAtt" : [ "PrimaryServerEC2Instance", "PrivateIp" ] }, ":6443/arcgis\",\r\n",
" \"use_join_site_tool\" : false,\r\n",
" \"config_store_type\" : \"", {"Fn::If": ["UseCloudStore", "AMAZON", "FILESYSTEM"]}, "\",\r\n",
" \"config_store_connection_string\" : \"", {"Fn::If": ["UseCloudStore",
{"Fn::Join" : ["", ["NAMESPACE=", {"Ref" : "AWS::StackName"}, ";REGION=", { "Ref" : "AWS::Region" } ]]},
"\\\\\\\\FILESERVER\\\\config-store"]}, "\"\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"preferredidentifier\" : \"ip\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisdatastore\",\r\n",
" \"backup_dir\" : \"\\\\\\\\FILESERVER\\\\data\\\\arcgisdatastore\\\\backup\"\r\n",
" },\r\n",
" \"portal\" : {\r\n",
" \"domain_name\" : \"", {"Ref": "SiteDomain"}, "\",\r\n",
" \"primary_machine_url\" : \"https://", { "Fn::GetAtt" : [ "PrimaryServerEC2Instance", "PrivateIp" ] }, ":7443\",\r\n",
" \"private_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"web_context_url\" : \"https://", {"Ref": "SiteDomain"}, "/portal\",\r\n",
" \"admin_username\" : \"", {"Ref": "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref": "SiteAdminPassword"}, "\",\r\n",
" \"authorization_file\" : \"C:\\\\Temp\\\\", {"Ref": "PortalLicenseFile"}, "\"\r\n",
" },\r\n",
" \"web_adaptor\" : {\r\n",
" \"admin_access\" : true\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\n",
" \"recipe[arcgis-enterprise::system]\",\r\n",
" \"recipe[esri-iis]\",\r\n",
" \"recipe[arcgis-enterprise::server_node]\",\r\n",
" \"recipe[arcgis-enterprise::server_wa]\",\r\n",
" \"recipe[arcgis-enterprise::datastore_standby]\",\r\n",
" \"recipe[arcgis-enterprise::portal_standby]\",\r\n",
" \"recipe[arcgis-enterprise::portal_wa]\",\r\n",
" \"recipe[arcgis-enterprise::federation]\",\r\n",
" \"recipe[arcgis-enterprise::post_install]\"]\r\n",
"}\r\n"]]
}
}
}
}
}
}
},
"SecondaryServerRecoveryAlarm" : {
"Type" : "AWS::CloudWatch::Alarm",
"Properties" : {
"AlarmDescription" : "Trigger a recovery when instance status check fails for 5 consecutive minutes.",
"MetricName" : "StatusCheckFailed_System",
"Namespace" : "AWS/EC2",
"Statistic" : "Minimum",
"Period" : "60",
"EvaluationPeriods" : "5",
"Threshold" : "0",
"ComparisonOperator" : "GreaterThanThreshold",
"AlarmActions" : [ {"Fn::Join" : ["", ["arn:aws:automate:", { "Ref" : "AWS::Region" }, ":ec2:recover" ]]} ],
"Dimensions" : [ {
"Name" : "InstanceId",
"Value" : {"Ref" : "SecondaryServerEC2Instance"}
} ]
}
},
"SecondaryServerWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
},
"SecondaryServerWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"Properties" : {
"Count" : "1",
"Handle" : {"Ref" : "SecondaryServerWaitHandle"},
"Timeout" : "10800"
}
},
"LaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"DependsOn" : "SecondaryServerWaitCondition",
"Properties" : {
"AssociatePublicIpAddress" : true,
"ImageId" : {"Fn::FindInMap" : ["RegionMap", {"Ref":"AWS::Region"}, "en"]},
"InstanceType" : {"Ref" : "BDSInstanceType"},
"KeyName" : {"Ref" : "KeyName"},
"IamInstanceProfile" : {"Ref" : "IAMInstanceProfile"},
"SecurityGroups" : [ {"Ref": "SecurityGroup"} ],
"InstanceMonitoring" : true,
"BlockDeviceMappings": [ {
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeRoot"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}, {
"DeviceName": "xvdg",
"Ebs": {
"VolumeSize": {"Ref": "DriveSizeData"},
"DeleteOnTermination": true,
"VolumeType": "gp2"
}
}],
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"",
[
"\r\n",
"try \r\n",
"{ \r\n",
" $stackName = '", {"Ref": "AWS::StackName"}, "' \r\n",
" $region = '", {"Ref": "AWS::Region"}, "' \r\n",
" $waitHandle = '", {"Ref": "AutoScalingGroupWaitHandle"}, "' \r\n",
" $InstanceName = 'LaunchConfig' \r\n",
" $NodeJSONPath = 'C:\\\\chef\\\\node.json' \r\n",
" $ChefLogFile = 'C:\\\\chef\\\\chef-run.log' \r\n",
" $execName = \"cfn-init\" \r\n",
" $execArgs = \"-v -s $stackName -r CloudWatchSettings --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $execArgs = \"-v -s $stackName -r $InstanceName --region $region\" \r\n",
" $process = Start-Process $execName -PassThru -Wait -ArgumentList $execArgs.Split(' ') \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-init' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process chef-solo -PassThru -Wait -ArgumentList (\"-j\", $NodeJSONPath, \"-L\",$ChefLogFile, \"-l\", \"info\") \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Chef run failed. See 'C:\\\\chef\\\\chef-run.log' for details.\" \r\n",
" } \r\n",
" \r\n",
" $process = Start-Process cfn-signal -PassThru -Wait -ArgumentList $waitHandle \r\n",
" if ($process.ExitCode -ne 0) { \r\n",
" throw \"Process 'cfn-signal' exit code : $($process.ExitCode)\" \r\n",
" } \r\n",
"} \r\n",
"catch \r\n",
"{ \r\n",
" Write-Output \"ERROR: $($_.Exception.Message)\" \r\n",
" cfn-signal -e 1 -r \"$($_.Exception.Message)\" \"$WaitHandle\" \r\n",
"} \r\n",
"\r\n"
]
]
}
}
},
"Metadata" : {
"AWS::CloudFormation::Authentication" : {
"S3AccessCreds" : {
"type" : "S3",
"buckets" : [ {"Ref" : "DeploymentBucket"} ],
"roleName" : {"Ref" : "IAMRole"}
}
},
"AWS::CloudFormation::Init" : {
"config" : {
"files" : {
"C:\\chef\\node.json" : {
"content" : {
"Fn::Join" : [ "", [
"{\r\n",
" \"arcgis\" : {\r\n",
" \"run_as_password\" : \"", {"Ref" : "RunAsUserPassword"}, "\",\r\n",
" \"hosts\" : {\r\n",
" \"FILESERVER\" : \"", {"Fn::GetAtt" : [ "FileServerEC2Instance", "PrivateIp" ]}, "\"\r\n",
" },\r\n",
" \"server\" : {\r\n",
" \"admin_username\" : \"", {"Ref" : "SiteAdmin"}, "\",\r\n",
" \"admin_password\" : \"", {"Ref" : "SiteAdminPassword" }, "\",\r\n",
" \"domain_name\" : \"", { "Fn::GetAtt" : [ "PrimaryServerEC2Instance", "PrivateIp" ] }, "\",\r\n",
" \"private_url\" : \"https://", { "Fn::GetAtt" : [ "PrimaryServerEC2Instance", "PrivateIp" ] }, ":6443/arcgis\"\r\n",
" },\r\n",
" \"data_store\" : {\r\n",
" \"types\" : \"spatiotemporal\",\r\n",
" \"preferredidentifier\" : \"ip\",\r\n",
" \"data_dir\" : \"D:\\\\arcgisdatastore\",\r\n",
" \"backup_dir\" : \"\\\\\\\\FILESERVER\\\\data\\\\arcgisdatastore\\\\backup\"\r\n",
" }\r\n",
" },\r\n",
" \"run_list\" : [\r\n",
" \"recipe[arcgis-enterprise::hosts]\",\r\n",
" \"recipe[arcgis-enterprise::datastore]\"]\r\n",
"}\r\n" ] ]
}
}
}
}
}
}
},
"AutoScalingGroup" : {
"Type" : "AWS::AutoScaling::AutoScalingGroup",
"Properties" : {
"VPCZoneIdentifier" : [ {"Ref" : "Subnet1"}, {"Ref" : "Subnet2"} ],
"Cooldown" : "300",
"MaxSize" : {"Ref" : "BDSInstances"},
"MinSize" : {"Ref" : "BDSInstances"},
"LaunchConfigurationName" : {"Ref" : "LaunchConfig"},
"HealthCheckType" : "EC2",
"HealthCheckGracePeriod" : "3600",
"Tags" : [ {
"Key" : "Name",
"Value" : {"Fn::Join" : ["", [{"Ref" : "AWS::StackName"}, "-bds"]]},
"PropagateAtLaunch" : true
} ]
},
"UpdatePolicy": {
"AutoScalingReplacingUpdate": {
"WillReplace": "true"
}
}
},
"AutoScalingGroupWaitHandle" : {
"Type" : "AWS::CloudFormation::WaitConditionHandle",
"Properties" : {}
},
"AutoScalingGroupWaitCondition" : {
"Type" : "AWS::CloudFormation::WaitCondition",
"DependsOn" : "LaunchConfig",
"Properties" : {
"Count" : {"Ref" : "BDSInstances"},
"Handle" : {"Ref" : "AutoScalingGroupWaitHandle"},
"Timeout" : "14400"
}
},
"CloudWatchSettings" : {
"Type" : "AWS::Logs::MetricFilter",
"Properties": {
"LogGroupName": {"Ref": "DeploymentLogs"},
"FilterPattern": "[level=FATAL, message]",
"MetricTransformations": [{
"MetricValue": "1",
"MetricNamespace": "ArcGIS/Deployment",
"MetricName": "ErrorCount"
}]
},
"Metadata" : {
"AWS::CloudFormation::Init" : {
"configSets" : {
"default": ["config"],
"post-install-script": ["post-install-config"]
},
"post-install-config": {
"sources" : {
"D:\\PostInstallScripts" : {"Fn::If": ["RunPostInstall", {"Fn::GetAtt": [ "ValidatePostInstallationScript", "S3ObjectURL" ]}, ""]}
}
},
"config" : {
"sources" : {
"C:\\chef" : "https://arcgisstore1051.s3.amazonaws.com/7333/cookbooks/arcgis-3.1.0-cookbooks.zip",
"C:\\Program Files\\Amazon\\cfn-bootstrap" : "https://arcgisstore1051.s3.amazonaws.com/endpoints.zip"
}
}
}
}
},
"SSMDocument" : {
"Type" : "AWS::SSM::Document",
"Condition" : "SSMSupported",
"Properties" : {
"DocumentType" : "Command",
"Content" : {
"schemaVersion": "2.0",
"description": "CloudWatch Logs tasks",
"mainSteps": [
{
"action" :"aws:cloudWatch",
"name": "cloudWatch",
"settings": {
"startType": "Enabled"
},
"inputs": {
"EngineConfiguration": {
"PollInterval": "00:00:15",
"Components": [ {
"Id": "CfnInitLogStream",
"FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"Region": { "Ref": "AWS::Region" },
"LogGroup": { "Ref": "DeploymentLogs" },
"LogStream": "{instance_id}/cfn-init.log"
}
},
{
"Id": "ChefRunLogStream",
"FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"Region": { "Ref": "AWS::Region" },
"LogGroup": { "Ref": "DeploymentLogs" },
"LogStream": "{instance_id}/chef-run.log"
}
},
{
"Id": "CfnInitLogs",
"FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"LogDirectoryPath": "C:\\cfn\\log",
"TimestampFormat": "yyyy-MM-dd HH:mm:ss,fff",
"Encoding": "UTF-8",
"Filter": "cfn-init.log",
"CultureName": "en-US",
"TimeZoneKind": "Local",
"LineCount": "1"
}
},
{
"Id": "ChefRunLogs",
"FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"LogDirectoryPath": "C:\\chef",
"TimestampFormat": "[yyyy-MM-ddTHH:mm:sszzz]",
"Encoding": "UTF-8",
"Filter": "chef-run.log",
"CultureName": "en-US",
"TimeZoneKind": "Local",
"LineCount": "1"
}
}],
"Flows": {
"Flows":["CfnInitLogs,CfnInitLogStream", "ChefRunLogs,ChefRunLogStream"]
}
}
}
},
{
"action": "aws:runPowerShellScript",
"name": "runPowerShellScript",
"inputs": {
"runCommand": ["Start-Sleep -s 30;echo EOF >> C:\\chef\\chef-run.log; echo EOF >> C:\\cfn\\log\\cfn-init.log"]
}
}]
}
}
},
"SSMAssociation": {
"Type": "AWS::SSM::Association",
"Condition" : "SSMSupported",
"Properties": {
"Name": { "Ref": "SSMDocument" },
"Targets": [{
"Key": "tag:aws:cloudformation:stack-id",
"Values": [{"Ref": "AWS::StackId"}]
}]
}
}
},
"Outputs" : {
"ManagerURL" : {
"Value" : {"Fn::Join" : [ "", [ "https://", {"Ref" : "SiteDomain"}, "/server/manager" ]]},
"Description" : "ArcGIS Server Manager URL"
},
"RestURL" : {
"Value" : {"Fn::Join" : [ "", [ "https://", {"Ref" : "SiteDomain"}, "/server/rest" ]]},
"Description" : "ArcGIS REST Services Directory URL"
},
"PortalURL": {
"Value": {"Fn::Join": ["", ["https://", {"Ref" : "SiteDomain"}, "/portal/home" ]]},
"Description": "Portal for ArcGIS Home URL"
},
"LogsURL" : {
"Value" : {"Fn::Join" : [ "", [ "https://console.aws.amazon.com/cloudwatch/home?region=", {"Ref" : "AWS::Region"}, "#logStream:group=", {"Ref" : "DeploymentLogs"}]]},
"Description" : "Deployment Logs"
},
"DNSName" : {
"Description" : "Elastic load balancer DNS name",
"Value" : {"Fn::GetAtt" : ["ELB", "DNSName"]}
},
"StopStackFunction": {
"Value" : {"Fn::Join": ["", [ "https://console.aws.amazon.com/lambda/home?region=", {"Ref": "AWS::Region"}, "#/functions/", {"Ref": "StopStackFunction"} ] ]},
"Description" : "Lambda function used to stop all EC2 instances in the stack."
},
"StartStackFunction": {
"Value" : {"Fn::Join": ["", [ "https://console.aws.amazon.com/lambda/home?region=", {"Ref": "AWS::Region"}, "#/functions/", {"Ref": "StartStackFunction"} ] ]},
"Description" : "Lambda function used to start all EC2 instances in the stack."
}
}
}