spot_build 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.ruby-version +1 -0
 - data/Gemfile +3 -0
 - data/Gemfile.lock +39 -0
 - data/LICENSE +21 -0
 - data/README.md +16 -0
 - data/bin/spot_build +5 -0
 - data/lib/spot_build/buildkite_agent.rb +77 -0
 - data/lib/spot_build/spot_instance.rb +25 -0
 - data/lib/spot_build/sqs_event.rb +24 -0
 - data/lib/spot_build.rb +56 -0
 - data/spot_build.gemspec +21 -0
 - metadata +96 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 58c259e6f3b6c9e4ccbc8682426d3ab23b257406
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 9a6d4d033c24ab2778946281c967e359968e9f12
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: bd29f93748e8113a7c31ad592eeef931cecdd6b75dc40884760013261e62d0138fd3dad58ec556f2852fbf4900173c432acb32f2b0405566f2bdee1db582d758
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 9db1142b19e9fcd33367394df0bccafad2bb655e8ba37ff9d7ac46864687726bfcdb60f9ccf53c2c51352cd8d3129cf5d20b93cccd2271bb297bdeb9e93fec05
         
     | 
    
        data/.ruby-version
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            2.3.0
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,39 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            PATH
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: .
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                spot_build (0.0.2)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  aws-sdk (~> 2)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  buildkit (~> 0.4)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  link_header (~> 0.0.2)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 10 
     | 
    
         
            +
              remote: https://rubygems.org/
         
     | 
| 
      
 11 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 12 
     | 
    
         
            +
                addressable (2.3.8)
         
     | 
| 
      
 13 
     | 
    
         
            +
                aws-sdk (2.6.38)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  aws-sdk-resources (= 2.6.38)
         
     | 
| 
      
 15 
     | 
    
         
            +
                aws-sdk-core (2.6.38)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  aws-sigv4 (~> 1.0)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  jmespath (~> 1.0)
         
     | 
| 
      
 18 
     | 
    
         
            +
                aws-sdk-resources (2.6.38)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  aws-sdk-core (= 2.6.38)
         
     | 
| 
      
 20 
     | 
    
         
            +
                aws-sigv4 (1.0.0)
         
     | 
| 
      
 21 
     | 
    
         
            +
                buildkit (0.4.0)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  sawyer (~> 0.6.0)
         
     | 
| 
      
 23 
     | 
    
         
            +
                faraday (0.9.2)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  multipart-post (>= 1.2, < 3)
         
     | 
| 
      
 25 
     | 
    
         
            +
                jmespath (1.3.1)
         
     | 
| 
      
 26 
     | 
    
         
            +
                link_header (0.0.8)
         
     | 
| 
      
 27 
     | 
    
         
            +
                multipart-post (2.0.0)
         
     | 
| 
      
 28 
     | 
    
         
            +
                sawyer (0.6.0)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  addressable (~> 2.3.5)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  faraday (~> 0.8, < 0.10)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 33 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 36 
     | 
    
         
            +
              spot_build!
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            BUNDLED WITH
         
     | 
| 
      
 39 
     | 
    
         
            +
               1.13.6
         
     | 
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2016 Envato
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 13 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Managing Spot Fleets with Buildkite
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            AWS EC2 Spot instances are cheaper, Buildkite Agents are a natural fit for Spot instnaces as the workload is interruptable.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            SpotBuild makes it easier to use Spot instances and Spot fleets with Buildkite Agents by providing an agent that will shutdown the agent when the instance is scheduled for termination, preventing it from starting any new jobs and retry the current job it's working on.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Running
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Run this gem as a daemon on your buildkite agents and supply it the Organisation Slug and a Buildkite API token with the following permissions:
         
     | 
| 
      
 10 
     | 
    
         
            +
            - read_agents
         
     | 
| 
      
 11 
     | 
    
         
            +
            - read_builds
         
     | 
| 
      
 12 
     | 
    
         
            +
            - write_builds
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ## Development Status
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            Very early stages of development
         
     | 
    
        data/bin/spot_build
    ADDED
    
    
| 
         @@ -0,0 +1,77 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'buildkit'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'socket'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'link_header'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module SpotBuild
         
     | 
| 
      
 6 
     | 
    
         
            +
              class BuildkiteAgent
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(token, org_slug)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @client = Buildkit.new(token: token)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @org_slug = org_slug
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def the_end_is_nigh
         
     | 
| 
      
 13 
     | 
    
         
            +
                  return unless agent_running?
         
     | 
| 
      
 14 
     | 
    
         
            +
                  job = current_job
         
     | 
| 
      
 15 
     | 
    
         
            +
                  stop(true)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  reschedule_job(job)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def stop(force="false")
         
     | 
| 
      
 20 
     | 
    
         
            +
                  return unless agent_running?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @client.stop_agent(@org_slug, agent_id, "{\"force\": #{force}}")
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def agent_running?
         
     | 
| 
      
 25 
     | 
    
         
            +
                  !agent.nil?
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                private
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def reschedule_job(job)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  return if job.nil?
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @client.retry_job(@org_slug, job_pipeline(job[:build_url]), job_build(job[:build_url]), job[:id])
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # build_url: https://api.buildkite.com/v2/organizations/my-great-org/pipelines/sleeper/builds/50
         
     | 
| 
      
 36 
     | 
    
         
            +
                def job_pipeline(build_url)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  build_url[%r{organizations/#{@org_slug}/pipelines/([^/]*)}, 1]
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def job_build(build_url)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  build_url[%r{organizations/#{@org_slug}/pipelines/[^/]*/builds/([0-9]*)}, 1]
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def current_job
         
     | 
| 
      
 45 
     | 
    
         
            +
                  agent[:job]
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                def agent_id
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @agent_id ||= agent[:id]
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                def agent
         
     | 
| 
      
 53 
     | 
    
         
            +
                  agents.select { |agent| agent.hostname == Socket.gethostname }.first
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def agents
         
     | 
| 
      
 57 
     | 
    
         
            +
                  with_pagination do |options = {}|
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @client.agents(@org_slug, options)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # This is definately not thread safe
         
     | 
| 
      
 63 
     | 
    
         
            +
                def with_pagination(&block)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  results = yield
         
     | 
| 
      
 65 
     | 
    
         
            +
                  while next_ref = next_link_ref(@client.last_response.headers["link"])
         
     | 
| 
      
 66 
     | 
    
         
            +
                    uri = URI.parse(next_ref.href)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    next_page = uri.query.split("=")[1]
         
     | 
| 
      
 68 
     | 
    
         
            +
                    results.push(yield page: next_page)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  results.flatten
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def next_link_ref(header)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  LinkHeader.parse(header).find_link(["rel", "next"])
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'net/http'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'time'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module SpotBuild
         
     | 
| 
      
 5 
     | 
    
         
            +
              class SpotInstance
         
     | 
| 
      
 6 
     | 
    
         
            +
                def shutdown_if_required(&block)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  return false unless self.class.scheduled_for_termination?
         
     | 
| 
      
 8 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 9 
     | 
    
         
            +
                  true
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def self.scheduled_for_termination?
         
     | 
| 
      
 13 
     | 
    
         
            +
                  !time_until_termination.nil?
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def self.time_until_termination
         
     | 
| 
      
 17 
     | 
    
         
            +
                  uri = URI('http://169.254.169.254/latest/meta-data/spot/termination-time')
         
     | 
| 
      
 18 
     | 
    
         
            +
                  response = Net::HTTP.get_response(uri)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  return nil if response.code == "404"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Time.parse(response.body) - Time.now
         
     | 
| 
      
 21 
     | 
    
         
            +
                rescue ArgumentError
         
     | 
| 
      
 22 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'aws-sdk'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'timeout'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module SpotBuild
         
     | 
| 
      
 5 
     | 
    
         
            +
              class SqsEvent
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(url:, timeout:, region: ENV['AWS_REGION'])
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @queue = Aws::SQS::Queue.new(url: url, region: region)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @timeout = timeout
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def shutdown_if_required(&block)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  # Any message to this queue is treated as a "I should shutdown"
         
     | 
| 
      
 13 
     | 
    
         
            +
                  message = @queue.receive_messages(
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attribute_names: ["All"],
         
     | 
| 
      
 15 
     | 
    
         
            +
                    max_number_of_messages: 1,
         
     | 
| 
      
 16 
     | 
    
         
            +
                    visibility_timeout: (@timeout - 5),
         
     | 
| 
      
 17 
     | 
    
         
            +
                  ).first
         
     | 
| 
      
 18 
     | 
    
         
            +
                  return false if message.nil?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  yield
         
     | 
| 
      
 20 
     | 
    
         
            +
                  message.delete
         
     | 
| 
      
 21 
     | 
    
         
            +
                  true
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/spot_build.rb
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spot_build/buildkite_agent'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'spot_build/spot_instance'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'spot_build/sqs_event'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module SpotBuild
         
     | 
| 
      
 7 
     | 
    
         
            +
              DEFAULT_TIMEOUT = 300
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def self.run
         
     | 
| 
      
 10 
     | 
    
         
            +
                options = parse_options
         
     | 
| 
      
 11 
     | 
    
         
            +
                options[:timeout] ||= DEFAULT_TIMEOUT
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                checks = [SpotInstance.new]
         
     | 
| 
      
 14 
     | 
    
         
            +
                if options[:queue_url]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  checks.push(SqsEvent.new(url: options[:queue_url], timeout: options[:timeout], region: options[:aws_region]))
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                agent = BuildkiteAgent.new(options[:token], options[:org_slug])
         
     | 
| 
      
 19 
     | 
    
         
            +
                loop do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  checks.each do |check|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    terminating = check.shutdown_if_required do
         
     | 
| 
      
 22 
     | 
    
         
            +
                      timeout = SpotInstance.scheduled_for_termination? ? (SpotInstance.time_until_termination - 30) : options[:timeout]
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      agent.stop
         
     | 
| 
      
 25 
     | 
    
         
            +
                      Timeout::timeout(timeout) do
         
     | 
| 
      
 26 
     | 
    
         
            +
                        while agent.agent_running?
         
     | 
| 
      
 27 
     | 
    
         
            +
                          sleep 5
         
     | 
| 
      
 28 
     | 
    
         
            +
                        end
         
     | 
| 
      
 29 
     | 
    
         
            +
                      end rescue Timeout::Error
         
     | 
| 
      
 30 
     | 
    
         
            +
                      agent.the_end_is_nigh
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
                    %x(shutdown -h now) if terminating
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  sleep 2
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def self.parse_options
         
     | 
| 
      
 39 
     | 
    
         
            +
                options = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                parser = OptionParser.new do |opts|
         
     | 
| 
      
 41 
     | 
    
         
            +
                  opts.banner = "Usage: #{__FILE__} [options]"
         
     | 
| 
      
 42 
     | 
    
         
            +
                  opts.on("-t", "--token TOKEN", "Buildkite API token") { |v| options[:token] = v }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  opts.on("-o", "--org-slug ORGANISATION-SLUG", "The Buildkite Organisation Slug") { |v| options[:org_slug] = v }
         
     | 
| 
      
 44 
     | 
    
         
            +
                  opts.on("-s", "--sqs-queue SQS-QUEUE-URL", "The SQS Queue URL we should monitor for events that tell us to shutdown") { |v| options[:queue_url] = v }
         
     | 
| 
      
 45 
     | 
    
         
            +
                  opts.on("--timeout TIMEOUT", "The amount of time to wait for the buildkite agent to stop before shutting down. Only used if --sqs-queue is specified") { |v| options[:timeout] = v.to_i }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  opts.on("-r", "--aws-region REGION", "The AWS Region the SQS queue resides in")  { |v| options[:aws_region] = v }
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
                parser.parse!
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                if options[:token].nil? || options[:org_slug].nil?
         
     | 
| 
      
 51 
     | 
    
         
            +
                  raise OptionParser::MissingArgument, "You must specify Token and Organisational Slug.\n#{parser.help}"
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                options
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
    
        data/spot_build.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Gem::Specification.new do |gem|
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem.name          = 'spot_build'
         
     | 
| 
      
 6 
     | 
    
         
            +
              gem.version       = '0.0.4'
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.authors       = ['Patrick Robinson']
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem.email         = []
         
     | 
| 
      
 9 
     | 
    
         
            +
              gem.description   = 'Helps manage Buildkite Agents running on EC2 Spot instances'
         
     | 
| 
      
 10 
     | 
    
         
            +
              gem.summary       = gem.description
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem.homepage      = 'https://github.com/envato/spot_build'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              gem.files         = `git ls-files`.split($/)
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 16 
     | 
    
         
            +
              gem.require_paths = ['lib']
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              gem.add_dependency 'buildkit', '~> 0.4'
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.add_dependency 'aws-sdk', '~> 2'
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.add_dependency 'link_header', '~> 0.0.2'
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,96 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: spot_build
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.4
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Patrick Robinson
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-05-30 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              name: buildkit
         
     | 
| 
      
 15 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 16 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 17 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 18 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 19 
     | 
    
         
            +
                    version: '0.4'
         
     | 
| 
      
 20 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 21 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '0.4'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: aws-sdk
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 30 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 31 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 32 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: '2'
         
     | 
| 
      
 34 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '2'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              name: link_header
         
     | 
| 
      
 43 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 44 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 45 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 46 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 47 
     | 
    
         
            +
                    version: 0.0.2
         
     | 
| 
      
 48 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 49 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: 0.0.2
         
     | 
| 
      
 55 
     | 
    
         
            +
            description: Helps manage Buildkite Agents running on EC2 Spot instances
         
     | 
| 
      
 56 
     | 
    
         
            +
            email: []
         
     | 
| 
      
 57 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 58 
     | 
    
         
            +
            - spot_build
         
     | 
| 
      
 59 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 60 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 61 
     | 
    
         
            +
            files:
         
     | 
| 
      
 62 
     | 
    
         
            +
            - .ruby-version
         
     | 
| 
      
 63 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 64 
     | 
    
         
            +
            - Gemfile.lock
         
     | 
| 
      
 65 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 66 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 67 
     | 
    
         
            +
            - bin/spot_build
         
     | 
| 
      
 68 
     | 
    
         
            +
            - lib/spot_build.rb
         
     | 
| 
      
 69 
     | 
    
         
            +
            - lib/spot_build/buildkite_agent.rb
         
     | 
| 
      
 70 
     | 
    
         
            +
            - lib/spot_build/spot_instance.rb
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/spot_build/sqs_event.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - spot_build.gemspec
         
     | 
| 
      
 73 
     | 
    
         
            +
            homepage: https://github.com/envato/spot_build
         
     | 
| 
      
 74 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 75 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 76 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 77 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 78 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 79 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 80 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 81 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 82 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 83 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 84 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 85 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 86 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 87 
     | 
    
         
            +
              - - '>='
         
     | 
| 
      
 88 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 89 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 90 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 91 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 92 
     | 
    
         
            +
            rubygems_version: 2.0.14.1
         
     | 
| 
      
 93 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 94 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 95 
     | 
    
         
            +
            summary: Helps manage Buildkite Agents running on EC2 Spot instances
         
     | 
| 
      
 96 
     | 
    
         
            +
            test_files: []
         
     |