hadouken 0.1.4.pre
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 +13 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +20 -0
- data/README.md +55 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/hadouken.gemspec +84 -0
- data/lib/hadouken.rb +29 -0
- data/lib/hadouken/executor.rb +236 -0
- data/lib/hadouken/ext/net_ssh_multi_session_actions.rb +31 -0
- data/lib/hadouken/group.rb +32 -0
- data/lib/hadouken/groups.rb +42 -0
- data/lib/hadouken/host.rb +120 -0
- data/lib/hadouken/plan.rb +48 -0
- data/lib/hadouken/runner.rb +84 -0
- data/lib/hadouken/strategy/base.rb +15 -0
- data/lib/hadouken/strategy/by_group.rb +15 -0
- data/lib/hadouken/strategy/by_group_parallel.rb +34 -0
- data/lib/hadouken/strategy/by_host.rb +14 -0
- data/lib/hadouken/task.rb +58 -0
- data/lib/hadouken/tasks.rb +17 -0
- data/test/helper.rb +21 -0
- data/test/test_hadouken.rb +118 -0
- metadata +164 -0
@@ -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
|
data/test/helper.rb
ADDED
@@ -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: []
|