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
@@ -26,6 +26,8 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
26
26
  defaultfor :operatingsystem => :amazon, :operatingsystemmajrelease => ["2"]
27
27
  defaultfor :operatingsystem => :debian, :operatingsystemmajrelease => ["8", "stretch/sid", "9", "buster/sid"]
28
28
 
29
+ defaultfor :operatingsystem => :LinuxMint
30
+ notdefaultfor :operatingsystem => :LinuxMint, :operatingsystemmajrelease => ["10", "11", "12", "13", "14", "15", "16", "17"] # These are using upstart
29
31
  defaultfor :operatingsystem => :ubuntu
30
32
  notdefaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => ["10.04", "12.04", "14.04", "14.10"] # These are using upstart
31
33
  defaultfor :operatingsystem => :cumuluslinux, :operatingsystemmajrelease => ["3"]
@@ -123,6 +125,21 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
123
125
  end
124
126
  end
125
127
 
128
+ # Define the daemon_reload? function to check if the unit is requiring to trigger a "systemctl daemon-reload"
129
+ # If the unit file is flagged with NeedDaemonReload=yes, then a systemd daemon-reload will be run.
130
+ # If multiple unit files have been updated, the first one flagged will trigger the daemon-reload for all of them.
131
+ # The others will be then flagged with NeedDaemonReload=no. So the command will run only once in a puppet run.
132
+ # This function is called only on start & restart unit options.
133
+ # Reference: (PUP-3483) Systemd provider doesn't scan for changed units
134
+ def daemon_reload?
135
+ cmd = [command(:systemctl), 'show', @resource[:name], '--property=NeedDaemonReload']
136
+ daemon_reload = execute(cmd, :failonfail => false).strip.split('=').last
137
+ if daemon_reload == 'yes'
138
+ daemon_reload_cmd = [command(:systemctl), 'daemon-reload']
139
+ execute(daemon_reload_cmd, :failonfail => false)
140
+ end
141
+ end
142
+
126
143
  def enable
127
144
  self.unmask
128
145
  systemctl_change_enable(:enable)
@@ -156,6 +173,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
156
173
 
157
174
  def restart
158
175
  begin
176
+ daemon_reload?
159
177
  super
160
178
  rescue Puppet::Error => e
161
179
  raise Puppet::Error.new(prepare_error_message(@resource[:name], 'restart', e))
@@ -164,6 +182,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
164
182
 
165
183
  def start
166
184
  begin
185
+ daemon_reload?
167
186
  super
168
187
  rescue Puppet::Error => e
169
188
  raise Puppet::Error.new(prepare_error_message(@resource[:name], 'start', e))
@@ -17,6 +17,7 @@ Puppet::Type.type(:service).provide :upstart, :parent => :debian do
17
17
  ]
18
18
 
19
19
  defaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => ["10.04", "12.04", "14.04", "14.10"]
20
+ defaultfor :operatingsystem => :LinuxMint, :operatingsystemmajrelease => ["10", "11", "12", "13", "14", "15", "16", "17"]
20
21
 
21
22
  commands :start => "/sbin/start",
22
23
  :stop => "/sbin/stop",
@@ -15,6 +15,7 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
15
15
  confine :operatingsystem => :windows
16
16
 
17
17
  has_feature :refreshable
18
+ has_feature :configurable_timeout
18
19
 
19
20
  def enable
20
21
  Puppet::Util::Windows::Service.set_startup_mode( @resource[:name], :SERVICE_AUTO_START )
@@ -35,6 +36,8 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
35
36
  end
36
37
 
37
38
  def enabled?
39
+ return :false unless Puppet::Util::Windows::Service.exists?(@resource[:name])
40
+
38
41
  start_type = Puppet::Util::Windows::Service.service_start_type(@resource[:name])
39
42
  debug("Service #{@resource[:name]} start type is #{start_type}")
40
43
  case start_type
@@ -54,6 +57,13 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
54
57
  end
55
58
 
56
59
  def start
60
+ if status == :paused
61
+ Puppet::Util::Windows::Service.resume(@resource[:name], timeout: @resource[:timeout])
62
+ return
63
+ end
64
+
65
+ # status == :stopped here
66
+
57
67
  if enabled? == :false
58
68
  # If disabled and not managing enable, respect disabled and fail.
59
69
  if @resource[:enable].nil?
@@ -66,21 +76,24 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
66
76
  manual_start
67
77
  end
68
78
  end
69
- Puppet::Util::Windows::Service.start(@resource[:name])
79
+ Puppet::Util::Windows::Service.start(@resource[:name], timeout: @resource[:timeout])
70
80
  end
71
81
 
72
82
  def stop
73
- Puppet::Util::Windows::Service.stop(@resource[:name])
83
+ Puppet::Util::Windows::Service.stop(@resource[:name], timeout: @resource[:timeout])
74
84
  end
75
85
 
76
86
  def status
87
+ return :stopped unless Puppet::Util::Windows::Service.exists?(@resource[:name])
88
+
77
89
  current_state = Puppet::Util::Windows::Service.service_state(@resource[:name])
78
90
  state = case current_state
79
91
  when :SERVICE_STOPPED,
80
- :SERVICE_PAUSED,
81
- :SERVICE_STOP_PENDING,
82
- :SERVICE_PAUSE_PENDING
92
+ :SERVICE_STOP_PENDING
83
93
  :stopped
94
+ when :SERVICE_PAUSED,
95
+ :SERVICE_PAUSE_PENDING
96
+ :paused
84
97
  when :SERVICE_RUNNING,
85
98
  :SERVICE_CONTINUE_PENDING,
86
99
  :SERVICE_START_PENDING
@@ -92,6 +105,10 @@ Puppet::Type.type(:service).provide :windows, :parent => :service do
92
105
  return state
93
106
  end
94
107
 
108
+ def default_timeout
109
+ Puppet::Util::Windows::Service::DEFAULT_TIMEOUT
110
+ end
111
+
95
112
  # returns all providers for all existing services and startup state
96
113
  def self.instances
97
114
  services = []
@@ -10,6 +10,7 @@
10
10
  # See https://puppet.com/docs/puppet/latest/provider_development.html
11
11
  # for more information
12
12
  require 'puppet/provider/aix_object'
13
+ require 'puppet/util/posix'
13
14
  require 'tempfile'
14
15
  require 'date'
15
16
 
@@ -76,13 +77,23 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
76
77
  # a String, etc. in the property. This routine does a final check to
77
78
  # ensure our value doesn't have whitespace before we convert it to
78
79
  # an attribute.
79
- def groups_to_groups(groups)
80
+ def groups_property_to_attribute(groups)
80
81
  if groups =~ /\s/
81
82
  raise ArgumentError, _("Invalid value %{groups}: Groups must be comma separated!") % { groups: groups }
82
83
  end
83
84
 
84
85
  groups
85
86
  end
87
+
88
+ # We do not directly use the groups attribute value because that will
89
+ # always include the primary group, even if our user is not one of its
90
+ # members. Instead, we retrieve our property value by parsing the etc/group file,
91
+ # which matches what we do on our other POSIX platforms like Linux and Solaris.
92
+ #
93
+ # See https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.files/group_security.htm
94
+ def groups_attribute_to_property(provider, _groups)
95
+ Puppet::Util::POSIX.groups_of(provider.resource[:name]).join(',')
96
+ end
86
97
  end
87
98
 
88
99
  mapping puppet_property: :comment,
@@ -99,7 +110,8 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
99
110
  attribute_to_property: method(:pgrp_to_gid)
100
111
 
101
112
  mapping puppet_property: :groups,
102
- property_to_attribute: method(:groups_to_groups)
113
+ property_to_attribute: method(:groups_property_to_attribute),
114
+ attribute_to_property: method(:groups_attribute_to_property)
103
115
 
104
116
  mapping puppet_property: :home
105
117
  mapping puppet_property: :shell
@@ -121,6 +133,24 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
121
133
  # properties + a getter for the attributes property).
122
134
  mk_resource_methods
123
135
 
136
+ # Setting the primary group (pgrp attribute) on AIX causes both the
137
+ # current and new primary groups to be included in our user's groups,
138
+ # which is undesirable behavior. Thus, this custom setter resets the
139
+ # 'groups' property back to its previous value after setting the primary
140
+ # group.
141
+ def gid=(value)
142
+ old_pgrp = gid
143
+ cur_groups = groups
144
+
145
+ set(:gid, value)
146
+
147
+ begin
148
+ self.groups = cur_groups
149
+ rescue Puppet::Error => detail
150
+ raise Puppet::Error, _("Could not reset the groups property back to %{cur_groups} after setting the primary group on %{resource}[%{name}]. This means that the previous primary group of %{old_pgrp} and the new primary group of %{new_pgrp} have been added to %{cur_groups}. You will need to manually reset the groups property if this is undesirable behavior. Detail: %{detail}") % { cur_groups: cur_groups, resource: @resource.class.name, name: @resource.name, old_pgrp: old_pgrp, new_pgrp: value, detail: detail }, detail.backtrace
151
+ end
152
+ end
153
+
124
154
  # Helper function that parses the password from the given
125
155
  # password filehandle. This is here to make testing easier
126
156
  # for #password since we cannot configure Mocha to mock out
@@ -213,6 +243,22 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
213
243
  def create
214
244
  super
215
245
 
246
+ # We specify the 'groups' AIX attribute in AixObject's create method
247
+ # when creating our user. However, this does not always guarantee that
248
+ # our 'groups' property is set to the right value. For example, the
249
+ # primary group will always be included in the 'groups' property. This is
250
+ # bad if we're explicitly managing the 'groups' property under inclusive
251
+ # membership, and we are not specifying the primary group in the 'groups'
252
+ # property value.
253
+ #
254
+ # Setting the groups property here a second time will ensure that our user is
255
+ # created and in the right state. Note that this is an idempotent operation,
256
+ # so if AixObject's create method already set it to the right value, then this
257
+ # will noop.
258
+ if (groups = @resource.should(:groups))
259
+ self.groups = groups
260
+ end
261
+
216
262
  if (password = @resource.should(:password))
217
263
  self.password = password
218
264
  end
@@ -134,15 +134,6 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
134
134
  cmd
135
135
  end
136
136
 
137
- def check_manage_expiry
138
- cmd = []
139
- if @resource[:expiry] and not @resource.forcelocal?
140
- cmd << "-e #{@resource[:expiry]}"
141
- end
142
-
143
- cmd
144
- end
145
-
146
137
  def check_system_users
147
138
  if self.class.system_users? and resource.system?
148
139
  ["-r"]
@@ -188,7 +179,8 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
188
179
 
189
180
  def modifycmd(param, value)
190
181
  if @resource.forcelocal?
191
- if param == :groups
182
+ case param
183
+ when :groups, :expiry
192
184
  cmd = [command(:modify)]
193
185
  else
194
186
  cmd = [command(property_manages_password_age?(param) ? :localpassword : :localmodify)]
@@ -124,7 +124,15 @@ Puppet::Type.type(:user).provide :windows_adsi do
124
124
  end
125
125
 
126
126
  def password=(value)
127
- user.password = value
127
+ if user.disabled?
128
+ warning _("The user account '%s' is disabled; puppet will not reset the password" % @resource[:name])
129
+ elsif user.locked_out?
130
+ warning _("The user account '%s' is locked out; puppet will not reset the password" % @resource[:name])
131
+ elsif user.expired?
132
+ warning _("The user account '%s' is expired; puppet will not reset the password" % @resource[:name])
133
+ else
134
+ user.password = value
135
+ end
128
136
  end
129
137
 
130
138
  def uid
@@ -558,11 +558,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
558
558
  Puppet::FileSystem.open(resourcefile.value, resourcefile.mode.to_i(8), "w:UTF-8") do |f|
559
559
  to_print = resources.map do |resource|
560
560
  next unless resource.managed?
561
- if resource.name_var
562
- "#{resource.type}[#{resource[resource.name_var]}]"
563
- else
564
- "#{resource.ref.downcase}"
565
- end
561
+ "#{resource.ref.downcase}"
566
562
  end.compact
567
563
  f.puts to_print.join("\n")
568
564
  end
@@ -583,7 +583,9 @@ class Puppet::Resource
583
583
  delete(attribute)
584
584
  end
585
585
 
586
- parameters_to_include = options[:parameters_to_include] || []
586
+ parameters_to_include = resource_type.parameters_to_include
587
+ parameters_to_include += options[:parameters_to_include] || []
588
+
587
589
  delete(attribute) unless properties.include?(attribute) || parameters_to_include.include?(attribute)
588
590
  end
589
591
  self
@@ -23,7 +23,7 @@ class Puppet::SSL::Host
23
23
  Certificate = Puppet::SSL::Certificate
24
24
  CertificateRequest = Puppet::SSL::CertificateRequest
25
25
 
26
- attr_reader :name, :crl_path
26
+ attr_reader :name, :device, :crl_path
27
27
 
28
28
  attr_writer :key, :certificate, :certificate_request, :crl_usage
29
29
 
@@ -146,6 +146,17 @@ class Puppet::SSL::Host
146
146
  @certificate
147
147
  end
148
148
 
149
+ # The puppet parameters for commands output by the validate_ methods depend
150
+ # upon whether this is an agent or a device.
151
+
152
+ def clean_params
153
+ @device ? "--target #{Puppet[:certname]}" : ''
154
+ end
155
+
156
+ def puppet_params
157
+ @device ? "device -v --target #{Puppet[:certname]}" : 'agent -t'
158
+ end
159
+
149
160
  # Validate that our private key matches the specified certificate.
150
161
  #
151
162
  # @param [Puppet::SSL::Certificate] cert the certificate to check
@@ -154,16 +165,15 @@ class Puppet::SSL::Host
154
165
  raise Puppet::Error, _("No certificate to validate.") unless cert
155
166
  raise Puppet::Error, _("No private key with which to validate certificate with fingerprint: %{fingerprint}") % { fingerprint: cert.fingerprint } unless key
156
167
  unless cert.content.check_private_key(key.content)
157
- raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: cert.fingerprint, cert_name: Puppet[:certname], ssl_dir: Puppet[:ssldir], cert_dir: Puppet[:certdir].gsub('/', '\\') }
168
+ raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: cert.fingerprint, cert_name: Puppet[:certname], clean_params: clean_params, puppet_params: puppet_params }
158
169
  The certificate retrieved from the master does not match the agent's private key. Did you forget to run as root?
159
170
  Certificate fingerprint: %{fingerprint}
160
171
  To fix this, remove the certificate from both the master and the agent and then start a puppet run, which will automatically regenerate a certificate.
161
172
  On the master:
162
- puppet cert clean %{cert_name}
173
+ puppetserver ca clean --certname %{cert_name}
163
174
  On the agent:
164
- 1a. On most platforms: find %{ssl_dir} -name %{cert_name}.pem -delete
165
- 1b. On Windows: del "%{cert_dir}\\%{cert_name}.pem" /f
166
- 2. puppet agent -t
175
+ 1. puppet ssl clean %{clean_params}
176
+ 2. puppet %{puppet_params}
167
177
  ERROR_STRING
168
178
  end
169
179
  end
@@ -237,16 +247,15 @@ ERROR_STRING
237
247
 
238
248
  def validate_local_csr_with_key(csr, key)
239
249
  if key.content.public_key.to_s != csr.content.public_key.to_s
240
- raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: csr.fingerprint, csr_public_key: csr.content.public_key.to_text, agent_public_key: key.content.public_key.to_text, cert_name: Puppet[:certname], ssl_dir: Puppet[:ssldir], cert_dir: Puppet[:certdir].gsub('/', '\\') }
250
+ raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: csr.fingerprint, csr_public_key: csr.content.public_key.to_text, agent_public_key: key.content.public_key.to_text, clean_params: clean_params, puppet_params: puppet_params }
241
251
  The local CSR does not match the agent's public key.
242
252
  CSR fingerprint: %{fingerprint}
243
253
  CSR public key: %{csr_public_key}
244
254
  Agent public key: %{agent_public_key}
245
255
  To fix this, remove the CSR from the agent and then start a puppet run, which will automatically regenerate a CSR.
246
256
  On the agent:
247
- 1a. On most platforms: find %{ssl_dir} -name %{cert_name}.pem -delete
248
- 1b. On Windows: del "%{cert_dir}\\%{cert_name}.pem" /f
249
- 2. puppet agent -t
257
+ 1. puppet ssl clean %{clean_params}
258
+ 2. puppet %{puppet_params}
250
259
  ERROR_STRING
251
260
  end
252
261
  end
@@ -254,25 +263,25 @@ ERROR_STRING
254
263
 
255
264
  def validate_csr_with_key(csr, key)
256
265
  if key.content.public_key.to_s != csr.content.public_key.to_s
257
- raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: csr.fingerprint, csr_public_key: csr.content.public_key.to_text, agent_public_key: key.content.public_key.to_text, cert_name: Puppet[:certname], ssl_dir: Puppet[:ssldir], cert_dir: Puppet[:certdir].gsub('/', '\\') }
266
+ raise Puppet::Error, _(<<ERROR_STRING) % { fingerprint: csr.fingerprint, csr_public_key: csr.content.public_key.to_text, agent_public_key: key.content.public_key.to_text, cert_name: Puppet[:certname], clean_params: clean_params, puppet_params: puppet_params }
258
267
  The CSR retrieved from the master does not match the agent's public key.
259
268
  CSR fingerprint: %{fingerprint}
260
269
  CSR public key: %{csr_public_key}
261
270
  Agent public key: %{agent_public_key}
262
271
  To fix this, remove the CSR from both the master and the agent and then start a puppet run, which will automatically regenerate a CSR.
263
272
  On the master:
264
- puppet cert clean %{cert_name}
273
+ puppetserver ca clean --certname %{cert_name}
265
274
  On the agent:
266
- 1a. On most platforms: find %{ssl_dir} -name %{cert_name}.pem -delete
267
- 1b. On Windows: del "%{cert_dir}\\%{cert_name}.pem" /f
268
- 2. puppet agent -t
275
+ 1. puppet ssl clean %{clean_params}
276
+ 2. puppet %{puppet_params}
269
277
  ERROR_STRING
270
278
  end
271
279
  end
272
280
  private :validate_csr_with_key
273
281
 
274
- def initialize(name = nil)
282
+ def initialize(name = nil, device = false)
275
283
  @name = (name || Puppet[:certname]).downcase
284
+ @device = device
276
285
  Puppet::SSL::Base.validate_certname(@name)
277
286
  @key = @certificate = @certificate_request = nil
278
287
  @crl_usage = Puppet.settings[:certificate_revocation]
@@ -576,6 +585,7 @@ ERROR_STRING
576
585
  end
577
586
  end
578
587
  end
588
+ public :download_certificate_from_ca
579
589
 
580
590
  # Returns the file path for the named certificate, based on this host's
581
591
  # configuration.
@@ -0,0 +1,34 @@
1
+ # A syntax checker for JSON.
2
+ # @api public
3
+ require 'puppet/syntax_checkers'
4
+ class Puppet::SyntaxCheckers::EPP < Puppet::Plugins::SyntaxCheckers::SyntaxChecker
5
+
6
+ # Checks the text for Puppet Language EPP syntax issues and reports them to the given acceptor.
7
+ #
8
+ # Error messages from the checker are capped at 100 chars from the source text.
9
+ #
10
+ # @param text [String] The text to check
11
+ # @param syntax [String] The syntax identifier in mime style (only accepts 'pp')
12
+ # @param acceptor [#accept] A Diagnostic acceptor
13
+ # @param source_pos [Puppet::Pops::Adapters::SourcePosAdapter] A source pos adapter with location information
14
+ # @api public
15
+ #
16
+ def check(text, syntax, acceptor, source_pos)
17
+ raise ArgumentError.new(_("EPP syntax checker: the text to check must be a String.")) unless text.is_a?(String)
18
+ raise ArgumentError.new(_("EPP syntax checker: the syntax identifier must be a String, e.g. pp")) unless syntax == 'epp'
19
+ raise ArgumentError.new(_("EPP syntax checker: invalid Acceptor, got: '%{klass}'.") % { klass: acceptor.class.name }) unless acceptor.is_a?(Puppet::Pops::Validation::Acceptor)
20
+
21
+ begin
22
+ Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.singleton.parse_string(text)
23
+ rescue => e
24
+ # Cap the message to 100 chars and replace newlines
25
+ msg = _("EPP syntax checker: \"%{message}\"") % { message: e.message().slice(0,500).gsub(/\r?\n/, "\\n") }
26
+
27
+ # TODO: improve the pops API to allow simpler diagnostic creation while still maintaining capabilities
28
+ # and the issue code. (In this case especially, where there is only a single error message being issued).
29
+ #
30
+ issue = Puppet::Pops::Issues::issue(:ILLEGAL_EPP) { msg }
31
+ acceptor.accept(Puppet::Pops::Validation::Diagnostic.new(:error, issue, source_pos.file, source_pos, {}))
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # A syntax checker for JSON.
2
+ # @api public
3
+ require 'puppet/syntax_checkers'
4
+ class Puppet::SyntaxCheckers::PP < Puppet::Plugins::SyntaxCheckers::SyntaxChecker
5
+
6
+ # Checks the text for Puppet Language syntax issues and reports them to the given acceptor.
7
+ #
8
+ # Error messages from the checker are capped at 100 chars from the source text.
9
+ #
10
+ # @param text [String] The text to check
11
+ # @param syntax [String] The syntax identifier in mime style (only accepts 'pp')
12
+ # @param acceptor [#accept] A Diagnostic acceptor
13
+ # @param source_pos [Puppet::Pops::Adapters::SourcePosAdapter] A source pos adapter with location information
14
+ # @api public
15
+ #
16
+ def check(text, syntax, acceptor, source_pos)
17
+ raise ArgumentError.new(_("PP syntax checker: the text to check must be a String.")) unless text.is_a?(String)
18
+ raise ArgumentError.new(_("PP syntax checker: the syntax identifier must be a String, e.g. pp")) unless syntax == 'pp'
19
+ raise ArgumentError.new(_("PP syntax checker: invalid Acceptor, got: '%{klass}'.") % { klass: acceptor.class.name }) unless acceptor.is_a?(Puppet::Pops::Validation::Acceptor)
20
+
21
+ begin
22
+ Puppet::Pops::Parser::EvaluatingParser.singleton.parse_string(text)
23
+ rescue => e
24
+ # Cap the message to 100 chars and replace newlines
25
+ msg = _("PP syntax checker: \"%{message}\"") % { message: e.message().slice(0,500).gsub(/\r?\n/, "\\n") }
26
+
27
+ # TODO: improve the pops API to allow simpler diagnostic creation while still maintaining capabilities
28
+ # and the issue code. (In this case especially, where there is only a single error message being issued).
29
+ #
30
+ issue = Puppet::Pops::Issues::issue(:ILLEGAL_PP) { msg }
31
+ acceptor.accept(Puppet::Pops::Validation::Diagnostic.new(:error, issue, source_pos.file, source_pos, {}))
32
+ end
33
+ end
34
+ end
@@ -147,12 +147,18 @@ class Puppet::Transaction::EventManager
147
147
  resource.send(callback)
148
148
 
149
149
  if not resource.is_a?(Puppet::Type.type(:whit))
150
- resource.notice n_("Triggered '%{callback}' from %{count} event", "Triggered '%{callback}' from %{count} events", events.length) % { count: events.length, callback: callback }
150
+ message = n_("Triggered '%{callback}' from %{count} event", "Triggered '%{callback}' from %{count} events", events.length) % { count: events.length, callback: callback }
151
+ resource.notice message
152
+ add_callback_status_event(resource, callback, message, "success")
151
153
  end
154
+
152
155
  return true
153
156
  rescue => detail
154
157
  resource_error_message = _("Failed to call %{callback}: %{detail}") % { callback: callback, detail: detail }
155
158
  resource.err resource_error_message
159
+ if not resource.is_a?(Puppet::Type.type(:whit))
160
+ add_callback_status_event(resource, callback, resource_error_message, "failure")
161
+ end
156
162
 
157
163
  transaction.resource_status(resource).failed_to_restart = true
158
164
  transaction.resource_status(resource).fail_with_event(resource_error_message)
@@ -160,6 +166,12 @@ class Puppet::Transaction::EventManager
160
166
  return false
161
167
  end
162
168
 
169
+ def add_callback_status_event(resource, callback, message, status)
170
+ options = { message: message, status: status, name: callback.to_s }
171
+ event = resource.event options
172
+ transaction.resource_status(resource) << event if event
173
+ end
174
+
163
175
  def process_noop_events(resource, callback, events)
164
176
  resource.notice n_("Would have triggered '%{callback}' from %{count} event", "Would have triggered '%{callback}' from %{count} events", events.length) % { count: events.length, callback: callback }
165
177
 
@@ -64,7 +64,7 @@ class Puppet::Transaction::Persistence
64
64
  begin
65
65
  result = Puppet::Util::Yaml.safe_load_file(filename, [Symbol])
66
66
  rescue Puppet::Util::Yaml::YamlLoadError => detail
67
- Puppet.log_exception(detail, _("Transaction store file %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail }, { :level => :warning })
67
+ Puppet.log_exception(detail, _("Transaction store file %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail })
68
68
 
69
69
  begin
70
70
  File.rename(filename, filename + ".bad")
@@ -158,7 +158,9 @@ class Puppet::Transaction::ResourceHarness
158
158
  raise
159
159
  ensure
160
160
  if event
161
- event.calculate_corrective_change(@persistence.get_system_value(context.resource.ref, param.name.to_s))
161
+ name = param.name.to_s
162
+ event.message ||= _("could not create change error message for %{name}") % { name: name }
163
+ event.calculate_corrective_change(@persistence.get_system_value(context.resource.ref, name))
162
164
  context.record(event)
163
165
  event.send_log
164
166
  context.synced_params << param.name
@@ -87,6 +87,8 @@ module Puppet
87
87
  behavior can be configured with `auth_membership`."
88
88
 
89
89
  def change_to_s(currentvalue, newvalue)
90
+ newvalue = actual_should(currentvalue, newvalue)
91
+
90
92
  currentvalue = currentvalue.join(",") if currentvalue != :absent
91
93
  newvalue = newvalue.join(",")
92
94
  super(currentvalue, newvalue)
@@ -110,7 +112,33 @@ module Puppet
110
112
 
111
113
  super(currentvalue)
112
114
  end
113
- alias :should_to_s :is_to_s
115
+
116
+ def should_to_s(newvalue)
117
+ is_to_s(actual_should(retrieve, newvalue))
118
+ end
119
+
120
+ # Calculates the actual should value given the current and
121
+ # new values. This is only used in should_to_s and change_to_s
122
+ # to fix the change notification issue reported in PUP-6542.
123
+ def actual_should(currentvalue, newvalue)
124
+ currentvalue = munge_members_value(currentvalue)
125
+ newvalue = munge_members_value(newvalue)
126
+
127
+ if @resource[:auth_membership]
128
+ newvalue.uniq.sort
129
+ else
130
+ (currentvalue + newvalue).uniq.sort
131
+ end
132
+ end
133
+
134
+ # Useful helper to handle the possible property value types that we can
135
+ # both pass-in and return. It munges the value into an array
136
+ def munge_members_value(value)
137
+ return [] if value == :absent
138
+ return value.split(',') if value.is_a?(String)
139
+
140
+ value
141
+ end
114
142
 
115
143
  validate do |value|
116
144
  if provider.respond_to?(:member_valid?)
@@ -172,7 +172,7 @@ module Puppet
172
172
  when is == @latest
173
173
  return true
174
174
  when is == :present
175
- # This will only happen on retarded packaging systems
175
+ # This will only happen on packaging systems
176
176
  # that can't query versions.
177
177
  return true
178
178
  else
@@ -271,6 +271,10 @@ module Puppet
271
271
  providify
272
272
  paramclass(:provider).isnamevar
273
273
 
274
+ def self.parameters_to_include
275
+ [:provider]
276
+ end
277
+
274
278
  # We have more than one namevar, so we need title_patterns. However, we
275
279
  # cheat and set the patterns to map to name only and completely ignore
276
280
  # provider. So far, the logic that determines uniqueness appears to just
@@ -87,6 +87,12 @@ Puppet::Type.newtype(:resources) do
87
87
  end
88
88
  end
89
89
 
90
+ WINDOWS_SYSTEM_SID_REGEXES =
91
+ # Administrator, Guest, Domain Admins, Schema Admins, Enterprise Admins.
92
+ # https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
93
+ [/S-1-5-21.+-500/, /S-1-5-21.+-501/, /S-1-5-21.+-512/, /S-1-5-21.+-518/,
94
+ /S-1-5-21.+-519/]
95
+
90
96
  def check(resource)
91
97
  @checkmethod ||= "#{self[:name]}_check"
92
98
  @hascheck ||= respond_to?(@checkmethod)
@@ -145,8 +151,12 @@ Puppet::Type.newtype(:resources) do
145
151
 
146
152
  return false if system_users.include?(resource[:name])
147
153
  return false if unless_uids && unless_uids.include?(current_uid)
148
-
149
- current_uid > self[:unless_system_user]
154
+ if current_uid.is_a?(String)
155
+ # Windows user; is a system user if any regex matches.
156
+ WINDOWS_SYSTEM_SID_REGEXES.none? { |regex| current_uid =~ regex }
157
+ else
158
+ current_uid > self[:unless_system_user]
159
+ end
150
160
  end
151
161
 
152
162
  def system_users
@@ -46,6 +46,13 @@ module Puppet
46
46
  }
47
47
 
48
48
  This will cause resources to be applied every 30 minutes by default.
49
+
50
+ The `statettl` setting on the agent affects the ability of a schedule to
51
+ determine if a resource has already been checked. If the `statettl` is
52
+ set lower than the span of the associated schedule resource, then a
53
+ resource could be checked & applied multiple times in the schedule as
54
+ the information about when the resource was last checked will have
55
+ expired from the cache.
49
56
  EOT
50
57
 
51
58
  apply_to_all
@@ -45,6 +45,8 @@ module Puppet
45
45
  feature :maskable, "The provider can 'mask' the service.",
46
46
  :methods => [:mask]
47
47
 
48
+ feature :configurable_timeout, "The provider can specify a minumum timeout for syncing service properties"
49
+
48
50
  newproperty(:enable, :required_features => :enableable) do
49
51
  desc "Whether a service should be enabled to start at boot.
50
52
  This property behaves quite differently depending on the platform;
@@ -237,6 +239,16 @@ module Puppet
237
239
  desc "Specify a command to config a service, or a path to a manifest to do so."
238
240
  end
239
241
 
242
+ newparam(:timeout, :required_features => :configurable_timeout) do
243
+ desc "Specify an optional minimum timeout (in seconds) for puppet to wait when syncing service properties"
244
+ defaultto { provider.class.respond_to?(:default_timeout) ? provider.default_timeout : 10 }
245
+ validate do |value|
246
+ if (not value.is_a? Integer) || value < 1
247
+ raise Puppet::Error.new(_("\"%{value}\" is not a positive integer: the timeout parameter must be specified as a positive integer") % { value: value })
248
+ end
249
+ end
250
+ end
251
+
240
252
  # Basically just a synonym for restarting. Used to respond
241
253
  # to events.
242
254
  def refresh