chef 0.7.10 → 0.7.12

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 (70) hide show
  1. data/distro/debian/etc/init.d/chef-client +175 -0
  2. data/distro/debian/etc/init.d/chef-indexer +175 -0
  3. data/distro/debian/etc/init.d/chef-server +120 -0
  4. data/distro/debian/man/man1/chef-indexer.1 +42 -0
  5. data/distro/debian/man/man1/chef-server.1 +108 -0
  6. data/distro/debian/man/man8/chef-client.8 +61 -0
  7. data/distro/debian/man/man8/chef-solo.8 +58 -0
  8. data/distro/redhat/etc/chef/client.rb +16 -0
  9. data/distro/redhat/etc/chef/indexer.rb +10 -0
  10. data/distro/redhat/etc/chef/server.rb +22 -0
  11. data/distro/redhat/etc/init.d/chef-client +74 -0
  12. data/distro/redhat/etc/init.d/chef-indexer +76 -0
  13. data/distro/redhat/etc/init.d/chef-server +77 -0
  14. data/lib/chef.rb +1 -1
  15. data/lib/chef/client.rb +33 -8
  16. data/lib/chef/compile.rb +34 -2
  17. data/lib/chef/cookbook.rb +29 -2
  18. data/lib/chef/cookbook_loader.rb +61 -49
  19. data/lib/chef/couchdb.rb +7 -3
  20. data/lib/chef/mixin/command.rb +67 -32
  21. data/lib/chef/mixin/convert_to_class_name.rb +48 -0
  22. data/lib/chef/mixin/find_preferred_file.rb +5 -14
  23. data/lib/chef/mixin/from_file.rb +14 -0
  24. data/lib/chef/mixin/generate_url.rb +2 -1
  25. data/lib/chef/mixin/recipe_definition_dsl_core.rb +77 -0
  26. data/lib/chef/platform.rb +1 -1
  27. data/lib/chef/provider.rb +63 -2
  28. data/lib/chef/provider/cron.rb +75 -25
  29. data/lib/chef/provider/deploy.rb +281 -0
  30. data/lib/chef/provider/deploy/revision.rb +70 -0
  31. data/lib/chef/provider/deploy/timestamped.rb +33 -0
  32. data/lib/chef/provider/git.rb +194 -0
  33. data/lib/chef/provider/group.rb +2 -2
  34. data/lib/chef/provider/group/gpasswd.rb +50 -0
  35. data/lib/chef/provider/group/groupadd.rb +2 -16
  36. data/lib/chef/provider/group/usermod.rb +57 -0
  37. data/lib/chef/provider/ifconfig.rb +3 -3
  38. data/lib/chef/provider/mount.rb +0 -4
  39. data/lib/chef/provider/mount/mount.rb +2 -2
  40. data/lib/chef/provider/package.rb +2 -2
  41. data/lib/chef/provider/package/apt.rb +4 -4
  42. data/lib/chef/provider/package/dpkg.rb +9 -13
  43. data/lib/chef/provider/package/freebsd.rb +6 -6
  44. data/lib/chef/provider/package/macports.rb +4 -4
  45. data/lib/chef/provider/package/portage.rb +3 -3
  46. data/lib/chef/provider/package/rpm.rb +4 -4
  47. data/lib/chef/provider/package/rubygems.rb +10 -4
  48. data/lib/chef/provider/package/yum.rb +6 -6
  49. data/lib/chef/provider/remote_file.rb +14 -7
  50. data/lib/chef/provider/service.rb +8 -2
  51. data/lib/chef/provider/service/freebsd.rb +1 -1
  52. data/lib/chef/provider/service/init.rb +8 -63
  53. data/lib/chef/provider/service/redhat.rb +2 -2
  54. data/lib/chef/provider/service/simple.rb +115 -0
  55. data/lib/chef/provider/subversion.rb +145 -0
  56. data/lib/chef/provider/template.rb +2 -0
  57. data/lib/chef/provider/user.rb +2 -2
  58. data/lib/chef/recipe.rb +9 -75
  59. data/lib/chef/resource.rb +131 -7
  60. data/lib/chef/resource/cron.rb +36 -0
  61. data/lib/chef/resource/deploy.rb +360 -0
  62. data/lib/chef/resource/deploy_revision.rb +35 -0
  63. data/lib/chef/resource/git.rb +36 -0
  64. data/lib/chef/resource/group.rb +2 -0
  65. data/lib/chef/resource/scm.rb +129 -0
  66. data/lib/chef/resource/subversion.rb +33 -0
  67. data/lib/chef/resource/timestamped_deploy.rb +31 -0
  68. data/lib/chef/resource_collection.rb +32 -4
  69. data/lib/chef/runner.rb +35 -28
  70. metadata +40 -11
@@ -153,12 +153,16 @@ class Chef
153
153
  end
154
154
 
155
155
  def view_uri(design, view)
156
- Chef::Config[:couchdb_version] ||= @rest.run_request(:GET, URI.parse(@rest.url + "/"), false, 10, false)["version"].gsub(/-.+/,"").to_f
156
+ Chef::Config[:couchdb_version] ||= @rest.run_request(:GET,
157
+ URI.parse(@rest.url + "/"),
158
+ false,
159
+ 10,
160
+ false)["version"].gsub(/-.+/,"").to_f
157
161
  case Chef::Config[:couchdb_version]
158
- when 0.9, 0.10
159
- "#{Chef::Config[:couchdb_database]}/_design/#{design}/_view/#{view}"
160
162
  when 0.8
161
163
  "#{Chef::Config[:couchdb_database]}/_view/#{design}/#{view}"
164
+ else
165
+ "#{Chef::Config[:couchdb_database]}/_design/#{design}/_view/#{view}"
162
166
  end
163
167
  end
164
168
 
@@ -112,13 +112,22 @@ class Chef
112
112
  end
113
113
  end
114
114
 
115
+ status, stdout, stderr = output_of_command(args[:command], args)
116
+ command_output << "STDOUT: #{stdout}"
117
+ command_output << "STDERR: #{stderr}"
118
+ handle_command_failures(status, command_output, args)
119
+
120
+ status
121
+ end
122
+
123
+ module_function :run_command
124
+
125
+ def output_of_command(command, args)
126
+ Chef::Log.debug("Executing #{command}")
127
+ stderr_string, stdout_string, status = "", "", nil
128
+
115
129
  exec_processing_block = lambda do |pid, stdin, stdout, stderr|
116
- Chef::Log.debug("---- Begin output of #{args[:command]} ----")
117
- Chef::Log.debug("STDOUT: #{stdout.string.chomp}")
118
- Chef::Log.debug("STDERR: #{stderr.string.chomp}")
119
- command_output << "STDOUT: #{stdout.string.chomp}"
120
- command_output << "STDERR: #{stderr.string.chomp}"
121
- Chef::Log.debug("---- End output of #{args[:command]} ----")
130
+ stdout_string, stderr_string = stdout.string.chomp, stderr.string.chomp
122
131
  end
123
132
 
124
133
  args[:cwd] ||= Dir.tmpdir
@@ -126,44 +135,65 @@ class Chef
126
135
  raise Chef::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory"
127
136
  end
128
137
 
129
- Chef::Log.debug("Executing #{args[:command]}")
130
-
131
- status = nil
132
-
133
138
  Dir.chdir(args[:cwd]) do
134
139
  if args[:timeout]
135
140
  begin
136
141
  Timeout.timeout(args[:timeout]) do
137
- status = popen4(args[:command], args, &exec_processing_block)
142
+ status = popen4(command, args, &exec_processing_block)
138
143
  end
139
144
  rescue Timeout::Error => e
140
- Chef::Log.error("#{args[:command]} exceeded timeout #{args[:timeout]}")
145
+ Chef::Log.error("#{command} exceeded timeout #{args[:timeout]}")
141
146
  raise(e)
142
147
  end
143
148
  else
144
- status = popen4(args[:command], args, &exec_processing_block)
149
+ status = popen4(command, args, &exec_processing_block)
145
150
  end
146
151
 
147
- unless args[:ignore_failure]
148
- args[:returns] ||= 0
149
- if status.exitstatus != args[:returns]
150
- # if the log level is not debug, through output of command when we fail
151
- output = ""
152
- if Chef::Log.logger.level > 0
153
- output << "\n---- Begin output of #{args[:command]} ----\n"
154
- output << "#{command_output}"
155
- output << "---- End output of #{args[:command]} ----\n"
156
- end
157
- raise Chef::Exceptions::Exec, "#{args[:command]} returned #{status.exitstatus}, expected #{args[:returns]}#{output}"
152
+ Chef::Log.debug("---- Begin output of #{command} ----")
153
+ Chef::Log.debug("STDOUT: #{stdout_string}")
154
+ Chef::Log.debug("STDERR: #{stderr_string}")
155
+ Chef::Log.debug("---- End output of #{command} ----")
156
+ Chef::Log.debug("Ran #{command} returned #{status.exitstatus}")
157
+ end
158
+
159
+ return status, stdout_string, stderr_string
160
+ end
161
+
162
+ module_function :output_of_command
163
+
164
+ def handle_command_failures(status, command_output, args={})
165
+ unless args[:ignore_failure]
166
+ args[:returns] ||= 0
167
+ if status.exitstatus != args[:returns]
168
+ # if the log level is not debug, through output of command when we fail
169
+ output = ""
170
+ if Chef::Log.logger.level > 0
171
+ output << "\n---- Begin output of #{args[:command]} ----\n"
172
+ output << "#{command_output}"
173
+ output << "---- End output of #{args[:command]} ----\n"
158
174
  end
175
+ raise Chef::Exceptions::Exec, "#{args[:command]} returned #{status.exitstatus}, expected #{args[:returns]}#{output}"
159
176
  end
160
- Chef::Log.debug("Ran #{args[:command]} returned #{status.exitstatus}")
161
177
  end
162
- status
163
178
  end
164
179
 
165
- module_function :run_command
180
+ module_function :handle_command_failures
166
181
 
182
+ # Call #run_command but set LC_ALL to the system's current environment so it doesn't get changed to C.
183
+ #
184
+ # === Parameters
185
+ # args<Hash>: A number of required and optional arguments that will be handed out to #run_command
186
+ #
187
+ # === Returns
188
+ # Returns the result of #run_command
189
+ def run_command_with_systems_locale(args={})
190
+ args[:environment] ||= {}
191
+ args[:environment]["LC_ALL"] = ENV["LC_ALL"]
192
+ run_command args
193
+ end
194
+
195
+ module_function :run_command_with_systems_locale
196
+
167
197
  # This is taken directly from Ara T Howard's Open4 library, and then
168
198
  # modified to suit the needs of Chef. Any bugs here are most likely
169
199
  # my own, and not Ara's.
@@ -189,7 +219,14 @@ class Chef
189
219
  unless args[:group].kind_of?(Integer)
190
220
  args[:group] = Etc.getgrnam(args[:group]).gid if args[:group]
191
221
  end
192
- args[:environment] ||= nil
222
+ args[:environment] ||= {}
223
+
224
+ # Default on C locale so parsing commands output can be done
225
+ # independently of the node's default locale.
226
+ # "LC_ALL" could be set to nil, in which case we also must ignore it.
227
+ unless args[:environment].has_key?("LC_ALL")
228
+ args[:environment]["LC_ALL"] = "C"
229
+ end
193
230
 
194
231
  pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe
195
232
 
@@ -223,10 +260,8 @@ class Chef
223
260
  Process.uid = args[:user]
224
261
  end
225
262
 
226
- if args[:environment]
227
- args[:environment].each do |key,value|
228
- ENV[key] = value
229
- end
263
+ args[:environment].each do |key,value|
264
+ ENV[key] = value
230
265
  end
231
266
 
232
267
  if args[:umask]
@@ -0,0 +1,48 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Christopher Walters (<cw@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008, 2009 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
+ class Chef
21
+ module Mixin
22
+ module ConvertToClassName
23
+
24
+ def convert_to_class_name(str)
25
+ rname = nil
26
+ regexp = %r{^(.+?)(_(.+))?$}
27
+
28
+ mn = str.match(regexp)
29
+ if mn
30
+ rname = mn[1].capitalize
31
+
32
+ while mn && mn[3]
33
+ mn = mn[3].match(regexp)
34
+ rname << mn[1].capitalize if mn
35
+ end
36
+ end
37
+
38
+ rname
39
+ end
40
+
41
+ def filename_to_qualified_string(base, filename)
42
+ file_base = File.basename(filename, ".rb")
43
+ base.to_s + (file_base == 'default' ? '' : "_#{file_base}")
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -72,26 +72,17 @@ class Chef
72
72
  File.join("#{platform}", "#{file_name}"),
73
73
  File.join("default", "#{file_name}")
74
74
  ]
75
- to_send = nil
76
75
 
76
+ file_list_str = file_list.keys.join("\n")
77
77
  preferences.each do |pref|
78
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
79
+ matcher = /^(.+#{pref})$/
80
+ if match = matcher.match(file_list_str)
81
+ return match[1]
86
82
  end
87
- break if to_send
88
83
  end
89
84
 
90
- unless to_send
91
- raise Chef::Exceptions::FileNotFound, "Cannot find a preferred file for #{file_name}!"
92
- end
93
-
94
- to_send
85
+ raise Chef::Exceptions::FileNotFound, "Cannot find a preferred file for #{file_name}!"
95
86
  end
96
87
 
97
88
  end
@@ -1,5 +1,6 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Christopher Walters (<cw@opscode.com>)
3
4
  # Copyright:: Copyright (c) 2008 Opscode, Inc.
4
5
  # License:: Apache License, Version 2.0
5
6
  #
@@ -31,6 +32,19 @@ class Chef
31
32
  raise IOError, "Cannot open or read #{filename}!"
32
33
  end
33
34
  end
35
+
36
+ # Loads a given ruby file, and runs class_eval against it in the context of the current
37
+ # object.
38
+ #
39
+ # Raises an IOError if the file cannot be found, or is not readable.
40
+ def class_from_file(filename)
41
+ if File.exists?(filename) && File.readable?(filename)
42
+ self.class_eval(IO.read(filename), filename, 1)
43
+ else
44
+ raise IOError, "Cannot open or read #{filename}!"
45
+ end
46
+ end
47
+
34
48
  end
35
49
  end
36
50
  end
@@ -23,6 +23,7 @@ class Chef
23
23
  module GenerateURL
24
24
 
25
25
  def generate_cookbook_url(url, cookbook, type, node, args=nil)
26
+ Chef::Log.debug("generating cookbook url for url=#{url}, cookbook=#{cookbook.inspect}, type=#{type}, node=#{node}")
26
27
  new_url = nil
27
28
  if url =~ /^(http|https):\/\//
28
29
  new_url = url
@@ -39,7 +40,7 @@ class Chef
39
40
  end
40
41
  end
41
42
  end
42
-
43
+ Chef::Log.debug("generated cookbook url: #{new_url}")
43
44
  return new_url
44
45
  end
45
46
 
@@ -0,0 +1,77 @@
1
+ #
2
+ # Author:: Adam Jacob (<adam@opscode.com>)
3
+ # Author:: Christopher Walters (<cw@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008, 2009 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/recipe'
21
+ require 'chef/resource'
22
+ require 'chef/mixin/convert_to_class_name'
23
+
24
+ class Chef
25
+ module Mixin
26
+ module RecipeDefinitionDSLCore
27
+
28
+ include Chef::Mixin::ConvertToClassName
29
+
30
+ def method_missing(method_symbol, *args, &block)
31
+ # If we have a definition that matches, we want to use that instead. This should
32
+ # let you do some really crazy over-riding of "native" types, if you really want
33
+ # to.
34
+ if @definitions.has_key?(method_symbol)
35
+ # This dupes the high level object, but we still need to dup the params
36
+ new_def = @definitions[method_symbol].dup
37
+ new_def.params = new_def.params.dup
38
+ new_def.node = @node
39
+ # This sets up the parameter overrides
40
+ new_def.instance_eval(&block) if block
41
+ new_recipe = Chef::Recipe.new(@cookbook_name, @recipe_name, @node, @collection, @definitions, @cookbook_loader)
42
+ new_recipe.params = new_def.params
43
+ new_recipe.params[:name] = args[0]
44
+ new_recipe.instance_eval(&new_def.recipe)
45
+ else
46
+ # Otherwise, we're rocking the regular resource call route.
47
+ method_name = method_symbol.to_s
48
+ rname = convert_to_class_name(method_name)
49
+
50
+ # If we have a resource like this one, we want to steal its state
51
+ resource = begin
52
+ args << @collection
53
+ args << @node
54
+ Chef::Resource.const_get(rname).new(*args)
55
+ rescue NameError => e
56
+ if e.to_s =~ /Chef::Resource/
57
+ raise NameError, "Cannot find #{rname} for #{method_name}\nOriginal exception: #{e.class}: #{e.message}"
58
+ else
59
+ raise e
60
+ end
61
+ end
62
+ resource.load_prior_resource
63
+ resource.cookbook_name = @cookbook_name
64
+ resource.recipe_name = @recipe_name
65
+ resource.params = @params
66
+ # Determine whether this resource is being created in the context of an enclosing Provider
67
+ resource.enclosing_provider = self.is_a?(Chef::Provider) ? self : nil
68
+ resource.instance_eval(&block) if block
69
+
70
+ @collection.insert(resource)
71
+ resource
72
+ end
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -93,7 +93,7 @@ class Chef
93
93
  :bash => Chef::Provider::Script,
94
94
  :csh => Chef::Provider::Script,
95
95
  :user => Chef::Provider::User::Useradd,
96
- :group => Chef::Provider::Group::Groupadd,
96
+ :group => Chef::Provider::Group::Gpasswd,
97
97
  :http_request => Chef::Provider::HttpRequest,
98
98
  :route => Chef::Provider::Route,
99
99
  :ifconfig => Chef::Provider::Ifconfig,
@@ -1,6 +1,7 @@
1
1
  #
2
2
  # Author:: Adam Jacob (<adam@opscode.com>)
3
- # Copyright:: Copyright (c) 2008 Opscode, Inc.
3
+ # Author:: Christopher Walters (<cw@opscode.com>)
4
+ # Copyright:: Copyright (c) 2008, 2009 Opscode, Inc.
4
5
  # License:: Apache License, Version 2.0
5
6
  #
6
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,15 +17,25 @@
16
17
  # limitations under the License.
17
18
  #
18
19
 
20
+ require 'chef/mixin/from_file'
21
+ require 'chef/mixin/convert_to_class_name'
22
+ require 'chef/mixin/recipe_definition_dsl_core'
23
+
19
24
  class Chef
20
25
  class Provider
21
26
 
27
+ include Chef::Mixin::RecipeDefinitionDSLCore
28
+
22
29
  attr_accessor :node, :new_resource, :current_resource
23
30
 
24
- def initialize(node, new_resource)
31
+ def initialize(node, new_resource, collection=nil, definitions={}, cookbook_loader=nil)
25
32
  @node = node
26
33
  @new_resource = new_resource
27
34
  @current_resource = nil
35
+ @collection = collection
36
+ @definitions = definitions
37
+ @cookbook_loader = cookbook_loader
38
+ @cookbook_name = @new_resource.cookbook_name
28
39
  end
29
40
 
30
41
  def load_current_resource
@@ -36,5 +47,55 @@ class Chef
36
47
  true
37
48
  end
38
49
 
50
+ protected
51
+
52
+ def recipe_eval(*args, &block)
53
+ provider_collection, @collection = @collection, Chef::ResourceCollection.new
54
+
55
+ instance_eval(*args, &block)
56
+ Chef::Runner.new(@node, @collection).converge
57
+
58
+ @collection = provider_collection
59
+ end
60
+
61
+ public
62
+
63
+ class << self
64
+ include Chef::Mixin::ConvertToClassName
65
+
66
+ def build_from_file(cookbook_name, filename)
67
+ pname = filename_to_qualified_string(cookbook_name, filename)
68
+
69
+ new_provider_class = Class.new self do |cls|
70
+
71
+ def load_current_resource
72
+ # silence Chef::Exceptions::Override exception
73
+ end
74
+
75
+ class << cls
76
+ include Chef::Mixin::FromFile
77
+
78
+ # setup DSL's shortcut methods
79
+ def action(name, &block)
80
+ define_method("action_#{name.to_s}") do
81
+ instance_eval(&block)
82
+ end
83
+ end
84
+ end
85
+
86
+ # load provider definition from file
87
+ cls.class_from_file(filename)
88
+ end
89
+
90
+ # register new class as a Chef::Provider
91
+ pname = filename_to_qualified_string(cookbook_name, filename)
92
+ class_name = convert_to_class_name(pname)
93
+ Chef::Provider.const_set(class_name, new_provider_class)
94
+ Chef::Log.debug("Loaded contents of #{filename} into a provider named #{pname} defined in Chef::Provider::#{class_name}")
95
+
96
+ new_provider_class
97
+ end
98
+ end
99
+
39
100
  end
40
101
  end