switchtower 0.10.0 → 1.0.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/lib/switchtower/actor.rb +51 -20
- data/lib/switchtower/cli.rb +1 -1
- data/lib/switchtower/command.rb +1 -2
- data/lib/switchtower/configuration.rb +49 -7
- data/lib/switchtower/extensions.rb +38 -0
- data/lib/switchtower/gateway.rb +15 -3
- data/lib/switchtower/generators/rails/deployment/templates/switchtower.rake +6 -2
- data/lib/switchtower/logger.rb +8 -5
- data/lib/switchtower/recipes/standard.rb +49 -10
- data/lib/switchtower/scm/base.rb +2 -2
- data/lib/switchtower/scm/baz.rb +118 -0
- data/lib/switchtower/scm/bzr.rb +70 -0
- data/lib/switchtower/scm/cvs.rb +57 -6
- data/lib/switchtower/scm/perforce.rb +139 -0
- data/lib/switchtower/scm/subversion.rb +8 -3
- data/lib/switchtower/transfer.rb +1 -1
- data/lib/switchtower/utils.rb +26 -0
- data/lib/switchtower/version.rb +3 -3
- data/test/actor_test.rb +34 -1
- data/test/configuration_test.rb +16 -1
- data/test/fixtures/custom.rb +3 -0
- data/test/scm/cvs_test.rb +24 -2
- data/test/scm/subversion_test.rb +17 -2
- data/test/utils.rb +8 -0
- metadata +9 -3
    
        data/lib/switchtower/transfer.rb
    CHANGED
    
    | @@ -58,7 +58,7 @@ module SwitchTower | |
| 58 58 | 
             
                      sftp = @actor.sessions[server].sftp
         | 
| 59 59 | 
             
                      sftp.connect unless sftp.state == :open
         | 
| 60 60 |  | 
| 61 | 
            -
                      sftp.open(@filename, IO::WRONLY | IO::CREAT, @params[:mode] || 0660) do |status, handle|
         | 
| 61 | 
            +
                      sftp.open(@filename, IO::WRONLY | IO::CREAT | IO::TRUNC, @params[:mode] || 0660) do |status, handle|
         | 
| 62 62 | 
             
                        break unless check_status("open #{@filename}", server, status)
         | 
| 63 63 |  | 
| 64 64 | 
             
                        logger.info "uploading data to #{server}:#{@filename}"
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            module SwitchTower
         | 
| 2 | 
            +
              # A helper method for converting a comma-delimited string into an array of
         | 
| 3 | 
            +
              # roles.
         | 
| 4 | 
            +
              def self.str2roles(string)
         | 
| 5 | 
            +
                list = string.split(/,/).map { |s| s.strip.to_sym }
         | 
| 6 | 
            +
                list.empty? ? nil : list
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              # Used by third-party task bundles to identify the switchtower configuration
         | 
| 10 | 
            +
              # that is loading them. It's return value is not reliable in other contexts.
         | 
| 11 | 
            +
              # If +require_config+ is not false, an exception will be raised if the current
         | 
| 12 | 
            +
              # configuration is not set.
         | 
| 13 | 
            +
              def self.configuration(require_config=false)
         | 
| 14 | 
            +
                config = Thread.current[:switchtower_configuration]
         | 
| 15 | 
            +
                if require_config && config.nil?
         | 
| 16 | 
            +
                  raise "Please require this file from within a SwitchTower recipe"
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                config
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              # Used internally by SwitchTower to specify the current configuration before
         | 
| 22 | 
            +
              # loading a third-party task bundle.
         | 
| 23 | 
            +
              def self.configuration=(config)
         | 
| 24 | 
            +
                Thread.current[:switchtower_configuration] = config
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
    
        data/lib/switchtower/version.rb
    CHANGED
    
    | @@ -18,13 +18,13 @@ module SwitchTower | |
| 18 18 | 
             
                  good
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 | 
            -
                MAJOR =  | 
| 22 | 
            -
                MINOR =  | 
| 21 | 
            +
                MAJOR = 1
         | 
| 22 | 
            +
                MINOR = 0
         | 
| 23 23 | 
             
                TINY  = 0
         | 
| 24 24 |  | 
| 25 25 | 
             
                STRING = [MAJOR, MINOR, TINY].join(".")
         | 
| 26 26 |  | 
| 27 | 
            -
                SSH_REQUIRED = [1,0, | 
| 27 | 
            +
                SSH_REQUIRED = [1,0,8]
         | 
| 28 28 | 
             
                SFTP_REQUIRED = [1,1,0]
         | 
| 29 29 | 
             
              end
         | 
| 30 30 | 
             
            end
         | 
    
        data/test/actor_test.rb
    CHANGED
    
    | @@ -4,6 +4,7 @@ require 'stringio' | |
| 4 4 | 
             
            require 'test/unit'
         | 
| 5 5 | 
             
            require 'switchtower/actor'
         | 
| 6 6 | 
             
            require 'switchtower/logger'
         | 
| 7 | 
            +
            require 'switchtower/configuration'
         | 
| 7 8 |  | 
| 8 9 | 
             
            class ActorTest < Test::Unit::TestCase
         | 
| 9 10 |  | 
| @@ -83,6 +84,12 @@ class ActorTest < Test::Unit::TestCase | |
| 83 84 | 
             
                end
         | 
| 84 85 | 
             
              end
         | 
| 85 86 |  | 
| 87 | 
            +
              module CustomExtension
         | 
| 88 | 
            +
                def do_something_extra(a, b, c)
         | 
| 89 | 
            +
                  run "echo '#{a} :: #{b} :: #{c}'"
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
             | 
| 86 93 | 
             
              def setup
         | 
| 87 94 | 
             
                TestingCommand.reset!
         | 
| 88 95 | 
             
                @actor = TestActor.new(MockConfiguration.new)
         | 
| @@ -162,7 +169,7 @@ class ActorTest < Test::Unit::TestCase | |
| 162 169 | 
             
                  run "do this"
         | 
| 163 170 | 
             
                end
         | 
| 164 171 |  | 
| 165 | 
            -
                assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers | 
| 172 | 
            +
                assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers.sort
         | 
| 166 173 | 
             
              end
         | 
| 167 174 |  | 
| 168 175 | 
             
              def test_run_in_task_without_explicit_roles_selects_all_roles
         | 
| @@ -258,4 +265,30 @@ class ActorTest < Test::Unit::TestCase | |
| 258 265 | 
             
                @actor.foo
         | 
| 259 266 | 
             
                assert_equal %w(foo after_foo), history
         | 
| 260 267 | 
             
              end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
              def test_uppercase_variables
         | 
| 270 | 
            +
                config = SwitchTower::Configuration.new(TestActor)
         | 
| 271 | 
            +
                config.set :HELLO, "world"
         | 
| 272 | 
            +
                assert_equal "world", config.actor.instance_eval("HELLO")
         | 
| 273 | 
            +
                config.set :HELLO, "test"
         | 
| 274 | 
            +
                assert_equal "test", config.actor.instance_eval("HELLO")
         | 
| 275 | 
            +
              end
         | 
| 276 | 
            +
             | 
| 277 | 
            +
              def test_connect_when_no_matching_servers
         | 
| 278 | 
            +
                @actor.define_task :foo, :roles => :db, :only => { :fnoofy => true } do
         | 
| 279 | 
            +
                  run "do this"
         | 
| 280 | 
            +
                end
         | 
| 281 | 
            +
             | 
| 282 | 
            +
                assert_raises(RuntimeError) { @actor.foo }
         | 
| 283 | 
            +
              end
         | 
| 284 | 
            +
             | 
| 285 | 
            +
              def test_custom_extension
         | 
| 286 | 
            +
                assert SwitchTower.plugin(:custom, CustomExtension)
         | 
| 287 | 
            +
                @actor.define_task :foo, :roles => :db do
         | 
| 288 | 
            +
                  custom.do_something_extra(1, 2, 3)
         | 
| 289 | 
            +
                end
         | 
| 290 | 
            +
                assert_nothing_raised { @actor.foo }
         | 
| 291 | 
            +
                assert TestingCommand.invoked?
         | 
| 292 | 
            +
                assert SwitchTower.remove_plugin(:custom)
         | 
| 293 | 
            +
              end
         | 
| 261 294 | 
             
            end
         | 
    
        data/test/configuration_test.rb
    CHANGED
    
    | @@ -125,6 +125,16 @@ class ConfigurationTest < Test::Unit::TestCase | |
| 125 125 | 
             
                assert_equal 1, @config.roles[:web].length
         | 
| 126 126 | 
             
              end
         | 
| 127 127 |  | 
| 128 | 
            +
              def test_load_proc_explicit
         | 
| 129 | 
            +
                @config.load :proc => Proc.new { set :gateway, "nifty.zoo.test" }
         | 
| 130 | 
            +
                assert_equal "nifty.zoo.test", @config.gateway
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              def test_load_proc_implicit
         | 
| 134 | 
            +
                @config.load { set :gateway, "nifty.zoo.test" }
         | 
| 135 | 
            +
                assert_equal "nifty.zoo.test", @config.gateway
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
             | 
| 128 138 | 
             
              def test_task_without_options
         | 
| 129 139 | 
             
                block = Proc.new { }
         | 
| 130 140 | 
             
                @config.task :hello, &block
         | 
| @@ -209,10 +219,15 @@ class ConfigurationTest < Test::Unit::TestCase | |
| 209 219 | 
             
              end
         | 
| 210 220 |  | 
| 211 221 | 
             
              def test_get_proc_variable_sets_original_value_hash
         | 
| 212 | 
            -
                @config.set | 
| 222 | 
            +
                @config.set(:proc) { "foo" }
         | 
| 213 223 | 
             
                assert_nil @config[:original_value][:proc]
         | 
| 214 224 | 
             
                assert_equal "foo", @config[:proc]
         | 
| 215 225 | 
             
                assert_not_nil @config[:original_value][:proc]
         | 
| 216 226 | 
             
                assert @config[:original_value][:proc].respond_to?(:call)
         | 
| 217 227 | 
             
              end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
              def test_require
         | 
| 230 | 
            +
                @config.require "#{File.dirname(__FILE__)}/fixtures/custom"
         | 
| 231 | 
            +
                assert_equal "foo", @config.gateway
         | 
| 232 | 
            +
              end
         | 
| 218 233 | 
             
            end
         | 
    
        data/test/scm/cvs_test.rb
    CHANGED
    
    | @@ -9,10 +9,15 @@ class ScmCvsTest < Test::Unit::TestCase | |
| 9 9 | 
             
                attr_accessor :story
         | 
| 10 10 | 
             
                attr_reader   :last_path
         | 
| 11 11 |  | 
| 12 | 
            -
                def cvs_log(path)
         | 
| 12 | 
            +
                def cvs_log(path,branch)
         | 
| 13 13 | 
             
                  @last_path = path
         | 
| 14 14 | 
             
                  story.shift
         | 
| 15 15 | 
             
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def cvs_branch(path)
         | 
| 18 | 
            +
                  "deploy-me"
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 16 21 | 
             
              end
         | 
| 17 22 |  | 
| 18 23 | 
             
              class MockChannel
         | 
| @@ -56,7 +61,6 @@ class ScmCvsTest < Test::Unit::TestCase | |
| 56 61 | 
             
              def setup
         | 
| 57 62 | 
             
                @config = MockConfiguration.new
         | 
| 58 63 | 
             
                @config[:repository] = ":ext:joetester@rubyforge.org:/hello/world"
         | 
| 59 | 
            -
                @config[:local] = "/hello/world"
         | 
| 60 64 | 
             
                @config[:cvs] = "/path/to/cvs"
         | 
| 61 65 | 
             
                @config[:password] = "chocolatebrownies"
         | 
| 62 66 | 
             
                @config[:now] = Time.utc(2005,8,24,12,0,0)
         | 
| @@ -144,11 +148,19 @@ MSG | |
| 144 148 | 
             
              end
         | 
| 145 149 |  | 
| 146 150 | 
             
              def test_latest_revision
         | 
| 151 | 
            +
                @config[:local] = "/hello/world"
         | 
| 147 152 | 
             
                @scm.story = [ @log_msg ]
         | 
| 148 153 | 
             
                assert_equal "2004-10-12 02:21:02", @scm.latest_revision
         | 
| 149 154 | 
             
                assert_equal "/hello/world", @scm.last_path
         | 
| 150 155 | 
             
              end
         | 
| 151 156 |  | 
| 157 | 
            +
              def test_latest_with_default_local
         | 
| 158 | 
            +
                @config[:local] = nil
         | 
| 159 | 
            +
                @scm.story = [ @log_msg ]
         | 
| 160 | 
            +
                assert_equal "2004-10-12 02:21:02", @scm.latest_revision
         | 
| 161 | 
            +
                assert_equal ".", @scm.last_path
         | 
| 162 | 
            +
              end
         | 
| 163 | 
            +
             | 
| 152 164 | 
             
              def test_checkout
         | 
| 153 165 | 
             
                @actor.story = []
         | 
| 154 166 | 
             
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| @@ -161,4 +173,14 @@ MSG | |
| 161 173 | 
             
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 162 174 | 
             
                assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
         | 
| 163 175 | 
             
              end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
              def test_current_branch
         | 
| 178 | 
            +
                assert_equal "deploy-me", @scm.current_branch
         | 
| 179 | 
            +
              end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
              def test_default_current_branch
         | 
| 182 | 
            +
                @config[:branch] = "default-branch"
         | 
| 183 | 
            +
                @scm = CvsTest.new(@config)
         | 
| 184 | 
            +
                assert_equal "default-branch", @scm.current_branch
         | 
| 185 | 
            +
              end
         | 
| 164 186 | 
             
            end
         | 
    
        data/test/scm/subversion_test.rb
    CHANGED
    
    | @@ -84,7 +84,7 @@ MSG | |
| 84 84 | 
             
                @actor.story = []
         | 
| 85 85 | 
             
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 86 86 | 
             
                assert_nil @actor.channels.last.sent_data
         | 
| 87 | 
            -
                assert_match %r{/path/to/svn}, @actor.command
         | 
| 87 | 
            +
                assert_match %r{/path/to/svn co\s+-q}, @actor.command
         | 
| 88 88 | 
             
              end
         | 
| 89 89 |  | 
| 90 90 | 
             
              def test_checkout_via_export
         | 
| @@ -92,7 +92,7 @@ MSG | |
| 92 92 | 
             
                @config[:checkout] = "export"
         | 
| 93 93 | 
             
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 94 94 | 
             
                assert_nil @actor.channels.last.sent_data
         | 
| 95 | 
            -
                assert_match %r{/path/to/svn export}, @actor.command
         | 
| 95 | 
            +
                assert_match %r{/path/to/svn export\s+-q}, @actor.command
         | 
| 96 96 | 
             
              end
         | 
| 97 97 |  | 
| 98 98 | 
             
              def test_update
         | 
| @@ -119,4 +119,19 @@ MSG | |
| 119 119 | 
             
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 120 120 | 
             
                assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
         | 
| 121 121 | 
             
              end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              def test_svn_password
         | 
| 124 | 
            +
                @config[:svn_password] = "butterscotchcandies"
         | 
| 125 | 
            +
                @actor.story = [[:out, "Password: "]]
         | 
| 126 | 
            +
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 127 | 
            +
                assert_equal ["butterscotchcandies\n"], @actor.channels.last.sent_data
         | 
| 128 | 
            +
              end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
              def test_svn_username
         | 
| 131 | 
            +
                @actor.story = []
         | 
| 132 | 
            +
                @config[:svn_username] = "turtledove"
         | 
| 133 | 
            +
                assert_nothing_raised { @scm.checkout(@actor) }
         | 
| 134 | 
            +
                assert_nil @actor.channels.last.sent_data
         | 
| 135 | 
            +
                assert_match %r{/path/to/svn co --username turtledove}, @actor.command
         | 
| 136 | 
            +
              end
         | 
| 122 137 | 
             
            end
         | 
    
        data/test/utils.rb
    CHANGED
    
    | @@ -32,6 +32,14 @@ class MockConfiguration < Hash | |
| 32 32 | 
             
                @logger ||= MockLogger.new
         | 
| 33 33 | 
             
              end
         | 
| 34 34 |  | 
| 35 | 
            +
              def set(variable, value=nil, &block)
         | 
| 36 | 
            +
                  self[variable] = value
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              def respond_to?(sym)
         | 
| 40 | 
            +
                self.has_key?(sym)
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 35 43 | 
             
              def method_missing(sym, *args)
         | 
| 36 44 | 
             
                if args.length == 0
         | 
| 37 45 | 
             
                  self[sym]
         | 
    
        metadata
    CHANGED
    
    | @@ -3,8 +3,8 @@ rubygems_version: 0.8.11 | |
| 3 3 | 
             
            specification_version: 1
         | 
| 4 4 | 
             
            name: switchtower
         | 
| 5 5 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 6 | 
            -
              version: 0. | 
| 7 | 
            -
            date: 2006- | 
| 6 | 
            +
              version: 1.0.0
         | 
| 7 | 
            +
            date: 2006-02-18 00:00:00 -07:00
         | 
| 8 8 | 
             
            summary: "SwitchTower is a framework and utility for executing commands in parallel     on
         | 
| 9 9 | 
             
              multiple remote machines, via SSH. The primary goal is to simplify and    
         | 
| 10 10 | 
             
              automate the deployment of web applications."
         | 
| @@ -38,6 +38,7 @@ files: | |
| 38 38 | 
             
              - lib/switchtower/cli.rb
         | 
| 39 39 | 
             
              - lib/switchtower/command.rb
         | 
| 40 40 | 
             
              - lib/switchtower/configuration.rb
         | 
| 41 | 
            +
              - lib/switchtower/extensions.rb
         | 
| 41 42 | 
             
              - lib/switchtower/gateway.rb
         | 
| 42 43 | 
             
              - lib/switchtower/generators
         | 
| 43 44 | 
             
              - lib/switchtower/logger.rb
         | 
| @@ -45,6 +46,7 @@ files: | |
| 45 46 | 
             
              - lib/switchtower/scm
         | 
| 46 47 | 
             
              - lib/switchtower/ssh.rb
         | 
| 47 48 | 
             
              - lib/switchtower/transfer.rb
         | 
| 49 | 
            +
              - lib/switchtower/utils.rb
         | 
| 48 50 | 
             
              - lib/switchtower/version.rb
         | 
| 49 51 | 
             
              - lib/switchtower/generators/rails
         | 
| 50 52 | 
             
              - lib/switchtower/generators/rails/deployment
         | 
| @@ -57,8 +59,11 @@ files: | |
| 57 59 | 
             
              - lib/switchtower/recipes/templates
         | 
| 58 60 | 
             
              - lib/switchtower/recipes/templates/maintenance.rhtml
         | 
| 59 61 | 
             
              - lib/switchtower/scm/base.rb
         | 
| 62 | 
            +
              - lib/switchtower/scm/baz.rb
         | 
| 63 | 
            +
              - lib/switchtower/scm/bzr.rb
         | 
| 60 64 | 
             
              - lib/switchtower/scm/cvs.rb
         | 
| 61 65 | 
             
              - lib/switchtower/scm/darcs.rb
         | 
| 66 | 
            +
              - lib/switchtower/scm/perforce.rb
         | 
| 62 67 | 
             
              - lib/switchtower/scm/subversion.rb
         | 
| 63 68 | 
             
              - examples/sample.rb
         | 
| 64 69 | 
             
              - test/actor_test.rb
         | 
| @@ -69,6 +74,7 @@ files: | |
| 69 74 | 
             
              - test/ssh_test.rb
         | 
| 70 75 | 
             
              - test/utils.rb
         | 
| 71 76 | 
             
              - test/fixtures/config.rb
         | 
| 77 | 
            +
              - test/fixtures/custom.rb
         | 
| 72 78 | 
             
              - test/scm/cvs_test.rb
         | 
| 73 79 | 
             
              - test/scm/subversion_test.rb
         | 
| 74 80 | 
             
            test_files: []
         | 
| @@ -87,7 +93,7 @@ dependencies: | |
| 87 93 | 
             
                    - 
         | 
| 88 94 | 
             
                      - ">="
         | 
| 89 95 | 
             
                      - !ruby/object:Gem::Version 
         | 
| 90 | 
            -
                        version: 1.0. | 
| 96 | 
            +
                        version: 1.0.8
         | 
| 91 97 | 
             
                  version: 
         | 
| 92 98 | 
             
              - !ruby/object:Gem::Dependency 
         | 
| 93 99 | 
             
                name: net-sftp
         |