chef 11.0.0.beta.0 → 11.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/bin/chef-apply +1 -1
  2. data/distro/common/html/chef-client.8.html +3 -3
  3. data/distro/common/html/chef-expander.8.html +3 -3
  4. data/distro/common/html/chef-expanderctl.8.html +3 -3
  5. data/distro/common/html/chef-server-webui.8.html +3 -3
  6. data/distro/common/html/chef-server.8.html +3 -3
  7. data/distro/common/html/chef-shell.1.html +3 -3
  8. data/distro/common/html/chef-solo.8.html +3 -3
  9. data/distro/common/html/chef-solr.8.html +3 -3
  10. data/distro/common/html/knife-bootstrap.1.html +3 -3
  11. data/distro/common/html/knife-client.1.html +3 -3
  12. data/distro/common/html/knife-configure.1.html +3 -3
  13. data/distro/common/html/knife-cookbook-site.1.html +3 -3
  14. data/distro/common/html/knife-cookbook.1.html +3 -3
  15. data/distro/common/html/knife-data-bag.1.html +3 -3
  16. data/distro/common/html/knife-environment.1.html +3 -3
  17. data/distro/common/html/knife-exec.1.html +3 -3
  18. data/distro/common/html/knife-index.1.html +3 -3
  19. data/distro/common/html/knife-node.1.html +3 -3
  20. data/distro/common/html/knife-role.1.html +3 -3
  21. data/distro/common/html/knife-search.1.html +3 -3
  22. data/distro/common/html/knife-ssh.1.html +3 -3
  23. data/distro/common/html/knife-status.1.html +3 -3
  24. data/distro/common/html/knife-tag.1.html +3 -3
  25. data/distro/common/html/knife.1.html +3 -3
  26. data/distro/common/man/man1/chef-shell.1 +1 -1
  27. data/distro/common/man/man1/knife-bootstrap.1 +1 -1
  28. data/distro/common/man/man1/knife-client.1 +1 -1
  29. data/distro/common/man/man1/knife-configure.1 +1 -1
  30. data/distro/common/man/man1/knife-cookbook-site.1 +1 -1
  31. data/distro/common/man/man1/knife-cookbook.1 +1 -1
  32. data/distro/common/man/man1/knife-data-bag.1 +1 -1
  33. data/distro/common/man/man1/knife-environment.1 +1 -1
  34. data/distro/common/man/man1/knife-exec.1 +1 -1
  35. data/distro/common/man/man1/knife-index.1 +1 -1
  36. data/distro/common/man/man1/knife-node.1 +1 -1
  37. data/distro/common/man/man1/knife-role.1 +1 -1
  38. data/distro/common/man/man1/knife-search.1 +1 -1
  39. data/distro/common/man/man1/knife-ssh.1 +1 -1
  40. data/distro/common/man/man1/knife-status.1 +1 -1
  41. data/distro/common/man/man1/knife-tag.1 +1 -1
  42. data/distro/common/man/man1/knife.1 +1 -1
  43. data/distro/common/man/man8/chef-client.8 +1 -1
  44. data/distro/common/man/man8/chef-expander.8 +1 -1
  45. data/distro/common/man/man8/chef-expanderctl.8 +1 -1
  46. data/distro/common/man/man8/chef-server-webui.8 +1 -1
  47. data/distro/common/man/man8/chef-server.8 +1 -1
  48. data/distro/common/man/man8/chef-solo.8 +1 -1
  49. data/distro/common/man/man8/chef-solr.8 +1 -1
  50. data/lib/chef/application/apply.rb +2 -2
  51. data/lib/chef/application/client.rb +8 -0
  52. data/lib/chef/client.rb +28 -0
  53. data/lib/chef/config.rb +2 -0
  54. data/lib/chef/cookbook/metadata.rb +0 -2
  55. data/lib/chef/dsl/data_query.rb +5 -0
  56. data/lib/chef/dsl/include_attribute.rb +3 -0
  57. data/lib/chef/dsl/include_recipe.rb +3 -0
  58. data/lib/chef/dsl/platform_introspection.rb +5 -0
  59. data/lib/chef/dsl/recipe.rb +4 -1
  60. data/lib/chef/exceptions.rb +1 -0
  61. data/lib/chef/formatters/error_inspectors/resource_failure_inspector.rb +8 -0
  62. data/lib/chef/mixin/deep_merge.rb +26 -0
  63. data/lib/chef/mixin/deprecation.rb +35 -0
  64. data/lib/chef/mixin/language.rb +16 -4
  65. data/lib/chef/mixin/language_include_attribute.rb +7 -1
  66. data/lib/chef/mixin/language_include_recipe.rb +7 -1
  67. data/lib/chef/mixin/recipe_definition_dsl_core.rb +4 -2
  68. data/lib/chef/mixins.rb +1 -1
  69. data/lib/chef/node.rb +0 -2
  70. data/lib/chef/node/attribute.rb +22 -17
  71. data/lib/chef/node/attribute_collections.rb +8 -1
  72. data/lib/chef/platform.rb +9 -0
  73. data/lib/chef/provider/cookbook_file.rb +28 -0
  74. data/lib/chef/resource.rb +12 -6
  75. data/lib/chef/version.rb +1 -1
  76. data/lib/chef/win32/api/security.rb +45 -1
  77. data/lib/chef/win32/registry.rb +23 -12
  78. data/lib/chef/win32/security.rb +19 -0
  79. data/spec/data/shef-config.rb +3 -0
  80. data/spec/functional/knife/smoke_test.rb +34 -0
  81. data/spec/functional/resource/cookbook_file_spec.rb +19 -0
  82. data/spec/functional/resource/registry_spec.rb +8 -12
  83. data/spec/functional/shell_spec.rb +5 -4
  84. data/spec/functional/win32/security_spec.rb +37 -0
  85. data/spec/spec_helper.rb +6 -0
  86. data/spec/support/lib/chef/resource/cat.rb +3 -5
  87. data/spec/support/lib/chef/resource/one_two_three_four.rb +8 -10
  88. data/spec/support/lib/chef/resource/zen_master.rb +8 -10
  89. data/spec/support/shared/functional/file_resource.rb +18 -0
  90. data/spec/support/shared/functional/securable_resource.rb +73 -70
  91. data/spec/unit/chef_fs/diff_spec.rb +30 -29
  92. data/spec/unit/client_spec.rb +62 -0
  93. data/spec/unit/mixin/deep_merge_spec.rb +37 -0
  94. data/spec/unit/mixin/deprecation_spec.rb +23 -0
  95. data/spec/unit/node/attribute_spec.rb +47 -0
  96. data/spec/unit/registry_helper_spec.rb +7 -5
  97. data/spec/unit/resource_spec.rb +23 -0
  98. metadata +4 -3
  99. data/lib/chef/mixin/check_helper.rb +0 -31
@@ -56,5 +56,8 @@ class Chef
56
56
  end
57
57
  end
58
58
 
59
+ # **DEPRECATED**
60
+ # This used to be part of chef/mixin/language_include_attribute. Load the file to activate the deprecation code.
61
+ require 'chef/mixin/language_include_attribute'
59
62
 
60
63
 
@@ -39,4 +39,7 @@ class Chef
39
39
  end
40
40
  end
41
41
 
42
+ # **DEPRECATED**
43
+ # This used to be part of chef/mixin/language_include_recipe. Load the file to activate the deprecation code.
44
+ require 'chef/mixin/language_include_recipe'
42
45
 
@@ -211,3 +211,8 @@ class Chef
211
211
  end
212
212
  end
213
213
  end
214
+
215
+ # **DEPRECATED**
216
+ # This used to be part of chef/mixin/language. Load the file to activate the deprecation code.
217
+ require 'chef/mixin/language'
218
+
@@ -20,7 +20,6 @@
20
20
  require 'chef/resource'
21
21
  require 'chef/resource_platform_map'
22
22
  require 'chef/mixin/convert_to_class_name'
23
- require 'chef/mixin/language'
24
23
 
25
24
  class Chef
26
25
  module DSL
@@ -82,3 +81,7 @@ class Chef
82
81
  end
83
82
  end
84
83
  end
84
+
85
+ # **DEPRECATED**
86
+ # This used to be part of chef/mixin/recipe_definition_dsl_core. Load the file to activate the deprecation code.
87
+ require 'chef/mixin/recipe_definition_dsl_core'
@@ -96,6 +96,7 @@ class Chef
96
96
  class Win32APIFunctionNotImplemented < NotImplementedError; end
97
97
  # Attempting to run windows code on a not-windows node
98
98
  class Win32NotWindows < RuntimeError; end
99
+ class WindowsNotAdmin < RuntimeError; end
99
100
  class ObsoleteDependencySyntax < ArgumentError; end
100
101
  class InvalidDataBagPath < ArgumentError; end
101
102
 
@@ -50,6 +50,14 @@ class Chef
50
50
  if exception.respond_to?(:source_listing)
51
51
  error_description.section("Template Context:", "#{exception.source_location}\n#{exception.source_listing}")
52
52
  end
53
+
54
+ if Chef::Platform.windows?
55
+ require 'chef/win32/security'
56
+
57
+ if !Chef::ReservedNames::Win32::Security.has_admin_privileges?
58
+ error_description.section("Missing Windows Admin Privileges", "chef-client doesn't have administrator privileges. This can be a possible reason for the resource failure.")
59
+ end
60
+ end
53
61
  end
54
62
 
55
63
  def recipe_snippet
@@ -110,6 +110,32 @@ class Chef
110
110
  dest
111
111
  end # deep_merge!
112
112
 
113
+ def hash_only_merge(merge_onto, merge_with)
114
+ hash_only_merge!(merge_onto.dup, merge_with.dup)
115
+ end
116
+
117
+ # Deep merge without Array merge.
118
+ # `merge_onto` is the object that will "lose" in case of conflict.
119
+ # `merge_with` is the object whose values will replace `merge_onto`s
120
+ # values when there is a conflict.
121
+ def hash_only_merge!(merge_onto, merge_with)
122
+ # If there are two Hashes, recursively merge.
123
+ if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
124
+ merge_with.each do |key, merge_with_value|
125
+ merge_onto[key] = hash_only_merge!(merge_onto[key], merge_with_value)
126
+ end
127
+ merge_onto
128
+
129
+ # If merge_with is nil, don't replace merge_onto
130
+ elsif merge_with.nil?
131
+ merge_onto
132
+
133
+ # In all other cases, replace merge_onto with merge_with
134
+ else
135
+ merge_with
136
+ end
137
+ end
138
+
113
139
  # Checks for attempted use of subtractive merge, which was removed for
114
140
  # Chef 11.0. If subtractive merge use is detected, will raise an
115
141
  # InvalidSubtractiveMerge exception.
@@ -18,7 +18,42 @@
18
18
 
19
19
  class Chef
20
20
  module Mixin
21
+
22
+
23
+ def self.deprecated_constants
24
+ @deprecated_constants ||= {}
25
+ end
26
+
27
+ # Add a deprecated constant to the Chef::Mixin namespace.
28
+ # === Arguments
29
+ # * name: the constant name, as a relative symbol.
30
+ # * replacement: the constant to return instead.
31
+ # * message: A message telling the user what to do instead.
32
+ # === Example:
33
+ # deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM)
34
+ # Chef::Mixin::RecipeDefinitionDSLCore is deprecated, use Chef::DSL::Recipe instead.
35
+ # EOM
36
+ def self.deprecate_constant(name, replacement, message)
37
+ deprecated_constants[name] = {:replacement => replacement, :message => message}
38
+ end
39
+
40
+ # Const missing hook to look up deprecated constants defined with
41
+ # deprecate_constant. Emits a warning to the logger and returns the
42
+ # replacement constant. Will call super, most likely causing an exception
43
+ # for the missing constant, if +name+ is not found in the
44
+ # deprecated_constants collection.
45
+ def self.const_missing(name)
46
+ if new_const = deprecated_constants[name]
47
+ Chef::Log.warn(new_const[:message])
48
+ Chef::Log.warn("Called from: \n#{caller[0...3].map {|l| "\t#{l}"}.join("\n")}")
49
+ new_const[:replacement]
50
+ else
51
+ super
52
+ end
53
+ end
54
+
21
55
  module Deprecation
56
+
22
57
  class DeprecatedObjectProxyBase
23
58
  KEEPERS = %w{__id__ __send__ instance_eval == equal? initialize object_id}
24
59
  instance_methods.each { |method_name| undef_method(method_name) unless KEEPERS.include?(method_name.to_s)}
@@ -18,19 +18,31 @@
18
18
 
19
19
  require 'chef/dsl/platform_introspection'
20
20
  require 'chef/dsl/data_query'
21
+ require 'chef/mixin/deprecation'
21
22
 
22
23
  class Chef
23
24
  module Mixin
24
25
 
25
- # == [DEPRECATED] Chef::Mixin::Language
26
- # This module is deprecated and remains only for backwards compatibility.
26
+ # == [DEPRECATED] Chef::Mixin::DeprecatedLanguageModule
27
+ # This module is a temporary replacement for the previous
28
+ # Chef::Mixin::Language. That module's functionality was split into two
29
+ # modules, Chef::DSL::PlatformIntrospection, and Chef::DSL::DataQuery.
27
30
  #
28
- # See Chef::DSL::PlatformIntrospection and Chef::DSL::DataQuery
29
- module Language
31
+ # This module includes both PlatformIntrospection and DataQuery to provide
32
+ # the same interfaces and behavior as the prior Mixin::Language.
33
+ #
34
+ # This module is loaded via const_missing hook when Chef::Mixin::Language
35
+ # is accessed. See chef/mixin/deprecation for details.
36
+ module DeprecatedLanguageModule
30
37
 
31
38
  include Chef::DSL::PlatformIntrospection
32
39
  include Chef::DSL::DataQuery
33
40
 
34
41
  end
42
+
43
+ deprecate_constant(:Language, DeprecatedLanguageModule, <<-EOM)
44
+ Chef::Mixin::Language is deprecated. Use either (or both)
45
+ Chef::DSL::PlatformIntrospection or Chef::DSL::DataQuery instead.
46
+ EOM
35
47
  end
36
48
  end
@@ -17,13 +17,19 @@
17
17
  #
18
18
 
19
19
  require 'chef/dsl/include_attribute'
20
+ require 'chef/mixin/deprecation'
20
21
 
21
22
  class Chef
22
23
  module Mixin
23
24
 
24
25
  # DEPRECATED: This is just here for compatibility, use
25
26
  # Chef::DSL::IncludeAttribute instead.
26
- LanguageIncludeAttribute = Chef::DSL::IncludeAttribute
27
+
28
+ deprecate_constant(:LanguageIncludeAttribute, Chef::DSL::IncludeAttribute, <<-EOM)
29
+ Chef::Mixin::LanguageIncludeAttribute is deprecated. Use
30
+ Chef::DSL::IncludeAttribute instead.
31
+ EOM
32
+
27
33
  end
28
34
  end
29
35
 
@@ -17,10 +17,16 @@
17
17
  #
18
18
 
19
19
  require 'chef/dsl/include_recipe'
20
+ require 'chef/mixin/deprecation'
20
21
 
21
22
  class Chef
22
23
  module Mixin
23
- LanguageIncludeRecipe = Chef::DSL::IncludeRecipe
24
+
25
+ deprecate_constant(:LanguageIncludeRecipe, Chef::DSL::IncludeRecipe, <<-EOM)
26
+ Chef::Mixin::LanguageIncludeRecipe is deprecated, use Chef::DSL::Recipe
27
+ instead.
28
+ EOM
29
+
24
30
  end
25
31
  end
26
32
 
@@ -24,10 +24,12 @@
24
24
  # This constant (module name) will eventually be deprecated and then removed.
25
25
  ###
26
26
 
27
- require 'chef/dsl/recipe'
27
+ require 'chef/mixin/deprecation'
28
28
 
29
29
  class Chef
30
30
  module Mixin
31
- RecipeDefinitionDSLCore = Chef::DSL::Recipe
31
+ deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM)
32
+ Chef::Mixin::RecipeDefinitionDSLCore is deprecated. Use Chef::DSL::Recipe instead.
33
+ EOM
32
34
  end
33
35
  end
@@ -1,5 +1,4 @@
1
1
  require 'chef/mixin/shell_out'
2
- require 'chef/mixin/check_helper'
3
2
  require 'chef/mixin/checksum'
4
3
  require 'chef/mixin/command'
5
4
  require 'chef/mixin/convert_to_class_name'
@@ -12,3 +11,4 @@ require 'chef/mixin/path_sanity'
12
11
  require 'chef/mixin/template'
13
12
  require 'chef/mixin/securable'
14
13
  require 'chef/mixin/xml_escape'
14
+
@@ -22,7 +22,6 @@
22
22
  require 'forwardable'
23
23
  require 'chef/config'
24
24
  require 'chef/nil_argument'
25
- require 'chef/mixin/check_helper'
26
25
  require 'chef/mixin/params_validate'
27
26
  require 'chef/mixin/from_file'
28
27
  require 'chef/mixin/deep_merge'
@@ -57,7 +56,6 @@ class Chef
57
56
  include Chef::DSL::IncludeAttribute
58
57
  include Chef::DSL::PlatformIntrospection
59
58
 
60
- include Chef::Mixin::CheckHelper
61
59
  include Chef::Mixin::ParamsValidate
62
60
 
63
61
  # Create a new Chef::Node object.
@@ -284,32 +284,20 @@ class Chef
284
284
 
285
285
  def merged_attributes
286
286
  @merged_attributes ||= begin
287
- resolved_attrs = COMPONENTS.inject(Mash.new) do |merged, component_ivar|
288
- component_value = instance_variable_get(component_ivar)
289
- Chef::Mixin::DeepMerge.merge(merged, component_value)
287
+ components = [merge_defaults, @normal, merge_overrides, @automatic]
288
+ resolved_attrs = components.inject(Mash.new) do |merged, component|
289
+ Chef::Mixin::DeepMerge.hash_only_merge(merged, component)
290
290
  end
291
291
  immutablize(resolved_attrs)
292
292
  end
293
293
  end
294
294
 
295
295
  def combined_override
296
- @combined_override ||= begin
297
- resolved_attrs = OVERRIDE_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
298
- component_value = instance_variable_get(component_ivar)
299
- Chef::Mixin::DeepMerge.merge(merged, component_value)
300
- end
301
- immutablize(resolved_attrs)
302
- end
296
+ @combined_override ||= immutablize(merge_overrides)
303
297
  end
304
298
 
305
299
  def combined_default
306
- @combined_default ||= begin
307
- resolved_attrs = DEFAULT_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
308
- component_value = instance_variable_get(component_ivar)
309
- Chef::Mixin::DeepMerge.merge(merged, component_value)
310
- end
311
- immutablize(resolved_attrs)
312
- end
300
+ @combined_default ||= immutablize(merge_defaults)
313
301
  end
314
302
 
315
303
  def [](key)
@@ -358,6 +346,23 @@ class Chef
358
346
  @set_unless_present
359
347
  end
360
348
 
349
+ private
350
+
351
+ def merge_defaults
352
+ DEFAULT_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
353
+ component_value = instance_variable_get(component_ivar)
354
+ Chef::Mixin::DeepMerge.merge(merged, component_value)
355
+ end
356
+ end
357
+
358
+ def merge_overrides
359
+ OVERRIDE_COMPONENTS.inject(Mash.new) do |merged, component_ivar|
360
+ component_value = instance_variable_get(component_ivar)
361
+ Chef::Mixin::DeepMerge.merge(merged, component_value)
362
+ end
363
+ end
364
+
365
+
361
366
  end
362
367
 
363
368
  end
@@ -154,7 +154,14 @@ class Chef
154
154
  alias :attribute? :has_key?
155
155
 
156
156
  def method_missing(symbol, *args)
157
- if args.empty?
157
+ # Calling `puts arg` implicitly calls #to_ary on `arg`. If `arg` does
158
+ # not implement #to_ary, ruby recognizes it as a single argument, and
159
+ # if it returns an Array, then ruby prints each element. If we don't
160
+ # account for that here, we'll auto-vivify a VividMash for the key
161
+ # :to_ary which creates an unwanted key and raises a TypeError.
162
+ if symbol == :to_ary
163
+ super
164
+ elsif args.empty?
158
165
  self[symbol]
159
166
  elsif symbol.to_s =~ /=$/
160
167
  key_to_set = symbol.to_s[/^(.+)=$/, 1]
@@ -476,6 +476,15 @@ class Chef
476
476
  end
477
477
  end
478
478
 
479
+ def windows_server_2003?
480
+ return false unless windows?
481
+
482
+ require 'ruby-wmi'
483
+
484
+ host = WMI::Win32_OperatingSystem.find(:first)
485
+ (host.version && host.version.start_with?("5.2"))
486
+ end
487
+
479
488
  private
480
489
 
481
490
  def explicit_provider(platform, version, resource_type)
@@ -47,6 +47,7 @@ class Chef
47
47
  Chef::Log.debug("#{@new_resource} staging #{file_cache_location} to #{tempfile.path}")
48
48
  tempfile.close
49
49
  FileUtils.cp(file_cache_location, tempfile.path)
50
+ enforce_tempfile_inheritance(tempfile.path)
50
51
  end
51
52
  update_new_file_state
52
53
  Chef::Log.info("#{@new_resource} created file #{@new_resource.path}")
@@ -80,6 +81,33 @@ class Chef
80
81
  ( ! ::File.exist?(@new_resource.path)) || ( ! compare_content)
81
82
  end
82
83
 
84
+ protected
85
+
86
+ def enforce_tempfile_inheritance(tempfile_path)
87
+ # On the Windows platform, files in the temp directory
88
+ # default to not inherit unless the new resource
89
+ # specifies rights of
90
+ # some sort. Here we ensure that even when no rights
91
+ # are
92
+ # specified, the dacl's inheritance flag is set.
93
+ if Chef::Platform.windows? &&
94
+ @new_resource.rights.nil? &&
95
+ @new_resource.group.nil? &&
96
+ @new_resource.owner.nil? &&
97
+ @new_resource.deny_rights.nil?
98
+
99
+ securable_tempfile = Chef::ReservedNames::Win32::Security::SecurableObject.new(tempfile_path)
100
+
101
+ # No rights were specified, so the dacl will have
102
+ # no explicit aces
103
+ default_dacl = Chef::ReservedNames::Win32::Security::ACL.create([])
104
+
105
+ # In setting this default dacl, set inheritance to
106
+ # true
107
+ securable_tempfile.set_dacl(default_dacl, true)
108
+ end
109
+ end
110
+
83
111
  end
84
112
  end
85
113
  end
@@ -18,8 +18,8 @@
18
18
  #
19
19
 
20
20
  require 'chef/mixin/params_validate'
21
- require 'chef/mixin/check_helper'
22
21
  require 'chef/dsl/platform_introspection'
22
+ require 'chef/dsl/data_query'
23
23
  require 'chef/dsl/registry_helper'
24
24
  require 'chef/mixin/convert_to_class_name'
25
25
  require 'chef/resource/conditional'
@@ -120,7 +120,7 @@ F
120
120
  FORBIDDEN_IVARS = [:@run_context, :@node, :@not_if, :@only_if, :@enclosing_provider]
121
121
  HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@node, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider]
122
122
 
123
- include Chef::Mixin::CheckHelper
123
+ include Chef::DSL::DataQuery
124
124
  include Chef::Mixin::ParamsValidate
125
125
  include Chef::DSL::PlatformIntrospection
126
126
  include Chef::DSL::RegistryHelper
@@ -324,17 +324,19 @@ F
324
324
  end
325
325
 
326
326
  def name(name=nil)
327
- set_if_args(@name, name) do
327
+ if !name.nil?
328
328
  raise ArgumentError, "name must be a string!" unless name.kind_of?(String)
329
329
  @name = name
330
330
  end
331
+ @name
331
332
  end
332
333
 
333
334
  def noop(tf=nil)
334
- set_if_args(@noop, tf) do
335
+ if !tf.nil?
335
336
  raise ArgumentError, "noop must be true or false!" unless tf == true || tf == false
336
337
  @noop = tf
337
338
  end
339
+ @noop
338
340
  end
339
341
 
340
342
  def ignore_failure(arg=nil)
@@ -536,10 +538,14 @@ F
536
538
  end
537
539
 
538
540
  def defined_at
541
+ # The following regexp should match these two sourceline formats:
542
+ # /some/path/to/file.rb:80:in `wombat_tears'
543
+ # C:/some/path/to/file.rb:80 in 1`wombat_tears'
544
+ # extracting the path to the source file and the line number.
545
+ (file, line_no) = source_line.match(/(.*):(\d+):?.*$/).to_a[1,2] if source_line
539
546
  if cookbook_name && recipe_name && source_line
540
- "#{cookbook_name}::#{recipe_name} line #{source_line.split(':')[1]}"
547
+ "#{cookbook_name}::#{recipe_name} line #{line_no}"
541
548
  elsif source_line
542
- file, line_no = source_line.split(':')
543
549
  "#{file} line #{line_no}"
544
550
  else
545
551
  "dynamically defined"