{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description": "Deis on EC2: http://deis.io/",
  "Parameters" : {
    "KeyPair" : {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the Deis hosts",
      "Type" : "String",
      "MinLength": "1",
      "MaxLength": "64",
      "AllowedPattern" : "[-_ a-zA-Z0-9]*",
      "ConstraintDescription" : "can contain only alphanumeric characters, spaces, dashes and underscores."
    },
    "ClusterSize": {
      "Default": "3",
      "MinValue": "3",
      "MaxValue": "12",
      "Description": "Number of nodes in cluster (3-12).",
      "Type": "Number"
    },
    "IamInstanceProfile" : {
      "Description" : "(Optional) Set IAM instance profile for Deis hosts (default: none)",
      "Type" : "String",
      "Default": ""
    },
    "SSHFrom" : {
      "Description" : "Lockdown SSH access to the Deis hosts (default: can be accessed from anywhere)",
      "Type" : "String",
      "MinLength": "9",
      "MaxLength": "18",
      "Default" : "0.0.0.0/0",
      "AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
      "ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x."
    },
    "InstanceType" : {
      "Description" : "EC2 instance type (see http://aws.amazon.com/ec2/instance-types/)",
      "Type" : "String",
      "Default" : "m3.large",
      "AllowedValues" : [
        "m3.medium",
        "m3.large",
        "m3.xlarge",
        "m3.2xlarge",
        "m1.medium",
        "m1.large",
        "m1.xlarge",
        "c3.large",
        "c3.xlarge",
        "c3.2xlarge",
        "c3.4xlarge",
        "c3.8xlarge",
        "c4.large",
        "c4.xlarge",
        "c4.2xlarge",
        "c4.4xlarge",
        "c4.8xlarge",
        "c1.medium",
        "c1.xlarge",
        "cc2.8xlarge",
        "g2.2xlarge",
        "cg1.4xlarge",
        "m2.xlarge",
        "m2.4xlarge",
        "cr1.8xlarge",
        "hi1.4xlarge",
        "hs1.8xlarge",
        "i2.xlarge",
        "i2.2xlarge",
        "i2.4xlarge",
        "i2.8xlarge",
        "r3.large",
        "r3.xlarge",
        "r3.2xlarge",
        "r3.4xlarge",
        "r3.8xlarge",
        "t2.medium"
      ],
      "ConstraintDescription" : "must be a valid EC2 instance type."
    },
    "EC2VirtualizationType" : {
      "Description" : "EC2 AMI virtualization type (see http://aws.amazon.com/amazon-linux-ami/instance-type-matrix/)",
      "Type": "String",
      "Default": "PV",
      "AllowedValues" : [ "PV", "HVM" ],
      "ConstraintDescription" : "must be either PV or HVM"
    },
    "EC2EBSVolumeType" : {
      "Description" : "EC2 EBS VolumeType",
      "Type": "String",
      "Default": "gp2",
      "AllowedValues" : [ "gp2", "standard" ],
      "ConstraintDescription" : "must be either 'gp2' for SSD or 'standard' for magnetic (provisioned iOPS requires further manual changes)"
    },
    "AssociatePublicIP": {
      "Description": "Whether to associate a public IP address to the instances",
      "Type": "String",
      "Default": "true",
      "AllowedValues" : [ "true", "false" ],
      "ConstraintDescription" : "must be either true or false"
    },
    "ELBScheme": {
      "Description": "Whether to create an internal-only load balancer, or a public-facing one (default)",
      "Type": "String",
      "Default": "internet-facing",
      "AllowedValues" : [ "internet-facing", "internal" ],
      "ConstraintDescription" : "must be either 'internet-facing' for public use, or 'internal' for private use"
    }
  },

  "Mappings" : {
    "CoreOSAMIs" : {
      "eu-central-1"   : { "PV" : "ami-8c003c91", "HVM" : "ami-92003c8f" },
      "ap-northeast-1" : { "PV" : "ami-9eb9439e", "HVM" : "ami-9cb9439c" },
      "sa-east-1"      : { "PV" : "ami-9be66386", "HVM" : "ami-99e66384" },
      "ap-southeast-2" : { "PV" : "ami-d53845ef", "HVM" : "ami-cb3845f1" },
      "ap-southeast-1" : { "PV" : "ami-a2cefcf0", "HVM" : "ami-a0cefcf2" },
      "us-east-1"      : { "PV" : "ami-d6033bbe", "HVM" : "ami-d2033bba" },
      "us-west-2"      : { "PV" : "ami-39280209", "HVM" : "ami-37280207" },
      "us-west-1"      : { "PV" : "ami-4df91b09", "HVM" : "ami-43f91b07" },
      "eu-west-1"      : { "PV" : "ami-2f422358", "HVM" : "ami-21422356" }

    },
    "RootDevices" : {
      "HVM" : { "Name": "/dev/xvda" },
      "PV"  : { "Name": "/dev/sda" }
    },
    "SubnetConfig" : {
      "VPC"     : { "CIDR" : "10.21.0.0/16" },
      "Subnet1" : { "CIDR" : "10.21.1.0/24" },
      "Subnet2" : { "CIDR" : "10.21.2.0/24" }
    }
  },

  "Conditions" : {
    "UseIamInstanceProfile" : {
      "Fn::Not" : [{
        "Fn::Equals" : [
          { "Ref" : "IamInstanceProfile" },
           ""
        ]
      }]
    }
  },

  "Resources" : {
    "VPC" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "EnableDnsSupport" : "true",
        "EnableDnsHostnames" : "true",
        "CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]},
        "Tags" : [
          { "Key" : "Application", "Value" : "Deis" }
        ]
      }
    },
    "Subnet1" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "AvailabilityZone": { "Fn::Select" : [ 0, { "Fn::GetAZs" : "" } ] },
        "CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Subnet1", "CIDR" ]},
        "Tags" : [
          { "Key" : "Application", "Value" : "Deis" },
          { "Key" : "Network", "Value" : "Private" }
        ]
      }
    },
    "Subnet2" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "AvailabilityZone": { "Fn::Select" : [ 1, { "Fn::GetAZs" : "" } ] },
        "CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Subnet2", "CIDR" ]},
        "Tags" : [
          { "Key" : "Application", "Value" : "Deis" },
          { "Key" : "Network", "Value" : "Private" }
        ]
      }
    },
    "InternetGateway" : {
      "Type" : "AWS::EC2::InternetGateway",
      "Properties" : {
        "Tags" : [
          { "Key" : "Application", "Value" : "Deis" },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },
    "GatewayToInternet" : {
       "Type" : "AWS::EC2::VPCGatewayAttachment",
       "Properties" : {
         "VpcId" : { "Ref" : "VPC" },
         "InternetGatewayId" : { "Ref" : "InternetGateway" }
       }
    },
    "PublicRouteTable" : {
      "Type" : "AWS::EC2::RouteTable",
      "DependsOn" : "GatewayToInternet",
      "Properties" : {
        "VpcId" : { "Ref" : "VPC" },
        "Tags" : [
          { "Key" : "Application", "Value" : "Deis" },
          { "Key" : "Network", "Value" : "Public" }
        ]
      }
    },
    "PublicRoute" : {
      "Type" : "AWS::EC2::Route",
      "DependsOn" : "GatewayToInternet",
      "Properties" : {
        "RouteTableId" : { "Ref" : "PublicRouteTable" },
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : { "Ref" : "InternetGateway" }
      }
    },
    "Subnet1RouteTableAssociation" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "SubnetId" : { "Ref" : "Subnet1" },
        "RouteTableId" : { "Ref" : "PublicRouteTable" }
      }
    },
    "Subnet2RouteTableAssociation" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "SubnetId" : { "Ref" : "Subnet2" },
        "RouteTableId" : { "Ref" : "PublicRouteTable" }
      }
    },
    "CoreOSServerAutoScale": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "Properties": {
        "AvailabilityZones": [
          { "Fn::GetAtt" : [ "Subnet1", "AvailabilityZone" ] },
          { "Fn::GetAtt" : [ "Subnet2", "AvailabilityZone" ] }
        ],
        "VPCZoneIdentifier": [
          { "Ref" : "Subnet1" },
          { "Ref" : "Subnet2" }
        ],
        "LaunchConfigurationName": {"Ref": "CoreOSServerLaunchConfig"},
        "MinSize": "3",
        "MaxSize": "12",
        "DesiredCapacity": {"Ref": "ClusterSize"},
        "Tags": [
            {"Key": "Name", "Value": "Deis", "PropagateAtLaunch": true}
        ],
        "LoadBalancerNames": [
          { "Ref": "DeisWebELB" }
        ]
      }
    },
    "CoreOSServerLaunchConfig": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "DependsOn" : "GatewayToInternet",
      "Properties": {
        "ImageId" : { "Fn::FindInMap" : [ "CoreOSAMIs", { "Ref" : "AWS::Region" }, { "Ref" : "EC2VirtualizationType" }]},
        "InstanceType": {"Ref": "InstanceType"},
        "IamInstanceProfile" : {
          "Fn::If" : [
            "UseIamInstanceProfile",
            { "Ref" : "IamInstanceProfile" },
            { "Ref" : "AWS::NoValue" }
          ]
        },
        "KeyName": {"Ref": "KeyPair"},
        "UserData" : { "Fn::Base64": { "Fn::Join": [ "", [ ] ] } },
        "AssociatePublicIpAddress": {"Ref": "AssociatePublicIP"},
        "SecurityGroups": [ { "Fn::GetAtt": ["VPCSecurityGroup", "GroupId"] } ],
        "BlockDeviceMappings" : [
          {
            "DeviceName" : { "Fn::FindInMap": [ "RootDevices", { "Ref": "EC2VirtualizationType" }, "Name" ] },
            "Ebs" : { "VolumeSize" : "50", "VolumeType": { "Ref": "EC2EBSVolumeType" } }
          },
          {
            "DeviceName" : "/dev/xvdf",
            "Ebs" : { "VolumeSize" : "100", "VolumeType": { "Ref": "EC2EBSVolumeType" } }
          }
        ]
      }
    },
    "DeisWebELB": {
      "Type": "AWS::ElasticLoadBalancing::LoadBalancer",
      "DependsOn" : "GatewayToInternet",
      "Properties": {
        "Scheme" : {"Ref": "ELBScheme"},
        "HealthCheck": {
          "HealthyThreshold": "4",
          "Interval": "15",
          "Target": "TCP:80",
          "Timeout": "5",
          "UnhealthyThreshold": "2"
        },
        "Subnets": [
          { "Ref" : "Subnet1" },
          { "Ref" : "Subnet2" }
        ],
        "Policies" : [{
           "PolicyName" : "EnableProxyProtocol",
           "PolicyType" : "ProxyProtocolPolicyType",
           "Attributes" : [{
              "Name"  : "ProxyProtocol",
              "Value" : "true"
           }],
           "InstancePorts" : ["80", "443"]
        }],
        "Listeners": [
          {
            "InstancePort": "80",
            "InstanceProtocol": "TCP",
            "LoadBalancerPort": "80",
            "Protocol": "TCP"
          },
          {
            "InstancePort": "443",
            "InstanceProtocol": "TCP",
            "LoadBalancerPort": "443",
            "Protocol": "TCP"
          },
          {
            "InstancePort": "2222",
            "InstanceProtocol": "TCP",
            "LoadBalancerPort": "2222",
            "Protocol": "TCP"
          }
        ],
        "SecurityGroups": [
          {
            "Fn::GetAtt": ["DeisWebELBSecurityGroup", "GroupId"]
          }
        ],
        "ConnectionSettings": {
          "IdleTimeout": 1200
        }
      }
    },
    "DeisWebELBSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Deis Web ELB SecurityGroup",
        "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"},
          {"IpProtocol": "tcp", "FromPort": "2222", "ToPort": "2222", "CidrIp": "0.0.0.0/0"}
        ],
        "VpcId": { "Ref" : "VPC" }
      }
    },
    "VPCSecurityGroup" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupDescription" : "Enable public SSH and intra-VPC communication",
        "SecurityGroupIngress" : [
          {"IpProtocol": "tcp", "FromPort" : "22",  "ToPort" : "22",  "CidrIp" : { "Ref" : "SSHFrom" }},
          {"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "SourceSecurityGroupId": { "Ref": "DeisWebELBSecurityGroup" } },
          {"IpProtocol": "tcp", "FromPort": "443", "ToPort": "443", "SourceSecurityGroupId": { "Ref": "DeisWebELBSecurityGroup" } },
          {"IpProtocol": "tcp", "FromPort": "2222", "ToPort": "2222", "SourceSecurityGroupId": { "Ref": "DeisWebELBSecurityGroup" } }
        ],
        "VpcId" : { "Ref" : "VPC" }
      }
    },
    "VPCSecurityGroupIngress": {
      "Type": "AWS::EC2::SecurityGroupIngress",
      "Properties": {
        "GroupId": { "Ref": "VPCSecurityGroup" },
        "IpProtocol": "-1",
        "FromPort": "0",
        "ToPort": "65535",
        "SourceSecurityGroupId": { "Ref": "VPCSecurityGroup" }
      }
    }
  },
  "Outputs" : {
    "DNSName" : {
      "Description" : "DNS Name of the ELB",
      "Value" :  { "Fn::GetAtt" : ["DeisWebELB", "DNSName"] }
    }
  }
}
