puppet 6.0.0 → 6.1.0

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 (259) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/Gemfile.lock +20 -20
  4. data/Guardfile.example +76 -0
  5. data/LICENSE +189 -4
  6. data/README.md +3 -3
  7. data/Rakefile +5 -2
  8. data/ext/solaris/smf/svc-puppetd +8 -1
  9. data/ext/solaris/smf/svc-puppetmasterd +8 -1
  10. data/lib/puppet/application/apply.rb +100 -59
  11. data/lib/puppet/application/cert.rb +4 -114
  12. data/lib/puppet/application/device.rb +48 -32
  13. data/lib/puppet/application/script.rb +1 -1
  14. data/lib/puppet/application/ssl.rb +135 -51
  15. data/lib/puppet/application.rb +5 -0
  16. data/lib/puppet/configurer.rb +2 -3
  17. data/lib/puppet/defaults.rb +33 -49
  18. data/lib/puppet/etc.rb +20 -0
  19. data/lib/puppet/face/config.rb +3 -3
  20. data/lib/puppet/face/key.rb +1 -1
  21. data/lib/puppet/face/node/clean.rb +0 -1
  22. data/lib/puppet/feature/base.rb +1 -1
  23. data/lib/puppet/file_bucket/dipper.rb +1 -1
  24. data/lib/puppet/file_serving/fileset.rb +1 -1
  25. data/lib/puppet/functions/abs.rb +1 -1
  26. data/lib/puppet/functions/new.rb +1 -1
  27. data/lib/puppet/module/task.rb +29 -38
  28. data/lib/puppet/pal/catalog_compiler.rb +96 -0
  29. data/lib/puppet/pal/compiler.rb +221 -0
  30. data/lib/puppet/pal/function_signature.rb +52 -0
  31. data/lib/puppet/pal/json_catalog_encoder.rb +67 -0
  32. data/lib/puppet/pal/pal_api.rb +15 -0
  33. data/lib/puppet/pal/pal_impl.rb +523 -0
  34. data/lib/puppet/pal/plan_signature.rb +71 -0
  35. data/lib/puppet/pal/script_compiler.rb +71 -0
  36. data/lib/puppet/pal/task_signature.rb +58 -0
  37. data/lib/puppet/parser/catalog_compiler.rb +24 -0
  38. data/lib/puppet/parser/compiler.rb +3 -1
  39. data/lib/puppet/parser/functions/generate.rb +7 -6
  40. data/lib/puppet/plugins/configuration.rb +5 -1
  41. data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +3 -1
  42. data/lib/puppet/pops/evaluator/deferred_resolver.rb +3 -0
  43. data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -1
  44. data/lib/puppet/pops/evaluator/external_syntax_support.rb +3 -3
  45. data/lib/puppet/pops/evaluator/runtime3_converter.rb +2 -2
  46. data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +19 -10
  47. data/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  48. data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
  49. data/lib/puppet/pops/parser/lexer2.rb +1 -1
  50. data/lib/puppet/pops/pcore.rb +10 -33
  51. data/lib/puppet/pops/serialization/to_data_converter.rb +9 -1
  52. data/lib/puppet/pops/serialization.rb +1 -0
  53. data/lib/puppet/pops/types/p_timespan_type.rb +2 -2
  54. data/lib/puppet/pops/types/string_converter.rb +18 -4
  55. data/lib/puppet/pops/validation/checker4_0.rb +17 -2
  56. data/lib/puppet/provider/exec.rb +59 -57
  57. data/lib/puppet/provider/group/aix.rb +18 -2
  58. data/lib/puppet/provider/group/windows_adsi.rb +7 -3
  59. data/lib/puppet/provider/nameservice.rb +1 -25
  60. data/lib/puppet/provider/package/dnf.rb +2 -0
  61. data/lib/puppet/provider/package/pkgng.rb +37 -21
  62. data/lib/puppet/provider/package/portage.rb +2 -2
  63. data/lib/puppet/provider/package/windows/exe_package.rb +16 -10
  64. data/lib/puppet/provider/package/windows/msi_package.rb +8 -0
  65. data/lib/puppet/provider/package/windows/package.rb +9 -1
  66. data/lib/puppet/provider/package/windows.rb +2 -2
  67. data/lib/puppet/provider/package/yum.rb +1 -1
  68. data/lib/puppet/provider/parsedfile.rb +25 -4
  69. data/lib/puppet/provider/service/launchd.rb +19 -3
  70. data/lib/puppet/provider/service/smf.rb +54 -0
  71. data/lib/puppet/provider/service/systemd.rb +19 -0
  72. data/lib/puppet/provider/service/upstart.rb +1 -0
  73. data/lib/puppet/provider/service/windows.rb +22 -5
  74. data/lib/puppet/provider/user/aix.rb +48 -2
  75. data/lib/puppet/provider/user/useradd.rb +2 -10
  76. data/lib/puppet/provider/user/windows_adsi.rb +9 -1
  77. data/lib/puppet/resource/catalog.rb +1 -5
  78. data/lib/puppet/resource.rb +3 -1
  79. data/lib/puppet/ssl/host.rb +26 -16
  80. data/lib/puppet/syntax_checkers/epp.rb +34 -0
  81. data/lib/puppet/syntax_checkers/pp.rb +34 -0
  82. data/lib/puppet/transaction/event_manager.rb +13 -1
  83. data/lib/puppet/transaction/persistence.rb +1 -1
  84. data/lib/puppet/transaction/resource_harness.rb +3 -1
  85. data/lib/puppet/type/group.rb +29 -1
  86. data/lib/puppet/type/package.rb +5 -1
  87. data/lib/puppet/type/resources.rb +12 -2
  88. data/lib/puppet/type/schedule.rb +7 -0
  89. data/lib/puppet/type/service.rb +12 -0
  90. data/lib/puppet/type/user.rb +5 -2
  91. data/lib/puppet/type.rb +6 -0
  92. data/lib/puppet/util/command_line.rb +2 -3
  93. data/lib/puppet/util/execution.rb +15 -1
  94. data/lib/puppet/util/filetype.rb +56 -8
  95. data/lib/puppet/util/log/destinations.rb +3 -2
  96. data/lib/puppet/util/logging.rb +3 -2
  97. data/lib/puppet/util/posix.rb +15 -0
  98. data/lib/puppet/util/selinux.rb +1 -1
  99. data/lib/puppet/util/storage.rb +12 -0
  100. data/lib/puppet/util/windows/adsi.rb +79 -2
  101. data/lib/puppet/util/windows/api_types.rb +1 -1
  102. data/lib/puppet/util/windows/process.rb +23 -3
  103. data/lib/puppet/util/windows/registry.rb +29 -5
  104. data/lib/puppet/util/windows/security.rb +14 -0
  105. data/lib/puppet/util/windows/service.rb +294 -74
  106. data/lib/puppet/util/windows/user.rb +3 -5
  107. data/lib/puppet/util.rb +7 -3
  108. data/lib/puppet/version.rb +1 -1
  109. data/lib/puppet.rb +1 -0
  110. data/lib/puppet_pal.rb +5 -1099
  111. data/locales/ja/puppet.po +952 -986
  112. data/locales/puppet.pot +592 -347
  113. data/man/man5/puppet.conf.5 +26 -31
  114. data/man/man8/puppet-agent.8 +1 -1
  115. data/man/man8/puppet-apply.8 +1 -1
  116. data/man/man8/puppet-catalog.8 +1 -1
  117. data/man/man8/puppet-config.8 +4 -4
  118. data/man/man8/puppet-describe.8 +1 -1
  119. data/man/man8/puppet-device.8 +23 -19
  120. data/man/man8/puppet-doc.8 +1 -1
  121. data/man/man8/puppet-epp.8 +1 -1
  122. data/man/man8/puppet-facts.8 +1 -1
  123. data/man/man8/puppet-filebucket.8 +1 -1
  124. data/man/man8/puppet-generate.8 +1 -1
  125. data/man/man8/puppet-help.8 +1 -1
  126. data/man/man8/puppet-key.8 +2 -2
  127. data/man/man8/puppet-lookup.8 +1 -1
  128. data/man/man8/puppet-man.8 +1 -1
  129. data/man/man8/puppet-module.8 +1 -1
  130. data/man/man8/puppet-node.8 +1 -1
  131. data/man/man8/puppet-parser.8 +1 -1
  132. data/man/man8/puppet-plugin.8 +1 -1
  133. data/man/man8/puppet-report.8 +1 -1
  134. data/man/man8/puppet-resource.8 +1 -1
  135. data/man/man8/puppet-script.8 +1 -1
  136. data/man/man8/puppet-ssl.8 +26 -3
  137. data/man/man8/puppet-status.8 +1 -1
  138. data/man/man8/puppet.8 +2 -2
  139. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load.rb +11 -0
  140. data/spec/fixtures/unit/provider/package/pkgng/pkg.query +7 -1
  141. data/spec/fixtures/unit/provider/package/pkgng/pkg.query.zsh +1 -0
  142. data/spec/fixtures/unit/provider/service/smf/svcs_fmri.out +6 -0
  143. data/spec/fixtures/unit/provider/service/smf/svcs_multiple_fmris.out +13 -0
  144. data/spec/integration/application/apply_spec.rb +4 -1
  145. data/spec/integration/parser/collection_spec.rb +4 -8
  146. data/spec/integration/provider/service/windows_spec.rb +5 -5
  147. data/spec/integration/ssl/key_spec.rb +0 -4
  148. data/spec/integration/transaction_spec.rb +559 -0
  149. data/spec/integration/type/file_spec.rb +6 -6
  150. data/spec/integration/util/windows/registry_spec.rb +39 -0
  151. data/spec/integration/util/windows/security_spec.rb +10 -7
  152. data/spec/integration/util/windows/user_spec.rb +37 -17
  153. data/spec/lib/puppet/test_ca.rb +1 -1
  154. data/spec/spec_helper.rb +1 -1
  155. data/spec/unit/agent_spec.rb +2 -2
  156. data/spec/unit/application/apply_spec.rb +55 -2
  157. data/spec/unit/application/device_spec.rb +10 -7
  158. data/spec/unit/application/face_base_spec.rb +1 -1
  159. data/spec/unit/application/lookup_spec.rb +2 -1
  160. data/spec/unit/application/ssl_spec.rb +178 -109
  161. data/spec/unit/application_spec.rb +29 -11
  162. data/spec/unit/configurer/downloader_spec.rb +1 -1
  163. data/spec/unit/configurer_spec.rb +16 -5
  164. data/spec/unit/etc_spec.rb +25 -0
  165. data/spec/unit/face/node_spec.rb +1 -3
  166. data/spec/unit/face/parser_spec.rb +15 -0
  167. data/spec/unit/file_serving/fileset_spec.rb +11 -11
  168. data/spec/unit/functions/logging_spec.rb +10 -3
  169. data/spec/unit/indirector/catalog/json_spec.rb +9 -3
  170. data/spec/unit/indirector/yaml_spec.rb +1 -1
  171. data/spec/unit/network/http/connection_spec.rb +2 -2
  172. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +36 -0
  173. data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +22 -4
  174. data/spec/unit/pops/loaders/loader_spec.rb +9 -17
  175. data/spec/unit/pops/loaders/loaders_spec.rb +48 -0
  176. data/spec/unit/pops/loaders/module_loaders_spec.rb +7 -7
  177. data/spec/unit/pops/parser/parse_heredoc_spec.rb +16 -0
  178. data/spec/unit/pops/serialization/to_from_hr_spec.rb +9 -0
  179. data/spec/unit/pops/types/p_timespan_type_spec.rb +22 -0
  180. data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -0
  181. data/spec/unit/pops/types/string_converter_spec.rb +25 -1
  182. data/spec/unit/pops/types/task_spec.rb +42 -116
  183. data/spec/unit/pops/validator/validator_spec.rb +24 -10
  184. data/spec/unit/provider/exec/posix_spec.rb +24 -0
  185. data/spec/unit/provider/group/aix_spec.rb +20 -6
  186. data/spec/unit/provider/group/ldap_spec.rb +22 -25
  187. data/spec/unit/provider/group/pw_spec.rb +7 -10
  188. data/spec/unit/provider/group/windows_adsi_spec.rb +42 -33
  189. data/spec/unit/provider/nameservice/directoryservice_spec.rb +97 -103
  190. data/spec/unit/provider/package/aix_spec.rb +5 -8
  191. data/spec/unit/provider/package/apt_spec.rb +3 -6
  192. data/spec/unit/provider/package/dnf_spec.rb +38 -25
  193. data/spec/unit/provider/package/dpkg_spec.rb +18 -21
  194. data/spec/unit/provider/package/freebsd_spec.rb +4 -7
  195. data/spec/unit/provider/package/gem_spec.rb +41 -41
  196. data/spec/unit/provider/package/hpux_spec.rb +7 -10
  197. data/spec/unit/provider/package/macports_spec.rb +13 -15
  198. data/spec/unit/provider/package/nim_spec.rb +3 -10
  199. data/spec/unit/provider/package/openbsd_spec.rb +14 -17
  200. data/spec/unit/provider/package/pip3_spec.rb +3 -6
  201. data/spec/unit/provider/package/pip_spec.rb +45 -49
  202. data/spec/unit/provider/package/pkgin_spec.rb +13 -18
  203. data/spec/unit/provider/package/pkgng_spec.rb +32 -27
  204. data/spec/unit/provider/package/puppet_gem_spec.rb +6 -9
  205. data/spec/unit/provider/package/tdnf_spec.rb +9 -12
  206. data/spec/unit/provider/package/windows/exe_package_spec.rb +3 -3
  207. data/spec/unit/provider/package/windows_spec.rb +4 -4
  208. data/spec/unit/provider/package/yum_spec.rb +30 -16
  209. data/spec/unit/provider/package/zypper_spec.rb +17 -19
  210. data/spec/unit/provider/service/bsd_spec.rb +7 -9
  211. data/spec/unit/provider/service/daemontools_spec.rb +12 -16
  212. data/spec/unit/provider/service/debian_spec.rb +6 -10
  213. data/spec/unit/provider/service/freebsd_spec.rb +2 -2
  214. data/spec/unit/provider/service/launchd_spec.rb +19 -0
  215. data/spec/unit/provider/service/openbsd_spec.rb +13 -17
  216. data/spec/unit/provider/service/rcng_spec.rb +2 -4
  217. data/spec/unit/provider/service/redhat_spec.rb +12 -11
  218. data/spec/unit/provider/service/runit_spec.rb +7 -14
  219. data/spec/unit/provider/service/smf_spec.rb +77 -13
  220. data/spec/unit/provider/service/src_spec.rb +11 -16
  221. data/spec/unit/provider/service/systemd_spec.rb +39 -1
  222. data/spec/unit/provider/service/windows_spec.rb +39 -7
  223. data/spec/unit/provider/user/aix_spec.rb +43 -2
  224. data/spec/unit/provider/user/hpux_spec.rb +3 -5
  225. data/spec/unit/provider/user/ldap_spec.rb +29 -32
  226. data/spec/unit/provider/user/pw_spec.rb +10 -13
  227. data/spec/unit/provider/user/useradd_spec.rb +2 -2
  228. data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
  229. data/spec/unit/puppet_pal_2pec.rb +6 -6
  230. data/spec/unit/puppet_pal_catalog_spec.rb +58 -0
  231. data/spec/unit/resource/catalog_spec.rb +2 -2
  232. data/spec/unit/resource_spec.rb +31 -0
  233. data/spec/unit/ssl/host_spec.rb +22 -1
  234. data/spec/unit/ssl/key_spec.rb +2 -4
  235. data/spec/unit/task_spec.rb +50 -5
  236. data/spec/unit/transaction/event_manager_spec.rb +12 -1
  237. data/spec/unit/transaction/persistence_spec.rb +4 -4
  238. data/spec/unit/transaction/resource_harness_spec.rb +18 -0
  239. data/spec/unit/type/group_spec.rb +11 -3
  240. data/spec/unit/type/resources_spec.rb +18 -0
  241. data/spec/unit/type/service_spec.rb +27 -1
  242. data/spec/unit/util/execution_spec.rb +77 -0
  243. data/spec/unit/util/filetype_spec.rb +13 -5
  244. data/spec/unit/util/log/destinations_spec.rb +10 -0
  245. data/spec/unit/util/logging_spec.rb +58 -41
  246. data/spec/unit/util/monkey_patches_spec.rb +18 -5
  247. data/spec/unit/util/posix_spec.rb +28 -0
  248. data/spec/unit/util/selinux_spec.rb +4 -0
  249. data/spec/unit/util/storage_spec.rb +107 -0
  250. data/spec/unit/util/suidmanager_spec.rb +1 -3
  251. data/spec/unit/util/windows/adsi_spec.rb +95 -0
  252. data/spec/unit/util/windows/service_spec.rb +377 -131
  253. metadata +24 -11
  254. data/ext/autotest/Rakefile +0 -8
  255. data/ext/autotest/config +0 -43
  256. data/ext/autotest/readme.rst +0 -16
  257. data/spec/fixtures/unit/provider/package/pkgng/pkg.info +0 -7
  258. data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +0 -1
  259. data/spec/watchr.rb +0 -137
@@ -4,71 +4,73 @@ require 'puppet/util/execution'
4
4
  class Puppet::Provider::Exec < Puppet::Provider
5
5
  include Puppet::Util::Execution
6
6
 
7
- def run(command, check = false)
8
- output = nil
9
- sensitive = resource.parameters[:command].sensitive
7
+ def environment
8
+ env = {}
10
9
 
11
- checkexe(command)
10
+ if (path = resource[:path])
11
+ env[:PATH] = path.join(File::PATH_SEPARATOR)
12
+ end
13
+
14
+ return env unless (envlist = resource[:environment])
12
15
 
13
- if dir = resource[:cwd]
14
- unless File.directory?(dir)
15
- if check
16
- dir = nil
17
- else
18
- self.fail _("Working directory '%{dir}' does not exist") % { dir: dir }
19
- end
16
+ envlist = [envlist] unless envlist.is_a? Array
17
+ envlist.each do |setting|
18
+ unless (match = /^(\w+)=((.|\n)*)$/.match(setting))
19
+ warning _("Cannot understand environment setting %{setting}") % { setting: setting.inspect }
20
+ next
20
21
  end
22
+ var = match[1]
23
+ value = match[2]
24
+
25
+ if env.include?(var) || env.include?(var.to_sym)
26
+ warning _("Overriding environment setting '%{var}' with '%{value}'") % { var: var, value: value }
27
+ end
28
+
29
+ if value.nil? || value.empty?
30
+ msg = _("Empty environment setting '%{var}'") % {var: var}
31
+ Puppet.warn_once('undefined_variables', "empty_env_var_#{var}", msg, resource.file, resource.line)
32
+ end
33
+
34
+ env[var] = value
21
35
  end
22
36
 
23
- dir ||= Dir.pwd
37
+ env
38
+ end
39
+
40
+ def run(command, check = false)
41
+ output = nil
42
+ sensitive = resource.parameters[:command].sensitive
43
+
44
+ checkexe(command)
24
45
 
25
46
  debug "Executing#{check ? " check": ""} '#{sensitive ? '[redacted]' : command}'"
26
- begin
27
- # Do our chdir
28
- Dir.chdir(dir) do
29
- environment = {}
30
-
31
- environment[:PATH] = resource[:path].join(File::PATH_SEPARATOR) if resource[:path]
32
-
33
- if envlist = resource[:environment]
34
- envlist = [envlist] unless envlist.is_a? Array
35
- envlist.each do |setting|
36
- if setting =~ /^(\w+)=((.|\n)+)$/
37
- env_name = $1
38
- value = $2
39
- if environment.include?(env_name) || environment.include?(env_name.to_sym)
40
- warning _("Overriding environment setting '%{env_name}' with '%{value}'") % { env_name: env_name, value: value }
41
- end
42
- environment[env_name] = value
43
- else
44
- warning _("Cannot understand environment setting %{setting}") % { setting: setting.inspect }
45
- end
46
- end
47
- end
48
-
49
- # Ruby 2.1 and later interrupt execution in a way that bypasses error
50
- # handling by default. Passing Timeout::Error causes an exception to be
51
- # raised that can be rescued inside of the block by cleanup routines.
52
- #
53
- # This is backwards compatible all the way to Ruby 1.8.7.
54
- Timeout::timeout(resource[:timeout], Timeout::Error) do
55
- # note that we are passing "false" for the "override_locale" parameter, which ensures that the user's
56
- # default/system locale will be respected. Callers may override this behavior by setting locale-related
57
- # environment variables (LANG, LC_ALL, etc.) in their 'environment' configuration.
58
- output = Puppet::Util::Execution.execute(command, :failonfail => false, :combine => true,
59
- :uid => resource[:user], :gid => resource[:group],
60
- :override_locale => false,
61
- :custom_environment => environment,
62
- :sensitive => sensitive)
63
- end
64
- # The shell returns 127 if the command is missing.
65
- if output.exitstatus == 127
66
- raise ArgumentError, output
67
- end
68
47
 
69
- end
70
- rescue Errno::ENOENT => detail
71
- self.fail Puppet::Error, detail.to_s, detail
48
+ # Ruby 2.1 and later interrupt execution in a way that bypasses error
49
+ # handling by default. Passing Timeout::Error causes an exception to be
50
+ # raised that can be rescued inside of the block by cleanup routines.
51
+ #
52
+ # This is backwards compatible all the way to Ruby 1.8.7.
53
+ Timeout::timeout(resource[:timeout], Timeout::Error) do
54
+ cwd = resource[:cwd]
55
+ cwd ||= Dir.pwd
56
+
57
+ # note that we are passing "false" for the "override_locale" parameter, which ensures that the user's
58
+ # default/system locale will be respected. Callers may override this behavior by setting locale-related
59
+ # environment variables (LANG, LC_ALL, etc.) in their 'environment' configuration.
60
+ output = Puppet::Util::Execution.execute(
61
+ command,
62
+ :failonfail => false,
63
+ :combine => true,
64
+ :cwd => cwd,
65
+ :uid => resource[:user], :gid => resource[:group],
66
+ :override_locale => false,
67
+ :custom_environment => environment(),
68
+ :sensitive => sensitive
69
+ )
70
+ end
71
+ # The shell returns 127 if the command is missing.
72
+ if output.exitstatus == 127
73
+ raise ArgumentError, output
72
74
  end
73
75
 
74
76
  # Return output twice as processstatus was returned before, but only exitstatus was ever called.
@@ -57,8 +57,14 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
57
57
  # Define some Puppet Property => AIX Attribute (and vice versa)
58
58
  # conversion functions here. This is so we can unit test them.
59
59
 
60
- def members_to_users(members)
61
- return members unless members.is_a?(Array)
60
+ def members_to_users(provider, members)
61
+ members = members.split(',') if members.is_a?(String)
62
+ unless provider.resource[:auth_membership]
63
+ current_members = provider.members
64
+ current_members = [] if current_members == :absent
65
+ members = (members + current_members).uniq
66
+ end
67
+
62
68
  members.join(',')
63
69
  end
64
70
 
@@ -79,4 +85,14 @@ Puppet::Type.type(:group).provide :aix, :parent => Puppet::Provider::AixObject d
79
85
  # the resource methods (property getters + setters for our mapped
80
86
  # properties + a getter for the attributes property).
81
87
  mk_resource_methods
88
+
89
+ # We could add this to the top-level members property since the
90
+ # implementation is not platform-specific; however, it is best
91
+ # to do it this way so that we do not accidentally break something.
92
+ # This is ok for now, since we do plan on moving this and the
93
+ # auth_membership management over to the property class in a future
94
+ # Puppet release.
95
+ def members_insync?(current, should)
96
+ current.sort == @resource.parameter(:members).actual_should(current, should)
97
+ end
82
98
  end
@@ -23,9 +23,12 @@ Puppet::Type.type(:group).provide :windows_adsi do
23
23
  # Cannot use munge of the group property to canonicalize @should
24
24
  # since the default array_matching comparison is not commutative
25
25
 
26
- current_sids = current.map(&:sid)
27
26
  # dupes automatically weeded out when hashes built
28
- specified_sids = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should).keys.to_a
27
+ current_members = Puppet::Util::Windows::ADSI::Group.name_sid_hash(current)
28
+ specified_members = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
29
+
30
+ current_sids = current_members.keys.to_a
31
+ specified_sids = specified_members.keys.to_a
29
32
 
30
33
  if @resource[:auth_membership]
31
34
  current_sids.sort == specified_sids.sort
@@ -63,7 +66,8 @@ Puppet::Type.type(:group).provide :windows_adsi do
63
66
  end
64
67
 
65
68
  def members
66
- group.members
69
+ @members ||= Puppet::Util::Windows::ADSI::Group.name_sid_hash(group.members)
70
+ @members.keys
67
71
  end
68
72
 
69
73
  def members=(members)
@@ -247,31 +247,7 @@ class Puppet::Provider::NameService < Puppet::Provider
247
247
  # The list of all groups the user is a member of. Different
248
248
  # user mgmt systems will need to override this method.
249
249
  def groups
250
- groups = []
251
-
252
- # Reset our group list
253
- Puppet::Etc.setgrent
254
-
255
- user = @resource[:name]
256
-
257
- # Now iterate across all of the groups, adding each one our
258
- # user is a member of
259
- while group = Puppet::Etc.getgrent
260
- members = group.mem
261
-
262
- groups << group.name if members.include? user
263
- end
264
-
265
- # We have to close the file, so each listing is a separate
266
- # reading of the file.
267
- Puppet::Etc.endgrent
268
-
269
- uniq_groups = groups.uniq
270
- if groups != uniq_groups
271
- debug("Removing any duplicate group entries")
272
- end
273
- # remove any double listed groups
274
- uniq_groups.join(",")
250
+ Puppet::Util::POSIX.groups_of(@resource[:name]).join(',')
275
251
  end
276
252
 
277
253
  # Convert the Etc struct into a hash.
@@ -30,6 +30,8 @@ Puppet::Type.type(:package).provide :dnf, :parent => :yum do
30
30
 
31
31
  defaultfor :operatingsystem => :fedora
32
32
  notdefaultfor :operatingsystem => :fedora, :operatingsystemmajrelease => (19..21).to_a
33
+ defaultfor :osfamily => :redhat
34
+ notdefaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
33
35
 
34
36
  def self.update_command
35
37
  # In DNF, update is deprecated for upgrade
@@ -16,42 +16,53 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
16
16
  pkg(['query', '-a', '%n %v %o'])
17
17
  end
18
18
 
19
+ def self.get_resource_info(name)
20
+ pkg(['query', '%n %v %o', name])
21
+ end
22
+
23
+ def self.cached_version_list
24
+ @version_list ||= get_version_list
25
+ end
26
+
19
27
  def self.get_version_list
20
- pkg(['version', '-voRL='])
28
+ @version_list = pkg(['version', '-voRL='])
21
29
  end
22
30
 
23
- def self.get_latest_version(origin, version_list)
24
- if latest_version = version_list.lines.find { |l| l =~ /^#{origin} / }
31
+ def self.get_latest_version(origin)
32
+ if latest_version = cached_version_list.lines.find { |l| l =~ /^#{origin} / }
25
33
  latest_version = latest_version.split(' ').last.split(')').first
26
34
  return latest_version
27
35
  end
28
36
  nil
29
37
  end
30
38
 
39
+ def self.parse_pkg_query_line(line)
40
+ name, version, origin = line.chomp.split(' ', 3)
41
+ latest_version = get_latest_version(origin) || version
42
+
43
+ {
44
+ :ensure => version,
45
+ :name => name,
46
+ :provider => self.name,
47
+ :origin => origin,
48
+ :version => version,
49
+ :latest => latest_version
50
+ }
51
+ end
52
+
31
53
  def self.instances
32
54
  packages = []
33
55
  begin
34
56
  info = self.get_query
35
- version_list = self.get_version_list
57
+ get_version_list
36
58
 
37
59
  unless info
38
60
  return packages
39
61
  end
40
62
 
41
63
  info.lines.each do |line|
42
-
43
- name, version, origin = line.chomp.split(" ", 3)
44
- latest_version = get_latest_version(origin, version_list) || version
45
-
46
- pkg = {
47
- :ensure => version,
48
- :name => name,
49
- :provider => self.name,
50
- :origin => origin,
51
- :version => version,
52
- :latest => latest_version
53
- }
54
- packages << new(pkg)
64
+ hash = parse_pkg_query_line(line)
65
+ packages << new(hash)
55
66
  end
56
67
 
57
68
  return packages
@@ -113,18 +124,23 @@ Puppet::Type.type(:package).provide :pkgng, :parent => Puppet::Provider::Package
113
124
  end
114
125
 
115
126
  def query
116
- if @property_hash[:ensure] == nil
127
+ begin
128
+ output = self.class.get_resource_info(resource[:name])
129
+ rescue Puppet::ExecutionFailure
117
130
  return nil
118
- else
119
- version = @property_hash[:version]
120
- return { :version => version }
121
131
  end
132
+
133
+ self.class.parse_pkg_query_line(output)
122
134
  end
123
135
 
124
136
  def version
125
137
  @property_hash[:version]
126
138
  end
127
139
 
140
+ def version=
141
+ pkg(['install', '-qfy', "#{resource[:name]}-#{resource[:version]}"])
142
+ end
143
+
128
144
  # Upgrade to the latest version
129
145
  def update
130
146
  install
@@ -117,7 +117,7 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
117
117
  if match
118
118
  result_fields.zip(match.captures) do |field, value|
119
119
  # some fields can be empty or (null) (if we are not passed a category in the package name for instance)
120
- if value == '(null)'
120
+ if value == '(null)' || value == '<unset>'
121
121
  package_info[field] = nil
122
122
  elsif !value or value.empty?
123
123
  package_info[field] = nil
@@ -133,7 +133,7 @@ Puppet::Type.type(:package).provide :portage, :parent => Puppet::Provider::Packa
133
133
  end
134
134
 
135
135
  def qatom_output_format
136
- '"[%{CATEGORY}] [%{PN}] [%{PV}] [%[PR]] [%[SLOT]] [%[pfx]] [%[sfx]]"'
136
+ '"[%[CATEGORY]] [%[PN]] [%[PV]] [%[PR]] [%[SLOT]] [%[pfx]] [%[sfx]]"'
137
137
  end
138
138
 
139
139
  def qatom_result_format
@@ -4,6 +4,19 @@ class Puppet::Provider::Package::Windows
4
4
  class ExePackage < Puppet::Provider::Package::Windows::Package
5
5
  attr_reader :uninstall_string
6
6
 
7
+ # registry values to load under each product entry in
8
+ # HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
9
+ # for this provider
10
+ REG_VALUE_NAMES = [
11
+ 'DisplayVersion',
12
+ 'UninstallString',
13
+ 'ParentKeyName',
14
+ 'Security Update',
15
+ 'Update Rollup',
16
+ 'Hotfix',
17
+ 'WindowsInstaller',
18
+ ]
19
+
7
20
  # Return an instance of the package from the registry, or nil
8
21
  def self.from_registry(name, values)
9
22
  if valid?(name, values)
@@ -42,17 +55,10 @@ class Puppet::Provider::Package::Windows
42
55
  end
43
56
 
44
57
  def self.install_command(resource)
45
- ['cmd.exe', '/c', 'start', '"puppet-install"', '/w', munge(resource[:source])]
58
+ munge(resource[:source])
46
59
  end
47
60
 
48
61
  def uninstall_command
49
- # 1. Launch using cmd /c start because if the executable is a console
50
- # application Windows will automatically display its console window
51
- # 2. Specify a quoted title, otherwise if uninstall_string is quoted,
52
- # start will interpret that to be the title, and get confused
53
- # 3. Specify /w (wait) to wait for uninstall to finish
54
- command = ['cmd.exe', '/c', 'start', '"puppet-uninstall"', '/w']
55
-
56
62
  # Only quote bare uninstall strings, e.g.
57
63
  # C:\Program Files (x86)\Notepad++\uninstall.exe
58
64
  # Don't quote uninstall strings that are already quoted, e.g.
@@ -60,9 +66,9 @@ class Puppet::Provider::Package::Windows
60
66
  # Don't quote uninstall strings that contain arguments:
61
67
  # "C:\Program Files (x86)\Git\unins000.exe" /SILENT
62
68
  if uninstall_string =~ /\A[^"]*.exe\Z/i
63
- command << "\"#{uninstall_string}\""
69
+ command = "\"#{uninstall_string}\""
64
70
  else
65
- command << uninstall_string
71
+ command = uninstall_string
66
72
  end
67
73
 
68
74
  command
@@ -8,6 +8,14 @@ class Puppet::Provider::Package::Windows
8
8
  INSTALLSTATE_DEFAULT = 5 # product is installed for the current user
9
9
  INSTALLUILEVEL_NONE = 2 # completely silent installation
10
10
 
11
+ # registry values to load under each product entry in
12
+ # HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
13
+ # for this provider
14
+ REG_VALUE_NAMES = [
15
+ 'DisplayVersion',
16
+ 'WindowsInstaller'
17
+ ]
18
+
11
19
  # Get the COM installer object, it's in a separate method for testing
12
20
  def self.installer
13
21
  # REMIND: when does the COM release happen?
@@ -11,6 +11,14 @@ class Puppet::Provider::Package::Windows
11
11
 
12
12
  attr_reader :name, :version
13
13
 
14
+ REG_DISPLAY_VALUE_NAMES = [ 'DisplayName', 'QuietDisplayName' ]
15
+
16
+ def self.reg_value_names_to_load
17
+ REG_DISPLAY_VALUE_NAMES |
18
+ MsiPackage::REG_VALUE_NAMES |
19
+ ExePackage::REG_VALUE_NAMES
20
+ end
21
+
14
22
  # Enumerate each package. The appropriate package subclass
15
23
  # will be yielded.
16
24
  def self.each(&block)
@@ -37,7 +45,7 @@ class Puppet::Provider::Package::Windows
37
45
  open(hive, 'Software\Microsoft\Windows\CurrentVersion\Uninstall', mode) do |uninstall|
38
46
  each_key(uninstall) do |name, wtime|
39
47
  open(hive, "#{uninstall.keyname}\\#{name}", mode) do |key|
40
- yield key, values(key)
48
+ yield key, values_by_name(key, reg_value_names_to_load)
41
49
  end
42
50
  end
43
51
  end
@@ -63,14 +63,14 @@ Puppet::Type.type(:package).provide(:windows, :parent => Puppet::Provider::Packa
63
63
  installer = Puppet::Provider::Package::Windows::Package.installer_class(resource)
64
64
 
65
65
  command = [installer.install_command(resource), install_options].flatten.compact.join(' ')
66
- output = execute(command, :failonfail => false, :combine => true)
66
+ output = execute(command, :failonfail => false, :combine => true, :cwd => File.dirname(resource[:source]), :suppress_window => true)
67
67
 
68
68
  check_result(output.exitstatus)
69
69
  end
70
70
 
71
71
  def uninstall
72
72
  command = [package.uninstall_command, uninstall_options].flatten.compact.join(' ')
73
- output = execute(command, :failonfail => false, :combine => true)
73
+ output = execute(command, :failonfail => false, :combine => true, :suppress_window => true)
74
74
 
75
75
  check_result(output.exitstatus)
76
76
  end
@@ -23,7 +23,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
23
23
  end
24
24
  end
25
25
 
26
- defaultfor :osfamily => :redhat
26
+ defaultfor :osfamily => :redhat, :operatingsystemmajrelease => (4..7).to_a
27
27
 
28
28
  def self.prefetch(packages)
29
29
  raise Puppet::Error, _("The yum provider can only be used as root") if Process.euid != 0
@@ -10,11 +10,17 @@ require 'puppet/util/fileparsing'
10
10
  #
11
11
  # Once the provider prefetches the data, it's the resource's job to copy
12
12
  # that data over to the @is variables.
13
+ #
14
+ # NOTE: The prefetch method swallows FileReadErrors by treating the
15
+ # corresponding target as an empty file. If you would like to turn this
16
+ # behavior off, then set the raise_prefetch_errors class variable to
17
+ # true. Doing so will error all resources associated with the failed
18
+ # target.
13
19
  class Puppet::Provider::ParsedFile < Puppet::Provider
14
20
  extend Puppet::Util::FileParsing
15
21
 
16
22
  class << self
17
- attr_accessor :default_target, :target
23
+ attr_accessor :default_target, :target, :raise_prefetch_errors
18
24
  end
19
25
 
20
26
  attr_accessor :property_hash
@@ -89,6 +95,10 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
89
95
 
90
96
  # Flush all of the records relating to a specific target.
91
97
  def self.flush_target(target)
98
+ if @raise_prefetch_errors && @failed_prefetch_targets.key?(target)
99
+ raise Puppet::Error, _("Failed to read %{target}'s records when prefetching them. Reason: %{detail}") % { target: target, detail: @failed_prefetch_targets[target] }
100
+ end
101
+
92
102
  backup_target(target)
93
103
 
94
104
  records = target_records(target).reject { |r|
@@ -142,6 +152,10 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
142
152
  @records = []
143
153
  @target_objects = {}
144
154
 
155
+ # Hash of <target> => <failure reason>.
156
+ @failed_prefetch_targets = {}
157
+ @raise_prefetch_errors = false
158
+
145
159
  @target = nil
146
160
 
147
161
  # Default to flat files
@@ -260,12 +274,19 @@ class Puppet::Provider::ParsedFile < Puppet::Provider
260
274
 
261
275
  # Prefetch an individual target.
262
276
  def self.prefetch_target(target)
263
-
264
277
  begin
265
278
  target_records = retrieve(target)
266
279
  rescue Puppet::Util::FileType::FileReadError => detail
267
- puts detail.backtrace if Puppet[:trace]
268
- Puppet.err _("Could not prefetch %{resource} provider '%{name}' target '%{target}': %{detail}. Treating as empty") % { resource: self.resource_type.name, name: self.name, target: target, detail: detail }
280
+ if @raise_prefetch_errors
281
+ # We will raise an error later in flush_target. This way,
282
+ # only the resources linked to our target will fail
283
+ # evaluation.
284
+ @failed_prefetch_targets[target] = detail.to_s
285
+ else
286
+ puts detail.backtrace if Puppet[:trace]
287
+ Puppet.err _("Could not prefetch %{resource} provider '%{name}' target '%{target}': %{detail}. Treating as empty") % { resource: self.resource_type.name, name: self.name, target: target, detail: detail }
288
+ end
289
+
269
290
  target_records = []
270
291
  end
271
292
 
@@ -196,6 +196,22 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
196
196
  Puppet::Util::Plist.read_plist_file(path)
197
197
  end
198
198
 
199
+ # Read overrides plist, retrying if necessary
200
+ def self.read_overrides
201
+ i = 1
202
+ overrides = nil
203
+ loop do
204
+ Puppet.debug(_("Reading overrides plist, attempt %{i}") % {i: i}) if i > 1
205
+ overrides = read_plist(launchd_overrides)
206
+ break unless overrides.nil?
207
+ raise Puppet::Error.new(_('Unable to read overrides plist, too many attempts')) if i == 20
208
+ Puppet.info(_('Overrides file could not be read, trying again.'))
209
+ Kernel.sleep(0.1)
210
+ i += 1
211
+ end
212
+ overrides
213
+ end
214
+
199
215
  # Clean out the @property_hash variable containing the cached list of services
200
216
  def flush
201
217
  @property_hash.clear
@@ -300,7 +316,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
300
316
  _, job_plist = plist_from_label(resource[:name])
301
317
  job_plist_disabled = job_plist["Disabled"] if job_plist.has_key?("Disabled")
302
318
 
303
- if FileTest.file?(self.class.launchd_overrides) and overrides = self.class.read_plist(self.class.launchd_overrides)
319
+ if FileTest.file?(self.class.launchd_overrides) and overrides = self.class.read_overrides
304
320
  if overrides.has_key?(resource[:name])
305
321
  if self.class.get_os_version < 14
306
322
  overrides_disabled = overrides[resource[:name]]["Disabled"] if overrides[resource[:name]].has_key?("Disabled")
@@ -324,7 +340,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
324
340
  # rather than dealing with launchctl as it is unable to change the Disabled flag
325
341
  # without actually loading/unloading the job.
326
342
  def enable
327
- overrides = self.class.read_plist(self.class.launchd_overrides)
343
+ overrides = self.class.read_overrides
328
344
  if self.class.get_os_version < 14
329
345
  overrides[resource[:name]] = { "Disabled" => false }
330
346
  else
@@ -334,7 +350,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
334
350
  end
335
351
 
336
352
  def disable
337
- overrides = self.class.read_plist(self.class.launchd_overrides)
353
+ overrides = self.class.read_overrides
338
354
  if self.class.get_os_version < 14
339
355
  overrides[resource[:name]] = { "Disabled" => true }
340
356
  else
@@ -49,6 +49,52 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
49
49
  end
50
50
  end
51
51
 
52
+ # Returns the service's FMRI. We fail if multiple FMRIs correspond to
53
+ # @resource[:name].
54
+ #
55
+ # If the service does not exist or we fail to get any FMRIs from svcs,
56
+ # this method will raise a Puppet::Error
57
+ def service_fmri
58
+ return @fmri if @fmri
59
+
60
+ # `svcs -l` is better to use because we can detect service instances
61
+ # that have not yet been activated or enabled (i.e. it lets us detect
62
+ # services that svcadm has not yet touched). `svcs -H -o fmri` is a bit
63
+ # more limited.
64
+ lines = svcs("-l", @resource[:name]).chomp.lines.to_a
65
+ lines.select! { |line| line =~ /^fmri/ }
66
+ fmris = lines.map! { |line| line.split(' ')[-1].chomp }
67
+ unless fmris.length == 1
68
+ raise Puppet::Error, _("Failed to get the FMRI of the %{service} service: The pattern '%{service}' matches multiple FMRIs! These are the FMRIs it matches: %{all_fmris}") % { service: @resource[:name], all_fmris: fmris.join(', ') }
69
+ end
70
+
71
+ @fmri = fmris.first
72
+ end
73
+
74
+ # Returns true if the provider supports incomplete services.
75
+ def supports_incomplete_services?
76
+ Puppet::Util::Package.versioncmp(Facter.value(:operatingsystemrelease), '11.1') >= 0
77
+ end
78
+
79
+ # Returns true if the service is complete. A complete service is a service that
80
+ # has the general/complete property defined.
81
+ def complete_service?
82
+ unless supports_incomplete_services?
83
+ raise Puppet::Error, _("Cannot query if the %{service} service is complete: The concept of complete/incomplete services was introduced in Solaris 11.1. You are on a Solaris %{release} machine.") % { service: @resource[:name], release: Facter.value(:operatingsystemrelease) }
84
+ end
85
+
86
+ return @complete_service if @complete_service
87
+
88
+ # We need to use the service's FMRI when querying its config. because
89
+ # general/complete is an instance-specific property.
90
+ fmri = service_fmri
91
+
92
+ # Check if the general/complete property is defined. If it is undefined,
93
+ # then svccfg will not print anything to the console.
94
+ property_defn = svccfg("-s", fmri, "listprop", "general/complete").chomp
95
+ @complete_service = ! property_defn.empty?
96
+ end
97
+
52
98
  def enable
53
99
  self.start
54
100
  end
@@ -131,6 +177,14 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
131
177
  end
132
178
 
133
179
  begin
180
+ if supports_incomplete_services?
181
+ unless complete_service?
182
+ debug _("The %{service} service is incomplete so its status will be reported as :stopped. See `svcs -xv %{fmri}` for more details.") % { service: @resource[:name], fmri: service_fmri }
183
+
184
+ return :stopped
185
+ end
186
+ end
187
+
134
188
  # get the current state and the next state, and if the next
135
189
  # state is set (i.e. not "-") use it for state comparison
136
190
  states = service_states