{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Buildkite stack v2.0.2",
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {
            "default": "Buildkite Configuration"
          },
          "Parameters": [
            "BuildkiteAgentRelease",
            "BuildkiteAgentToken",
            "BuildkiteQueue",
            "BuildkiteOrgSlug",
            "BuildkiteApiAccessToken"
          ]
        },
        {
          "Label": {
            "default": "Network Configuration"
          },
          "Parameters": [
            "VpcId",
            "Subnets",
            "AvailabilityZones",
            "SecurityGroupId"
          ]
        },
        {
          "Label": {
            "default": "Instance Configuration"
          },
          "Parameters": [
            "ImageId",
            "InstanceType",
            "AgentsPerInstance",
            "KeyName",
            "SpotPrice",
            "SecretsBucket",
            "ArtifactsBucket",
            "AuthorizedUsersUrl",
            "BootstrapScriptUrl",
            "RootVolumeSize",
            "AssociatePublicIpAddress",
            "ManagedPolicyARN"
          ]
        },
        {
          "Label": {
            "default": "Auto-scaling Configuration"
          },
          "Parameters": [
            "DesiredCapacity",
            "MinSize",
            "MaxSize",
            "ScaleUpAdjustment",
            "ScaleDownAdjustment"
          ]
        },
        {
          "Label": {
            "default": "Docker Registry Configuration"
          },
          "Parameters": [
            "ECRAccessPolicy"
          ]
        }
      ]
    }
  },
  "Parameters": {
    "KeyName": {
      "Description": "SSH keypair used to access the buildkite instances",
      "Type": "AWS::EC2::KeyPair::KeyName",
      "MinLength": 1
    },
    "BuildkiteAgentRelease": {
      "Type": "String",
      "AllowedValues": [
        "stable",
        "beta",
        "edge"
      ],
      "Default": "stable"
    },
    "BuildkiteAgentToken": {
      "Description": "Buildkite agent token",
      "Type": "String",
      "NoEcho": "true",
      "MinLength": 1
    },
    "BuildkiteOrgSlug": {
      "Description": "Buildkite organization slug",
      "Type": "String",
      "MinLength": 1
    },
    "BuildkiteApiAccessToken": {
      "Description": "Buildkite API access token with read_pipelines, read_builds and read_agents (required for metrics)",
      "Type": "String",
      "NoEcho": "true",
      "MinLength": 1
    },
    "BuildkiteQueue": {
      "Description": "Queue name that agents will use, targeted in pipeline steps using \"queue={value}\"",
      "Type": "String",
      "Default": "default",
      "MinLength": 1
    },
    "AgentsPerInstance": {
      "Description": "Number of Buildkite agents to run on each instance",
      "Type": "Number",
      "Default": 1,
      "MinValue": 1
    },
    "SecretsBucket": {
      "Description": "Optional - Name of an existing S3 bucket containing pipeline secrets",
      "Type": "String",
      "Default": ""
    },
    "ArtifactsBucket": {
      "Description": "Optional - Name of an existing S3 bucket for build artifact storage",
      "Type": "String",
      "Default": ""
    },
    "BootstrapScriptUrl": {
      "Description": "Optional - HTTPS or S3 URL to run on each instance during boot",
      "Type": "String",
      "Default": ""
    },
    "AuthorizedUsersUrl": {
      "Description": "Optional - HTTPS or S3 URL to periodically download ssh authorized_keys from",
      "Type": "String",
      "Default": ""
    },
    "VpcId": {
      "Type": "String",
      "Description": "Optional - Id of an existing VPC to launch instances into. Leave blank to have a new VPC created",
      "Default": ""
    },
    "Subnets": {
      "Type": "CommaDelimitedList",
      "Description": "Optional - Comma separated list of two existing VPC subnet ids where EC2 instances will run. Required if setting VpcId.",
      "Default": ""
    },
    "AvailabilityZones": {
      "Type": "CommaDelimitedList",
      "Description": "Optional - Comma separated list of AZs that subnets are created in (if Subnets parameter is not specified)",
      "Default": ""
    },
    "InstanceType": {
      "Description": "Instance type",
      "Type": "String",
      "Default": "t2.nano",
      "MinLength": 1
    },
    "SpotPrice": {
      "Description": "Spot bid price to use for the instances. 0 means normal (non-spot) instances",
      "Type": "String",
      "Default": 0
    },
    "DesiredCapacity": {
      "Description": "Desired number of instances to start with",
      "Type": "Number",
      "Default": 0,
      "MinValue": 0
    },
    "MaxSize": {
      "Description": "Maximum number of instances",
      "Type": "Number",
      "Default": 10,
      "MinValue": 1
    },
    "MinSize": {
      "Description": "Minimum number of instances",
      "Type": "Number",
      "Default": 0
    },
    "ScaleUpAdjustment": {
      "Description": "Number of instances to add on scale up events (ScheduledJobsCount > 0 for 1 min)",
      "Type": "Number",
      "Default": 5,
      "MinValue": 0
    },
    "ScaleDownAdjustment": {
      "Description": "Number of instances to remove on scale down events (UnfinishedJobs == 0 for 30 mins)",
      "Type": "Number",
      "Default": -1,
      "MaxValue": 0
    },
    "RootVolumeSize": {
      "Description": "Size of each instance's root EBS volume (in GB)",
      "Type": "Number",
      "Default": 250,
      "MinValue": 10
    },
    "SecurityGroupId": {
      "Type": "String",
      "Description": "Optional - Security group id to assign to instances",
      "Default": ""
    },
    "ImageId": {
      "Type": "String",
      "Description": "Optional - Custom AMI to use for instances (must be based on the stack's AMI)",
      "Default": ""
    },
    "ManagedPolicyARN": {
      "Type": "String",
      "Description": "Optional - ARN of a managed IAM policy to attach to the instance role",
      "Default": ""
    },
    "ECRAccessPolicy": {
      "Type": "String",
      "Description": "ECR access policy to give container instances",
      "AllowedValues": [
        "none",
        "readonly",
        "poweruser",
        "full"
      ],
      "Default": "none"
    },
    "AssociatePublicIpAddress": {
      "Type": "String",
      "Description": "Associate instances with public IP addresses",
      "AllowedValues": [
        "true",
        "false"
      ],
      "Default": "true"
    }
  },
  "Conditions": {
    "UseSpotInstances": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "SpotPrice"
            },
            0
          ]
        }
      ]
    },
    "CreateVpcResources": {
      "Fn::Equals": [
        {
          "Ref": "VpcId"
        },
        ""
      ]
    },
    "CreateSecurityGroup": {
      "Fn::Equals": [
        {
          "Ref": "SecurityGroupId"
        },
        ""
      ]
    },
    "UseSpecifiedAvailabilityZones": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Fn::Join": [
                "",
                {
                  "Ref": "AvailabilityZones"
                }
              ]
            },
            ""
          ]
        }
      ]
    },
    "UseSecretsBucket": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "SecretsBucket"
            },
            ""
          ]
        }
      ]
    },
    "UseArtifactsBucket": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "ArtifactsBucket"
            },
            ""
          ]
        }
      ]
    },
    "UseDefaultAMI": {
      "Fn::Equals": [
        {
          "Ref": "ImageId"
        },
        ""
      ]
    },
    "UseManagedPolicyARN": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "ManagedPolicyARN"
            },
            ""
          ]
        }
      ]
    },
    "UseECR": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "ECRAccessPolicy"
            },
            "none"
          ]
        }
      ]
    },
    "UseAutoscaling": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            {
              "Ref": "MaxSize"
            },
            {
              "Ref": "MinSize"
            }
          ]
        }
      ]
    },
    "CreateMetricsStack": {
      "Fn::And": [
        {
          "Condition": "UseAutoscaling"
        },
        {
          "Fn::Not": [
            {
              "Fn::Equals": [
                {
                  "Ref": "BuildkiteApiAccessToken"
                },
                ""
              ]
            }
          ]
        }
      ]
    }
  },
  "Mappings": {
    "ECRManagedPolicy": {
      "none": {
        "Policy": ""
      },
      "readonly": {
        "Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
      },
      "poweruser": {
        "Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser"
      },
      "full": {
        "Policy": "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess"
      }
    },
    "MetricsLambdaBucket": {
      "us-east-1": {
        "Bucket": "buildkite-metrics"
      },
      "us-east-2": {
        "Bucket": "buildkite-metrics-us-east-2"
      },
      "us-west-1": {
        "Bucket": "buildkite-metrics-us-west-1"
      },
      "us-west-2": {
        "Bucket": "buildkite-metrics-us-west-2"
      },
      "eu-west-1": {
        "Bucket": "buildkite-metrics-eu-west-1"
      },
      "eu-west-2": {
        "Bucket": "buildkite-metrics-eu-west-2"
      },
      "eu-central-1": {
        "Bucket": "buildkite-metrics-eu-central-1"
      },
      "ap-northeast-1": {
        "Bucket": "buildkite-metrics-ap-northeast-1"
      },
      "ap-northeast-2": {
        "Bucket": "buildkite-metrics-ap-northeast-2"
      },
      "ap-southeast-1": {
        "Bucket": "buildkite-metrics-ap-southeast-1"
      },
      "ap-southeast-2": {
        "Bucket": "buildkite-metrics-ap-southeast-2"
      },
      "ap-south-1": {
        "Bucket": "buildkite-metrics-ap-south-1"
      },
      "sa-east-1": {
        "Bucket": "buildkite-metrics-sa-east-1"
      }
    },
    "AWSRegion2AMI": {
      "us-east-1": {
        "AMI": "ami-a2b039b4"
      },
      "us-east-2": {
        "AMI": "ami-30b19555"
      },
      "us-west-1": {
        "AMI": "ami-25567345"
      },
      "us-west-2": {
        "AMI": "ami-db4dddbb"
      },
      "eu-west-1": {
        "AMI": "ami-716d5717"
      },
      "eu-west-2": {
        "AMI": "ami-20243044"
      },
      "eu-central-1": {
        "AMI": "ami-aa69bac5"
      },
      "ap-northeast-1": {
        "AMI": "ami-8990b3ee"
      },
      "ap-northeast-2": {
        "AMI": "ami-0bc31165"
      },
      "ap-southeast-1": {
        "AMI": "ami-2c59e74f"
      },
      "ap-southeast-2": {
        "AMI": "ami-a1f3fdc2"
      },
      "ap-south-1": {
        "AMI": "ami-3c8efd53"
      },
      "sa-east-1": {
        "AMI": "ami-c67113aa"
      }
    }
  },
  "Resources": {
    "IAMInstanceProfile": {
      "Type": "AWS::IAM::InstanceProfile",
      "Properties": {
        "Path": "/",
        "Roles": [
          {
            "Ref": "IAMRole"
          }
        ]
      }
    },
    "IAMRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AWS::StackName"
              },
              "-Role"
            ]
          ]
        },
        "ManagedPolicyArns": [
          {
            "Fn::If": [
              "UseManagedPolicyARN",
              {
                "Ref": "ManagedPolicyARN"
              },
              {
                "Ref": "AWS::NoValue"
              }
            ]
          },
          {
            "Fn::If": [
              "UseECR",
              {
                "Fn::FindInMap": [
                  "ECRManagedPolicy",
                  {
                    "Ref": "ECRAccessPolicy"
                  },
                  "Policy"
                ]
              },
              {
                "Ref": "AWS::NoValue"
              }
            ]
          }
        ],
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "ec2.amazonaws.com"
                ]
              },
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/"
      }
    },
    "IAMPolicies": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "InstancePolicy",
        "PolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "cloudwatch:PutMetricData",
                "cloudformation:DescribeStackResource",
                "ec2:DescribeTags",
                "autoscaling:DescribeAutoScalingInstances",
                "autoscaling:DescribeLifecycleHooks",
                "autoscaling:RecordLifecycleActionHeartbeat",
                "autoscaling:CompleteLifecycleAction",
                "autoscaling:SetInstanceHealth"
              ],
              "Resource": "*"
            },
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
              ],
              "Resource": "*"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IAMRole"
          }
        ]
      }
    },
    "SecretsBucketPolicies": {
      "Type": "AWS::IAM::Policy",
      "Condition": "UseSecretsBucket",
      "Properties": {
        "PolicyName": "SecretsBucketPolicy",
        "PolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "s3:Get*",
                "s3:Get",
                "s3:List*"
              ],
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [
                      "arn:aws:s3:::",
                      {
                        "Ref": "SecretsBucket"
                      },
                      "/*"
                    ]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      "arn:aws:s3:::",
                      {
                        "Ref": "SecretsBucket"
                      }
                    ]
                  ]
                }
              ]
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IAMRole"
          }
        ]
      }
    },
    "ArtifactsBucketPolicies": {
      "Type": "AWS::IAM::Policy",
      "Condition": "UseArtifactsBucket",
      "Properties": {
        "PolicyName": "ArtifactsBucketPolicy",
        "PolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "s3:Put*",
                "s3:List*",
                "s3:Get*"
              ],
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [
                      "arn:aws:s3:::",
                      {
                        "Ref": "ArtifactsBucket"
                      },
                      "/*"
                    ]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [
                      "arn:aws:s3:::",
                      {
                        "Ref": "ArtifactsBucket"
                      }
                    ]
                  ]
                }
              ]
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IAMRole"
          }
        ]
      }
    },
    "AgentLaunchConfiguration": {
      "Type": "AWS::AutoScaling::LaunchConfiguration",
      "Properties": {
        "AssociatePublicIpAddress": {
          "Ref": "AssociatePublicIpAddress"
        },
        "SecurityGroups": [
          {
            "Fn::If": [
              "CreateSecurityGroup",
              {
                "Ref": "SecurityGroup"
              },
              {
                "Ref": "SecurityGroupId"
              }
            ]
          }
        ],
        "KeyName": {
          "Ref": "KeyName"
        },
        "IamInstanceProfile": {
          "Ref": "IAMInstanceProfile"
        },
        "InstanceType": {
          "Ref": "InstanceType"
        },
        "SpotPrice": {
          "Fn::If": [
            "UseSpotInstances",
            {
              "Ref": "SpotPrice"
            },
            {
              "Ref": "AWS::NoValue"
            }
          ]
        },
        "ImageId": {
          "Fn::If": [
            "UseDefaultAMI",
            {
              "Fn::FindInMap": [
                "AWSRegion2AMI",
                {
                  "Ref": "AWS::Region"
                },
                "AMI"
              ]
            },
            {
              "Ref": "ImageId"
            }
          ]
        },
        "BlockDeviceMappings": [
          {
            "DeviceName": "/dev/xvda",
            "Ebs": {
              "VolumeSize": {
                "Ref": "RootVolumeSize"
              },
              "VolumeType": "gp2"
            }
          }
        ],
        "UserData": {
          "Fn::Base64": {
            "Fn::Join": [
              "",
              [
                "#!/bin/bash -xv\nBUILDKITE_STACK_NAME=\"",
                {
                  "Ref": "AWS::StackName"
                },
                "\" \\\nBUILDKITE_STACK_VERSION=v2.0.2 \\\nBUILDKITE_SECRETS_BUCKET=\"",
                {
                  "Ref": "SecretsBucket"
                },
                "\" \\\nBUILDKITE_AGENT_TOKEN=\"",
                {
                  "Ref": "BuildkiteAgentToken"
                },
                "\" \\\nBUILDKITE_AGENTS_PER_INSTANCE=\"",
                {
                  "Ref": "AgentsPerInstance"
                },
                "\" \\\nBUILDKITE_AGENT_RELEASE=\"",
                {
                  "Ref": "BuildkiteAgentRelease"
                },
                "\" \\\nBUILDKITE_QUEUE=\"",
                {
                  "Ref": "BuildkiteQueue"
                },
                "\" \\\nBUILDKITE_ELASTIC_BOOTSTRAP_SCRIPT=\"",
                {
                  "Ref": "BootstrapScriptUrl"
                },
                "\" \\\nBUILDKITE_AUTHORIZED_USERS_URL=\"",
                {
                  "Ref": "AuthorizedUsersUrl"
                },
                "\" \\\nBUILDKITE_ECR_POLICY=",
                {
                  "Ref": "ECRAccessPolicy"
                },
                " \\\nAWS_DEFAULT_REGION=",
                {
                  "Ref": "AWS::Region"
                },
                " \\\nAWS_REGION=",
                {
                  "Ref": "AWS::Region"
                },
                " \\\n  /usr/local/bin/bk-install-elastic-stack.sh\n"
              ]
            ]
          }
        }
      }
    },
    "AgentLifecycleTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "AgentLifecycleHookRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "autoscaling.amazonaws.com"
                ]
              },
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "AgentLifecyclePolicy",
            "PolicyDocument": {
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "sns:Publish"
                  ],
                  "Resource": {
                    "Ref": "AgentLifecycleTopic"
                  }
                }
              ]
            }
          }
        ],
        "Path": "/"
      }
    },
    "AgentLifecycleHook": {
      "Type": "AWS::AutoScaling::LifecycleHook",
      "Properties": {
        "AutoScalingGroupName": {
          "Ref": "AgentAutoScaleGroup"
        },
        "LifecycleTransition": "autoscaling:EC2_INSTANCE_TERMINATING",
        "DefaultResult": "CONTINUE",
        "NotificationTargetARN": {
          "Ref": "AgentLifecycleTopic"
        },
        "RoleARN": {
          "Fn::GetAtt": [
            "AgentLifecycleHookRole",
            "Arn"
          ]
        }
      }
    },
    "AgentAutoScaleGroup": {
      "Type": "AWS::AutoScaling::AutoScalingGroup",
      "Properties": {
        "VPCZoneIdentifier": {
          "Fn::If": [
            "CreateVpcResources",
            [
              {
                "Ref": "Subnet0"
              },
              {
                "Ref": "Subnet1"
              }
            ],
            {
              "Ref": "Subnets"
            }
          ]
        },
        "LaunchConfigurationName": {
          "Ref": "AgentLaunchConfiguration"
        },
        "DesiredCapacity": {
          "Ref": "DesiredCapacity"
        },
        "MinSize": {
          "Ref": "MinSize"
        },
        "MaxSize": {
          "Ref": "MaxSize"
        },
        "MetricsCollection": [
          {
            "Granularity": "1Minute",
            "Metrics": [
              "GroupMinSize",
              "GroupMaxSize",
              "GroupInServiceInstances",
              "GroupTerminatingInstances",
              "GroupPendingInstances"
            ]
          }
        ],
        "TerminationPolicies": [
          "OldestLaunchConfiguration",
          "ClosestToNextInstanceHour"
        ],
        "Tags": [
          {
            "Key": "Role",
            "Value": "buildkite-agent",
            "PropagateAtLaunch": "true"
          },
          {
            "Key": "Name",
            "Value": "buildkite-agent",
            "PropagateAtLaunch": "true"
          },
          {
            "Key": "BuildkiteAgentRelease",
            "Value": {
              "Ref": "BuildkiteAgentRelease"
            },
            "PropagateAtLaunch": "true"
          },
          {
            "Key": "BuildkiteQueue",
            "Value": {
              "Ref": "BuildkiteQueue"
            },
            "PropagateAtLaunch": "true"
          }
        ]
      },
      "CreationPolicy": {
        "ResourceSignal": {
          "Timeout": "PT5M",
          "Count": {
            "Ref": "MinSize"
          }
        }
      },
      "UpdatePolicy": {
        "AutoScalingRollingUpdate": {
          "MinInstancesInService": 0,
          "MaxBatchSize": 5,
          "PauseTime": "PT40M",
          "WaitOnResourceSignals": "true",
          "SuspendProcesses": [
            "AlarmNotification",
            "ScheduledActions"
          ]
        }
      }
    },
    "SecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Condition": "CreateSecurityGroup",
      "Properties": {
        "GroupDescription": "Enable access to SSH",
        "VpcId": {
          "Fn::If": [
            "CreateVpcResources",
            {
              "Ref": "Vpc"
            },
            {
              "Ref": "VpcId"
            }
          ]
        },
        "SecurityGroupIngress": [
          {
            "IpProtocol": "tcp",
            "FromPort": 22,
            "ToPort": 22,
            "CidrIp": "0.0.0.0/0"
          }
        ],
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "AgentScaleUpPolicy": {
      "Type": "AWS::AutoScaling::ScalingPolicy",
      "Condition": "UseAutoscaling",
      "Properties": {
        "AdjustmentType": "ChangeInCapacity",
        "AutoScalingGroupName": {
          "Ref": "AgentAutoScaleGroup"
        },
        "Cooldown": 120,
        "ScalingAdjustment": {
          "Ref": "ScaleUpAdjustment"
        }
      }
    },
    "AgentScaleDownPolicy": {
      "Type": "AWS::AutoScaling::ScalingPolicy",
      "Condition": "UseAutoscaling",
      "Properties": {
        "AdjustmentType": "ChangeInCapacity",
        "AutoScalingGroupName": {
          "Ref": "AgentAutoScaleGroup"
        },
        "Cooldown": 60,
        "ScalingAdjustment": {
          "Ref": "ScaleDownAdjustment"
        }
      }
    },
    "AgentUtilizationAlarmHigh": {
      "Type": "AWS::CloudWatch::Alarm",
      "Condition": "UseAutoscaling",
      "Properties": {
        "AlarmDescription": "Scale-up if ScheduledJobs > 0 for 1 minute",
        "MetricName": "ScheduledJobsCount",
        "Namespace": "Buildkite",
        "Statistic": "Minimum",
        "Period": 60,
        "EvaluationPeriods": 1,
        "Threshold": 0,
        "AlarmActions": [
          {
            "Ref": "AgentScaleUpPolicy"
          }
        ],
        "Dimensions": [
          {
            "Name": "Queue",
            "Value": {
              "Ref": "BuildkiteQueue"
            }
          }
        ],
        "ComparisonOperator": "GreaterThanThreshold"
      }
    },
    "AgentUtilizationAlarmLow": {
      "Type": "AWS::CloudWatch::Alarm",
      "Condition": "UseAutoscaling",
      "Properties": {
        "AlarmDescription": "Scale-down if UnfinishedJobs == 0 for 30 minutes",
        "MetricName": "UnfinishedJobsCount",
        "Namespace": "Buildkite",
        "Statistic": "Maximum",
        "Period": 300,
        "EvaluationPeriods": 6,
        "Threshold": 0,
        "AlarmActions": [
          {
            "Ref": "AgentScaleDownPolicy"
          }
        ],
        "Dimensions": [
          {
            "Name": "Queue",
            "Value": {
              "Ref": "BuildkiteQueue"
            }
          }
        ],
        "ComparisonOperator": "LessThanOrEqualToThreshold"
      }
    },
    "Vpc": {
      "Type": "AWS::EC2::VPC",
      "Condition": "CreateVpcResources",
      "Properties": {
        "CidrBlock": "10.0.0.0/16",
        "InstanceTenancy": "default",
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "Gateway": {
      "Type": "AWS::EC2::InternetGateway",
      "Condition": "CreateVpcResources",
      "Properties": {
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "GatewayAttachment": {
      "Type": "AWS::EC2::VPCGatewayAttachment",
      "DependsOn": "Gateway",
      "Condition": "CreateVpcResources",
      "Properties": {
        "InternetGatewayId": {
          "Ref": "Gateway"
        },
        "VpcId": {
          "Ref": "Vpc"
        }
      }
    },
    "Subnet0": {
      "Type": "AWS::EC2::Subnet",
      "Condition": "CreateVpcResources",
      "Properties": {
        "AvailabilityZone": {
          "Fn::If": [
            "UseSpecifiedAvailabilityZones",
            {
              "Fn::Select": [
                0,
                {
                  "Ref": "AvailabilityZones"
                }
              ]
            },
            {
              "Fn::Select": [
                0,
                {
                  "Fn::GetAZs": {
                    "Ref": "AWS::Region"
                  }
                }
              ]
            }
          ]
        },
        "CidrBlock": "10.0.1.0/24",
        "VpcId": {
          "Ref": "Vpc"
        },
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "Subnet1": {
      "Type": "AWS::EC2::Subnet",
      "Condition": "CreateVpcResources",
      "Properties": {
        "AvailabilityZone": {
          "Fn::If": [
            "UseSpecifiedAvailabilityZones",
            {
              "Fn::Select": [
                1,
                {
                  "Ref": "AvailabilityZones"
                }
              ]
            },
            {
              "Fn::Select": [
                1,
                {
                  "Fn::GetAZs": {
                    "Ref": "AWS::Region"
                  }
                }
              ]
            }
          ]
        },
        "CidrBlock": "10.0.2.0/24",
        "VpcId": {
          "Ref": "Vpc"
        },
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "Routes": {
      "Type": "AWS::EC2::RouteTable",
      "Condition": "CreateVpcResources",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "Tags": [
          {
            "Key": "Name",
            "Value": {
              "Ref": "AWS::StackName"
            }
          }
        ]
      }
    },
    "RouteDefault": {
      "Type": "AWS::EC2::Route",
      "Condition": "CreateVpcResources",
      "Properties": {
        "DestinationCidrBlock": "0.0.0.0/0",
        "GatewayId": {
          "Ref": "Gateway"
        },
        "RouteTableId": {
          "Ref": "Routes"
        }
      }
    },
    "Subnet0Routes": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Condition": "CreateVpcResources",
      "Properties": {
        "SubnetId": {
          "Ref": "Subnet0"
        },
        "RouteTableId": {
          "Ref": "Routes"
        }
      }
    },
    "Subnet1Routes": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Condition": "CreateVpcResources",
      "Properties": {
        "SubnetId": {
          "Ref": "Subnet1"
        },
        "RouteTableId": {
          "Ref": "Routes"
        }
      }
    },
    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Condition": "CreateMetricsStack",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/"
      }
    },
    "LambdaExecutionPolicy": {
      "DependsOn": "LambdaExecutionRole",
      "Type": "AWS::IAM::Policy",
      "Condition": "CreateMetricsStack",
      "Properties": {
        "PolicyName": "AccessToCloudwatchForBuildkiteMetrics",
        "Roles": [
          {
            "Ref": "LambdaExecutionRole"
          }
        ],
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "cloudwatch:PutMetricData",
                "autoscaling:SetInstanceHealth"
              ],
              "Resource": [
                "*"
              ]
            }
          ]
        }
      }
    },
    "BuildkiteMetricsFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": [
        "LambdaExecutionRole",
        "LambdaExecutionPolicy"
      ],
      "Condition": "CreateMetricsStack",
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Fn::FindInMap": [
              "MetricsLambdaBucket",
              {
                "Ref": "AWS::Region"
              },
              "Bucket"
            ]
          },
          "S3Key": "buildkite-metrics-v1.4.1-lambda.zip"
        },
        "Role": {
          "Fn::GetAtt": [
            "LambdaExecutionRole",
            "Arn"
          ]
        },
        "Timeout": 60,
        "Handler": "handler.handle",
        "Runtime": "python2.7",
        "MemorySize": 128,
        "Environment": {
          "Variables": {
            "BUILDKITE_TOKEN": {
              "Ref": "BuildkiteApiAccessToken"
            },
            "BUILDKITE_ORG": {
              "Ref": "BuildkiteOrgSlug"
            },
            "BUILDKITE_QUEUE": {
              "Ref": "BuildkiteQueue"
            }
          }
        }
      }
    },
    "ScheduledRule": {
      "Type": "AWS::Events::Rule",
      "Condition": "CreateMetricsStack",
      "Properties": {
        "Description": "ScheduledRule",
        "ScheduleExpression": "rate(1 minute)",
        "State": "ENABLED",
        "Targets": [
          {
            "Arn": {
              "Fn::GetAtt": [
                "BuildkiteMetricsFunction",
                "Arn"
              ]
            },
            "Id": "TargetBuildkiteMetricsFunction"
          }
        ]
      }
    },
    "PermissionForEventsToInvokeLambda": {
      "Type": "AWS::Lambda::Permission",
      "Condition": "CreateMetricsStack",
      "Properties": {
        "FunctionName": {
          "Ref": "BuildkiteMetricsFunction"
        },
        "Action": "lambda:InvokeFunction",
        "Principal": "events.amazonaws.com",
        "SourceArn": {
          "Fn::GetAtt": [
            "ScheduledRule",
            "Arn"
          ]
        }
      }
    }
  },
  "Outputs": {
    "AutoScalingGroupName": {
      "Value": {
        "Ref": "AgentAutoScaleGroup"
      }
    }
  }
}
