spiceweasel 2.6.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +6 -14
- data/README.md +33 -9
- data/bin/spiceweasel +3 -3
- data/lib/spiceweasel.rb +3 -2
- data/lib/spiceweasel/berksfile.rb +6 -10
- data/lib/spiceweasel/cli.rb +174 -129
- data/lib/spiceweasel/clusters.rb +31 -23
- data/lib/spiceweasel/command.rb +23 -5
- data/lib/spiceweasel/command_helper.rb +36 -2
- data/lib/spiceweasel/config.rb +4 -3
- data/lib/spiceweasel/cookbooks.rb +76 -57
- data/lib/spiceweasel/data_bags.rb +100 -64
- data/lib/spiceweasel/environments.rb +78 -56
- data/lib/spiceweasel/execute.rb +6 -7
- data/lib/spiceweasel/extract_local.rb +59 -46
- data/lib/spiceweasel/knife.rb +21 -20
- data/lib/spiceweasel/log.rb +5 -5
- data/lib/spiceweasel/nodes.rb +261 -193
- data/lib/spiceweasel/roles.rb +107 -76
- data/lib/spiceweasel/version.rb +5 -3
- data/test/chef-repo/Berksfile +4 -0
- data/test/chef-repo/Berksfile.lock +10 -0
- data/test/chef-repo/PASSWORD +1 -0
- data/test/chef-repo/cookbooks/abc/CHANGELOG.md +13 -0
- data/test/chef-repo/cookbooks/abc/README.md +68 -0
- data/test/chef-repo/cookbooks/abc/metadata.rb +7 -0
- data/test/chef-repo/cookbooks/abc/recipes/default.rb +8 -0
- data/test/chef-repo/cookbooks/def/CHANGELOG.md +13 -0
- data/test/chef-repo/cookbooks/def/README.md +68 -0
- data/test/chef-repo/cookbooks/def/metadata.rb +7 -0
- data/test/chef-repo/cookbooks/def/recipes/default.rb +8 -0
- data/test/chef-repo/cookbooks/fail1/README.md +68 -0
- data/test/chef-repo/cookbooks/fail1/metadata.rb +9 -0
- data/test/chef-repo/cookbooks/fail2/README.md +68 -0
- data/test/chef-repo/cookbooks/fail2/metadata.rb +9 -0
- data/test/chef-repo/cookbooks/fail3/README.md +68 -0
- data/test/chef-repo/cookbooks/fail3/metadata.rb +9 -0
- data/test/chef-repo/cookbooks/ghi/CHANGELOG.md +13 -0
- data/test/chef-repo/cookbooks/ghi/README.md +68 -0
- data/test/chef-repo/cookbooks/ghi/metadata.rb +7 -0
- data/test/chef-repo/cookbooks/ghi/recipes/default.rb +8 -0
- data/test/chef-repo/cookbooks/jkl/CHANGELOG.md +13 -0
- data/test/chef-repo/cookbooks/jkl/README.md +68 -0
- data/test/chef-repo/cookbooks/jkl/metadata.rb +10 -0
- data/test/chef-repo/cookbooks/jkl/recipes/default.rb +8 -0
- data/test/chef-repo/cookbooks/mno/CHANGELOG.md +13 -0
- data/test/chef-repo/cookbooks/mno/README.md +68 -0
- data/test/chef-repo/cookbooks/mno/metadata.rb +9 -0
- data/test/chef-repo/cookbooks/mno/recipes/default.rb +8 -0
- data/test/chef-repo/data_bags/junk/README +1 -0
- data/test/chef-repo/data_bags/junk/abc.json +4 -0
- data/test/chef-repo/data_bags/junk/ade.json +4 -0
- data/test/chef-repo/data_bags/junk/afg.json +4 -0
- data/test/chef-repo/data_bags/junk/bcd.json +4 -0
- data/test/chef-repo/data_bags/junk/sub1/cde1.json +4 -0
- data/test/chef-repo/data_bags/junk/sub1/cde2.json +4 -0
- data/test/chef-repo/data_bags/junk/sub2/def1.json +4 -0
- data/test/chef-repo/data_bags/junk/sub2/def2.json +4 -0
- data/test/chef-repo/data_bags/users/README +1 -0
- data/test/chef-repo/data_bags/users/badjson.json +8 -0
- data/test/chef-repo/data_bags/users/failname.json +8 -0
- data/test/chef-repo/data_bags/users/mray.json +8 -0
- data/test/chef-repo/data_bags/users/ubuntu.json +8 -0
- data/test/chef-repo/environments/development.rb +2 -0
- data/test/chef-repo/environments/fail2.rb +8 -0
- data/test/chef-repo/environments/fail3.rb +2 -0
- data/test/chef-repo/environments/production-blue.json +177 -0
- data/test/chef-repo/environments/production-green.json +177 -0
- data/test/chef-repo/environments/production-red.json +177 -0
- data/test/chef-repo/environments/qa.rb +2 -0
- data/test/chef-repo/environments/sub/efg1.rb +2 -0
- data/test/chef-repo/environments/sub/efg2.json +177 -0
- data/test/chef-repo/fail-cookbook1.yml +19 -0
- data/test/chef-repo/fail-cookbook2.yml +21 -0
- data/test/chef-repo/fail-cookbook3.yml +37 -0
- data/test/chef-repo/fail-cookbook4.yml +37 -0
- data/test/chef-repo/fail-cookbook5.yml +10 -0
- data/test/chef-repo/fail-cookbook6.yml +9 -0
- data/test/chef-repo/fail-db1.yml +12 -0
- data/test/chef-repo/fail-db2.yml +10 -0
- data/test/chef-repo/fail-db3.yml +10 -0
- data/test/chef-repo/fail-db4.yml +10 -0
- data/test/chef-repo/fail-env1.yml +27 -0
- data/test/chef-repo/fail-env2.yml +27 -0
- data/test/chef-repo/fail-env3.yml +28 -0
- data/test/chef-repo/fail-env4.yml +28 -0
- data/test/chef-repo/fail-roles1.yml +22 -0
- data/test/chef-repo/fail-roles2.yml +21 -0
- data/test/chef-repo/fail-roles3.yml +23 -0
- data/test/chef-repo/fail-roles4.yml +23 -0
- data/test/chef-repo/fail-roles5.yml +23 -0
- data/test/chef-repo/infrastructure.yml +43 -0
- data/test/chef-repo/nodes/boxy.lab.atx.json +1756 -0
- data/test/chef-repo/nodes/guenter.home.atx.json +2503 -0
- data/test/chef-repo/roles/README +1 -0
- data/test/chef-repo/roles/base.rb +18 -0
- data/test/chef-repo/roles/base2.rb +16 -0
- data/test/chef-repo/roles/base3.rb +17 -0
- data/test/chef-repo/roles/base4.rb +15 -0
- data/test/chef-repo/roles/fail1.rb +8 -0
- data/test/chef-repo/roles/fail2.rb +5 -0
- data/test/chef-repo/roles/fail3.rb +5 -0
- data/test/chef-repo/roles/sub/bw2.json +21 -0
- data/test/chef-repo/roles/sub/bwi1.json +20 -0
- data/test/chef-repo/roles/tc.rb +13 -0
- data/test/examples/cluster-file-example.yml +14 -0
- data/test/examples/example-cluster.yml +8 -0
- data/test/examples/example.json +127 -0
- data/test/examples/example.rb +128 -0
- data/test/examples/example.yml +67 -0
- data/test/examples/google-example.yml +33 -0
- data/test/examples/joyent-vsphere-example.yml +15 -0
- data/test/examples/knife.yml +7 -0
- data/test/examples/kvm-example.yml +22 -0
- data/test/examples/node-example.yml +23 -0
- data/test/examples/php-quick-start.yml +83 -0
- data/test/extract-repo/Berksfile +4 -0
- data/test/extract-repo/Berksfile.lock +10 -0
- data/test/extract-repo/cookbooks/abc/CHANGELOG.md +13 -0
- data/test/extract-repo/cookbooks/abc/README.md +68 -0
- data/test/extract-repo/cookbooks/abc/metadata.rb +7 -0
- data/test/extract-repo/cookbooks/abc/recipes/default.rb +8 -0
- data/test/extract-repo/cookbooks/def/CHANGELOG.md +13 -0
- data/test/extract-repo/cookbooks/def/README.md +68 -0
- data/test/extract-repo/cookbooks/def/metadata.rb +7 -0
- data/test/extract-repo/cookbooks/def/recipes/default.rb +8 -0
- data/test/extract-repo/cookbooks/ghi/CHANGELOG.md +13 -0
- data/test/extract-repo/cookbooks/ghi/README.md +68 -0
- data/test/extract-repo/cookbooks/ghi/metadata.rb +7 -0
- data/test/extract-repo/cookbooks/ghi/recipes/default.rb +8 -0
- data/test/extract-repo/cookbooks/jkl/CHANGELOG.md +13 -0
- data/test/extract-repo/cookbooks/jkl/README.md +68 -0
- data/test/extract-repo/cookbooks/jkl/metadata.rb +10 -0
- data/test/extract-repo/cookbooks/jkl/recipes/default.rb +8 -0
- data/test/extract-repo/cookbooks/mno/CHANGELOG.md +13 -0
- data/test/extract-repo/cookbooks/mno/README.md +68 -0
- data/test/extract-repo/cookbooks/mno/metadata.rb +9 -0
- data/test/extract-repo/cookbooks/mno/recipes/default.rb +8 -0
- data/test/extract-repo/data_bags/junk/README +1 -0
- data/test/extract-repo/data_bags/junk/abc.json +4 -0
- data/test/extract-repo/data_bags/junk/ade.json +4 -0
- data/test/extract-repo/data_bags/junk/afg.json +4 -0
- data/test/extract-repo/data_bags/junk/bcd.json +4 -0
- data/test/extract-repo/data_bags/junk/sub1/cde1.json +4 -0
- data/test/extract-repo/data_bags/junk/sub1/cde2.json +4 -0
- data/test/extract-repo/data_bags/junk/sub2/def1.json +4 -0
- data/test/extract-repo/data_bags/junk/sub2/def2.json +4 -0
- data/test/extract-repo/data_bags/users/README +1 -0
- data/test/extract-repo/data_bags/users/mray.json +8 -0
- data/test/extract-repo/data_bags/users/ubuntu.json +8 -0
- data/test/extract-repo/environments/development.rb +2 -0
- data/test/extract-repo/environments/production-blue.json +177 -0
- data/test/extract-repo/environments/production-green.json +177 -0
- data/test/extract-repo/environments/production-red.json +177 -0
- data/test/extract-repo/environments/qa.rb +2 -0
- data/test/extract-repo/environments/sub/efg1.rb +2 -0
- data/test/extract-repo/environments/sub/efg2.json +177 -0
- data/test/extract-repo/nodes/boxy.lab.atx.json +1756 -0
- data/test/extract-repo/nodes/guenter.home.atx.json +2503 -0
- data/test/extract-repo/roles/README +1 -0
- data/test/extract-repo/roles/base.rb +18 -0
- data/test/extract-repo/roles/base2.rb +16 -0
- data/test/extract-repo/roles/base3.rb +17 -0
- data/test/extract-repo/roles/base4.rb +16 -0
- data/test/extract-repo/roles/sub/bw2.json +21 -0
- data/test/extract-repo/roles/sub/bwi1.json +20 -0
- data/test/extract-repo/roles/tc.rb +13 -0
- data/test/extract-repo2/cookbooks/README.md +1 -0
- data/test/extract-repo2/data_bags/README.md +1 -0
- data/test/extract-repo2/environments/README.md +1 -0
- data/test/extract-repo2/nodes/README.md +1 -0
- data/test/extract-repo2/roles/README.md +1 -0
- metadata +357 -67
- data/spec/bin/chef_client_spec.rb +0 -72
- data/spec/bin/google_spec.rb +0 -105
- data/spec/bin/joyent-vsphere_spec.rb +0 -25
- data/spec/bin/knife_spec.rb +0 -18
- data/spec/bin/kvm_spec.rb +0 -29
- data/spec/bin/node_spec.rb +0 -108
- data/spec/bin/spiceweasel_spec.rb +0 -136
data/lib/spiceweasel/clusters.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
#
|
2
|
-
# Author:: Matt Ray (<matt@
|
3
|
+
# Author:: Matt Ray (<matt@getchef.com>)
|
3
4
|
#
|
4
|
-
# Copyright:: 2012-
|
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 =
|
26
|
-
@delete =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
data/lib/spiceweasel/command.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
data/lib/spiceweasel/config.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
#
|
2
|
-
# Author:: Matt Ray (<matt@
|
3
|
+
# Author:: Matt Ray (<matt@getchef.com>)
|
3
4
|
#
|
4
|
-
# Copyright:: 2012,
|
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@
|
3
|
+
# Author:: Matt Ray (<matt@getchef.com>)
|
3
4
|
#
|
4
|
-
# Copyright:: 2011-
|
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 =
|
30
|
-
@delete =
|
29
|
+
def initialize(cookbooks = [], other_cookbook_list = {}) # rubocop:disable CyclomaticComplexity
|
30
|
+
@create = []
|
31
|
+
@delete = []
|
31
32
|
@cookbook_list = other_cookbook_list
|
32
|
-
@dependencies =
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
75
|
-
|
68
|
+
create_command("knife cookbook#{Spiceweasel::Config[:knife_options]} upload #{name} #{options}")
|
69
|
+
else
|
70
|
+
c_names.push(name)
|
76
71
|
end
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
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("
|
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
|
108
|
-
Spiceweasel::Log.debug("cookbook
|
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
|
-
|
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@
|
3
|
+
# Author:: Matt Ray (<matt@getchef.com>)
|
3
4
|
#
|
4
|
-
# Copyright:: 2011-
|
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 '
|
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 =
|
30
|
-
@delete =
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
83
|
-
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
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
|