chef 0.7.10
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of chef might be problematic. Click here for more details.
- data/LICENSE +201 -0
- data/README.rdoc +135 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +26 -0
- data/lib/chef.rb +49 -0
- data/lib/chef/application.rb +98 -0
- data/lib/chef/application/agent.rb +18 -0
- data/lib/chef/application/client.rb +209 -0
- data/lib/chef/application/indexer.rb +141 -0
- data/lib/chef/application/server.rb +18 -0
- data/lib/chef/application/solo.rb +214 -0
- data/lib/chef/client.rb +396 -0
- data/lib/chef/compile.rb +138 -0
- data/lib/chef/config.rb +141 -0
- data/lib/chef/cookbook.rb +144 -0
- data/lib/chef/cookbook/metadata.rb +407 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook_loader.rb +168 -0
- data/lib/chef/couchdb.rb +172 -0
- data/lib/chef/daemon.rb +170 -0
- data/lib/chef/exceptions.rb +36 -0
- data/lib/chef/file_cache.rb +205 -0
- data/lib/chef/log.rb +39 -0
- data/lib/chef/mixin/check_helper.rb +31 -0
- data/lib/chef/mixin/checksum.rb +37 -0
- data/lib/chef/mixin/command.rb +351 -0
- data/lib/chef/mixin/create_path.rb +56 -0
- data/lib/chef/mixin/deep_merge.rb +36 -0
- data/lib/chef/mixin/find_preferred_file.rb +99 -0
- data/lib/chef/mixin/from_file.rb +36 -0
- data/lib/chef/mixin/generate_url.rb +48 -0
- data/lib/chef/mixin/language.rb +79 -0
- data/lib/chef/mixin/params_validate.rb +197 -0
- data/lib/chef/mixin/template.rb +84 -0
- data/lib/chef/node.rb +406 -0
- data/lib/chef/node/attribute.rb +412 -0
- data/lib/chef/openid_registration.rb +181 -0
- data/lib/chef/platform.rb +253 -0
- data/lib/chef/provider.rb +40 -0
- data/lib/chef/provider/cron.rb +137 -0
- data/lib/chef/provider/directory.rb +72 -0
- data/lib/chef/provider/execute.rb +58 -0
- data/lib/chef/provider/file.rb +191 -0
- data/lib/chef/provider/group.rb +120 -0
- data/lib/chef/provider/group/groupadd.rb +92 -0
- data/lib/chef/provider/group/pw.rb +88 -0
- data/lib/chef/provider/http_request.rb +102 -0
- data/lib/chef/provider/ifconfig.rb +131 -0
- data/lib/chef/provider/link.rb +157 -0
- data/lib/chef/provider/mount.rb +121 -0
- data/lib/chef/provider/mount/mount.rb +208 -0
- data/lib/chef/provider/package.rb +160 -0
- data/lib/chef/provider/package/apt.rb +110 -0
- data/lib/chef/provider/package/dpkg.rb +113 -0
- data/lib/chef/provider/package/freebsd.rb +153 -0
- data/lib/chef/provider/package/macports.rb +105 -0
- data/lib/chef/provider/package/portage.rb +124 -0
- data/lib/chef/provider/package/rpm.rb +99 -0
- data/lib/chef/provider/package/rubygems.rb +130 -0
- data/lib/chef/provider/package/yum-dump.py +104 -0
- data/lib/chef/provider/package/yum.rb +175 -0
- data/lib/chef/provider/remote_directory.rb +126 -0
- data/lib/chef/provider/remote_file.rb +134 -0
- data/lib/chef/provider/route.rb +118 -0
- data/lib/chef/provider/ruby_block.rb +15 -0
- data/lib/chef/provider/script.rb +42 -0
- data/lib/chef/provider/service.rb +129 -0
- data/lib/chef/provider/service/debian.rb +64 -0
- data/lib/chef/provider/service/freebsd.rb +157 -0
- data/lib/chef/provider/service/gentoo.rb +54 -0
- data/lib/chef/provider/service/init.rb +126 -0
- data/lib/chef/provider/service/redhat.rb +62 -0
- data/lib/chef/provider/template.rb +141 -0
- data/lib/chef/provider/user.rb +170 -0
- data/lib/chef/provider/user/pw.rb +113 -0
- data/lib/chef/provider/user/useradd.rb +107 -0
- data/lib/chef/queue.rb +145 -0
- data/lib/chef/recipe.rb +210 -0
- data/lib/chef/resource.rb +256 -0
- data/lib/chef/resource/apt_package.rb +34 -0
- data/lib/chef/resource/bash.rb +33 -0
- data/lib/chef/resource/cron.rb +143 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/directory.rb +76 -0
- data/lib/chef/resource/dpkg_package.rb +34 -0
- data/lib/chef/resource/execute.rb +127 -0
- data/lib/chef/resource/file.rb +84 -0
- data/lib/chef/resource/gem_package.rb +41 -0
- data/lib/chef/resource/group.rb +68 -0
- data/lib/chef/resource/http_request.rb +52 -0
- data/lib/chef/resource/ifconfig.rb +134 -0
- data/lib/chef/resource/link.rb +78 -0
- data/lib/chef/resource/macports_package.rb +29 -0
- data/lib/chef/resource/mount.rb +135 -0
- data/lib/chef/resource/package.rb +80 -0
- data/lib/chef/resource/perl.rb +33 -0
- data/lib/chef/resource/portage_package.rb +33 -0
- data/lib/chef/resource/python.rb +33 -0
- data/lib/chef/resource/remote_directory.rb +91 -0
- data/lib/chef/resource/remote_file.rb +60 -0
- data/lib/chef/resource/route.rb +135 -0
- data/lib/chef/resource/ruby.rb +33 -0
- data/lib/chef/resource/ruby_block.rb +20 -0
- data/lib/chef/resource/script.rb +51 -0
- data/lib/chef/resource/service.rb +134 -0
- data/lib/chef/resource/template.rb +60 -0
- data/lib/chef/resource/user.rb +98 -0
- data/lib/chef/resource_collection.rb +176 -0
- data/lib/chef/resource_definition.rb +67 -0
- data/lib/chef/rest.rb +238 -0
- data/lib/chef/role.rb +231 -0
- data/lib/chef/run_list.rb +156 -0
- data/lib/chef/runner.rb +123 -0
- data/lib/chef/search.rb +88 -0
- data/lib/chef/search/result.rb +64 -0
- data/lib/chef/search_index.rb +77 -0
- data/lib/chef/tasks/chef_repo.rake +345 -0
- data/lib/chef/util/file_edit.rb +125 -0
- data/lib/chef/util/fileedit.rb +121 -0
- metadata +262 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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
|
+
class Chef
|
19
|
+
module Mixin
|
20
|
+
module CreatePath
|
21
|
+
|
22
|
+
# Creates a given path, including all directories that lead up to it.
|
23
|
+
# Like mkdir_p, but without the leaking.
|
24
|
+
#
|
25
|
+
# === Parameters
|
26
|
+
# file_path<String, Array>:: A string that represents the path to create,
|
27
|
+
# or an Array with the path-parts.
|
28
|
+
#
|
29
|
+
# === Returns
|
30
|
+
# The created file_path.
|
31
|
+
def create_path(file_path)
|
32
|
+
unless file_path.kind_of?(String) || file_path.kind_of?(Array)
|
33
|
+
raise ArgumentError, "file_path must be a string or an array!"
|
34
|
+
end
|
35
|
+
|
36
|
+
if file_path.kind_of?(String)
|
37
|
+
file_path = File.expand_path(file_path).split(File::SEPARATOR)
|
38
|
+
file_path.shift if file_path[0] = ''
|
39
|
+
unless file_path[0].match("^#{File::SEPARATOR}")
|
40
|
+
file_path[0] = "#{File::SEPARATOR}#{file_path[0]}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
file_path.each_index do |i|
|
45
|
+
create_path = File.join(file_path[0, i + 1])
|
46
|
+
unless File.directory?(create_path)
|
47
|
+
Chef::Log.debug("Creating directory #{create_path}")
|
48
|
+
Dir.mkdir(create_path)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
File.expand_path(File.join(file_path))
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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
|
+
class Chef
|
19
|
+
module Mixin
|
20
|
+
class DeepMerge
|
21
|
+
def self.merge(first, second)
|
22
|
+
first = Mash.new(first).to_hash unless second.kind_of?(Mash)
|
23
|
+
first = first.to_hash
|
24
|
+
second = Mash.new(second).to_hash unless second.kind_of?(Mash)
|
25
|
+
second = second.to_hash
|
26
|
+
# Originally From: http://www.ruby-forum.com/topic/142809
|
27
|
+
# Author: Stefan Rusterholz
|
28
|
+
merger = proc do |key,v1,v2|
|
29
|
+
v1.respond_to?(:keys) && v2.respond_to?(:keys) ? v1.merge(v2, &merger) : v2
|
30
|
+
end
|
31
|
+
|
32
|
+
Mash.new(first.merge(second, &merger))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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 'chef/cookbook_loader'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
module Mixin
|
23
|
+
module FindPreferredFile
|
24
|
+
|
25
|
+
def load_cookbook_files(cookbook_id, file_type)
|
26
|
+
unless file_type == :remote_file || file_type == :template
|
27
|
+
raise ArgumentError, "You must supply :remote_file or :template as the file_type"
|
28
|
+
end
|
29
|
+
|
30
|
+
cl = Chef::CookbookLoader.new
|
31
|
+
cookbook = cl[cookbook_id]
|
32
|
+
raise NotFound unless cookbook
|
33
|
+
|
34
|
+
files = Hash.new
|
35
|
+
|
36
|
+
cookbook_method = nil
|
37
|
+
|
38
|
+
case file_type
|
39
|
+
when :remote_file
|
40
|
+
cookbook_method = :remote_files
|
41
|
+
when :template
|
42
|
+
cookbook_method = :template_files
|
43
|
+
end
|
44
|
+
|
45
|
+
cookbook.send(cookbook_method).each do |rf|
|
46
|
+
full = File.expand_path(rf)
|
47
|
+
name = File.basename(full)
|
48
|
+
case file_type
|
49
|
+
when :remote_file
|
50
|
+
rf =~ /^.+#{cookbook_id}[\\|\/]files[\\|\/](.+?)[\\|\/]#{name}/
|
51
|
+
when :template
|
52
|
+
rf =~ /^.+#{cookbook_id}[\\|\/]templates[\\|\/](.+?)[\\|\/]#{name}/
|
53
|
+
end
|
54
|
+
singlecopy = $1
|
55
|
+
files[full] = {
|
56
|
+
:name => name,
|
57
|
+
:singlecopy => singlecopy,
|
58
|
+
:file => full,
|
59
|
+
}
|
60
|
+
end
|
61
|
+
Chef::Log.debug("Preferred #{file_type} list: #{files.inspect}")
|
62
|
+
|
63
|
+
files
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_preferred_file(cookbook_id, file_type, file_name, fqdn, platform, version)
|
67
|
+
file_list = load_cookbook_files(cookbook_id, file_type)
|
68
|
+
|
69
|
+
preferences = [
|
70
|
+
File.join("host-#{fqdn}", "#{file_name}"),
|
71
|
+
File.join("#{platform}-#{version}", "#{file_name}"),
|
72
|
+
File.join("#{platform}", "#{file_name}"),
|
73
|
+
File.join("default", "#{file_name}")
|
74
|
+
]
|
75
|
+
to_send = nil
|
76
|
+
|
77
|
+
preferences.each do |pref|
|
78
|
+
Chef::Log.debug("Looking for #{pref}")
|
79
|
+
file_list.each_key do |file|
|
80
|
+
Chef::Log.debug("Checking for #{pref} #{file} ")
|
81
|
+
if file =~ /#{pref}$/
|
82
|
+
Chef::Log.debug("Matched #{pref} for #{file}!")
|
83
|
+
to_send = file
|
84
|
+
break
|
85
|
+
end
|
86
|
+
end
|
87
|
+
break if to_send
|
88
|
+
end
|
89
|
+
|
90
|
+
unless to_send
|
91
|
+
raise Chef::Exceptions::FileNotFound, "Cannot find a preferred file for #{file_name}!"
|
92
|
+
end
|
93
|
+
|
94
|
+
to_send
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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 Chef
|
20
|
+
module Mixin
|
21
|
+
module FromFile
|
22
|
+
|
23
|
+
# Loads a given ruby file, and runs instance_eval against it in the context of the current
|
24
|
+
# object.
|
25
|
+
#
|
26
|
+
# Raises an IOError if the file cannot be found, or is not readable.
|
27
|
+
def from_file(filename)
|
28
|
+
if File.exists?(filename) && File.readable?(filename)
|
29
|
+
self.instance_eval(IO.read(filename), filename, 1)
|
30
|
+
else
|
31
|
+
raise IOError, "Cannot open or read #{filename}!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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 'chef/platform'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
module Mixin
|
23
|
+
module GenerateURL
|
24
|
+
|
25
|
+
def generate_cookbook_url(url, cookbook, type, node, args=nil)
|
26
|
+
new_url = nil
|
27
|
+
if url =~ /^(http|https):\/\//
|
28
|
+
new_url = url
|
29
|
+
else
|
30
|
+
new_url = "cookbooks/#{cookbook}/#{type}?"
|
31
|
+
new_url += "id=#{url}"
|
32
|
+
platform, version = Chef::Platform.find_platform_and_version(node)
|
33
|
+
if type == "files" || type == "templates"
|
34
|
+
new_url += "&platform=#{platform}&version=#{version}&fqdn=#{node[:fqdn]}&node_name=#{node.name}"
|
35
|
+
end
|
36
|
+
if args
|
37
|
+
args.each do |key, value|
|
38
|
+
new_url += "&#{key}=#{value}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return new_url
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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 Chef
|
20
|
+
module Mixin
|
21
|
+
module Language
|
22
|
+
|
23
|
+
# Given a hash similar to the one we use for Platforms, select a value from the hash. Supports
|
24
|
+
# per platform defaults, along with a single base default. Arrays may be passed as hash keys and
|
25
|
+
# will be expanded.
|
26
|
+
#
|
27
|
+
# === Parameters
|
28
|
+
# platform_hash:: A platform-style hash.
|
29
|
+
#
|
30
|
+
# === Returns
|
31
|
+
# value:: Whatever the most specific value of the hash is.
|
32
|
+
def value_for_platform(platform_hash)
|
33
|
+
result = nil
|
34
|
+
|
35
|
+
platform_hash.each_pair do |key, value|
|
36
|
+
if key.is_a?(Array)
|
37
|
+
key.each { |array_key| platform_hash[array_key] = value }
|
38
|
+
platform_hash.delete(key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
if platform_hash.has_key?(@node[:platform])
|
42
|
+
if platform_hash[@node[:platform]].has_key?(@node[:platform_version])
|
43
|
+
result = platform_hash[@node[:platform]][@node[:platform_version]]
|
44
|
+
elsif platform_hash[@node[:platform]].has_key?("default")
|
45
|
+
result = platform_hash[@node[:platform]]["default"]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
unless result
|
50
|
+
if platform_hash.has_key?("default")
|
51
|
+
result = platform_hash["default"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
# Given a list of platforms, returns true if the current recipe is being run on a node with
|
59
|
+
# that platform, false otherwise.
|
60
|
+
#
|
61
|
+
# === Parameters
|
62
|
+
# args:: A list of platforms
|
63
|
+
#
|
64
|
+
# === Returns
|
65
|
+
# true:: If the current platform is in the list
|
66
|
+
# false:: If the current platform is not in the list
|
67
|
+
def platform?(*args)
|
68
|
+
has_platform = false
|
69
|
+
|
70
|
+
args.flatten.each do |platform|
|
71
|
+
has_platform = true if platform == @node[:platform]
|
72
|
+
end
|
73
|
+
|
74
|
+
has_platform
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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
|
+
class Chef
|
19
|
+
module Mixin
|
20
|
+
module ParamsValidate
|
21
|
+
|
22
|
+
# Takes a hash of options, along with a map to validate them. Returns the original
|
23
|
+
# options hash, plus any changes that might have been made (through things like setting
|
24
|
+
# default values in the validation map)
|
25
|
+
#
|
26
|
+
# For example:
|
27
|
+
#
|
28
|
+
# validate({ :one => "neat" }, { :one => { :kind_of => String }})
|
29
|
+
#
|
30
|
+
# Would raise an exception if the value of :one above is not a kind_of? string. Valid
|
31
|
+
# map options are:
|
32
|
+
#
|
33
|
+
# :default:: Sets the default value for this parameter.
|
34
|
+
# :callbacks:: Takes a hash of Procs, which should return true if the argument is valid.
|
35
|
+
# The key will be inserted into the error message if the Proc does not return true:
|
36
|
+
# "Option #{key}'s value #{value} #{message}!"
|
37
|
+
# :kind_of:: Ensure that the value is a kind_of?(Whatever). If passed an array, it will ensure
|
38
|
+
# that the value is one of those types.
|
39
|
+
# :respond_to:: Ensure that the value has a given method. Takes one method name or an array of
|
40
|
+
# method names.
|
41
|
+
# :required:: Raise an exception if this parameter is missing. Valid values are true or false,
|
42
|
+
# by default, options are not required.
|
43
|
+
# :regex:: Match the value of the paramater against a regular expression.
|
44
|
+
# :equal_to:: Match the value of the paramater with ==. An array means it can be equal to any
|
45
|
+
# of the values.
|
46
|
+
def validate(opts, map)
|
47
|
+
#--
|
48
|
+
# validate works by taking the keys in the validation map, assuming it's a hash, and
|
49
|
+
# looking for _pv_:symbol as methods. Assuming it find them, it calls the right
|
50
|
+
# one.
|
51
|
+
#++
|
52
|
+
raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash)
|
53
|
+
raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash)
|
54
|
+
|
55
|
+
map.each do |key, validation|
|
56
|
+
unless key.kind_of?(Symbol) || key.kind_of?(String)
|
57
|
+
raise ArgumentError, "Validation map keys must be symbols or strings!"
|
58
|
+
end
|
59
|
+
case validation
|
60
|
+
when true
|
61
|
+
_pv_required(opts, key)
|
62
|
+
when false
|
63
|
+
true
|
64
|
+
when Hash
|
65
|
+
validation.each do |check, carg|
|
66
|
+
check_method = "_pv_#{check.to_s}"
|
67
|
+
if self.respond_to?(check_method, true)
|
68
|
+
self.send(check_method, opts, key, carg)
|
69
|
+
else
|
70
|
+
raise ArgumentError, "Validation map has unknown check: #{check}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
opts
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_or_return(symbol, arg, validation)
|
79
|
+
iv_symbol = "@#{symbol.to_s}".to_sym
|
80
|
+
map = {
|
81
|
+
symbol => validation
|
82
|
+
}
|
83
|
+
if arg == nil
|
84
|
+
self.instance_variable_get(iv_symbol)
|
85
|
+
else
|
86
|
+
validate({ symbol => arg }, { symbol => validation })
|
87
|
+
self.instance_variable_set(iv_symbol, arg)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Return the value of a parameter, or nil if it doesn't exist.
|
94
|
+
def _pv_opts_lookup(opts, key)
|
95
|
+
if opts.has_key?(key.to_s)
|
96
|
+
opts[key.to_s]
|
97
|
+
elsif opts.has_key?(key.to_sym)
|
98
|
+
opts[key.to_sym]
|
99
|
+
else
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Raise an exception if the parameter is not found.
|
105
|
+
def _pv_required(opts, key, is_required=true)
|
106
|
+
if is_required
|
107
|
+
if opts.has_key?(key.to_s) || opts.has_key?(key.to_sym)
|
108
|
+
true
|
109
|
+
else
|
110
|
+
raise ArgumentError, "Required argument #{key} is missing!"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def _pv_equal_to(opts, key, to_be)
|
116
|
+
value = _pv_opts_lookup(opts, key)
|
117
|
+
if value != nil
|
118
|
+
passes = false
|
119
|
+
[ to_be ].flatten.each do |tb|
|
120
|
+
if value == tb
|
121
|
+
passes = true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
unless passes
|
125
|
+
raise ArgumentError, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}."
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Raise an exception if the parameter is not a kind_of?(to_be)
|
131
|
+
def _pv_kind_of(opts, key, to_be)
|
132
|
+
value = _pv_opts_lookup(opts, key)
|
133
|
+
if value != nil
|
134
|
+
passes = false
|
135
|
+
[ to_be ].flatten.each do |tb|
|
136
|
+
if value.kind_of?(tb)
|
137
|
+
passes = true
|
138
|
+
end
|
139
|
+
end
|
140
|
+
unless passes
|
141
|
+
raise ArgumentError, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}."
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Raise an exception if the parameter does not respond to a given set of methods.
|
147
|
+
def _pv_respond_to(opts, key, method_name_list)
|
148
|
+
value = _pv_opts_lookup(opts, key)
|
149
|
+
if value != nil
|
150
|
+
[ method_name_list ].flatten.each do |method_name|
|
151
|
+
unless value.respond_to?(method_name)
|
152
|
+
raise ArgumentError, "Option #{key} must have a #{method_name} method!"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Assign a default value to a parameter.
|
159
|
+
def _pv_default(opts, key, default_value)
|
160
|
+
value = _pv_opts_lookup(opts, key)
|
161
|
+
if value == nil
|
162
|
+
opts[key] = default_value
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Check a parameter against a regular expression.
|
167
|
+
def _pv_regex(opts, key, regex)
|
168
|
+
value = _pv_opts_lookup(opts, key)
|
169
|
+
passes = false
|
170
|
+
[ regex ].flatten.each do |r|
|
171
|
+
if value != nil
|
172
|
+
if r.match(value.to_s)
|
173
|
+
passes = true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
unless passes
|
178
|
+
raise ArgumentError, "Option #{key}'s value #{value} does not match regular expression #{regex.to_s}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# Check a parameter against a hash of proc's.
|
183
|
+
def _pv_callbacks(opts, key, callbacks)
|
184
|
+
raise ArgumentError, "Callback list must be a hash!" unless callbacks.kind_of?(Hash)
|
185
|
+
value = _pv_opts_lookup(opts, key)
|
186
|
+
if value != nil
|
187
|
+
callbacks.each do |message, zeproc|
|
188
|
+
if zeproc.call(value) != true
|
189
|
+
raise ArgumentError, "Option #{key}'s value #{value} #{message}!"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|