vagabond 0.2.4 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ ## v0.2.6
2
+ * Better use of `store_path` for working in standalone cookbooks
3
+ * Always vendor cookbooks when resolving, use knife to upload
4
+ * Clean up cluster test-kitchen support. Only resolve cookbooks once when in cluster mode
5
+ * Use `update` if `install` has already been preformed with librarian
6
+ * Add node name validation smarts to short circuit if action does not require it
7
+
1
8
  ## v0.2.4
2
9
  * Use correct sudo within provision action
3
10
  * Fix options helper in `destroy` (implicitly fixes `cluster` options)
@@ -25,6 +25,10 @@ module Vagabond
25
25
  end
26
26
  end
27
27
 
28
+ def cluster_validate?
29
+ false
30
+ end
31
+
28
32
  def _cluster
29
33
  clr = vagabondfile[:clusters][name] if vagabondfile[:clusters]
30
34
  if(clr)
@@ -30,7 +30,7 @@ module Vagabond
30
30
  end
31
31
  config[:daemon] = true
32
32
  config[:original] = tmpl
33
- config[:bind] = File.expand_path(File.dirname(vagabondfile.store_path))
33
+ config[:bind] = File.expand_path(vagabondfile.store_directory)
34
34
  ephemeral = Lxc::Ephemeral.new(config)
35
35
  ephemeral.start!(:fork)
36
36
  e_name = ephemeral.name
@@ -18,6 +18,10 @@ module Vagabond
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ def destroy_validate?
23
+ !options[:cluster]
24
+ end
21
25
 
22
26
  def _destroy
23
27
  name_required!
@@ -4,8 +4,8 @@ apt-get install -y -q wget
4
4
 
5
5
  mkdir -p /var/chef/cookbooks/vagabond
6
6
  mkdir -p /var/chef/cookbooks/lxc
7
- wget -qO- https://github.com/chrisroberts/chef-vagabond/tarball/master | tar xvzC /var/chef/cookbooks/vagabond --strip-components=1
8
- wget -qO- https://github.com/hw-cookbooks/lxc/tarball/master | tar xvzC /var/chef/cookbooks/lxc --strip-components=1
7
+ wget --no-check-certificate -qO- https://github.com/chrisroberts/chef-vagabond/tarball/master | tar xvzC /var/chef/cookbooks/vagabond --strip-components=1
8
+ wget --no-check-certificate -qO- https://github.com/hw-cookbooks/lxc/tarball/master | tar xvzC /var/chef/cookbooks/lxc --strip-components=1
9
9
 
10
10
  (
11
11
  echo "
@@ -1,8 +1,8 @@
1
1
  bash -c '
2
2
  apt-get install -y -q wget
3
3
  mkdir -p /var/chef/cache /var/chef/cookbooks/chef-server /var/chef/cookbooks/chef-server-populator
4
- wget -qO- https://github.com/opscode-cookbooks/chef-server/archive/master.tar.gz | tar xvzC /var/chef/cookbooks/chef-server --strip-components=1
5
- wget -qO- https://github.com/hw-cookbooks/chef-server-populator/tarball/master | tar xvzC /var/chef/cookbooks/chef-server-populator --strip-components=1
4
+ wget --no-check-certificate -qO- https://github.com/opscode-cookbooks/chef-server/archive/master.tar.gz | tar xvzC /var/chef/cookbooks/chef-server --strip-components=1
5
+ wget --no-check-certificate -qO- https://github.com/hw-cookbooks/chef-server-populator/tarball/master | tar xvzC /var/chef/cookbooks/chef-server-populator --strip-components=1
6
6
 
7
7
  mkdir -p /tmp/chef-server-setup
8
8
  (
@@ -84,9 +84,9 @@ module Vagabond
84
84
  setup(cookbook, :test)
85
85
 
86
86
  ui.info "#{ui.color('Vagabond:', :bold)} - Kitchen testing for cookbook #{ui.color(name, :cyan)}"
87
- results = Mash.new
88
87
  platforms = [options[:platform] || platform_map.keys].flatten
89
- if(cluster_name = options[:cluster])
88
+ @results = Mash[*platforms.zip([[]] * platforms.size).flatten(1)]
89
+ if(cluster_name = options.delete(:cluster))
90
90
  ui.info ui.color(" -> Cluster Testing #{cluster_name}!", :yellow)
91
91
  if(kitchen.clusters.empty? || kitchen.clusters[cluster_name].nil?)
92
92
  ui.fatal "Requested cluster is not defined: #{options[:cluster]}"
@@ -96,47 +96,76 @@ module Vagabond
96
96
  if(@solo && serv.vagabondfile[:local_chef_server].empty?)
97
97
  serv.vagabondfile[:local_chef_server].update(:enabled => true, :zero => true)
98
98
  end
99
- serv.options = options
99
+ internal_config.make_knife_config_if_required(:force)
100
+ serv.options = options.update(:auto_upload => false)
100
101
  serv.send(:do_create)
101
- serv.auto_upload # upload everything : make optional?
102
- suites = kitchen.clusters[options[:cluster]]
102
+ load_cookbooks(:upload)
103
+ suites = kitchen.clusters[cluster_name]
103
104
  platforms.each do |platform|
104
- %w(local_server_provision test destroy).each do |action|
105
+ begin
105
106
  suites.each do |suite_name|
106
- res = self.send("#{action}_node", platform, suite_name)
107
- if(action == 'test')
108
- results[platform] ||=[]
109
- results[platform] << {
107
+ unless(local_server_provision_node(platform, suite_name))
108
+ ui.error "Failed to provision #{suite_name} in platform #{platform}"
109
+ @results[platform] << {
110
110
  :suite_name => suite_name,
111
- :result => res
112
- }
111
+ :result => false
112
+ }
113
+ raise VagabondError::HostProvisionFailed.new("#{platform}[#{suite_name}]")
113
114
  end
114
115
  end
116
+ suites.each do |suite_name|
117
+ @results[platform] << {
118
+ :suite_name => suite_name,
119
+ :result => test_node(platform, suite_name)
120
+ }
121
+ end
122
+ rescue VagabondError::HostProvisionFailed => e
123
+ debug("Caught failed provision error. Scrubbing nodes. - #{e}")
124
+ ensure
125
+ suites.each do |suite_name|
126
+ destroy_node(platform, suite_name)
127
+ end
115
128
  end
116
129
  end
117
130
  serv.destroy
118
131
  else
119
- suites = options[:suites] ? options[:suites].split(',') : ['default']
132
+ load_cookbooks
133
+ suites = options[:suites] ? options[:suites].split(',') : kitchen.suites.map(&:name)
134
+ runners = []
120
135
  platforms.each do |platform|
121
136
  suites.each do |suite_name|
122
- provision_node(platform, suite_name)
123
- results[platform] ||= []
124
- results[platform] << {
125
- :suite_name => suite_name,
126
- :result => test_node(platform, suite_name)
127
- }
128
- destroy_node(platform, suite_name)
137
+ runner = lambda do
138
+ provision_node(platform, suite_name)
139
+ @results[platform] << {
140
+ :suite_name => suite_name,
141
+ :result => test_node(platform, suite_name)
142
+ }
143
+ destroy_node(platform, suite_name)
144
+ end
145
+ if(options[:parallel])
146
+ runners << Thread.new{ runner.call }
147
+ else
148
+ runner.call
149
+ end
150
+ end
151
+ end
152
+ if(options[:parallel])
153
+ until(runners.empty?)
154
+ runners.each do |runner|
155
+ runner.join
156
+ runners.delete(runner)
157
+ end
129
158
  end
130
159
  end
131
160
  end
132
161
  ui.info ui.color('Kitchen Test Results:', :bold)
133
- results.each do |platform, infos|
162
+ @results.each do |platform, infos|
134
163
  ui.info " Platform: #{ui.color(platform, :blue, :bold)}"
135
164
  infos.each do |res|
136
165
  ui.info " Suite: #{res[:suite_name]} -> #{res[:result] ? ui.color('SUCCESS!', :green) : ui.color('FAILED!', :red)}"
137
166
  end
138
167
  end
139
- raise KitchenTestFailed.new(infos.map{|res| res[:suite_name] unless res[:result]}.compact)
168
+ raise VagabondError::KitchenTestFailed.new(@results.values.flatten.map{|res| res[:suite_name] unless res[:result]}.compact)
140
169
  end
141
170
 
142
171
  desc 'status [NAME]', 'Show test node status'
@@ -154,6 +183,7 @@ module Vagabond
154
183
  def local_server_provision_node(platform, suite_name)
155
184
  run_list = generate_runlist(platform, suite_name)
156
185
  v_inst = vagabond_instance(:up, platform, :suite_name => suite_name, :run_list => run_list)
186
+ v_inst.options[:auto_provision] = true
157
187
  raise "ERROR! No local chef!" unless v_inst.options[:knife_opts]
158
188
  v_inst.send(:execute)
159
189
  end
@@ -164,8 +194,8 @@ module Vagabond
164
194
  ui.info ui.color(" -> Provisioning suite #{suite_name} on platform: #{platform}", :cyan)
165
195
  v_inst = vagabond_instance(:create, platform, :suite_name => suite_name)
166
196
  v_inst.send(:execute)
167
- solo_path = configure_for(v_inst.name, platform, suite_name, run_list, :dna, :cookbooks)
168
- v_inst.send(:provision_solo, solo_path)
197
+ directory = configure_for(v_inst.name, platform, suite_name, run_list, :dna, :cookbooks)
198
+ v_inst.send(:provision_solo, directory)
169
199
  end
170
200
 
171
201
  def test_node(platform, suite_name)
@@ -189,6 +219,7 @@ module Vagabond
189
219
  @solo = name.to_s.strip.empty?
190
220
  @options = options.dup
191
221
  @vagabondfile = Vagabondfile.new(options[:vagabond_file], :allow_missing)
222
+ base_setup
192
223
  setup_ui
193
224
  @internal_config = InternalConfiguration.new(@vagabondfile, ui, options)
194
225
  @name = name || action == :status ? name : discover_name
@@ -215,16 +246,20 @@ module Vagabond
215
246
  dir = File.join(File.dirname(vagabondfile.store_path), ".vagabond/node_configs/#{l_name}")
216
247
  FileUtils.mkdir_p(dir)
217
248
  _args = [args.include?(:integration) ? :integration : nil].compact
218
- write_dna(l_name, suite_name, dir, platform, runlist, *_args) if args.include?(:dna)
219
- load_cookbooks(l_name, suite_name, dir, platform, runlist, *_args) if args.include?(:cookbooks)
220
- write_solo_config(dir) if args.include?(:cookbooks) && !args.include?(:integration)
249
+ if(args.include?(:dna))
250
+ write_dna(l_name, suite_name, dir, platform, runlist, *_args)
251
+ end
252
+ if(args.include?(:cookbooks) && !args.include?(:integration))
253
+ write_solo_config(dir)
254
+ end
221
255
  dir
222
256
  end
223
257
 
224
258
  def write_solo_config(dir)
225
259
  File.open(File.join(dir, 'solo.rb'), 'w') do |file|
226
- file.write("cookbook_path '#{File.join(dir, 'cookbooks')}'\n")
260
+ file.write("cookbook_path '#{File.join(vagabondfile.store_directory, 'cookbooks')}'\n")
227
261
  end
262
+ dir
228
263
  end
229
264
 
230
265
  def write_dna(l_name, suite_name, dir, platform, runlist, *args)
@@ -236,9 +271,10 @@ module Vagabond
236
271
  dna.merge!(suite.attributes)
237
272
  end
238
273
  dna[:run_list] = runlist
239
- File.open(File.join(dir, 'dna.json'), 'w') do |file|
274
+ File.open(path = File.join(dir, 'dna.json'), 'w') do |file|
240
275
  file.write(JSON.dump(dna))
241
276
  end
277
+ path
242
278
  end
243
279
 
244
280
  def cookbook_path
@@ -265,15 +301,16 @@ module Vagabond
265
301
  contents.join("\n")
266
302
  end
267
303
 
268
- def load_cookbooks(l_name, suite_name, dir, platform, runlist, *_args)
304
+ def load_cookbooks(*args)
269
305
  if(File.exists?(File.join(vagabondfile.directory, 'Berksfile')))
270
- berks_vendor
306
+ uploader = berks_vendor(args.include?(:upload))
271
307
  else
272
- librarian_vendor
308
+ uploader = librarian_vendor(args.include?(:upload))
273
309
  end
310
+ uploader
274
311
  end
275
-
276
- def berks_vendor
312
+
313
+ def berks_vendor(upload=false)
277
314
  ui.info 'Cookbooks being vendored via berks'
278
315
  berk_uploader = Uploader::Berkshelf.new(
279
316
  vagabondfile.generate_store_path, options.merge(
@@ -282,23 +319,26 @@ module Vagabond
282
319
  :chef_server_url => options[:knife_opts].to_s.split(' ').last
283
320
  )
284
321
  )
285
- berk_uploader.upload
322
+ upload ? berk_uploader.upload : berk_uploader.prepare
323
+ berk_uploader
286
324
  end
287
325
 
288
- def librarian_vendor
326
+ def librarian_vendor(upload=false)
289
327
  ui.info 'Cookbooks being vendored with librarian'
290
328
  unless(File.exists?(cheffile = File.join(vagabondfile.directory, 'Cheffile')))
291
- File.open(cheffile = vagabond.generate_store_path, 'w') do |file|
329
+ File.open(cheffile = File.join(vagabondfile.generate_store_path, 'Cheffile'), 'w') do |file|
292
330
  file.write custom_cheffile
293
331
  end
294
332
  end
295
333
  librarian_uploader = Uploader::Librarian.new(
296
- vagabondfile.generate_store_path, options.merge(
334
+ vagabondfile.generate_store_path,
335
+ options.merge(
297
336
  :ui => ui,
298
337
  :cheffile => cheffile
299
338
  )
300
339
  )
301
- librarian_uploader.prepare
340
+ upload ? librarian_uploader.upload : librarian_uploader.prepare
341
+ librarian_uploader
302
342
  end
303
343
 
304
344
  def bus_node(v_inst, suite_name)
@@ -327,6 +367,8 @@ module Vagabond
327
367
  :disable_name_validate => true,
328
368
  :ui => ui
329
369
  )
370
+ v.vagabondfile = vagabondfile
371
+ v.vagabondfile.generate_store_path
330
372
  v.internal_config.force_bases = platform_map[platform][:template]
331
373
  v.internal_config.ensure_state
332
374
  v.mappings_key = :test_mappings
@@ -1,12 +1,12 @@
1
- require 'vagabond/uploader/berkshelf'
1
+ require 'vagabond/uploader/knife'
2
2
 
3
3
  module Vagabond
4
4
  class Uploader
5
- class Berkshelf < Uploader
5
+ class Berkshelf < Knife
6
6
 
7
7
  def initialize(*args)
8
8
  super
9
- %w(berksfile chef_server_url).each do |k|
9
+ %w(berksfile).each do |k|
10
10
  unless(options[k])
11
11
  raise ArgumentError.new "Option '#{k}' must be provided!"
12
12
  end
@@ -20,7 +20,7 @@ module Vagabond
20
20
  else
21
21
  cur = Mash.new
22
22
  end
23
- url = options[:chef_server_url]
23
+ url = options[:chef_server_url] || 'http://127.0.0.1'
24
24
  if(cur[:chef].nil? || cur[:chef][:chef_server_url] != url)
25
25
  cur[:chef] = Mash.new(:chef_server_url => url)
26
26
  cur[:ssl] = Mash.new(:verify => false)
@@ -28,19 +28,11 @@ module Vagabond
28
28
  file.write(JSON.dump(cur))
29
29
  end
30
30
  end
31
- end
32
-
33
- def upload(*args)
34
- prepare unless args.include?(:no_prepare)
35
- com = "berks upload -b #{options[:berksfile]} -c #{File.join(store, 'berks.json')}#{" #{Array(options[:berks_opts]).join(' ')}"}"
36
- debug(com)
37
- cmd = Mixlib::ShellOut.new(com, :live_stream => options[:debug], :env => {'HOME' => ENV['HOME']})
38
- cmd.run_command
39
- cmd.error!
31
+ vendor
32
+ options[:cookbook_paths] = [File.join(store, 'cookbooks')]
40
33
  end
41
34
 
42
35
  def vendor(*args)
43
- prepare unless args.include?(:no_prepare)
44
36
  FileUtils.mkdir_p(ckbk_store = File.join(store, 'cookbooks'))
45
37
  com = "berks install -b #{options[:berksfile]} -p #{ckbk_store}"
46
38
  debug(com)
@@ -10,6 +10,9 @@ module Vagabond
10
10
  if(options[:cookbook_paths])
11
11
  com << " --cookbook-path #{Array(options[:cookbook_paths]).join(':')}"
12
12
  end
13
+ if(File.exists?(knife_config = File.join(store, '.chef/knife.rb')))
14
+ com << " --config #{knife_config}"
15
+ end
13
16
  debug(com)
14
17
  cmd = Mixlib::ShellOut.new(com,
15
18
  :live_stream => options[:debug],
@@ -15,7 +15,11 @@ module Vagabond
15
15
  end
16
16
 
17
17
  def prepare
18
- com = "librarian-chef install --path=#{store}"
18
+ if(File.directory?(File.join(store, 'cookbooks')))
19
+ com = 'librarian-chef update' # TODO: Check path in .librarian config
20
+ else
21
+ com = "librarian-chef install --path=#{File.join(store, 'cookbooks')}"
22
+ end
19
23
  debug(com)
20
24
  cmd = Mixlib::ShellOut.new(com,
21
25
  :live_stream => options[:debug],
@@ -23,7 +27,7 @@ module Vagabond
23
27
  )
24
28
  cmd.run_command
25
29
  cmd.error!
26
- options[:cookbook_paths] = [store]
30
+ options[:cookbook_paths] = [File.join(store, 'cookbooks')]
27
31
  end
28
32
 
29
33
  end
@@ -133,8 +133,11 @@ module Vagabond
133
133
  @leftover_args = args
134
134
  setup_ui(_ui)
135
135
  load_configurations
136
- validate! unless action == 'cluster' # TODO -> allow action
137
- # method to check for validation run
136
+ if(respond_to?(check = "#{action}_validate?".to_sym))
137
+ validate! if send(check)
138
+ else
139
+ validate!
140
+ end
138
141
  end
139
142
 
140
143
  def name_required!
@@ -144,11 +147,11 @@ module Vagabond
144
147
  end
145
148
  end
146
149
 
147
- def provision_solo(path)
150
+ def provision_solo(dir)
148
151
  ui.info "#{ui.color('Vagabond:', :bold)} Provisioning node: #{ui.color(name, :magenta)}"
149
152
  lxc.container_ip(20) # force wait for container to appear and do so quietly
150
153
  direct_container_command(
151
- "chef-solo -c #{File.join(path, 'solo.rb')} -j #{File.join(path, 'dna.json')}",
154
+ "chef-solo -c #{File.join(dir, 'solo.rb')} -j #{File.join(dir, 'dna.json')}",
152
155
  :live_stream => STDOUT
153
156
  )
154
157
  end
@@ -6,5 +6,5 @@ module Vagabond
6
6
  super(v)
7
7
  end
8
8
  end
9
- VERSION = Version.new('0.2.4', 'train hopper')
9
+ VERSION = Version.new('0.2.6', 'gutterpup')
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagabond
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-20 00:00:00.000000000 Z
12
+ date: 2013-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef