chef 12.4.0.rc.0-universal-mingw32 → 12.4.0.rc.2-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +12 -1
  3. data/lib/chef/api_client.rb +130 -26
  4. data/lib/chef/application.rb +0 -1
  5. data/lib/chef/application/client.rb +8 -19
  6. data/lib/chef/audit/audit_reporter.rb +12 -7
  7. data/lib/chef/audit/logger.rb +36 -0
  8. data/lib/chef/audit/runner.rb +4 -2
  9. data/lib/chef/chef_class.rb +62 -11
  10. data/lib/chef/client.rb +587 -207
  11. data/lib/chef/config.rb +0 -1
  12. data/lib/chef/dsl/recipe.rb +45 -56
  13. data/lib/chef/dsl/resources.rb +3 -2
  14. data/lib/chef/event_dispatch/base.rb +7 -2
  15. data/lib/chef/exceptions.rb +4 -1
  16. data/lib/chef/file_content_management/deploy/mv_windows.rb +16 -6
  17. data/lib/chef/formatters/doc.rb +15 -7
  18. data/lib/chef/formatters/error_inspectors/api_error_formatting.rb +10 -7
  19. data/lib/chef/guard_interpreter/default_guard_interpreter.rb +2 -0
  20. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +4 -1
  21. data/lib/chef/http/authenticator.rb +7 -2
  22. data/lib/chef/knife.rb +16 -4
  23. data/lib/chef/knife/client_create.rb +55 -31
  24. data/lib/chef/knife/core/generic_presenter.rb +1 -1
  25. data/lib/chef/knife/core/subcommand_loader.rb +1 -1
  26. data/lib/chef/knife/osc_user_create.rb +97 -0
  27. data/lib/chef/knife/osc_user_delete.rb +51 -0
  28. data/lib/chef/knife/osc_user_edit.rb +58 -0
  29. data/lib/chef/knife/osc_user_list.rb +47 -0
  30. data/lib/chef/knife/osc_user_reregister.rb +64 -0
  31. data/lib/chef/knife/osc_user_show.rb +54 -0
  32. data/lib/chef/knife/user_create.rb +95 -36
  33. data/lib/chef/knife/user_delete.rb +52 -2
  34. data/lib/chef/knife/user_edit.rb +37 -7
  35. data/lib/chef/knife/user_list.rb +3 -0
  36. data/lib/chef/knife/user_reregister.rb +39 -8
  37. data/lib/chef/knife/user_show.rb +30 -1
  38. data/lib/chef/mixin/api_version_request_handling.rb +66 -0
  39. data/lib/chef/mixin/convert_to_class_name.rb +10 -4
  40. data/lib/chef/mixin/deprecation.rb +24 -0
  41. data/lib/chef/mixin/powershell_out.rb +98 -0
  42. data/lib/chef/mixin/provides.rb +5 -18
  43. data/lib/chef/mixin/uris.rb +11 -0
  44. data/lib/chef/mixin/windows_architecture_helper.rb +5 -2
  45. data/lib/chef/mixin/windows_env_helper.rb +11 -2
  46. data/lib/chef/node_map.rb +130 -75
  47. data/lib/chef/osc_user.rb +194 -0
  48. data/lib/chef/platform/provider_mapping.rb +2 -269
  49. data/lib/chef/platform/provider_priority_map.rb +6 -69
  50. data/lib/chef/platform/query_helpers.rb +5 -0
  51. data/lib/chef/platform/resource_priority_map.rb +12 -15
  52. data/lib/chef/policy_builder/policyfile.rb +1 -0
  53. data/lib/chef/provider.rb +19 -0
  54. data/lib/chef/provider/directory.rb +3 -0
  55. data/lib/chef/provider/dsc_resource.rb +8 -1
  56. data/lib/chef/provider/file.rb +1 -0
  57. data/lib/chef/provider/group/aix.rb +1 -0
  58. data/lib/chef/provider/group/dscl.rb +1 -1
  59. data/lib/chef/provider/group/gpasswd.rb +1 -0
  60. data/lib/chef/provider/group/groupmod.rb +1 -1
  61. data/lib/chef/provider/group/pw.rb +1 -0
  62. data/lib/chef/provider/group/suse.rb +2 -0
  63. data/lib/chef/provider/group/usermod.rb +2 -1
  64. data/lib/chef/provider/group/windows.rb +1 -1
  65. data/lib/chef/provider/ifconfig.rb +2 -0
  66. data/lib/chef/provider/ifconfig/aix.rb +1 -0
  67. data/lib/chef/provider/ifconfig/debian.rb +2 -0
  68. data/lib/chef/provider/ifconfig/redhat.rb +1 -0
  69. data/lib/chef/provider/lwrp_base.rb +4 -0
  70. data/lib/chef/provider/mount.rb +0 -1
  71. data/lib/chef/provider/mount/aix.rb +1 -0
  72. data/lib/chef/provider/mount/mount.rb +2 -0
  73. data/lib/chef/provider/mount/solaris.rb +2 -0
  74. data/lib/chef/provider/package.rb +55 -0
  75. data/lib/chef/provider/package/aix.rb +7 -7
  76. data/lib/chef/provider/package/apt.rb +3 -3
  77. data/lib/chef/provider/package/dpkg.rb +4 -4
  78. data/lib/chef/provider/package/easy_install.rb +5 -5
  79. data/lib/chef/provider/package/freebsd/base.rb +2 -2
  80. data/lib/chef/provider/package/freebsd/pkg.rb +6 -6
  81. data/lib/chef/provider/package/freebsd/pkgng.rb +5 -5
  82. data/lib/chef/provider/package/freebsd/port.rb +4 -4
  83. data/lib/chef/provider/package/homebrew.rb +2 -2
  84. data/lib/chef/provider/package/ips.rb +4 -4
  85. data/lib/chef/provider/package/macports.rb +5 -6
  86. data/lib/chef/provider/package/openbsd.rb +4 -5
  87. data/lib/chef/provider/package/pacman.rb +4 -4
  88. data/lib/chef/provider/package/portage.rb +2 -0
  89. data/lib/chef/provider/package/rpm.rb +7 -8
  90. data/lib/chef/provider/package/rubygems.rb +5 -12
  91. data/lib/chef/provider/package/smartos.rb +4 -4
  92. data/lib/chef/provider/package/solaris.rb +7 -7
  93. data/lib/chef/provider/package/windows/msi.rb +1 -1
  94. data/lib/chef/provider/package/yum.rb +4 -6
  95. data/lib/chef/provider/package/zypper.rb +16 -14
  96. data/lib/chef/provider/powershell_script.rb +129 -47
  97. data/lib/chef/provider/remote_file/content.rb +4 -1
  98. data/lib/chef/provider/remote_file/local_file.rb +10 -4
  99. data/lib/chef/provider/service.rb +44 -0
  100. data/lib/chef/provider/service/freebsd.rb +1 -1
  101. data/lib/chef/provider/service/init.rb +1 -0
  102. data/lib/chef/provider/service/macosx.rb +1 -1
  103. data/lib/chef/provider/service/windows.rb +0 -1
  104. data/lib/chef/provider/user.rb +1 -1
  105. data/lib/chef/provider/user/aix.rb +3 -2
  106. data/lib/chef/provider/user/pw.rb +1 -0
  107. data/lib/chef/provider/user/solaris.rb +2 -0
  108. data/lib/chef/provider/user/useradd.rb +1 -0
  109. data/lib/chef/provider_resolver.rb +87 -134
  110. data/lib/chef/resource.rb +274 -68
  111. data/lib/chef/resource/apt_package.rb +0 -2
  112. data/lib/chef/resource/bash.rb +0 -2
  113. data/lib/chef/resource/batch.rb +1 -1
  114. data/lib/chef/resource/bff_package.rb +0 -7
  115. data/lib/chef/resource/breakpoint.rb +3 -6
  116. data/lib/chef/resource/chef_gem.rb +0 -3
  117. data/lib/chef/resource/cookbook_file.rb +1 -3
  118. data/lib/chef/resource/cron.rb +2 -4
  119. data/lib/chef/resource/csh.rb +0 -2
  120. data/lib/chef/resource/deploy.rb +9 -6
  121. data/lib/chef/resource/deploy_revision.rb +0 -14
  122. data/lib/chef/resource/directory.rb +2 -4
  123. data/lib/chef/resource/dpkg_package.rb +0 -5
  124. data/lib/chef/resource/dsc_resource.rb +2 -3
  125. data/lib/chef/resource/dsc_script.rb +2 -3
  126. data/lib/chef/resource/easy_install_package.rb +0 -7
  127. data/lib/chef/resource/env.rb +3 -3
  128. data/lib/chef/resource/erl_call.rb +2 -5
  129. data/lib/chef/resource/execute.rb +2 -4
  130. data/lib/chef/resource/file.rb +2 -4
  131. data/lib/chef/resource/freebsd_package.rb +0 -5
  132. data/lib/chef/resource/gem_package.rb +0 -3
  133. data/lib/chef/resource/git.rb +0 -3
  134. data/lib/chef/resource/group.rb +2 -4
  135. data/lib/chef/resource/homebrew_package.rb +0 -2
  136. data/lib/chef/resource/http_request.rb +3 -4
  137. data/lib/chef/resource/ifconfig.rb +3 -4
  138. data/lib/chef/resource/ips_package.rb +2 -2
  139. data/lib/chef/resource/link.rb +3 -5
  140. data/lib/chef/resource/log.rb +2 -4
  141. data/lib/chef/resource/lwrp_base.rb +10 -61
  142. data/lib/chef/resource/macosx_service.rb +1 -2
  143. data/lib/chef/resource/macports_package.rb +0 -7
  144. data/lib/chef/resource/mdadm.rb +2 -5
  145. data/lib/chef/resource/mount.rb +2 -4
  146. data/lib/chef/resource/ohai.rb +2 -4
  147. data/lib/chef/resource/openbsd_package.rb +0 -6
  148. data/lib/chef/resource/package.rb +9 -6
  149. data/lib/chef/resource/pacman_package.rb +0 -7
  150. data/lib/chef/resource/paludis_package.rb +2 -3
  151. data/lib/chef/resource/perl.rb +0 -3
  152. data/lib/chef/resource/portage_package.rb +0 -3
  153. data/lib/chef/resource/powershell_script.rb +1 -2
  154. data/lib/chef/resource/python.rb +0 -3
  155. data/lib/chef/resource/reboot.rb +1 -3
  156. data/lib/chef/resource/registry_key.rb +3 -5
  157. data/lib/chef/resource/remote_directory.rb +3 -5
  158. data/lib/chef/resource/remote_file.rb +4 -5
  159. data/lib/chef/resource/route.rb +3 -5
  160. data/lib/chef/resource/rpm_package.rb +0 -2
  161. data/lib/chef/resource/ruby.rb +0 -4
  162. data/lib/chef/resource/ruby_block.rb +2 -4
  163. data/lib/chef/resource/scm.rb +3 -5
  164. data/lib/chef/resource/script.rb +0 -3
  165. data/lib/chef/resource/service.rb +3 -5
  166. data/lib/chef/resource/smartos_package.rb +0 -9
  167. data/lib/chef/resource/solaris_package.rb +0 -10
  168. data/lib/chef/resource/subversion.rb +1 -3
  169. data/lib/chef/resource/template.rb +0 -4
  170. data/lib/chef/resource/timestamped_deploy.rb +0 -4
  171. data/lib/chef/resource/user.rb +2 -5
  172. data/lib/chef/resource/whyrun_safe_ruby_block.rb +0 -7
  173. data/lib/chef/resource/windows_package.rb +3 -3
  174. data/lib/chef/resource/windows_script.rb +2 -2
  175. data/lib/chef/resource/windows_service.rb +3 -3
  176. data/lib/chef/resource/yum_package.rb +0 -3
  177. data/lib/chef/resource/zypper_package.rb +27 -0
  178. data/lib/chef/resource_builder.rb +7 -0
  179. data/lib/chef/resource_reporter.rb +1 -1
  180. data/lib/chef/resource_resolver.rb +108 -62
  181. data/lib/chef/resources.rb +1 -0
  182. data/lib/chef/rest.rb +1 -0
  183. data/lib/chef/server_api.rb +2 -0
  184. data/lib/chef/user.rb +193 -42
  185. data/lib/chef/util/backup.rb +9 -1
  186. data/lib/chef/util/path_helper.rb +0 -1
  187. data/lib/chef/version.rb +1 -1
  188. data/spec/functional/audit/runner_spec.rb +22 -42
  189. data/spec/functional/mixin/powershell_out_spec.rb +43 -0
  190. data/spec/functional/resource/execute_spec.rb +9 -2
  191. data/spec/functional/resource/file_spec.rb +25 -0
  192. data/spec/functional/resource/group_spec.rb +5 -0
  193. data/spec/functional/resource/link_spec.rb +5 -11
  194. data/spec/functional/resource/powershell_spec.rb +40 -5
  195. data/spec/functional/resource/user/useradd_spec.rb +10 -18
  196. data/spec/integration/recipes/lwrp_spec.rb +57 -0
  197. data/spec/integration/recipes/provider_choice.rb +2 -7
  198. data/spec/integration/recipes/recipe_dsl_spec.rb +517 -19
  199. data/spec/spec_helper.rb +1 -1
  200. data/spec/support/lib/chef/provider/openldap_includer.rb +29 -0
  201. data/spec/support/lib/chef/resource/cat.rb +0 -2
  202. data/spec/support/lib/chef/resource/one_two_three_four.rb +0 -6
  203. data/spec/support/lib/chef/resource/openldap_includer.rb +27 -0
  204. data/spec/support/lib/chef/resource/with_state.rb +0 -9
  205. data/spec/support/lib/chef/resource/zen_follower.rb +0 -6
  206. data/spec/support/lib/chef/resource/zen_master.rb +1 -6
  207. data/spec/support/shared/context/client.rb +277 -0
  208. data/spec/support/shared/examples/client.rb +53 -0
  209. data/spec/support/shared/functional/file_resource.rb +0 -4
  210. data/spec/support/shared/functional/securable_resource.rb +0 -24
  211. data/spec/support/shared/functional/securable_resource_with_reporting.rb +4 -4
  212. data/spec/support/shared/functional/windows_script.rb +1 -1
  213. data/spec/support/shared/unit/api_versioning.rb +77 -0
  214. data/spec/support/shared/unit/knife_shared.rb +40 -0
  215. data/spec/support/shared/unit/user_and_client_shared.rb +115 -0
  216. data/spec/unit/api_client_spec.rb +189 -14
  217. data/spec/unit/application/client_spec.rb +0 -5
  218. data/spec/unit/audit/audit_reporter_spec.rb +58 -14
  219. data/spec/unit/audit/logger_spec.rb +42 -0
  220. data/spec/unit/audit/runner_spec.rb +2 -2
  221. data/spec/unit/chef_fs/file_pattern_spec.rb +3 -15
  222. data/spec/unit/client_spec.rb +58 -374
  223. data/spec/unit/cookbook_spec.rb +0 -9
  224. data/spec/unit/cookbook_version_spec.rb +0 -20
  225. data/spec/unit/deprecation_spec.rb +55 -0
  226. data/spec/unit/dsl/resources_spec.rb +85 -0
  227. data/spec/unit/exceptions_spec.rb +2 -2
  228. data/spec/unit/file_content_management/deploy/mv_windows_spec.rb +60 -0
  229. data/spec/unit/formatters/doc_spec.rb +46 -0
  230. data/spec/unit/formatters/error_inspectors/api_error_formatting_spec.rb +12 -10
  231. data/spec/unit/guard_interpreter/resource_guard_interpreter_spec.rb +8 -0
  232. data/spec/unit/http/authenticator_spec.rb +11 -2
  233. data/spec/unit/knife/client_create_spec.rb +122 -51
  234. data/spec/unit/knife/core/subcommand_loader_spec.rb +19 -3
  235. data/spec/unit/knife/core/ui_spec.rb +14 -0
  236. data/spec/unit/knife/osc_user_create_spec.rb +93 -0
  237. data/spec/unit/knife/osc_user_delete_spec.rb +44 -0
  238. data/spec/unit/knife/osc_user_edit_spec.rb +52 -0
  239. data/spec/unit/knife/osc_user_list_spec.rb +37 -0
  240. data/spec/unit/knife/osc_user_reregister_spec.rb +58 -0
  241. data/spec/unit/knife/osc_user_show_spec.rb +46 -0
  242. data/spec/unit/knife/user_create_spec.rb +177 -51
  243. data/spec/unit/knife/user_delete_spec.rb +34 -8
  244. data/spec/unit/knife/user_edit_spec.rb +31 -12
  245. data/spec/unit/knife/user_list_spec.rb +7 -3
  246. data/spec/unit/knife/user_reregister_spec.rb +38 -17
  247. data/spec/unit/knife/user_show_spec.rb +35 -11
  248. data/spec/unit/knife_spec.rb +10 -4
  249. data/spec/unit/lwrp_spec.rb +228 -54
  250. data/spec/unit/mixin/api_version_request_handling_spec.rb +127 -0
  251. data/spec/unit/mixin/command_spec.rb +1 -2
  252. data/spec/unit/mixin/powershell_out_spec.rb +70 -0
  253. data/spec/unit/mixin/uris_spec.rb +23 -11
  254. data/spec/unit/node_map_spec.rb +4 -1
  255. data/spec/unit/osc_user_spec.rb +276 -0
  256. data/spec/unit/platform_spec.rb +0 -60
  257. data/spec/unit/provider/deploy_spec.rb +1 -1
  258. data/spec/unit/provider/directory_spec.rb +199 -135
  259. data/spec/unit/provider/ifconfig/debian_spec.rb +0 -10
  260. data/spec/unit/provider/package/aix_spec.rb +16 -16
  261. data/spec/unit/provider/package/dpkg_spec.rb +2 -2
  262. data/spec/unit/provider/package/freebsd/pkg_spec.rb +13 -13
  263. data/spec/unit/provider/package/freebsd/pkgng_spec.rb +9 -9
  264. data/spec/unit/provider/package/freebsd/port_spec.rb +7 -7
  265. data/spec/unit/provider/package/ips_spec.rb +22 -22
  266. data/spec/unit/provider/package/macports_spec.rb +10 -10
  267. data/spec/unit/provider/package/openbsd_spec.rb +4 -26
  268. data/spec/unit/provider/package/pacman_spec.rb +5 -5
  269. data/spec/unit/provider/package/rpm_spec.rb +14 -14
  270. data/spec/unit/provider/package/rubygems_spec.rb +10 -44
  271. data/spec/unit/provider/package/smartos_spec.rb +4 -4
  272. data/spec/unit/provider/package/solaris_spec.rb +11 -11
  273. data/spec/unit/provider/package/zypper_spec.rb +125 -90
  274. data/spec/unit/provider/package_spec.rb +34 -0
  275. data/spec/unit/provider/powershell_spec.rb +53 -11
  276. data/spec/unit/provider/remote_directory_spec.rb +2 -2
  277. data/spec/unit/provider/remote_file/local_file_spec.rb +25 -6
  278. data/spec/unit/provider/service/freebsd_service_spec.rb +0 -12
  279. data/spec/unit/provider/user_spec.rb +3 -3
  280. data/spec/unit/provider_resolver_spec.rb +463 -327
  281. data/spec/unit/recipe_spec.rb +42 -15
  282. data/spec/unit/resource/breakpoint_spec.rb +1 -1
  283. data/spec/unit/resource/erl_call_spec.rb +1 -1
  284. data/spec/unit/resource/file_spec.rb +1 -1
  285. data/spec/unit/resource/ifconfig_spec.rb +10 -6
  286. data/spec/unit/resource/remote_file_spec.rb +5 -0
  287. data/spec/unit/resource/route_spec.rb +1 -1
  288. data/spec/unit/resource/ruby_block_spec.rb +2 -2
  289. data/spec/unit/resource/template_spec.rb +1 -1
  290. data/spec/unit/resource/timestamped_deploy_spec.rb +1 -2
  291. data/spec/unit/resource/windows_service_spec.rb +1 -1
  292. data/spec/unit/resource_spec.rb +99 -13
  293. data/spec/unit/rest_spec.rb +5 -5
  294. data/spec/unit/run_context_spec.rb +41 -0
  295. data/spec/unit/runner_spec.rb +2 -2
  296. data/spec/unit/user_spec.rb +406 -93
  297. data/tasks/maintainers.rb +69 -0
  298. metadata +37 -4
@@ -16,6 +16,8 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ require 'chef/audit/logger'
20
+
19
21
  class Chef
20
22
  class Audit
21
23
  class Runner
@@ -115,8 +117,8 @@ class Chef
115
117
  # the output stream to be changed for a formatter once the formatter has
116
118
  # been added.
117
119
  def set_streams
118
- RSpec.configuration.output_stream = Chef::Config[:log_location]
119
- RSpec.configuration.error_stream = Chef::Config[:log_location]
120
+ RSpec.configuration.output_stream = Chef::Audit::Logger
121
+ RSpec.configuration.error_stream = Chef::Audit::Logger
120
122
  end
121
123
 
122
124
  # Add formatters which we use to
@@ -26,6 +26,9 @@
26
26
  # injected" into this class by other objects and do not reference the class symbols in those files
27
27
  # directly and we do not need to require those files here.
28
28
 
29
+ require 'chef/platform/provider_priority_map'
30
+ require 'chef/platform/resource_priority_map'
31
+
29
32
  class Chef
30
33
  class << self
31
34
 
@@ -33,50 +36,74 @@ class Chef
33
36
  # Public API
34
37
  #
35
38
 
39
+ #
36
40
  # Get the node object
37
41
  #
38
42
  # @return [Chef::Node] node object of the chef-client run
43
+ #
39
44
  attr_reader :node
40
45
 
46
+ #
41
47
  # Get the run context
42
48
  #
43
49
  # @return [Chef::RunContext] run_context of the chef-client run
50
+ #
44
51
  attr_reader :run_context
45
52
 
53
+ #
46
54
  # Get the array of providers associated with a resource_name for the current node
47
55
  #
48
56
  # @param resource_name [Symbol] name of the resource as a symbol
57
+ #
49
58
  # @return [Array<Class>] Priority Array of Provider Classes to use for the resource_name on the node
59
+ #
50
60
  def get_provider_priority_array(resource_name)
51
- @provider_priority_map.get_priority_array(node, resource_name).dup
61
+ result = provider_priority_map.get_priority_array(node, resource_name)
62
+ result = result.dup if result
63
+ result
52
64
  end
53
65
 
66
+ #
54
67
  # Get the array of resources associated with a resource_name for the current node
55
68
  #
56
69
  # @param resource_name [Symbol] name of the resource as a symbol
70
+ #
57
71
  # @return [Array<Class>] Priority Array of Resource Classes to use for the resource_name on the node
72
+ #
58
73
  def get_resource_priority_array(resource_name)
59
- @resource_priority_map.get_priority_array(node, resource_name).dup
74
+ result = resource_priority_map.get_priority_array(node, resource_name)
75
+ result = result.dup if result
76
+ result
60
77
  end
61
78
 
79
+ #
62
80
  # Set the array of providers associated with a resource_name for the current node
63
81
  #
64
82
  # @param resource_name [Symbol] name of the resource as a symbol
65
- # @param priority_array [Array<Class>] Array of Classes to set as the priority for resource_name on the node
83
+ # @param priority_array [Class, Array<Class>] Class or Array of Classes to set as the priority for resource_name on the node
66
84
  # @param filter [Hash] Chef::Nodearray-style filter
85
+ #
67
86
  # @return [Array<Class>] Modified Priority Array of Provider Classes to use for the resource_name on the node
68
- def set_provider_priority_array(resource_name, priority_array, *filter)
69
- @provider_priority_map.set_priority_array(resource_name, priority_array, *filter).dup
87
+ #
88
+ def set_provider_priority_array(resource_name, priority_array, *filter, &block)
89
+ result = provider_priority_map.set_priority_array(resource_name, priority_array, *filter, &block)
90
+ result = result.dup if result
91
+ result
70
92
  end
71
93
 
94
+ #
72
95
  # Get the array of resources associated with a resource_name for the current node
73
96
  #
74
97
  # @param resource_name [Symbol] name of the resource as a symbol
75
- # @param priority_array [Array<Class>] Array of Classes to set as the priority for resource_name on the node
98
+ # @param priority_array [Class, Array<Class>] Class or Array of Classes to set as the priority for resource_name on the node
76
99
  # @param filter [Hash] Chef::Nodearray-style filter
100
+ #
77
101
  # @return [Array<Class>] Modified Priority Array of Resource Classes to use for the resource_name on the node
78
- def set_resource_priority_array(resource_name, priority_array, *filter)
79
- @resource_priority_map.set_priority_array(resource_name, priority_array, *filter).dup
102
+ #
103
+ def set_resource_priority_array(resource_name, priority_array, *filter, &block)
104
+ result = resource_priority_map.set_priority_array(resource_name, priority_array, *filter, &block)
105
+ result = result.dup if result
106
+ result
80
107
  end
81
108
 
82
109
  #
@@ -85,22 +112,27 @@ class Chef
85
112
  # *NOT* for public consumption ]
86
113
  #
87
114
 
115
+ #
88
116
  # Sets the resource_priority_map
89
117
  #
90
- # @api private
91
118
  # @param resource_priority_map [Chef::Platform::ResourcePriorityMap]
119
+ #
120
+ # @api private
92
121
  def set_resource_priority_map(resource_priority_map)
93
122
  @resource_priority_map = resource_priority_map
94
123
  end
95
124
 
125
+ #
96
126
  # Sets the provider_priority_map
97
127
  #
98
- # @api private
99
128
  # @param provider_priority_map [Chef::Platform::providerPriorityMap]
129
+ #
130
+ # @api private
100
131
  def set_provider_priority_map(provider_priority_map)
101
132
  @provider_priority_map = provider_priority_map
102
133
  end
103
134
 
135
+ #
104
136
  # Sets the node object
105
137
  #
106
138
  # @api private
@@ -109,14 +141,17 @@ class Chef
109
141
  @node = node
110
142
  end
111
143
 
144
+ #
112
145
  # Sets the run_context object
113
146
  #
114
- # @api private
115
147
  # @param run_context [Chef::RunContext]
148
+ #
149
+ # @api private
116
150
  def set_run_context(run_context)
117
151
  @run_context = run_context
118
152
  end
119
153
 
154
+ #
120
155
  # Resets the internal state
121
156
  #
122
157
  # @api private
@@ -126,5 +161,21 @@ class Chef
126
161
  @provider_priority_map = nil
127
162
  @resource_priority_map = nil
128
163
  end
164
+
165
+ # @api private
166
+ def provider_priority_map
167
+ @provider_priority_map ||= begin
168
+ # these slurp in the resource+provider world, so be exceedingly lazy about requiring them
169
+ Chef::Platform::ProviderPriorityMap.instance
170
+ end
171
+ end
172
+ # @api private
173
+ def resource_priority_map
174
+ @resource_priority_map ||= begin
175
+ Chef::Platform::ResourcePriorityMap.instance
176
+ end
177
+ end
129
178
  end
179
+
180
+ reset!
130
181
  end
@@ -50,6 +50,7 @@ require 'chef/run_lock'
50
50
  require 'chef/policy_builder'
51
51
  require 'chef/request_id'
52
52
  require 'chef/platform/rebooter'
53
+ require 'chef/mixin/deprecation'
53
54
  require 'ohai'
54
55
  require 'rbconfig'
55
56
 
@@ -60,121 +61,273 @@ class Chef
60
61
  class Client
61
62
  include Chef::Mixin::PathSanity
62
63
 
63
- # IO stream that will be used as 'STDOUT' for formatters. Formatters are
64
- # configured during `initialize`, so this provides a convenience for
65
- # setting alternative IO stream during tests.
66
- STDOUT_FD = STDOUT
67
-
68
- # IO stream that will be used as 'STDERR' for formatters. Formatters are
69
- # configured during `initialize`, so this provides a convenience for
70
- # setting alternative IO stream during tests.
71
- STDERR_FD = STDERR
64
+ extend Chef::Mixin::Deprecation
72
65
 
73
- # Clears all notifications for client run status events.
74
- # Primarily for testing purposes.
75
- def self.clear_notifications
76
- @run_start_notifications = nil
77
- @run_completed_successfully_notifications = nil
78
- @run_failed_notifications = nil
79
- end
80
-
81
- # The list of notifications to be run when the client run starts.
82
- def self.run_start_notifications
83
- @run_start_notifications ||= []
84
- end
85
-
86
- # The list of notifications to be run when the client run completes
87
- # successfully.
88
- def self.run_completed_successfully_notifications
89
- @run_completed_successfully_notifications ||= []
90
- end
91
-
92
- # The list of notifications to be run when the client run fails.
93
- def self.run_failed_notifications
94
- @run_failed_notifications ||= []
95
- end
96
-
97
- # Add a notification for the 'client run started' event. The notification
98
- # is provided as a block. The current Chef::RunStatus object will be passed
99
- # to the notification_block when the event is triggered.
100
- def self.when_run_starts(&notification_block)
101
- run_start_notifications << notification_block
102
- end
103
-
104
- # Add a notification for the 'client run success' event. The notification
105
- # is provided as a block. The current Chef::RunStatus object will be passed
106
- # to the notification_block when the event is triggered.
107
- def self.when_run_completes_successfully(&notification_block)
108
- run_completed_successfully_notifications << notification_block
109
- end
66
+ #
67
+ # The status of the Chef run.
68
+ #
69
+ # @return [Chef::RunStatus]
70
+ #
71
+ attr_reader :run_status
110
72
 
111
- # Add a notification for the 'client run failed' event. The notification
112
- # is provided as a block. The current Chef::RunStatus is passed to the
113
- # notification_block when the event is triggered.
114
- def self.when_run_fails(&notification_block)
115
- run_failed_notifications << notification_block
73
+ #
74
+ # The node represented by this client.
75
+ #
76
+ # @return [Chef::Node]
77
+ #
78
+ def node
79
+ run_status.node
116
80
  end
117
-
118
- # Callback to fire notifications that the Chef run is starting
119
- def run_started
120
- self.class.run_start_notifications.each do |notification|
121
- notification.call(run_status)
122
- end
123
- @events.run_started(run_status)
81
+ def node=(value)
82
+ run_status.node = value
124
83
  end
125
84
 
126
- # Callback to fire notifications that the run completed successfully
127
- def run_completed_successfully
128
- success_handlers = self.class.run_completed_successfully_notifications
129
- success_handlers.each do |notification|
130
- notification.call(run_status)
131
- end
132
- end
85
+ #
86
+ # The ohai system used by this client.
87
+ #
88
+ # @return [Ohai::System]
89
+ #
90
+ attr_reader :ohai
133
91
 
134
- # Callback to fire notifications that the Chef run failed
135
- def run_failed
136
- failure_handlers = self.class.run_failed_notifications
137
- failure_handlers.each do |notification|
138
- notification.call(run_status)
139
- end
140
- end
92
+ #
93
+ # The rest object used to communicate with the Chef server.
94
+ #
95
+ # @return [Chef::REST]
96
+ #
97
+ attr_reader :rest
141
98
 
142
- attr_accessor :node
143
- attr_accessor :ohai
144
- attr_accessor :rest
99
+ #
100
+ # The runner used to converge.
101
+ #
102
+ # @return [Chef::Runner]
103
+ #
145
104
  attr_accessor :runner
146
105
 
106
+ #
107
+ # Extra node attributes that were applied to the node.
108
+ #
109
+ # @return [Hash]
110
+ #
147
111
  attr_reader :json_attribs
148
- attr_reader :run_status
112
+
113
+ #
114
+ # The event dispatcher for the Chef run, including any configured output
115
+ # formatters and event loggers.
116
+ #
117
+ # @return [EventDispatch::Dispatcher]
118
+ #
119
+ # @see Chef::Formatters
120
+ # @see Chef::Config#formatters
121
+ # @see Chef::Config#stdout
122
+ # @see Chef::Config#stderr
123
+ # @see Chef::Config#force_logger
124
+ # @see Chef::Config#force_formatter
125
+ # TODO add stdout, stderr, and default formatters to Chef::Config so the
126
+ # defaults aren't calculated here. Remove force_logger and force_formatter
127
+ # from this code.
128
+ # @see Chef::EventLoggers
129
+ # @see Chef::Config#disable_event_logger
130
+ # @see Chef::Config#event_loggers
131
+ # @see Chef::Config#event_handlers
132
+ #
149
133
  attr_reader :events
150
134
 
135
+ #
151
136
  # Creates a new Chef::Client.
137
+ #
138
+ # @param json_attribs [Hash] Node attributes to layer into the node when it is
139
+ # fetched.
140
+ # @param args [Hash] Options:
141
+ # @option args [Array<RunList::RunListItem>] :override_runlist A runlist to
142
+ # use instead of the node's embedded run list.
143
+ # @option args [Array<String>] :specific_recipes A list of recipe file paths
144
+ # to load after the run list has been loaded.
145
+ #
152
146
  def initialize(json_attribs=nil, args={})
153
147
  @json_attribs = json_attribs || {}
154
- @node = nil
155
- @runner = nil
156
148
  @ohai = Ohai::System.new
157
149
 
158
150
  event_handlers = configure_formatters + configure_event_loggers
159
151
  event_handlers += Array(Chef::Config[:event_handlers])
160
152
 
161
153
  @events = EventDispatch::Dispatcher.new(*event_handlers)
154
+ # TODO it seems like a bad idea to be deletin' other peoples' hashes.
162
155
  @override_runlist = args.delete(:override_runlist)
163
156
  @specific_recipes = args.delete(:specific_recipes)
164
- @run_status = Chef::RunStatus.new(node, events)
157
+ @run_status = Chef::RunStatus.new(nil, events)
165
158
 
166
159
  if new_runlist = args.delete(:runlist)
167
160
  @json_attribs["run_list"] = new_runlist
168
161
  end
162
+ end
169
163
 
170
- # these slurp in the resource+provider world, so be exceedingly lazy about requiring them
171
- require 'chef/platform/provider_priority_map' unless defined? Chef::Platform::ProviderPriorityMap
172
- require 'chef/platform/resource_priority_map' unless defined? Chef::Platform::ResourcePriorityMap
164
+ #
165
+ # Do a full run for this Chef::Client.
166
+ #
167
+ # Locks the run while doing its job.
168
+ #
169
+ # Fires run_start before doing anything and fires run_completed or
170
+ # run_failed when finished. Also notifies client listeners of run_started
171
+ # at the beginning of Compile, and run_completed_successfully or run_failed
172
+ # when all is complete.
173
+ #
174
+ # Phase 1: Setup
175
+ # --------------
176
+ # Gets information about the system and the run we are doing.
177
+ #
178
+ # 1. Run ohai to collect system information.
179
+ # 2. Register / connect to the Chef server (unless in solo mode).
180
+ # 3. Retrieve the node (or create a new one).
181
+ # 4. Merge in json_attribs, Chef::Config.environment, and override_run_list.
182
+ #
183
+ # @see #run_ohai
184
+ # @see #load_node
185
+ # @see #build_node
186
+ # @see Chef::Config#lockfile
187
+ # @see Chef::RunLock#acquire
188
+ #
189
+ # Phase 2: Compile
190
+ # ----------------
191
+ # Decides *what* we plan to converge by compiling recipes.
192
+ #
193
+ # 1. Sync required cookbooks to the local cache.
194
+ # 2. Load libraries from all cookbooks.
195
+ # 3. Load attributes from all cookbooks.
196
+ # 4. Load LWRPs from all cookbooks.
197
+ # 5. Load resource definitions from all cookbooks.
198
+ # 6. Load recipes in the run list.
199
+ # 7. Load recipes from the command line.
200
+ #
201
+ # @see #setup_run_context Syncs and compiles cookbooks.
202
+ # @see Chef::CookbookCompiler#compile
203
+ #
204
+ # Phase 3: Converge
205
+ # -----------------
206
+ # Brings the system up to date.
207
+ #
208
+ # 1. Converge the resources built from recipes in Phase 2.
209
+ # 2. Save the node.
210
+ # 3. Reboot if we were asked to.
211
+ #
212
+ # @see #converge_and_save
213
+ # @see Chef::Runner
214
+ #
215
+ # Phase 4: Audit
216
+ # --------------
217
+ # Runs 'control_group' audits in recipes. This entire section can be enabled or disabled with config.
218
+ #
219
+ # 1. 'control_group' DSL collects audits during Phase 2
220
+ # 2. Audits are run using RSpec
221
+ # 3. Errors are collected and reported using the formatters
222
+ #
223
+ # @see #run_audits
224
+ # @see Chef::Audit::Runner#run
225
+ #
226
+ # @raise [Chef::Exceptions::RunFailedWrappingError] If converge or audit failed.
227
+ #
228
+ # @see Chef::Config#enforce_path_sanity
229
+ # @see Chef::Config#solo
230
+ # @see Chef::Config#audit_mode
231
+ #
232
+ # @return Always returns true.
233
+ #
234
+ def run
235
+ run_error = nil
173
236
 
174
- Chef.set_provider_priority_map(Chef::Platform::ProviderPriorityMap.instance)
175
- Chef.set_resource_priority_map(Chef::Platform::ResourcePriorityMap.instance)
237
+ runlock = RunLock.new(Chef::Config.lockfile)
238
+ # TODO feels like acquire should have its own block arg for this
239
+ runlock.acquire
240
+ # don't add code that may fail before entering this section to be sure to release lock
241
+ begin
242
+ runlock.save_pid
243
+
244
+ request_id = Chef::RequestID.instance.request_id
245
+ run_context = nil
246
+ events.run_start(Chef::VERSION)
247
+ Chef::Log.info("*** Chef #{Chef::VERSION} ***")
248
+ Chef::Log.info "Chef-client pid: #{Process.pid}"
249
+ Chef::Log.debug("Chef-client request_id: #{request_id}")
250
+ enforce_path_sanity
251
+ run_ohai
252
+
253
+ register unless Chef::Config[:solo]
254
+
255
+ load_node
256
+
257
+ build_node
258
+
259
+ run_status.run_id = request_id
260
+ run_status.start_clock
261
+ Chef::Log.info("Starting Chef Run for #{node.name}")
262
+ run_started
263
+
264
+ do_windows_admin_check
265
+
266
+ run_context = setup_run_context
267
+
268
+ if Chef::Config[:audit_mode] != :audit_only
269
+ converge_error = converge_and_save(run_context)
270
+ end
271
+
272
+ if Chef::Config[:why_run] == true
273
+ # why_run should probably be renamed to why_converge
274
+ Chef::Log.debug("Not running controls in 'why_run' mode - this mode is used to see potential converge changes")
275
+ elsif Chef::Config[:audit_mode] != :disabled
276
+ audit_error = run_audits(run_context)
277
+ end
278
+
279
+ # Raise converge_error so run_failed reporters/events are processed.
280
+ raise converge_error if converge_error
281
+
282
+ run_status.stop_clock
283
+ Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds")
284
+ run_completed_successfully
285
+ events.run_completed(node)
286
+
287
+ # rebooting has to be the last thing we do, no exceptions.
288
+ Chef::Platform::Rebooter.reboot_if_needed!(node)
289
+ rescue Exception => run_error
290
+ # CHEF-3336: Send the error first in case something goes wrong below and we don't know why
291
+ Chef::Log.debug("Re-raising exception: #{run_error.class} - #{run_error.message}\n#{run_error.backtrace.join("\n ")}")
292
+ # If we failed really early, we may not have a run_status yet. Too early for these to be of much use.
293
+ if run_status
294
+ run_status.stop_clock
295
+ run_status.exception = run_error
296
+ run_failed
297
+ end
298
+ events.run_failed(run_error)
299
+ ensure
300
+ Chef::RequestID.instance.reset_request_id
301
+ request_id = nil
302
+ @run_status = nil
303
+ run_context = nil
304
+ runlock.release
305
+ GC.start
306
+ end
307
+
308
+ # Raise audit, converge, and other errors here so that we exit
309
+ # with the proper exit status code and everything gets raised
310
+ # as a RunFailedWrappingError
311
+ if run_error || converge_error || audit_error
312
+ error = if run_error == converge_error
313
+ Chef::Exceptions::RunFailedWrappingError.new(converge_error, audit_error)
314
+ else
315
+ Chef::Exceptions::RunFailedWrappingError.new(run_error, converge_error, audit_error)
316
+ end
317
+ error.fill_backtrace
318
+ Chef::Application.debug_stacktrace(error)
319
+ raise error
320
+ end
321
+
322
+ true
176
323
  end
177
324
 
325
+ #
326
+ # Private API
327
+ # TODO make this stuff protected or private
328
+ #
329
+
330
+ # @api private
178
331
  def configure_formatters
179
332
  formatters_for_run.map do |formatter_name, output_path|
180
333
  if output_path.nil?
@@ -187,6 +340,7 @@ class Chef
187
340
  end
188
341
  end
189
342
 
343
+ # @api private
190
344
  def formatters_for_run
191
345
  if Chef::Config.formatters.empty?
192
346
  [default_formatter]
@@ -195,6 +349,7 @@ class Chef
195
349
  end
196
350
  end
197
351
 
352
+ # @api private
198
353
  def default_formatter
199
354
  if (STDOUT.tty? && !Chef::Config[:force_logger]) || Chef::Config[:force_formatter]
200
355
  [:doc]
@@ -203,6 +358,7 @@ class Chef
203
358
  end
204
359
  end
205
360
 
361
+ # @api private
206
362
  def configure_event_loggers
207
363
  if Chef::Config.disable_event_logger
208
364
  []
@@ -219,8 +375,9 @@ class Chef
219
375
  end
220
376
  end
221
377
 
222
- # Resource repoters send event information back to the chef server for processing.
223
- # Can only be called after we have a @rest object
378
+ # Resource reporters send event information back to the chef server for
379
+ # processing. Can only be called after we have a @rest object
380
+ # @api private
224
381
  def register_reporters
225
382
  [
226
383
  Chef::ResourceReporter.new(rest),
@@ -230,43 +387,123 @@ class Chef
230
387
  end
231
388
  end
232
389
 
390
+ #
391
+ # Callback to fire notifications that the Chef run is starting
392
+ #
393
+ # @api private
394
+ #
395
+ def run_started
396
+ self.class.run_start_notifications.each do |notification|
397
+ notification.call(run_status)
398
+ end
399
+ events.run_started(run_status)
400
+ end
401
+
402
+ #
403
+ # Callback to fire notifications that the run completed successfully
404
+ #
405
+ # @api private
406
+ #
407
+ def run_completed_successfully
408
+ success_handlers = self.class.run_completed_successfully_notifications
409
+ success_handlers.each do |notification|
410
+ notification.call(run_status)
411
+ end
412
+ end
413
+
414
+ #
415
+ # Callback to fire notifications that the Chef run failed
416
+ #
417
+ # @api private
418
+ #
419
+ def run_failed
420
+ failure_handlers = self.class.run_failed_notifications
421
+ failure_handlers.each do |notification|
422
+ notification.call(run_status)
423
+ end
424
+ end
425
+
426
+ #
233
427
  # Instantiates a Chef::Node object, possibly loading the node's prior state
234
- # when using chef-client. Delegates to policy_builder. Injects the built node
235
- # into the Chef class.
428
+ # when using chef-client. Sets Chef.node to the new node.
236
429
  #
237
430
  # @return [Chef::Node] The node object for this Chef run
431
+ #
432
+ # @see Chef::PolicyBuilder#load_node
433
+ #
434
+ # @api private
435
+ #
238
436
  def load_node
239
437
  policy_builder.load_node
240
- @node = policy_builder.node
241
- Chef.set_node(@node)
438
+ run_status.node = policy_builder.node
439
+ Chef.set_node(policy_builder.node)
242
440
  node
243
441
  end
244
442
 
245
- # Mutates the `node` object to prepare it for the chef run. Delegates to
246
- # policy_builder
443
+ #
444
+ # Mutates the `node` object to prepare it for the chef run.
247
445
  #
248
446
  # @return [Chef::Node] The updated node object
447
+ #
448
+ # @see Chef::PolicyBuilder#build_node
449
+ #
450
+ # @api private
451
+ #
249
452
  def build_node
250
453
  policy_builder.build_node
251
- @run_status.node = node
454
+ run_status.node = node
252
455
  node
253
456
  end
254
457
 
458
+ #
459
+ # Sync cookbooks to local cache.
460
+ #
461
+ # TODO this appears to be unused.
462
+ #
463
+ # @see Chef::PolicyBuilder#sync_cookbooks
464
+ #
465
+ # @api private
466
+ #
467
+ def sync_cookbooks
468
+ policy_builder.sync_cookbooks
469
+ end
470
+
471
+ #
472
+ # Sets up the run context.
473
+ #
474
+ # @see Chef::PolicyBuilder#setup_run_context
475
+ #
476
+ # @return The newly set up run context
477
+ #
478
+ # @api private
255
479
  def setup_run_context
256
- run_context = policy_builder.setup_run_context(@specific_recipes)
480
+ run_context = policy_builder.setup_run_context(specific_recipes)
257
481
  assert_cookbook_path_not_empty(run_context)
258
482
  run_status.run_context = run_context
259
483
  run_context
260
484
  end
261
485
 
262
- def sync_cookbooks
263
- policy_builder.sync_cookbooks
264
- end
265
-
486
+ #
487
+ # The PolicyBuilder strategy for figuring out run list and cookbooks.
488
+ #
489
+ # @return [Chef::PolicyBuilder::Policyfile, Chef::PolicyBuilder::ExpandNodeObject]
490
+ #
491
+ # @api private
492
+ #
266
493
  def policy_builder
267
- @policy_builder ||= Chef::PolicyBuilder.strategy.new(node_name, ohai.data, json_attribs, @override_runlist, events)
494
+ @policy_builder ||= Chef::PolicyBuilder.strategy.new(node_name, ohai.data, json_attribs, override_runlist, events)
268
495
  end
269
496
 
497
+ #
498
+ # Save the updated node to Chef.
499
+ #
500
+ # Does not save if we are in solo mode or using override_runlist.
501
+ #
502
+ # @see Chef::Node#save
503
+ # @see Chef::Config#solo
504
+ #
505
+ # @api private
506
+ #
270
507
  def save_updated_node
271
508
  if Chef::Config[:solo]
272
509
  # nothing to do
@@ -274,16 +511,46 @@ class Chef
274
511
  Chef::Log.warn("Skipping final node save because override_runlist was given")
275
512
  else
276
513
  Chef::Log.debug("Saving the current state of node #{node_name}")
277
- @node.save
514
+ node.save
278
515
  end
279
516
  end
280
517
 
518
+ #
519
+ # Run ohai plugins. Runs all ohai plugins unless minimal_ohai is specified.
520
+ #
521
+ # Sends the ohai_completed event when finished.
522
+ #
523
+ # @see Chef::EventDispatcher#
524
+ # @see Chef::Config#minimal_ohai
525
+ #
526
+ # @api private
527
+ #
281
528
  def run_ohai
282
529
  filter = Chef::Config[:minimal_ohai] ? %w[fqdn machinename hostname platform platform_version os os_version] : nil
283
530
  ohai.all_plugins(filter)
284
- @events.ohai_completed(node)
531
+ events.ohai_completed(node)
285
532
  end
286
533
 
534
+ #
535
+ # Figure out the node name we are working with.
536
+ #
537
+ # It tries these, in order:
538
+ # - Chef::Config.node_name
539
+ # - ohai[:fqdn]
540
+ # - ohai[:machinename]
541
+ # - ohai[:hostname]
542
+ #
543
+ # If we are running against a server with authentication protocol < 1.0, we
544
+ # *require* authentication protocol version 1.1.
545
+ #
546
+ # @raise [Chef::Exceptions::CannotDetermineNodeName] If the node name is not
547
+ # set and cannot be determined via ohai.
548
+ #
549
+ # @see Chef::Config#node_name
550
+ # @see Chef::Config#authentication_protocol_version
551
+ #
552
+ # @api private
553
+ #
287
554
  def node_name
288
555
  name = Chef::Config[:node_name] || ohai[:fqdn] || ohai[:machinename] || ohai[:hostname]
289
556
  Chef::Config[:node_name] = name
@@ -292,6 +559,8 @@ class Chef
292
559
 
293
560
  # node names > 90 bytes only work with authentication protocol >= 1.1
294
561
  # see discussion in config.rb.
562
+ # TODO use a computed default in Chef::Config to determine this instead of
563
+ # setting it.
295
564
  if name.bytesize > 90
296
565
  Chef::Config[:authentication_protocol_version] = "1.1"
297
566
  end
@@ -300,46 +569,86 @@ class Chef
300
569
  end
301
570
 
302
571
  #
303
- # === Returns
304
- # rest<Chef::REST>:: returns Chef::REST connection object
572
+ # Determine our private key and set up the connection to the Chef server.
573
+ #
574
+ # Skips registration and fires the `skipping_registration` event if
575
+ # Chef::Config.client_key is unspecified or already exists.
576
+ #
577
+ # If Chef::Config.client_key does not exist, we register the client with the
578
+ # Chef server and fire the registration_start and registration_completed events.
579
+ #
580
+ # @return [Chef::REST] The server connection object.
581
+ #
582
+ # @see Chef::Config#chef_server_url
583
+ # @see Chef::Config#client_key
584
+ # @see Chef::ApiClient::Registration#run
585
+ # @see Chef::EventDispatcher#skipping_registration
586
+ # @see Chef::EventDispatcher#registration_start
587
+ # @see Chef::EventDispatcher#registration_completed
588
+ # @see Chef::EventDispatcher#registration_failed
589
+ #
590
+ # @api private
591
+ #
305
592
  def register(client_name=node_name, config=Chef::Config)
306
593
  if !config[:client_key]
307
- @events.skipping_registration(client_name, config)
594
+ events.skipping_registration(client_name, config)
308
595
  Chef::Log.debug("Client key is unspecified - skipping registration")
309
596
  elsif File.exists?(config[:client_key])
310
- @events.skipping_registration(client_name, config)
597
+ events.skipping_registration(client_name, config)
311
598
  Chef::Log.debug("Client key #{config[:client_key]} is present - skipping registration")
312
599
  else
313
- @events.registration_start(node_name, config)
600
+ events.registration_start(node_name, config)
314
601
  Chef::Log.info("Client key #{config[:client_key]} is not present - registering")
315
602
  Chef::ApiClient::Registration.new(node_name, config[:client_key]).run
316
- @events.registration_completed
603
+ events.registration_completed
317
604
  end
318
605
  # We now have the client key, and should use it from now on.
319
606
  @rest = Chef::REST.new(config[:chef_server_url], client_name, config[:client_key])
320
607
  register_reporters
321
608
  rescue Exception => e
609
+ # TODO this should probably only ever fire if we *started* registration.
610
+ # Move it to the block above.
322
611
  # TODO: munge exception so a semantic failure message can be given to the
323
612
  # user
324
- @events.registration_failed(client_name, e, config)
613
+ events.registration_failed(client_name, e, config)
325
614
  raise
326
615
  end
327
616
 
328
- # Converges the node.
329
617
  #
330
- # === Returns
331
- # The thrown exception, if there was one. If this returns nil the converge was successful.
618
+ # Converges all compiled resources.
619
+ #
620
+ # Fires the converge_start, converge_complete and converge_failed events.
621
+ #
622
+ # If the exception `:end_client_run_early` is thrown during convergence, it
623
+ # does not mark the run complete *or* failed, and returns `nil`
624
+ #
625
+ # @param run_context The run context.
626
+ #
627
+ # @return The thrown exception, if we are in audit mode. `nil` means the
628
+ # converge was successful or ended early.
629
+ #
630
+ # @raise Any converge exception, unless we are in audit mode, in which case
631
+ # we *return* the exception.
632
+ #
633
+ # @see Chef::Runner#converge
634
+ # @see Chef::Config#audit_mode
635
+ # @see Chef::EventDispatch#converge_start
636
+ # @see Chef::EventDispatch#converge_complete
637
+ # @see Chef::EventDispatch#converge_failed
638
+ #
639
+ # @api private
640
+ #
332
641
  def converge(run_context)
333
642
  converge_exception = nil
334
643
  catch(:end_client_run_early) do
335
644
  begin
336
- @events.converge_start(run_context)
645
+ events.converge_start(run_context)
337
646
  Chef::Log.debug("Converging node #{node_name}")
338
647
  @runner = Chef::Runner.new(run_context)
339
- runner.converge
340
- @events.converge_complete
648
+ @runner.converge
649
+ events.converge_complete
341
650
  rescue Exception => e
342
- @events.converge_failed(e)
651
+ events.converge_failed(e)
343
652
  raise e if Chef::Config[:audit_mode] == :disabled
344
653
  converge_exception = e
345
654
  end
@@ -347,8 +656,28 @@ class Chef
347
656
  converge_exception
348
657
  end
349
658
 
659
+ #
660
+ # Converge the node via and then save it if successful.
661
+ #
662
+ # @param run_context The run context.
663
+ #
664
+ # @return The thrown exception, if we are in audit mode. `nil` means the
665
+ # converge was successful or ended early.
666
+ #
667
+ # @raise Any converge or node save exception, unless we are in audit mode,
668
+ # in which case we *return* the exception.
669
+ #
670
+ # @see #converge
671
+ # @see #save_updated_mode
672
+ # @see Chef::Config#audit_mode
673
+ #
674
+ # @api private
675
+ #
350
676
  # We don't want to change the old API on the `converge` method to have it perform
351
677
  # saving. So we wrap it in this method.
678
+ # TODO given this seems to be pretty internal stuff, how badly do we need to
679
+ # split this stuff up?
680
+ #
352
681
  def converge_and_save(run_context)
353
682
  converge_exception = converge(run_context)
354
683
  unless converge_exception
@@ -362,37 +691,67 @@ class Chef
362
691
  converge_exception
363
692
  end
364
693
 
694
+ #
695
+ # Run the audit phase.
696
+ #
697
+ # Triggers the audit_phase_start, audit_phase_complete and
698
+ # audit_phase_failed events.
699
+ #
700
+ # @param run_context The run context.
701
+ #
702
+ # @return Any thrown exceptions. `nil` if successful.
703
+ #
704
+ # @see Chef::Audit::Runner#run
705
+ # @see Chef::EventDispatch#audit_phase_start
706
+ # @see Chef::EventDispatch#audit_phase_complete
707
+ # @see Chef::EventDispatch#audit_phase_failed
708
+ #
709
+ # @api private
710
+ #
365
711
  def run_audits(run_context)
366
- audit_exception = nil
367
712
  begin
368
- @events.audit_phase_start(run_status)
713
+ events.audit_phase_start(run_status)
369
714
  Chef::Log.info("Starting audit phase")
370
715
  auditor = Chef::Audit::Runner.new(run_context)
371
716
  auditor.run
372
717
  if auditor.failed?
373
- raise Chef::Exceptions::AuditsFailed.new(auditor.num_failed, auditor.num_total)
718
+ audit_exception = Chef::Exceptions::AuditsFailed.new(auditor.num_failed, auditor.num_total)
719
+ @events.audit_phase_failed(audit_exception, Chef::Audit::Logger.read_buffer)
720
+ else
721
+ @events.audit_phase_complete(Chef::Audit::Logger.read_buffer)
374
722
  end
375
- @events.audit_phase_complete
376
723
  rescue Exception => e
377
724
  Chef::Log.error("Audit phase failed with error message: #{e.message}")
378
- @events.audit_phase_failed(e)
725
+ @events.audit_phase_failed(e, Chef::Audit::Logger.read_buffer)
379
726
  audit_exception = e
380
727
  end
381
728
  audit_exception
382
729
  end
383
730
 
384
- # Expands the run list. Delegates to the policy_builder.
385
731
  #
386
- # Normally this does not need to be called from here, it will be called by
387
- # build_node. This is provided so external users (like the chefspec
388
- # project) can inject custom behavior into the run process.
732
+ # Expands the run list.
733
+ #
734
+ # @return [Chef::RunListExpansion] The expanded run list.
735
+ #
736
+ # @see Chef::PolicyBuilder#expand_run_list
389
737
  #
390
- # === Returns
391
- # RunListExpansion: A RunListExpansion or API compatible object.
392
738
  def expanded_run_list
393
739
  policy_builder.expand_run_list
394
740
  end
395
741
 
742
+ #
743
+ # Check if the user has Administrator privileges on windows.
744
+ #
745
+ # Throws an error if the user is not an admin, and
746
+ # `Chef::Config.fatal_windows_admin_check` is true.
747
+ #
748
+ # @raise [Chef::Exceptions::WindowsNotAdmin] If the user is not an admin.
749
+ #
750
+ # @see Chef::platform#windows?
751
+ # @see Chef::Config#fatal_windows_admin_check
752
+ #
753
+ # @api private
754
+ #
396
755
  def do_windows_admin_check
397
756
  if Chef::Platform.windows?
398
757
  Chef::Log.debug("Checking for administrator privileges....")
@@ -412,99 +771,121 @@ class Chef
412
771
  end
413
772
  end
414
773
 
415
- # Do a full run for this Chef::Client. Calls:
416
- #
417
- # * run_ohai - Collect information about the system
418
- # * build_node - Get the last known state, merge with local changes
419
- # * register - If not in solo mode, make sure the server knows about this client
420
- # * sync_cookbooks - If not in solo mode, populate the local cache with the node's cookbooks
421
- # * converge - Bring this system up to date
422
- #
423
- # === Returns
424
- # true:: Always returns true.
425
- def run
426
- runlock = RunLock.new(Chef::Config.lockfile)
427
- runlock.acquire
428
- # don't add code that may fail before entering this section to be sure to release lock
429
- begin
430
- runlock.save_pid
431
-
432
- request_id = Chef::RequestID.instance.request_id
433
- run_context = nil
434
- @events.run_start(Chef::VERSION)
435
- Chef::Log.info("*** Chef #{Chef::VERSION} ***")
436
- Chef::Log.info "Chef-client pid: #{Process.pid}"
437
- Chef::Log.debug("Chef-client request_id: #{request_id}")
438
- enforce_path_sanity
439
- run_ohai
440
-
441
- register unless Chef::Config[:solo]
442
-
443
- load_node
444
-
445
- build_node
774
+ # Notification registration
775
+ class<<self
776
+ #
777
+ # Add a listener for the 'client run started' event.
778
+ #
779
+ # @param notification_block The callback (takes |run_status| parameter).
780
+ # @yieldparam [Chef::RunStatus] run_status The run status.
781
+ #
782
+ def when_run_starts(&notification_block)
783
+ run_start_notifications << notification_block
784
+ end
446
785
 
447
- run_status.run_id = request_id
448
- run_status.start_clock
449
- Chef::Log.info("Starting Chef Run for #{node.name}")
450
- run_started
786
+ #
787
+ # Add a listener for the 'client run success' event.
788
+ #
789
+ # @param notification_block The callback (takes |run_status| parameter).
790
+ # @yieldparam [Chef::RunStatus] run_status The run status.
791
+ #
792
+ def when_run_completes_successfully(&notification_block)
793
+ run_completed_successfully_notifications << notification_block
794
+ end
451
795
 
452
- do_windows_admin_check
796
+ #
797
+ # Add a listener for the 'client run failed' event.
798
+ #
799
+ # @param notification_block The callback (takes |run_status| parameter).
800
+ # @yieldparam [Chef::RunStatus] run_status The run status.
801
+ #
802
+ def when_run_fails(&notification_block)
803
+ run_failed_notifications << notification_block
804
+ end
453
805
 
454
- run_context = setup_run_context
806
+ #
807
+ # Clears all listeners for client run status events.
808
+ #
809
+ # Primarily for testing purposes.
810
+ #
811
+ # @api private
812
+ #
813
+ def clear_notifications
814
+ @run_start_notifications = nil
815
+ @run_completed_successfully_notifications = nil
816
+ @run_failed_notifications = nil
817
+ end
455
818
 
456
- if Chef::Config[:audit_mode] != :audit_only
457
- converge_error = converge_and_save(run_context)
458
- end
819
+ #
820
+ # TODO These seem protected to me.
821
+ #
822
+
823
+ #
824
+ # Listeners to be run when the client run starts.
825
+ #
826
+ # @return [Array<Proc>]
827
+ #
828
+ # @api private
829
+ #
830
+ def run_start_notifications
831
+ @run_start_notifications ||= []
832
+ end
459
833
 
460
- if Chef::Config[:why_run] == true
461
- # why_run should probably be renamed to why_converge
462
- Chef::Log.debug("Not running controls in 'why_run' mode - this mode is used to see potential converge changes")
463
- elsif Chef::Config[:audit_mode] != :disabled
464
- audit_error = run_audits(run_context)
465
- end
834
+ #
835
+ # Listeners to be run when the client run completes successfully.
836
+ #
837
+ # @return [Array<Proc>]
838
+ #
839
+ # @api private
840
+ #
841
+ def run_completed_successfully_notifications
842
+ @run_completed_successfully_notifications ||= []
843
+ end
466
844
 
467
- if converge_error || audit_error
468
- e = Chef::Exceptions::RunFailedWrappingError.new(converge_error, audit_error)
469
- e.fill_backtrace
470
- raise e
471
- end
845
+ #
846
+ # Listeners to be run when the client run fails.
847
+ #
848
+ # @return [Array<Proc>]
849
+ #
850
+ # @api private
851
+ #
852
+ def run_failed_notifications
853
+ @run_failed_notifications ||= []
854
+ end
855
+ end
472
856
 
473
- run_status.stop_clock
474
- Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds")
475
- run_completed_successfully
476
- @events.run_completed(node)
857
+ #
858
+ # IO stream that will be used as 'STDOUT' for formatters. Formatters are
859
+ # configured during `initialize`, so this provides a convenience for
860
+ # setting alternative IO stream during tests.
861
+ #
862
+ # @api private
863
+ #
864
+ STDOUT_FD = STDOUT
477
865
 
478
- # rebooting has to be the last thing we do, no exceptions.
479
- Chef::Platform::Rebooter.reboot_if_needed!(node)
866
+ #
867
+ # IO stream that will be used as 'STDERR' for formatters. Formatters are
868
+ # configured during `initialize`, so this provides a convenience for
869
+ # setting alternative IO stream during tests.
870
+ #
871
+ # @api private
872
+ #
873
+ STDERR_FD = STDERR
480
874
 
481
- true
875
+ #
876
+ # Deprecated writers
877
+ #
482
878
 
483
- rescue Exception => e
484
- # CHEF-3336: Send the error first in case something goes wrong below and we don't know why
485
- Chef::Log.debug("Re-raising exception: #{e.class} - #{e.message}\n#{e.backtrace.join("\n ")}")
486
- # If we failed really early, we may not have a run_status yet. Too early for these to be of much use.
487
- if run_status
488
- run_status.stop_clock
489
- run_status.exception = e
490
- run_failed
491
- end
492
- Chef::Application.debug_stacktrace(e)
493
- @events.run_failed(e)
494
- raise
495
- ensure
496
- Chef::RequestID.instance.reset_request_id
497
- request_id = nil
498
- @run_status = nil
499
- run_context = nil
500
- runlock.release
501
- GC.start
502
- end
503
- true
504
- end
879
+ include Chef::Mixin::Deprecation
880
+ deprecated_attr_writer :ohai, "There is no alternative. Leave ohai alone!"
881
+ deprecated_attr_writer :rest, "There is no alternative. Leave rest alone!"
882
+ deprecated_attr :runner, "There is no alternative. Leave runner alone!"
505
883
 
506
884
  private
507
885
 
886
+ attr_reader :override_runlist
887
+ attr_reader :specific_recipes
888
+
508
889
  def empty_directory?(path)
509
890
  !File.exists?(path) || (Dir.entries(path).size <= 2)
510
891
  end
@@ -536,7 +917,6 @@ class Chef
536
917
 
537
918
  Chef::ReservedNames::Win32::Security.has_admin_privileges?
538
919
  end
539
-
540
920
  end
541
921
  end
542
922