vagabond 0.2.4 → 0.2.6

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.
@@ -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