spiceweasel 1.2.0 → 2.0.0

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.
@@ -1,66 +0,0 @@
1
- #
2
- # Author:: Geoff Meakin
3
- # Author:: Matt Ray (<matt@opscode.com>)
4
- #
5
- # Copyright:: 2012, Opscode, Inc <legal@opscode.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
-
20
- class Spiceweasel::CookbookData
21
-
22
- attr_accessor :_name, :_dependencies, :_version
23
-
24
- def initialize(file_name)
25
- @_name = file_name.split('/').last
26
- @_dependencies = []
27
- @_version = ""
28
- @file_name = file_name
29
- end
30
-
31
- def is_readable?
32
- return false unless File.directory?("cookbooks/#{@_name}")
33
- return false unless File.exists?("cookbooks/#{@_name}/metadata.rb")
34
- true
35
- end
36
-
37
- def read
38
- if File.exists?("cookbooks/#{@_name}/metadata.rb") && File.readable?("cookbooks/#{@_name}/metadata.rb")
39
- self.instance_eval(IO.read("cookbooks/#{@_name}/metadata.rb"), "cookbooks/#{@_name}/metadata.rb", 1)
40
- else
41
- raise IOError, "Cannot open or read cookbooks/#{@_name}/metadata.rb!"
42
- end
43
- {'name' => @_name, 'version' => @_version, 'dependencies' => @_dependencies }
44
- end
45
-
46
- def name(*args) # Override metadata.rb DSL
47
- @_name = args.shift
48
- end
49
-
50
- def version(*args) # Override metadata.rb DSL
51
- @_version = args.shift
52
- end
53
-
54
- def depends(*args) # Override metadata.rb DSL
55
- cookbook = args.shift
56
- if args.length > 0
57
- cookbook_version = args.shift
58
- end
59
- @_dependencies << {'cookbook' => cookbook, 'version' => cookbook_version}
60
- end
61
-
62
- def method_missing(m, *args, &block)
63
- true
64
- end
65
-
66
- end
@@ -1,96 +0,0 @@
1
- #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
- #
4
- # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- class Spiceweasel::CookbookList
20
- def initialize(cookbooks = [], options = {})
21
- @create = @delete = ''
22
- @cookbook_list = {}
23
- @dependencies = []
24
- #validate each of the cookbooks specified in the manifest
25
- if cookbooks
26
- cookbooks.each do |cookbook|
27
- cb = cookbook.keys.first
28
- if cookbook[cb] and cookbook[cb].length > 0
29
- version = cookbook[cb][0].to_s || ""
30
- args = cookbook[cb][1] || ""
31
- end
32
- STDOUT.puts "DEBUG: cookbook: #{cb} #{version}" if Spiceweasel::DEBUG
33
- if File.directory?("cookbooks")
34
- if File.directory?("cookbooks/#{cb}")
35
- validateMetadata(cb,version) unless Spiceweasel::NOVALIDATION
36
- else
37
- if Spiceweasel::SITEINSTALL #use knife cookbook site install
38
- @create += "knife cookbook#{options['knife_options']} site install #{cb} #{version} #{args}\n"
39
- else #use knife cookbook site download, untar and then remove the tarball
40
- @create += "knife cookbook#{options['knife_options']} site download #{cb} #{version} --file cookbooks/#{cb}.tgz #{args}\n"
41
- @create += "tar -C cookbooks/ -xf cookbooks/#{cb}.tgz\n"
42
- @create += "rm -f cookbooks/#{cb}.tgz\n"
43
- end
44
- end
45
- else
46
- STDERR.puts "'cookbooks' directory not found, unable to validate, download and load cookbooks" unless Spiceweasel::NOVALIDATION
47
- end
48
- @create += "knife cookbook#{options['knife_options']} upload #{cb}\n"
49
- @delete += "knife cookbook#{options['knife_options']} delete #{cb} #{version} -a -y\n"
50
-
51
- @cookbook_list[cb] = version
52
- end
53
- validateDependencies() unless Spiceweasel::NOVALIDATION
54
- end
55
- end
56
-
57
- #check the metadata for versions and gather deps
58
- def validateMetadata(cookbook,version)
59
- #check metadata.rb for requested version
60
- metadata = File.open("cookbooks/#{cookbook}/metadata.rb").grep(/^version/)[0].split()[1].gsub(/"/,'').to_s
61
- STDOUT.puts "DEBUG: cookbook metadata version: #{metadata}" if Spiceweasel::DEBUG
62
- if version and (metadata != version)
63
- STDERR.puts "ERROR: Invalid version '#{version}' of '#{cookbook}' requested, '#{metadata}' is already in the cookbooks directory."
64
- exit(-1)
65
- end
66
- deps = File.open("cookbooks/#{cookbook}/metadata.rb").grep(/^depends/)
67
- deps.each do |dependency|
68
- STDOUT.puts "DEBUG: cookbook #{cookbook} metadata dependency: #{dependency}" if Spiceweasel::DEBUG
69
- line = dependency.split()
70
- if line[1] =~ /^["']/ #ignore variables and versions
71
- cbdep = line[1].gsub(/["']/,'')
72
- cbdep.gsub!(/\,/,'') if cbdep.end_with?(',')
73
- STDOUT.puts "DEBUG: cookbook #{cookbook} metadata depends: #{cbdep}" if Spiceweasel::DEBUG
74
- @dependencies << cbdep
75
- end
76
- end
77
- return @cookbook
78
- end
79
-
80
- #compare the list of cookbook deps with those specified
81
- def validateDependencies()
82
- STDOUT.puts "DEBUG: cookbook validateDependencies: '#{@dependencies}'" if Spiceweasel::DEBUG
83
- @dependencies.each do |dep|
84
- if !member?(dep)
85
- STDERR.puts "ERROR: Cookbook dependency '#{dep}' is missing from the list of cookbooks in the manifest."
86
- exit(-1)
87
- end
88
- end
89
- end
90
-
91
- attr_reader :cookbook_list, :create, :delete
92
-
93
- def member?(cookbook)
94
- cookbook_list.keys.include?(cookbook)
95
- end
96
- end
@@ -1,81 +0,0 @@
1
- #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
- #
4
- # Copyright:: 2011, Opscode, Inc <legal@opscode.com>
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'json'
20
-
21
- class Spiceweasel::DataBagList
22
- def initialize(data_bags = [], options = {})
23
- @create = @delete = ''
24
- if data_bags
25
- if !File.directory?("data_bags")
26
- STDERR.puts "ERROR: 'data_bags' directory not found, unable to validate or load data bag items" unless Spiceweasel::NOVALIDATION
27
- end
28
- data_bags.each do |data_bag|
29
- db = data_bag.keys[0]
30
- STDOUT.puts "DEBUG: data bag: #{db}" if Spiceweasel::DEBUG
31
- if !File.directory?("data_bags/#{db}")
32
- STDERR.puts "ERROR: 'data_bags/#{db}' directory not found, unable to validate or load data bag items" unless Spiceweasel::NOVALIDATION
33
- end
34
- @create += "knife data bag#{options['knife_options']} create #{db}\n"
35
- @delete += "knife data bag#{options['knife_options']} delete #{db} -y\n"
36
- items = data_bag[db] || []
37
- secret = nil
38
- while item = items.shift
39
- STDOUT.puts "DEBUG: data bag #{db} item: #{item}" if Spiceweasel::DEBUG
40
- if item.start_with?("secret")
41
- secret = item.split()[1]
42
- if !File.exists?(secret) and !Spiceweasel::NOVALIDATION
43
- STDERR.puts "ERROR: secret key #{secret} not found, unable to load encrypted data bags for data bag #{db}."
44
- exit(-1)
45
- end
46
- next
47
- end
48
- if item =~ /\*/ #wildcard support, will fail if directory not present
49
- files = Dir.glob("data_bags/#{db}/#{item}.json")
50
- items += files.collect {|x| x[x.rindex('/')+1..-6]}
51
- STDOUT.puts "DEBUG: found items '#{items}' for data bag: #{db}" if Spiceweasel::DEBUG
52
- next
53
- end
54
- validateItem(db, item) unless Spiceweasel::NOVALIDATION
55
- if secret
56
- @create += "knife data bag#{options['knife_options']} from file #{db} #{item}.json --secret-file #{secret}\n"
57
- else
58
- @create += "knife data bag#{options['knife_options']} from file #{db} #{item}.json\n"
59
- end
60
- end
61
- end
62
- end
63
- end
64
-
65
- #validate the item to be loaded
66
- def validateItem(db, item)
67
- if !File.exists?("data_bags/#{db}/#{item}.json")
68
- STDERR.puts "ERROR: data bag '#{db}' item '#{item}' file 'data_bags/#{db}/#{item}.json' does not exist"
69
- exit(-1)
70
- end
71
- f = File.read("data_bags/#{db}/#{item}.json")
72
- itemfile = JSON.parse(f) #invalid JSON will throw a trace
73
- #validate the id matches the file name
74
- if !item.eql?(itemfile['id'])
75
- 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."
76
- exit(-1)
77
- end
78
- end
79
-
80
- attr_reader :create, :delete
81
- end
@@ -1,121 +0,0 @@
1
- #
2
- # Author:: Geoff Meakin
3
- # Author:: Matt Ray (<matt@opscode.com>)
4
- #
5
- # Copyright:: 2012, Opscode, Inc <legal@opscode.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
-
20
- class Spiceweasel::DirectoryExtractor
21
-
22
- def self.parse_objects
23
- objects = {"cookbooks" => nil, "roles" => nil, "environments" => nil, "data bags" => nil, "nodes" => nil}
24
- # COOKBOOKS
25
- cookbooks = []
26
- Dir.glob("cookbooks/*").each do |cookbook_full_path|
27
- cookbook = cookbook_full_path.split('/').last
28
- STDOUT.puts "DEBUG: dir_ext: cookbook: '#{cookbook}'" if Spiceweasel::DEBUG
29
- cookbook_data = Spiceweasel::CookbookData.new(cookbook)
30
- if cookbook_data.is_readable?
31
- cookbooks << cookbook_data.read
32
- end
33
- end
34
- STDOUT.puts "DEBUG: dir_ext: cookbooks: '#{cookbooks}'" if Spiceweasel::DEBUG
35
- cookbooks = self.order_cookbooks_by_dependency(cookbooks)
36
- objects["cookbooks"] = cookbooks unless cookbooks.empty?
37
-
38
- # ROLES
39
- roles = []
40
- Dir.glob("roles/*.{rb,json}").each do |role_full_path|
41
- role = self.grab_name_from_path(role_full_path)
42
- STDOUT.puts "DEBUG: dir_ext: role: '#{role}'" if Spiceweasel::DEBUG
43
- roles << {role => nil}
44
- end
45
- objects["roles"] = roles unless roles.nil?
46
- # ENVIRONMENTS
47
- environments = []
48
- Dir.glob("environments/*.{rb,json}").each do |environment_full_path|
49
- environment = self.grab_name_from_path(environment_full_path)
50
- STDOUT.puts "DEBUG: dir_ext: environment: '#{environment}'" if Spiceweasel::DEBUG
51
- environments << {environment => nil}
52
- end
53
- objects["environments"] = environments unless environments.empty?
54
- # DATA BAGS
55
- data_bags = []
56
- Dir.glob("data_bags/*").each do |data_bag_full_path|
57
- data_bag = data_bag_full_path.split('/').last
58
- STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}'" if Spiceweasel::DEBUG
59
- data_bag_items = []
60
- Dir.glob("#{data_bag_full_path}/*.{rb,json}").each do |data_bag_item_full_path|
61
- STDOUT.puts "DEBUG: dir_ext: data_bag: '#{data_bag}':'#{data_bag_item_full_path}'" if Spiceweasel::DEBUG
62
- data_bag_items << self.grab_name_from_path(data_bag_item_full_path)
63
- end if File.directory?(data_bag_full_path)
64
- data_bags << {data_bag => data_bag_items} unless data_bag_items.empty?
65
- end
66
- objects["data bags"] = data_bags unless data_bags.empty?
67
- # NODES
68
- # TODO: Cant use this yet as node_list.rb doesnt support node from file syntax but expects the node info to be part of the objects passed in
69
- # nodes = []
70
- # Dir.glob("nodes/*.{rb,json}").each do |node_full_path|
71
- # node = self.grab_name_from_path(node_full_path)
72
- # nodes << {node => nil}
73
- # end
74
- # objects["nodes"] = nodes unless nodes.empty?
75
-
76
- objects
77
- end
78
-
79
- def self.grab_name_from_path(path)
80
- name = path.split('/').last.split('.')
81
- if name.length>1
82
- name.pop
83
- end
84
- name.join('.')
85
- end
86
-
87
- def self.order_cookbooks_by_dependency(cookbooks)
88
- # Weak algorithm, not particularly elegant, ignores version info as unlikely to have two versions of a cookbook anyway
89
- # We're going to find the cookbooks with their dependencies matched and keep going until all we have is unmatched deps
90
-
91
- sorted_cookbooks = []
92
- unsorted_cookbooks = cookbooks
93
- scount = 0
94
- #keep looping until no more cookbooks are left or can't remove remainders
95
- while unsorted_cookbooks.any? and scount < cookbooks.length
96
- cookbook = unsorted_cookbooks.shift
97
- #if all the cookbook dependencies are in sorted_cookbooks
98
- if sorted_cookbooks.eql?(sorted_cookbooks | cookbook['dependencies'].collect {|x| x['cookbook']})
99
- sorted_cookbooks.push(cookbook['name'])
100
- scount = 0
101
- else #put it back in the list
102
- unsorted_cookbooks.push(cookbook)
103
- scount = scount + 1
104
- end
105
- STDOUT.puts "DEBUG: dir_ext: sorted_cookbooks: '#{sorted_cookbooks}' #{scount}" if Spiceweasel::DEBUG
106
- end
107
- if scount > 0
108
- remainders = unsorted_cookbooks.collect {|x| x['name']}
109
- STDOUT.puts "DEBUG: dir_ext: remainders: '#{remainders}'" if Spiceweasel::DEBUG
110
- if Spiceweasel::NOVALIDATION #stuff is missing, oh well
111
- sorted_cookbooks.push(remainders).flatten!
112
- else
113
- deps = unsorted_cookbooks.collect {|x| x['dependencies'].collect {|x| x['cookbook']} - sorted_cookbooks}
114
- STDERR.puts "ERROR: Dependencies not satisfied or circular dependencies in cookbook(s): #{remainders} depend(s) on #{deps}"
115
- exit(-1)
116
- end
117
- end
118
- #hack to get the format same as yaml/json parse
119
- return sorted_cookbooks.collect {|x| {x => nil} }
120
- end
121
- end
@@ -1,96 +0,0 @@
1
- #
2
- # Author:: Matt Ray (<matt@opscode.com>)
3
- #
4
- # Copyright:: 2011-2012, Opscode, Inc <legal@opscode.com>
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
-
19
- require 'json'
20
-
21
- class Spiceweasel::EnvironmentList
22
- def initialize(environments = [], cookbooks = {}, options = {})
23
- @create = @delete = ''
24
- @environment_list = []
25
- if environments
26
- environments.each do |env|
27
- environment = env.keys[0]
28
- STDOUT.puts "DEBUG: environment: #{environment}" if Spiceweasel::DEBUG
29
- if File.directory?("environments")
30
- validate(environment, cookbooks) unless Spiceweasel::NOVALIDATION
31
- else
32
- STDERR.puts "'environments' directory not found, unable to validate or load environments" unless Spiceweasel::NOVALIDATION
33
- end
34
- if File.exists?("environments/#{environment}.json")
35
- @create += "knife environment#{options['knife_options']} from file #{environment}.json\n"
36
- else #assume no .json means they want .rb and catchall for misssing dir
37
- @create += "knife environment#{options['knife_options']} from file #{environment}.rb\n"
38
- end
39
- @delete += "knife environment#{options['knife_options']} delete #{environment} -y\n"
40
- @environment_list << environment
41
- end
42
- end
43
- end
44
-
45
- #validate the content of the environment file
46
- def validate(environment, cookbooks)
47
- #validate the environments passed in match the name of either the .rb or .json
48
- if File.exists?("environments/#{environment}.rb")
49
- #validate that the name inside the file matches
50
- name = File.open("environments/#{environment}.rb").grep(/^name/)[0].split()[1].gsub(/"/,'').to_s
51
- if !environment.eql?(name)
52
- STDERR.puts "ERROR: Environment '#{environment}' listed in the manifest does not match the name '#{name}' within the environments/#{environment}.rb file."
53
- exit(-1)
54
- end
55
- #validate the cookbooks exist if they're mentioned
56
- envcookbooks = File.open("environments/#{environment}.rb").grep(/^cookbook /)
57
- envcookbooks.each do |cb|
58
- dep = cb.split()[1].gsub(/"/,'').gsub(/,/,'')
59
- STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{dep}'" if Spiceweasel::DEBUG
60
- if !cookbooks.member?(dep)
61
- STDERR.puts "ERROR: Cookbook dependency '#{dep}' from environment '#{environment}' is missing from the list of cookbooks in the manifest."
62
- exit(-1)
63
- end
64
- end
65
- elsif File.exists?("environments/#{environment}.json")
66
- #load the json, don't symbolize since we don't need json_class
67
- f = File.read("environments/#{environment}.json")
68
- JSON.create_id = nil
69
- envfile = JSON.parse(f, {:symbolize_names => false})
70
- STDOUT.puts "DEBUG: environment: '#{environment}' file: '#{envfile}'" if Spiceweasel::DEBUG
71
- #validate that the name inside the file matches
72
- STDOUT.puts "DEBUG: environment: '#{environment}' name: '#{envfile['name']}'" if Spiceweasel::DEBUG
73
- if !environment.eql?(envfile['name'])
74
- STDERR.puts "ERROR: Environment '#{environment}' listed in the manifest does not match the name '#{envfile['name']}' within the 'environments/#{environment}.json' file."
75
- exit(-1)
76
- end
77
- #validate the cookbooks exist if they're mentioned
78
- envfile['cookbook_versions'].keys.each do |cb|
79
- STDOUT.puts "DEBUG: environment: '#{environment}' cookbook: '#{cb}'" if Spiceweasel::DEBUG
80
- if !cookbooks.member?(cb.to_s)
81
- STDERR.puts "ERROR: Cookbook dependency '#{cb}' from environment '#{environment}' is missing from the list of cookbooks in the manifest."
82
- exit(-1)
83
- end
84
- end
85
- else #environment is not here
86
- STDERR.puts "ERROR: Invalid Environment '#{environment}' listed in the manifest but not found in the environments directory."
87
- exit(-1)
88
- end
89
- end
90
-
91
- attr_reader :environment_list, :create, :delete
92
-
93
- def member?(environment)
94
- environment_list.include?(environment)
95
- end
96
- end