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,141 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Christopher Brown (<cb@opscode.com>)
4
+ # Author:: AJ Christensen (<aj@opscode.com>)
5
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ require 'mixlib/config'
21
+
22
+ class Chef
23
+ class Config
24
+
25
+ extend Mixlib::Config
26
+
27
+ # Manages the chef secret session key
28
+ # === Returns
29
+ # <newkey>:: A new or retrieved session key
30
+ #
31
+ def self.manage_secret_key
32
+ newkey = nil
33
+ if Chef::FileCache.has_key?("chef_server_cookie_id")
34
+ newkey = Chef::FileCache.load("chef_server_cookie_id")
35
+ else
36
+ chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
37
+ newkey = ""
38
+ 40.times { |i| newkey << chars[rand(chars.size-1)] }
39
+ Chef::FileCache.store("chef_server_cookie_id", newkey)
40
+ end
41
+ newkey
42
+ end
43
+
44
+
45
+ # Override the config dispatch to set the value of multiple server options simultaneously
46
+ #
47
+ # === Parameters
48
+ # url<String>:: String to be set for all of the chef-server-api URL's
49
+ #
50
+ config_attr_writer :chef_server_url do |url|
51
+ configure do |c|
52
+ [ :registration_url,
53
+ :openid_url,
54
+ :template_url,
55
+ :remotefile_url,
56
+ :search_url,
57
+ :role_url ].each do |u|
58
+ c[u] = url
59
+ end
60
+ end
61
+ url
62
+ end
63
+
64
+ # Override the config dispatch to set the value of log_location configuration option
65
+ #
66
+ # === Parameters
67
+ # location<IO||String>:: Logging location as either an IO stream or string representing log file path
68
+ #
69
+ config_attr_writer :log_location do |location|
70
+ if location.respond_to? :sync=
71
+ location
72
+ elsif location.respond_to? :to_str
73
+ File.new(location.to_str, "a")
74
+ end
75
+ end
76
+
77
+ # Override the config dispatch to set the value of authorized_openid_providers when openid_providers (deprecated) is used
78
+ #
79
+ # === Parameters
80
+ # providers<Array>:: An array of openid providers that are authorized to login to the chef server
81
+ #
82
+ config_attr_writer :openid_providers do |providers|
83
+ configure { |c| c[:authorized_openid_providers] = providers }
84
+ providers
85
+ end
86
+
87
+ authorized_openid_identifiers nil
88
+ authorized_openid_providers nil
89
+ chef_server_url nil
90
+ cookbook_path [ "/var/chef/site-cookbooks", "/var/chef/cookbooks" ]
91
+ couchdb_database "chef"
92
+ couchdb_url "http://localhost:5984"
93
+ couchdb_version nil
94
+ daemonize nil
95
+ delay 0
96
+ executable_path ENV['PATH'] ? ENV['PATH'].split(File::PATH_SEPARATOR) : []
97
+ file_cache_path "/var/chef/cache"
98
+ file_store_path "/var/chef/store"
99
+ group nil
100
+ http_retry_count 5
101
+ http_retry_delay 5
102
+ interval nil
103
+ json_attribs nil
104
+ log_level :info
105
+ log_location STDOUT
106
+ node_name nil
107
+ node_path "/var/chef/node"
108
+ openid_cstore_couchdb false
109
+ openid_cstore_path "/var/chef/openid/cstore"
110
+ openid_providers nil
111
+ openid_store_couchdb false
112
+ openid_store_path "/var/chef/openid/db"
113
+ openid_url "http://localhost:4001"
114
+ pid_file nil
115
+ queue_host "localhost"
116
+ queue_password ""
117
+ queue_port 61613
118
+ queue_retry_count 5
119
+ queue_retry_delay 5
120
+ queue_user ""
121
+ queue_prefix nil
122
+ registration_url "http://localhost:4000"
123
+ remotefile_url "http://localhost:4000"
124
+ rest_timeout 60
125
+ run_command_stderr_timeout 120
126
+ run_command_stdout_timeout 120
127
+ search_index_path "/var/chef/search_index"
128
+ search_url "http://localhost:4000"
129
+ solo false
130
+ splay nil
131
+ ssl_client_cert ""
132
+ ssl_client_key ""
133
+ ssl_verify_mode :verify_none
134
+ template_url "http://localhost:4000"
135
+ user nil
136
+ validation_token nil
137
+ role_path "/var/chef/roles"
138
+ role_url "http://localhost:4000"
139
+ recipe_url nil
140
+ end
141
+ end
@@ -0,0 +1,144 @@
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
+ require 'chef/log'
19
+ require 'chef/node'
20
+ require 'chef/resource_definition'
21
+ require 'chef/recipe'
22
+
23
+ class Chef
24
+ class Cookbook
25
+
26
+ attr_accessor :attribute_files, :definition_files, :template_files, :remote_files,
27
+ :lib_files, :name
28
+ attr_reader :recipe_files
29
+
30
+ # Creates a new Chef::Cookbook object.
31
+ #
32
+ # === Returns
33
+ # object<Chef::Cookbook>:: Duh. :)
34
+ def initialize(name)
35
+ @name = name
36
+ @attribute_files = Array.new
37
+ @definition_files = Array.new
38
+ @template_files = Array.new
39
+ @remote_files = Array.new
40
+ @recipe_files = Array.new
41
+ @recipe_names = Hash.new
42
+ @lib_files = Array.new
43
+ end
44
+
45
+ # Loads all the library files in this cookbook via require.
46
+ #
47
+ # === Returns
48
+ # true:: Always returns true
49
+ def load_libraries
50
+ @lib_files.each do |file|
51
+ Chef::Log.debug("Loading cookbook #{name} library file: #{file}")
52
+ require file
53
+ end
54
+ true
55
+ end
56
+
57
+ # Loads all the attribute files in this cookbook within a particular <Chef::Node>.
58
+ #
59
+ # === Parameters
60
+ # node<Chef::Node>:: The Chef::Node to apply the attributes to
61
+ #
62
+ # === Returns
63
+ # node<Chef::Node>:: The updated Chef::Node object
64
+ #
65
+ # === Raises
66
+ # <ArgumentError>:: If the argument is not a kind_of? <Chef::Node>
67
+ def load_attributes(node)
68
+ unless node.kind_of?(Chef::Node)
69
+ raise ArgumentError, "You must pass a Chef::Node to load_attributes!"
70
+ end
71
+ @attribute_files.each do |file|
72
+ Chef::Log.debug("Loading attributes from #{file}")
73
+ node.from_file(file)
74
+ end
75
+ node
76
+ end
77
+
78
+ # Loads all the resource definitions in this cookbook.
79
+ #
80
+ # === Returns
81
+ # definitions<Hash>: A hash of <Chef::ResourceDefinition> objects, keyed by name.
82
+ def load_definitions
83
+ results = Hash.new
84
+ @definition_files.each do |file|
85
+ Chef::Log.debug("Loading cookbook #{name}'s definitions from #{file}")
86
+ resourcedef = Chef::ResourceDefinition.new
87
+ resourcedef.from_file(file)
88
+ results[resourcedef.name] = resourcedef
89
+ end
90
+ results
91
+ end
92
+
93
+ def recipe_files=(*args)
94
+ @recipe_files = args.flatten
95
+ @recipe_files.each_index do |i|
96
+ file = @recipe_files[i]
97
+ case file
98
+ when /(.+\/)(.+).rb$/
99
+ @recipe_names[$2] = i
100
+ when /(.+).rb$/
101
+ @recipe_names[$1] = i
102
+ else
103
+ @recipe_names[file] = i
104
+ end
105
+ end
106
+ @recipe_files
107
+ end
108
+
109
+ def recipe?(name)
110
+ lookup_name = name
111
+ if name =~ /(.+)::(.+)/
112
+ cookbook_name = $1
113
+ lookup_name = $2
114
+ return false unless cookbook_name == @name
115
+ end
116
+ @recipe_names.has_key?(lookup_name)
117
+ end
118
+
119
+ def recipes
120
+ results = Array.new
121
+ @recipe_names.each_key do |rname|
122
+ results << "#{@name}::#{rname}"
123
+ end
124
+ results
125
+ end
126
+
127
+ def load_recipe(name, node, collection=nil, definitions=nil, cookbook_loader=nil)
128
+ cookbook_name = @name
129
+ recipe_name = nil
130
+ nmatch = name.match(/^(.+?)::(.+)$/)
131
+ recipe_name = nmatch ? nmatch[2] : name
132
+
133
+ unless @recipe_names.has_key?(recipe_name)
134
+ raise ArgumentError, "Cannot find a recipe matching #{recipe_name} in cookbook #{@name}"
135
+ end
136
+ Chef::Log.debug("Found recipe #{recipe_name} in cookbook #{cookbook_name}") if Chef::Log.debug?
137
+ recipe = Chef::Recipe.new(cookbook_name, recipe_name, node,
138
+ collection, definitions, cookbook_loader)
139
+ recipe.from_file(@recipe_files[@recipe_names[recipe_name]])
140
+ recipe
141
+ end
142
+
143
+ end
144
+ end
@@ -0,0 +1,407 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: AJ Christensen (<aj@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008 Opscode, Inc.
5
+ # License:: Apache License, Version 2.0
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
+ require 'chef/mixin/from_file'
21
+ require 'chef/mixin/params_validate'
22
+ require 'chef/mixin/check_helper'
23
+ require 'chef/log'
24
+ require 'chef/cookbook/metadata/version'
25
+
26
+ class Chef
27
+ class Cookbook
28
+ class Metadata
29
+
30
+ include Chef::Mixin::CheckHelper
31
+ include Chef::Mixin::ParamsValidate
32
+ include Chef::Mixin::FromFile
33
+
34
+ attr_accessor :cookbook,
35
+ :platforms,
36
+ :dependencies,
37
+ :recommendations,
38
+ :suggestions,
39
+ :conflicting,
40
+ :providing,
41
+ :replacing,
42
+ :attributes,
43
+ :recipes,
44
+ :version
45
+
46
+ # Builds a new Chef::Cookbook::Metadata object.
47
+ #
48
+ # === Parameters
49
+ # cookbook<String>:: An optional cookbook object
50
+ # maintainer<String>:: An optional maintainer
51
+ # maintainer_email<String>:: An optional maintainer email
52
+ # license<String>::An optional license. Default is Apache v2.0
53
+ #
54
+ # === Returns
55
+ # metadata<Chef::Cookbook::Metadata>
56
+ def initialize(cookbook=nil, maintainer='Your Name', maintainer_email='youremail@example.com', license='Apache v2.0')
57
+ @cookbook = cookbook
58
+ @name = cookbook ? cookbook.name : ""
59
+ @long_description = ""
60
+ self.maintainer(maintainer)
61
+ self.maintainer_email(maintainer_email)
62
+ self.license(license)
63
+ self.description('A fabulous new cookbook')
64
+ @platforms = Mash.new
65
+ @dependencies = Mash.new
66
+ @recommendations = Mash.new
67
+ @suggestions = Mash.new
68
+ @conflicting = Mash.new
69
+ @providing = Mash.new
70
+ @replacing = Mash.new
71
+ @attributes = Mash.new
72
+ @recipes = Mash.new
73
+ @version = Version.new "0.0.0"
74
+ if cookbook
75
+ @recipes = cookbook.recipes.inject({}) do |r, e|
76
+ e = self.name if e =~ /::default$/
77
+ r[e] = ""
78
+ self.provides e
79
+ r
80
+ end
81
+ end
82
+ end
83
+
84
+ # Sets the cookbooks maintainer, or returns it.
85
+ #
86
+ # === Parameters
87
+ # maintainer<String>:: The maintainers name
88
+ #
89
+ # === Returns
90
+ # maintainer<String>:: Returns the current maintainer.
91
+ def maintainer(arg=nil)
92
+ set_or_return(
93
+ :maintainer,
94
+ arg,
95
+ :kind_of => [ String ]
96
+ )
97
+ end
98
+
99
+ # Sets the maintainers email address, or returns it.
100
+ #
101
+ # === Parameters
102
+ # maintainer_email<String>:: The maintainers email address
103
+ #
104
+ # === Returns
105
+ # maintainer_email<String>:: Returns the current maintainer email.
106
+ def maintainer_email(arg=nil)
107
+ set_or_return(
108
+ :maintainer_email,
109
+ arg,
110
+ :kind_of => [ String ]
111
+ )
112
+ end
113
+
114
+ # Sets the current license, or returns it.
115
+ #
116
+ # === Parameters
117
+ # license<String>:: The current license.
118
+ #
119
+ # === Returns
120
+ # license<String>:: Returns the current license
121
+ def license(arg=nil)
122
+ set_or_return(
123
+ :license,
124
+ arg,
125
+ :kind_of => [ String ]
126
+ )
127
+ end
128
+
129
+ # Sets the current description, or returns it. Should be short - one line only!
130
+ #
131
+ # === Parameters
132
+ # description<String>:: The new description
133
+ #
134
+ # === Returns
135
+ # description<String>:: Returns the description
136
+ def description(arg=nil)
137
+ set_or_return(
138
+ :description,
139
+ arg,
140
+ :kind_of => [ String ]
141
+ )
142
+ end
143
+
144
+ # Sets the current long description, or returns it. Might come from a README, say.
145
+ #
146
+ # === Parameters
147
+ # long_description<String>:: The new long description
148
+ #
149
+ # === Returns
150
+ # long_description<String>:: Returns the long description
151
+ def long_description(arg=nil)
152
+ set_or_return(
153
+ :long_description,
154
+ arg,
155
+ :kind_of => [ String ]
156
+ )
157
+ end
158
+
159
+ # Sets the current cookbook version, or returns it. Can be two or three digits, seperated
160
+ # by dots. ie: '2.1', '1.5.4' or '0.9'.
161
+ #
162
+ # === Parameters
163
+ # version<String>:: The curent version, as a string
164
+ #
165
+ # === Returns
166
+ # version<String>:: Returns the current version
167
+ def version(arg=nil)
168
+ if arg
169
+ @version = Version.new(arg)
170
+ end
171
+
172
+ @version.to_s
173
+ end
174
+
175
+ # Sets the name of the cookbook, or returns it.
176
+ #
177
+ # === Parameters
178
+ # name<String>:: The curent cookbook name.
179
+ #
180
+ # === Returns
181
+ # name<String>:: Returns the current cookbook name.
182
+ def name(arg=nil)
183
+ set_or_return(
184
+ :name,
185
+ arg,
186
+ :kind_of => [ String ]
187
+ )
188
+ end
189
+
190
+ # Adds a supported platform, with version checking strings.
191
+ #
192
+ # === Parameters
193
+ # platform<String>,<Symbol>:: The platform (like :ubuntu or :mac_os_x)
194
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
195
+ #
196
+ # === Returns
197
+ # versions<Array>:: Returns the list of versions for the platform
198
+ def supports(platform, *versions)
199
+ versions.each { |v| _check_version_expression(v) }
200
+ @platforms[platform] = versions
201
+ @platforms[platform]
202
+ end
203
+
204
+ # Adds a dependency on another cookbook, with version checking strings.
205
+ #
206
+ # === Parameters
207
+ # cookbook<String>:: The cookbook
208
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
209
+ #
210
+ # === Returns
211
+ # versions<Array>:: Returns the list of versions for the platform
212
+ def depends(cookbook, *versions)
213
+ versions.each { |v| _check_version_expression(v) }
214
+ @dependencies[cookbook] = versions
215
+ @dependencies[cookbook]
216
+ end
217
+
218
+ # Adds a recommendation for another cookbook, with version checking strings.
219
+ #
220
+ # === Parameters
221
+ # cookbook<String>:: The cookbook
222
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
223
+ #
224
+ # === Returns
225
+ # versions<Array>:: Returns the list of versions for the platform
226
+ def recommends(cookbook, *versions)
227
+ versions.each { |v| _check_version_expression(v) }
228
+ @recommendations[cookbook] = versions
229
+ @recommendations[cookbook]
230
+ end
231
+
232
+ # Adds a suggestion for another cookbook, with version checking strings.
233
+ #
234
+ # === Parameters
235
+ # cookbook<String>:: The cookbook
236
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
237
+ #
238
+ # === Returns
239
+ # versions<Array>:: Returns the list of versions for the platform
240
+ def suggests(cookbook, *versions)
241
+ versions.each { |v| _check_version_expression(v) }
242
+ @suggestions[cookbook] = versions
243
+ @suggestions[cookbook]
244
+ end
245
+
246
+ # Adds a conflict for another cookbook, with version checking strings.
247
+ #
248
+ # === Parameters
249
+ # cookbook<String>:: The cookbook
250
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
251
+ #
252
+ # === Returns
253
+ # versions<Array>:: Returns the list of versions for the platform
254
+ def conflicts(cookbook, *versions)
255
+ versions.each { |v| _check_version_expression(v) }
256
+ @conflicting[cookbook] = versions
257
+ @conflicting[cookbook]
258
+ end
259
+
260
+ # Adds a recipe, definition, or resource provided by this cookbook.
261
+ #
262
+ # Recipes are specified as normal
263
+ # Definitions are followed by (), and can include :params for prototyping
264
+ # Resources are the stringified version (service[apache2])
265
+ #
266
+ # === Parameters
267
+ # recipe, definition, resource<String>:: The thing we provide
268
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
269
+ #
270
+ # === Returns
271
+ # versions<Array>:: Returns the list of versions for the platform
272
+ def provides(cookbook, *versions)
273
+ versions.each { |v| _check_version_expression(v) }
274
+ @providing[cookbook] = versions
275
+ @providing[cookbook]
276
+ end
277
+
278
+ # Adds a cookbook that is replaced by this one, with version checking strings.
279
+ #
280
+ # === Parameters
281
+ # cookbook<String>:: The cookbook we replace
282
+ # *versions<String>:: A list of versions matching << <= = >= >> followed by a version.
283
+ #
284
+ # === Returns
285
+ # versions<Array>:: Returns the list of versions for the platform
286
+ def replaces(cookbook, *versions)
287
+ versions.each { |v| _check_version_expression(v) }
288
+ @replacing[cookbook] = versions
289
+ @replacing[cookbook]
290
+ end
291
+
292
+ # Adds a description for a recipe.
293
+ #
294
+ # === Parameters
295
+ # recipe<String>:: The recipe
296
+ # description<String>:: The description of the recipe
297
+ #
298
+ # === Returns
299
+ # description<String>:: Returns the current description
300
+ def recipe(name, description)
301
+ @recipes[name] = description
302
+ end
303
+
304
+ # Adds an attribute that a user needs to configure for this cookbook. Takes
305
+ # a name (with the / notation for a nested attribute), followed by any of
306
+ # these options
307
+ #
308
+ # display_name<String>:: What a UI should show for this attribute
309
+ # description<String>:: A hint as to what this attr is for
310
+ # multiple_values<True>,<False>:: Whether it supports multiple values
311
+ # type<String>:: "string", "hash" or "array" - default is "string"
312
+ # required<True>,<False>:: Whether this attr is required - default false
313
+ # recipes<Array>:: An array of recipes which need this attr set.
314
+ # default<String>,<Array>,<Hash>:: The default value
315
+ #
316
+ # === Parameters
317
+ # name<String>:: The name of the attribute ('foo', or 'apache2/log_dir')
318
+ # options<Hash>:: The description of the options
319
+ #
320
+ # === Returns
321
+ # options<Hash>:: Returns the current options hash
322
+ def attribute(name, options)
323
+ validate(
324
+ options,
325
+ {
326
+ :display_name => { :kind_of => String },
327
+ :description => { :kind_of => String },
328
+ :multiple_values => { :equal_to => [ true, false ], :default => false },
329
+ :type => { :equal_to => [ "string", "array", "hash" ], :default => "string" },
330
+ :required => { :equal_to => [ true, false ], :default => false },
331
+ :recipes => { :kind_of => [ Array ], :default => [] },
332
+ :default => { :kind_of => [ String, Array, Hash ] }
333
+ }
334
+ )
335
+ @attributes[name] = options
336
+ @attributes[name]
337
+ end
338
+
339
+ def _check_version_expression(version_string)
340
+ if version_string =~ /^(>>|>=|=|<=|<<) (.+)$/
341
+ [ $1, $2 ]
342
+ else
343
+ raise ArgumentError, "Version expression #{version_string} is invalid!"
344
+ end
345
+ end
346
+
347
+ def to_json(*a)
348
+ result = {
349
+ :name => self.name,
350
+ :description => self.description,
351
+ :long_description => self.long_description,
352
+ :maintainer => self.maintainer,
353
+ :maintainer_email => self.maintainer_email,
354
+ :license => self.license,
355
+ :platforms => self.platforms,
356
+ :dependencies => self.dependencies,
357
+ :recommendations => self.recommendations,
358
+ :suggestions => self.suggestions,
359
+ :conflicting => self.conflicting,
360
+ :providing => self.providing,
361
+ :replacing => self.replacing,
362
+ :attributes => self.attributes,
363
+ :recipes => self.recipes,
364
+ :version => self.version
365
+ }
366
+ result.to_json(*a)
367
+ end
368
+
369
+ def self.from_hash(o)
370
+ cm = self.new()
371
+ cm.from_hash(o)
372
+ cm
373
+ end
374
+
375
+ def from_hash(o)
376
+ self.name o['name'] if o.has_key?('name')
377
+ self.description o['description'] if o.has_key?('description')
378
+ self.long_description o['long_description'] if o.has_key?('long_description')
379
+ self.maintainer o['maintainer'] if o.has_key?('maintainer')
380
+ self.maintainer_email o['maintainer_email'] if o.has_key?('maintainer_email')
381
+ self.license o['license'] if o.has_key?('license')
382
+ self.platforms = o['platforms'] if o.has_key?('platforms')
383
+ self.dependencies = o['dependencies'] if o.has_key?('dependencies')
384
+ self.recommendations = o['recommendations'] if o.has_key?('recommendations')
385
+ self.suggestions = o['suggestions'] if o.has_key?('suggestions')
386
+ self.conflicting = o['conflicting'] if o.has_key?('conflicting')
387
+ self.providing = o['providing'] if o.has_key?('providing')
388
+ self.replacing = o['replacing'] if o.has_key?('replacing')
389
+ self.attributes = o['attributes'] if o.has_key?('attributes')
390
+ self.recipes = o['recipes'] if o.has_key?('recipes')
391
+ self.version = o['version'] if o.has_key?('version')
392
+ self
393
+ end
394
+
395
+ def self.from_json(string)
396
+ o = JSON.parse(string)
397
+ self.from_hash(o)
398
+ end
399
+
400
+ def from_json(string)
401
+ o = JSON.parse(string)
402
+ from_hash(o)
403
+ end
404
+
405
+ end
406
+ end
407
+ end