rubble 0.0.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.
- checksums.yaml +15 -0
- data/LICENSE.txt +674 -0
- data/README.md +29 -0
- data/bin/rubble +5 -0
- data/demo/applique/qed_test.rb +82 -0
- data/demo/applique/rubble_test.rb +33 -0
- data/demo/environment.md +32 -0
- data/demo/file_set.md +65 -0
- data/demo/logging.md +11 -0
- data/demo/server.md +53 -0
- data/demo/snapshot.md +32 -0
- data/demo/tool.md +36 -0
- data/lib/rubble.rb +15 -0
- data/lib/rubble/application.rb +82 -0
- data/lib/rubble/command/activate.rb +13 -0
- data/lib/rubble/command/base.rb +57 -0
- data/lib/rubble/command/upload.rb +28 -0
- data/lib/rubble/context.rb +33 -0
- data/lib/rubble/dsl.rb +31 -0
- data/lib/rubble/environment.rb +38 -0
- data/lib/rubble/executor/base.rb +134 -0
- data/lib/rubble/executor/local.rb +113 -0
- data/lib/rubble/executor/remote.rb +81 -0
- data/lib/rubble/file_set.rb +41 -0
- data/lib/rubble/logging.rb +23 -0
- data/lib/rubble/plan/base.rb +21 -0
- data/lib/rubble/plan/deploy.rb +11 -0
- data/lib/rubble/resource/base.rb +43 -0
- data/lib/rubble/resource/database.rb +8 -0
- data/lib/rubble/resource/fileset.rb +93 -0
- data/lib/rubble/resource/webapp.rb +22 -0
- data/lib/rubble/scope.rb +44 -0
- data/lib/rubble/server.rb +61 -0
- data/lib/rubble/snapshot.rb +21 -0
- data/lib/rubble/target/base.rb +24 -0
- data/lib/rubble/target/directory.rb +11 -0
- data/lib/rubble/target/mysql.rb +8 -0
- data/lib/rubble/target/tomcat.rb +20 -0
- data/lib/rubble/tool.rb +138 -0
- data/lib/rubble/version.rb +3 -0
- metadata +244 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'rubble/executor/base'
|
2
|
+
require 'rye'
|
3
|
+
require 'rubble/logging'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module Rubble
|
7
|
+
module Executor
|
8
|
+
class Remote < Base
|
9
|
+
attr_reader :box
|
10
|
+
attr_reader :server
|
11
|
+
attr_reader :local_executor
|
12
|
+
|
13
|
+
def initialize(server, local_executor)
|
14
|
+
super()
|
15
|
+
|
16
|
+
@server = server
|
17
|
+
@local_executor = local_executor
|
18
|
+
@box = Rye::Box.new(server.name, :safe => false)
|
19
|
+
end
|
20
|
+
|
21
|
+
def rsync_remote_prefix
|
22
|
+
"#{server.name}:"
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_exists?(file_name)
|
26
|
+
box.file_exists?(file_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def mkdir(directory)
|
30
|
+
@log.info("Creating directory '#{directory}'.")
|
31
|
+
exec('mkdir', '-p', directory.to_s)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cd(directory, create)
|
35
|
+
@log.info("Changing directory to #{directory}.")
|
36
|
+
if create then
|
37
|
+
mkdir directory
|
38
|
+
end
|
39
|
+
box.cd(directory.to_s)
|
40
|
+
end
|
41
|
+
|
42
|
+
def symlink(source, target)
|
43
|
+
@log.info("Symlinking #{source} to #{target}.")
|
44
|
+
run('ln', '-s', '-f', '-T', source.to_s, target.to_s)
|
45
|
+
end
|
46
|
+
|
47
|
+
def run(*command)
|
48
|
+
Logging.context(:server => server.name) do
|
49
|
+
command_str = Shellwords.join(command)
|
50
|
+
@log.debug(command_str)
|
51
|
+
box.execute(command_str)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def close
|
56
|
+
if not @box.nil? then
|
57
|
+
@box.disconnect
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def sync_up(filesets, target_dir, *options)
|
62
|
+
includes = rsync_includes(filesets)
|
63
|
+
parameters = includes.dirs.dup << (rsync_remote_prefix + target_dir).to_s
|
64
|
+
@local_executor.rsync(*parameters, :includes => includes.files, :recursive => true, :delete => true,
|
65
|
+
:delete_excluded => true)
|
66
|
+
end
|
67
|
+
|
68
|
+
def sync_down(filesets, target_dir, *options)
|
69
|
+
files = rsync_includes(filesets).map {|f| rsync_remote_prefix + f}
|
70
|
+
parameters = [target_dir].concat(files)
|
71
|
+
parameters.concat(options)
|
72
|
+
@local_executor.rsync *parameters
|
73
|
+
end
|
74
|
+
|
75
|
+
def sync_remote(source_dir, target_dir, *options)
|
76
|
+
parameters = [source_dir, target_dir, *options]
|
77
|
+
rsync *parameters
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Rubble
|
4
|
+
class FileSet
|
5
|
+
attr_reader :dir
|
6
|
+
attr_reader :files
|
7
|
+
|
8
|
+
def initialize(dir, *files)
|
9
|
+
@dir = Pathname.pwd + Pathname(dir)
|
10
|
+
if files.nil? then
|
11
|
+
@files = []
|
12
|
+
else
|
13
|
+
flattened_files = (files || []).collect {|f| Array(f)}.flatten
|
14
|
+
|
15
|
+
@files = flattened_files.map do |f|
|
16
|
+
p = (@dir + Pathname(f)).relative_path_from(@dir)
|
17
|
+
if p.to_s.start_with?('../') or p.to_s == '.' then
|
18
|
+
raise ArgumentError, "File name '#{f}' must be relative to base directory #{@dir} of the file set."
|
19
|
+
end
|
20
|
+
p
|
21
|
+
end
|
22
|
+
|
23
|
+
@files.sort!
|
24
|
+
end
|
25
|
+
|
26
|
+
@files.freeze
|
27
|
+
end
|
28
|
+
|
29
|
+
def paths
|
30
|
+
@files.map {|f| @dir + f}
|
31
|
+
end
|
32
|
+
|
33
|
+
def empty?
|
34
|
+
@files.empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
to_yaml
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'logging'
|
2
|
+
|
3
|
+
module Logging
|
4
|
+
class << self
|
5
|
+
def context(*options)
|
6
|
+
options.each do |option|
|
7
|
+
option.each do |k, v|
|
8
|
+
Logging.mdc[k] = v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
if block_given? then
|
13
|
+
yield
|
14
|
+
end
|
15
|
+
ensure
|
16
|
+
options.each do |option|
|
17
|
+
option.each do |k, v|
|
18
|
+
Logging.mdc.delete(k)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubble/dsl'
|
2
|
+
require 'docile'
|
3
|
+
|
4
|
+
module Rubble
|
5
|
+
module Plan
|
6
|
+
class Base
|
7
|
+
attr_reader :env
|
8
|
+
attr_reader :target
|
9
|
+
attr_reader :resource
|
10
|
+
attr_reader :server
|
11
|
+
def initialize(env, server, params)
|
12
|
+
@env = env
|
13
|
+
@server = server
|
14
|
+
params.each do |k, v|
|
15
|
+
@resource = k
|
16
|
+
@target = v
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubble/dsl'
|
2
|
+
require 'rubble/snapshot'
|
3
|
+
require 'digest'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module Rubble
|
7
|
+
module Resource
|
8
|
+
class Base
|
9
|
+
attr_reader :name
|
10
|
+
def initialize(name, *params)
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
self.class.name.split('::').last.downcase
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_version(filesets)
|
19
|
+
md = Digest::SHA1.new
|
20
|
+
filesets.each do |fileset|
|
21
|
+
fileset.paths.each do |path|
|
22
|
+
md.file(path)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
md.hexdigest.force_encoding('UTF-8')
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_filesets
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def snapshot
|
33
|
+
filesets = get_filesets
|
34
|
+
version = get_version(filesets)
|
35
|
+
Snapshot.new(version, *filesets)
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
to_yaml
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'rubble/resource/base'
|
2
|
+
require 'rubble/file_set'
|
3
|
+
require 'find'
|
4
|
+
require 'docile'
|
5
|
+
|
6
|
+
module Rubble
|
7
|
+
module Resource
|
8
|
+
class Directory
|
9
|
+
attr_reader :includes
|
10
|
+
attr_reader :excludes
|
11
|
+
dsl_accessor :hidden
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
@includes = []
|
16
|
+
@excludes = []
|
17
|
+
@default_includes = ['**/*']
|
18
|
+
@default_excludes = ['**/*~', '**/#*#']
|
19
|
+
@flags = File::FNM_PATHNAME
|
20
|
+
end
|
21
|
+
|
22
|
+
def includes(*pattern)
|
23
|
+
@includes.concat(Array(pattern))
|
24
|
+
end
|
25
|
+
|
26
|
+
def excludes(*pattern)
|
27
|
+
@excludes.concat(Array(pattern))
|
28
|
+
end
|
29
|
+
|
30
|
+
def hidden(*values)
|
31
|
+
if values.empty? then
|
32
|
+
(@flags & File.FNM_DOTMATCH) != 0
|
33
|
+
else
|
34
|
+
if values[0] then
|
35
|
+
@flags |= File.FNM_DOTMATCH
|
36
|
+
else
|
37
|
+
@flags &= ~File.FNM_DOTMATCH
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_fileset
|
43
|
+
files = []
|
44
|
+
dir = Pathname.new(@name)
|
45
|
+
|
46
|
+
Find.find(dir) do |path|
|
47
|
+
pathname = Pathname.new(path).relative_path_from(dir).to_s
|
48
|
+
|
49
|
+
if pathname != '.' then
|
50
|
+
match = (@includes.empty? ? @default_includes : @includes).any? {|p| File.fnmatch?(p, pathname, @flags)}
|
51
|
+
match = match and not (@excludes.empty? ? @default_excludes : @excludes).any? {|p| File.fnmatch?(p, pathname, @flags)}
|
52
|
+
|
53
|
+
if match then
|
54
|
+
if not File.directory?(path) then
|
55
|
+
files << pathname
|
56
|
+
end
|
57
|
+
else
|
58
|
+
if File.directory?(path) then
|
59
|
+
Find.prune
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
FileSet.new(dir.to_s, files)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Fileset < Base
|
70
|
+
def initialize(name, *params)
|
71
|
+
super(name, *params)
|
72
|
+
|
73
|
+
@directories = []
|
74
|
+
end
|
75
|
+
|
76
|
+
def directory(name, &block)
|
77
|
+
dir = Directory.new(name)
|
78
|
+
if not block.nil? then
|
79
|
+
Docile.dsl_eval(dir, &block)
|
80
|
+
end
|
81
|
+
@directories << dir
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_filesets
|
85
|
+
filesets = []
|
86
|
+
@directories.each do |directory|
|
87
|
+
filesets << directory.get_fileset
|
88
|
+
end
|
89
|
+
filesets
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubble/resource/base'
|
2
|
+
require 'rubble/file_set'
|
3
|
+
|
4
|
+
module Rubble
|
5
|
+
module Resource
|
6
|
+
class Webapp < Base
|
7
|
+
dsl_accessor :war
|
8
|
+
|
9
|
+
def initialize(name, *params)
|
10
|
+
super(name, *params)
|
11
|
+
|
12
|
+
@war = "target/#{name}.war"
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_filesets
|
16
|
+
dir = File.dirname(@war)
|
17
|
+
files = [File.basename(@war)]
|
18
|
+
[FileSet.new(dir, files)]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/rubble/scope.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Rubble
|
2
|
+
class Scope
|
3
|
+
attr_reader :environment
|
4
|
+
attr_reader :server
|
5
|
+
def initialize(environment, server)
|
6
|
+
@environment = environment
|
7
|
+
@server = server
|
8
|
+
end
|
9
|
+
|
10
|
+
def tool
|
11
|
+
@environment.tool
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure_plan(type, *params, &block)
|
15
|
+
plan = tool.create_plan(type, @environment, @server, *params)
|
16
|
+
|
17
|
+
if not block.nil? then
|
18
|
+
Docile.dsl_eval(plan, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
@environment.add_plan(plan)
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(symbol, *arguments, &block)
|
25
|
+
if tool.is_plan?(symbol) then
|
26
|
+
configure_plan(symbol, *arguments, &block)
|
27
|
+
elsif tool.is_target?(symbol) then
|
28
|
+
@server.provide_target(symbol, arguments[0])
|
29
|
+
elsif tool.is_resource?(symbol) then
|
30
|
+
tool.provide_resource(symbol, arguments[0])
|
31
|
+
else
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def respond_to?(symbol, include_private = false)
|
37
|
+
if tool.is_plan?(symbol) or tool.is_resource?(symbol) or tool.is_target?(symbol) then
|
38
|
+
true
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'logging'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'rubble/dsl'
|
4
|
+
|
5
|
+
module Rubble
|
6
|
+
class Server
|
7
|
+
attr_reader :tool
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :targets
|
10
|
+
dsl_accessor :rubble_dir
|
11
|
+
dsl_accessor :deploy_dir
|
12
|
+
dsl_accessor :user
|
13
|
+
dsl_accessor :group
|
14
|
+
|
15
|
+
def initialize(tool, name)
|
16
|
+
@tool = tool
|
17
|
+
@name = name
|
18
|
+
|
19
|
+
@log = Logging.logger[self]
|
20
|
+
@targets = {}
|
21
|
+
@rubble_dir = "/var/rubble"
|
22
|
+
@user = 'root'
|
23
|
+
@group = 'root'
|
24
|
+
@deploy_dir = '#{env.name}/#{resource.type}/#{resource.name}'
|
25
|
+
end
|
26
|
+
|
27
|
+
def provide_target(type, name)
|
28
|
+
group = @targets.fetch(type) do |k|
|
29
|
+
@targets[type] = {}
|
30
|
+
end
|
31
|
+
group.fetch(name) do |k|
|
32
|
+
group[name] = block_given? ? yield : @tool.create_target(type, name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def configure_target(type, name, *params, &block)
|
37
|
+
target = provide_target(type, name) do
|
38
|
+
@tool.create_target(type, name, *params)
|
39
|
+
end
|
40
|
+
if not block.nil? then
|
41
|
+
Docile.dsl_eval(target, &block)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(symbol, *arguments, &block)
|
46
|
+
if not @tool.nil? and @tool.is_target?(symbol) then
|
47
|
+
configure_target(symbol, *arguments, &block)
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def respond_to?(symbol, include_private = false)
|
54
|
+
if not @tool.nil? and @tool.is_target?(symbol) then
|
55
|
+
true
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|