jamie 0.1.0.alpha15 → 0.1.0.alpha16

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/Rakefile CHANGED
@@ -19,4 +19,9 @@ end
19
19
 
20
20
  Tailor::RakeTask.new
21
21
 
22
+ desc "yep"
23
+ task :stats do
24
+ sh "countloc -r lib/jamie lib/jamie.rb"
25
+ end
26
+
22
27
  task :default => [ :cane, :tailor ]
data/jamie.gemspec CHANGED
@@ -26,4 +26,5 @@ Gem::Specification.new do |gem|
26
26
  gem.add_development_dependency 'maruku'
27
27
  gem.add_development_dependency 'cane'
28
28
  gem.add_development_dependency 'tailor'
29
+ gem.add_development_dependency 'countloc'
29
30
  end
data/lib/jamie/cli.rb CHANGED
@@ -251,38 +251,6 @@ module Jamie
251
251
 
252
252
  specs = fetcher.find_matching(dep, false, false, false)
253
253
  end
254
-
255
- # A rather insane and questionable class to quickly consume a metadata.rb
256
- # file and return the cookbook name and version attributes.
257
- #
258
- # @see https://twitter.com/fnichol/status/281650077901144064
259
- # @see https://gist.github.com/4343327
260
- class MetadataChopper < Hash
261
-
262
- # Return an Array containing the cookbook name and version attributes,
263
- # or nil values if they could not be parsed.
264
- #
265
- # @param metadata_file [String] path to a metadata.rb file
266
- # @return [Array<String>] array containing the cookbook name and version
267
- # attributes or nil values if they could not be determined
268
- def self.extract(metadata_file)
269
- mc = new(File.expand_path(metadata_file))
270
- [ mc[:name], mc[:version] ]
271
- end
272
-
273
- # Creates a new instances and loads in the contents of the metdata.rb
274
- # file. If you value your life, you may want to avoid reading the
275
- # implementation.
276
- #
277
- # @param metadata_file [String] path to a metadata.rb file
278
- def initialize(metadata_file)
279
- eval(IO.read(metadata_file), nil, metadata_file)
280
- end
281
-
282
- def method_missing(meth, *args, &block)
283
- self[meth] = args.first
284
- end
285
- end
286
254
  end
287
255
 
288
256
  # A generator to create a new Jamie driver plugin.
data/lib/jamie/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Jamie
4
4
 
5
- VERSION = "0.1.0.alpha15"
5
+ VERSION = "0.1.0.alpha16"
6
6
  end
data/lib/jamie.rb CHANGED
@@ -365,7 +365,7 @@ module Jamie
365
365
  # to gracfully stop action chaining
366
366
  def create
367
367
  puts "-----> Creating instance #{name}"
368
- platform.driver.create(self)
368
+ action(:create) { |state| platform.driver.create(self, state) }
369
369
  puts " Creation of instance #{name} complete."
370
370
  self
371
371
  end
@@ -379,7 +379,7 @@ module Jamie
379
379
  # to gracfully stop action chaining
380
380
  def converge
381
381
  puts "-----> Converging instance #{name}"
382
- platform.driver.converge(self)
382
+ action(:converge) { |state| platform.driver.converge(self, state) }
383
383
  puts " Convergence of instance #{name} complete."
384
384
  self
385
385
  end
@@ -393,7 +393,7 @@ module Jamie
393
393
  # to gracfully stop action chaining
394
394
  def setup
395
395
  puts "-----> Setting up instance #{name}"
396
- platform.driver.setup(self)
396
+ action(:setup) { |state| platform.driver.setup(self, state) }
397
397
  puts " Setup of instance #{name} complete."
398
398
  self
399
399
  end
@@ -407,7 +407,7 @@ module Jamie
407
407
  # to gracfully stop action chaining
408
408
  def verify
409
409
  puts "-----> Verifying instance #{name}"
410
- platform.driver.verify(self)
410
+ action(:verify) { |state| platform.driver.verify(self, state) }
411
411
  puts " Verification of instance #{name} complete."
412
412
  self
413
413
  end
@@ -421,7 +421,8 @@ module Jamie
421
421
  # to gracfully stop action chaining
422
422
  def destroy
423
423
  puts "-----> Destroying instance #{name}"
424
- platform.driver.destroy(self)
424
+ action(:destroy) { |state| platform.driver.destroy(self, state) }
425
+ destroy_state
425
426
  puts " Destruction of instance #{name} complete."
426
427
  self
427
428
  end
@@ -450,6 +451,37 @@ module Jamie
450
451
  puts " Testing of instance #{name} complete."
451
452
  self
452
453
  end
454
+
455
+ private
456
+
457
+ def action(what)
458
+ state = load_state
459
+ yield state if block_given?
460
+ state['last_action'] = what.to_s
461
+ ensure
462
+ dump_state(state)
463
+ end
464
+
465
+ def load_state
466
+ File.exists?(statefile) ? YAML.load_file(statefile) : Hash.new
467
+ end
468
+
469
+ def dump_state(state)
470
+ dir = File.dirname(statefile)
471
+
472
+ FileUtils.mkdir_p(dir) if !File.directory?(dir)
473
+ File.open(statefile, "wb") { |f| f.write(YAML.dump(state)) }
474
+ end
475
+
476
+ def destroy_state
477
+ FileUtils.rm(statefile) if File.exists?(statefile)
478
+ end
479
+
480
+ def statefile
481
+ File.expand_path(File.join(
482
+ platform.driver['jamie_root'], ".jamie", "#{name}.yml"
483
+ ))
484
+ end
453
485
  end
454
486
 
455
487
  # Command string generator to interface with Jamie Runner (jr). The
@@ -686,85 +718,42 @@ module Jamie
686
718
  # Creates an instance.
687
719
  #
688
720
  # @param instance [Instance] an instance
721
+ # @param state [Hash] mutable instance and driver state
689
722
  # @raise [ActionFailed] if the action could not be completed
690
- def create(instance)
691
- action(:create, instance)
692
- end
723
+ def create(instance, state) ; end
693
724
 
694
725
  # Converges a running instance.
695
726
  #
696
727
  # @param instance [Instance] an instance
728
+ # @param state [Hash] mutable instance and driver state
697
729
  # @raise [ActionFailed] if the action could not be completed
698
- def converge(instance)
699
- action(:converge, instance)
700
- end
730
+ def converge(instance, state) ; end
701
731
 
702
732
  # Sets up an instance.
703
733
  #
704
734
  # @param instance [Instance] an instance
735
+ # @param state [Hash] mutable instance and driver state
705
736
  # @raise [ActionFailed] if the action could not be completed
706
- def setup(instance)
707
- action(:setup, instance)
708
- end
737
+ def setup(instance, state) ; end
709
738
 
710
739
  # Verifies a converged instance.
711
740
  #
712
741
  # @param instance [Instance] an instance
742
+ # @param state [Hash] mutable instance and driver state
713
743
  # @raise [ActionFailed] if the action could not be completed
714
- def verify(instance)
715
- action(:verify, instance)
716
- end
744
+ def verify(instance, state) ; end
717
745
 
718
746
  # Destroys an instance.
719
747
  #
720
748
  # @param instance [Instance] an instance
749
+ # @param state [Hash] mutable instance and driver state
721
750
  # @raise [ActionFailed] if the action could not be completed
722
- def destroy(instance)
723
- action(:destroy, instance)
724
- destroy_state(instance)
725
- end
751
+ def destroy(instance, state) ; end
726
752
 
727
753
  protected
728
754
 
729
755
  attr_reader :config
730
756
 
731
- def action(what, instance)
732
- state = load_state(instance)
733
- public_send("perform_#{what}", instance, state)
734
- state['last_action'] = what.to_s
735
- ensure
736
- dump_state(instance, state)
737
- end
738
-
739
- def load_state(instance)
740
- statefile = state_filepath(instance)
741
-
742
- if File.exists?(statefile)
743
- YAML.load_file(statefile)
744
- else
745
- { 'name' => instance.name }
746
- end
747
- end
748
-
749
- def dump_state(instance, state)
750
- statefile = state_filepath(instance)
751
- dir = File.dirname(statefile)
752
-
753
- FileUtils.mkdir_p(dir) if !File.directory?(dir)
754
- File.open(statefile, "wb") { |f| f.write(YAML.dump(state)) }
755
- end
756
-
757
- def destroy_state(instance)
758
- statefile = state_filepath(instance)
759
- FileUtils.rm(statefile) if File.exists?(statefile)
760
- end
761
-
762
- def state_filepath(instance)
763
- File.expand_path(File.join(
764
- config['jamie_root'], ".jamie", "#{instance.name}.yml"
765
- ))
766
- end
767
-
768
757
  def run_command(cmd, use_sudo = nil, log_subject = nil)
769
758
  use_sudo = config['use_sudo'] if use_sudo.nil?
770
759
  log_subject = Util.to_snake_case(self.class.to_s)
@@ -783,11 +772,15 @@ module Jamie
783
772
 
784
773
  # Base class for a driver that uses SSH to communication with an instance.
785
774
  # A subclass must implement the following methods:
786
- # * #perform_create(instance, state)
787
- # * #perform_destroy(instance, state)
775
+ # * #create(instance, state)
776
+ # * #destroy(instance, state)
788
777
  class SSHBase < Base
789
778
 
790
- def perform_converge(instance, state)
779
+ def create(instance, state)
780
+ raise NotImplementedError, "#create must be implemented by subclass."
781
+ end
782
+
783
+ def converge(instance, state)
791
784
  ssh_args = generate_ssh_args(state)
792
785
 
793
786
  install_omnibus(ssh_args) if config['require_chef_omnibus']
@@ -796,7 +789,7 @@ module Jamie
796
789
  run_chef_solo(ssh_args)
797
790
  end
798
791
 
799
- def perform_setup(instance, state)
792
+ def setup(instance, state)
800
793
  ssh_args = generate_ssh_args(state)
801
794
 
802
795
  if instance.jr.setup_cmd
@@ -804,7 +797,7 @@ module Jamie
804
797
  end
805
798
  end
806
799
 
807
- def perform_verify(instance, state)
800
+ def verify(instance, state)
808
801
  ssh_args = generate_ssh_args(state)
809
802
 
810
803
  if instance.jr.run_cmd
@@ -813,6 +806,10 @@ module Jamie
813
806
  end
814
807
  end
815
808
 
809
+ def destroy(instance, state)
810
+ raise NotImplementedError, "#destroy must be implemented by subclass."
811
+ end
812
+
816
813
  protected
817
814
 
818
815
  def generate_ssh_args(state)
@@ -988,16 +985,21 @@ module Jamie
988
985
  end
989
986
 
990
987
  def local_cookbooks
988
+ tmpdir = Dir.mktmpdir("#{instance.name}-cookbooks")
989
+ prepare_tmpdir(tmpdir)
990
+ tmpdir
991
+ end
992
+
993
+ def prepare_tmpdir(tmpdir)
991
994
  if File.exists?(File.join(jamie_root, "Berksfile"))
992
- tmpdir = Dir.mktmpdir(instance.name)
993
995
  run_berks(tmpdir)
994
- tmpdir
995
996
  elsif File.exists?(File.join(jamie_root, "Cheffile"))
996
- tmpdir = Dir.mktmpdir(instance.name)
997
997
  run_librarian(tmpdir)
998
- tmpdir
998
+ elsif File.directory?(File.join(jamie_root, "cookbooks"))
999
+ cp_cookbooks(tmpdir)
999
1000
  else
1000
- abort "Berksfile or Cheffile must exist in #{jamie_root}"
1001
+ FileUtils.rmtree(tmpdir)
1002
+ abort "Berksfile, Cheffile or cookbooks/ must exist in #{jamie_root}"
1001
1003
  end
1002
1004
  end
1003
1005
 
@@ -1018,6 +1020,50 @@ module Jamie
1018
1020
  end
1019
1021
  run_command "librarian-chef install --path #{tmpdir}"
1020
1022
  end
1023
+
1024
+ def cp_cookbooks(tmpdir)
1025
+ metadata_rb = File.join(jamie_root, "metadata.rb")
1026
+ cb_name = MetadataChopper.extract(metadata_rb).first
1027
+ abort ">>>>>> name attribute must be set in metadata.rb." if cb_name.nil?
1028
+ cb_path = File.join(tmpdir, cb_name)
1029
+ glob = Dir.glob("#{jamie_root}/{metadata.rb,README.*," +
1030
+ "attributes,files,libraries,providers,recipes,resources,templates}")
1031
+
1032
+ FileUtils.cp_r(File.join(jamie_root, "cookbooks", "."), tmpdir)
1033
+ FileUtils.mkdir_p(cb_path)
1034
+ FileUtils.cp_r(glob, cb_path)
1035
+ end
1021
1036
  end
1022
1037
 
1038
+ # A rather insane and questionable class to quickly consume a metadata.rb
1039
+ # file and return the cookbook name and version attributes.
1040
+ #
1041
+ # @see https://twitter.com/fnichol/status/281650077901144064
1042
+ # @see https://gist.github.com/4343327
1043
+ class MetadataChopper < Hash
1044
+
1045
+ # Return an Array containing the cookbook name and version attributes,
1046
+ # or nil values if they could not be parsed.
1047
+ #
1048
+ # @param metadata_file [String] path to a metadata.rb file
1049
+ # @return [Array<String>] array containing the cookbook name and version
1050
+ # attributes or nil values if they could not be determined
1051
+ def self.extract(metadata_file)
1052
+ mc = new(File.expand_path(metadata_file))
1053
+ [ mc[:name], mc[:version] ]
1054
+ end
1055
+
1056
+ # Creates a new instances and loads in the contents of the metdata.rb
1057
+ # file. If you value your life, you may want to avoid reading the
1058
+ # implementation.
1059
+ #
1060
+ # @param metadata_file [String] path to a metadata.rb file
1061
+ def initialize(metadata_file)
1062
+ eval(IO.read(metadata_file), nil, metadata_file)
1063
+ end
1064
+
1065
+ def method_missing(meth, *args, &block)
1066
+ self[meth] = args.first
1067
+ end
1068
+ end
1023
1069
  end
@@ -11,10 +11,10 @@ module Jamie
11
11
  # <%= klass_name %> driver for Jamie.
12
12
  class <%= klass_name %> < Jamie::Driver::SSHBase
13
13
 
14
- def perform_create(instance, state)
14
+ def create(instance, state)
15
15
  end
16
16
 
17
- def perform_destroy(instance, state)
17
+ def destroy(instance, state)
18
18
  end
19
19
  end
20
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jamie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha15
4
+ version: 0.1.0.alpha16
5
5
  prerelease: 6
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: 2012-12-24 00:00:00.000000000 Z
12
+ date: 2012-12-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -139,6 +139,22 @@ dependencies:
139
139
  - - ! '>='
140
140
  - !ruby/object:Gem::Version
141
141
  version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: countloc
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
142
158
  description: A Chef convergence integration test harness
143
159
  email:
144
160
  - fnichol@nichol.ca
@@ -183,7 +199,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
183
199
  version: '0'
184
200
  segments:
185
201
  - 0
186
- hash: 2338100729257258503
202
+ hash: -1684640608008309798
187
203
  required_rubygems_version: !ruby/object:Gem::Requirement
188
204
  none: false
189
205
  requirements: