gluez 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/gluez +3 -0
- data/lib/gluez.rb +129 -0
- data/lib/gluez/erb/engine.rb +19 -0
- data/lib/gluez/erb/vars.rb +19 -0
- data/lib/gluez/ext/string.rb +18 -0
- data/lib/gluez/formatter.rb +24 -0
- data/lib/gluez/impl/linux.rb +146 -0
- data/lib/gluez/impl/mac.rb +34 -0
- data/lib/gluez/option_wrapper.rb +20 -0
- metadata +64 -0
data/bin/gluez
ADDED
data/lib/gluez.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'gluez/ext/string'
|
4
|
+
|
5
|
+
require 'gluez/option_wrapper'
|
6
|
+
require 'gluez/formatter'
|
7
|
+
require 'gluez/erb/engine'
|
8
|
+
|
9
|
+
require 'gluez/impl/linux'
|
10
|
+
# require 'gluez/impl/mac'
|
11
|
+
|
12
|
+
module Gluez
|
13
|
+
|
14
|
+
def self.run(entries, cfg={})
|
15
|
+
|
16
|
+
cfg = {
|
17
|
+
:file_dir => "."
|
18
|
+
}.merge(cfg)
|
19
|
+
|
20
|
+
lines = []
|
21
|
+
lines << "#!/bin/bash"
|
22
|
+
# lines << "set -x"
|
23
|
+
lines << "set -e"
|
24
|
+
|
25
|
+
entries.each do |entry|
|
26
|
+
|
27
|
+
task, name, opts = entry
|
28
|
+
|
29
|
+
opts ||= {}
|
30
|
+
opts = OptionWrapper.new(opts)
|
31
|
+
|
32
|
+
name, setup, steps = Gluez::Impl::Linux.steps(cfg, task, name, opts)
|
33
|
+
entry[1] = name
|
34
|
+
|
35
|
+
fun = function_name(task, name)
|
36
|
+
|
37
|
+
lines << "function #{fun} {"
|
38
|
+
lines << setup if setup
|
39
|
+
|
40
|
+
notifies = []
|
41
|
+
opts[:notifies, Array.new].each do |notify|
|
42
|
+
notify_task, notify_name = notify
|
43
|
+
notify_fun = function_name(notify_task, notify_name)
|
44
|
+
|
45
|
+
notifies << notify_fun
|
46
|
+
|
47
|
+
unless entries.detect{|entry| entry[0] == notify_task && entry[1] == notify_name}
|
48
|
+
entries << [notify_task, notify_name, {:embedded => true}]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
add_steps(true, lines, [], [fun, steps], notifies)
|
53
|
+
|
54
|
+
lines << "}"
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
entries.each do |entry|
|
59
|
+
task, name, opts = entry
|
60
|
+
opts ||= {}
|
61
|
+
|
62
|
+
lines << function_name(task, name) unless opts[:embedded]
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
Formatter.format(lines.join("\n"))
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def self.function_name(task, name)
|
72
|
+
"#{task}_#{name}".gsub('/', '_').gsub(':', '_').gsub("@", "_").gsub("~", "_").gsub(".", "_")
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.add_steps(first, lines, completed, steps_wrapper, notifies)
|
76
|
+
|
77
|
+
fun, steps = steps_wrapper
|
78
|
+
|
79
|
+
if first
|
80
|
+
if steps.length == 2
|
81
|
+
add_steps(false, lines, [], [fun, steps], notifies)
|
82
|
+
else
|
83
|
+
checks = []
|
84
|
+
steps.each_with_index do |step, idx|
|
85
|
+
checks << step if idx % 2 == 0
|
86
|
+
end
|
87
|
+
|
88
|
+
lines << "if [[ #{checks.join(' && ')} ]]; then"
|
89
|
+
lines << " echo \"[ #{fun} ] up2date\""
|
90
|
+
lines << "else"
|
91
|
+
lines << " echo \"[ #{fun} ] NOT up2date\""
|
92
|
+
add_steps(false, lines, [], [fun, steps], notifies)
|
93
|
+
lines << "fi"
|
94
|
+
end
|
95
|
+
|
96
|
+
else
|
97
|
+
check, code = steps.slice!(0,2)
|
98
|
+
|
99
|
+
if check == "1 -eq 0"
|
100
|
+
completed << "1 -eq 1"
|
101
|
+
else
|
102
|
+
completed << check
|
103
|
+
end
|
104
|
+
|
105
|
+
lines << "if [[ #{check} ]]; then"
|
106
|
+
lines << " echo \"[ #{fun} ] up2date\""
|
107
|
+
lines << "else"
|
108
|
+
lines << " #{code}"
|
109
|
+
lines << " if [[ #{completed.join(' && ')} ]]; then"
|
110
|
+
lines << " echo \"[ #{fun} ] applied\""
|
111
|
+
lines << " else"
|
112
|
+
lines << " exit 1"
|
113
|
+
lines << " fi"
|
114
|
+
|
115
|
+
lines << "fi"
|
116
|
+
|
117
|
+
if steps.empty?
|
118
|
+
notifies.each do |notify|
|
119
|
+
lines << notify
|
120
|
+
end
|
121
|
+
else
|
122
|
+
add_steps(false, lines, completed, [fun, steps], notifies)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
require 'gluez/erb/vars'
|
5
|
+
|
6
|
+
module Gluez
|
7
|
+
module Erb
|
8
|
+
class Engine
|
9
|
+
def self.parse(content, vars={})
|
10
|
+
v = Gluez::Vars.new(vars)
|
11
|
+
|
12
|
+
erb = ERB.new(content)
|
13
|
+
content2 = erb.result(v.get_binding)
|
14
|
+
|
15
|
+
Base64.encode64(content2)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gluez
|
2
|
+
class Vars
|
3
|
+
def initialize(hash={})
|
4
|
+
hash.each_pair do |key, val|
|
5
|
+
self.metaclass.send(:define_method, key) do
|
6
|
+
val
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def metaclass
|
12
|
+
class << self; self; end
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_binding
|
16
|
+
binding
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class String
|
2
|
+
def strip2
|
3
|
+
unless self.empty?
|
4
|
+
lines = self.split("\n")
|
5
|
+
indent = 0
|
6
|
+
lines[0].each_char do |char|
|
7
|
+
if char == " "
|
8
|
+
indent += 1
|
9
|
+
else
|
10
|
+
break
|
11
|
+
end
|
12
|
+
end
|
13
|
+
lines.collect{|line| line.gsub(/^([ ]{0,#{indent}})/, "")}.join("\n")
|
14
|
+
else
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Gluez
|
2
|
+
class Formatter
|
3
|
+
def self.format(lines)
|
4
|
+
indent = 0
|
5
|
+
|
6
|
+
prev_line = nil
|
7
|
+
lines.split("\n").collect do |line|
|
8
|
+
line = line.strip
|
9
|
+
|
10
|
+
indent -= 2 if ['}', 'fi', 'else'].include?(line)
|
11
|
+
|
12
|
+
l = (' ' * indent) + line
|
13
|
+
indent += 2 if [/^function /, /^if /, /^else/].any?{|e| line =~ e}
|
14
|
+
|
15
|
+
indent -= 2 if line =~ /^data=/
|
16
|
+
indent += 2 if line == ')' && prev_line == 'DATA'
|
17
|
+
|
18
|
+
prev_line = line
|
19
|
+
|
20
|
+
l
|
21
|
+
end.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Gluez
|
2
|
+
module Impl
|
3
|
+
class Linux
|
4
|
+
def self.steps(cfg, task, name, opts)
|
5
|
+
|
6
|
+
setup = nil
|
7
|
+
steps = []
|
8
|
+
|
9
|
+
case task
|
10
|
+
when :gem
|
11
|
+
steps << "$(su -l #{opts[:user]} -c \"gem list | awk '{print \\$1}' | grep ^#{name}$ | wc -l\") -eq 1"
|
12
|
+
steps << "su -l #{opts[:user]} -c \"gem install #{name} --version #{opts[:version]} --user-install --no-rdoc --no-ri\""
|
13
|
+
|
14
|
+
name = "#{name}@#{opts[:user]}"
|
15
|
+
|
16
|
+
when :file
|
17
|
+
steps << "-f #{name}"
|
18
|
+
steps << "touch #{name}"
|
19
|
+
|
20
|
+
steps << "\"$(stat -L --format=%a #{name})\" = \"#{opts[:chmod, "644"]}\""
|
21
|
+
steps << "chmod #{opts[:chmod, "644"]} #{name}"
|
22
|
+
|
23
|
+
steps << "\"$(stat -L --format=%G:%U #{name})\" = \"#{opts[:chown, "root:root"]}\""
|
24
|
+
steps << "chown --no-dereference #{opts[:chown, "root:root"]} #{name}"
|
25
|
+
|
26
|
+
when :dir
|
27
|
+
steps << "-d #{name}"
|
28
|
+
steps << "mkdir #{name}"
|
29
|
+
|
30
|
+
steps << "\"$(stat -L --format=%a #{name})\" = \"#{opts[:chmod, "755"]}\""
|
31
|
+
steps << "chmod #{opts[:chmod, "755"]} #{name}"
|
32
|
+
|
33
|
+
steps << "\"$(stat -L --format=%G:%U #{name})\" = \"#{opts[:chown, "root:root"]}\""
|
34
|
+
steps << "chown --no-dereference #{opts[:chown, "root:root"]} #{name}"
|
35
|
+
|
36
|
+
when :package
|
37
|
+
steps << "$(apt-cache policy #{name} | grep Installed | wc -l) -eq 1 && $(apt-cache policy #{name} | grep Installed | grep '(none)' | wc -l) -eq 0"
|
38
|
+
steps << "apt-get install #{name} --yes"
|
39
|
+
|
40
|
+
when :transfer
|
41
|
+
raw = File.read(cfg[:file_dir] + "/files/" + opts[:source])
|
42
|
+
|
43
|
+
content = Gluez::Erb::Engine.parse(raw, opts[:vars, {}])
|
44
|
+
|
45
|
+
setup = <<-CMD
|
46
|
+
data=$(cat <<\\DATA
|
47
|
+
#{content.strip}
|
48
|
+
DATA
|
49
|
+
)
|
50
|
+
CMD
|
51
|
+
|
52
|
+
steps << "-f #{name}"
|
53
|
+
steps << "touch #{name}"
|
54
|
+
|
55
|
+
steps << "\"$(stat -L --format=%a #{name})\" = \"#{opts[:chmod, "644"]}\""
|
56
|
+
steps << "chmod #{opts[:chmod, "644"]} #{name}"
|
57
|
+
|
58
|
+
steps << "\"$(stat -L --format=%G:%U #{name})\" = \"#{opts[:chown, "root:root"]}\""
|
59
|
+
steps << "chown --no-dereference #{opts[:chown, "root:root"]} #{name}"
|
60
|
+
|
61
|
+
steps << "\"$(echo -n $data | base64 -i -d | md5sum - | awk '{print $1}')\" = \"$(md5sum #{name} | awk '{print $1}')\""
|
62
|
+
steps << "echo -n ${data} | base64 -i -d > #{name}"
|
63
|
+
|
64
|
+
when :group
|
65
|
+
steps << "$(cat /etc/group | grep ^#{name}: | wc -l) -eq 1"
|
66
|
+
steps << "groupadd --gid #{opts[:gid]} #{name}"
|
67
|
+
|
68
|
+
when :user
|
69
|
+
steps << "$(cat /etc/passwd | grep ^#{name}: | wc -l) -eq 1"
|
70
|
+
steps << "useradd --create-home --uid #{opts[:uid]} --gid #{opts[:gid]} --shell #{opts[:shell, "/bin/bash"]} #{name}"
|
71
|
+
|
72
|
+
when :start
|
73
|
+
setup = "service --status-all 1>/tmp/gluez.tmp 2>&1"
|
74
|
+
steps << "\"$(grep #{name} /tmp/gluez.tmp | wc -l)\" = \"1\" && \"$(service #{name} status | grep -E 'is running|start/running' | wc -l)\" = \"1\""
|
75
|
+
steps << "service #{name} start"
|
76
|
+
|
77
|
+
when :stop
|
78
|
+
setup = "service --status-all 1>/tmp/gluez.tmp 2>&1"
|
79
|
+
steps << "\"$(grep #{name} /tmp/gluez.tmp | wc -l)\" = \"1\" && \"$(service #{name} status | grep -E 'is running|start/running' | wc -l)\" = \"0\""
|
80
|
+
steps << "service #{name} stop"
|
81
|
+
|
82
|
+
when :restart
|
83
|
+
setup = "service --status-all 1>/tmp/gluez.tmp 2>&1"
|
84
|
+
steps << "1 -eq 0"
|
85
|
+
steps << <<-CODE
|
86
|
+
if [[ "$(grep #{name} /tmp/gluez.tmp | wc -l)" = "1" && "$(service #{name} status | grep -E 'is running|start/running' | wc -l)" = "1" ]]; then
|
87
|
+
service #{name} restart
|
88
|
+
else
|
89
|
+
service #{name} start
|
90
|
+
fi
|
91
|
+
CODE
|
92
|
+
|
93
|
+
when :bash
|
94
|
+
steps << opts[:not_if]
|
95
|
+
steps << "su -l #{opts[:user, 'root']} -c '#{opts[:code]}'"
|
96
|
+
|
97
|
+
when :link
|
98
|
+
steps << "-L #{name} && $(file #{name} | grep \"#{name}: symbolic link to \\`#{opts[:target]}'\" | wc -l) -eq 1"
|
99
|
+
steps << "ln -f -s #{opts[:target]} #{name}"
|
100
|
+
|
101
|
+
steps << "\"$(stat --format=%G:%U #{name})\" = \"#{opts[:chown]}\""
|
102
|
+
steps << "chown --no-dereference #{opts[:chown]} #{name}"
|
103
|
+
|
104
|
+
when :enable
|
105
|
+
steps << "$(update-rc.d -n -f #{name} remove | grep '/etc/rc' | wc -l) -gt 0"
|
106
|
+
steps << "/usr/sbin/update-rc.d #{name} defaults"
|
107
|
+
|
108
|
+
when :disable
|
109
|
+
steps << "$(update-rc.d -n -f #{name} remove | grep '/etc/rc' | wc -l) -eq 0"
|
110
|
+
steps << "/usr/sbin/update-rc.d -f #{name} remove"
|
111
|
+
|
112
|
+
when :source
|
113
|
+
user = opts[:user, "root"]
|
114
|
+
home_dir = (user != "root") ? "/home/#{opts[:user]}" : "/root"
|
115
|
+
|
116
|
+
steps << "-d #{home_dir}/tmp"
|
117
|
+
steps << "mkdir #{home_dir}/tmp && chown #{user}:#{user} #{home_dir}/tmp"
|
118
|
+
|
119
|
+
steps << "-f #{opts[:binary]}"
|
120
|
+
steps << <<-CODE
|
121
|
+
[ -f #{home_dir}/tmp/#{opts[:filename]} ] && rm #{home_dir}/tmp/#{opts[:filename]}
|
122
|
+
[ -d #{home_dir}/tmp/#{opts[:folder]} ] && rm -rf #{home_dir}/tmp/#{opts[:folder]}
|
123
|
+
|
124
|
+
wget --no-check-certificate -O #{home_dir}/tmp/#{opts[:filename]} #{name}
|
125
|
+
|
126
|
+
chown #{user}:#{user} #{home_dir}/tmp/#{opts[:filename]}
|
127
|
+
|
128
|
+
tar -C #{home_dir}/tmp/ -x#{opts[:filename] =~ /\.tar\.bz2/ ? "j" : "z"}f #{home_dir}/tmp/#{opts[:filename]}
|
129
|
+
|
130
|
+
chown -R #{user}:#{user} #{home_dir}/tmp/#{opts[:folder]}
|
131
|
+
|
132
|
+
su -l #{user} -c 'cd #{home_dir}/tmp/#{opts[:folder]} && #{opts[:steps].join(' && ')}'
|
133
|
+
|
134
|
+
chown -R #{user}:#{user} #{home_dir}/tmp/#{opts[:folder].split('/').first}
|
135
|
+
CODE
|
136
|
+
|
137
|
+
else
|
138
|
+
raise "unsupported task: #{task}, name: #{name}, opts: #{opts.inspect}"
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
[name, setup, steps]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Gluez
|
2
|
+
module Impl
|
3
|
+
class Mac
|
4
|
+
def self.steps(cfg, task, name, opts)
|
5
|
+
|
6
|
+
setup = nil
|
7
|
+
steps = []
|
8
|
+
|
9
|
+
case task
|
10
|
+
|
11
|
+
when :group
|
12
|
+
steps << "$(/usr/bin/dscl . -list Groups | grep ^#{name}$ | wc -l) -eq 1"
|
13
|
+
steps << "$(/usr/bin/dscl . -create /Groups/#{name} PrimaryGroupID #{opts[:gid]})"
|
14
|
+
|
15
|
+
when :user
|
16
|
+
steps << "$(/usr/bin/dscl . -list Users | grep ^#{name}$ | wc -l) -eq 1"
|
17
|
+
steps << "$(/usr/bin/dscl . -create /Users/#{name} UniqueID #{opts[:uid]} PrimaryGroupID #{opts[:gid]} UserShell #{opts[:shell, "/bin/bash"]} NFSHomeDir /Users/#{name})"
|
18
|
+
|
19
|
+
steps << "-d /Users/#{name}"
|
20
|
+
steps << "mkdir /Users/#{name}"
|
21
|
+
|
22
|
+
steps << "\"$(stat -L -f %Sg:%Su /Users/#{name})\" = \"#{name}:#{name}\""
|
23
|
+
steps << "chown #{name}:#{name} /Users/#{name}"
|
24
|
+
|
25
|
+
else
|
26
|
+
raise "unsupported task: #{task}, name: #{name}, opts: #{opts.inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
[name, setup, steps]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Gluez
|
2
|
+
class OptionWrapper
|
3
|
+
def initialize(options)
|
4
|
+
@options = options
|
5
|
+
end
|
6
|
+
|
7
|
+
def [](name, default=nil)
|
8
|
+
value = @options[name]
|
9
|
+
if value
|
10
|
+
value
|
11
|
+
else
|
12
|
+
if default
|
13
|
+
default
|
14
|
+
else
|
15
|
+
raise "missing option: #{name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gluez
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: "0.1"
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jan Zimmek
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-01 00:00:00 +02:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: a server configuration toolkit
|
18
|
+
email: jan.zimmek@web.de
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files: []
|
24
|
+
|
25
|
+
files:
|
26
|
+
- lib/gluez/erb/engine.rb
|
27
|
+
- lib/gluez/erb/vars.rb
|
28
|
+
- lib/gluez/ext/string.rb
|
29
|
+
- lib/gluez/formatter.rb
|
30
|
+
- lib/gluez/impl/linux.rb
|
31
|
+
- lib/gluez/impl/mac.rb
|
32
|
+
- lib/gluez/option_wrapper.rb
|
33
|
+
- lib/gluez.rb
|
34
|
+
- bin/gluez
|
35
|
+
has_rdoc: true
|
36
|
+
homepage:
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.6.2
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: a server configuration toolkit
|
63
|
+
test_files: []
|
64
|
+
|