chef 12.4.3-universal-mingw32 → 12.5.1-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (320) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +21 -25
  3. data/Gemfile +46 -0
  4. data/README.md +4 -4
  5. data/Rakefile +4 -110
  6. data/bin/chef-service-manager +3 -1
  7. data/distro/common/html/knife_cookbook_site.html +18 -18
  8. data/distro/common/man/man1/knife-cookbook-site.1 +11 -11
  9. data/lib/chef.rb +1 -1
  10. data/lib/chef/application.rb +1 -1
  11. data/lib/chef/application/apply.rb +19 -1
  12. data/lib/chef/application/client.rb +11 -5
  13. data/lib/chef/application/knife.rb +2 -2
  14. data/lib/chef/application/solo.rb +1 -1
  15. data/lib/chef/application/windows_service_manager.rb +19 -12
  16. data/lib/chef/chef_class.rb +46 -0
  17. data/lib/chef/chef_fs/config.rb +22 -24
  18. data/lib/chef/chef_fs/data_handler/client_data_handler.rb +3 -1
  19. data/lib/chef/chef_fs/file_pattern.rb +4 -15
  20. data/lib/chef/chef_fs/file_system/acl_dir.rb +3 -4
  21. data/lib/chef/chef_fs/file_system/acls_dir.rb +5 -1
  22. data/lib/chef/chef_fs/file_system/base_fs_dir.rb +0 -5
  23. data/lib/chef/chef_fs/file_system/base_fs_object.rb +5 -2
  24. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +2 -9
  25. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_entry.rb +2 -9
  26. data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbooks_dir.rb +10 -17
  27. data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +1 -12
  28. data/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +15 -11
  29. data/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +8 -2
  30. data/lib/chef/chef_fs/file_system/cookbook_dir.rb +4 -4
  31. data/lib/chef/chef_fs/file_system/cookbooks_acl_dir.rb +1 -1
  32. data/lib/chef/chef_fs/file_system/cookbooks_dir.rb +3 -11
  33. data/lib/chef/chef_fs/file_system/data_bags_dir.rb +3 -5
  34. data/lib/chef/chef_fs/file_system/environments_dir.rb +1 -1
  35. data/lib/chef/chef_fs/file_system/file_system_entry.rb +7 -4
  36. data/lib/chef/chef_fs/file_system/memory_dir.rb +2 -3
  37. data/lib/chef/chef_fs/file_system/multiplexed_dir.rb +15 -0
  38. data/lib/chef/chef_fs/file_system/nodes_dir.rb +1 -1
  39. data/lib/chef/chef_fs/file_system/organization_members_entry.rb +2 -2
  40. data/lib/chef/chef_fs/file_system/rest_list_dir.rb +4 -9
  41. data/lib/chef/chef_fs/knife.rb +35 -7
  42. data/lib/chef/chef_fs/path_utils.rb +65 -34
  43. data/lib/chef/client.rb +2 -3
  44. data/lib/chef/config.rb +34 -2
  45. data/lib/chef/{mixin/wstring.rb → constants.rb} +9 -13
  46. data/lib/chef/cookbook/metadata.rb +25 -3
  47. data/lib/chef/cookbook/synchronizer.rb +1 -1
  48. data/lib/chef/cookbook_site_streaming_uploader.rb +1 -1
  49. data/lib/chef/cookbook_version.rb +3 -3
  50. data/lib/chef/delayed_evaluator.rb +21 -0
  51. data/lib/chef/deprecation/mixin/template.rb +1 -2
  52. data/lib/chef/deprecation/provider/cookbook_file.rb +1 -1
  53. data/lib/chef/deprecation/provider/file.rb +1 -1
  54. data/lib/chef/deprecation/provider/remote_directory.rb +52 -0
  55. data/lib/chef/deprecation/provider/remote_file.rb +1 -2
  56. data/lib/chef/deprecation/provider/template.rb +1 -1
  57. data/lib/chef/deprecation/warnings.rb +3 -4
  58. data/lib/chef/dsl/reboot_pending.rb +3 -2
  59. data/lib/chef/dsl/recipe.rb +26 -7
  60. data/lib/chef/dsl/resources.rb +2 -2
  61. data/lib/chef/event_dispatch/base.rb +51 -22
  62. data/lib/chef/event_dispatch/dispatcher.rb +21 -6
  63. data/lib/chef/event_dispatch/dsl.rb +64 -0
  64. data/lib/chef/exceptions.rb +28 -1
  65. data/lib/chef/file_content_management/tempfile.rb +1 -1
  66. data/lib/chef/formatters/base.rb +3 -0
  67. data/lib/chef/formatters/doc.rb +56 -6
  68. data/lib/chef/formatters/error_inspectors/compile_error_inspector.rb +36 -0
  69. data/lib/chef/formatters/minimal.rb +2 -2
  70. data/lib/chef/guard_interpreter/resource_guard_interpreter.rb +3 -1
  71. data/lib/chef/http/http_request.rb +1 -1
  72. data/lib/chef/knife.rb +35 -55
  73. data/lib/chef/knife/bootstrap.rb +41 -0
  74. data/lib/chef/knife/bootstrap/chef_vault_handler.rb +1 -0
  75. data/lib/chef/knife/bootstrap/client_builder.rb +16 -0
  76. data/lib/chef/knife/bootstrap/templates/README.md +3 -4
  77. data/lib/chef/knife/bootstrap/templates/chef-full.erb +1 -1
  78. data/lib/chef/knife/cookbook_create.rb +1 -1
  79. data/lib/chef/knife/cookbook_site_download.rb +1 -1
  80. data/lib/chef/knife/cookbook_site_install.rb +1 -1
  81. data/lib/chef/knife/cookbook_site_share.rb +6 -6
  82. data/lib/chef/knife/cookbook_site_unshare.rb +2 -2
  83. data/lib/chef/knife/core/bootstrap_context.rb +12 -4
  84. data/lib/chef/knife/core/custom_manifest_loader.rb +69 -0
  85. data/lib/chef/knife/core/gem_glob_loader.rb +138 -0
  86. data/lib/chef/knife/core/hashed_command_loader.rb +80 -0
  87. data/lib/chef/knife/core/node_presenter.rb +24 -1
  88. data/lib/chef/knife/core/object_loader.rb +1 -0
  89. data/lib/chef/knife/core/subcommand_loader.rb +131 -146
  90. data/lib/chef/knife/node_run_list_remove.rb +12 -1
  91. data/lib/chef/knife/null.rb +10 -0
  92. data/lib/chef/knife/rehash.rb +62 -0
  93. data/lib/chef/knife/search.rb +3 -3
  94. data/lib/chef/knife/ssh.rb +52 -30
  95. data/lib/chef/knife/ssl_check.rb +3 -2
  96. data/lib/chef/knife/user_edit.rb +1 -2
  97. data/lib/chef/local_mode.rb +5 -0
  98. data/lib/chef/log.rb +5 -1
  99. data/lib/chef/mixin/deprecation.rb +8 -8
  100. data/lib/chef/mixin/params_validate.rb +362 -135
  101. data/lib/chef/mixin/template.rb +48 -0
  102. data/lib/chef/mixin/which.rb +1 -1
  103. data/lib/chef/mixin/wide_string.rb +72 -0
  104. data/lib/chef/mixin/windows_architecture_helper.rb +15 -39
  105. data/lib/chef/mixin/windows_env_helper.rb +4 -1
  106. data/lib/chef/monkey_patches/webrick-utils.rb +51 -0
  107. data/lib/chef/monkey_patches/win32/registry.rb +72 -0
  108. data/lib/chef/node.rb +116 -3
  109. data/lib/chef/node_map.rb +2 -2
  110. data/lib/chef/platform/handler_map.rb +0 -5
  111. data/lib/chef/platform/provider_mapping.rb +5 -6
  112. data/lib/chef/platform/query_helpers.rb +46 -4
  113. data/lib/chef/platform/rebooter.rb +1 -1
  114. data/lib/chef/platform/service_helpers.rb +30 -32
  115. data/lib/chef/policy_builder.rb +1 -8
  116. data/lib/chef/policy_builder/dynamic.rb +186 -0
  117. data/lib/chef/policy_builder/expand_node_object.rb +30 -15
  118. data/lib/chef/policy_builder/policyfile.rb +155 -18
  119. data/lib/chef/property.rb +568 -0
  120. data/lib/chef/provider.rb +222 -13
  121. data/lib/chef/provider/batch.rb +8 -0
  122. data/lib/chef/provider/deploy.rb +5 -7
  123. data/lib/chef/provider/directory.rb +14 -2
  124. data/lib/chef/provider/dsc_resource.rb +5 -9
  125. data/lib/chef/provider/group/pw.rb +1 -1
  126. data/lib/chef/provider/ifconfig.rb +2 -2
  127. data/lib/chef/provider/lwrp_base.rb +1 -75
  128. data/lib/chef/provider/mount.rb +7 -3
  129. data/lib/chef/provider/package.rb +1 -1
  130. data/lib/chef/provider/package/dpkg.rb +5 -11
  131. data/lib/chef/provider/package/rpm.rb +2 -2
  132. data/lib/chef/provider/package/rubygems.rb +1 -1
  133. data/lib/chef/provider/package/windows/msi.rb +2 -2
  134. data/lib/chef/provider/package/yum.rb +17 -5
  135. data/lib/chef/provider/powershell_script.rb +59 -23
  136. data/lib/chef/provider/registry_key.rb +5 -5
  137. data/lib/chef/provider/remote_directory.rb +190 -102
  138. data/lib/chef/provider/service.rb +12 -2
  139. data/lib/chef/provider/service/aix.rb +1 -1
  140. data/lib/chef/provider/service/debian.rb +3 -5
  141. data/lib/chef/provider/service/freebsd.rb +1 -1
  142. data/lib/chef/provider/service/gentoo.rb +3 -3
  143. data/lib/chef/provider/service/init.rb +3 -3
  144. data/lib/chef/provider/service/insserv.rb +2 -4
  145. data/lib/chef/provider/service/invokercd.rb +2 -4
  146. data/lib/chef/provider/service/macosx.rb +5 -1
  147. data/lib/chef/provider/service/openbsd.rb +2 -1
  148. data/lib/chef/provider/service/redhat.rb +52 -16
  149. data/lib/chef/provider/service/simple.rb +2 -2
  150. data/lib/chef/provider/service/systemd.rb +3 -5
  151. data/lib/chef/provider/service/upstart.rb +4 -6
  152. data/lib/chef/provider/subversion.rb +13 -7
  153. data/lib/chef/provider/template/content.rb +16 -6
  154. data/lib/chef/provider/user/solaris.rb +32 -4
  155. data/lib/chef/provider/windows_script.rb +3 -5
  156. data/lib/chef/provider_resolver.rb +2 -2
  157. data/lib/chef/recipe.rb +1 -8
  158. data/lib/chef/resource.rb +563 -90
  159. data/lib/chef/resource/action_class.rb +83 -0
  160. data/lib/chef/resource/chef_gem.rb +3 -3
  161. data/lib/chef/resource/deploy.rb +8 -2
  162. data/lib/chef/resource/dsc_script.rb +2 -0
  163. data/lib/chef/resource/file/verification.rb +7 -1
  164. data/lib/chef/resource/lwrp_base.rb +1 -7
  165. data/lib/chef/resource/registry_key.rb +1 -1
  166. data/lib/chef/resource/service.rb +10 -2
  167. data/lib/chef/resource/subversion.rb +5 -0
  168. data/lib/chef/resource/windows_script.rb +6 -2
  169. data/lib/chef/resource/yum_package.rb +10 -1
  170. data/lib/chef/resource_resolver.rb +3 -3
  171. data/lib/chef/run_context.rb +402 -83
  172. data/lib/chef/run_list/versioned_recipe_list.rb +15 -0
  173. data/lib/chef/run_lock.rb +30 -21
  174. data/lib/chef/util/powershell/ps_credential.rb +4 -0
  175. data/lib/chef/util/windows.rb +0 -32
  176. data/lib/chef/util/windows/net_group.rb +85 -106
  177. data/lib/chef/util/windows/net_use.rb +35 -71
  178. data/lib/chef/util/windows/net_user.rb +0 -1
  179. data/lib/chef/util/windows/volume.rb +19 -19
  180. data/lib/chef/version.rb +3 -3
  181. data/lib/chef/win32/api.rb +1 -0
  182. data/lib/chef/win32/api/file.rb +20 -0
  183. data/lib/chef/win32/api/net.rb +163 -43
  184. data/lib/chef/win32/api/registry.rb +51 -0
  185. data/lib/chef/win32/api/system.rb +23 -0
  186. data/lib/chef/win32/api/unicode.rb +0 -43
  187. data/lib/chef/win32/crypto.rb +2 -1
  188. data/lib/chef/win32/file.rb +28 -3
  189. data/lib/chef/win32/mutex.rb +1 -2
  190. data/lib/chef/win32/net.rb +162 -8
  191. data/lib/chef/win32/process.rb +13 -0
  192. data/lib/chef/win32/registry.rb +35 -30
  193. data/lib/chef/win32/security.rb +1 -1
  194. data/lib/chef/win32/security/token.rb +1 -1
  195. data/lib/chef/win32/system.rb +62 -0
  196. data/lib/chef/win32/unicode.rb +7 -2
  197. data/lib/chef/win32/version.rb +0 -4
  198. data/lib/chef/workstation_config_loader.rb +3 -158
  199. data/spec/data/cookbooks/openldap/templates/default/helpers.erb +14 -0
  200. data/spec/data/cookbooks/openldap/templates/default/nested_openldap_partials.erb +1 -0
  201. data/spec/data/cookbooks/openldap/templates/default/nested_partial.erb +1 -0
  202. data/spec/data/dsc_lcm.pfx +0 -0
  203. data/spec/data/run_context/cookbooks/include/recipes/default.rb +24 -0
  204. data/spec/data/run_context/cookbooks/include/recipes/includee.rb +3 -0
  205. data/spec/functional/dsl/reboot_pending_spec.rb +33 -43
  206. data/spec/functional/knife/cookbook_delete_spec.rb +17 -7
  207. data/spec/functional/knife/ssh_spec.rb +16 -0
  208. data/spec/functional/rebooter_spec.rb +1 -1
  209. data/spec/functional/resource/deploy_revision_spec.rb +1 -1
  210. data/spec/functional/resource/dsc_resource_spec.rb +2 -0
  211. data/spec/functional/resource/dsc_script_spec.rb +91 -2
  212. data/spec/functional/resource/group_spec.rb +67 -44
  213. data/spec/functional/resource/{powershell_spec.rb → powershell_script_spec.rb} +107 -18
  214. data/spec/functional/resource/windows_service_spec.rb +1 -1
  215. data/spec/functional/run_lock_spec.rb +368 -189
  216. data/spec/functional/win32/{registry_helper_spec.rb → registry_spec.rb} +16 -23
  217. data/spec/functional/win32/service_manager_spec.rb +2 -2
  218. data/spec/integration/client/client_spec.rb +51 -0
  219. data/spec/integration/knife/chef_repo_path_spec.rb +13 -11
  220. data/spec/integration/knife/download_spec.rb +4 -0
  221. data/spec/integration/knife/list_spec.rb +8 -0
  222. data/spec/integration/knife/upload_spec.rb +1 -1
  223. data/spec/integration/recipes/recipe_dsl_spec.rb +1 -16
  224. data/spec/integration/recipes/remote_directory.rb +74 -0
  225. data/spec/integration/recipes/resource_action_spec.rb +363 -0
  226. data/spec/integration/recipes/resource_converge_if_changed_spec.rb +423 -0
  227. data/spec/integration/recipes/resource_load_spec.rb +206 -0
  228. data/spec/spec_helper.rb +9 -0
  229. data/spec/support/platform_helpers.rb +13 -0
  230. data/spec/support/shared/context/win32.rb +34 -0
  231. data/spec/support/shared/functional/win32_service.rb +2 -1
  232. data/spec/support/shared/functional/windows_script.rb +63 -26
  233. data/spec/support/shared/unit/mock_shellout.rb +46 -0
  234. data/spec/support/shared/unit/provider/file.rb +10 -4
  235. data/spec/unit/application/client_spec.rb +16 -3
  236. data/spec/unit/application/knife_spec.rb +2 -2
  237. data/spec/unit/application/solo_spec.rb +4 -3
  238. data/spec/unit/chef_class_spec.rb +23 -4
  239. data/spec/unit/chef_fs/path_util_spec.rb +108 -0
  240. data/spec/unit/client_spec.rb +6 -1
  241. data/spec/unit/config_spec.rb +31 -0
  242. data/spec/unit/cookbook/metadata_spec.rb +23 -3
  243. data/spec/unit/cookbook/syntax_check_spec.rb +3 -0
  244. data/spec/unit/deprecation_spec.rb +3 -6
  245. data/spec/unit/dsl/reboot_pending_spec.rb +12 -6
  246. data/spec/unit/event_dispatch/dispatcher_spec.rb +65 -3
  247. data/spec/unit/event_dispatch/dsl_spec.rb +83 -0
  248. data/spec/unit/formatters/doc_spec.rb +32 -0
  249. data/spec/unit/formatters/error_inspectors/compile_error_inspector_spec.rb +26 -0
  250. data/spec/unit/json_compat_spec.rb +4 -3
  251. data/spec/unit/knife/bootstrap/client_builder_spec.rb +27 -0
  252. data/spec/unit/knife/bootstrap_spec.rb +55 -3
  253. data/spec/unit/knife/cookbook_site_share_spec.rb +3 -3
  254. data/spec/unit/knife/core/bootstrap_context_spec.rb +21 -4
  255. data/spec/unit/knife/core/custom_manifest_loader_spec.rb +41 -0
  256. data/spec/unit/knife/core/gem_glob_loader_spec.rb +210 -0
  257. data/spec/unit/knife/core/hashed_command_loader_spec.rb +93 -0
  258. data/spec/unit/knife/core/subcommand_loader_spec.rb +16 -192
  259. data/spec/unit/knife/node_run_list_remove_spec.rb +17 -0
  260. data/spec/unit/knife/ssl_check_spec.rb +4 -0
  261. data/spec/unit/mixin/enforce_ownership_and_permissions_spec.rb +10 -10
  262. data/spec/unit/mixin/params_validate_spec.rb +4 -2
  263. data/spec/unit/mixin/template_spec.rb +5 -1
  264. data/spec/unit/mixin/windows_architecture_helper_spec.rb +13 -8
  265. data/spec/unit/node_spec.rb +220 -0
  266. data/spec/unit/platform/query_helpers_spec.rb +146 -3
  267. data/spec/unit/policy_builder/dynamic_spec.rb +275 -0
  268. data/spec/unit/policy_builder/expand_node_object_spec.rb +37 -38
  269. data/spec/unit/policy_builder/policyfile_spec.rb +260 -46
  270. data/spec/unit/property/state_spec.rb +506 -0
  271. data/spec/unit/property/validation_spec.rb +663 -0
  272. data/spec/unit/property_spec.rb +1094 -0
  273. data/spec/unit/provider/deploy_spec.rb +5 -5
  274. data/spec/unit/provider/directory_spec.rb +35 -0
  275. data/spec/unit/provider/dsc_resource_spec.rb +3 -10
  276. data/spec/unit/provider/ifconfig_spec.rb +22 -2
  277. data/spec/unit/provider/mount/aix_spec.rb +2 -1
  278. data/spec/unit/provider/mount/mount_spec.rb +6 -0
  279. data/spec/unit/provider/mount/windows_spec.rb +14 -0
  280. data/spec/unit/provider/mount_spec.rb +12 -1
  281. data/spec/unit/provider/package/dpkg_spec.rb +8 -1
  282. data/spec/unit/provider/package/rpm_spec.rb +18 -1
  283. data/spec/unit/provider/package/rubygems_spec.rb +18 -0
  284. data/spec/unit/provider/package/yum_spec.rb +97 -24
  285. data/spec/unit/provider/powershell_script_spec.rb +106 -0
  286. data/spec/unit/provider/registry_key_spec.rb +12 -0
  287. data/spec/unit/provider/remote_directory_spec.rb +1 -2
  288. data/spec/unit/provider/service/aix_service_spec.rb +3 -3
  289. data/spec/unit/provider/service/gentoo_service_spec.rb +4 -4
  290. data/spec/unit/provider/service/macosx_spec.rb +4 -4
  291. data/spec/unit/provider/service/openbsd_service_spec.rb +10 -8
  292. data/spec/unit/provider/service/redhat_spec.rb +88 -8
  293. data/spec/unit/provider/service/upstart_service_spec.rb +11 -7
  294. data/spec/unit/provider/service/windows_spec.rb +211 -200
  295. data/spec/unit/provider/subversion_spec.rb +50 -31
  296. data/spec/unit/provider/template/content_spec.rb +93 -2
  297. data/spec/unit/provider/user/solaris_spec.rb +66 -9
  298. data/spec/unit/provider_resolver_spec.rb +707 -650
  299. data/spec/unit/provider_spec.rb +1 -3
  300. data/spec/unit/recipe_spec.rb +0 -4
  301. data/spec/unit/resource/deploy_spec.rb +7 -1
  302. data/spec/unit/resource/dsc_script_spec.rb +4 -0
  303. data/spec/unit/resource/file/verification_spec.rb +33 -5
  304. data/spec/unit/resource/{powershell_spec.rb → powershell_script_spec.rb} +17 -13
  305. data/spec/unit/resource/service_spec.rb +4 -4
  306. data/spec/unit/resource/subversion_spec.rb +4 -0
  307. data/spec/unit/resource/yum_package_spec.rb +10 -1
  308. data/spec/unit/resource_spec.rb +2 -2
  309. data/spec/unit/run_context/child_run_context_spec.rb +133 -0
  310. data/spec/unit/run_context_spec.rb +7 -0
  311. data/spec/unit/run_list/versioned_recipe_list_spec.rb +5 -0
  312. data/spec/unit/win32/registry_spec.rb +394 -0
  313. data/tasks/external_tests.rb +47 -23
  314. data/tasks/maintainers.rb +155 -14
  315. metadata +64 -53
  316. data/lib/chef/knife/bootstrap/templates/archlinux-gems.erb +0 -76
  317. data/lib/chef/knife/bootstrap/templates/chef-aix.erb +0 -72
  318. data/spec/unit/provider/powershell_spec.rb +0 -80
  319. data/spec/unit/registry_helper_spec.rb +0 -376
  320. data/spec/unit/workstation_config_loader_spec.rb +0 -283
@@ -0,0 +1,1094 @@
1
+ require 'support/shared/integration/integration_helper'
2
+
3
+ describe "Chef::Resource.property" do
4
+ include IntegrationSupport
5
+
6
+ module Namer
7
+ @i = 0
8
+ def self.next_resource_name
9
+ "chef_resource_property_spec_#{@i += 1}"
10
+ end
11
+ def self.reset_index
12
+ @current_index = 0
13
+ end
14
+ def self.current_index
15
+ @current_index
16
+ end
17
+ def self.next_index
18
+ @current_index += 1
19
+ end
20
+ end
21
+
22
+ def lazy(&block)
23
+ Chef::DelayedEvaluator.new(&block)
24
+ end
25
+
26
+ before do
27
+ Namer.reset_index
28
+ end
29
+
30
+ def self.new_resource_name
31
+ Namer.next_resource_name
32
+ end
33
+
34
+ let(:resource_class) do
35
+ new_resource_name = self.class.new_resource_name
36
+ Class.new(Chef::Resource) do
37
+ resource_name new_resource_name
38
+ def next_index
39
+ Namer.next_index
40
+ end
41
+ end
42
+ end
43
+
44
+ let(:resource) do
45
+ resource_class.new("blah")
46
+ end
47
+
48
+ def self.english_join(values)
49
+ return '<nothing>' if values.size == 0
50
+ return values[0].inspect if values.size == 1
51
+ "#{values[0..-2].map { |v| v.inspect }.join(", ")} and #{values[-1].inspect}"
52
+ end
53
+
54
+ def self.with_property(*properties, &block)
55
+ tags_index = properties.find_index { |p| !p.is_a?(String)}
56
+ if tags_index
57
+ properties, tags = properties[0..tags_index-1], properties[tags_index..-1]
58
+ else
59
+ tags = []
60
+ end
61
+ if properties.size == 1
62
+ description = "With property #{properties.first}"
63
+ else
64
+ description = "With properties #{english_join(properties.map { |property| "#{property.inspect}" })}"
65
+ end
66
+ context description, *tags do
67
+ before do
68
+ properties.each do |property_str|
69
+ resource_class.class_eval("property #{property_str}", __FILE__, __LINE__)
70
+ end
71
+ end
72
+ instance_eval(&block)
73
+ end
74
+ end
75
+
76
+ # Basic properties
77
+ with_property ':bare_property' do
78
+ it "can be set" do
79
+ expect(resource.bare_property 10).to eq 10
80
+ expect(resource.bare_property).to eq 10
81
+ end
82
+ it "emits a deprecation warning and does a get, if set to nil" do
83
+ expect(resource.bare_property 10).to eq 10
84
+ expect { resource.bare_property nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError
85
+ Chef::Config[:treat_deprecation_warnings_as_errors] = false
86
+ expect(resource.bare_property nil).to eq 10
87
+ expect(resource.bare_property).to eq 10
88
+ end
89
+ it "can be updated" do
90
+ expect(resource.bare_property 10).to eq 10
91
+ expect(resource.bare_property 20).to eq 20
92
+ expect(resource.bare_property).to eq 20
93
+ end
94
+ it "can be set with =" do
95
+ expect(resource.bare_property 10).to eq 10
96
+ expect(resource.bare_property).to eq 10
97
+ end
98
+ it "can be set to nil with =" do
99
+ expect(resource.bare_property 10).to eq 10
100
+ expect(resource.bare_property = nil).to be_nil
101
+ expect(resource.bare_property).to be_nil
102
+ end
103
+ it "can be updated with =" do
104
+ expect(resource.bare_property 10).to eq 10
105
+ expect(resource.bare_property = 20).to eq 20
106
+ expect(resource.bare_property).to eq 20
107
+ end
108
+ end
109
+
110
+ with_property ":x, name_property: true" do
111
+ context "and subclass" do
112
+ let(:subresource_class) do
113
+ new_resource_name = self.class.new_resource_name
114
+ Class.new(resource_class) do
115
+ resource_name new_resource_name
116
+ end
117
+ end
118
+ let(:subresource) do
119
+ subresource_class.new('blah')
120
+ end
121
+
122
+ context "with property :x on the subclass" do
123
+ before do
124
+ subresource_class.class_eval do
125
+ property :x
126
+ end
127
+ end
128
+
129
+ it "x is still name_property" do
130
+ expect(subresource.x).to eq 'blah'
131
+ end
132
+ end
133
+
134
+ context "with property :x, name_attribute: false on the subclass" do
135
+ before do
136
+ subresource_class.class_eval do
137
+ property :x, name_attribute: false
138
+ end
139
+ end
140
+
141
+ it "x is no longer name_property" do
142
+ expect(subresource.x).to be_nil
143
+ end
144
+ end
145
+
146
+ context "with property :x, default: 10 on the subclass" do
147
+ before do
148
+ subresource_class.class_eval do
149
+ property :x, default: 10
150
+ end
151
+ end
152
+
153
+ it "x is no longer name_property" do
154
+ expect(subresource.x).to eq(10)
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ with_property ":x, Integer" do
161
+ context "and subclass" do
162
+ let(:subresource_class) do
163
+ new_resource_name = self.class.new_resource_name
164
+ Class.new(resource_class) do
165
+ resource_name new_resource_name
166
+ end
167
+ end
168
+ let(:subresource) do
169
+ subresource_class.new('blah')
170
+ end
171
+
172
+ it "x is inherited" do
173
+ expect(subresource.x 10).to eq 10
174
+ expect(subresource.x).to eq 10
175
+ expect(subresource.x = 20).to eq 20
176
+ expect(subresource.x).to eq 20
177
+ expect(subresource_class.properties[:x]).not_to be_nil
178
+ end
179
+
180
+ it "x's validation is inherited" do
181
+ expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed
182
+ end
183
+
184
+ context "with property :y on the subclass" do
185
+ before do
186
+ subresource_class.class_eval do
187
+ property :y
188
+ end
189
+ end
190
+
191
+ it "x is still there" do
192
+ expect(subresource.x 10).to eq 10
193
+ expect(subresource.x).to eq 10
194
+ expect(subresource.x = 20).to eq 20
195
+ expect(subresource.x).to eq 20
196
+ expect(subresource_class.properties[:x]).not_to be_nil
197
+ end
198
+ it "y is there" do
199
+ expect(subresource.y 10).to eq 10
200
+ expect(subresource.y).to eq 10
201
+ expect(subresource.y = 20).to eq 20
202
+ expect(subresource.y).to eq 20
203
+ expect(subresource_class.properties[:y]).not_to be_nil
204
+ end
205
+ it "y is not on the superclass" do
206
+ expect { resource_class.y 10 }.to raise_error
207
+ expect(resource_class.properties[:y]).to be_nil
208
+ end
209
+ end
210
+
211
+ context "with property :x on the subclass" do
212
+ before do
213
+ subresource_class.class_eval do
214
+ property :x
215
+ end
216
+ end
217
+
218
+ it "x is still there" do
219
+ expect(subresource.x 10).to eq 10
220
+ expect(subresource.x).to eq 10
221
+ expect(subresource.x = 20).to eq 20
222
+ expect(subresource.x).to eq 20
223
+ expect(subresource_class.properties[:x]).not_to be_nil
224
+ expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x]
225
+ end
226
+
227
+ it "x's validation is inherited" do
228
+ expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed
229
+ end
230
+ end
231
+
232
+ context "with property :x, default: 80 on the subclass" do
233
+ before do
234
+ subresource_class.class_eval do
235
+ property :x, default: 80
236
+ end
237
+ end
238
+
239
+ it "x is still there" do
240
+ expect(subresource.x 10).to eq 10
241
+ expect(subresource.x).to eq 10
242
+ expect(subresource.x = 20).to eq 20
243
+ expect(subresource.x).to eq 20
244
+ expect(subresource_class.properties[:x]).not_to be_nil
245
+ expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x]
246
+ end
247
+
248
+ it "x defaults to 80" do
249
+ expect(subresource.x).to eq 80
250
+ end
251
+
252
+ it "x's validation is inherited" do
253
+ expect { subresource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed
254
+ end
255
+ end
256
+
257
+ context "with property :x, String on the subclass" do
258
+ before do
259
+ subresource_class.class_eval do
260
+ property :x, String
261
+ end
262
+ end
263
+
264
+ it "x is still there" do
265
+ expect(subresource.x "10").to eq "10"
266
+ expect(subresource.x).to eq "10"
267
+ expect(subresource.x = "20").to eq "20"
268
+ expect(subresource.x).to eq "20"
269
+ expect(subresource_class.properties[:x]).not_to be_nil
270
+ expect(subresource_class.properties[:x]).not_to eq resource_class.properties[:x]
271
+ end
272
+
273
+ it "x's validation is overwritten" do
274
+ expect { subresource.x 10 }.to raise_error Chef::Exceptions::ValidationFailed
275
+ expect(subresource.x 'ohno').to eq 'ohno'
276
+ expect(subresource.x).to eq 'ohno'
277
+ end
278
+
279
+ it "the superclass's validation for x is still there" do
280
+ expect { resource.x 'ohno' }.to raise_error Chef::Exceptions::ValidationFailed
281
+ expect(resource.x 10).to eq 10
282
+ expect(resource.x).to eq 10
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ context "Chef::Resource::Property#reset_property" do
289
+ it "when a resource is newly created, reset_property(:name) sets property to nil" do
290
+ expect(resource.property_is_set?(:name)).to be_truthy
291
+ resource.reset_property(:name)
292
+ expect(resource.property_is_set?(:name)).to be_falsey
293
+ expect(resource.name).to be_nil
294
+ end
295
+
296
+ it "when referencing an undefined property, reset_property(:x) raises an error" do
297
+ expect { resource.reset_property(:x) }.to raise_error(ArgumentError)
298
+ end
299
+
300
+ with_property ':x' do
301
+ it "when the resource is newly created, reset_property(:x) does nothing" do
302
+ expect(resource.property_is_set?(:x)).to be_falsey
303
+ resource.reset_property(:x)
304
+ expect(resource.property_is_set?(:x)).to be_falsey
305
+ expect(resource.x).to be_nil
306
+ end
307
+ it "when x is set, reset_property resets it" do
308
+ resource.x 10
309
+ expect(resource.property_is_set?(:x)).to be_truthy
310
+ resource.reset_property(:x)
311
+ expect(resource.property_is_set?(:x)).to be_falsey
312
+ expect(resource.x).to be_nil
313
+ end
314
+ end
315
+
316
+ with_property ':x, Integer' do
317
+ it "when the resource is newly created, reset_property(:x) does nothing" do
318
+ expect(resource.property_is_set?(:x)).to be_falsey
319
+ resource.reset_property(:x)
320
+ expect(resource.property_is_set?(:x)).to be_falsey
321
+ expect(resource.x).to be_nil
322
+ end
323
+ it "when x is set, reset_property resets it even though `nil` is technically invalid" do
324
+ resource.x 10
325
+ expect(resource.property_is_set?(:x)).to be_truthy
326
+ resource.reset_property(:x)
327
+ expect(resource.property_is_set?(:x)).to be_falsey
328
+ expect(resource.x).to be_nil
329
+ end
330
+ end
331
+
332
+ with_property ':x, default: 10' do
333
+ it "when the resource is newly created, reset_property(:x) does nothing" do
334
+ expect(resource.property_is_set?(:x)).to be_falsey
335
+ resource.reset_property(:x)
336
+ expect(resource.property_is_set?(:x)).to be_falsey
337
+ expect(resource.x).to eq 10
338
+ end
339
+ it "when x is set, reset_property resets it and it returns the default" do
340
+ resource.x 20
341
+ resource.reset_property(:x)
342
+ expect(resource.property_is_set?(:x)).to be_falsey
343
+ expect(resource.x).to eq 10
344
+ end
345
+ end
346
+
347
+ with_property ':x, default: lazy { 10 }' do
348
+ it "when the resource is newly created, reset_property(:x) does nothing" do
349
+ expect(resource.property_is_set?(:x)).to be_falsey
350
+ resource.reset_property(:x)
351
+ expect(resource.property_is_set?(:x)).to be_falsey
352
+ expect(resource.x).to eq 10
353
+ end
354
+ it "when x is set, reset_property resets it and it returns the default" do
355
+ resource.x 20
356
+ resource.reset_property(:x)
357
+ expect(resource.property_is_set?(:x)).to be_falsey
358
+ expect(resource.x).to eq 10
359
+ end
360
+ end
361
+ end
362
+
363
+ context "Chef::Resource::Property#property_is_set?" do
364
+ it "when a resource is newly created, property_is_set?(:name) is true" do
365
+ expect(resource.property_is_set?(:name)).to be_truthy
366
+ end
367
+
368
+ it "when referencing an undefined property, property_is_set?(:x) raises an error" do
369
+ expect { resource.property_is_set?(:x) }.to raise_error(ArgumentError)
370
+ end
371
+
372
+ with_property ':x' do
373
+ it "when the resource is newly created, property_is_set?(:x) is false" do
374
+ expect(resource.property_is_set?(:x)).to be_falsey
375
+ end
376
+ it "when x is set, property_is_set?(:x) is true" do
377
+ resource.x 10
378
+ expect(resource.property_is_set?(:x)).to be_truthy
379
+ end
380
+ it "when x is set with =, property_is_set?(:x) is true" do
381
+ resource.x = 10
382
+ expect(resource.property_is_set?(:x)).to be_truthy
383
+ end
384
+ it "when x is set to a lazy value, property_is_set?(:x) is true" do
385
+ resource.x lazy { 10 }
386
+ expect(resource.property_is_set?(:x)).to be_truthy
387
+ end
388
+ it "when x is retrieved, property_is_set?(:x) is false" do
389
+ resource.x
390
+ expect(resource.property_is_set?(:x)).to be_falsey
391
+ end
392
+ end
393
+
394
+ with_property ':x, default: 10' do
395
+ it "when the resource is newly created, property_is_set?(:x) is false" do
396
+ expect(resource.property_is_set?(:x)).to be_falsey
397
+ end
398
+ it "when x is set, property_is_set?(:x) is true" do
399
+ resource.x 10
400
+ expect(resource.property_is_set?(:x)).to be_truthy
401
+ end
402
+ it "when x is set with =, property_is_set?(:x) is true" do
403
+ resource.x = 10
404
+ expect(resource.property_is_set?(:x)).to be_truthy
405
+ end
406
+ it "when x is set to a lazy value, property_is_set?(:x) is true" do
407
+ resource.x lazy { 10 }
408
+ expect(resource.property_is_set?(:x)).to be_truthy
409
+ end
410
+ it "when x is retrieved, property_is_set?(:x) is false" do
411
+ resource.x
412
+ expect(resource.property_is_set?(:x)).to be_falsey
413
+ end
414
+ end
415
+
416
+ with_property ':x, default: nil' do
417
+ it "when the resource is newly created, property_is_set?(:x) is false" do
418
+ expect(resource.property_is_set?(:x)).to be_falsey
419
+ end
420
+ it "when x is set, property_is_set?(:x) is true" do
421
+ resource.x 10
422
+ expect(resource.property_is_set?(:x)).to be_truthy
423
+ end
424
+ it "when x is set with =, property_is_set?(:x) is true" do
425
+ resource.x = 10
426
+ expect(resource.property_is_set?(:x)).to be_truthy
427
+ end
428
+ it "when x is set to a lazy value, property_is_set?(:x) is true" do
429
+ resource.x lazy { 10 }
430
+ expect(resource.property_is_set?(:x)).to be_truthy
431
+ end
432
+ it "when x is retrieved, property_is_set?(:x) is false" do
433
+ resource.x
434
+ expect(resource.property_is_set?(:x)).to be_falsey
435
+ end
436
+ end
437
+
438
+ with_property ':x, default: lazy { 10 }' do
439
+ it "when the resource is newly created, property_is_set?(:x) is false" do
440
+ expect(resource.property_is_set?(:x)).to be_falsey
441
+ end
442
+ it "when x is set, property_is_set?(:x) is true" do
443
+ resource.x 10
444
+ expect(resource.property_is_set?(:x)).to be_truthy
445
+ end
446
+ it "when x is set with =, property_is_set?(:x) is true" do
447
+ resource.x = 10
448
+ expect(resource.property_is_set?(:x)).to be_truthy
449
+ end
450
+ it "when x is retrieved, property_is_set?(:x) is false" do
451
+ resource.x
452
+ expect(resource.property_is_set?(:x)).to be_falsey
453
+ end
454
+ end
455
+ end
456
+
457
+ context "Chef::Resource::Property#default" do
458
+ with_property ':x, default: 10' do
459
+ it "when x is set, it returns its value" do
460
+ expect(resource.x 20).to eq 20
461
+ expect(resource.property_is_set?(:x)).to be_truthy
462
+ expect(resource.x).to eq 20
463
+ end
464
+ it "when x is not set, it returns 10" do
465
+ expect(resource.x).to eq 10
466
+ end
467
+ it "when x is not set, it is not included in state" do
468
+ expect(resource.state_for_resource_reporter).to eq({})
469
+ end
470
+ it "when x is set to nil, it returns nil" do
471
+ resource.instance_eval { @x = nil }
472
+ expect(resource.x).to be_nil
473
+ end
474
+
475
+ context "With a subclass" do
476
+ let(:subresource_class) do
477
+ new_resource_name = self.class.new_resource_name
478
+ Class.new(resource_class) do
479
+ resource_name new_resource_name
480
+ end
481
+ end
482
+ let(:subresource) { subresource_class.new('blah') }
483
+ it "The default is inherited" do
484
+ expect(subresource.x).to eq 10
485
+ end
486
+ end
487
+ end
488
+
489
+ with_property ':x, default: 10, identity: true' do
490
+ it "when x is not set, it is included in identity" do
491
+ expect(resource.identity).to eq(10)
492
+ end
493
+ end
494
+
495
+ with_property ':x, default: 1, identity: true', ':y, default: 2, identity: true' do
496
+ it "when x is not set, it is still included in identity" do
497
+ resource.y 20
498
+ expect(resource.identity).to eq(x: 1, y: 20)
499
+ end
500
+ end
501
+
502
+ with_property ':x, default: nil' do
503
+ it "when x is not set, it returns nil" do
504
+ expect(resource.x).to be_nil
505
+ end
506
+ end
507
+
508
+ with_property ':x' do
509
+ it "when x is not set, it returns nil" do
510
+ expect(resource.x).to be_nil
511
+ end
512
+ end
513
+
514
+ context "hash default" do
515
+ context "(deprecations allowed)" do
516
+ before { Chef::Config[:treat_deprecation_warnings_as_errors] = false }
517
+
518
+ with_property ':x, default: {}' do
519
+ it "when x is not set, it returns {}" do
520
+ expect(resource.x).to eq({})
521
+ end
522
+ it "The same exact value is returned multiple times in a row" do
523
+ value = resource.x
524
+ expect(value).to eq({})
525
+ expect(resource.x.object_id).to eq(value.object_id)
526
+ end
527
+ it "Multiple instances of x receive the exact same value" do
528
+ expect(resource.x.object_id).to eq(resource_class.new('blah2').x.object_id)
529
+ end
530
+ end
531
+ end
532
+
533
+ with_property ':x, default: lazy { {} }' do
534
+ it "when x is not set, it returns {}" do
535
+ expect(resource.x).to eq({})
536
+ end
537
+ # it "The value is different each time it is called" do
538
+ # value = resource.x
539
+ # expect(value).to eq({})
540
+ # expect(resource.x.object_id).not_to eq(value.object_id)
541
+ # end
542
+ it "Multiple instances of x receive different values" do
543
+ expect(resource.x.object_id).not_to eq(resource_class.new('blah2').x.object_id)
544
+ end
545
+ end
546
+ end
547
+
548
+ context "with a class with 'blah' as both class and instance methods" do
549
+ before do
550
+ resource_class.class_eval do
551
+ def self.blah
552
+ 'class'
553
+ end
554
+ def blah
555
+ "#{name}#{next_index}"
556
+ end
557
+ end
558
+ end
559
+
560
+ with_property ':x, default: lazy { blah }' do
561
+ it "x is run in context of the instance" do
562
+ expect(resource.x).to eq "blah1"
563
+ end
564
+ it "x is run in the context of each instance it is run in" do
565
+ expect(resource.x).to eq "blah1"
566
+ expect(resource_class.new('another').x).to eq "another2"
567
+ # expect(resource.x).to eq "blah3"
568
+ end
569
+ end
570
+
571
+ with_property ':x, default: lazy { |x| "#{blah}#{x.blah}" }' do
572
+ it "x is run in context of the class (where it was defined) and passed the instance" do
573
+ expect(resource.x).to eq "classblah1"
574
+ end
575
+ it "x is passed the value of each instance it is run in" do
576
+ expect(resource.x).to eq "classblah1"
577
+ expect(resource_class.new('another').x).to eq "classanother2"
578
+ # expect(resource.x).to eq "classblah3"
579
+ end
580
+ end
581
+ end
582
+
583
+ context "validation of defaults" do
584
+ with_property ':x, String, default: 10' do
585
+ it "when the resource is created, no error is raised" do
586
+ resource
587
+ end
588
+ it "when x is set, no error is raised" do
589
+ expect(resource.x 'hi').to eq 'hi'
590
+ expect(resource.x).to eq 'hi'
591
+ end
592
+ it "when x is retrieved, no validation error is raised" do
593
+ expect(resource.x).to eq 10
594
+ end
595
+ # it "when x is retrieved, a validation error is raised" do
596
+ # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
597
+ # end
598
+ end
599
+
600
+ with_property ":x, String, default: lazy { Namer.next_index }" do
601
+ it "when the resource is created, no error is raised" do
602
+ resource
603
+ end
604
+ it "when x is set, no error is raised" do
605
+ expect(resource.x 'hi').to eq 'hi'
606
+ expect(resource.x).to eq 'hi'
607
+ end
608
+ it "when x is retrieved, no validation error is raised" do
609
+ expect(resource.x).to eq 1
610
+ expect(Namer.current_index).to eq 1
611
+ end
612
+ # it "when x is retrieved, a validation error is raised" do
613
+ # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
614
+ # expect(Namer.current_index).to eq 1
615
+ # end
616
+ end
617
+
618
+ with_property ":x, default: lazy { Namer.next_index.to_s }, is: proc { |v| Namer.next_index; true }" do
619
+ it "validation is not run at all on the default value" do
620
+ expect(resource.x).to eq '1'
621
+ expect(Namer.current_index).to eq 1
622
+ end
623
+ # it "validation is run each time" do
624
+ # expect(resource.x).to eq '1'
625
+ # expect(Namer.current_index).to eq 2
626
+ # expect(resource.x).to eq '1'
627
+ # expect(Namer.current_index).to eq 2
628
+ # end
629
+ end
630
+
631
+ with_property ":x, default: lazy { Namer.next_index.to_s.freeze }, is: proc { |v| Namer.next_index; true }" do
632
+ it "validation is not run at all on the default value" do
633
+ expect(resource.x).to eq '1'
634
+ expect(Namer.current_index).to eq 1
635
+ end
636
+ # it "validation is only run the first time" do
637
+ # expect(resource.x).to eq '1'
638
+ # expect(Namer.current_index).to eq 2
639
+ # expect(resource.x).to eq '1'
640
+ # expect(Namer.current_index).to eq 2
641
+ # end
642
+ end
643
+ end
644
+
645
+ context "coercion of defaults" do
646
+ # Frozen default, non-frozen coerce
647
+ with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
648
+ it "when the resource is created, the proc is not yet run" do
649
+ resource
650
+ expect(Namer.current_index).to eq 0
651
+ end
652
+ it "when x is set, coercion is run" do
653
+ expect(resource.x 'hi').to eq 'hi1'
654
+ expect(resource.x).to eq 'hi1'
655
+ expect(Namer.current_index).to eq 1
656
+ end
657
+ it "when x is retrieved, coercion is run exactly once" do
658
+ expect(resource.x).to eq '101'
659
+ expect(resource.x).to eq '101'
660
+ expect(Namer.current_index).to eq 1
661
+ end
662
+ end
663
+
664
+ # Frozen default, frozen coerce
665
+ with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: 10' do
666
+ it "when the resource is created, the proc is not yet run" do
667
+ resource
668
+ expect(Namer.current_index).to eq 0
669
+ end
670
+ it "when x is set, coercion is run" do
671
+ expect(resource.x 'hi').to eq 'hi1'
672
+ expect(resource.x).to eq 'hi1'
673
+ expect(Namer.current_index).to eq 1
674
+ end
675
+ it "when x is retrieved, coercion is run each time" do
676
+ expect(resource.x).to eq '101'
677
+ expect(resource.x).to eq '102'
678
+ expect(Namer.current_index).to eq 2
679
+ end
680
+ end
681
+
682
+ # Frozen lazy default, non-frozen coerce
683
+ with_property ':x, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
684
+ it "when the resource is created, the proc is not yet run" do
685
+ resource
686
+ expect(Namer.current_index).to eq 0
687
+ end
688
+ it "when x is set, coercion is run" do
689
+ expect(resource.x 'hi').to eq 'hi1'
690
+ expect(resource.x).to eq 'hi1'
691
+ expect(Namer.current_index).to eq 1
692
+ end
693
+ it "when x is retrieved, coercion is run exactly once" do
694
+ expect(resource.x).to eq '101'
695
+ expect(resource.x).to eq '101'
696
+ expect(Namer.current_index).to eq 1
697
+ end
698
+ end
699
+
700
+ # Non-frozen lazy default, frozen coerce
701
+ with_property ':x, coerce: proc { |v| "#{v}#{next_index}".freeze }, default: lazy { "10" }' do
702
+ it "when the resource is created, the proc is not yet run" do
703
+ resource
704
+ expect(Namer.current_index).to eq 0
705
+ end
706
+ it "when x is set, coercion is run" do
707
+ expect(resource.x 'hi').to eq 'hi1'
708
+ expect(resource.x).to eq 'hi1'
709
+ expect(Namer.current_index).to eq 1
710
+ end
711
+ it "when x is retrieved, coercion is run each time" do
712
+ expect(resource.x).to eq '101'
713
+ expect(resource.x).to eq '102'
714
+ expect(Namer.current_index).to eq 2
715
+ end
716
+ end
717
+
718
+ with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
719
+ it "coercion is only run the first time x is retrieved, and validation is not run" do
720
+ expect(Namer.current_index).to eq 0
721
+ expect(resource.x).to eq '101'
722
+ expect(Namer.current_index).to eq 1
723
+ expect(resource.x).to eq '101'
724
+ expect(Namer.current_index).to eq 1
725
+ end
726
+ end
727
+
728
+ context "validation and coercion of defaults" do
729
+ with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
730
+ it "when x is retrieved, it is coerced before validating and passes" do
731
+ expect(resource.x).to eq '101'
732
+ end
733
+ end
734
+ with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: 10' do
735
+ it "when x is retrieved, it is coerced and not validated" do
736
+ expect(resource.x).to eq '101'
737
+ end
738
+ # it "when x is retrieved, it is coerced before validating and fails" do
739
+ # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
740
+ # end
741
+ end
742
+ with_property ':x, String, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
743
+ it "when x is retrieved, it is coerced before validating and passes" do
744
+ expect(resource.x).to eq '101'
745
+ end
746
+ end
747
+ with_property ':x, Integer, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
748
+ it "when x is retrieved, it is coerced and not validated" do
749
+ expect(resource.x).to eq '101'
750
+ end
751
+ # it "when x is retrieved, it is coerced before validating and fails" do
752
+ # expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
753
+ # end
754
+ end
755
+ with_property ':x, proc { |v| Namer.next_index; true }, coerce: proc { |v| "#{v}#{next_index}" }, default: lazy { 10 }' do
756
+ it "coercion is only run the first time x is retrieved, and validation is not run" do
757
+ expect(Namer.current_index).to eq 0
758
+ expect(resource.x).to eq '101'
759
+ expect(Namer.current_index).to eq 1
760
+ expect(resource.x).to eq '101'
761
+ expect(Namer.current_index).to eq 1
762
+ end
763
+ end
764
+ end
765
+ end
766
+ end
767
+
768
+ context "Chef::Resource#lazy" do
769
+ with_property ':x' do
770
+ it "setting x to a lazy value does not run it immediately" do
771
+ resource.x lazy { Namer.next_index }
772
+ expect(Namer.current_index).to eq 0
773
+ end
774
+ it "you can set x to a lazy value in the instance" do
775
+ resource.instance_eval do
776
+ x lazy { Namer.next_index }
777
+ end
778
+ expect(resource.x).to eq 1
779
+ expect(Namer.current_index).to eq 1
780
+ end
781
+ it "retrieving a lazy value pops it open" do
782
+ resource.x lazy { Namer.next_index }
783
+ expect(resource.x).to eq 1
784
+ expect(Namer.current_index).to eq 1
785
+ end
786
+ it "retrieving a lazy value twice evaluates it twice" do
787
+ resource.x lazy { Namer.next_index }
788
+ expect(resource.x).to eq 1
789
+ expect(resource.x).to eq 2
790
+ expect(Namer.current_index).to eq 2
791
+ end
792
+ it "setting the same lazy value on two different instances runs it on each instancee" do
793
+ resource2 = resource_class.new("blah2")
794
+ l = lazy { Namer.next_index }
795
+ resource.x l
796
+ resource2.x l
797
+ expect(resource2.x).to eq 1
798
+ expect(resource.x).to eq 2
799
+ expect(resource2.x).to eq 3
800
+ end
801
+
802
+ context "when the class has a class and instance method named blah" do
803
+ before do
804
+ resource_class.class_eval do
805
+ def self.blah
806
+ "class"
807
+ end
808
+ def blah
809
+ "#{name}#{Namer.next_index}"
810
+ end
811
+ end
812
+ end
813
+ def blah
814
+ "example"
815
+ end
816
+ # it "retrieving lazy { blah } gets the instance variable" do
817
+ # resource.x lazy { blah }
818
+ # expect(resource.x).to eq "blah1"
819
+ # end
820
+ # it "retrieving lazy { blah } from two different instances gets two different instance variables" do
821
+ # resource2 = resource_class.new("another")
822
+ # l = lazy { blah }
823
+ # resource2.x l
824
+ # resource.x l
825
+ # expect(resource2.x).to eq "another1"
826
+ # expect(resource.x).to eq "blah2"
827
+ # expect(resource2.x).to eq "another3"
828
+ # end
829
+ it 'retrieving lazy { |x| "#{blah}#{x.blah}" } gets the example and instance variables' do
830
+ resource.x lazy { |x| "#{blah}#{x.blah}" }
831
+ expect(resource.x).to eq "exampleblah1"
832
+ end
833
+ it 'retrieving lazy { |x| "#{blah}#{x.blah}" } from two different instances gets two different instance variables' do
834
+ resource2 = resource_class.new("another")
835
+ l = lazy { |x| "#{blah}#{x.blah}" }
836
+ resource2.x l
837
+ resource.x l
838
+ expect(resource2.x).to eq "exampleanother1"
839
+ expect(resource.x).to eq "exampleblah2"
840
+ expect(resource2.x).to eq "exampleanother3"
841
+ end
842
+ end
843
+ end
844
+
845
+ with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
846
+ it "lazy values are not coerced on set" do
847
+ resource.x lazy { Namer.next_index }
848
+ expect(Namer.current_index).to eq 0
849
+ end
850
+ it "lazy values are coerced on get" do
851
+ resource.x lazy { Namer.next_index }
852
+ expect(resource.x).to eq "12"
853
+ expect(Namer.current_index).to eq 2
854
+ end
855
+ it "lazy values are coerced on each access" do
856
+ resource.x lazy { Namer.next_index }
857
+ expect(resource.x).to eq "12"
858
+ expect(Namer.current_index).to eq 2
859
+ expect(resource.x).to eq "34"
860
+ expect(Namer.current_index).to eq 4
861
+ end
862
+ end
863
+
864
+ with_property ':x, String' do
865
+ it "lazy values are not validated on set" do
866
+ resource.x lazy { Namer.next_index }
867
+ expect(Namer.current_index).to eq 0
868
+ end
869
+ it "lazy values are validated on get" do
870
+ resource.x lazy { Namer.next_index }
871
+ expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
872
+ expect(Namer.current_index).to eq 1
873
+ end
874
+ end
875
+
876
+ with_property ':x, is: proc { |v| Namer.next_index; true }' do
877
+ it "lazy values are validated on each access" do
878
+ resource.x lazy { Namer.next_index }
879
+ expect(resource.x).to eq 1
880
+ expect(Namer.current_index).to eq 2
881
+ expect(resource.x).to eq 3
882
+ expect(Namer.current_index).to eq 4
883
+ end
884
+ end
885
+
886
+ with_property ':x, Integer, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
887
+ it "lazy values are not validated or coerced on set" do
888
+ resource.x lazy { Namer.next_index }
889
+ expect(Namer.current_index).to eq 0
890
+ end
891
+ it "lazy values are coerced before being validated, which fails" do
892
+ resource.x lazy { Namer.next_index }
893
+ expect(Namer.current_index).to eq 0
894
+ expect { resource.x }.to raise_error Chef::Exceptions::ValidationFailed
895
+ expect(Namer.current_index).to eq 2
896
+ end
897
+ end
898
+
899
+ with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }, is: proc { |v| Namer.next_index; true }' do
900
+ it "lazy values are coerced and validated exactly once" do
901
+ resource.x lazy { Namer.next_index }
902
+ expect(resource.x).to eq "12"
903
+ expect(Namer.current_index).to eq 3
904
+ expect(resource.x).to eq "45"
905
+ expect(Namer.current_index).to eq 6
906
+ end
907
+ end
908
+
909
+ with_property ':x, String, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
910
+ it "lazy values are coerced before being validated, which succeeds" do
911
+ resource.x lazy { Namer.next_index }
912
+ expect(resource.x).to eq "12"
913
+ expect(Namer.current_index).to eq 2
914
+ end
915
+ end
916
+ end
917
+
918
+ context "Chef::Resource::Property#coerce" do
919
+ with_property ':x, coerce: proc { |v| "#{v}#{Namer.next_index}" }' do
920
+ it "coercion runs on set" do
921
+ expect(resource.x 10).to eq "101"
922
+ expect(Namer.current_index).to eq 1
923
+ end
924
+ it "coercion sets the value (and coercion does not run on get)" do
925
+ expect(resource.x 10).to eq "101"
926
+ expect(resource.x).to eq "101"
927
+ expect(Namer.current_index).to eq 1
928
+ end
929
+ it "coercion runs each time set happens" do
930
+ expect(resource.x 10).to eq "101"
931
+ expect(Namer.current_index).to eq 1
932
+ expect(resource.x 10).to eq "102"
933
+ expect(Namer.current_index).to eq 2
934
+ end
935
+ end
936
+ with_property ':x, coerce: proc { |x| Namer.next_index; raise "hi" if x == 10; x }, is: proc { |x| Namer.next_index; x != 10 }' do
937
+ it "failed coercion fails to set the value" do
938
+ resource.x 20
939
+ expect(resource.x).to eq 20
940
+ expect(Namer.current_index).to eq 2
941
+ expect { resource.x 10 }.to raise_error 'hi'
942
+ expect(resource.x).to eq 20
943
+ expect(Namer.current_index).to eq 3
944
+ end
945
+ it "validation does not run if coercion fails" do
946
+ expect { resource.x 10 }.to raise_error 'hi'
947
+ expect(Namer.current_index).to eq 1
948
+ end
949
+ end
950
+ end
951
+
952
+ context "Chef::Resource::Property validation" do
953
+ with_property ':x, is: proc { |v| Namer.next_index; v.is_a?(Integer) }' do
954
+ it "validation runs on set" do
955
+ expect(resource.x 10).to eq 10
956
+ expect(Namer.current_index).to eq 1
957
+ end
958
+ it "validation sets the value (and validation does not run on get)" do
959
+ expect(resource.x 10).to eq 10
960
+ expect(resource.x).to eq 10
961
+ expect(Namer.current_index).to eq 1
962
+ end
963
+ it "validation runs each time set happens" do
964
+ expect(resource.x 10).to eq 10
965
+ expect(Namer.current_index).to eq 1
966
+ expect(resource.x 10).to eq 10
967
+ expect(Namer.current_index).to eq 2
968
+ end
969
+ it "failed validation fails to set the value" do
970
+ expect(resource.x 10).to eq 10
971
+ expect(Namer.current_index).to eq 1
972
+ expect { resource.x 'blah' }.to raise_error Chef::Exceptions::ValidationFailed
973
+ expect(resource.x).to eq 10
974
+ expect(Namer.current_index).to eq 2
975
+ end
976
+ end
977
+ end
978
+
979
+ [ 'name_attribute', 'name_property' ].each do |name|
980
+ context "Chef::Resource::Property##{name}" do
981
+ with_property ":x, #{name}: true" do
982
+ it "defaults x to resource.name" do
983
+ expect(resource.x).to eq 'blah'
984
+ end
985
+ it "does not pick up resource.name if set" do
986
+ expect(resource.x 10).to eq 10
987
+ expect(resource.x).to eq 10
988
+ end
989
+ it "binds to the latest resource.name when run" do
990
+ resource.name 'foo'
991
+ expect(resource.x).to eq 'foo'
992
+ end
993
+ it "caches resource.name" do
994
+ expect(resource.x).to eq 'blah'
995
+ resource.name 'foo'
996
+ expect(resource.x).to eq 'blah'
997
+ end
998
+ end
999
+
1000
+ with_property ":x, #{name}: false" do
1001
+ it "defaults to nil" do
1002
+ expect(resource.x).to be_nil
1003
+ end
1004
+ end
1005
+
1006
+ with_property ":x, #{name}: nil" do
1007
+ it "defaults to nil" do
1008
+ expect(resource.x).to be_nil
1009
+ end
1010
+ end
1011
+
1012
+ context "default ordering deprecation warnings" do
1013
+ it "emits a deprecation warning for property :x, default: 10, #{name}: true" do
1014
+ expect { resource_class.property :x, :default => 10, name.to_sym => true }.to raise_error Chef::Exceptions::DeprecatedFeatureError,
1015
+ /Cannot specify both default and name_property together on property x of resource chef_resource_property_spec_(\d+). Only one \(default\) will be obeyed./
1016
+ end
1017
+ it "emits a deprecation warning for property :x, default: nil, #{name}: true" do
1018
+ expect { resource_class.property :x, :default => nil, name.to_sym => true }.to raise_error Chef::Exceptions::DeprecatedFeatureError,
1019
+ /Cannot specify both default and name_property together on property x of resource chef_resource_property_spec_(\d+). Only one \(name_property\) will be obeyed./
1020
+ end
1021
+ it "emits a deprecation warning for property :x, #{name}: true, default: 10" do
1022
+ expect { resource_class.property :x, name.to_sym => true, :default => 10 }.to raise_error Chef::Exceptions::DeprecatedFeatureError,
1023
+ /Cannot specify both default and name_property together on property x of resource chef_resource_property_spec_(\d+). Only one \(name_property\) will be obeyed./
1024
+ end
1025
+ it "emits a deprecation warning for property :x, #{name}: true, default: nil" do
1026
+ expect { resource_class.property :x, name.to_sym => true, :default => nil }.to raise_error Chef::Exceptions::DeprecatedFeatureError,
1027
+ /Cannot specify both default and name_property together on property x of resource chef_resource_property_spec_(\d+). Only one \(name_property\) will be obeyed./
1028
+ end
1029
+ end
1030
+
1031
+ context "default ordering" do
1032
+ before { Chef::Config[:treat_deprecation_warnings_as_errors] = false }
1033
+ with_property ":x, default: 10, #{name}: true" do
1034
+ it "chooses default over #{name}" do
1035
+ expect(resource.x).to eq 10
1036
+ end
1037
+ end
1038
+ with_property ":x, default: nil, #{name}: true" do
1039
+ it "chooses #{name} over default" do
1040
+ expect(resource.x).to eq 'blah'
1041
+ end
1042
+ end
1043
+ with_property ":x, #{name}: true, default: 10" do
1044
+ it "chooses #{name} over default" do
1045
+ expect(resource.x).to eq 'blah'
1046
+ end
1047
+ end
1048
+ with_property ":x, #{name}: true, default: nil" do
1049
+ it "chooses #{name} over default" do
1050
+ expect(resource.x).to eq 'blah'
1051
+ end
1052
+ end
1053
+ end
1054
+
1055
+ context "default ordering when #{name} is nil" do
1056
+ with_property ":x, #{name}: nil, default: 10" do
1057
+ it "chooses default" do
1058
+ expect(resource.x).to eq 10
1059
+ end
1060
+ end
1061
+ with_property ":x, default: 10, #{name}: nil" do
1062
+ it "chooses default" do
1063
+ expect(resource.x).to eq 10
1064
+ end
1065
+ end
1066
+ end
1067
+
1068
+ context "default ordering when #{name} is false" do
1069
+ with_property ":x, #{name}: false, default: 10" do
1070
+ it "chooses default" do
1071
+ expect(resource.x).to eq 10
1072
+ end
1073
+ end
1074
+ with_property ":x, default: 10, #{name}: nil" do
1075
+ it "chooses default" do
1076
+ expect(resource.x).to eq 10
1077
+ end
1078
+ end
1079
+ end
1080
+
1081
+ end
1082
+ end
1083
+
1084
+ it "raises an error if both name_property and name_attribute are specified" do
1085
+ expect { resource_class.property :x, :name_property => false, :name_attribute => 1 }.to raise_error ArgumentError,
1086
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
1087
+ expect { resource_class.property :x, :name_property => false, :name_attribute => nil }.to raise_error ArgumentError,
1088
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
1089
+ expect { resource_class.property :x, :name_property => false, :name_attribute => false }.to raise_error ArgumentError,
1090
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
1091
+ expect { resource_class.property :x, :name_property => true, :name_attribute => true }.to raise_error ArgumentError,
1092
+ /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
1093
+ end
1094
+ end