gluez 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/gluez ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+
3
+ # /usr/bin/env ruby "require gluez; Gluez::run"
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
+