cluster_management 0.0.1 → 0.5.1
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/Rakefile +1 -1
- data/lib/cluster_management/cluster_management.rb +39 -0
- data/lib/cluster_management/integration/vos.rb +4 -0
- data/lib/cluster_management/package.rb +53 -17
- data/lib/cluster_management/support.rb +17 -0
- data/lib/cluster_management.rb +3 -8
- data/readme.md +78 -21
- data/spec/package_spec.rb +136 -0
- data/spec/spec_helper.rb +67 -0
- metadata +8 -4
- data/lib/cluster_management/rake.rb +0 -11
data/Rakefile
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module ClusterManagement
|
2
|
+
class << self
|
3
|
+
#
|
4
|
+
# use :integration attribute to provide integration with your tool (use integration/rsh as a sample).
|
5
|
+
#
|
6
|
+
attr_writer :integration
|
7
|
+
def integration
|
8
|
+
unless @integration
|
9
|
+
not_supported = -> *args {raise "you must provide your own implementation!"}
|
10
|
+
@integration = {
|
11
|
+
has_mark?: not_supported,
|
12
|
+
mark: not_supported
|
13
|
+
}
|
14
|
+
end
|
15
|
+
@integration
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
#
|
20
|
+
# you must override this method to provide your own implementation
|
21
|
+
#
|
22
|
+
attr_writer :boxes
|
23
|
+
def boxes
|
24
|
+
unless @boxes
|
25
|
+
warn('you must override :boxes method to provide your own behaviour')
|
26
|
+
return []
|
27
|
+
end
|
28
|
+
@boxes
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
#
|
33
|
+
# Rake integration
|
34
|
+
#
|
35
|
+
def rake_task *args, &block
|
36
|
+
task *args, &block
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,39 +1,75 @@
|
|
1
|
-
module
|
1
|
+
module ClusterManagement
|
2
2
|
class Package < Hash
|
3
3
|
class Dsl
|
4
|
-
attr_reader :package
|
4
|
+
attr_reader :package, :box
|
5
5
|
|
6
|
-
def initialize package
|
7
|
-
@package = package
|
6
|
+
def initialize package, box
|
7
|
+
@package, @box = package, box
|
8
8
|
end
|
9
9
|
|
10
|
-
def version
|
10
|
+
def version; package.version end
|
11
|
+
|
11
12
|
def applied? &b; package.applied = b end
|
12
13
|
def apply &b; package.apply = b end
|
13
14
|
def verify &b; package.verify = b end
|
14
15
|
def after_applying &b; package.after_applying = b end
|
16
|
+
|
17
|
+
def apply_once &b
|
18
|
+
mark = package.version ? "#{package.name}:#{package.version}" : package.name.to_s
|
19
|
+
applied?{ClusterManagement.integration[:has_mark?].call box, mark}
|
20
|
+
apply &b
|
21
|
+
after_applying{ClusterManagement.integration[:mark].call box, mark}
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
25
|
attr_accessor :applied, :apply, :verify, :after_applying, :name, :version
|
18
26
|
|
19
|
-
def initialize name
|
20
|
-
@name = name
|
21
|
-
end
|
22
|
-
|
23
|
-
def configure_with &b
|
24
|
-
dsl = Dsl.new self
|
25
|
-
b.call dsl
|
27
|
+
def initialize name, version
|
28
|
+
@name, @version = name, version
|
26
29
|
end
|
27
30
|
|
28
|
-
def
|
29
|
-
|
31
|
+
def configure box, &b
|
32
|
+
dsl = Dsl.new self, box
|
33
|
+
dsl.instance_eval &b
|
34
|
+
|
35
|
+
if applied
|
36
|
+
package_applied = applied.call box
|
37
|
+
# ensure_boolean! package_applied, :applied?
|
38
|
+
else
|
39
|
+
package_applied = false
|
40
|
+
end
|
41
|
+
|
30
42
|
if apply and !package_applied
|
31
|
-
|
43
|
+
ClusterManagement.logger.info %(applying '#{name}#{version ? ":#{version}" : ''}' to '#{box}'\n)
|
32
44
|
apply.call box
|
33
45
|
end
|
34
|
-
|
46
|
+
|
47
|
+
if verify
|
48
|
+
verified = verify.call box
|
49
|
+
# ensure_boolean! verified, 'verify'
|
50
|
+
raise "invalid '#{name}' package for '#{box}'!" unless verified
|
51
|
+
end
|
35
52
|
after_applying && after_applying.call(box)
|
36
|
-
# print "done\n" if apply and !package_applied
|
53
|
+
# print "done\n" if apply and !package_applied
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
def ensure_boolean! value, method
|
58
|
+
unless value.eql?(true) or value.eql?(false)
|
59
|
+
raise "invalid return value in '#{name}.#{method}' (only true/false allowed)!"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def package name_or_options, version = nil, &block
|
66
|
+
version ||= name_or_options.delete :version if name_or_options.is_a? Hash
|
67
|
+
ClusterManagement.rake_task name_or_options do |task, *args|
|
68
|
+
if block
|
69
|
+
ClusterManagement.boxes.each do |box|
|
70
|
+
package = ClusterManagement::Package.new task.name, version
|
71
|
+
package.configure box, &block
|
72
|
+
end
|
37
73
|
end
|
38
74
|
end
|
39
75
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ClusterManagement
|
4
|
+
class << self
|
5
|
+
#
|
6
|
+
# Logger
|
7
|
+
#
|
8
|
+
attr_writer :logger
|
9
|
+
def logger
|
10
|
+
unless @logger
|
11
|
+
@logger = Logger.new STDOUT
|
12
|
+
@logger.formatter = -> severity, datetime, progname, msg {msg}
|
13
|
+
end
|
14
|
+
@logger
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/cluster_management.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
%w(
|
2
|
-
|
2
|
+
support
|
3
3
|
package
|
4
|
+
cluster_management
|
4
5
|
).each{|f| require "cluster_management/#{f}"}
|
5
6
|
|
6
|
-
|
7
|
-
# you must override this method to provide your own implementation
|
8
|
-
#
|
9
|
-
def boxes
|
10
|
-
warn 'you must override :boxes method to provide your own behaviour'
|
11
|
-
[]
|
12
|
-
end
|
7
|
+
require 'cluster_management/integration/vos' unless $cluster_management_dont_include_integration
|
data/readme.md
CHANGED
@@ -3,37 +3,90 @@
|
|
3
3
|
It may be **usefull if Your claster has about 1-10 boxes**, and tools like Chef, Puppet, Capistrano are too complex and proprietary for your needs.
|
4
4
|
**It's extremely easy**, there are only 3 methods.
|
5
5
|
|
6
|
+
## Package management
|
7
|
+
|
6
8
|
Define your packages, they are just rake tasks, so you probably know how to work with them:
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
box.bash 'apt-get install ruby'
|
13
|
-
box.mark :ruby
|
14
|
-
end
|
10
|
+
package :ruby do
|
11
|
+
applied?{box.has_mark? :ruby}
|
12
|
+
apply do
|
13
|
+
box.bash 'apt-get install ruby'
|
15
14
|
end
|
15
|
+
after_applying{box.mark :ruby}
|
16
|
+
end
|
17
|
+
|
18
|
+
or you can use a little shorter notation (it's equivalent to the previous):
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
box.bash 'gem install rails'
|
21
|
-
box.mark :rails
|
22
|
-
end
|
20
|
+
package rails: :ruby, version: 3 do
|
21
|
+
apply_once do
|
22
|
+
box.bash 'gem install rails'
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
|
26
|
+
And it's understands dependencies, so the :rails package will apply :ruby before applying itself.
|
27
|
+
It also support iterative development, so you don't need to write all the config at once, do it by small steps, adding one package after another.
|
28
|
+
And you can use versioning to update already installed packages - if you change version of some package it will be reapplied next run.
|
29
|
+
|
30
|
+
And, last step - define (I intentionally leave implementation of this method to You, it's very specific to Your environment)
|
31
|
+
to what machines it should be applied:
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
33
|
+
module ClusterManagement
|
34
|
+
def self.boxes
|
35
|
+
unless @boxes
|
36
|
+
host = ENV['host'] || raise(":host not defined!")
|
37
|
+
box = Vos::Box.new host: host, ssh: config.ssh!.to_h
|
38
|
+
box.open
|
39
|
+
|
40
|
+
@boxes = [box]
|
41
|
+
end
|
42
|
+
@boxes
|
43
|
+
end
|
32
44
|
end
|
33
45
|
|
34
|
-
|
46
|
+
Now, you can press the enter:
|
47
|
+
|
48
|
+
$ rake os:rails host=myapp.com
|
49
|
+
|
50
|
+
and packager will do all the job of installing and configuring your cluster boxes, and prints you something like that
|
51
|
+
(it's a sample output of some of my own box, you can see config details here [my_cluster][my_cluster]):
|
52
|
+
|
53
|
+
$ rake app_server host=universal.xxx.com
|
54
|
+
applying 'basic:os:5' to '<Box: universal.xxx.com>'
|
55
|
+
applying 'basic:apt' to '<Box: universal.xxx.com>'
|
56
|
+
applying 'basic:system_tools' to '<Box: universal.xxx.com>'
|
57
|
+
applying 'basic:ruby' to '<Box: universal.xxx.com>'
|
58
|
+
building ... done
|
59
|
+
updating path ... done
|
60
|
+
applying 'basic:git' to '<Box: universal.xxx.com>'
|
61
|
+
applying 'basic:security:6' to '<Box: universal.xxx.com>'
|
62
|
+
applying 'basic:manual_management:2' to '<Box: universal.xxx.com>'
|
63
|
+
applying 'app_server:fake_gem:2' to '<Box: universal.xxx.com>'
|
64
|
+
applying 'app_server:custom_ruby:3' to '<Box: universal.xxx.com>'
|
65
|
+
|
66
|
+
You can also use standard Rake -T command to see docs (it's also from my config, details are here [my_cluster][my_cluster]):
|
67
|
+
|
68
|
+
$ rake -T
|
69
|
+
rake app_server # app server
|
70
|
+
rake app_server:custom_ruby # custom ruby (with encoding globally set to unicode and enabled fake_gem hack)
|
71
|
+
rake app_server:fake_gem # fake_gem
|
72
|
+
rake basic # Box with basic packages installed
|
73
|
+
rake basic:apt # apt
|
74
|
+
rake basic:git # git
|
75
|
+
rake basic:manual_management # Makes box handy for manual management
|
76
|
+
rake basic:os # Checks OS version and add some very basic stuff
|
77
|
+
rake basic:ruby # ruby
|
78
|
+
rake basic:security # security
|
79
|
+
rake basic:system_tools # System tools, mainly for build support
|
80
|
+
rake db # db
|
81
|
+
rake db:mongodb # MongoDB
|
82
|
+
|
83
|
+
## Runtime services
|
35
84
|
|
36
|
-
|
85
|
+
[add details here]
|
86
|
+
|
87
|
+
## Deployment
|
88
|
+
|
89
|
+
[add more details here]
|
37
90
|
|
38
91
|
**You can use it also for deployment**, exactly the same way, configure it the way you like, it's just rake
|
39
92
|
tasks. And by the way, the *box.mark ...* is just an example check, you can use anything there.
|
@@ -41,6 +94,10 @@ tasks. And by the way, the *box.mark ...* is just an example check, you can use
|
|
41
94
|
It checks if the package already has been applied to box, so you can evolve your configuration and apply
|
42
95
|
it multiple times, it will apply only missing packages (or drop the *applied?* clause and it will be applied every run).
|
43
96
|
|
97
|
+
# Temporarry stuff, don't bother to read it
|
98
|
+
|
44
99
|
- small
|
45
100
|
- uses well known tools (rake and anytingh ssh-enabled)
|
46
|
-
- support iterative development
|
101
|
+
- support iterative development
|
102
|
+
|
103
|
+
[my_cluster]: https://github.com/alexeypetrushin/my_cluster/tree/master/lib/packages
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cluster_management/package'
|
3
|
+
|
4
|
+
describe 'Package' do
|
5
|
+
before :each do
|
6
|
+
ClusterManagement.box = :box
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should allow empty declaration' do
|
10
|
+
package :tools
|
11
|
+
ClusterManagement.last_task.should_not be_nil
|
12
|
+
|
13
|
+
ClusterManagement.last_task = nil
|
14
|
+
package(:tools){}
|
15
|
+
ClusterManagement.last_task.should_not be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "basic" do
|
19
|
+
check = mock()
|
20
|
+
check.should_receive(:applied?).ordered.and_return(false)
|
21
|
+
check.should_receive(:apply).ordered
|
22
|
+
check.should_receive(:verify).ordered.and_return(true)
|
23
|
+
check.should_receive(:after_applying).ordered
|
24
|
+
|
25
|
+
the_package, the_box = nil, nil
|
26
|
+
package :tools, 1 do
|
27
|
+
package.is_a?(ClusterManagement::Package).should == true
|
28
|
+
version.should == 1
|
29
|
+
box.should == :box
|
30
|
+
|
31
|
+
|
32
|
+
applied?{check.applied?(box)}
|
33
|
+
apply{check.apply(box)}
|
34
|
+
verify{check.verify(box)}
|
35
|
+
after_applying{check.after_applying(box)}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not reapply package but always verify it" do
|
40
|
+
check = mock()
|
41
|
+
check.should_not_receive(:apply)
|
42
|
+
check.should_receive(:verify).and_return(true)
|
43
|
+
|
44
|
+
package :tools do
|
45
|
+
applied?{true}
|
46
|
+
apply{check.apply}
|
47
|
+
verify{check.verify}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should verify packages" do
|
52
|
+
-> {
|
53
|
+
package :tools do
|
54
|
+
verify{false}
|
55
|
+
end
|
56
|
+
}.should raise_error(/invalid.*tools/)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should apply to all boxes" do
|
60
|
+
boxes = [:a, :b]
|
61
|
+
ClusterManagement.stub(:boxes).and_return(boxes)
|
62
|
+
|
63
|
+
check = []
|
64
|
+
package :tools do
|
65
|
+
apply{check << box}
|
66
|
+
end
|
67
|
+
check.should == boxes
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should support version attribute' do
|
71
|
+
package :tools, 2 do
|
72
|
+
version.should == 2
|
73
|
+
end
|
74
|
+
|
75
|
+
package tools: :os, version: 2 do
|
76
|
+
version.should == 2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "apply_once" do
|
81
|
+
def build_box_for key, has_mark
|
82
|
+
box = mock()
|
83
|
+
box.should_receive(:has_mark?).ordered.with(key).and_return(has_mark)
|
84
|
+
box.should_receive(:mark).ordered.with(key)
|
85
|
+
ClusterManagement.box = box
|
86
|
+
box
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should apply if not applied" do
|
90
|
+
box = build_box_for('tools', false)
|
91
|
+
|
92
|
+
check = mock()
|
93
|
+
check.should_receive(:apply_once).with(box)
|
94
|
+
|
95
|
+
package :tools do
|
96
|
+
apply_once{check.apply_once(box)}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not apply if applied" do
|
101
|
+
box = build_box_for('tools', true)
|
102
|
+
|
103
|
+
check = mock()
|
104
|
+
check.should_not_receive(:apply_once)
|
105
|
+
|
106
|
+
package :tools do
|
107
|
+
apply_once{check.apply_once}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should support versioning" do
|
112
|
+
box = build_box_for('tools:2', false)
|
113
|
+
|
114
|
+
check = mock()
|
115
|
+
check.should_receive(:apply_once)
|
116
|
+
|
117
|
+
package :tools, 2 do
|
118
|
+
apply_once{check.apply_once}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
# def version version; package.version = version end
|
126
|
+
# def applied? &b; package.applied = b end
|
127
|
+
# def apply &b; package.apply = b end
|
128
|
+
# def verify &b; package.verify = b end
|
129
|
+
# def after_applying &b; package.after_applying = b end
|
130
|
+
#
|
131
|
+
# def apply_once &b
|
132
|
+
# mark = package.version ? "#{package.name}:#{package.version}" : package.name
|
133
|
+
# applied?{INTEGRATION[:has_mark?].call box, mark}
|
134
|
+
# apply &b
|
135
|
+
# after_applying{INTEGRATION[:mark].call box, mark}
|
136
|
+
# end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rspec_ext'
|
2
|
+
|
3
|
+
require 'cluster_management/support'
|
4
|
+
require 'cluster_management/cluster_management'
|
5
|
+
|
6
|
+
|
7
|
+
#
|
8
|
+
# Boxes stub
|
9
|
+
#
|
10
|
+
module ClusterManagement
|
11
|
+
class << self
|
12
|
+
attr_accessor :box
|
13
|
+
|
14
|
+
def boxes
|
15
|
+
[box]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# Integration stub
|
23
|
+
#
|
24
|
+
ClusterManagement.integration = {
|
25
|
+
has_mark?: -> box, mark {box.has_mark? mark},
|
26
|
+
mark: -> box, mark {box.mark mark}
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
#
|
31
|
+
# Task stub
|
32
|
+
#
|
33
|
+
module ClusterManagement
|
34
|
+
class Task
|
35
|
+
attr_accessor :name
|
36
|
+
def initialize name
|
37
|
+
@name = name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_accessor :last_task
|
43
|
+
|
44
|
+
def rake_task name_or_options, &block
|
45
|
+
name = if name_or_options.is_a? Hash
|
46
|
+
name_or_options.first.first
|
47
|
+
else
|
48
|
+
name_or_options
|
49
|
+
end
|
50
|
+
task = Task.new name
|
51
|
+
block.call task if block
|
52
|
+
self.last_task = task
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
#
|
59
|
+
# Logger stub
|
60
|
+
#
|
61
|
+
module ClusterManagement
|
62
|
+
class << self
|
63
|
+
def logger
|
64
|
+
@logger ||= Logger.new nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 5
|
8
8
|
- 1
|
9
|
-
version: 0.
|
9
|
+
version: 0.5.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Alexey Petrushin
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-02-
|
17
|
+
date: 2011-02-09 00:00:00 +03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -29,9 +29,13 @@ extra_rdoc_files: []
|
|
29
29
|
files:
|
30
30
|
- Rakefile
|
31
31
|
- readme.md
|
32
|
+
- lib/cluster_management/cluster_management.rb
|
33
|
+
- lib/cluster_management/integration/vos.rb
|
32
34
|
- lib/cluster_management/package.rb
|
33
|
-
- lib/cluster_management/
|
35
|
+
- lib/cluster_management/support.rb
|
34
36
|
- lib/cluster_management.rb
|
37
|
+
- spec/package_spec.rb
|
38
|
+
- spec/spec_helper.rb
|
35
39
|
has_rdoc: true
|
36
40
|
homepage: http://github.com/alexeypetrushin/cluster_management
|
37
41
|
licenses: []
|