<commit_before>
## Provides the infrastructure for a scalable buildkite cluster

Parameters:
  KeyName:
    Description: The ssh keypair used to access the buildkite instances
    Type: AWS::EC2::KeyPair::KeyName

  BuildkiteOrgSlug:
    Description: Your Buildkite organization slug
    Type: String

  BuildkiteAgentToken:
    Description: Your Buildkite agent token from Buildkite.com
    Type: String
    NoEcho: true

  BuildkiteAgentMetadata:
    Description: The metadata to register the agent with
    Type: String
    Default: queue=elastic docker=true dockercompose=true

  ProvisionBucket:
    Description: An s3 bucket containing dockercfg and id_rsa_buildkite
    Type: String

  AuthorizedUsersUrl:
    Description: An optional url to periodically download ssh authorized_keys from
    Type: String

  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VpcId of your existing Virtual Private Cloud (VPC).

  Subnets:
    Type: List<AWS::EC2::Subnet::Id>
    Description: The list of SubnetIds where the instances will be launched

  InstanceType:
    Description: The type of instance to use for the agent
    Type: String
    Default: m3.medium
    AllowedValues:
      - c4.large
      - c4.xlarge
      - c4.2xlarge
      - c4.4xlarge
      - c4.8xlarge
      - t2.micro
      - t2.small
      - t2.medium
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge

  SpotPrice:
    Description: An optional spot price to use for the agents
    Type: String
    Default: 0

  MaxSize:
    Description: The maximum number of agents to launch
    Type: Number
    Default: 6

  MinSize:
    Description: The minumum number of agents to launch
    Type: Number
    Default: 1

  AgentsPerHost:
    Description: The number of buildkite agents to run per host
    Type: Number
    Default: 6

Conditions:
    UseSpotInstances:
      !Not [ !Equals [ $(SpotPrice), 0 ] ]

Resources:
  # Allow ec2 instances to assume a role and be granted the IAMPolicies
  IAMInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: [ $(IAMRole) ]
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: [ ec2.amazonaws.com ]
            Action: sts:AssumeRole
      Path: /

  # Policies for the agent instances
  IAMPolicies:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: InstancePolicy
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - cloudwatch:PutMetricData
              - cloudformation:DescribeStackResource
              - ec2:DescribeTags
            Resource: "*"
          - Effect: Allow
            Action:
              - s3:GetObject
              - s3:GetObjectVersion
              - s3:ListBucket
              - s3:ListBucketVersions
            Resource: "arn:aws:s3:::$(ProvisionBucket)/*"
      Roles:
        - $(IAMRole)

  AgentLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      SecurityGroups: [ $(SecurityGroup) ]
      KeyName : $(KeyName)
      IamInstanceProfile: $(IAMInstanceProfile)
      InstanceType: $(InstanceType)
      SpotPrice: !If [ "UseSpotInstances", $(SpotPrice), '$(AWS::NoValue)' ]
      ImageId : $(AWSArch2AMI[$(AWS::Region)][$(AWSInstanceType2Arch[$(InstanceType)][Arch])])
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs: { VolumeSize: 80, VolumeType: gp2 }
      UserData: !Base64 |
        #!/bin/bash -xv
        /usr/local/bin/cfn-init -s $(AWS::StackId) -r AgentLaunchConfiguration --region $(AWS::Region)
        /usr/local/bin/cfn-signal -e \$? -r 'cfn-init finished' \
          --stack $(AWS::StackName) --resource 'AgentAutoScaleGroup' --region $(AWS::Region)

    Metadata:
      AWS::CloudFormation::Authentication:
        S3AccessCreds:
          type: S3
          roleName: $(IAMRole)
          buckets: $(ProvisionBucket)

      # see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
      AWS::CloudFormation::Init:
        config:
          files:
            "/root/.ssh/id_rsa":
              source: "https://s3.amazonaws.com/$(ProvisionBucket)/id_rsa_buildkite"
              mode: '000400'
              owner: root
              group: root
              authentication: S3AccessCreds
            "/home/ubuntu/.dockercfg":
              source: "https://s3.amazonaws.com/$(ProvisionBucket)/dockercfg"
              mode: '000400'
              owner: ubuntu
              group: ubuntu
              authentication: S3AccessCreds
            "/lib/systemd/system/ssh-agent.service":
              content: |
                [Unit]
                Description=ssh-agent
                Before=docker.service
                [Service]
                Type=forking
                Environment=SSH_AUTH_SOCK=/ssh-agent
                ExecStart=/usr/bin/ssh-agent -a \$SSH_AUTH_SOCK
                ExecStartPost=/usr/bin/ssh-add /root/.ssh/id_rsa
                [Install]
                WantedBy=default.target
              mode: '000400'
              owner: root
              group: root
            "/home/ubuntu/buildkite/hooks/environment":
              content: |
                #!/bin/bash -eu
                echo "~~~ Stopping existing docker containers"
                if [[ \$(docker ps -q | wc -l) -gt 0 ]] ; then
                  docker stop \$(docker ps -q)
                fi
              mode: '000700'
              owner: ubuntu
              group: ubuntu
            "/home/ubuntu/docker-compose.yml":
              content: |
                buildkite:
                  image: buildkite/agent:dind
                  privileged: true
                  environment:
                    - BUILDKITE_AGENT_TOKEN=$(BuildkiteAgentToken)
                    - BUILDKITE_AGENT_META_DATA=$(BuildkiteAgentMetadata)
                    - BUILDKITE_AGENT_NAME=elastic-%hostname-%n
                    - SSH_AUTH_SOCK=/ssh-agent
                  volumes:
                    - /ssh-agent:/ssh-agent
                    - /home/ubuntu/.dockercfg:/root/.dockercfg
                    - /home/ubuntu/buildkite/hooks:/buildkite/hooks
                  restart: always
                  log_driver: syslog
              mode: '000600'
              owner: ubuntu
              group: ubuntu
            "/etc/cron.hourly/authorized_keys":
              content: |
                #!/bin/bash -eu
                test -z "$(AuthorizedUsersUrl)" && exit 0
                curl --silent -f "$(AuthorizedUsersUrl)" > /tmp/authorized_keys
                mv /tmp/authorized_keys /home/ubuntu/.ssh/authorized_keys
                chmod 600 /home/ubuntu/.ssh/authorized_keys
                chown ubuntu: /home/ubuntu/.ssh/authorized_keys
              mode: '000700'
              owner: root
              group: root
            "/etc/cron.d/cloudwatch":
              content: |
                */2 * * * * root perl /usr/local/aws-scripts-mon/mon-put-instance-data.pl --mem-util --disk-space-util --disk-path=/ --disk-path=/var/lib/docker --from-cron<commit_msg>Use agent image with specific docker version<commit_after>
## Provides the infrastructure for a scalable buildkite cluster

Parameters:
  KeyName:
    Description: The ssh keypair used to access the buildkite instances
    Type: AWS::EC2::KeyPair::KeyName

  BuildkiteOrgSlug:
    Description: Your Buildkite organization slug
    Type: String

  BuildkiteAgentToken:
    Description: Your Buildkite agent token from Buildkite.com
    Type: String
    NoEcho: true

  BuildkiteAgentMetadata:
    Description: The metadata to register the agent with
    Type: String
    Default: queue=elastic docker=true dockercompose=true

  ProvisionBucket:
    Description: An s3 bucket containing dockercfg and id_rsa_buildkite
    Type: String

  AuthorizedUsersUrl:
    Description: An optional url to periodically download ssh authorized_keys from
    Type: String

  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VpcId of your existing Virtual Private Cloud (VPC).

  Subnets:
    Type: List<AWS::EC2::Subnet::Id>
    Description: The list of SubnetIds where the instances will be launched

  InstanceType:
    Description: The type of instance to use for the agent
    Type: String
    Default: m3.medium
    AllowedValues:
      - c4.large
      - c4.xlarge
      - c4.2xlarge
      - c4.4xlarge
      - c4.8xlarge
      - t2.micro
      - t2.small
      - t2.medium
      - m3.medium
      - m3.large
      - m3.xlarge
      - m3.2xlarge

  SpotPrice:
    Description: An optional spot price to use for the agents
    Type: String
    Default: 0

  MaxSize:
    Description: The maximum number of agents to launch
    Type: Number
    Default: 6

  MinSize:
    Description: The minumum number of agents to launch
    Type: Number
    Default: 1

  AgentsPerHost:
    Description: The number of buildkite agents to run per host
    Type: Number
    Default: 6

Conditions:
    UseSpotInstances:
      !Not [ !Equals [ $(SpotPrice), 0 ] ]

Resources:
  # Allow ec2 instances to assume a role and be granted the IAMPolicies
  IAMInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles: [ $(IAMRole) ]
  IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: [ ec2.amazonaws.com ]
            Action: sts:AssumeRole
      Path: /

  # Policies for the agent instances
  IAMPolicies:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: InstancePolicy
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - cloudwatch:PutMetricData
              - cloudformation:DescribeStackResource
              - ec2:DescribeTags
            Resource: "*"
          - Effect: Allow
            Action:
              - s3:GetObject
              - s3:GetObjectVersion
              - s3:ListBucket
              - s3:ListBucketVersions
            Resource: "arn:aws:s3:::$(ProvisionBucket)/*"
      Roles:
        - $(IAMRole)

  AgentLaunchConfiguration:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      SecurityGroups: [ $(SecurityGroup) ]
      KeyName : $(KeyName)
      IamInstanceProfile: $(IAMInstanceProfile)
      InstanceType: $(InstanceType)
      SpotPrice: !If [ "UseSpotInstances", $(SpotPrice), '$(AWS::NoValue)' ]
      ImageId : $(AWSArch2AMI[$(AWS::Region)][$(AWSInstanceType2Arch[$(InstanceType)][Arch])])
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs: { VolumeSize: 80, VolumeType: gp2 }
      UserData: !Base64 |
        #!/bin/bash -xv
        /usr/local/bin/cfn-init -s $(AWS::StackId) -r AgentLaunchConfiguration --region $(AWS::Region)
        /usr/local/bin/cfn-signal -e \$? -r 'cfn-init finished' \
          --stack $(AWS::StackName) --resource 'AgentAutoScaleGroup' --region $(AWS::Region)

    Metadata:
      AWS::CloudFormation::Authentication:
        S3AccessCreds:
          type: S3
          roleName: $(IAMRole)
          buckets: $(ProvisionBucket)

      # see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html
      AWS::CloudFormation::Init:
        config:
          files:
            "/root/.ssh/id_rsa":
              source: "https://s3.amazonaws.com/$(ProvisionBucket)/id_rsa_buildkite"
              mode: '000400'
              owner: root
              group: root
              authentication: S3AccessCreds
            "/home/ubuntu/.dockercfg":
              source: "https://s3.amazonaws.com/$(ProvisionBucket)/dockercfg"
              mode: '000400'
              owner: ubuntu
              group: ubuntu
              authentication: S3AccessCreds
            "/lib/systemd/system/ssh-agent.service":
              content: |
                [Unit]
                Description=ssh-agent
                Before=docker.service
                [Service]
                Type=forking
                Environment=SSH_AUTH_SOCK=/ssh-agent
                ExecStart=/usr/bin/ssh-agent -a \$SSH_AUTH_SOCK
                ExecStartPost=/usr/bin/ssh-add /root/.ssh/id_rsa
                [Install]
                WantedBy=default.target
              mode: '000400'
              owner: root
              group: root
            "/home/ubuntu/buildkite/hooks/environment":
              content: |
                #!/bin/bash -eu
                echo "~~~ Stopping existing docker containers"
                if [[ \$(docker ps -q | wc -l) -gt 0 ]] ; then
                  docker stop \$(docker ps -q)
                fi
              mode: '000700'
              owner: ubuntu
              group: ubuntu
            "/home/ubuntu/docker-compose.yml":
              content: |
                buildkite:
                  image: 99designs/buildkite-agent:docker-1.6-compose-1.3
                  privileged: true
                  environment:
                    - BUILDKITE_AGENT_TOKEN=$(BuildkiteAgentToken)
                    - BUILDKITE_AGENT_META_DATA=$(BuildkiteAgentMetadata)
                    - BUILDKITE_AGENT_NAME=elastic-%hostname-%n
                    - SSH_AUTH_SOCK=/ssh-agent
                  volumes:
                    - /ssh-agent:/ssh-agent
                    - /home/ubuntu/.dockercfg:/root/.dockercfg
                    - /home/ubuntu/buildkite/hooks:/buildkite/hooks
                  restart: always
                  log_driver: syslog
              mode: '000600'
              owner: ubuntu
              group: ubuntu
            "/etc/cron.hourly/authorized_keys":
              content: |
                #!/bin/bash -eu
                test -z "$(AuthorizedUsersUrl)" && exit 0
                curl --silent -f "$(AuthorizedUsersUrl)" > /tmp/authorized_keys
                mv /tmp/authorized_keys /home/ubuntu/.ssh/authorized_keys
                chmod 600 /home/ubuntu/.ssh/authorized_keys
                chown ubuntu: /home/ubuntu/.ssh/authorized_keys
              mode: '000700'
              owner: root
              group: root
            "/etc/cron.d/cloudwatch":
              content: |
                */2 * * * * root perl /usr/local/aws-scripts-mon/mon-put-instance-data.pl --mem-util --disk-space-util --disk-path=/ --disk-path=/var/lib/docker --from-cron
{'fraction_non_alphanumeric': 0.09687478345229021, 'fraction_numerical': 0.012888919686785393, 'mean_word_length': 1.7411206077872745, 'pattern_counts': {'":': 14, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1418925', 'n_tokens_mistral': 4405, 'n_tokens_neox': 4040, 'n_words': 935}