jamie 0.1.0.alpha15 → 0.1.0.alpha16

Sign up to get free protection for your applications and to get access to all the features.
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: