inprovise 0.2.4 → 0.2.5

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.
@@ -9,10 +9,11 @@ class Inprovise::Controller
9
9
 
10
10
  class << self
11
11
 
12
+ private
13
+
12
14
  def controllers
13
15
  @controllers ||= Array.new.extend(MonitorMixin)
14
16
  end
15
- private :controllers
16
17
 
17
18
  def add(ctrl)
18
19
  controllers.synchronize do
@@ -20,28 +21,24 @@ class Inprovise::Controller
20
21
  end
21
22
  ctrl
22
23
  end
23
- private :add
24
24
 
25
25
  def head
26
26
  controllers.synchronize do
27
27
  return controllers.first
28
28
  end
29
29
  end
30
- private :head
31
30
 
32
31
  def shift
33
32
  controllers.synchronize do
34
33
  return controllers.shift
35
34
  end
36
35
  end
37
- private :shift
38
36
 
39
37
  def empty?
40
38
  controllers.synchronize do
41
39
  return controllers.empty?
42
40
  end
43
41
  end
44
- private :empty?
45
42
 
46
43
  def get_value(v)
47
44
  begin
@@ -50,14 +47,19 @@ class Inprovise::Controller
50
47
  v
51
48
  end
52
49
  end
53
- private :get_value
54
50
 
55
- def list_scripts(options)
51
+ def load_schemes(options)
56
52
  # load all specified schemes
57
53
  (Array === options[:scheme] ? options[:scheme] : [options[:scheme]]).each {|s| Inprovise::DSL.include(s) }
54
+ end
55
+
56
+ public
57
+
58
+ def list_scripts(options)
59
+ load_schemes(options)
58
60
  $stdout.puts
59
- $stdout.puts " PROVISIONING SCRIPTS"
60
- $stdout.puts " ===================="
61
+ $stdout.puts ' PROVISIONING SCRIPTS'
62
+ $stdout.puts ' ===================='
61
63
  Inprovise::ScriptIndex.default.scripts.sort.each do |scrname|
62
64
  script = Inprovise::ScriptIndex.default.get(scrname)
63
65
  if script.description || options[:all]
@@ -66,8 +68,8 @@ class Inprovise::Controller
66
68
  end
67
69
  end
68
70
 
69
- def parse_config(cfg, opts = {})
70
- cfg.inject(opts) do |rc,cfg|
71
+ def parse_config(cfglist, opts = {})
72
+ cfglist.inject(opts) do |rc, cfg|
71
73
  k,v = cfg.split('=')
72
74
  k = k.split('.')
73
75
  h = rc
@@ -92,8 +94,7 @@ class Inprovise::Controller
92
94
  run_group_command(command, options, *args)
93
95
  end
94
96
  else # :apply, :revert, :validate or :trigger
95
- # load all specified schemes
96
- (Array === options[:scheme] ? options[:scheme] : [options[:scheme]]).each {|s| Inprovise::DSL.include(s) }
97
+ load_schemes(options)
97
98
  # extract config
98
99
  cfg = parse_config(options[:config])
99
100
  # get script/action
@@ -129,11 +130,13 @@ class Inprovise::Controller
129
130
  end
130
131
 
131
132
  def run_node_command(cmd, options, *names)
132
- add(Inprovise::Controller.new).run_node_command(cmd, options, *names)
133
+ add(Inprovise::Controller.new).send(:"#{cmd}_node", options, *names)
134
+ Inprovise::Infrastructure.save
133
135
  end
134
136
 
135
137
  def run_group_command(cmd, options, *names)
136
- add(Inprovise::Controller.new).run_group_command(cmd, options, *names)
138
+ add(Inprovise::Controller.new).send(:"#{cmd}_group", options, *names)
139
+ Inprovise::Infrastructure.save
137
140
  end
138
141
 
139
142
  def run_provisioning_command(command, script, opts, *targets)
@@ -183,93 +186,93 @@ class Inprovise::Controller
183
186
  end
184
187
  end
185
188
 
186
- def run_node_command(command, options, *names)
187
- case command
188
- when :add
189
- opts = self.class.parse_config(options[:config], { host: options[:address] })
190
- opts[:credentials] = self.class.parse_config(options[:credential])
191
- @targets << (node = Inprovise::Infrastructure::Node.new(names.first, opts))
189
+ def add_node(options, *names)
190
+ opts = self.class.parse_config(options[:config], { host: options[:address] })
191
+ opts[:credentials] = self.class.parse_config(options[:credential])
192
+ @targets << (node = Inprovise::Infrastructure::Node.new(names.first, opts))
192
193
 
193
- Inprovise.log.local("Adding #{node.to_s}")
194
+ Inprovise.log.local("Adding #{node}")
194
195
 
195
- Inprovise::Sniffer.run_sniffers_for(node) if options[:sniff]
196
+ Inprovise::Sniffer.run_sniffers_for(node) if options[:sniff]
196
197
 
197
- options[:group].each do |g|
198
- grp = Inprovise::Infrastructure.find(g)
199
- raise ArgumentError, "Unknown group #{g}" unless grp
200
- node.add_to(grp)
201
- end
202
- when :remove
203
- names.each do |name|
204
- node = Inprovise::Infrastructure.find(name)
205
- raise ArgumentError, "Invalid node #{name}" unless node && node.is_a?(Inprovise::Infrastructure::Node)
198
+ options[:group].each do |g|
199
+ grp = Inprovise::Infrastructure.find(g)
200
+ raise ArgumentError, "Unknown group #{g}" unless grp
201
+ node.add_to(grp)
202
+ end
203
+ end
206
204
 
207
- Inprovise.log.local("Removing #{node.to_s}")
205
+ def remove_node(_options, *names)
206
+ names.each do |name|
207
+ node = Inprovise::Infrastructure.find(name)
208
+ raise ArgumentError, "Invalid node #{name}" unless node && node.is_a?(Inprovise::Infrastructure::Node)
208
209
 
209
- Inprovise::Infrastructure.deregister(name)
210
- end
211
- when :update
212
- @targets = names.collect do |name|
213
- tgt = Inprovise::Infrastructure.find(name)
214
- raise ArgumentError, "Unknown target [#{name}]" unless tgt
215
- tgt.targets
216
- end.flatten.uniq
217
- opts = self.class.parse_config(options[:config])
218
- opts[:credentials] = self.class.parse_config(options[:credential])
219
- if Inprovise.sequential || (!options[:sniff]) || @targets.size == 1
220
- @targets.each {|tgt| run_target_update(tgt, opts.dup, options) }
221
- else
222
- threads = @targets.map {|tgt| Thread.new { run_target_update(tgt, opts.dup, options) } }
223
- threads.each {|t| t.join }
224
- end
210
+ Inprovise.log.local("Removing #{node}")
211
+
212
+ Inprovise::Infrastructure.deregister(name)
225
213
  end
226
- Inprovise::Infrastructure.save
227
214
  end
228
215
 
229
- def run_group_command(command, options, *names)
230
- case command
231
- when :add
232
- options[:target].each {|t| raise ArgumentError, "Unknown target [#{t}]" unless Inprovise::Infrastructure.find(t) }
233
- opts = self.class.parse_config(options[:config])
234
- grp = Inprovise::Infrastructure::Group.new(names.first, opts, options[:target])
216
+ def update_node(options, *names)
217
+ @targets = names.collect do |name|
218
+ tgt = Inprovise::Infrastructure.find(name)
219
+ raise ArgumentError, "Unknown target [#{name}]" unless tgt
220
+ tgt.targets
221
+ end.flatten.uniq
222
+ opts = self.class.parse_config(options[:config])
223
+ opts[:credentials] = self.class.parse_config(options[:credential])
224
+ if Inprovise.sequential || (!options[:sniff]) || @targets.size == 1
225
+ @targets.each {|tgt| run_target_update(tgt, opts.dup, options) }
226
+ else
227
+ threads = @targets.map {|tgt| Thread.new { run_target_update(tgt, opts.dup, options) } }
228
+ threads.each {|t| t.join }
229
+ end
230
+ end
235
231
 
236
- Inprovise.log.local("Adding #{grp.to_s}")
232
+ def add_group(options, *names)
233
+ options[:target].each {|t| raise ArgumentError, "Unknown target [#{t}]" unless Inprovise::Infrastructure.find(t) }
234
+ opts = self.class.parse_config(options[:config])
235
+ grp = Inprovise::Infrastructure::Group.new(names.first, opts, options[:target])
237
236
 
238
- options[:target].each do |t|
239
- tgt = Inprovise::Infrastructure.find(t)
240
- raise ArgumentError, "Unknown target #{t}" unless tgt
241
- tgt.add_to(grp)
242
- end
243
- when :remove
244
- names.each do |name|
245
- grp = Inprovise::Infrastructure.find(name)
246
- raise ArgumentError, "Invalid group #{name}" unless grp && grp.is_a?(Inprovise::Infrastructure::Group)
237
+ Inprovise.log.local("Adding #{grp}")
247
238
 
248
- Inprovise.log.local("Removing #{grp.to_s}")
239
+ options[:target].each do |t|
240
+ tgt = Inprovise::Infrastructure.find(t)
241
+ raise ArgumentError, "Unknown target #{t}" unless tgt
242
+ tgt.add_to(grp)
243
+ end
244
+ end
249
245
 
250
- Inprovise::Infrastructure.deregister(name)
251
- end
252
- when :update
253
- groups = names.collect do |name|
254
- grp = Inprovise::Infrastructure.find(name)
255
- raise ArgumentError, "Invalid group #{name}" unless grp && grp.is_a?(Inprovise::Infrastructure::Group)
256
- grp
257
- end
258
- opts = self.class.parse_config(options[:config])
259
- grp_tgts = options[:target].collect do |t|
260
- tgt = Inprovise::Infrastructure.find(t)
261
- raise ArgumentError, "Unknown target #{t}" unless tgt
262
- tgt
263
- end
264
- groups.each do |grp|
265
- Inprovise.log.local("Updating #{grp.to_s}")
266
-
267
- grp.config.clear if options[:reset]
268
- grp.config.merge!(opts)
269
- grp_tgts.each {|tgt| tgt.add_to(grp) }
270
- end
246
+ def remove_group(_options, *names)
247
+ names.each do |name|
248
+ grp = Inprovise::Infrastructure.find(name)
249
+ raise ArgumentError, "Invalid group #{name}" unless grp && grp.is_a?(Inprovise::Infrastructure::Group)
250
+
251
+ Inprovise.log.local("Removing #{grp}")
252
+
253
+ Inprovise::Infrastructure.deregister(name)
254
+ end
255
+ end
256
+
257
+ def update_group(options, *names)
258
+ groups = names.collect do |name|
259
+ tgt = Inprovise::Infrastructure.find(name)
260
+ raise ArgumentError, "Invalid group #{name}" unless tgt && tgt.is_a?(Inprovise::Infrastructure::Group)
261
+ tgt
262
+ end
263
+ opts = self.class.parse_config(options[:config])
264
+ grp_tgts = options[:target].collect do |tnm|
265
+ tgt = Inprovise::Infrastructure.find(tnm)
266
+ raise ArgumentError, "Unknown target #{tnm}" unless tgt
267
+ tgt
268
+ end
269
+ groups.each do |grp|
270
+ Inprovise.log.local("Updating #{grp}")
271
+
272
+ grp.config.clear if options[:reset]
273
+ grp.config.merge!(opts)
274
+ grp_tgts.each {|gt| gt.add_to(grp) }
271
275
  end
272
- Inprovise::Infrastructure.save
273
276
  end
274
277
 
275
278
  private
@@ -298,7 +301,7 @@ class Inprovise::Controller
298
301
  end
299
302
 
300
303
  def run_target_update(tgt, tgt_opts, options)
301
- Inprovise.log.local("Updating #{tgt.to_s}")
304
+ Inprovise.log.local("Updating #{tgt}")
302
305
 
303
306
  if options[:reset]
304
307
  # preserve :host
@@ -3,6 +3,8 @@
3
3
  # Author:: Martin Corino
4
4
  # License:: Distributes under the same license as Ruby
5
5
 
6
+ # :nocov:
7
+
6
8
  Inprovise::CmdHelper.define('cygwin', Inprovise::CmdHelper.implementations['linux']) do
7
9
 
8
10
  def initialize(channel)
@@ -41,3 +43,6 @@ Inprovise::CmdHelper.define('cygwin', Inprovise::CmdHelper.implementations['linu
41
43
  # basic commands
42
44
 
43
45
  end
46
+
47
+ # :nocov:
48
+
@@ -3,6 +3,8 @@
3
3
  # Author:: Martin Corino
4
4
  # License:: Distributes under the same license as Ruby
5
5
 
6
+ # :nocov:
7
+
6
8
  Inprovise::CmdHelper.define('linux') do
7
9
 
8
10
  def initialize(channel, sudo=false)
@@ -48,11 +50,11 @@ Inprovise::CmdHelper.define('linux') do
48
50
  # file management
49
51
 
50
52
  def upload(from, to)
51
- @channel.upload(real_path(from), real_path(to))
53
+ @channel.upload(from, real_path(to))
52
54
  end
53
55
 
54
56
  def download(from, to)
55
- @channel.download(real_path(from), real_path(to))
57
+ @channel.download(real_path(from), to)
56
58
  end
57
59
 
58
60
  # basic commands
@@ -101,7 +103,7 @@ Inprovise::CmdHelper.define('linux') do
101
103
  def directory?(path)
102
104
  path = real_path(path)
103
105
  begin
104
- @channel.file?(path)
106
+ @channel.directory?(path)
105
107
  rescue
106
108
  (exec("stat --format=%f #{path}").chomp.hex & 0x4000) == 0x4000
107
109
  end
@@ -185,3 +187,6 @@ Inprovise::CmdHelper.define('linux') do
185
187
  end
186
188
 
187
189
  end
190
+
191
+ # :nocov:
192
+
@@ -5,6 +5,8 @@
5
5
 
6
6
  require 'digest/sha1'
7
7
 
8
+ # :nocov:
9
+
8
10
  Inprovise::CmdHelper.define('windows') do
9
11
 
10
12
  # platform properties
@@ -125,3 +127,5 @@ Inprovise::CmdHelper.define('windows') do
125
127
  end
126
128
 
127
129
  end
130
+
131
+ # :nocov:
@@ -253,7 +253,7 @@ class Inprovise::Infrastructure::Node < Inprovise::Infrastructure::Target
253
253
  @history << {cmd:cmd, output:output}
254
254
  output
255
255
  rescue Exception
256
- raise RuntimeError, "Failed to communicate with [#{self.to_s}]"
256
+ raise RuntimeError, "Failed to communicate with [#{self}]"
257
257
  end
258
258
  end
259
259
 
@@ -5,6 +5,8 @@
5
5
 
6
6
  Inprovise::Sniffer.define('linux', false) do
7
7
 
8
+ # :nocov:
9
+
8
10
  action('main') do |attrs|
9
11
  attrs[:machine] = run('uname -m').chomp
10
12
  if remote('/etc/os-release').exists?
@@ -61,4 +63,6 @@ Inprovise::Sniffer.define('linux', false) do
61
63
  end
62
64
  end
63
65
 
66
+ # :nocov:
67
+
64
68
  end
@@ -5,6 +5,8 @@
5
5
 
6
6
  Inprovise::Sniffer.define('platform') do
7
7
 
8
+ # :nocov:
9
+
8
10
  action('helper') do |attrs|
9
11
  # determin the best CmdHelper if not user defined
10
12
  attrs[:helper] = case attrs[:os]
@@ -39,6 +41,8 @@ Inprovise::Sniffer.define('platform') do
39
41
  (node.config[:attributes][:platform] ||= {}).merge!(attrs)
40
42
  end
41
43
 
44
+ # :nocov:
45
+
42
46
  end
43
47
 
44
48
  require_relative './windows.rb'
@@ -5,6 +5,8 @@
5
5
 
6
6
  Inprovise::Sniffer.define('windows', false) do
7
7
 
8
+ # :nocov:
9
+
8
10
  action('main') do |attrs|
9
11
  attrs[:machine] = env('PROCESSOR_ARCHITECTURE').chomp =~ /amd64/i ? 'x86_64' : 'x86'
10
12
  osver = run('cmd /c ver').strip
@@ -29,4 +31,6 @@ Inprovise::Sniffer.define('windows', false) do
29
31
  end
30
32
  end
31
33
 
34
+ # :nocov:
35
+
32
36
  end
@@ -19,7 +19,7 @@ class Inprovise::Template
19
19
  end
20
20
 
21
21
  def render_to_tempfile(locals={})
22
- basename = @path.respond_to?(:call) ? 'inprovise-inline-tpl' : File.basename(@path).gsub('.', '-')
22
+ basename = @path.respond_to?(:call) ? 'inprovise-inline-tpl' : File.basename(@path).tr('.', '-')
23
23
  file = Tempfile.new(basename)
24
24
  file.write render(locals)
25
25
  file.close
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Inprovise
7
7
 
8
- VERSION = '0.2.4'
8
+ VERSION = '0.2.5'
9
9
 
10
10
  end
@@ -0,0 +1,189 @@
1
+ # ScriptRunner tests for Inprovise
2
+ #
3
+ # Author:: Martin Corino
4
+ # License:: Distributes under the same license as Ruby
5
+
6
+ require_relative 'test_helper'
7
+
8
+ describe Inprovise::CmdHelper do
9
+ before :each do
10
+ @node = Inprovise::Infrastructure::Node.new('myNode', {channel: 'test', helper: 'linux'})
11
+ end
12
+
13
+ after :each do
14
+ reset_infrastructure!
15
+ end
16
+
17
+ describe 'helper' do
18
+
19
+ describe 'platform specifics' do
20
+ it 'provides appropriate administrator account' do
21
+ @node.helper.admin_user.must_equal 'root'
22
+ end
23
+
24
+ it 'provides appropriate environment variable format' do
25
+ @node.helper.env_reference('VAR').must_equal '$VAR'
26
+ end
27
+ end
28
+
29
+ describe 'working directory' do
30
+ it 'manages working directory' do
31
+ @node.channel.expects(:run).with('pwd', false).returns('/root')
32
+ @node.helper.cwd.must_equal '/root'
33
+ end
34
+
35
+ it 'returns old cwd on setting cwd' do
36
+ @node.helper.set_cwd('/home/user').must_be_nil
37
+ @node.helper.cwd.must_equal '/home/user'
38
+ @node.helper.set_cwd('/root').must_equal '/home/user'
39
+ @node.helper.cwd.must_equal '/root'
40
+ @node.helper.set_cwd(nil).must_equal '/root'
41
+ @node.channel.expects(:run).with('pwd', false).returns('/root')
42
+ @node.helper.cwd.must_equal '/root'
43
+ end
44
+ end
45
+
46
+ describe 'command execution' do
47
+ it 'runs commands' do
48
+ @node.channel.expects(:run).with('echo ok', false).returns('ok')
49
+ @node.helper.run('echo ok').must_equal 'ok'
50
+ end
51
+
52
+ it 'runs sudo commands' do
53
+ @node.channel.expects(:run).with('sudo sh -c "echo ok"', false).returns('ok')
54
+ @node.helper.sudo.run('echo ok').must_equal 'ok'
55
+ end
56
+
57
+ it 'runs commands in cwd' do
58
+ @node.helper.set_cwd('/home/user')
59
+ @node.channel.expects(:run).with('cd /home/user; echo ok', false).returns('ok')
60
+ @node.helper.run('echo ok').must_equal 'ok'
61
+ end
62
+ end
63
+
64
+ describe 'file transfer' do
65
+ it 'uploads files' do
66
+ @node.channel.expects(:upload).with('/from/path', '/to/path')
67
+ @node.helper.upload('/from/path', '/to/path')
68
+ end
69
+
70
+ it 'downloads files' do
71
+ @node.channel.expects(:download).with('/from/path', '/to/path')
72
+ @node.helper.download('/from/path', '/to/path')
73
+ end
74
+
75
+ it 'uploads files with changed cwd' do
76
+ @node.helper.set_cwd('/home/user')
77
+ @node.channel.expects(:upload).with('/from/path', '/home/user/to/path')
78
+ @node.helper.upload('/from/path', 'to/path')
79
+ end
80
+
81
+ it 'downloads files with changed cwd' do
82
+ @node.helper.set_cwd('/home/user')
83
+ @node.channel.expects(:download).with('/home/user/from/path', '/to/path')
84
+ @node.helper.download('from/path', '/to/path')
85
+ end
86
+ end
87
+
88
+ describe 'file management' do
89
+
90
+ it 'returns file content' do
91
+ @node.channel.expects(:content).with('/file/path')
92
+ @node.helper.cat('/file/path')
93
+ end
94
+
95
+ it 'returns file content from cwd' do
96
+ @node.helper.set_cwd('/home/user')
97
+ @node.channel.expects(:content).with('/home/user/file/path')
98
+ @node.helper.cat('file/path')
99
+ end
100
+
101
+ it 'creates a directory' do
102
+ @node.channel.expects(:run).with('mkdir -p /dir/path', false)
103
+ @node.helper.mkdir('/dir/path')
104
+ end
105
+
106
+ it 'creates a directory from cwd' do
107
+ @node.helper.set_cwd('/home/user')
108
+ @node.channel.expects(:run).with('mkdir -p /home/user/dir/path', false)
109
+ @node.helper.mkdir('dir/path')
110
+ end
111
+
112
+ it 'checks path existence' do
113
+ @node.channel.expects(:exists?).with('/file/path').returns(true)
114
+ @node.helper.exists?('/file/path').must_equal true
115
+ end
116
+
117
+ it 'check file existence' do
118
+ @node.channel.expects(:file?).with('/file/path').returns(true)
119
+ @node.helper.file?('/file/path').must_equal true
120
+ end
121
+
122
+ it 'checks directory existence' do
123
+ @node.channel.expects(:directory?).with('/dir/path').returns(true)
124
+ @node.helper.directory?('/dir/path').must_equal true
125
+ end
126
+
127
+ it 'copies files' do
128
+ @node.channel.expects(:run).with("cp /from/path /to/path", false)
129
+ @node.helper.copy('/from/path', '/to/path')
130
+ end
131
+
132
+ it 'moves files' do
133
+ @node.channel.expects(:run).with("mv /from/path /to/path", false)
134
+ @node.helper.move('/from/path', '/to/path')
135
+ end
136
+
137
+ it 'deletes files' do
138
+ @node.channel.expects(:delete).with('/file/path')
139
+ @node.helper.delete('/file/path')
140
+ end
141
+
142
+ it 'returns file permissions' do
143
+ @node.channel.expects(:permissions).with('/file/path').returns(0755)
144
+ @node.helper.permissions('/file/path').must_equal 0755
145
+ end
146
+
147
+ it 'sets file permissions' do
148
+ @node.channel.expects(:set_permissions).with('/file/path', 0755)
149
+ @node.helper.set_permissions('/file/path', 0755)
150
+ end
151
+
152
+ it 'returns file owner' do
153
+ @node.channel.expects(:owner).with('/file/path').returns({ :user => 'me', :group => 'them' })
154
+ @node.helper.owner('/file/path').must_equal({ :user => 'me', :group => 'them' })
155
+ end
156
+
157
+ it 'sets file owner' do
158
+ @node.channel.expects(:set_owner).with('/file/path', 'me','them')
159
+ @node.helper.set_owner('/file/path', 'me','them')
160
+ end
161
+
162
+ end
163
+
164
+ describe 'shell utilities' do
165
+
166
+ it 'echoes' do
167
+ @node.channel.expects(:run).with('echo ok', false).returns('ok')
168
+ @node.helper.echo('ok').must_equal 'ok'
169
+ end
170
+
171
+ it 'returns an environment variables value' do
172
+ @node.channel.expects(:run).with('echo $HOME', false).returns('/home/user')
173
+ @node.helper.env('HOME').must_equal '/home/user'
174
+ end
175
+
176
+ it 'returns an SHA1 hash for the file content' do
177
+ @node.channel.expects(:run).with('sha1sum /file/path', false).returns('A1B2C3D4')
178
+ @node.helper.hash_for('/file/path').must_equal 'A1B2C3D4'
179
+ end
180
+
181
+ it 'checks binary existence' do
182
+ @node.channel.expects(:run).with('which ruby', false).returns('/usr/bin/ruby')
183
+ @node.helper.binary_exists?('ruby').must_equal true
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+ end