jamie 0.1.0.beta3 → 0.1.0.beta4

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.
data/Gemfile CHANGED
@@ -10,5 +10,4 @@ end
10
10
 
11
11
  group :test do
12
12
  gem 'rake', '~> 0.9'
13
- gem 'pry'
14
13
  end
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ Rake::TestTask.new do |t|
7
7
  t.verbose = true
8
8
  end
9
9
 
10
- task :default => [ :test ]
10
+ task :default => [:test]
11
11
 
12
12
  unless RUBY_ENGINE == 'jruby'
13
13
  require 'cane/rake_task'
@@ -29,9 +29,17 @@ unless RUBY_ENGINE == 'jruby'
29
29
  )
30
30
  end
31
31
 
32
- Tailor::RakeTask.new
32
+ Tailor::RakeTask.new do |task|
33
+ task.file_set('bin/*', 'binaries')
34
+ task.file_set('lib/**/*.rb', 'code') do |style|
35
+ # TODO: Tailor is confused thinking `module Jamie` is a class. Until
36
+ # the classes are split in seperate files, let's punt on this
37
+ style.max_code_lines_in_class 1550, level: :warn
38
+ end
39
+ task.file_set('spec/**/*.rb', 'tests')
40
+ end
33
41
 
34
- Rake::Task[:default].enhance [ :cane, :tailor ]
42
+ Rake::Task[:default].enhance [:cane, :tailor]
35
43
  end
36
44
 
37
45
  desc "Display LOC stats"
@@ -42,4 +50,4 @@ task :stats do
42
50
  sh "countloc -r spec"
43
51
  end
44
52
 
45
- Rake::Task[:default].enhance [ :stats ]
53
+ Rake::Task[:default].enhance [:stats]
@@ -22,6 +22,7 @@ Gem::Specification.new do |gem|
22
22
 
23
23
  gem.add_dependency 'celluloid'
24
24
  gem.add_dependency 'thor'
25
+ gem.add_dependency 'pry'
25
26
  gem.add_dependency 'net-ssh'
26
27
  gem.add_dependency 'net-scp'
27
28
  gem.add_dependency 'mixlib-shellout'
@@ -164,7 +164,7 @@ module Jamie
164
164
  def log_level
165
165
  @log_level ||= begin
166
166
  ENV['JAMIE_LOG'] && ENV['JAMIE_LOG'].downcase.to_sym ||
167
- Jamie::DEFAULT_LOG_LEVEL
167
+ Jamie::DEFAULT_LOG_LEVEL
168
168
  end
169
169
  end
170
170
 
@@ -286,7 +286,7 @@ module Jamie
286
286
  def platform_driver_hash(platform_name)
287
287
  h = yaml[:platforms].find { |p| p[:name] == platform_name } || Hash.new
288
288
 
289
- h.select { |key, value| [ :driver_plugin, :driver_config ].include?(key) }
289
+ h.select { |key, value| [:driver_plugin, :driver_config].include?(key) }
290
290
  end
291
291
 
292
292
  def new_instance_logger(index)
@@ -355,7 +355,7 @@ module Jamie
355
355
 
356
356
  def common_driver_hash
357
357
  yaml.select do |key, value|
358
- [ :driver_plugin, :driver_config ].include?(key)
358
+ [:driver_plugin, :driver_config].include?(key)
359
359
  end
360
360
  end
361
361
  end
@@ -374,7 +374,7 @@ module Jamie
374
374
 
375
375
  COLORS = %w(
376
376
  cyan yellow green magenta red blue bright_cyan bright_yellow
377
- bright_green bright_magenta bright_red, bright_blue
377
+ bright_green bright_magenta bright_red bright_blue
378
378
  ).freeze
379
379
 
380
380
  def self.escape(name)
@@ -563,7 +563,7 @@ module Jamie
563
563
  private
564
564
 
565
565
  def validate_options(opts)
566
- [ :name, :run_list ].each do |k|
566
+ [:name, :run_list].each do |k|
567
567
  raise ClientError, "Suite#new requires option :#{k}" if opts[k].nil?
568
568
  end
569
569
  end
@@ -604,7 +604,7 @@ module Jamie
604
604
  private
605
605
 
606
606
  def validate_options(opts)
607
- [ :name ].each do |k|
607
+ [:name].each do |k|
608
608
  raise ClientError, "Platform#new requires option :#{k}" if opts[k].nil?
609
609
  end
610
610
  end
@@ -792,7 +792,7 @@ module Jamie
792
792
  private
793
793
 
794
794
  def validate_options(opts)
795
- [ :suite, :platform, :driver, :jr, :logger ].each do |k|
795
+ [:suite, :platform, :driver, :jr, :logger].each do |k|
796
796
  raise ClientError, "Instance#new requires option :#{k}" if opts[k].nil?
797
797
  end
798
798
  end
@@ -838,7 +838,7 @@ module Jamie
838
838
  banner "#{output_verb} #{to_str}"
839
839
  elapsed = action(verb) { |state| driver.public_send(verb, state) }
840
840
  info("Finished #{output_verb.downcase} #{to_str}" +
841
- " #{Util.duration(elapsed.real)}.")
841
+ " #{Util.duration(elapsed.real)}.")
842
842
  yield if block_given?
843
843
  Actor.current
844
844
  end
@@ -927,7 +927,7 @@ module Jamie
927
927
 
928
928
  private
929
929
 
930
- TRANSITIONS = [ :destroy, :create, :converge, :setup, :verify ]
930
+ TRANSITIONS = [:destroy, :create, :converge, :setup, :verify]
931
931
 
932
932
  def self.index(transition)
933
933
  if transition.nil?
@@ -953,7 +953,7 @@ module Jamie
953
953
  # @param [Hash] opts optional configuration
954
954
  # @option opts [TrueClass, FalseClass] :use_sudo whether or not to invoke
955
955
  # sudo before commands requiring root access (default: `true`)
956
- def initialize(suite_name, opts = {:use_sudo => true})
956
+ def initialize(suite_name, opts = { :use_sudo => true })
957
957
  validate_options(suite_name)
958
958
 
959
959
  @suite_name = suite_name
@@ -972,7 +972,7 @@ module Jamie
972
972
  @setup_cmd ||= if local_suite_files.empty?
973
973
  nil
974
974
  else
975
- <<-INSTALL_CMD.gsub(/ {10}/, '')
975
+ <<-INSTALL_CMD.gsub(/^ {10}/, '')
976
976
  #{sudo}#{ruby_bin} -e "$(cat <<"EOF"
977
977
  #{install_script}
978
978
  EOF
@@ -994,7 +994,7 @@ module Jamie
994
994
  @sync_cmd ||= if local_suite_files.empty?
995
995
  nil
996
996
  else
997
- <<-INSTALL_CMD.gsub(/ {10}/, '')
997
+ <<-INSTALL_CMD.gsub(/^ {10}/, '')
998
998
  #{sudo}#{jr_bin} cleanup-suites
999
999
  #{local_suite_files.map { |f| stream_file(f, remote_file(f)) }.join}
1000
1000
  INSTALL_CMD
@@ -1053,7 +1053,7 @@ module Jamie
1053
1053
  def stream_file(local_path, remote_path)
1054
1054
  local_file = IO.read(local_path)
1055
1055
  md5 = Digest::MD5.hexdigest(local_file)
1056
- perms = sprintf("%o", File.stat(local_path).mode)[3,3]
1056
+ perms = sprintf("%o", File.stat(local_path).mode)[3, 3]
1057
1057
  jr_stream_file = "#{jr_bin} stream-file #{remote_path} #{md5} #{perms}"
1058
1058
 
1059
1059
  <<-STREAMFILE.gsub(/^ {8}/, '')
@@ -1115,7 +1115,7 @@ module Jamie
1115
1115
 
1116
1116
  def self.symbolized_hash(obj)
1117
1117
  if obj.is_a?(Hash)
1118
- obj.inject({}) { |h, (k,v)| h[k.to_sym] = symbolized_hash(v) ; h }
1118
+ obj.inject({}) { |h, (k, v)| h[k.to_sym] = symbolized_hash(v) ; h }
1119
1119
  elsif obj.is_a?(Array)
1120
1120
  obj.inject([]) { |a, v| a << symbolized_hash(v) ; a }
1121
1121
  else
@@ -1126,7 +1126,7 @@ module Jamie
1126
1126
  def self.duration(total)
1127
1127
  minutes = (total / 60).to_i
1128
1128
  seconds = (total - (minutes * 60))
1129
- "(%dm%.2fs)" % [ minutes, seconds ]
1129
+ "(%dm%.2fs)" % [minutes, seconds]
1130
1130
  end
1131
1131
  end
1132
1132
 
@@ -1316,7 +1316,7 @@ module Jamie
1316
1316
  end
1317
1317
  end
1318
1318
  end
1319
- @validations << [ attr, block ]
1319
+ @validations << [attr, block]
1320
1320
  end
1321
1321
 
1322
1322
  def self.no_parallel_for(*methods)
@@ -1391,7 +1391,7 @@ module Jamie
1391
1391
  opts[:password] = config[:password] if config[:password]
1392
1392
  opts[:keys] = Array(config[:ssh_key]) if config[:ssh_key]
1393
1393
 
1394
- [ state[:hostname], config[:username], opts ]
1394
+ [state[:hostname], config[:username], opts]
1395
1395
  end
1396
1396
 
1397
1397
  def chef_home
@@ -1475,7 +1475,7 @@ module Jamie
1475
1475
  socket = TCPSocket.new(hostname, config[:port])
1476
1476
  IO.select([socket], nil, nil, 5)
1477
1477
  rescue SocketError, Errno::ECONNREFUSED,
1478
- Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
1478
+ Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
1479
1479
  sleep 2
1480
1480
  false
1481
1481
  rescue Errno::EPERM, Errno::ETIMEDOUT
@@ -1546,8 +1546,9 @@ module Jamie
1546
1546
  end
1547
1547
 
1548
1548
  def upload_path(scp, path, dir = File.basename(path))
1549
- scp.upload!(path, "#{chef_home}/#{dir}", :recursive => true
1550
- ) do |ch, name, sent, total|
1549
+ dest = "#{chef_home}/#{dir}"
1550
+
1551
+ scp.upload!(path, dest, :recursive => true) do |ch, name, sent, total|
1551
1552
  if sent == total
1552
1553
  info("Uploaded #{name.sub(%r{^#{path}/}, '')} (#{total} bytes)")
1553
1554
  end
@@ -1593,7 +1594,8 @@ module Jamie
1593
1594
  fatal("#{name} must be installed, add it to your Gemfile.")
1594
1595
  raise UserError, "#{bin} command not found"
1595
1596
  end
1596
- run_command "#{bin} install --path #{tmpdir}"
1597
+
1598
+ Jamie.mutex.synchronize { run_command "#{bin} install --path #{tmpdir}" }
1597
1599
  end
1598
1600
 
1599
1601
  def cp_cookbooks(tmpdir)
@@ -1628,7 +1630,7 @@ module Jamie
1628
1630
  # attributes or nil values if they could not be determined
1629
1631
  def self.extract(metadata_file)
1630
1632
  mc = new(File.expand_path(metadata_file))
1631
- [ mc[:name], mc[:version] ]
1633
+ [mc[:name], mc[:version]]
1632
1634
  end
1633
1635
 
1634
1636
  # Creates a new instances and loads in the contents of the metdata.rb
@@ -47,10 +47,10 @@ module Jamie
47
47
  def list(*args)
48
48
  result = parse_subcommand(args.first)
49
49
  if options[:bare]
50
- say Array(result).map{ |i| i.name }.join("\n")
50
+ say Array(result).map { |i| i.name }.join("\n")
51
51
  else
52
52
  table = [
53
- [ set_color("Instance", :green), set_color("Last Action", :green) ]
53
+ [set_color("Instance", :green), set_color("Last Action", :green)]
54
54
  ]
55
55
  table += Array(result).map { |i| display_instance(i) }
56
56
  print_table(table)
@@ -107,7 +107,7 @@ module Jamie
107
107
  results = get_filtered_instances(regexp)
108
108
  if results.size > 1
109
109
  die task, "Argument `#{regexp}' returned multiple results:\n" +
110
- results.map{ |i| " * #{i.name}" }.join("\n")
110
+ results.map { |i| " * #{i.name}" }.join("\n")
111
111
  end
112
112
  instance = results.pop
113
113
 
@@ -210,7 +210,7 @@ module Jamie
210
210
  when nil then set_color("<Not Created>", :red)
211
211
  else set_color("<Unknown>", :white)
212
212
  end
213
- [ set_color(instance.name, :white), action ]
213
+ [set_color(instance.name, :white), action]
214
214
  end
215
215
 
216
216
  def die(task, msg)
@@ -220,18 +220,19 @@ module Jamie
220
220
  end
221
221
 
222
222
  def pry_prompts
223
- [ proc { |target_self, nest_level, pry|
224
- [ "[#{pry.input_array.size}] ",
223
+ [
224
+ proc { |target_self, nest_level, pry|
225
+ ["[#{pry.input_array.size}] ",
225
226
  "jc(#{Pry.view_clip(target_self.class)})",
226
227
  "#{":#{nest_level}" unless nest_level.zero?}> "
227
228
  ].join
228
229
  },
229
230
  proc { |target_self, nest_level, pry|
230
- [ "[#{pry.input_array.size}] ",
231
+ ["[#{pry.input_array.size}] ",
231
232
  "jc(#{Pry.view_clip(target_self.class)})",
232
233
  "#{":#{nest_level}" unless nest_level.zero?}* "
233
234
  ].join
234
- }
235
+ },
235
236
  ]
236
237
  end
237
238
  end
@@ -265,7 +266,7 @@ module Jamie
265
266
  puts ">>>>> Jamie gem not loaded, omitting tasks" unless ENV['CI']
266
267
  end
267
268
  THOR
268
- empty_directory "test/integration/standard" if init_test_dir?
269
+ empty_directory "test/integration/default" if init_test_dir?
269
270
  append_to_gitignore(".jamie/")
270
271
  append_to_gitignore(".jamie.local.yml")
271
272
  add_plugins
@@ -277,7 +278,7 @@ module Jamie
277
278
  url_base = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes"
278
279
  platforms = [
279
280
  { :n => 'ubuntu', :vers => %w(12.04 10.04), :rl => "recipe[apt]" },
280
- { :n => 'centos', :vers => %w(6.3 5.8), :rl => "recipe[yum::epel]" }
281
+ { :n => 'centos', :vers => %w(6.3 5.8), :rl => "recipe[yum::epel]" },
281
282
  ]
282
283
  platforms = platforms.map do |p|
283
284
  p[:vers].map do |v|
@@ -296,15 +297,14 @@ module Jamie
296
297
  nil
297
298
  end
298
299
  run_list = cookbook_name ? "recipe[#{cookbook_name}]" : nil
299
- attributes = cookbook_name ? { cookbook_name => nil } : nil
300
300
 
301
301
  { 'driver_plugin' => 'vagrant',
302
302
  'platforms' => platforms,
303
303
  'suites' => [
304
- { 'name' => 'standard',
304
+ { 'name' => 'default',
305
305
  'run_list' => Array(run_list),
306
- 'attributes' => attributes
307
- }
306
+ 'attributes' => Hash.new
307
+ },
308
308
  ]
309
309
  }.to_yaml
310
310
  end
@@ -345,7 +345,7 @@ module Jamie
345
345
 
346
346
  def list_plugins
347
347
  specs = fetch_gem_specs.map { |t| t.first }.map { |t| t[0, 2] }.
348
- sort { |x,y| x[0] <=> y[0] }
348
+ sort { |x, y| x[0] <=> y[0] }
349
349
  specs = specs[0, 49].push(["...", "..."]) if specs.size > 49
350
350
  specs = specs.unshift(["Gem Name", "Latest Stable Release"])
351
351
  print_table(specs, :indent => 4)
@@ -55,14 +55,22 @@ module Jamie
55
55
  private
56
56
 
57
57
  def report(action, state)
58
- info("[Dummy] Action ##{action} called on " +
59
- "instance=#{instance} with state=#{state}")
58
+ what = action.capitalize
59
+ info("[Dummy] #{what} on instance=#{instance} with state=#{state}")
60
+ sleep_if_set
61
+ random_failure_if_set
62
+ debug("[Dummy] #{what} completed (#{config[:sleep]}s).")
63
+ end
64
+
65
+ def sleep_if_set
60
66
  sleep(config[:sleep].to_f) if config[:sleep].to_f > 0.0
67
+ end
68
+
69
+ def random_failure_if_set
61
70
  if config[:random_failure] && [true, false].sample
62
71
  debug("[Dummy] Random failure for action ##{action}.")
63
72
  raise ActionFailed, "Action ##{action} failed for #{instance.to_str}."
64
73
  end
65
- debug("[Dummy] Action ##{action} completed (#{config[:sleep]}s).")
66
74
  end
67
75
  end
68
76
  end
@@ -55,7 +55,7 @@ module Jamie
55
55
 
56
56
  self.class.desc "all", "Run all test instances"
57
57
  self.class.send(:define_method, :all) do
58
- config.instances.each { |i| invoke i.name.gsub(/-/, '_') }
58
+ config.instances.each { |i| invoke i.name.gsub(/-/, '_') }
59
59
  end
60
60
  end
61
61
  end
@@ -18,5 +18,5 @@
18
18
 
19
19
  module Jamie
20
20
 
21
- VERSION = "0.1.0.beta3"
21
+ VERSION = "0.1.0.beta4"
22
22
  end
@@ -0,0 +1,77 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require_relative '../../spec_helper'
20
+
21
+ describe Jamie::Config::Collection do
22
+
23
+ let(:collection) do
24
+ Jamie::Config::Collection.new([
25
+ obj('one'), obj('two', 'a'), obj('two', 'b'), obj('three')
26
+ ])
27
+ end
28
+
29
+ it "transparently wraps an Array" do
30
+ collection.must_be_instance_of Array
31
+ end
32
+
33
+ describe "#get" do
34
+
35
+ it "returns a single object by its name" do
36
+ collection.get('three').must_equal obj('three')
37
+ end
38
+
39
+ it "returns the first occurance of an object by its name" do
40
+ collection.get('two').must_equal obj('two', 'a')
41
+ end
42
+
43
+ it "returns nil if an object cannot be found by its name" do
44
+ collection.get('nope').must_be_nil
45
+ end
46
+ end
47
+
48
+ describe "#get_all" do
49
+
50
+ it "returns a Collection of objects whose name matches the regex" do
51
+ result = collection.get_all(/(one|three)/)
52
+ result.size.must_equal 2
53
+ result[0].must_equal obj('one')
54
+ result[1].must_equal obj('three')
55
+ result.get_all(/one/).size.must_equal 1
56
+ end
57
+
58
+ it "returns an empty Collection if on matches are found" do
59
+ result = collection.get_all(/noppa/)
60
+ result.must_equal []
61
+ result.get("nahuh").must_be_nil
62
+ end
63
+ end
64
+
65
+ describe "#as_name" do
66
+
67
+ it "returns an Array of names as strings" do
68
+ collection.as_names.must_equal %w{one two two three}
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def obj(name, extra = nil)
75
+ OpenStruct.new(:name => name, :extra => extra)
76
+ end
77
+ end