hadouken 0.1.4.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ module Hadouken::Task
2
+ class Base
3
+ attr_reader :plan
4
+ attr_reader :group_name
5
+
6
+ def initialize(opts)
7
+ @group_name = opts[:group]
8
+ @plan = opts[:plan ]
9
+ end
10
+
11
+ def group?
12
+ !! @group_name
13
+ end
14
+
15
+ def group
16
+ @plan.group(@group_name)
17
+ end
18
+
19
+ def self.create!(instance, opts)
20
+ return case instance
21
+ # autovivify
22
+ when String then Hadouken::Task::Command.new instance, opts
23
+ when Array then Hadouken::Task::Command.new instance, opts
24
+ when Proc then Hadouken::Task::Callback.new instance, opts
25
+
26
+ # go with it
27
+ when Hadouken::Strategy::Base then instance
28
+ when Hadouken::Task::Base then instance
29
+
30
+ # no chance
31
+ else raise ArgumentError
32
+ end
33
+ end
34
+ end
35
+
36
+ class Command < Base
37
+ def initialize(command, opts)
38
+ @command = command
39
+ super(opts)
40
+ end
41
+
42
+ # TODO: sanitize command so it has a chance of working
43
+ def command
44
+ @command
45
+ end
46
+ end
47
+
48
+ class Callback < Base
49
+ def initialize(fn, opts)
50
+ @proc = fn
51
+ super opts
52
+ end
53
+
54
+ def call(opts)
55
+ @proc.call(*opts)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ class Hadouken::Tasks
2
+ include Enumerable
3
+
4
+ def initialize
5
+ @tasks = []
6
+ end
7
+
8
+ def each
9
+ @tasks.each do |task|
10
+ yield task
11
+ end
12
+ end
13
+
14
+ def add(task, opts={})
15
+ @tasks << Hadouken::Task::Base.create!(task, opts)
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'test/unit'
12
+ require 'shoulda'
13
+ require 'mocha'
14
+ require 'pp'
15
+
16
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
17
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
18
+ require 'hadouken'
19
+
20
+ class Test::Unit::TestCase
21
+ end
@@ -0,0 +1,118 @@
1
+ require 'helper'
2
+
3
+ class TestHadouken < Test::Unit::TestCase
4
+
5
+ context "yeah" do
6
+ setup do
7
+ Net::SSH::Multi::Session.any_instance.stubs(:exec).returns(true)
8
+ Net::SSH::Multi::Subsession.any_instance.stubs(:exec).returns(true)
9
+ end
10
+
11
+ should "create a group" do
12
+ g = Hadouken::Group.new(:name => :pony, :range => (1..5), :pattern => "pony-%05d")
13
+ assert_equal g.name, :pony
14
+ assert_equal g.range, (1..5)
15
+ assert_equal g.pattern, "pony-%05d"
16
+ assert_equal g.size, 5
17
+ assert_equal g.hosts, g.range.map{|i| g.pattern % i}
18
+ end
19
+
20
+ should "create a collection of groups" do
21
+ plan = Hadouken::Plan.new
22
+ plan.verbose = true
23
+ plan.add_group Hadouken::Group.new(:name => :cat, :range => (1..3), :pattern => "cat-%05d")
24
+ plan.add_group Hadouken::Group.new(:name => :dog, :range => (1..5), :pattern => "dog-%05d")
25
+
26
+ assert_equal 8, plan.groups.hosts.size
27
+ assert_equal plan.groups.fetch(:cat), plan.groups[:cat]
28
+ assert_equal 'cat-00003', plan.groups.fetch(:cat).hosts.last
29
+ assert_equal 'dog-00005', plan.groups.fetch(:dog).hosts.last
30
+ end
31
+
32
+ should "use by-host strategy" do
33
+ plan = Hadouken::Plan.new
34
+ plan.verbose = true
35
+ plan.add_group Hadouken::Group.new(:name => :cat, :range => (1..3), :pattern => "cat-%05d")
36
+ plan.add_group Hadouken::Group.new(:name => :dog, :range => (1..3), :pattern => "dog-%05d")
37
+
38
+ cats = (1..3).map{|i| "cat-%05d" % i}
39
+ dogs = (1..3).map{|i| "dog-%05d" % i}
40
+ crazy = [ cats + dogs ]
41
+
42
+ servers = Hadouken::Strategy::ByHost.new(plan).host_strategy
43
+ assert_equal crazy, servers
44
+ end
45
+
46
+ should "use by-host strategy with two at a time" do
47
+ plan = Hadouken::Plan.new
48
+ plan.verbose = true
49
+ plan.add_group Hadouken::Group.new(:name => :cat, :range => (1..3), :pattern => "cat-%05d")
50
+ plan.add_group Hadouken::Group.new(:name => :dog, :range => (1..3), :pattern => "dog-%05d")
51
+
52
+ cats = (1..3).map{|i| "cat-%05d" % i}
53
+ dogs = (1..3).map{|i| "dog-%05d" % i}
54
+ crazy = []
55
+ (cats + dogs).each_slice(2) do |s|
56
+ crazy << s
57
+ end
58
+
59
+ servers = Hadouken::Strategy::ByHost.new(plan, :max_hosts => 2).host_strategy
60
+ assert_equal crazy, servers
61
+ end
62
+
63
+
64
+ should "use by-group strategy with two at a time" do
65
+ plan = Hadouken::Plan.new
66
+ plan.verbose = true
67
+ plan.add_group Hadouken::Group.new(:name => :cat, :range => (1..3), :pattern => "cat-%05d")
68
+ plan.add_group Hadouken::Group.new(:name => :dog, :range => (1..3), :pattern => "dog-%05d")
69
+
70
+ cats = (1..3).map{|i| "cat-%05d" % i}
71
+ dogs = (1..3).map{|i| "dog-%05d" % i}
72
+
73
+ servers = Hadouken::Strategy::ByGroup.new(plan, :max_hosts => 2).host_strategy
74
+ assert_equal cats[0..1], servers[0]
75
+ assert_equal [cats[2]], servers[1]
76
+ assert_equal dogs[0..1], servers[2]
77
+ assert_equal [dogs[2]], servers[3]
78
+ end
79
+
80
+
81
+ should "use by-group-parallel strategy" do
82
+ plan = Hadouken::Plan.new
83
+ plan.verbose = true
84
+ plan.name = :pet_store
85
+ plan.add_group Hadouken::Group.new(:name => :cat, :range => (1..3), :pattern => "cat-%05d")
86
+ plan.add_group Hadouken::Group.new(:name => :dog, :range => (1..3), :pattern => "dog-%05d")
87
+ plan.add_group Hadouken::Group.new(:name => :hog, :range => (1..3), :pattern => "hog-%05d")
88
+
89
+ cats = (1..3).map{|i| "cat-%05d" % i}
90
+ dogs = (1..3).map{|i| "dog-%05d" % i}
91
+ hogs = (1..3).map{|i| "hog-%05d" % i}
92
+
93
+ crazy = []
94
+ crazy << [ cats[0], dogs[0], hogs[0] ]
95
+ crazy << [ cats[1], dogs[1], hogs[1] ]
96
+ crazy << [ cats[2], dogs[2], hogs[2] ]
97
+
98
+ plan.tasks.add Hadouken::Strategy::ByHost.new(plan)
99
+ plan.tasks.add Hadouken::Task::Command.new("aaa", :plan => plan)
100
+ plan.tasks.add "bbb", :plan => plan
101
+ plan.tasks.add Proc.new{|host|
102
+ }, :plan => plan
103
+
104
+ plan.tasks.add Hadouken::Strategy::ByGroupParallel.new(plan, :max_hosts => 4, :traversal => :depth)
105
+ plan.tasks.add Hadouken::Task::Command.new("doggie", :plan => plan, :group_name => :dog)
106
+ plan.tasks.add Hadouken::Task::Command.new("kitty", :plan => plan, :group_name => :cat)
107
+ plan.tasks.add Hadouken::Task::Command.new("pig", :plan => plan, :group_name => :hog)
108
+ plan.tasks.add Proc.new{|host|
109
+ puts "**************** #{host} ******************"
110
+ }, :plan => plan
111
+
112
+ Hadouken::Executor.run!(plan)
113
+ end
114
+
115
+
116
+
117
+ end
118
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hadouken
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.4.pre
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Matt Knopp
9
+ - Chris Gray
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-01-27 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: net-ssh
17
+ requirement: &70333320089840 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *70333320089840
26
+ - !ruby/object:Gem::Dependency
27
+ name: net-ssh-multi
28
+ requirement: &70333320089100 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *70333320089100
37
+ - !ruby/object:Gem::Dependency
38
+ name: yajl-ruby
39
+ requirement: &70333320088360 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *70333320088360
48
+ - !ruby/object:Gem::Dependency
49
+ name: shoulda
50
+ requirement: &70333320087540 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70333320087540
59
+ - !ruby/object:Gem::Dependency
60
+ name: mocha
61
+ requirement: &70333320086600 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *70333320086600
70
+ - !ruby/object:Gem::Dependency
71
+ name: bundler
72
+ requirement: &70333320085440 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.0
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *70333320085440
81
+ - !ruby/object:Gem::Dependency
82
+ name: jeweler
83
+ requirement: &70333320084320 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: 1.6.4
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *70333320084320
92
+ - !ruby/object:Gem::Dependency
93
+ name: rcov
94
+ requirement: &70333320098940 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ type: :development
101
+ prerelease: false
102
+ version_requirements: *70333320098940
103
+ description: run commands over ssh in a way that makes sense for deploying artifacts
104
+ email:
105
+ - mknopp@yammer-inc.com, cgray@yammer-inc.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files:
109
+ - LICENSE.txt
110
+ - README.md
111
+ files:
112
+ - .document
113
+ - Gemfile
114
+ - Gemfile.lock
115
+ - LICENSE.txt
116
+ - README.md
117
+ - Rakefile
118
+ - VERSION
119
+ - hadouken.gemspec
120
+ - lib/hadouken.rb
121
+ - lib/hadouken/executor.rb
122
+ - lib/hadouken/ext/net_ssh_multi_session_actions.rb
123
+ - lib/hadouken/group.rb
124
+ - lib/hadouken/groups.rb
125
+ - lib/hadouken/host.rb
126
+ - lib/hadouken/plan.rb
127
+ - lib/hadouken/runner.rb
128
+ - lib/hadouken/strategy/base.rb
129
+ - lib/hadouken/strategy/by_group.rb
130
+ - lib/hadouken/strategy/by_group_parallel.rb
131
+ - lib/hadouken/strategy/by_host.rb
132
+ - lib/hadouken/task.rb
133
+ - lib/hadouken/tasks.rb
134
+ - test/helper.rb
135
+ - test/test_hadouken.rb
136
+ homepage: http://github.com/mhat/hadouken
137
+ licenses:
138
+ - MIT
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ none: false
145
+ requirements:
146
+ - - ! '>='
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ segments:
150
+ - 0
151
+ hash: -2045406218975922941
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>'
156
+ - !ruby/object:Gem::Version
157
+ version: 1.3.1
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 1.8.11
161
+ signing_key:
162
+ specification_version: 3
163
+ summary: run commands over ssh in a way that makes sense for deploying artifacts
164
+ test_files: []