chef 13.6.4-universal-mingw32 → 13.7.16-universal-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. checksums.yaml +5 -5
  2. data/VERSION +1 -1
  3. data/acceptance/Gemfile +2 -2
  4. data/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb +1 -6
  5. data/distro/powershell/chef/chef.psm1 +1 -5
  6. data/lib/chef/api_client.rb +5 -5
  7. data/lib/chef/api_client_v1.rb +6 -6
  8. data/lib/chef/application.rb +3 -2
  9. data/lib/chef/application/knife.rb +4 -0
  10. data/lib/chef/chef_class.rb +2 -2
  11. data/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb +1 -1
  12. data/lib/chef/chef_fs/data_handler/data_handler_base.rb +2 -4
  13. data/lib/chef/client.rb +3 -3
  14. data/lib/chef/cookbook/chefignore.rb +4 -0
  15. data/lib/chef/cookbook/cookbook_collection.rb +2 -2
  16. data/lib/chef/cookbook/metadata.rb +2 -2
  17. data/lib/chef/data_bag.rb +1 -1
  18. data/lib/chef/deprecated.rb +10 -0
  19. data/lib/chef/event_dispatch/base.rb +2 -2
  20. data/lib/chef/http.rb +10 -10
  21. data/lib/chef/knife.rb +16 -15
  22. data/lib/chef/knife/configure.rb +12 -36
  23. data/lib/chef/knife/cookbook_upload.rb +4 -4
  24. data/lib/chef/knife/core/bootstrap_context.rb +1 -1
  25. data/lib/chef/knife/core/status_presenter.rb +6 -2
  26. data/lib/chef/knife/core/ui.rb +1 -1
  27. data/lib/chef/knife/data_bag_secret_options.rb +1 -1
  28. data/lib/chef/knife/data_bag_show.rb +1 -1
  29. data/lib/chef/knife/edit.rb +1 -1
  30. data/lib/chef/knife/ssh.rb +47 -35
  31. data/lib/chef/knife/user_create.rb +2 -0
  32. data/lib/chef/knife/user_delete.rb +2 -0
  33. data/lib/chef/knife/user_edit.rb +2 -0
  34. data/lib/chef/knife/user_reregister.rb +2 -0
  35. data/lib/chef/knife/user_show.rb +2 -0
  36. data/lib/chef/mixin/powershell_out.rb +1 -1
  37. data/lib/chef/node/attribute.rb +46 -70
  38. data/lib/chef/node/attribute_collections.rb +5 -5
  39. data/lib/chef/node/common_api.rb +1 -1
  40. data/lib/chef/node/immutable_collections.rb +180 -23
  41. data/lib/chef/node/mixin/state_tracking.rb +6 -6
  42. data/lib/chef/node_map.rb +63 -45
  43. data/lib/chef/property.rb +8 -8
  44. data/lib/chef/provider.rb +9 -3
  45. data/lib/chef/provider/apt_preference.rb +1 -1
  46. data/lib/chef/provider/apt_repository.rb +1 -1
  47. data/lib/chef/provider/apt_update.rb +1 -1
  48. data/lib/chef/provider/file.rb +1 -1
  49. data/lib/chef/provider/group/dscl.rb +6 -2
  50. data/lib/chef/provider/ifconfig.rb +96 -34
  51. data/lib/chef/provider/launchd.rb +0 -1
  52. data/lib/chef/provider/log.rb +3 -13
  53. data/lib/chef/provider/package/dnf.rb +1 -1
  54. data/lib/chef/provider/package/smartos.rb +2 -2
  55. data/lib/chef/provider/reboot.rb +12 -0
  56. data/lib/chef/provider/remote_directory.rb +1 -1
  57. data/lib/chef/provider/remote_file/http.rb +3 -2
  58. data/lib/chef/provider/service/solaris.rb +6 -2
  59. data/lib/chef/provider/systemd_unit.rb +34 -33
  60. data/lib/chef/provider/user/dscl.rb +1 -1
  61. data/lib/chef/provider/windows_path.rb +6 -7
  62. data/lib/chef/provider/windows_task.rb +89 -33
  63. data/lib/chef/provider/yum_repository.rb +24 -9
  64. data/lib/chef/resource/apt_package.rb +1 -0
  65. data/lib/chef/resource/apt_preference.rb +4 -0
  66. data/lib/chef/resource/apt_repository.rb +4 -0
  67. data/lib/chef/resource/apt_update.rb +3 -0
  68. data/lib/chef/resource/bash.rb +4 -0
  69. data/lib/chef/resource/batch.rb +5 -0
  70. data/lib/chef/resource/bff_package.rb +4 -0
  71. data/lib/chef/resource/breakpoint.rb +6 -0
  72. data/lib/chef/resource/cab_package.rb +6 -6
  73. data/lib/chef/resource/chef_gem.rb +13 -0
  74. data/lib/chef/resource/chocolatey_package.rb +4 -6
  75. data/lib/chef/resource/cookbook_file.rb +13 -15
  76. data/lib/chef/resource/cron.rb +2 -0
  77. data/lib/chef/resource/csh.rb +4 -0
  78. data/lib/chef/resource/directory.rb +8 -26
  79. data/lib/chef/resource/dnf_package.rb +5 -0
  80. data/lib/chef/resource/dpkg_package.rb +2 -0
  81. data/lib/chef/resource/dsc_resource.rb +5 -0
  82. data/lib/chef/resource/dsc_script.rb +6 -0
  83. data/lib/chef/resource/env.rb +3 -0
  84. data/lib/chef/resource/erl_call.rb +5 -0
  85. data/lib/chef/resource/execute.rb +5 -1
  86. data/lib/chef/resource/file.rb +2 -1
  87. data/lib/chef/resource/file/verification.rb +10 -0
  88. data/lib/chef/resource/freebsd_package.rb +10 -2
  89. data/lib/chef/resource/gem_package.rb +2 -0
  90. data/lib/chef/resource/git.rb +2 -0
  91. data/lib/chef/resource/group.rb +1 -0
  92. data/lib/chef/resource/homebrew_package.rb +3 -0
  93. data/lib/chef/resource/http_request.rb +2 -0
  94. data/lib/chef/resource/ifconfig.rb +23 -150
  95. data/lib/chef/resource/ips_package.rb +1 -0
  96. data/lib/chef/resource/ksh.rb +6 -0
  97. data/lib/chef/resource/launchd.rb +5 -4
  98. data/lib/chef/resource/link.rb +10 -0
  99. data/lib/chef/resource/log.rb +19 -46
  100. data/lib/chef/resource/macports_package.rb +1 -0
  101. data/lib/chef/resource/mdadm.rb +4 -0
  102. data/lib/chef/resource/mount.rb +1 -0
  103. data/lib/chef/resource/msu_package.rb +7 -8
  104. data/lib/chef/resource/ohai.rb +2 -0
  105. data/lib/chef/resource/openbsd_package.rb +3 -0
  106. data/lib/chef/resource/osx_profile.rb +10 -40
  107. data/lib/chef/resource/package.rb +6 -0
  108. data/lib/chef/resource/pacman_package.rb +1 -0
  109. data/lib/chef/resource/paludis_package.rb +3 -0
  110. data/lib/chef/resource/perl.rb +4 -0
  111. data/lib/chef/resource/portage_package.rb +1 -0
  112. data/lib/chef/resource/powershell_package.rb +5 -0
  113. data/lib/chef/resource/powershell_script.rb +8 -0
  114. data/lib/chef/resource/python.rb +4 -0
  115. data/lib/chef/resource/reboot.rb +14 -20
  116. data/lib/chef/resource/registry_key.rb +1 -0
  117. data/lib/chef/resource/remote_directory.rb +3 -0
  118. data/lib/chef/resource/remote_file.rb +2 -0
  119. data/lib/chef/resource/resource_notification.rb +17 -0
  120. data/lib/chef/resource/route.rb +1 -0
  121. data/lib/chef/resource/rpm_package.rb +1 -0
  122. data/lib/chef/resource/ruby.rb +4 -0
  123. data/lib/chef/resource/ruby_block.rb +3 -0
  124. data/lib/chef/resource/script.rb +4 -0
  125. data/lib/chef/resource/service.rb +1 -0
  126. data/lib/chef/resource/smartos_package.rb +1 -0
  127. data/lib/chef/resource/solaris_package.rb +1 -0
  128. data/lib/chef/resource/subversion.rb +1 -0
  129. data/lib/chef/resource/systemd_unit.rb +6 -0
  130. data/lib/chef/resource/template.rb +9 -0
  131. data/lib/chef/resource/user.rb +1 -0
  132. data/lib/chef/resource/windows_package.rb +2 -0
  133. data/lib/chef/resource/windows_path.rb +5 -10
  134. data/lib/chef/resource/windows_service.rb +3 -0
  135. data/lib/chef/resource/windows_task.rb +66 -87
  136. data/lib/chef/resource/yum_repository.rb +26 -22
  137. data/lib/chef/resource/zypper_package.rb +2 -0
  138. data/lib/chef/resource/zypper_repository.rb +6 -1
  139. data/lib/chef/run_context.rb +8 -2
  140. data/lib/chef/server_api.rb +1 -0
  141. data/lib/chef/util/selinux.rb +5 -4
  142. data/lib/chef/version.rb +1 -1
  143. data/lib/chef/version/platform.rb +18 -0
  144. data/lib/chef/version_constraint/platform.rb +2 -0
  145. data/spec/data/client.d_00/02-strings.rb +2 -0
  146. data/spec/functional/assets/chefinittest +6 -4
  147. data/spec/functional/knife/ssh_spec.rb +54 -7
  148. data/spec/functional/resource/bff_spec.rb +3 -3
  149. data/spec/functional/resource/ifconfig_spec.rb +1 -1
  150. data/spec/functional/resource/mount_spec.rb +7 -3
  151. data/spec/functional/resource/user/useradd_spec.rb +4 -4
  152. data/spec/functional/resource/windows_task_spec.rb +6 -6
  153. data/spec/functional/win32/security_spec.rb +7 -33
  154. data/spec/integration/knife/data_bag_show_spec.rb +1 -1
  155. data/spec/integration/recipes/noop_resource_spec.rb +1 -1
  156. data/spec/integration/recipes/recipe_dsl_spec.rb +30 -30
  157. data/spec/integration/recipes/resource_action_spec.rb +2 -2
  158. data/spec/integration/recipes/resource_converge_if_changed_spec.rb +71 -15
  159. data/spec/spec_helper.rb +19 -0
  160. data/spec/support/shared/functional/execute_resource.rb +1 -1
  161. data/spec/support/shared/unit/application_dot_d.rb +2 -0
  162. data/spec/support/shared/unit/execute_resource.rb +8 -1
  163. data/spec/support/shared/unit/provider/file.rb +9 -1
  164. data/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb +10 -7
  165. data/spec/unit/chef_fs/file_system/repository/directory_spec.rb +2 -2
  166. data/spec/unit/client_spec.rb +1 -1
  167. data/spec/unit/deprecated_spec.rb +4 -4
  168. data/spec/unit/http_spec.rb +9 -0
  169. data/spec/unit/knife/bootstrap_spec.rb +5 -0
  170. data/spec/unit/knife/configure_spec.rb +10 -60
  171. data/spec/unit/knife/data_bag_create_spec.rb +40 -2
  172. data/spec/unit/knife/data_bag_show_spec.rb +16 -2
  173. data/spec/unit/knife/ssh_spec.rb +85 -39
  174. data/spec/unit/knife_spec.rb +2 -0
  175. data/spec/unit/lwrp_spec.rb +5 -3
  176. data/spec/unit/mixin/powershell_type_coercions_spec.rb +7 -6
  177. data/spec/unit/node/attribute_spec.rb +55 -24
  178. data/spec/unit/node/immutable_collections_spec.rb +28 -14
  179. data/spec/unit/node/vivid_mash_spec.rb +27 -10
  180. data/spec/unit/node_map_spec.rb +34 -0
  181. data/spec/unit/property_spec.rb +13 -13
  182. data/spec/unit/provider/group/dscl_spec.rb +14 -5
  183. data/spec/unit/provider/ifconfig_spec.rb +10 -3
  184. data/spec/unit/provider/remote_file/http_spec.rb +23 -19
  185. data/spec/unit/provider/service/solaris_smf_service_spec.rb +6 -5
  186. data/spec/unit/provider/user/dscl_spec.rb +26 -0
  187. data/spec/unit/provider/windows_task_spec.rb +148 -4
  188. data/spec/unit/provider_spec.rb +1 -1
  189. data/spec/unit/resource/apt_package_spec.rb +1 -1
  190. data/spec/unit/resource/bash_spec.rb +8 -10
  191. data/spec/unit/resource/batch_spec.rb +1 -1
  192. data/spec/unit/resource/cab_package_spec.rb +19 -1
  193. data/spec/unit/resource/chef_gem_spec.rb +3 -3
  194. data/spec/unit/resource/chocolatey_package_spec.rb +10 -10
  195. data/spec/unit/resource/conditional_spec.rb +2 -2
  196. data/spec/unit/resource/cookbook_file_spec.rb +24 -30
  197. data/spec/unit/resource/cron_spec.rb +79 -82
  198. data/spec/unit/resource/csh_spec.rb +8 -10
  199. data/spec/unit/resource/deploy_spec.rb +1 -1
  200. data/spec/unit/resource/directory_spec.rb +28 -31
  201. data/spec/unit/resource/dnf_package_spec.rb +9 -9
  202. data/spec/unit/resource/env_spec.rb +7 -7
  203. data/spec/unit/resource/erl_call_spec.rb +9 -9
  204. data/spec/unit/resource/execute_spec.rb +6 -6
  205. data/spec/unit/resource/file/verification_spec.rb +18 -4
  206. data/spec/unit/resource/file_spec.rb +53 -56
  207. data/spec/unit/resource/freebsd_package_spec.rb +7 -7
  208. data/spec/unit/resource/gem_package_spec.rb +1 -1
  209. data/spec/unit/resource/git_spec.rb +7 -9
  210. data/spec/unit/resource/group_spec.rb +60 -70
  211. data/spec/unit/resource/http_request_spec.rb +16 -19
  212. data/spec/unit/resource/ifconfig_spec.rb +3 -3
  213. data/spec/unit/resource/ips_package_spec.rb +3 -5
  214. data/spec/unit/resource/ksh_spec.rb +8 -10
  215. data/spec/unit/resource/launchd_spec.rb +17 -10
  216. data/spec/unit/resource/link_spec.rb +53 -53
  217. data/spec/unit/resource/log_spec.rb +24 -28
  218. data/spec/unit/resource/mdadm_spec.rb +42 -44
  219. data/spec/unit/resource/mount_spec.rb +97 -99
  220. data/spec/unit/resource/msu_package_spec.rb +14 -8
  221. data/spec/unit/resource/ohai_spec.rb +15 -17
  222. data/spec/unit/resource/openbsd_package_spec.rb +3 -3
  223. data/spec/unit/resource/osx_profile_spec.rb +7 -7
  224. data/spec/unit/resource/package_spec.rb +36 -40
  225. data/spec/unit/resource/perl_spec.rb +8 -11
  226. data/spec/unit/resource/portage_package_spec.rb +8 -10
  227. data/spec/unit/resource/powershell_package_spec.rb +9 -9
  228. data/spec/unit/resource/python_spec.rb +8 -11
  229. data/spec/unit/resource/reboot_spec.rb +50 -0
  230. data/spec/unit/resource/registry_key_spec.rb +84 -98
  231. data/spec/unit/resource/remote_directory_spec.rb +40 -42
  232. data/spec/unit/resource/remote_file_spec.rb +78 -80
  233. data/spec/unit/resource/route_spec.rb +42 -44
  234. data/spec/unit/resource/rpm_package_spec.rb +5 -7
  235. data/spec/unit/resource/ruby_block_spec.rb +14 -16
  236. data/spec/unit/resource/ruby_spec.rb +8 -12
  237. data/spec/unit/resource/scm_spec.rb +66 -69
  238. data/spec/unit/resource/script_spec.rb +1 -1
  239. data/spec/unit/resource/service_spec.rb +80 -83
  240. data/spec/unit/resource/smartos_package_spec.rb +5 -0
  241. data/spec/unit/resource/solaris_package_spec.rb +3 -5
  242. data/spec/unit/resource/subversion_spec.rb +18 -16
  243. data/spec/unit/resource/systemd_unit_spec.rb +50 -54
  244. data/spec/unit/resource/template_spec.rb +56 -61
  245. data/spec/unit/resource/user_spec.rb +47 -53
  246. data/spec/unit/resource/windows_package_spec.rb +1 -1
  247. data/spec/unit/resource/windows_path_spec.rb +11 -8
  248. data/spec/unit/resource/windows_task_spec.rb +129 -33
  249. data/spec/unit/resource/yum_package_spec.rb +1 -1
  250. data/spec/unit/resource/yum_repository_spec.rb +61 -8
  251. data/spec/unit/resource/zypper_repository_spec.rb +17 -18
  252. data/spec/unit/util/selinux_spec.rb +3 -6
  253. data/tasks/dependencies.rb +0 -5
  254. data/tasks/rspec.rb +1 -1
  255. metadata +7 -19
  256. data/acceptance/.DS_Store +0 -0
  257. data/acceptance/.bundle/config +0 -2
  258. data/acceptance/top-cookbooks/.kitchen.docker.yml +0 -13
  259. data/acceptance/top-cookbooks/.kitchen.git.yml +0 -11
  260. data/distro/.DS_Store +0 -0
  261. data/lib/.DS_Store +0 -0
  262. data/lib/chef/.DS_Store +0 -0
  263. data/lib/chef/knife/.DS_Store +0 -0
  264. data/lib/chef/mixin/.DS_Store +0 -0
  265. data/spec/.DS_Store +0 -0
  266. data/spec/functional/.DS_Store +0 -0
  267. data/spec/support/.DS_Store +0 -0
  268. data/spec/unit/.DS_Store +0 -0
  269. data/tasks/.DS_Store +0 -0
@@ -63,13 +63,13 @@ class Chef
63
63
  MUTATOR_METHODS.each do |mutator|
64
64
  define_method(mutator) do |*args, &block|
65
65
  ret = super(*args, &block)
66
- send_reset_cache
66
+ send_reset_cache(__path__)
67
67
  ret
68
68
  end
69
69
  end
70
70
 
71
71
  def delete(key, &block)
72
- send_reset_cache(__path__, key)
72
+ send_reset_cache(__path__)
73
73
  super
74
74
  end
75
75
 
@@ -147,13 +147,13 @@ class Chef
147
147
  # object.
148
148
 
149
149
  def delete(key, &block)
150
- send_reset_cache(__path__, key)
150
+ send_reset_cache(__path__)
151
151
  super
152
152
  end
153
153
 
154
154
  MUTATOR_METHODS.each do |mutator|
155
155
  define_method(mutator) do |*args, &block|
156
- send_reset_cache
156
+ send_reset_cache(__path__)
157
157
  super(*args, &block)
158
158
  end
159
159
  end
@@ -174,7 +174,7 @@ class Chef
174
174
 
175
175
  def []=(key, value)
176
176
  ret = super
177
- send_reset_cache(__path__, key)
177
+ send_reset_cache(__path__)
178
178
  ret
179
179
  end
180
180
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright:: Copyright 2016, Chef Software, Inc.
2
+ # Copyright:: Copyright 2016-2017, Chef Software Inc.
3
3
  # License:: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,22 +30,16 @@ class Chef
30
30
  e
31
31
  end
32
32
 
33
- def convert_value(value)
33
+ def convert_value(value, path = nil)
34
34
  case value
35
35
  when Hash
36
- ImmutableMash.new(value, __root__, __node__, __precedence__)
36
+ ImmutableMash.new({}, __root__, __node__, __precedence__, path)
37
37
  when Array
38
- ImmutableArray.new(value, __root__, __node__, __precedence__)
39
- when ImmutableMash, ImmutableArray
40
- value
38
+ ImmutableArray.new([], __root__, __node__, __precedence__, path)
41
39
  else
42
40
  safe_dup(value).freeze
43
41
  end
44
42
  end
45
-
46
- def immutablize(value)
47
- convert_value(value)
48
- end
49
43
  end
50
44
 
51
45
  # == ImmutableArray
@@ -59,17 +53,51 @@ class Chef
59
53
  # Chef::Node::Attribute's values, it overrides all reader methods to
60
54
  # detect staleness and raise an error if accessed when stale.
61
55
  class ImmutableArray < Array
56
+ alias_method :internal_clear, :clear
57
+ alias_method :internal_replace, :replace
58
+ alias_method :internal_push, :<<
59
+ alias_method :internal_to_a, :to_a
60
+ alias_method :internal_each, :each
61
+ private :internal_push, :internal_replace, :internal_clear, :internal_each
62
+ protected :internal_to_a
63
+
62
64
  include Immutablize
63
65
 
64
- alias :internal_push :<<
65
- private :internal_push
66
+ methods = Array.instance_methods - Object.instance_methods +
67
+ [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ]
66
68
 
67
- def initialize(array_data = [])
68
- array_data.each do |value|
69
- internal_push(immutablize(value))
69
+ methods.each do |method|
70
+ define_method method do |*args, &block|
71
+ ensure_generated_cache!
72
+ super(*args, &block)
70
73
  end
71
74
  end
72
75
 
76
+ def each
77
+ ensure_generated_cache!
78
+ # aggressively pre generate the cache, works around ruby being too smart and fiddling with internals
79
+ internal_each { |i| i.ensure_generated_cache! if i.respond_to?(:ensure_generated_cache!) }
80
+ super
81
+ end
82
+
83
+ # because sometimes ruby gives us back Arrays or ImmutableArrays out of objects from things like #uniq or array slices
84
+ def return_normal_array(array)
85
+ if array.respond_to?(:internal_to_a, true)
86
+ array.internal_to_a
87
+ else
88
+ array.to_a
89
+ end
90
+ end
91
+
92
+ def uniq
93
+ ensure_generated_cache!
94
+ return_normal_array(super)
95
+ end
96
+
97
+ def initialize(array_data = [])
98
+ # Immutable collections no longer have initialized state
99
+ end
100
+
73
101
  # For elements like Fixnums, true, nil...
74
102
  def safe_dup(e)
75
103
  e.dup
@@ -96,8 +124,81 @@ class Chef
96
124
 
97
125
  alias_method :to_array, :to_a
98
126
 
127
+ def [](*args)
128
+ ensure_generated_cache!
129
+ args.length > 1 ? return_normal_array(super) : super # correctly handle array slices
130
+ end
131
+
132
+ def reset
133
+ @generated_cache = false
134
+ @short_circuit_attr_level = nil
135
+ internal_clear # redundant?
136
+ end
137
+
138
+ # @api private
139
+ def ensure_generated_cache!
140
+ generate_cache unless @generated_cache
141
+ @generated_cache = true
142
+ end
143
+
144
+ # This can be set to e.g. [ :@default ] by the parent container to cause this container
145
+ # to only use the default level and to bypass deep merging (the common case is either
146
+ # default-level or automatic-level and we aren't doing any deep merging). Right now it
147
+ # "optimized" for the case where we're no longer merging anything and only tracking a
148
+ # single level, and setting this to anything other than a size=1 array would behave
149
+ # in a broken fashion. That could be fixed, but the perf boost would likely not be
150
+ # that large in the typical case.
151
+ #
152
+ # @api private
153
+ attr_accessor :short_circuit_attr_levels
154
+
99
155
  private
100
156
 
157
+ # deep merging of array attribute within normal and override where they are merged together
158
+ def combined_components(components)
159
+ combined_values = nil
160
+ components.each do |component|
161
+ values = __node__.attributes.instance_variable_get(component).read(*__path__)
162
+ next unless values.is_a?(Array)
163
+ @tracked_components << component
164
+ combined_values ||= []
165
+ combined_values += values
166
+ end
167
+ combined_values
168
+ end
169
+
170
+ def get_array(component)
171
+ array = __node__.attributes.instance_variable_get(component).read(*__path__)
172
+ if array.is_a?(Array)
173
+ @tracked_components << component
174
+ array
175
+ end # else nil
176
+ end
177
+
178
+ def generate_cache
179
+ internal_clear
180
+ components = []
181
+ @tracked_components = []
182
+ if short_circuit_attr_levels
183
+ components << get_array(short_circuit_attr_levels.first)
184
+ else
185
+ components << combined_components(Attribute::DEFAULT_COMPONENTS)
186
+ components << get_array(:@normal)
187
+ components << combined_components(Attribute::OVERRIDE_COMPONENTS)
188
+ components << get_array(:@automatic)
189
+ end
190
+ highest = components.compact.last
191
+ if highest.is_a?(Array)
192
+ internal_replace( highest.each_with_index.map { |x, i| convert_value(x, __path__ + [ i ] ) } )
193
+ end
194
+ if @tracked_components.size == 1
195
+ # tracked_components is accurate enough to tell us if we're not really merging
196
+ internal_each do |key, value|
197
+ value.short_circuit_attr_levels = @tracked_components if value.respond_to?(:short_circuit_attr_levels)
198
+ end
199
+ end
200
+ end
201
+
101
202
  # needed for __path__
102
203
  def convert_key(key)
103
204
  key
@@ -120,19 +221,31 @@ class Chef
120
221
  # it is stale.
121
222
  # * Values can be accessed in attr_reader-like fashion via method_missing.
122
223
  class ImmutableMash < Mash
224
+ alias_method :internal_clear, :clear
225
+ alias_method :internal_key?, :key? # FIXME: could bypass convert_key in Mash for perf
226
+ alias_method :internal_each, :each
227
+
123
228
  include Immutablize
124
229
  include CommonAPI
125
230
 
231
+ methods = Hash.instance_methods - Object.instance_methods +
232
+ [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ]
233
+
234
+ methods.each do |method|
235
+ define_method method do |*args, &block|
236
+ ensure_generated_cache!
237
+ super(*args, &block)
238
+ end
239
+ end
240
+
126
241
  # this is for deep_merge usage, chef users must never touch this API
127
242
  # @api private
128
243
  def internal_set(key, value)
129
- regular_writer(key, convert_value(value))
244
+ regular_writer(key, convert_value(value, __path__ + [ key ]))
130
245
  end
131
246
 
132
247
  def initialize(mash_data = {})
133
- mash_data.each do |key, value|
134
- internal_set(key, value)
135
- end
248
+ # Immutable collections no longer have initialized state
136
249
  end
137
250
 
138
251
  alias :attribute? :has_key?
@@ -168,11 +281,55 @@ class Chef
168
281
 
169
282
  alias_method :to_hash, :to_h
170
283
 
171
- # For elements like Fixnums, true, nil...
172
- def safe_dup(e)
173
- e.dup
174
- rescue TypeError
175
- e
284
+ def [](key)
285
+ ensure_generated_cache!
286
+ super
287
+ end
288
+
289
+ alias_method :to_hash, :to_h
290
+
291
+ def reset
292
+ @generated_cache = false
293
+ @short_circuit_attr_level = nil
294
+ internal_clear # redundant?
295
+ end
296
+
297
+ # @api private
298
+ def ensure_generated_cache!
299
+ generate_cache unless @generated_cache
300
+ @generated_cache = true
301
+ end
302
+
303
+ # @api private
304
+ attr_accessor :short_circuit_attr_levels
305
+
306
+ private
307
+
308
+ def generate_cache
309
+ internal_clear
310
+ components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse
311
+ # tracked_components is not entirely accurate due to the short-circuit
312
+ tracked_components = []
313
+ components.each do |component|
314
+ subhash = __node__.attributes.instance_variable_get(component).read(*__path__)
315
+ unless subhash.nil? # FIXME: nil is used for not present
316
+ tracked_components << component
317
+ if subhash.kind_of?(Hash)
318
+ subhash.keys.each do |key|
319
+ next if internal_key?(key)
320
+ internal_set(key, subhash[key])
321
+ end
322
+ else
323
+ break
324
+ end
325
+ end
326
+ end
327
+ if tracked_components.size == 1
328
+ # tracked_components is accurate enough to tell us if we're not really merging
329
+ internal_each do |key, value|
330
+ value.short_circuit_attr_levels = tracked_components if value.respond_to?(:short_circuit_attr_levels)
331
+ end
332
+ end
176
333
  end
177
334
 
178
335
  prepend Chef::Node::Mixin::StateTracking
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright:: Copyright 2016, Chef Software, Inc.
2
+ # Copyright:: Copyright 2016-2017, Chef Software Inc.
3
3
  # License:: Apache License, Version 2.0
4
4
  #
5
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,11 +24,12 @@ class Chef
24
24
  attr_reader :__node__
25
25
  attr_reader :__precedence__
26
26
 
27
- def initialize(data = nil, root = self, node = nil, precedence = nil)
27
+ def initialize(data = nil, root = self, node = nil, precedence = nil, path = nil)
28
28
  # __path__ and __root__ must be nil when we call super so it knows
29
29
  # to avoid resetting the cache on construction
30
30
  data.nil? ? super() : super(data)
31
- @__path__ = []
31
+ @__path__ = path
32
+ @__path__ ||= []
32
33
  @__root__ = root
33
34
  @__node__ = node
34
35
  @__precedence__ = precedence
@@ -76,9 +77,8 @@ class Chef
76
77
  end
77
78
  end
78
79
 
79
- def send_reset_cache(path = nil, key = nil)
80
- next_path = [ path, key ].flatten.compact
81
- __root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !next_path.nil?
80
+ def send_reset_cache(path)
81
+ __root__.reset_cache(*path) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !path.nil?
82
82
  end
83
83
 
84
84
  def copy_state_to(ret, next_path)
@@ -16,6 +16,25 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ #
20
+ # example of a NodeMap entry for the user resource (as typed on the DSL):
21
+ #
22
+ # :user=>
23
+ # [{:klass=>Chef::Resource::User::AixUser, :os=>"aix"},
24
+ # {:klass=>Chef::Resource::User::DsclUser, :os=>"darwin"},
25
+ # {:klass=>Chef::Resource::User::PwUser, :os=>"freebsd"},
26
+ # {:klass=>Chef::Resource::User::LinuxUser, :os=>"linux"},
27
+ # {:klass=>Chef::Resource::User::SolarisUser,
28
+ # :os=>["omnios", "solaris2"]},
29
+ # {:klass=>Chef::Resource::User::WindowsUser, :os=>"windows"}],
30
+ #
31
+ # the entries in the array are pre-sorted into priority order (blocks/platform_version/platform/platform_family/os/none) so that
32
+ # the first entry's :klass that matches the filter is returned when doing a get.
33
+ #
34
+ # note that as this examples show filter values may be a scalar string or an array of scalar strings.
35
+ #
36
+ # XXX: confusingly, in the *_priority_map the :klass may be an array of Strings of class names
37
+ #
19
38
  class Chef
20
39
  class NodeMap
21
40
 
@@ -31,13 +50,12 @@ class Chef
31
50
  #
32
51
  # @return [NodeMap] Returns self for possible chaining
33
52
  #
34
- def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block)
35
- filters = {}
36
- filters[:platform] = platform if platform
37
- filters[:platform_version] = platform_version if platform_version
38
- filters[:platform_family] = platform_family if platform_family
39
- filters[:os] = os if os
40
- new_matcher = { value: value, filters: filters }
53
+ def set(key, klass, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block)
54
+ new_matcher = { klass: klass }
55
+ new_matcher[:platform] = platform if platform
56
+ new_matcher[:platform_version] = platform_version if platform_version
57
+ new_matcher[:platform_family] = platform_family if platform_family
58
+ new_matcher[:os] = os if os
41
59
  new_matcher[:block] = block if block
42
60
  new_matcher[:canonical] = canonical if canonical
43
61
  new_matcher[:override] = override if override
@@ -48,7 +66,10 @@ class Chef
48
66
  map[key] ||= []
49
67
  map[key].each_with_index do |matcher, index|
50
68
  cmp = compare_matchers(key, new_matcher, matcher)
51
- insert_at ||= index if cmp && cmp <= 0
69
+ if cmp && cmp <= 0
70
+ insert_at = index
71
+ break
72
+ end
52
73
  end
53
74
  if insert_at
54
75
  map[key].insert(insert_at, new_matcher)
@@ -68,11 +89,14 @@ class Chef
68
89
  # @param canonical [Boolean] `true` or `false` to match canonical or
69
90
  # non-canonical values only. `nil` to ignore canonicality. Default: `nil`
70
91
  #
71
- # @return [Object] Value
92
+ # @return [Object] Class
72
93
  #
73
94
  def get(node, key, canonical: nil)
74
- raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil?
75
- list(node, key, canonical: canonical).first
95
+ return nil unless map.has_key?(key)
96
+ map[key].map do |matcher|
97
+ return matcher[:klass] if node_matches?(node, matcher) && canonical_matches?(canonical, matcher)
98
+ end
99
+ nil
76
100
  end
77
101
 
78
102
  #
@@ -85,23 +109,22 @@ class Chef
85
109
  # @param canonical [Boolean] `true` or `false` to match canonical or
86
110
  # non-canonical values only. `nil` to ignore canonicality. Default: `nil`
87
111
  #
88
- # @return [Object] Value
112
+ # @return [Object] Class
89
113
  #
90
114
  def list(node, key, canonical: nil)
91
- raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil?
92
115
  return [] unless map.has_key?(key)
93
116
  map[key].select do |matcher|
94
117
  node_matches?(node, matcher) && canonical_matches?(canonical, matcher)
95
- end.map { |matcher| matcher[:value] }
118
+ end.map { |matcher| matcher[:klass] }
96
119
  end
97
120
 
98
121
  # Seriously, don't use this, it's nearly certain to change on you
99
122
  # @return remaining
100
123
  # @api private
101
- def delete_canonical(key, value)
124
+ def delete_canonical(key, klass)
102
125
  remaining = map[key]
103
126
  if remaining
104
- remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:value]) == Array(value) }
127
+ remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:klass]) == Array(klass) }
105
128
  if remaining.empty?
106
129
  map.delete(key)
107
130
  remaining = nil
@@ -143,7 +166,7 @@ class Chef
143
166
 
144
167
  filter_values.empty? ||
145
168
  Array(filter_values).any? do |v|
146
- Chef::VersionConstraint::Platform.new(v).include?(value)
169
+ Gem::Requirement.new(v).satisfied_by?(Gem::Version.new(value))
147
170
  end
148
171
  end
149
172
 
@@ -161,7 +184,7 @@ class Chef
161
184
 
162
185
  def node_matches?(node, matcher)
163
186
  return true if !node
164
- filters_match?(node, matcher[:filters]) && block_matches?(node, matcher[:block])
187
+ filters_match?(node, matcher) && block_matches?(node, matcher[:block])
165
188
  end
166
189
 
167
190
  def canonical_matches?(canonical, matcher)
@@ -171,17 +194,17 @@ class Chef
171
194
 
172
195
  # @api private
173
196
  def dispatch_compare_matchers(key, new_matcher, matcher)
174
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:block] }
197
+ cmp = compare_matcher_properties(new_matcher[:block], matcher[:block])
175
198
  return cmp if cmp != 0
176
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_version] }
199
+ cmp = compare_matcher_properties(new_matcher[:platform_version], matcher[:platform_version])
177
200
  return cmp if cmp != 0
178
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform] }
201
+ cmp = compare_matcher_properties(new_matcher[:platform], matcher[:platform])
179
202
  return cmp if cmp != 0
180
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_family] }
203
+ cmp = compare_matcher_properties(new_matcher[:platform_family], matcher[:platform_family])
181
204
  return cmp if cmp != 0
182
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:os] }
205
+ cmp = compare_matcher_properties(new_matcher[:os], matcher[:os])
183
206
  return cmp if cmp != 0
184
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:override] }
207
+ cmp = compare_matcher_properties(new_matcher[:override], matcher[:override])
185
208
  return cmp if cmp != 0
186
209
  # If all things are identical, return 0
187
210
  0
@@ -195,37 +218,32 @@ class Chef
195
218
  if cmp == 0
196
219
  # Sort by class name (ascending) as well, if all other properties
197
220
  # are exactly equal
198
- if new_matcher[:value].is_a?(Class) && !new_matcher[:override]
199
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:value].name }
221
+ # XXX: remove this in Chef-14 and use last-writer-wins (prepend if they match)
222
+ if !new_matcher[:override]
223
+ # we only sort classes, which only sorts the handler array, this magically does not sort
224
+ # the priority array via the invisible else here.
225
+ if new_matcher[:klass].is_a?(Class)
226
+ cmp = compare_matcher_properties(new_matcher[:klass].name, matcher[:klass].name)
227
+ end
200
228
  end
201
229
  end
202
230
  cmp
203
231
  end
204
232
 
205
- def compare_matcher_properties(new_matcher, matcher)
206
- a = yield(new_matcher)
207
- b = yield(matcher)
233
+ def compare_matcher_properties(a, b)
234
+ # falsity comparisons here handle both "nil" and "false"
235
+ return 1 if !a && b
236
+ return -1 if !b && a
237
+ return 0 if !a && !b
208
238
 
209
- # Check for blcacklists ('!windows'). Those always come *after* positive
239
+ # Check for blacklists ('!windows'). Those always come *after* positive
210
240
  # whitelists.
211
241
  a_negated = Array(a).any? { |f| f.is_a?(String) && f.start_with?("!") }
212
242
  b_negated = Array(b).any? { |f| f.is_a?(String) && f.start_with?("!") }
213
- if a_negated != b_negated
214
- return 1 if a_negated
215
- return -1 if b_negated
216
- end
243
+ return 1 if a_negated && !b_negated
244
+ return -1 if b_negated && !a_negated
217
245
 
218
- # We treat false / true and nil / not-nil with the same comparison
219
- a = nil if a == false
220
- b = nil if b == false
221
- cmp = a <=> b
222
- # This is the case where one is non-nil, and one is nil. The one that is
223
- # nil is "greater" (i.e. it should come last).
224
- if cmp.nil?
225
- return 1 if a.nil?
226
- return -1 if b.nil?
227
- end
228
- cmp
246
+ a <=> b
229
247
  end
230
248
 
231
249
  def map