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 +5 -0
- data/jamie.gemspec +1 -0
- data/lib/jamie/cli.rb +0 -32
- data/lib/jamie/version.rb +1 -1
- data/lib/jamie.rb +114 -68
- data/templates/plugin/driver.rb.erb +2 -2
- metadata +19 -3
data/Rakefile
CHANGED
data/jamie.gemspec
CHANGED
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
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
|
-
# * #
|
787
|
-
# * #
|
775
|
+
# * #create(instance, state)
|
776
|
+
# * #destroy(instance, state)
|
788
777
|
class SSHBase < Base
|
789
778
|
|
790
|
-
def
|
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
|
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
|
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
|
-
|
998
|
+
elsif File.directory?(File.join(jamie_root, "cookbooks"))
|
999
|
+
cp_cookbooks(tmpdir)
|
999
1000
|
else
|
1000
|
-
|
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
|
14
|
+
def create(instance, state)
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
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.
|
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-
|
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:
|
202
|
+
hash: -1684640608008309798
|
187
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
204
|
none: false
|
189
205
|
requirements:
|