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.

Files changed (120) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +135 -0
  3. data/bin/chef-client +26 -0
  4. data/bin/chef-solo +26 -0
  5. data/lib/chef.rb +49 -0
  6. data/lib/chef/application.rb +98 -0
  7. data/lib/chef/application/agent.rb +18 -0
  8. data/lib/chef/application/client.rb +209 -0
  9. data/lib/chef/application/indexer.rb +141 -0
  10. data/lib/chef/application/server.rb +18 -0
  11. data/lib/chef/application/solo.rb +214 -0
  12. data/lib/chef/client.rb +396 -0
  13. data/lib/chef/compile.rb +138 -0
  14. data/lib/chef/config.rb +141 -0
  15. data/lib/chef/cookbook.rb +144 -0
  16. data/lib/chef/cookbook/metadata.rb +407 -0
  17. data/lib/chef/cookbook/metadata/version.rb +87 -0
  18. data/lib/chef/cookbook_loader.rb +168 -0
  19. data/lib/chef/couchdb.rb +172 -0
  20. data/lib/chef/daemon.rb +170 -0
  21. data/lib/chef/exceptions.rb +36 -0
  22. data/lib/chef/file_cache.rb +205 -0
  23. data/lib/chef/log.rb +39 -0
  24. data/lib/chef/mixin/check_helper.rb +31 -0
  25. data/lib/chef/mixin/checksum.rb +37 -0
  26. data/lib/chef/mixin/command.rb +351 -0
  27. data/lib/chef/mixin/create_path.rb +56 -0
  28. data/lib/chef/mixin/deep_merge.rb +36 -0
  29. data/lib/chef/mixin/find_preferred_file.rb +99 -0
  30. data/lib/chef/mixin/from_file.rb +36 -0
  31. data/lib/chef/mixin/generate_url.rb +48 -0
  32. data/lib/chef/mixin/language.rb +79 -0
  33. data/lib/chef/mixin/params_validate.rb +197 -0
  34. data/lib/chef/mixin/template.rb +84 -0
  35. data/lib/chef/node.rb +406 -0
  36. data/lib/chef/node/attribute.rb +412 -0
  37. data/lib/chef/openid_registration.rb +181 -0
  38. data/lib/chef/platform.rb +253 -0
  39. data/lib/chef/provider.rb +40 -0
  40. data/lib/chef/provider/cron.rb +137 -0
  41. data/lib/chef/provider/directory.rb +72 -0
  42. data/lib/chef/provider/execute.rb +58 -0
  43. data/lib/chef/provider/file.rb +191 -0
  44. data/lib/chef/provider/group.rb +120 -0
  45. data/lib/chef/provider/group/groupadd.rb +92 -0
  46. data/lib/chef/provider/group/pw.rb +88 -0
  47. data/lib/chef/provider/http_request.rb +102 -0
  48. data/lib/chef/provider/ifconfig.rb +131 -0
  49. data/lib/chef/provider/link.rb +157 -0
  50. data/lib/chef/provider/mount.rb +121 -0
  51. data/lib/chef/provider/mount/mount.rb +208 -0
  52. data/lib/chef/provider/package.rb +160 -0
  53. data/lib/chef/provider/package/apt.rb +110 -0
  54. data/lib/chef/provider/package/dpkg.rb +113 -0
  55. data/lib/chef/provider/package/freebsd.rb +153 -0
  56. data/lib/chef/provider/package/macports.rb +105 -0
  57. data/lib/chef/provider/package/portage.rb +124 -0
  58. data/lib/chef/provider/package/rpm.rb +99 -0
  59. data/lib/chef/provider/package/rubygems.rb +130 -0
  60. data/lib/chef/provider/package/yum-dump.py +104 -0
  61. data/lib/chef/provider/package/yum.rb +175 -0
  62. data/lib/chef/provider/remote_directory.rb +126 -0
  63. data/lib/chef/provider/remote_file.rb +134 -0
  64. data/lib/chef/provider/route.rb +118 -0
  65. data/lib/chef/provider/ruby_block.rb +15 -0
  66. data/lib/chef/provider/script.rb +42 -0
  67. data/lib/chef/provider/service.rb +129 -0
  68. data/lib/chef/provider/service/debian.rb +64 -0
  69. data/lib/chef/provider/service/freebsd.rb +157 -0
  70. data/lib/chef/provider/service/gentoo.rb +54 -0
  71. data/lib/chef/provider/service/init.rb +126 -0
  72. data/lib/chef/provider/service/redhat.rb +62 -0
  73. data/lib/chef/provider/template.rb +141 -0
  74. data/lib/chef/provider/user.rb +170 -0
  75. data/lib/chef/provider/user/pw.rb +113 -0
  76. data/lib/chef/provider/user/useradd.rb +107 -0
  77. data/lib/chef/queue.rb +145 -0
  78. data/lib/chef/recipe.rb +210 -0
  79. data/lib/chef/resource.rb +256 -0
  80. data/lib/chef/resource/apt_package.rb +34 -0
  81. data/lib/chef/resource/bash.rb +33 -0
  82. data/lib/chef/resource/cron.rb +143 -0
  83. data/lib/chef/resource/csh.rb +33 -0
  84. data/lib/chef/resource/directory.rb +76 -0
  85. data/lib/chef/resource/dpkg_package.rb +34 -0
  86. data/lib/chef/resource/execute.rb +127 -0
  87. data/lib/chef/resource/file.rb +84 -0
  88. data/lib/chef/resource/gem_package.rb +41 -0
  89. data/lib/chef/resource/group.rb +68 -0
  90. data/lib/chef/resource/http_request.rb +52 -0
  91. data/lib/chef/resource/ifconfig.rb +134 -0
  92. data/lib/chef/resource/link.rb +78 -0
  93. data/lib/chef/resource/macports_package.rb +29 -0
  94. data/lib/chef/resource/mount.rb +135 -0
  95. data/lib/chef/resource/package.rb +80 -0
  96. data/lib/chef/resource/perl.rb +33 -0
  97. data/lib/chef/resource/portage_package.rb +33 -0
  98. data/lib/chef/resource/python.rb +33 -0
  99. data/lib/chef/resource/remote_directory.rb +91 -0
  100. data/lib/chef/resource/remote_file.rb +60 -0
  101. data/lib/chef/resource/route.rb +135 -0
  102. data/lib/chef/resource/ruby.rb +33 -0
  103. data/lib/chef/resource/ruby_block.rb +20 -0
  104. data/lib/chef/resource/script.rb +51 -0
  105. data/lib/chef/resource/service.rb +134 -0
  106. data/lib/chef/resource/template.rb +60 -0
  107. data/lib/chef/resource/user.rb +98 -0
  108. data/lib/chef/resource_collection.rb +176 -0
  109. data/lib/chef/resource_definition.rb +67 -0
  110. data/lib/chef/rest.rb +238 -0
  111. data/lib/chef/role.rb +231 -0
  112. data/lib/chef/run_list.rb +156 -0
  113. data/lib/chef/runner.rb +123 -0
  114. data/lib/chef/search.rb +88 -0
  115. data/lib/chef/search/result.rb +64 -0
  116. data/lib/chef/search_index.rb +77 -0
  117. data/lib/chef/tasks/chef_repo.rake +345 -0
  118. data/lib/chef/util/file_edit.rb +125 -0
  119. data/lib/chef/util/fileedit.rb +121 -0
  120. 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
+