spiceweasel 2.6.0 → 2.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +6 -14
  2. data/README.md +33 -9
  3. data/bin/spiceweasel +3 -3
  4. data/lib/spiceweasel.rb +3 -2
  5. data/lib/spiceweasel/berksfile.rb +6 -10
  6. data/lib/spiceweasel/cli.rb +174 -129
  7. data/lib/spiceweasel/clusters.rb +31 -23
  8. data/lib/spiceweasel/command.rb +23 -5
  9. data/lib/spiceweasel/command_helper.rb +36 -2
  10. data/lib/spiceweasel/config.rb +4 -3
  11. data/lib/spiceweasel/cookbooks.rb +76 -57
  12. data/lib/spiceweasel/data_bags.rb +100 -64
  13. data/lib/spiceweasel/environments.rb +78 -56
  14. data/lib/spiceweasel/execute.rb +6 -7
  15. data/lib/spiceweasel/extract_local.rb +59 -46
  16. data/lib/spiceweasel/knife.rb +21 -20
  17. data/lib/spiceweasel/log.rb +5 -5
  18. data/lib/spiceweasel/nodes.rb +261 -193
  19. data/lib/spiceweasel/roles.rb +107 -76
  20. data/lib/spiceweasel/version.rb +5 -3
  21. data/test/chef-repo/Berksfile +4 -0
  22. data/test/chef-repo/Berksfile.lock +10 -0
  23. data/test/chef-repo/PASSWORD +1 -0
  24. data/test/chef-repo/cookbooks/abc/CHANGELOG.md +13 -0
  25. data/test/chef-repo/cookbooks/abc/README.md +68 -0
  26. data/test/chef-repo/cookbooks/abc/metadata.rb +7 -0
  27. data/test/chef-repo/cookbooks/abc/recipes/default.rb +8 -0
  28. data/test/chef-repo/cookbooks/def/CHANGELOG.md +13 -0
  29. data/test/chef-repo/cookbooks/def/README.md +68 -0
  30. data/test/chef-repo/cookbooks/def/metadata.rb +7 -0
  31. data/test/chef-repo/cookbooks/def/recipes/default.rb +8 -0
  32. data/test/chef-repo/cookbooks/fail1/README.md +68 -0
  33. data/test/chef-repo/cookbooks/fail1/metadata.rb +9 -0
  34. data/test/chef-repo/cookbooks/fail2/README.md +68 -0
  35. data/test/chef-repo/cookbooks/fail2/metadata.rb +9 -0
  36. data/test/chef-repo/cookbooks/fail3/README.md +68 -0
  37. data/test/chef-repo/cookbooks/fail3/metadata.rb +9 -0
  38. data/test/chef-repo/cookbooks/ghi/CHANGELOG.md +13 -0
  39. data/test/chef-repo/cookbooks/ghi/README.md +68 -0
  40. data/test/chef-repo/cookbooks/ghi/metadata.rb +7 -0
  41. data/test/chef-repo/cookbooks/ghi/recipes/default.rb +8 -0
  42. data/test/chef-repo/cookbooks/jkl/CHANGELOG.md +13 -0
  43. data/test/chef-repo/cookbooks/jkl/README.md +68 -0
  44. data/test/chef-repo/cookbooks/jkl/metadata.rb +10 -0
  45. data/test/chef-repo/cookbooks/jkl/recipes/default.rb +8 -0
  46. data/test/chef-repo/cookbooks/mno/CHANGELOG.md +13 -0
  47. data/test/chef-repo/cookbooks/mno/README.md +68 -0
  48. data/test/chef-repo/cookbooks/mno/metadata.rb +9 -0
  49. data/test/chef-repo/cookbooks/mno/recipes/default.rb +8 -0
  50. data/test/chef-repo/data_bags/junk/README +1 -0
  51. data/test/chef-repo/data_bags/junk/abc.json +4 -0
  52. data/test/chef-repo/data_bags/junk/ade.json +4 -0
  53. data/test/chef-repo/data_bags/junk/afg.json +4 -0
  54. data/test/chef-repo/data_bags/junk/bcd.json +4 -0
  55. data/test/chef-repo/data_bags/junk/sub1/cde1.json +4 -0
  56. data/test/chef-repo/data_bags/junk/sub1/cde2.json +4 -0
  57. data/test/chef-repo/data_bags/junk/sub2/def1.json +4 -0
  58. data/test/chef-repo/data_bags/junk/sub2/def2.json +4 -0
  59. data/test/chef-repo/data_bags/users/README +1 -0
  60. data/test/chef-repo/data_bags/users/badjson.json +8 -0
  61. data/test/chef-repo/data_bags/users/failname.json +8 -0
  62. data/test/chef-repo/data_bags/users/mray.json +8 -0
  63. data/test/chef-repo/data_bags/users/ubuntu.json +8 -0
  64. data/test/chef-repo/environments/development.rb +2 -0
  65. data/test/chef-repo/environments/fail2.rb +8 -0
  66. data/test/chef-repo/environments/fail3.rb +2 -0
  67. data/test/chef-repo/environments/production-blue.json +177 -0
  68. data/test/chef-repo/environments/production-green.json +177 -0
  69. data/test/chef-repo/environments/production-red.json +177 -0
  70. data/test/chef-repo/environments/qa.rb +2 -0
  71. data/test/chef-repo/environments/sub/efg1.rb +2 -0
  72. data/test/chef-repo/environments/sub/efg2.json +177 -0
  73. data/test/chef-repo/fail-cookbook1.yml +19 -0
  74. data/test/chef-repo/fail-cookbook2.yml +21 -0
  75. data/test/chef-repo/fail-cookbook3.yml +37 -0
  76. data/test/chef-repo/fail-cookbook4.yml +37 -0
  77. data/test/chef-repo/fail-cookbook5.yml +10 -0
  78. data/test/chef-repo/fail-cookbook6.yml +9 -0
  79. data/test/chef-repo/fail-db1.yml +12 -0
  80. data/test/chef-repo/fail-db2.yml +10 -0
  81. data/test/chef-repo/fail-db3.yml +10 -0
  82. data/test/chef-repo/fail-db4.yml +10 -0
  83. data/test/chef-repo/fail-env1.yml +27 -0
  84. data/test/chef-repo/fail-env2.yml +27 -0
  85. data/test/chef-repo/fail-env3.yml +28 -0
  86. data/test/chef-repo/fail-env4.yml +28 -0
  87. data/test/chef-repo/fail-roles1.yml +22 -0
  88. data/test/chef-repo/fail-roles2.yml +21 -0
  89. data/test/chef-repo/fail-roles3.yml +23 -0
  90. data/test/chef-repo/fail-roles4.yml +23 -0
  91. data/test/chef-repo/fail-roles5.yml +23 -0
  92. data/test/chef-repo/infrastructure.yml +43 -0
  93. data/test/chef-repo/nodes/boxy.lab.atx.json +1756 -0
  94. data/test/chef-repo/nodes/guenter.home.atx.json +2503 -0
  95. data/test/chef-repo/roles/README +1 -0
  96. data/test/chef-repo/roles/base.rb +18 -0
  97. data/test/chef-repo/roles/base2.rb +16 -0
  98. data/test/chef-repo/roles/base3.rb +17 -0
  99. data/test/chef-repo/roles/base4.rb +15 -0
  100. data/test/chef-repo/roles/fail1.rb +8 -0
  101. data/test/chef-repo/roles/fail2.rb +5 -0
  102. data/test/chef-repo/roles/fail3.rb +5 -0
  103. data/test/chef-repo/roles/sub/bw2.json +21 -0
  104. data/test/chef-repo/roles/sub/bwi1.json +20 -0
  105. data/test/chef-repo/roles/tc.rb +13 -0
  106. data/test/examples/cluster-file-example.yml +14 -0
  107. data/test/examples/example-cluster.yml +8 -0
  108. data/test/examples/example.json +127 -0
  109. data/test/examples/example.rb +128 -0
  110. data/test/examples/example.yml +67 -0
  111. data/test/examples/google-example.yml +33 -0
  112. data/test/examples/joyent-vsphere-example.yml +15 -0
  113. data/test/examples/knife.yml +7 -0
  114. data/test/examples/kvm-example.yml +22 -0
  115. data/test/examples/node-example.yml +23 -0
  116. data/test/examples/php-quick-start.yml +83 -0
  117. data/test/extract-repo/Berksfile +4 -0
  118. data/test/extract-repo/Berksfile.lock +10 -0
  119. data/test/extract-repo/cookbooks/abc/CHANGELOG.md +13 -0
  120. data/test/extract-repo/cookbooks/abc/README.md +68 -0
  121. data/test/extract-repo/cookbooks/abc/metadata.rb +7 -0
  122. data/test/extract-repo/cookbooks/abc/recipes/default.rb +8 -0
  123. data/test/extract-repo/cookbooks/def/CHANGELOG.md +13 -0
  124. data/test/extract-repo/cookbooks/def/README.md +68 -0
  125. data/test/extract-repo/cookbooks/def/metadata.rb +7 -0
  126. data/test/extract-repo/cookbooks/def/recipes/default.rb +8 -0
  127. data/test/extract-repo/cookbooks/ghi/CHANGELOG.md +13 -0
  128. data/test/extract-repo/cookbooks/ghi/README.md +68 -0
  129. data/test/extract-repo/cookbooks/ghi/metadata.rb +7 -0
  130. data/test/extract-repo/cookbooks/ghi/recipes/default.rb +8 -0
  131. data/test/extract-repo/cookbooks/jkl/CHANGELOG.md +13 -0
  132. data/test/extract-repo/cookbooks/jkl/README.md +68 -0
  133. data/test/extract-repo/cookbooks/jkl/metadata.rb +10 -0
  134. data/test/extract-repo/cookbooks/jkl/recipes/default.rb +8 -0
  135. data/test/extract-repo/cookbooks/mno/CHANGELOG.md +13 -0
  136. data/test/extract-repo/cookbooks/mno/README.md +68 -0
  137. data/test/extract-repo/cookbooks/mno/metadata.rb +9 -0
  138. data/test/extract-repo/cookbooks/mno/recipes/default.rb +8 -0
  139. data/test/extract-repo/data_bags/junk/README +1 -0
  140. data/test/extract-repo/data_bags/junk/abc.json +4 -0
  141. data/test/extract-repo/data_bags/junk/ade.json +4 -0
  142. data/test/extract-repo/data_bags/junk/afg.json +4 -0
  143. data/test/extract-repo/data_bags/junk/bcd.json +4 -0
  144. data/test/extract-repo/data_bags/junk/sub1/cde1.json +4 -0
  145. data/test/extract-repo/data_bags/junk/sub1/cde2.json +4 -0
  146. data/test/extract-repo/data_bags/junk/sub2/def1.json +4 -0
  147. data/test/extract-repo/data_bags/junk/sub2/def2.json +4 -0
  148. data/test/extract-repo/data_bags/users/README +1 -0
  149. data/test/extract-repo/data_bags/users/mray.json +8 -0
  150. data/test/extract-repo/data_bags/users/ubuntu.json +8 -0
  151. data/test/extract-repo/environments/development.rb +2 -0
  152. data/test/extract-repo/environments/production-blue.json +177 -0
  153. data/test/extract-repo/environments/production-green.json +177 -0
  154. data/test/extract-repo/environments/production-red.json +177 -0
  155. data/test/extract-repo/environments/qa.rb +2 -0
  156. data/test/extract-repo/environments/sub/efg1.rb +2 -0
  157. data/test/extract-repo/environments/sub/efg2.json +177 -0
  158. data/test/extract-repo/nodes/boxy.lab.atx.json +1756 -0
  159. data/test/extract-repo/nodes/guenter.home.atx.json +2503 -0
  160. data/test/extract-repo/roles/README +1 -0
  161. data/test/extract-repo/roles/base.rb +18 -0
  162. data/test/extract-repo/roles/base2.rb +16 -0
  163. data/test/extract-repo/roles/base3.rb +17 -0
  164. data/test/extract-repo/roles/base4.rb +16 -0
  165. data/test/extract-repo/roles/sub/bw2.json +21 -0
  166. data/test/extract-repo/roles/sub/bwi1.json +20 -0
  167. data/test/extract-repo/roles/tc.rb +13 -0
  168. data/test/extract-repo2/cookbooks/README.md +1 -0
  169. data/test/extract-repo2/data_bags/README.md +1 -0
  170. data/test/extract-repo2/environments/README.md +1 -0
  171. data/test/extract-repo2/nodes/README.md +1 -0
  172. data/test/extract-repo2/roles/README.md +1 -0
  173. metadata +357 -67
  174. data/spec/bin/chef_client_spec.rb +0 -72
  175. data/spec/bin/google_spec.rb +0 -105
  176. data/spec/bin/joyent-vsphere_spec.rb +0 -25
  177. data/spec/bin/knife_spec.rb +0 -18
  178. data/spec/bin/kvm_spec.rb +0 -29
  179. data/spec/bin/node_spec.rb +0 -108
  180. data/spec/bin/spiceweasel_spec.rb +0 -136
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2012-2013, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2012-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -17,40 +18,43 @@
17
18
  #
18
19
 
19
20
  module Spiceweasel
21
+ # manages parsing of cluster files
20
22
  class Clusters
21
-
22
23
  attr_reader :create, :delete
23
24
 
24
- def initialize(clusters, cookbooks, environments, roles, knifecommands)
25
- @create = Array.new
26
- @delete = Array.new
27
- if clusters
28
- Spiceweasel::Log.debug("clusters: #{clusters}")
29
- clusters.each do |cluster|
30
- cluster_name = cluster.keys.first
31
- cluster_process_nodes(cluster, cluster_name, cookbooks, environments, roles, knifecommands)
32
- end
25
+ def initialize(clusters, cookbooks, environments, roles, knifecommands, rootoptions)
26
+ @create = []
27
+ @delete = []
28
+ return unless clusters
29
+ Spiceweasel::Log.debug("clusters: #{clusters}")
30
+ clusters.each do |cluster|
31
+ cluster_name = cluster.keys.first
32
+ cluster_process_nodes(cluster, cluster_name, cookbooks, environments, roles, knifecommands, rootoptions)
33
33
  end
34
34
  end
35
35
 
36
36
  # configure the individual nodes within the cluster
37
- def cluster_process_nodes(cluster, environment, cookbooks, environments, roles, knifecommands)
37
+ def cluster_process_nodes(cluster, environment, cookbooks, environments, roles, knifecommands, rootoptions)
38
38
  Spiceweasel::Log.debug("cluster::cluster_process_nodes '#{environment}' '#{cluster[environment]}'")
39
39
  cluster[environment].each do |node|
40
40
  node_name = node.keys.first
41
41
  options = node[node_name]['options'] || ''
42
42
  validate_environment(options, environment, environments) unless Spiceweasel::Config[:novalidation]
43
- #push the Environment back on the options
43
+ # push the Environment back on the options
44
44
  node[node_name]['options'] = options + " -E #{environment}"
45
45
  end
46
46
  # let's reuse the Nodes logic
47
- nodes = Spiceweasel::Nodes.new(cluster[environment], cookbooks, environments, roles, knifecommands)
47
+ nodes = Spiceweasel::Nodes.new(cluster[environment], cookbooks, environments, roles, knifecommands, rootoptions)
48
48
  @create.concat(nodes.create)
49
- #what about providers??
49
+ # what about providers??
50
50
  nodes.delete.each do |del|
51
- @delete << del unless del.to_s =~ /^knife client|^knife node/
51
+ @delete.push(del) unless del.to_s =~ /^knife client|^knife node/
52
+ end
53
+ if bundler?
54
+ @delete.push(Command.new("for N in $(bundle exec knife node list -E #{environment}); do bundle exec knife client delete $N -y; bundle exec knife node delete $N -y; done"))
55
+ else
56
+ @delete.push(Command.new("for N in $(knife node list -E #{environment}); do knife client delete $N -y; knife node delete $N -y; done"))
52
57
  end
53
- @delete << "for N in $(knife node list -E #{environment}); do knife client delete $N -y; knife node delete $N -y; done"
54
58
  end
55
59
 
56
60
  def validate_environment(options, cluster, environments)
@@ -58,12 +62,16 @@ module Spiceweasel
58
62
  STDERR.puts "ERROR: Environment '#{cluster}' is listed in the cluster, but not specified as an 'environment' in the manifest."
59
63
  exit(-1)
60
64
  end
61
- if options =~ /-E/ #Environment must match the cluster
62
- env = options.split('-E')[1].split[0]
63
- STDERR.puts "ERROR: Environment '#{env}' is specified for a node in cluster '#{cluster}'. The Environment is the cluster name."
64
- exit(-1)
65
- end
65
+
66
+ return unless options =~ /-E/ # Environment must match the cluster
67
+
68
+ env = options.split('-E')[1].split[0]
69
+ STDERR.puts "ERROR: Environment '#{env}' is specified for a node in cluster '#{cluster}'. The Environment is the cluster name."
70
+ exit(-1)
66
71
  end
67
72
 
73
+ def bundler?
74
+ ENV.key?('BUNDLE_BIN_PATH')
75
+ end
68
76
  end
69
77
  end
@@ -1,15 +1,34 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Matt Ray (<matt@getchef.com>)
4
+ #
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
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
+
1
20
  module Spiceweasel
21
+ # prepares shellout calls
2
22
  class Command
3
-
4
23
  attr_reader :allow_failure
5
24
  attr_reader :timeout
6
25
  attr_reader :command
7
-
8
- def initialize(command, options={})
26
+
27
+ def initialize(command, options = {})
9
28
  @command = command.rstrip
10
29
  @options = options
11
30
  @timeout = options['timeout']
12
- @allow_failure = options.has_key?('allow_failure') ? options['allow_failure'] : true
31
+ @allow_failure = options.key?('allow_failure') ? options['allow_failure'] : true
13
32
  end
14
33
 
15
34
  def shellout_opts
@@ -20,6 +39,5 @@ module Spiceweasel
20
39
 
21
40
  alias_method :allow_failure?, :allow_failure
22
41
  alias_method :to_s, :command
23
-
24
42
  end
25
43
  end
@@ -1,15 +1,49 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Matt Ray (<matt@getchef.com>)
4
+ #
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
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
+
1
20
  require 'spiceweasel/command'
2
21
 
3
22
  module Spiceweasel
23
+ # helpers for create and delete commands
4
24
  module CommandHelper
5
25
  def create_command(*args)
6
26
  @create ||= []
7
- @create.push(Command.new(*args))
27
+ if bundler?
28
+ args[0] = 'bundle exec ' + args[0]
29
+ @create.push(Command.new(*args))
30
+ else
31
+ @create.push(Command.new(*args))
32
+ end
8
33
  end
9
34
 
10
35
  def delete_command(*args)
11
36
  @delete ||= []
12
- @delete.push(Command.new(*args))
37
+ if bundler?
38
+ args[0] = 'bundle exec ' + args[0]
39
+ @delete.push(Command.new(*args))
40
+ else
41
+ @delete.push(Command.new(*args))
42
+ end
43
+ end
44
+
45
+ def bundler?
46
+ ENV.key?('BUNDLE_BIN_PATH')
13
47
  end
14
48
  end
15
49
  end
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2012, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2012-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -19,6 +20,7 @@
19
20
  require 'mixlib/config'
20
21
 
21
22
  module Spiceweasel
23
+ # provides defaults and manages the configuration via Mixlib::Config
22
24
  class Config
23
25
  extend Mixlib::Config
24
26
 
@@ -41,6 +43,5 @@ module Spiceweasel
41
43
  parallel false
42
44
  rebuild false
43
45
  siteinstall false
44
-
45
46
  end
46
47
  end
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -19,73 +20,92 @@
19
20
  require 'chef/cookbook/metadata'
20
21
 
21
22
  module Spiceweasel
23
+ # manages parsing of Cookbooks
22
24
  class Cookbooks
23
-
24
25
  include CommandHelper
25
26
 
26
27
  attr_reader :cookbook_list, :create, :delete
27
28
 
28
- def initialize(cookbooks = [], other_cookbook_list = {})
29
- @create = Array.new
30
- @delete = Array.new
29
+ def initialize(cookbooks = [], other_cookbook_list = {}) # rubocop:disable CyclomaticComplexity
30
+ @create = []
31
+ @delete = []
31
32
  @cookbook_list = other_cookbook_list
32
- @dependencies = Array.new
33
- #validate each of the cookbooks specified in the manifest
34
- if cookbooks
35
- @loader = Chef::CookbookLoader.new(Spiceweasel::Config[:cookbook_dir])
33
+ @dependencies = []
34
+
35
+ return unless cookbooks
36
+
37
+ # validate each of the cookbooks specified in the manifest
38
+ @loader = Chef::CookbookLoader.new(Spiceweasel::Config[:cookbook_dir])
39
+ begin
36
40
  @loader.load_cookbooks
37
- Spiceweasel::Log.debug("cookbooks: #{cookbooks}")
41
+ rescue SyntaxError => e
42
+ STDERR.puts 'ERROR: invalid cookbook metadata.'
43
+ STDERR.puts e.message
44
+ exit(-1)
45
+ end
46
+ Spiceweasel::Log.debug("cookbooks: #{cookbooks}")
38
47
 
39
- c_names = []
40
- cookbooks.each do |cookbook|
41
- name = cookbook.keys.first
42
- if cookbook[name]
43
- version = cookbook[name]['version']
44
- options = cookbook[name]['options']
45
- end
46
- Spiceweasel::Log.debug("cookbook: #{name} #{version} #{options}")
47
- if File.directory?("cookbooks")
48
+ validate_cookbooks(cookbooks)
49
+ end
48
50
 
49
- if @loader.cookbooks_by_name[name]
50
- validateMetadata(name,version) unless Spiceweasel::Config[:novalidation]
51
- else
52
- if Spiceweasel::Config[:siteinstall] #use knife cookbook site install
53
- create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} site install #{name} #{version} #{options}")
54
- else #use knife cookbook site download, untar and then remove the tarball
55
- create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} site download #{name} #{version} --file cookbooks/#{name}.tgz #{options}")
56
- create_command("tar -C cookbooks/ -xf cookbooks/#{name}.tgz")
57
- create_command("rm -f cookbooks/#{name}.tgz")
58
- end
59
- end
60
- elsif !Spiceweasel::Config[:novalidation]
61
- STDERR.puts "ERROR: 'cookbooks' directory not found, unable to validate, download and load cookbooks"
62
- exit(-1)
63
- end
51
+ def validate_cookbooks(cookbooks)
52
+ c_names = []
53
+ cookbooks.each do |cookbook|
54
+ name = cookbook.keys.first
55
+ if cookbook[name]
56
+ version = cookbook[name]['version']
57
+ options = cookbook[name]['options']
58
+ end
59
+ Spiceweasel::Log.debug("cookbook: #{name} #{version} #{options}")
60
+
61
+ validate_metadata_or_get_knife_commands_wrapper(name, options, version)
64
62
 
65
- if(options)
66
- if !c_names.empty?
67
- create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{c_names.join(' ')}")
68
- c_names = []
69
- end
70
- create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{name} #{options}")
71
- else
72
- c_names.push(name)
63
+ if options
64
+ unless c_names.empty?
65
+ create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{c_names.join(' ')}")
66
+ c_names = []
73
67
  end
74
- delete_command("knife cookbook#{Spiceweasel::Config[:knife_options]} delete #{name} #{version} -a -y")
75
- @cookbook_list[name] = version #used for validation
68
+ create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{name} #{options}")
69
+ else
70
+ c_names.push(name)
76
71
  end
77
- if !c_names.empty?
78
- create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{c_names.join(' ')}")
72
+ delete_command("knife cookbook#{Spiceweasel::Config[:knife_options]} delete #{name} #{version} -a -y")
73
+ @cookbook_list[name] = version # used for validation
74
+ end
75
+ unless c_names.empty?
76
+ create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{c_names.join(' ')}")
77
+ end
78
+ validate_dependencies unless Spiceweasel::Config[:novalidation]
79
+ end
80
+
81
+ def validate_metadata_or_get_knife_commands_wrapper(name, options, version)
82
+ if File.directory?('cookbooks')
83
+ if @loader.cookbooks_by_name[name]
84
+ validate_metadata(name, version) unless Spiceweasel::Config[:novalidation]
85
+ else
86
+ get_knife_commands(name, options, version)
79
87
  end
80
- validateDependencies() unless Spiceweasel::Config[:novalidation]
88
+ elsif !Spiceweasel::Config[:novalidation]
89
+ STDERR.puts "ERROR: 'cookbooks' directory not found, unable to validate, download and load cookbooks"
90
+ exit(-1)
81
91
  end
82
92
  end
83
93
 
84
- #check the metadata for versions and gather deps
85
- def validateMetadata(cookbook,version)
86
- #check metadata.rb for requested version
94
+ def get_knife_commands(name, options, version)
95
+ if Spiceweasel::Config[:siteinstall] # use knife cookbook site install
96
+ create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} site install #{name} #{version} #{options}")
97
+ else # use knife cookbook site download, untar and then remove the tarball
98
+ create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} site download #{name} #{version} --file cookbooks/#{name}.tgz #{options}")
99
+ create_command("tar -C cookbooks/ -xf cookbooks/#{name}.tgz")
100
+ create_command("rm -f cookbooks/#{name}.tgz")
101
+ end
102
+ end
103
+
104
+ # check the metadata for versions and gather deps
105
+ def validate_metadata(cookbook, version)
106
+ # check metadata.rb for requested version
87
107
  metadata = @loader.cookbooks_by_name[cookbook].metadata
88
- Spiceweasel::Log.debug("validateMetadata: #{cookbook} #{metadata.name} #{metadata.version}")
108
+ Spiceweasel::Log.debug("validate_metadata: #{cookbook} #{metadata.name} #{metadata.version}")
89
109
  # Should the cookbook directory match the name in the metadata?
90
110
  if metadata.name.empty?
91
111
  Spiceweasel::Log.warn("No cookbook name in the #{cookbook} metadata.rb.")
@@ -103,11 +123,11 @@ module Spiceweasel
103
123
  end
104
124
  end
105
125
 
106
- #compare the list of cookbook deps with those specified
107
- def validateDependencies()
108
- Spiceweasel::Log.debug("cookbook validateDependencies: '#{@dependencies}'")
126
+ # compare the list of cookbook deps with those specified
127
+ def validate_dependencies
128
+ Spiceweasel::Log.debug("cookbook validate_dependencies: '#{@dependencies}'")
109
129
  @dependencies.each do |dep|
110
- if !member?(dep)
130
+ unless member?(dep)
111
131
  STDERR.puts "ERROR: Cookbook dependency '#{dep}' is missing from the list of cookbooks in the manifest."
112
132
  exit(-1)
113
133
  end
@@ -117,6 +137,5 @@ module Spiceweasel
117
137
  def member?(cookbook)
118
138
  cookbook_list.keys.include?(cookbook)
119
139
  end
120
-
121
140
  end
122
141
  end
@@ -1,7 +1,8 @@
1
+ # encoding: UTF-8
1
2
  #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
+ # Author:: Matt Ray (<matt@getchef.com>)
3
4
  #
4
- # Copyright:: 2011-2013, Opscode, Inc <legal@opscode.com>
5
+ # Copyright:: 2011-2014, Chef Software, Inc <legal@getchef.com>
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
7
8
  # you may not use this file except in compliance with the License.
@@ -16,85 +17,120 @@
16
17
  # limitations under the License.
17
18
  #
18
19
 
19
- require 'yajl/json_gem'
20
+ require 'ffi_yajl'
21
+
22
+ require 'spiceweasel/command_helper'
20
23
 
21
24
  module Spiceweasel
25
+ # manages parsing of Data Bags
22
26
  class DataBags
23
-
24
27
  include CommandHelper
25
28
 
26
29
  attr_reader :create, :delete
27
30
 
28
- def initialize(data_bags = [])
29
- @create = Array.new
30
- @delete = Array.new
31
- if data_bags
32
- Spiceweasel::Log.debug("data bags: #{data_bags}")
33
- data_bags.each do |data_bag|
34
- db = data_bag.keys.first
35
- #check directories
36
- if !File.directory?("data_bags") && !Spiceweasel::Config[:novalidation]
37
- STDERR.puts "ERROR: 'data_bags' directory not found, unable to validate or load data bag items"
38
- exit(-1)
39
- end
40
- if !File.directory?("data_bags/#{db}") && !Spiceweasel::Config[:novalidation]
41
- STDERR.puts "ERROR: 'data_bags/#{db}' directory not found, unable to validate or load data bag items"
42
- exit(-1)
43
- end
44
- create_command("knife data bag#{Spiceweasel::Config[:knife_options]} create #{db}")
45
- delete_command("knife data bag#{Spiceweasel::Config[:knife_options]} delete #{db} -y")
46
- if data_bag[db]
47
- items = data_bag[db]['items']
48
- secret = data_bag[db]['secret']
49
- if secret && !File.exists?(File.expand_path(secret)) && !Spiceweasel::Config[:novalidation]
50
- STDERR.puts "ERROR: secret key #{secret} not found, unable to load encrypted data bags for data bag #{db}."
51
- exit(-1)
52
- end
53
- end
54
- items = [] if items.nil?
55
- Spiceweasel::Log.debug("data bag: #{db} #{secret} #{items}")
56
- items.each do |item|
57
- Spiceweasel::Log.debug("data bag #{db} item: #{item}")
58
- if item =~ /\*/ #wildcard support, will fail if directory not present
59
- files = Dir.glob("data_bags/#{db}/#{item}")
60
- #remove anything not ending in .json
61
- files.delete_if {|x| !x.end_with?('.json')}
62
- items.concat(files.collect {|x| x["data_bags/#{db}/".length..-6]})
63
- Spiceweasel::Log.debug("found files '#{files}' for data bag: #{db} with wildcard #{item}")
64
- next
65
- end
66
- validateItem(db, item) unless Spiceweasel::Config[:novalidation]
67
- end
68
- items.delete_if {|x| x.include?("*")} #remove wildcards
69
- items.sort!.uniq!
70
- unless items.empty?
71
- if secret
72
- create_command("knife data bag#{Spiceweasel::Config[:knife_options]} from file #{db} #{items.join('.json ')}.json --secret-file #{secret}")
73
- else
74
- create_command("knife data bag#{Spiceweasel::Config[:knife_options]} from file #{db} #{items.join('.json ')}.json")
75
- end
76
- end
31
+ def initialize(data_bags = []) # rubocop:disable CyclomaticComplexity
32
+ @create = []
33
+ @delete = []
34
+
35
+ return unless data_bags
36
+
37
+ Spiceweasel::Log.debug("data bags: #{data_bags}")
38
+
39
+ data_bags.each do |data_bag|
40
+ db, items, secret = knife_data_bag_create_delete(data_bag)
41
+ items = invoke_validate_item(db, items, secret)
42
+
43
+ items.delete_if { |x| x.include?('*') } # remove wildcards
44
+
45
+ items.sort!.uniq!
46
+
47
+ data_bag_from_file(db, items, secret)
48
+ end
49
+ end
50
+
51
+ def data_bag_from_file(db, items, secret)
52
+ return if items.empty?
53
+
54
+ if secret
55
+ create_command("knife data bag#{Spiceweasel::Config[:knife_options]} from file #{db} #{items.join('.json ')}.json --secret-file #{secret}")
56
+ else
57
+ create_command("knife data bag#{Spiceweasel::Config[:knife_options]} from file #{db} #{items.join('.json ')}.json")
58
+ end
59
+ end
60
+
61
+ def invoke_validate_item(db, items, secret)
62
+ items = [] if items.nil?
63
+ Spiceweasel::Log.debug("data bag: #{db} #{secret} #{items}")
64
+ items.each do |item|
65
+ Spiceweasel::Log.debug("data bag #{db} item: #{item}")
66
+ if item =~ /\*/ # wildcard support, will fail if directory not present
67
+ files = Dir.glob("data_bags/#{db}/#{item}")
68
+ # remove anything not ending in .json
69
+ files.delete_if { |x| !x.end_with?('.json') }
70
+ items.concat(files.map { |x| x["data_bags/#{db}/".length..-6] })
71
+ Spiceweasel::Log.debug("found files '#{files}' for data bag: #{db} with wildcard #{item}")
72
+ next
73
+ end
74
+ validate_item(db, item) unless Spiceweasel::Config[:novalidation]
75
+ end
76
+ items
77
+ end
78
+
79
+ def knife_data_bag_create_delete(data_bag)
80
+ db = data_bag.keys.first
81
+ # check directories
82
+ if !File.directory?('data_bags') && !Spiceweasel::Config[:novalidation]
83
+ STDERR.puts "ERROR: 'data_bags' directory not found, unable to validate or load data bag items"
84
+ exit(-1)
85
+ end
86
+
87
+ if !File.directory?("data_bags/#{db}") && !Spiceweasel::Config[:novalidation]
88
+ STDERR.puts "ERROR: 'data_bags/#{db}' directory not found, unable to validate or load data bag items"
89
+ exit(-1)
90
+ end
91
+
92
+ create_command("knife data bag#{Spiceweasel::Config[:knife_options]} create #{db}")
93
+ delete_command("knife data bag#{Spiceweasel::Config[:knife_options]} delete #{db} -y")
94
+
95
+ items, secret = identify_items_secret(data_bag, db)
96
+ return db, items, secret
97
+ end
98
+
99
+ def identify_items_secret(data_bag, db)
100
+ items = nil
101
+ secret = nil
102
+ if data_bag[db]
103
+ items = data_bag[db]['items']
104
+ secret = data_bag[db]['secret']
105
+ if secret && !File.exist?(File.expand_path(secret)) && !Spiceweasel::Config[:novalidation]
106
+ STDERR.puts "ERROR: secret key #{secret} not found, unable to load encrypted data bags for data bag #{db}."
107
+ exit(-1)
77
108
  end
78
109
  end
110
+ return items, secret
79
111
  end
80
112
 
81
- #validate the item to be loaded
82
- def validateItem(db, item)
83
- if !File.exists?("data_bags/#{db}/#{item}.json")
113
+ # validate the item to be loaded
114
+ def validate_item(db, item)
115
+ unless File.exist?("data_bags/#{db}/#{item}.json")
84
116
  STDERR.puts "ERROR: data bag '#{db}' item '#{item}' file 'data_bags/#{db}/#{item}.json' does not exist"
85
117
  exit(-1)
86
118
  end
87
119
  f = File.read("data_bags/#{db}/#{item}.json")
88
- itemfile = JSON.parse(f) #invalid JSON will throw a trace
89
- #validate the id matches the file name
90
- if item =~ /\// #pull out directories
91
- item = item.split('/').last
92
- end
93
- if !item.eql?(itemfile['id'])
94
- STDERR.puts "ERROR: data bag '#{db}' item '#{item}' listed in the manifest does not match the id '#{itemfile['id']}' within the 'data_bags/#{db}/#{item}.json' file."
120
+ begin
121
+ itemfile = JSON.parse(f)
122
+ rescue JSON::ParserError => e # invalid JSON
123
+ STDERR.puts "ERROR: data bag '#{db} item '#{item}' has JSON errors."
124
+ STDERR.puts e.message
95
125
  exit(-1)
96
126
  end
97
- end
127
+ # validate the id matches the file name
128
+ item = item.split('/').last if item =~ /\// # pull out directories
98
129
 
130
+ return if item.eql?(itemfile['id'])
131
+
132
+ STDERR.puts "ERROR: data bag '#{db}' item '#{item}' listed in the manifest does not match the id '#{itemfile['id']}' within the 'data_bags/#{db}/#{item}.json' file."
133
+ exit(-1)
134
+ end
99
135
  end
100
136
  end