blitz 0.1.0
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.
- data/.document +5 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +26 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +22 -0
- data/Rakefile +51 -0
- data/bin/blitz +11 -0
- data/blitz.gemspec +80 -0
- data/lib/blitz.rb +31 -0
- data/lib/blitz/client.rb +35 -0
- data/lib/blitz/command.rb +22 -0
- data/lib/blitz/command/api.rb +96 -0
- data/lib/blitz/command/curl.rb +272 -0
- data/lib/blitz/command/help.rb +22 -0
- data/lib/blitz/curl/error.rb +45 -0
- data/lib/blitz/curl/sprint.rb +108 -0
- data/lib/blitz/helper.rb +15 -0
- data/test/helper.rb +17 -0
- data/test/test_blitz.rb +6 -0
- metadata +182 -0
    
        data/.document
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            source "http://rubygems.org"
         | 
| 2 | 
            +
            # Add dependencies required to use your gem here.
         | 
| 3 | 
            +
            # Example:
         | 
| 4 | 
            +
            #   gem "activesupport", ">= 2.3.5"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            gem "rest-client", "~> 1.6.1"
         | 
| 7 | 
            +
            gem "json", "~> 1.4.6"
         | 
| 8 | 
            +
            gem "json_pure", "~> 1.4.6"
         | 
| 9 | 
            +
            gem "hexy", "~> 0.1.1"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            # Add dependencies to develop your gem here.
         | 
| 12 | 
            +
            # Include everything needed to run rake, tests, features, etc.
         | 
| 13 | 
            +
            group :development do
         | 
| 14 | 
            +
              gem "bundler", "~> 1.0.0"
         | 
| 15 | 
            +
              gem "jeweler", "~> 1.5.1"
         | 
| 16 | 
            +
            end
         | 
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            GEM
         | 
| 2 | 
            +
              remote: http://rubygems.org/
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                git (1.2.5)
         | 
| 5 | 
            +
                hexy (0.1.1)
         | 
| 6 | 
            +
                jeweler (1.5.1)
         | 
| 7 | 
            +
                  bundler (~> 1.0.0)
         | 
| 8 | 
            +
                  git (>= 1.2.5)
         | 
| 9 | 
            +
                  rake
         | 
| 10 | 
            +
                json (1.4.6)
         | 
| 11 | 
            +
                json_pure (1.4.6)
         | 
| 12 | 
            +
                mime-types (1.16)
         | 
| 13 | 
            +
                rake (0.8.7)
         | 
| 14 | 
            +
                rest-client (1.6.1)
         | 
| 15 | 
            +
                  mime-types (>= 1.16)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            PLATFORMS
         | 
| 18 | 
            +
              ruby
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            DEPENDENCIES
         | 
| 21 | 
            +
              bundler (~> 1.0.0)
         | 
| 22 | 
            +
              hexy (~> 0.1.1)
         | 
| 23 | 
            +
              jeweler (~> 1.5.1)
         | 
| 24 | 
            +
              json (~> 1.4.6)
         | 
| 25 | 
            +
              json_pure (~> 1.4.6)
         | 
| 26 | 
            +
              rest-client (~> 1.6.1)
         | 
    
        data/LICENSE.txt
    ADDED
    
    | @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            Copyright (c) 2011 Mu Dynamics
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining
         | 
| 4 | 
            +
            a copy of this software and associated documentation files (the
         | 
| 5 | 
            +
            "Software"), to deal in the Software without restriction, including
         | 
| 6 | 
            +
            without limitation the rights to use, copy, modify, merge, publish,
         | 
| 7 | 
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         | 
| 8 | 
            +
            permit persons to whom the Software is furnished to do so, subject to
         | 
| 9 | 
            +
            the following conditions:
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            The above copyright notice and this permission notice shall be
         | 
| 12 | 
            +
            included in all copies or substantial portions of the Software.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         | 
| 15 | 
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         | 
| 16 | 
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         | 
| 17 | 
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
         | 
| 18 | 
            +
            LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
         | 
| 19 | 
            +
            OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
         | 
| 20 | 
            +
            WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         | 
    
        data/README.rdoc
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            ## 
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Make load and performance a fun sport.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Run a sprint from around the world
         | 
| 6 | 
            +
            * Rush your API and website to scale it out
         | 
| 7 | 
            +
            * Condition your site around the clock
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ## Getting started
         | 
| 10 | 
            +
            Login to [blitz.io](http://blitz.io) and in the blitz bar type:
         | 
| 11 | 
            +
                --api-key
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            Now
         | 
| 14 | 
            +
                gem install blitz
         | 
| 15 | 
            +
                
         | 
| 16 | 
            +
            and run a sprint like this:
         | 
| 17 | 
            +
                blitz curl --region california http://blitz.io
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
            and you can rush like this:
         | 
| 20 | 
            +
                blitz curl --region california --pattern 1-100:60 http://blitz.io
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            Copyright (c) 2011 Mu Dynamics. See LICENSE.txt for further details.
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
            require 'bundler'
         | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              Bundler.setup(:default, :development)
         | 
| 7 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 8 | 
            +
              $stderr.puts e.message
         | 
| 9 | 
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 10 | 
            +
              exit e.status_code
         | 
| 11 | 
            +
            end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require 'rake'
         | 
| 14 | 
            +
            require 'jeweler'
         | 
| 15 | 
            +
            require 'blitz'
         | 
| 16 | 
            +
            Jeweler::Tasks.new do |gem|
         | 
| 17 | 
            +
              # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
         | 
| 18 | 
            +
              gem.name = "blitz"
         | 
| 19 | 
            +
              gem.homepage = "http://blitz.io"
         | 
| 20 | 
            +
              gem.license = "MIT"
         | 
| 21 | 
            +
              gem.summary = %Q{Make load and performance testing a fun sport}
         | 
| 22 | 
            +
              gem.description = %Q{Make load and performance testing a fun sport}
         | 
| 23 | 
            +
              gem.email = "kowsik@gmail.com"
         | 
| 24 | 
            +
              gem.authors = ["pcapr"]
         | 
| 25 | 
            +
              gem.version = Blitz::Version
         | 
| 26 | 
            +
              gem.executables = ['blitz']
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              # Include your dependencies below. Runtime dependencies are required when using your gem,
         | 
| 29 | 
            +
              # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
         | 
| 30 | 
            +
              #  gem.add_runtime_dependency 'jabber4r', '> 0.1'
         | 
| 31 | 
            +
              #  gem.add_development_dependency 'rspec', '> 1.2.3'
         | 
| 32 | 
            +
            end
         | 
| 33 | 
            +
            Jeweler::RubygemsDotOrgTasks.new
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            require 'rake/testtask'
         | 
| 36 | 
            +
            Rake::TestTask.new(:test) do |test|
         | 
| 37 | 
            +
              test.libs << 'lib' << 'test'
         | 
| 38 | 
            +
              test.pattern = 'test/**/test_*.rb'
         | 
| 39 | 
            +
              test.verbose = true
         | 
| 40 | 
            +
            end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            task :default => :test
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            require 'rake/rdoctask'
         | 
| 45 | 
            +
            Rake::RDocTask.new do |rdoc|
         | 
| 46 | 
            +
              rdoc.rdoc_dir = 'rdoc'
         | 
| 47 | 
            +
              rdoc.title = "blitz #{Blitz::Version}"
         | 
| 48 | 
            +
              rdoc.rdoc_files.include('README*')
         | 
| 49 | 
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         | 
| 50 | 
            +
            end
         | 
| 51 | 
            +
             | 
    
        data/bin/blitz
    ADDED
    
    | @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
         | 
| 4 | 
            +
            $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'blitz'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            argv = ARGV.dup
         | 
| 9 | 
            +
            ARGV.clear
         | 
| 10 | 
            +
            cmd = argv.shift.strip rescue 'help'
         | 
| 11 | 
            +
            Blitz.run cmd, argv
         | 
    
        data/blitz.gemspec
    ADDED
    
    | @@ -0,0 +1,80 @@ | |
| 1 | 
            +
            # Generated by jeweler
         | 
| 2 | 
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         | 
| 4 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |s|
         | 
| 7 | 
            +
              s.name = %q{blitz}
         | 
| 8 | 
            +
              s.version = "0.1.0"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 | 
            +
              s.authors = ["pcapr"]
         | 
| 12 | 
            +
              s.date = %q{2011-03-10}
         | 
| 13 | 
            +
              s.default_executable = %q{blitz}
         | 
| 14 | 
            +
              s.description = %q{Make load and performance testing a fun sport}
         | 
| 15 | 
            +
              s.email = %q{kowsik@gmail.com}
         | 
| 16 | 
            +
              s.executables = ["blitz"]
         | 
| 17 | 
            +
              s.extra_rdoc_files = [
         | 
| 18 | 
            +
                "LICENSE.txt",
         | 
| 19 | 
            +
                "README.rdoc"
         | 
| 20 | 
            +
              ]
         | 
| 21 | 
            +
              s.files = [
         | 
| 22 | 
            +
                ".document",
         | 
| 23 | 
            +
                "Gemfile",
         | 
| 24 | 
            +
                "Gemfile.lock",
         | 
| 25 | 
            +
                "LICENSE.txt",
         | 
| 26 | 
            +
                "README.rdoc",
         | 
| 27 | 
            +
                "Rakefile",
         | 
| 28 | 
            +
                "bin/blitz",
         | 
| 29 | 
            +
                "blitz.gemspec",
         | 
| 30 | 
            +
                "lib/blitz.rb",
         | 
| 31 | 
            +
                "lib/blitz/client.rb",
         | 
| 32 | 
            +
                "lib/blitz/command.rb",
         | 
| 33 | 
            +
                "lib/blitz/command/api.rb",
         | 
| 34 | 
            +
                "lib/blitz/command/curl.rb",
         | 
| 35 | 
            +
                "lib/blitz/command/help.rb",
         | 
| 36 | 
            +
                "lib/blitz/curl/error.rb",
         | 
| 37 | 
            +
                "lib/blitz/curl/sprint.rb",
         | 
| 38 | 
            +
                "lib/blitz/helper.rb",
         | 
| 39 | 
            +
                "test/helper.rb",
         | 
| 40 | 
            +
                "test/test_blitz.rb"
         | 
| 41 | 
            +
              ]
         | 
| 42 | 
            +
              s.homepage = %q{http://blitz.io}
         | 
| 43 | 
            +
              s.licenses = ["MIT"]
         | 
| 44 | 
            +
              s.require_paths = ["lib"]
         | 
| 45 | 
            +
              s.rubygems_version = %q{1.3.7}
         | 
| 46 | 
            +
              s.summary = %q{Make load and performance testing a fun sport}
         | 
| 47 | 
            +
              s.test_files = [
         | 
| 48 | 
            +
                "test/helper.rb",
         | 
| 49 | 
            +
                "test/test_blitz.rb"
         | 
| 50 | 
            +
              ]
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              if s.respond_to? :specification_version then
         | 
| 53 | 
            +
                current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
         | 
| 54 | 
            +
                s.specification_version = 3
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 57 | 
            +
                  s.add_runtime_dependency(%q<rest-client>, ["~> 1.6.1"])
         | 
| 58 | 
            +
                  s.add_runtime_dependency(%q<json>, ["~> 1.4.6"])
         | 
| 59 | 
            +
                  s.add_runtime_dependency(%q<json_pure>, ["~> 1.4.6"])
         | 
| 60 | 
            +
                  s.add_runtime_dependency(%q<hexy>, ["~> 0.1.1"])
         | 
| 61 | 
            +
                  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 62 | 
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
         | 
| 63 | 
            +
                else
         | 
| 64 | 
            +
                  s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
         | 
| 65 | 
            +
                  s.add_dependency(%q<json>, ["~> 1.4.6"])
         | 
| 66 | 
            +
                  s.add_dependency(%q<json_pure>, ["~> 1.4.6"])
         | 
| 67 | 
            +
                  s.add_dependency(%q<hexy>, ["~> 0.1.1"])
         | 
| 68 | 
            +
                  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 69 | 
            +
                  s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              else
         | 
| 72 | 
            +
                s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
         | 
| 73 | 
            +
                s.add_dependency(%q<json>, ["~> 1.4.6"])
         | 
| 74 | 
            +
                s.add_dependency(%q<json_pure>, ["~> 1.4.6"])
         | 
| 75 | 
            +
                s.add_dependency(%q<hexy>, ["~> 0.1.1"])
         | 
| 76 | 
            +
                s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 77 | 
            +
                s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
| 80 | 
            +
             | 
    
        data/lib/blitz.rb
    ADDED
    
    | @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'hexy'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Blitz
         | 
| 5 | 
            +
                require 'blitz/helper'
         | 
| 6 | 
            +
                Version = "0.1.0".freeze
         | 
| 7 | 
            +
                    
         | 
| 8 | 
            +
                extend Blitz::Helper
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                def self.run cmd, argv
         | 
| 11 | 
            +
                    kname, mname = cmd.split(':', 2)
         | 
| 12 | 
            +
                    klass = Blitz::Command.const_get kname.capitalize rescue nil
         | 
| 13 | 
            +
                    mname ||= 'default'
         | 
| 14 | 
            +
                    mname = "cmd_#{mname}".to_sym
         | 
| 15 | 
            +
                    if klass and klass < Blitz::Command and klass.method_defined? mname
         | 
| 16 | 
            +
                        command = klass.new
         | 
| 17 | 
            +
                        begin
         | 
| 18 | 
            +
                            command.send mname, argv
         | 
| 19 | 
            +
                        rescue Test::Unit::AssertionFailedError, ArgumentError => e
         | 
| 20 | 
            +
                            error e.message.chomp('.')
         | 
| 21 | 
            +
                        end
         | 
| 22 | 
            +
                    else
         | 
| 23 | 
            +
                        error "Unknown command #{cmd}"
         | 
| 24 | 
            +
                    end        
         | 
| 25 | 
            +
                end    
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            require 'blitz/client'
         | 
| 29 | 
            +
            require 'blitz/curl/error'
         | 
| 30 | 
            +
            require 'blitz/curl/sprint'
         | 
| 31 | 
            +
            require 'blitz/command'
         | 
    
        data/lib/blitz/client.rb
    ADDED
    
    | @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'json/pure'
         | 
| 3 | 
            +
            require 'restclient'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class Blitz
         | 
| 6 | 
            +
            class Client
         | 
| 7 | 
            +
                attr_reader :blitz
         | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                def initialize user, apik, host='blitz.io'
         | 
| 10 | 
            +
                    scheme = host.index('localhost') ? 'http' : 'https'
         | 
| 11 | 
            +
                    @blitz = RestClient::Resource.new "#{scheme}://#{host}", \
         | 
| 12 | 
            +
                        :headers => {
         | 
| 13 | 
            +
                            :x_api_user => user,
         | 
| 14 | 
            +
                            :x_api_key => apik,
         | 
| 15 | 
            +
                            :x_gem_version => ::Blitz::Version
         | 
| 16 | 
            +
                        }
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                def curl_execute data
         | 
| 20 | 
            +
                    JSON.parse blitz['/api/1/curl/execute'].post(data.to_json)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                def login
         | 
| 24 | 
            +
                    JSON.parse blitz['/login/api'].get
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                
         | 
| 27 | 
            +
                def job_status job_id
         | 
| 28 | 
            +
                    JSON.parse blitz["/api/1/jobs/#{job_id}/status"].get
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                def abort_job job_id
         | 
| 32 | 
            +
                    JSON.parse blitz["/api/1/jobs/#{job_id}/abort"].put ''
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
            end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            require 'test/unit/assertions'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # The default template string contains what was sent and received. Strip 
         | 
| 4 | 
            +
            # these out since we don't need them
         | 
| 5 | 
            +
            class Test::Unit::Assertions::AssertionMessage
         | 
| 6 | 
            +
                alias :old_template :template
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                def template
         | 
| 9 | 
            +
                    @template_string = ''
         | 
| 10 | 
            +
                    @parameters = []
         | 
| 11 | 
            +
                    old_template
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class Blitz
         | 
| 16 | 
            +
            class Command
         | 
| 17 | 
            +
                include Test::Unit::Assertions
         | 
| 18 | 
            +
                include Helper
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
            end # Blitz
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            Dir["#{File.dirname(__FILE__)}/command/*.rb"].each { |c| require c }
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            class Blitz
         | 
| 2 | 
            +
            class Command
         | 
| 3 | 
            +
            class API < Command
         | 
| 4 | 
            +
                attr_accessor :credentials
         | 
| 5 | 
            +
                    
         | 
| 6 | 
            +
                def cmd_init argv
         | 
| 7 | 
            +
                    FileUtils.rm credentials_file rescue nil
         | 
| 8 | 
            +
                    API.client
         | 
| 9 | 
            +
                    
         | 
| 10 | 
            +
                    msg "You are now ready to blitz!"
         | 
| 11 | 
            +
                    msg "Try blitz help to learn more about the commands."
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
                
         | 
| 14 | 
            +
                def client
         | 
| 15 | 
            +
                    get_credentials
         | 
| 16 | 
            +
                    Blitz::Client.new(user, password, host)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                def user
         | 
| 20 | 
            +
                    get_credentials
         | 
| 21 | 
            +
                    @credentials[0]
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                
         | 
| 24 | 
            +
                def password
         | 
| 25 | 
            +
                    get_credentials
         | 
| 26 | 
            +
                    @credentials[1]
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                
         | 
| 29 | 
            +
                def host
         | 
| 30 | 
            +
                    ENV['BLITZ_HOST'] || 'blitz.io'
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                
         | 
| 33 | 
            +
                def credentials_file
         | 
| 34 | 
            +
                    ENV['HOME'] + '/.blitz/credentials'
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
                
         | 
| 37 | 
            +
                def get_credentials
         | 
| 38 | 
            +
                    return if @credentials
         | 
| 39 | 
            +
                    unless @credentials = read_credentials
         | 
| 40 | 
            +
                        @credentials = ask_for_credentials
         | 
| 41 | 
            +
                        save_credentials
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    @credentials
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
                
         | 
| 46 | 
            +
                def read_credentials
         | 
| 47 | 
            +
                    File.exists?(credentials_file) and File.read(credentials_file).split("\n")        
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
                
         | 
| 50 | 
            +
                def ask_for_credentials
         | 
| 51 | 
            +
                    msg "Enter your blitz credentials."
         | 
| 52 | 
            +
                    print "User-ID: "
         | 
| 53 | 
            +
                    user = ask
         | 
| 54 | 
            +
                    print "API-Key: "
         | 
| 55 | 
            +
                    apik = ask
         | 
| 56 | 
            +
                    apik2 = Blitz::Client.new(user, apik, host).login['api_key']
         | 
| 57 | 
            +
                    if not apik2
         | 
| 58 | 
            +
                        error "Authentication failed"
         | 
| 59 | 
            +
                        exit 1
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                    
         | 
| 62 | 
            +
                    [ user, apik2 ]
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
                
         | 
| 65 | 
            +
                def save_credentials
         | 
| 66 | 
            +
                    write_credentials
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
                
         | 
| 69 | 
            +
                def write_credentials
         | 
| 70 | 
            +
                    FileUtils.mkdir_p(File.dirname(credentials_file))
         | 
| 71 | 
            +
                    File.open(credentials_file, 'w') do |f|
         | 
| 72 | 
            +
                      f.puts self.credentials
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                    set_credentials_permissions
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
                
         | 
| 77 | 
            +
                def set_credentials_permissions
         | 
| 78 | 
            +
                    FileUtils.chmod 0700, File.dirname(credentials_file)
         | 
| 79 | 
            +
                    FileUtils.chmod 0600, credentials_file        
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
                
         | 
| 82 | 
            +
                def self.instance
         | 
| 83 | 
            +
                    @instance ||= API.new
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
                
         | 
| 86 | 
            +
                def self.client
         | 
| 87 | 
            +
                    self.instance.client
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
                
         | 
| 90 | 
            +
                private
         | 
| 91 | 
            +
                def initialize
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
            end
         | 
| 94 | 
            +
            Api = API
         | 
| 95 | 
            +
            end # Command
         | 
| 96 | 
            +
            end # Blitz
         | 
| @@ -0,0 +1,272 @@ | |
| 1 | 
            +
            class Blitz
         | 
| 2 | 
            +
            class Command
         | 
| 3 | 
            +
            class Curl < Command
         | 
| 4 | 
            +
                def cmd_help argv
         | 
| 5 | 
            +
                    help
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def cmd_run argv
         | 
| 9 | 
            +
                    args = parse_cli argv
         | 
| 10 | 
            +
                    if args['help']
         | 
| 11 | 
            +
                        return help
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    if not args['pattern']
         | 
| 15 | 
            +
                        sprint args
         | 
| 16 | 
            +
                        return
         | 
| 17 | 
            +
                    else
         | 
| 18 | 
            +
                        error "Rushing not supported yet, but coming soon"
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                alias_method :cmd_default, :cmd_run
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                private
         | 
| 25 | 
            +
                def authorize_error e
         | 
| 26 | 
            +
                    base_url = "#{e.scheme}://#{e.host}:#{e.port}"
         | 
| 27 | 
            +
                    puts
         | 
| 28 | 
            +
                    error "You haven't verified that you are the devops dude for #{e.host}"
         | 
| 29 | 
            +
                    error ""
         | 
| 30 | 
            +
                    error "Make sure the following URL is reachable by us and returns the value 42."
         | 
| 31 | 
            +
                    error "#{base_url}/#{e.uuid}"
         | 
| 32 | 
            +
                    error ""
         | 
| 33 | 
            +
                    error "If your app is RESTfully built with sinatra or rails, simply"
         | 
| 34 | 
            +
                    error "add a route like so:"
         | 
| 35 | 
            +
                    error ""
         | 
| 36 | 
            +
                    error "get '/#{e.uuid}' do"
         | 
| 37 | 
            +
                    error "    '42'"
         | 
| 38 | 
            +
                    error "end"
         | 
| 39 | 
            +
                    error ""
         | 
| 40 | 
            +
                    error "And we'll be on our merry way to blitz #{e.host}"
         | 
| 41 | 
            +
                    puts
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def sprint args
         | 
| 45 | 
            +
                    begin
         | 
| 46 | 
            +
                        job = ::Blitz::Curl::Sprint.execute args
         | 
| 47 | 
            +
                        result = job.result
         | 
| 48 | 
            +
                        print_sprint_result args, result
         | 
| 49 | 
            +
                    rescue ::Blitz::Curl::Error::Authorize => e
         | 
| 50 | 
            +
                        authorize_error e
         | 
| 51 | 
            +
                    rescue ::Blitz::Curl::Error::Region => e
         | 
| 52 | 
            +
                        error "#{e.region}: #{e.message}"
         | 
| 53 | 
            +
                    rescue ::Blitz::Curl::Error => e
         | 
| 54 | 
            +
                        error e.message
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def print_sprint_result args, result
         | 
| 59 | 
            +
                    rtt = result.duration
         | 
| 60 | 
            +
            		if rtt < 1.0
         | 
| 61 | 
            +
            			rtt = (rtt * 1000).floor.to_s + ' ms';
         | 
| 62 | 
            +
            		else
         | 
| 63 | 
            +
            			rtt = ("%.2f" % rtt) + ' sec';
         | 
| 64 | 
            +
            		end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            		puts "-" * 70
         | 
| 67 | 
            +
                    msg "#{result.region}: Response time of #{rtt}"
         | 
| 68 | 
            +
                    unless args['dump-header'] or args['verbose']
         | 
| 69 | 
            +
                        msg "Try --verbose to see the request/response headers"
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
                    puts "-" * 70
         | 
| 72 | 
            +
                    puts
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    if args['dump-header'] or args['verbose']
         | 
| 75 | 
            +
                        puts "> " + result.request.line
         | 
| 76 | 
            +
                        result.request.headers.each_pair { |k, v| puts "> #{k}: #{v}\r\n" }
         | 
| 77 | 
            +
                        puts
         | 
| 78 | 
            +
                    
         | 
| 79 | 
            +
                        content = result.request.content
         | 
| 80 | 
            +
                        if not content.empty?
         | 
| 81 | 
            +
                            if /^[[:print:]]+$/ =~ content
         | 
| 82 | 
            +
                                puts content
         | 
| 83 | 
            +
                            else
         | 
| 84 | 
            +
                                puts Hexy.new(content).to_s
         | 
| 85 | 
            +
                            end
         | 
| 86 | 
            +
                            puts
         | 
| 87 | 
            +
                        end
         | 
| 88 | 
            +
                    
         | 
| 89 | 
            +
                        puts "< " + result.response.line
         | 
| 90 | 
            +
                        result.response.headers.each_pair { |k, v| puts "> #{k}: #{v}\r\n" }
         | 
| 91 | 
            +
                        puts
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
                    
         | 
| 94 | 
            +
                    content = result.response.content
         | 
| 95 | 
            +
                    if not content.empty?
         | 
| 96 | 
            +
                        if /^[[:print:]]+$/ =~ content
         | 
| 97 | 
            +
                            puts content
         | 
| 98 | 
            +
                        else
         | 
| 99 | 
            +
                            puts Hexy.new(content).to_s
         | 
| 100 | 
            +
                        end
         | 
| 101 | 
            +
                    end
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                def help
         | 
| 105 | 
            +
                    helps = [
         | 
| 106 | 
            +
                        { :short => '-A', :long => '--user-agent', :value => '<string>', :help => 'User-Agent to send to server' },
         | 
| 107 | 
            +
                        { :short => '-b', :long => '--cookie', :value => 'name=<string>', :help => 'Cookie to send to the server (multiple)' },
         | 
| 108 | 
            +
                        { :short => '-d', :long => '--data', :value => '<string>', :help => 'Data to send in a PUT or POST request' },
         | 
| 109 | 
            +
                        { :short => '-D', :long => '--dump-header', :value => '<file>', :help => 'Print the request/response headers' },
         | 
| 110 | 
            +
                        { :short => '-e', :long => '--referer', :value => '<string>', :help => 'Referer URL' },
         | 
| 111 | 
            +
                        { :short => '-h', :long => '--help', :value => '', :help => 'Help on command line options' },
         | 
| 112 | 
            +
                        { :short => '-H', :long => '--header', :value => '<string>', :help => 'Custom header to pass to server' },
         | 
| 113 | 
            +
                        { :short => '-p', :long => '--pattern', :value => '<s>-<e>:<d>', :help => 'Ramp from s to e concurrent requests in d secs' },
         | 
| 114 | 
            +
                        { :short => '-r', :long => '--region', :value => '<string>', :help => 'Choose one of california, virginia, singapore or ireland' },
         | 
| 115 | 
            +
                        { :short => '-s', :long => '--status', :value => '<number>', :help => 'Assert on the HTTP response status code' },
         | 
| 116 | 
            +
                        { :short => '-T', :long => '--timeout', :value => '<ms>', :help => 'Wait time for both connect and responses' },
         | 
| 117 | 
            +
                        { :short => '-u', :long => '--user', :value => '<user[:pass]>', :help => 'User and password for authentication' },
         | 
| 118 | 
            +
                        { :short => '-X', :long => '--request', :value => '<string>', :help => 'Request method to use (GET, HEAD, PUT, etc.)' },
         | 
| 119 | 
            +
                        { :short => '-v', :long => '--verbose', :value => '', :help => 'Print the request/response headers' },
         | 
| 120 | 
            +
                        { :short => '-1', :long => '--tlsv1', :value => '', :help => 'Use TLSv1 (SSL)' },
         | 
| 121 | 
            +
                        { :short => '-2', :long => '--sslv2', :value => '', :help => 'Use SSLv2 (SSL)' },
         | 
| 122 | 
            +
                        { :short => '-3', :long => '--sslv3', :value => '', :help => 'Use SSLv3 (SSL)' }
         | 
| 123 | 
            +
                    ]
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                    max_long_size = helps.inject(0) { |memo, obj| [ obj[:long].size, memo ].max }
         | 
| 126 | 
            +
                    max_value_size = helps.inject(0) { |memo, obj| [ obj[:value].size, memo ].max }
         | 
| 127 | 
            +
                    puts
         | 
| 128 | 
            +
                    msg "Usage: blitz curl <options> <url>"
         | 
| 129 | 
            +
                    puts
         | 
| 130 | 
            +
                    helps.each do |h|
         | 
| 131 | 
            +
                        msg "%-*s %*s %-*s %s" % [max_long_size, h[:long], 2, h[:short], max_value_size, h[:value], h[:help]]
         | 
| 132 | 
            +
                    end
         | 
| 133 | 
            +
                    puts
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                def parse_cli argv
         | 
| 137 | 
            +
                    hash = Hash.new
         | 
| 138 | 
            +
                    while not argv.empty?
         | 
| 139 | 
            +
                        break if argv.first[0,1] != '-'
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                        k = argv.shift
         | 
| 142 | 
            +
                        if [ '-A', '--user-agent' ].member? k
         | 
| 143 | 
            +
                            hash['user-agent'] = shift(k, argv)
         | 
| 144 | 
            +
                            next
         | 
| 145 | 
            +
                        end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                        if [ '-b', '--cookie' ].member? k
         | 
| 148 | 
            +
                            # TODO: support cookie jars
         | 
| 149 | 
            +
                            hash['cookies'] ||= []
         | 
| 150 | 
            +
                            hash['cookies'] << shift(k, argv)
         | 
| 151 | 
            +
                            next
         | 
| 152 | 
            +
                        end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                        if [ '-d', '--data' ].member? k
         | 
| 155 | 
            +
                            hash['content'] ||= Hash.new
         | 
| 156 | 
            +
                            hash['content']['data'] ||= []
         | 
| 157 | 
            +
                            v = shift(k, argv)
         | 
| 158 | 
            +
                            v = File.read v[1..-1] if v =~ /^@/
         | 
| 159 | 
            +
                            hash['content']['data'] << v
         | 
| 160 | 
            +
                            next
         | 
| 161 | 
            +
                        end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                        if [ '-D', '--dump-header' ].member? k
         | 
| 164 | 
            +
                            hash['dump-header'] = shift(k, argv)
         | 
| 165 | 
            +
                            next
         | 
| 166 | 
            +
                        end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                        if [ '-e', '--referer'].member? k
         | 
| 169 | 
            +
                            hash['referer'] = shift(k, argv)
         | 
| 170 | 
            +
                            next
         | 
| 171 | 
            +
                        end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                        if [ '-h', '--help' ].member? k
         | 
| 174 | 
            +
                            hash['help'] = true
         | 
| 175 | 
            +
                            next
         | 
| 176 | 
            +
                        end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                        if [ '-H', '--header' ].member? k
         | 
| 179 | 
            +
                            hash['headers'] ||= []
         | 
| 180 | 
            +
                            hash['headers'].push shift(k, argv)
         | 
| 181 | 
            +
                            next
         | 
| 182 | 
            +
                        end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                        if [ '-p', '--pattern' ].member? k
         | 
| 185 | 
            +
                            v = shift(k, argv)
         | 
| 186 | 
            +
                            if not /^(\d+)-(\d+):(\d+)$/ =~ v
         | 
| 187 | 
            +
                                raise Test::Unit::AssertionFailedError, "invalid ramp pattern"
         | 
| 188 | 
            +
                            end
         | 
| 189 | 
            +
                            hash['pattern'] = {
         | 
| 190 | 
            +
                                'iterations' => 1,
         | 
| 191 | 
            +
                                'intervals' => [{
         | 
| 192 | 
            +
                                    'iterations' => 1,
         | 
| 193 | 
            +
                                    'start' => $1.to_i,
         | 
| 194 | 
            +
                                    'end' => $2.to_i,
         | 
| 195 | 
            +
                                    'duration' => $3.to_i
         | 
| 196 | 
            +
                                }]
         | 
| 197 | 
            +
                            }
         | 
| 198 | 
            +
                            next
         | 
| 199 | 
            +
                        end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                        if [ '-r', '--region' ].member? k
         | 
| 202 | 
            +
                            v = shift(k, argv)
         | 
| 203 | 
            +
                            assert_match(/^california|virginia|singapore|ireland|japan$/, v, 'region must be one of california, virginia, singapore, japan or ireland')
         | 
| 204 | 
            +
                            hash['region'] = v
         | 
| 205 | 
            +
                            next
         | 
| 206 | 
            +
                        end
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                        if [ '-s', '--status' ].member? k
         | 
| 209 | 
            +
                            hash['status'] = shift(k, argv).to_i
         | 
| 210 | 
            +
                            next
         | 
| 211 | 
            +
                        end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                        if [ '-T', '--timeout' ].member? k
         | 
| 214 | 
            +
                            hash['timeout'] = shift(k, argv).to_i
         | 
| 215 | 
            +
                            next
         | 
| 216 | 
            +
                        end
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                        if [ '-u', '--user' ].member? k
         | 
| 219 | 
            +
                            hash['user'] = shift(k, argv)
         | 
| 220 | 
            +
                            next
         | 
| 221 | 
            +
                        end
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                        if [ '-X', '--request' ].member? k
         | 
| 224 | 
            +
                            hash['request'] = shift(k, argv)
         | 
| 225 | 
            +
                            next
         | 
| 226 | 
            +
                        end
         | 
| 227 | 
            +
                        
         | 
| 228 | 
            +
                        if [ '-v', '--verbose' ].member? k
         | 
| 229 | 
            +
                            hash['verbose'] = true
         | 
| 230 | 
            +
                            next
         | 
| 231 | 
            +
                        end
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                        if [ '-1', '--tlsv1' ].member? k
         | 
| 234 | 
            +
                            hash['ssl'] = 'tlsv1'
         | 
| 235 | 
            +
                            next
         | 
| 236 | 
            +
                        end
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                        if [ '-2', '--sslv2' ].member? k
         | 
| 239 | 
            +
                            hash['ssl'] = 'sslv2'
         | 
| 240 | 
            +
                            next
         | 
| 241 | 
            +
                        end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                        if [ '-3', '--sslv3' ].member? k
         | 
| 244 | 
            +
                            hash['ssl'] = 'sslv2'
         | 
| 245 | 
            +
                            next
         | 
| 246 | 
            +
                        end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                        raise ArgumentError, "Unknown option #{k}"
         | 
| 249 | 
            +
                    end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                    if not hash['help']
         | 
| 252 | 
            +
                        url = argv.shift
         | 
| 253 | 
            +
                        assert_not_nil(url, 'no URL specified!')
         | 
| 254 | 
            +
                        hash['url'] = url
         | 
| 255 | 
            +
                    end
         | 
| 256 | 
            +
                    
         | 
| 257 | 
            +
                    if hash.member? 'content'
         | 
| 258 | 
            +
                        data_size = hash['content']['data'].inject(0) { |m, v| m + v.size }
         | 
| 259 | 
            +
                        assert(data_size < 10*1024, "POST content must be < 10K")
         | 
| 260 | 
            +
                    end
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                    hash
         | 
| 263 | 
            +
                end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                def shift key, argv
         | 
| 266 | 
            +
                    val = argv.shift
         | 
| 267 | 
            +
                    assert_not_nil(val, "missing value for #{key}")
         | 
| 268 | 
            +
                    val
         | 
| 269 | 
            +
                end
         | 
| 270 | 
            +
            end # Curl
         | 
| 271 | 
            +
            end # Command
         | 
| 272 | 
            +
            end # Blitz
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            class Blitz
         | 
| 2 | 
            +
            class Command
         | 
| 3 | 
            +
            class Help < Command
         | 
| 4 | 
            +
                def cmd_default argv
         | 
| 5 | 
            +
                    puts
         | 
| 6 | 
            +
                    msg "Usage: blitz <command> <options>"
         | 
| 7 | 
            +
                    helps = [
         | 
| 8 | 
            +
                        { :cmd => 'help', :help => "Display this help" },
         | 
| 9 | 
            +
                        { :cmd => 'api:init', :help => 'Validate your API key' },
         | 
| 10 | 
            +
                        { :cmd => 'curl', :help => 'Run a sprint or a rush' },
         | 
| 11 | 
            +
                        { :cmd => 'curl:help', :help => 'Show help on sprint and rushing' }
         | 
| 12 | 
            +
                    ]
         | 
| 13 | 
            +
                    
         | 
| 14 | 
            +
                    max_cmd_size = helps.inject(0) { |memo, obj| [ obj[:cmd].size, memo ].max } + 4
         | 
| 15 | 
            +
                    helps.each do |h|
         | 
| 16 | 
            +
                        msg "%*s - %s" % [max_cmd_size, h[:cmd], h[:help]]
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                    puts
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
            end # Command
         | 
| 22 | 
            +
            end # Blitz
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            class Blitz
         | 
| 2 | 
            +
            module Curl
         | 
| 3 | 
            +
            class Error < StandardError
         | 
| 4 | 
            +
                def initialize json={}
         | 
| 5 | 
            +
                    super json['reason'] || "Hmmm, something went wrong. Try again in a little bit?"
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
                
         | 
| 8 | 
            +
                class Authorize < Error
         | 
| 9 | 
            +
                    attr_reader :scheme, :host, :port, :uuid
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize json
         | 
| 12 | 
            +
                        @scheme = json['scheme']
         | 
| 13 | 
            +
                        @host   = json['host']
         | 
| 14 | 
            +
                        @port   = json['port']
         | 
| 15 | 
            +
                        @uuid   = json['uuid']
         | 
| 16 | 
            +
                        super
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                class Region < Error
         | 
| 21 | 
            +
                    attr_reader :region
         | 
| 22 | 
            +
                    
         | 
| 23 | 
            +
                    def initialize json
         | 
| 24 | 
            +
                        @region = json['region']
         | 
| 25 | 
            +
                        super
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                
         | 
| 29 | 
            +
                class DNS < Region
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                class Connect < Region
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
                
         | 
| 35 | 
            +
                class Timeout < Region
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                class Parse < Region
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
                
         | 
| 41 | 
            +
                class Status < Region
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
            end
         | 
| 44 | 
            +
            end # Curl
         | 
| 45 | 
            +
            end # Blitz
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            class Blitz
         | 
| 2 | 
            +
            module Curl 
         | 
| 3 | 
            +
            class Sprint
         | 
| 4 | 
            +
                class Request
         | 
| 5 | 
            +
                    attr_reader :line
         | 
| 6 | 
            +
                    attr_reader :method
         | 
| 7 | 
            +
                    attr_reader :url
         | 
| 8 | 
            +
                    attr_reader :headers
         | 
| 9 | 
            +
                    attr_reader :content
         | 
| 10 | 
            +
                    
         | 
| 11 | 
            +
                    def initialize json
         | 
| 12 | 
            +
                        @line = json['line']
         | 
| 13 | 
            +
                        @method = json['method']
         | 
| 14 | 
            +
                        @url = json['url']
         | 
| 15 | 
            +
                        @content = json['content'].unpack('m')[0]
         | 
| 16 | 
            +
                        @headers = json['headers']
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                class Response
         | 
| 21 | 
            +
                    attr_reader :line
         | 
| 22 | 
            +
                    attr_reader :status
         | 
| 23 | 
            +
                    attr_reader :message
         | 
| 24 | 
            +
                    attr_reader :headers
         | 
| 25 | 
            +
                    attr_reader :content
         | 
| 26 | 
            +
                    
         | 
| 27 | 
            +
                    def initialize json
         | 
| 28 | 
            +
                        @line = json['line']
         | 
| 29 | 
            +
                        @status = json['status']
         | 
| 30 | 
            +
                        @message = json['message']
         | 
| 31 | 
            +
                        @content = json['content'].unpack('m')[0]
         | 
| 32 | 
            +
                        @headers = json['headers']
         | 
| 33 | 
            +
                    end        
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                
         | 
| 36 | 
            +
                class Result
         | 
| 37 | 
            +
                    attr_reader :region
         | 
| 38 | 
            +
                    attr_reader :duration
         | 
| 39 | 
            +
                    attr_reader :connect
         | 
| 40 | 
            +
                    attr_reader :request
         | 
| 41 | 
            +
                    attr_reader :response
         | 
| 42 | 
            +
                    
         | 
| 43 | 
            +
                    def initialize json
         | 
| 44 | 
            +
                        result = json['result']
         | 
| 45 | 
            +
                        @region = result['region']
         | 
| 46 | 
            +
                        @duration = result['duration']
         | 
| 47 | 
            +
                        @connect = result['connect']
         | 
| 48 | 
            +
                        @request = Request.new result['request']
         | 
| 49 | 
            +
                        @response = Response.new result['response']
         | 
| 50 | 
            +
                    end        
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
                
         | 
| 53 | 
            +
                def self.execute args
         | 
| 54 | 
            +
                    args.delete 'pattern'
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    res = Command::API.client.curl_execute args
         | 
| 57 | 
            +
                    raise Error.new(res) if res['error']
         | 
| 58 | 
            +
                    return self.new res['job_id']
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
                
         | 
| 61 | 
            +
                attr_reader :job_id
         | 
| 62 | 
            +
                
         | 
| 63 | 
            +
                def initialize job_id
         | 
| 64 | 
            +
                    @job_id = job_id
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
                
         | 
| 67 | 
            +
                def result
         | 
| 68 | 
            +
                    while true
         | 
| 69 | 
            +
                        sleep 2.0
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                        job = Command::API.client.job_status job_id
         | 
| 72 | 
            +
                        if job['error']
         | 
| 73 | 
            +
                            raise Error
         | 
| 74 | 
            +
                        end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                        result = job['result']
         | 
| 77 | 
            +
                        next if job['status'] == 'queued'
         | 
| 78 | 
            +
                        next if job['status'] == 'running' and not result
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                        raise Error if not result
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                        error = result['error']
         | 
| 83 | 
            +
                        if error
         | 
| 84 | 
            +
                            if error == 'dns'
         | 
| 85 | 
            +
                                raise Error::DNS.new(result)
         | 
| 86 | 
            +
                            elsif error == 'connect'
         | 
| 87 | 
            +
                                raise Error::Connect.new(result)
         | 
| 88 | 
            +
                            elsif error == 'timeout'
         | 
| 89 | 
            +
                                raise Error::Timeout.new(result)
         | 
| 90 | 
            +
                            elsif error == 'parse'
         | 
| 91 | 
            +
                                raise Error::Parse.new(result)
         | 
| 92 | 
            +
                            elsif result['assert'] == 0
         | 
| 93 | 
            +
                                raise Error::Status.new(result)
         | 
| 94 | 
            +
                            else
         | 
| 95 | 
            +
                                raise Error
         | 
| 96 | 
            +
                            end
         | 
| 97 | 
            +
                        end
         | 
| 98 | 
            +
                        
         | 
| 99 | 
            +
                        return Result.new(job)
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                def abort
         | 
| 104 | 
            +
                    Command::API.client.abort_job job_id rescue nil
         | 
| 105 | 
            +
                end    
         | 
| 106 | 
            +
            end
         | 
| 107 | 
            +
            end # Curl
         | 
| 108 | 
            +
            end # Blitz
         | 
    
        data/lib/blitz/helper.rb
    ADDED
    
    
    
        data/test/helper.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'bundler'
         | 
| 3 | 
            +
            begin
         | 
| 4 | 
            +
                Bundler.setup(:default, :development)
         | 
| 5 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 6 | 
            +
                $stderr.puts e.message
         | 
| 7 | 
            +
                $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 8 | 
            +
                exit e.status_code
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
            require 'test/unit'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            $LOAD_PATH.unshift(File.dirname(__FILE__))
         | 
| 13 | 
            +
            $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
         | 
| 14 | 
            +
            require 'blitz'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            class Test::Unit::TestCase
         | 
| 17 | 
            +
            end
         | 
    
        data/test/test_blitz.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | @@ -0,0 +1,182 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification 
         | 
| 2 | 
            +
            name: blitz
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            +
              hash: 27
         | 
| 5 | 
            +
              prerelease: false
         | 
| 6 | 
            +
              segments: 
         | 
| 7 | 
            +
              - 0
         | 
| 8 | 
            +
              - 1
         | 
| 9 | 
            +
              - 0
         | 
| 10 | 
            +
              version: 0.1.0
         | 
| 11 | 
            +
            platform: ruby
         | 
| 12 | 
            +
            authors: 
         | 
| 13 | 
            +
            - pcapr
         | 
| 14 | 
            +
            autorequire: 
         | 
| 15 | 
            +
            bindir: bin
         | 
| 16 | 
            +
            cert_chain: []
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            date: 2011-03-10 00:00:00 -08:00
         | 
| 19 | 
            +
            default_executable: blitz
         | 
| 20 | 
            +
            dependencies: 
         | 
| 21 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 22 | 
            +
              type: :runtime
         | 
| 23 | 
            +
              prerelease: false
         | 
| 24 | 
            +
              name: rest-client
         | 
| 25 | 
            +
              version_requirements: &id001 !ruby/object:Gem::Requirement 
         | 
| 26 | 
            +
                none: false
         | 
| 27 | 
            +
                requirements: 
         | 
| 28 | 
            +
                - - ~>
         | 
| 29 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 30 | 
            +
                    hash: 13
         | 
| 31 | 
            +
                    segments: 
         | 
| 32 | 
            +
                    - 1
         | 
| 33 | 
            +
                    - 6
         | 
| 34 | 
            +
                    - 1
         | 
| 35 | 
            +
                    version: 1.6.1
         | 
| 36 | 
            +
              requirement: *id001
         | 
| 37 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 38 | 
            +
              type: :runtime
         | 
| 39 | 
            +
              prerelease: false
         | 
| 40 | 
            +
              name: json
         | 
| 41 | 
            +
              version_requirements: &id002 !ruby/object:Gem::Requirement 
         | 
| 42 | 
            +
                none: false
         | 
| 43 | 
            +
                requirements: 
         | 
| 44 | 
            +
                - - ~>
         | 
| 45 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 46 | 
            +
                    hash: 11
         | 
| 47 | 
            +
                    segments: 
         | 
| 48 | 
            +
                    - 1
         | 
| 49 | 
            +
                    - 4
         | 
| 50 | 
            +
                    - 6
         | 
| 51 | 
            +
                    version: 1.4.6
         | 
| 52 | 
            +
              requirement: *id002
         | 
| 53 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 54 | 
            +
              type: :runtime
         | 
| 55 | 
            +
              prerelease: false
         | 
| 56 | 
            +
              name: json_pure
         | 
| 57 | 
            +
              version_requirements: &id003 !ruby/object:Gem::Requirement 
         | 
| 58 | 
            +
                none: false
         | 
| 59 | 
            +
                requirements: 
         | 
| 60 | 
            +
                - - ~>
         | 
| 61 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 62 | 
            +
                    hash: 11
         | 
| 63 | 
            +
                    segments: 
         | 
| 64 | 
            +
                    - 1
         | 
| 65 | 
            +
                    - 4
         | 
| 66 | 
            +
                    - 6
         | 
| 67 | 
            +
                    version: 1.4.6
         | 
| 68 | 
            +
              requirement: *id003
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 70 | 
            +
              type: :runtime
         | 
| 71 | 
            +
              prerelease: false
         | 
| 72 | 
            +
              name: hexy
         | 
| 73 | 
            +
              version_requirements: &id004 !ruby/object:Gem::Requirement 
         | 
| 74 | 
            +
                none: false
         | 
| 75 | 
            +
                requirements: 
         | 
| 76 | 
            +
                - - ~>
         | 
| 77 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 78 | 
            +
                    hash: 25
         | 
| 79 | 
            +
                    segments: 
         | 
| 80 | 
            +
                    - 0
         | 
| 81 | 
            +
                    - 1
         | 
| 82 | 
            +
                    - 1
         | 
| 83 | 
            +
                    version: 0.1.1
         | 
| 84 | 
            +
              requirement: *id004
         | 
| 85 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 86 | 
            +
              type: :development
         | 
| 87 | 
            +
              prerelease: false
         | 
| 88 | 
            +
              name: bundler
         | 
| 89 | 
            +
              version_requirements: &id005 !ruby/object:Gem::Requirement 
         | 
| 90 | 
            +
                none: false
         | 
| 91 | 
            +
                requirements: 
         | 
| 92 | 
            +
                - - ~>
         | 
| 93 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 94 | 
            +
                    hash: 23
         | 
| 95 | 
            +
                    segments: 
         | 
| 96 | 
            +
                    - 1
         | 
| 97 | 
            +
                    - 0
         | 
| 98 | 
            +
                    - 0
         | 
| 99 | 
            +
                    version: 1.0.0
         | 
| 100 | 
            +
              requirement: *id005
         | 
| 101 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 102 | 
            +
              type: :development
         | 
| 103 | 
            +
              prerelease: false
         | 
| 104 | 
            +
              name: jeweler
         | 
| 105 | 
            +
              version_requirements: &id006 !ruby/object:Gem::Requirement 
         | 
| 106 | 
            +
                none: false
         | 
| 107 | 
            +
                requirements: 
         | 
| 108 | 
            +
                - - ~>
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 110 | 
            +
                    hash: 1
         | 
| 111 | 
            +
                    segments: 
         | 
| 112 | 
            +
                    - 1
         | 
| 113 | 
            +
                    - 5
         | 
| 114 | 
            +
                    - 1
         | 
| 115 | 
            +
                    version: 1.5.1
         | 
| 116 | 
            +
              requirement: *id006
         | 
| 117 | 
            +
            description: Make load and performance testing a fun sport
         | 
| 118 | 
            +
            email: kowsik@gmail.com
         | 
| 119 | 
            +
            executables: 
         | 
| 120 | 
            +
            - blitz
         | 
| 121 | 
            +
            extensions: []
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            extra_rdoc_files: 
         | 
| 124 | 
            +
            - LICENSE.txt
         | 
| 125 | 
            +
            - README.rdoc
         | 
| 126 | 
            +
            files: 
         | 
| 127 | 
            +
            - .document
         | 
| 128 | 
            +
            - Gemfile
         | 
| 129 | 
            +
            - Gemfile.lock
         | 
| 130 | 
            +
            - LICENSE.txt
         | 
| 131 | 
            +
            - README.rdoc
         | 
| 132 | 
            +
            - Rakefile
         | 
| 133 | 
            +
            - bin/blitz
         | 
| 134 | 
            +
            - blitz.gemspec
         | 
| 135 | 
            +
            - lib/blitz.rb
         | 
| 136 | 
            +
            - lib/blitz/client.rb
         | 
| 137 | 
            +
            - lib/blitz/command.rb
         | 
| 138 | 
            +
            - lib/blitz/command/api.rb
         | 
| 139 | 
            +
            - lib/blitz/command/curl.rb
         | 
| 140 | 
            +
            - lib/blitz/command/help.rb
         | 
| 141 | 
            +
            - lib/blitz/curl/error.rb
         | 
| 142 | 
            +
            - lib/blitz/curl/sprint.rb
         | 
| 143 | 
            +
            - lib/blitz/helper.rb
         | 
| 144 | 
            +
            - test/helper.rb
         | 
| 145 | 
            +
            - test/test_blitz.rb
         | 
| 146 | 
            +
            has_rdoc: true
         | 
| 147 | 
            +
            homepage: http://blitz.io
         | 
| 148 | 
            +
            licenses: 
         | 
| 149 | 
            +
            - MIT
         | 
| 150 | 
            +
            post_install_message: 
         | 
| 151 | 
            +
            rdoc_options: []
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            require_paths: 
         | 
| 154 | 
            +
            - lib
         | 
| 155 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         | 
| 156 | 
            +
              none: false
         | 
| 157 | 
            +
              requirements: 
         | 
| 158 | 
            +
              - - ">="
         | 
| 159 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 160 | 
            +
                  hash: 3
         | 
| 161 | 
            +
                  segments: 
         | 
| 162 | 
            +
                  - 0
         | 
| 163 | 
            +
                  version: "0"
         | 
| 164 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         | 
| 165 | 
            +
              none: false
         | 
| 166 | 
            +
              requirements: 
         | 
| 167 | 
            +
              - - ">="
         | 
| 168 | 
            +
                - !ruby/object:Gem::Version 
         | 
| 169 | 
            +
                  hash: 3
         | 
| 170 | 
            +
                  segments: 
         | 
| 171 | 
            +
                  - 0
         | 
| 172 | 
            +
                  version: "0"
         | 
| 173 | 
            +
            requirements: []
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            rubyforge_project: 
         | 
| 176 | 
            +
            rubygems_version: 1.3.7
         | 
| 177 | 
            +
            signing_key: 
         | 
| 178 | 
            +
            specification_version: 3
         | 
| 179 | 
            +
            summary: Make load and performance testing a fun sport
         | 
| 180 | 
            +
            test_files: 
         | 
| 181 | 
            +
            - test/helper.rb
         | 
| 182 | 
            +
            - test/test_blitz.rb
         |