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.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/Gemfile.lock +20 -20
- data/Guardfile.example +76 -0
- data/LICENSE +189 -4
- data/README.md +3 -3
- data/Rakefile +5 -2
- data/ext/solaris/smf/svc-puppetd +8 -1
- data/ext/solaris/smf/svc-puppetmasterd +8 -1
- data/lib/puppet/application/apply.rb +100 -59
- data/lib/puppet/application/cert.rb +4 -114
- data/lib/puppet/application/device.rb +48 -32
- data/lib/puppet/application/script.rb +1 -1
- data/lib/puppet/application/ssl.rb +135 -51
- data/lib/puppet/application.rb +5 -0
- data/lib/puppet/configurer.rb +2 -3
- data/lib/puppet/defaults.rb +33 -49
- data/lib/puppet/etc.rb +20 -0
- data/lib/puppet/face/config.rb +3 -3
- data/lib/puppet/face/key.rb +1 -1
- data/lib/puppet/face/node/clean.rb +0 -1
- data/lib/puppet/feature/base.rb +1 -1
- data/lib/puppet/file_bucket/dipper.rb +1 -1
- data/lib/puppet/file_serving/fileset.rb +1 -1
- data/lib/puppet/functions/abs.rb +1 -1
- data/lib/puppet/functions/new.rb +1 -1
- data/lib/puppet/module/task.rb +29 -38
- data/lib/puppet/pal/catalog_compiler.rb +96 -0
- data/lib/puppet/pal/compiler.rb +221 -0
- data/lib/puppet/pal/function_signature.rb +52 -0
- data/lib/puppet/pal/json_catalog_encoder.rb +67 -0
- data/lib/puppet/pal/pal_api.rb +15 -0
- data/lib/puppet/pal/pal_impl.rb +523 -0
- data/lib/puppet/pal/plan_signature.rb +71 -0
- data/lib/puppet/pal/script_compiler.rb +71 -0
- data/lib/puppet/pal/task_signature.rb +58 -0
- data/lib/puppet/parser/catalog_compiler.rb +24 -0
- data/lib/puppet/parser/compiler.rb +3 -1
- data/lib/puppet/parser/functions/generate.rb +7 -6
- data/lib/puppet/plugins/configuration.rb +5 -1
- data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +3 -1
- data/lib/puppet/pops/evaluator/deferred_resolver.rb +3 -0
- data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -1
- data/lib/puppet/pops/evaluator/external_syntax_support.rb +3 -3
- data/lib/puppet/pops/evaluator/runtime3_converter.rb +2 -2
- data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +19 -10
- data/lib/puppet/pops/loader/task_instantiator.rb +13 -70
- data/lib/puppet/pops/parser/heredoc_support.rb +1 -2
- data/lib/puppet/pops/parser/lexer2.rb +1 -1
- data/lib/puppet/pops/pcore.rb +10 -33
- data/lib/puppet/pops/serialization/to_data_converter.rb +9 -1
- data/lib/puppet/pops/serialization.rb +1 -0
- data/lib/puppet/pops/types/p_timespan_type.rb +2 -2
- data/lib/puppet/pops/types/string_converter.rb +18 -4
- data/lib/puppet/pops/validation/checker4_0.rb +17 -2
- data/lib/puppet/provider/exec.rb +59 -57
- data/lib/puppet/provider/group/aix.rb +18 -2
- data/lib/puppet/provider/group/windows_adsi.rb +7 -3
- data/lib/puppet/provider/nameservice.rb +1 -25
- data/lib/puppet/provider/package/dnf.rb +2 -0
- data/lib/puppet/provider/package/pkgng.rb +37 -21
- data/lib/puppet/provider/package/portage.rb +2 -2
- data/lib/puppet/provider/package/windows/exe_package.rb +16 -10
- data/lib/puppet/provider/package/windows/msi_package.rb +8 -0
- data/lib/puppet/provider/package/windows/package.rb +9 -1
- data/lib/puppet/provider/package/windows.rb +2 -2
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/parsedfile.rb +25 -4
- data/lib/puppet/provider/service/launchd.rb +19 -3
- data/lib/puppet/provider/service/smf.rb +54 -0
- data/lib/puppet/provider/service/systemd.rb +19 -0
- data/lib/puppet/provider/service/upstart.rb +1 -0
- data/lib/puppet/provider/service/windows.rb +22 -5
- data/lib/puppet/provider/user/aix.rb +48 -2
- data/lib/puppet/provider/user/useradd.rb +2 -10
- data/lib/puppet/provider/user/windows_adsi.rb +9 -1
- data/lib/puppet/resource/catalog.rb +1 -5
- data/lib/puppet/resource.rb +3 -1
- data/lib/puppet/ssl/host.rb +26 -16
- data/lib/puppet/syntax_checkers/epp.rb +34 -0
- data/lib/puppet/syntax_checkers/pp.rb +34 -0
- data/lib/puppet/transaction/event_manager.rb +13 -1
- data/lib/puppet/transaction/persistence.rb +1 -1
- data/lib/puppet/transaction/resource_harness.rb +3 -1
- data/lib/puppet/type/group.rb +29 -1
- data/lib/puppet/type/package.rb +5 -1
- data/lib/puppet/type/resources.rb +12 -2
- data/lib/puppet/type/schedule.rb +7 -0
- data/lib/puppet/type/service.rb +12 -0
- data/lib/puppet/type/user.rb +5 -2
- data/lib/puppet/type.rb +6 -0
- data/lib/puppet/util/command_line.rb +2 -3
- data/lib/puppet/util/execution.rb +15 -1
- data/lib/puppet/util/filetype.rb +56 -8
- data/lib/puppet/util/log/destinations.rb +3 -2
- data/lib/puppet/util/logging.rb +3 -2
- data/lib/puppet/util/posix.rb +15 -0
- data/lib/puppet/util/selinux.rb +1 -1
- data/lib/puppet/util/storage.rb +12 -0
- data/lib/puppet/util/windows/adsi.rb +79 -2
- data/lib/puppet/util/windows/api_types.rb +1 -1
- data/lib/puppet/util/windows/process.rb +23 -3
- data/lib/puppet/util/windows/registry.rb +29 -5
- data/lib/puppet/util/windows/security.rb +14 -0
- data/lib/puppet/util/windows/service.rb +294 -74
- data/lib/puppet/util/windows/user.rb +3 -5
- data/lib/puppet/util.rb +7 -3
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet.rb +1 -0
- data/lib/puppet_pal.rb +5 -1099
- data/locales/ja/puppet.po +952 -986
- data/locales/puppet.pot +592 -347
- data/man/man5/puppet.conf.5 +26 -31
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +4 -4
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +23 -19
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +2 -2
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +26 -3
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/usee/lib/puppet/parser/functions/bad_func_load.rb +11 -0
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query +7 -1
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query.zsh +1 -0
- data/spec/fixtures/unit/provider/service/smf/svcs_fmri.out +6 -0
- data/spec/fixtures/unit/provider/service/smf/svcs_multiple_fmris.out +13 -0
- data/spec/integration/application/apply_spec.rb +4 -1
- data/spec/integration/parser/collection_spec.rb +4 -8
- data/spec/integration/provider/service/windows_spec.rb +5 -5
- data/spec/integration/ssl/key_spec.rb +0 -4
- data/spec/integration/transaction_spec.rb +559 -0
- data/spec/integration/type/file_spec.rb +6 -6
- data/spec/integration/util/windows/registry_spec.rb +39 -0
- data/spec/integration/util/windows/security_spec.rb +10 -7
- data/spec/integration/util/windows/user_spec.rb +37 -17
- data/spec/lib/puppet/test_ca.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/agent_spec.rb +2 -2
- data/spec/unit/application/apply_spec.rb +55 -2
- data/spec/unit/application/device_spec.rb +10 -7
- data/spec/unit/application/face_base_spec.rb +1 -1
- data/spec/unit/application/lookup_spec.rb +2 -1
- data/spec/unit/application/ssl_spec.rb +178 -109
- data/spec/unit/application_spec.rb +29 -11
- data/spec/unit/configurer/downloader_spec.rb +1 -1
- data/spec/unit/configurer_spec.rb +16 -5
- data/spec/unit/etc_spec.rb +25 -0
- data/spec/unit/face/node_spec.rb +1 -3
- data/spec/unit/face/parser_spec.rb +15 -0
- data/spec/unit/file_serving/fileset_spec.rb +11 -11
- data/spec/unit/functions/logging_spec.rb +10 -3
- data/spec/unit/indirector/catalog/json_spec.rb +9 -3
- data/spec/unit/indirector/yaml_spec.rb +1 -1
- data/spec/unit/network/http/connection_spec.rb +2 -2
- data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +36 -0
- data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +22 -4
- data/spec/unit/pops/loaders/loader_spec.rb +9 -17
- data/spec/unit/pops/loaders/loaders_spec.rb +48 -0
- data/spec/unit/pops/loaders/module_loaders_spec.rb +7 -7
- data/spec/unit/pops/parser/parse_heredoc_spec.rb +16 -0
- data/spec/unit/pops/serialization/to_from_hr_spec.rb +9 -0
- data/spec/unit/pops/types/p_timespan_type_spec.rb +22 -0
- data/spec/unit/pops/types/p_timestamp_type_spec.rb +19 -0
- data/spec/unit/pops/types/string_converter_spec.rb +25 -1
- data/spec/unit/pops/types/task_spec.rb +42 -116
- data/spec/unit/pops/validator/validator_spec.rb +24 -10
- data/spec/unit/provider/exec/posix_spec.rb +24 -0
- data/spec/unit/provider/group/aix_spec.rb +20 -6
- data/spec/unit/provider/group/ldap_spec.rb +22 -25
- data/spec/unit/provider/group/pw_spec.rb +7 -10
- data/spec/unit/provider/group/windows_adsi_spec.rb +42 -33
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +97 -103
- data/spec/unit/provider/package/aix_spec.rb +5 -8
- data/spec/unit/provider/package/apt_spec.rb +3 -6
- data/spec/unit/provider/package/dnf_spec.rb +38 -25
- data/spec/unit/provider/package/dpkg_spec.rb +18 -21
- data/spec/unit/provider/package/freebsd_spec.rb +4 -7
- data/spec/unit/provider/package/gem_spec.rb +41 -41
- data/spec/unit/provider/package/hpux_spec.rb +7 -10
- data/spec/unit/provider/package/macports_spec.rb +13 -15
- data/spec/unit/provider/package/nim_spec.rb +3 -10
- data/spec/unit/provider/package/openbsd_spec.rb +14 -17
- data/spec/unit/provider/package/pip3_spec.rb +3 -6
- data/spec/unit/provider/package/pip_spec.rb +45 -49
- data/spec/unit/provider/package/pkgin_spec.rb +13 -18
- data/spec/unit/provider/package/pkgng_spec.rb +32 -27
- data/spec/unit/provider/package/puppet_gem_spec.rb +6 -9
- data/spec/unit/provider/package/tdnf_spec.rb +9 -12
- data/spec/unit/provider/package/windows/exe_package_spec.rb +3 -3
- data/spec/unit/provider/package/windows_spec.rb +4 -4
- data/spec/unit/provider/package/yum_spec.rb +30 -16
- data/spec/unit/provider/package/zypper_spec.rb +17 -19
- data/spec/unit/provider/service/bsd_spec.rb +7 -9
- data/spec/unit/provider/service/daemontools_spec.rb +12 -16
- data/spec/unit/provider/service/debian_spec.rb +6 -10
- data/spec/unit/provider/service/freebsd_spec.rb +2 -2
- data/spec/unit/provider/service/launchd_spec.rb +19 -0
- data/spec/unit/provider/service/openbsd_spec.rb +13 -17
- data/spec/unit/provider/service/rcng_spec.rb +2 -4
- data/spec/unit/provider/service/redhat_spec.rb +12 -11
- data/spec/unit/provider/service/runit_spec.rb +7 -14
- data/spec/unit/provider/service/smf_spec.rb +77 -13
- data/spec/unit/provider/service/src_spec.rb +11 -16
- data/spec/unit/provider/service/systemd_spec.rb +39 -1
- data/spec/unit/provider/service/windows_spec.rb +39 -7
- data/spec/unit/provider/user/aix_spec.rb +43 -2
- data/spec/unit/provider/user/hpux_spec.rb +3 -5
- data/spec/unit/provider/user/ldap_spec.rb +29 -32
- data/spec/unit/provider/user/pw_spec.rb +10 -13
- data/spec/unit/provider/user/useradd_spec.rb +2 -2
- data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
- data/spec/unit/puppet_pal_2pec.rb +6 -6
- data/spec/unit/puppet_pal_catalog_spec.rb +58 -0
- data/spec/unit/resource/catalog_spec.rb +2 -2
- data/spec/unit/resource_spec.rb +31 -0
- data/spec/unit/ssl/host_spec.rb +22 -1
- data/spec/unit/ssl/key_spec.rb +2 -4
- data/spec/unit/task_spec.rb +50 -5
- data/spec/unit/transaction/event_manager_spec.rb +12 -1
- data/spec/unit/transaction/persistence_spec.rb +4 -4
- data/spec/unit/transaction/resource_harness_spec.rb +18 -0
- data/spec/unit/type/group_spec.rb +11 -3
- data/spec/unit/type/resources_spec.rb +18 -0
- data/spec/unit/type/service_spec.rb +27 -1
- data/spec/unit/util/execution_spec.rb +77 -0
- data/spec/unit/util/filetype_spec.rb +13 -5
- data/spec/unit/util/log/destinations_spec.rb +10 -0
- data/spec/unit/util/logging_spec.rb +58 -41
- data/spec/unit/util/monkey_patches_spec.rb +18 -5
- data/spec/unit/util/posix_spec.rb +28 -0
- data/spec/unit/util/selinux_spec.rb +4 -0
- data/spec/unit/util/storage_spec.rb +107 -0
- data/spec/unit/util/suidmanager_spec.rb +1 -3
- data/spec/unit/util/windows/adsi_spec.rb +95 -0
- data/spec/unit/util/windows/service_spec.rb +377 -131
- metadata +24 -11
- data/ext/autotest/Rakefile +0 -8
- data/ext/autotest/config +0 -43
- data/ext/autotest/readme.rst +0 -16
- data/spec/fixtures/unit/provider/package/pkgng/pkg.info +0 -7
- data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +0 -1
- data/spec/watchr.rb +0 -137
|
@@ -17,6 +17,10 @@ module Puppet::Util::Windows
|
|
|
17
17
|
# no shorter
|
|
18
18
|
DEFAULT_TIMEOUT = 30
|
|
19
19
|
|
|
20
|
+
# Service error codes
|
|
21
|
+
# https://docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes--1000-1299-
|
|
22
|
+
ERROR_SERVICE_DOES_NOT_EXIST = 0x00000424
|
|
23
|
+
|
|
20
24
|
# Service control codes
|
|
21
25
|
# https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-controlserviceexw
|
|
22
26
|
SERVICE_CONTROL_STOP = 0x00000001
|
|
@@ -36,6 +40,26 @@ module Puppet::Util::Windows
|
|
|
36
40
|
SERVICE_CONTROL_PRESHUTDOWN = 0x0000000F
|
|
37
41
|
SERVICE_CONTROL_TIMECHANGE = 0x00000010
|
|
38
42
|
SERVICE_CONTROL_TRIGGEREVENT = 0x00000020
|
|
43
|
+
SERVICE_CONTROL_SIGNALS = {
|
|
44
|
+
SERVICE_CONTROL_STOP => :SERVICE_CONTROL_STOP,
|
|
45
|
+
SERVICE_CONTROL_PAUSE => :SERVICE_CONTROL_PAUSE,
|
|
46
|
+
SERVICE_CONTROL_CONTINUE => :SERVICE_CONTROL_CONTINUE,
|
|
47
|
+
SERVICE_CONTROL_INTERROGATE => :SERVICE_CONTROL_INTERROGATE,
|
|
48
|
+
SERVICE_CONTROL_SHUTDOWN => :SERVICE_CONTROL_SHUTDOWN,
|
|
49
|
+
SERVICE_CONTROL_PARAMCHANGE => :SERVICE_CONTROL_PARAMCHANGE,
|
|
50
|
+
SERVICE_CONTROL_NETBINDADD => :SERVICE_CONTROL_NETBINDADD,
|
|
51
|
+
SERVICE_CONTROL_NETBINDREMOVE => :SERVICE_CONTROL_NETBINDREMOVE,
|
|
52
|
+
SERVICE_CONTROL_NETBINDENABLE => :SERVICE_CONTROL_NETBINDENABLE,
|
|
53
|
+
SERVICE_CONTROL_NETBINDDISABLE => :SERVICE_CONTROL_NETBINDDISABLE,
|
|
54
|
+
SERVICE_CONTROL_DEVICEEVENT => :SERVICE_CONTROL_DEVICEEVENT,
|
|
55
|
+
SERVICE_CONTROL_HARDWAREPROFILECHANGE => :SERVICE_CONTROL_HARDWAREPROFILECHANGE,
|
|
56
|
+
SERVICE_CONTROL_POWEREVENT => :SERVICE_CONTROL_POWEREVENT,
|
|
57
|
+
SERVICE_CONTROL_SESSIONCHANGE => :SERVICE_CONTROL_SESSIONCHANGE,
|
|
58
|
+
SERVICE_CONTROL_PRESHUTDOWN => :SERVICE_CONTROL_PRESHUTDOWN,
|
|
59
|
+
SERVICE_CONTROL_TIMECHANGE => :SERVICE_CONTROL_TIMECHANGE,
|
|
60
|
+
SERVICE_CONTROL_TRIGGEREVENT => :SERVICE_CONTROL_TRIGGEREVENT
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
|
|
40
64
|
# Service start type codes
|
|
41
65
|
# https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-changeserviceconfigw
|
|
@@ -77,7 +101,14 @@ module Puppet::Util::Windows
|
|
|
77
101
|
SERVICE_START_PENDING = 0x00000002
|
|
78
102
|
SERVICE_STOP_PENDING = 0x00000003
|
|
79
103
|
SERVICE_STOPPED = 0x00000001
|
|
80
|
-
|
|
104
|
+
UNSAFE_PENDING_STATES = [SERVICE_START_PENDING, SERVICE_STOP_PENDING]
|
|
105
|
+
FINAL_STATES = {
|
|
106
|
+
SERVICE_CONTINUE_PENDING => SERVICE_RUNNING,
|
|
107
|
+
SERVICE_PAUSE_PENDING => SERVICE_PAUSED,
|
|
108
|
+
SERVICE_START_PENDING => SERVICE_RUNNING,
|
|
109
|
+
SERVICE_STOP_PENDING => SERVICE_STOPPED
|
|
110
|
+
}
|
|
111
|
+
SERVICE_STATES = {
|
|
81
112
|
SERVICE_CONTINUE_PENDING => :SERVICE_CONTINUE_PENDING,
|
|
82
113
|
SERVICE_PAUSE_PENDING => :SERVICE_PAUSE_PENDING,
|
|
83
114
|
SERVICE_PAUSED => :SERVICE_PAUSED,
|
|
@@ -249,59 +280,97 @@ module Puppet::Util::Windows
|
|
|
249
280
|
)
|
|
250
281
|
end
|
|
251
282
|
|
|
252
|
-
#
|
|
283
|
+
# Returns true if the service exists, false otherwise.
|
|
253
284
|
#
|
|
254
|
-
# @param [
|
|
255
|
-
def
|
|
256
|
-
open_service(service_name, SC_MANAGER_CONNECT,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
285
|
+
# @param [String] service_name name of the service
|
|
286
|
+
def exists?(service_name)
|
|
287
|
+
open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_STATUS) do |_|
|
|
288
|
+
true
|
|
289
|
+
end
|
|
290
|
+
rescue Puppet::Util::Windows::Error => e
|
|
291
|
+
return false if e.code == ERROR_SERVICE_DOES_NOT_EXIST
|
|
292
|
+
raise e
|
|
293
|
+
end
|
|
294
|
+
module_function :exists?
|
|
295
|
+
|
|
296
|
+
# Start a windows service
|
|
297
|
+
#
|
|
298
|
+
# @param [String] service_name name of the service to start
|
|
299
|
+
# @param optional [Integer] timeout the minumum number of seconds to wait before timing out
|
|
300
|
+
def start(service_name, timeout: DEFAULT_TIMEOUT)
|
|
301
|
+
Puppet.debug _("Starting the %{service_name} service. Timeout set to: %{timeout} seconds") % { service_name: service_name, timeout: timeout }
|
|
302
|
+
|
|
303
|
+
valid_initial_states = [
|
|
304
|
+
SERVICE_STOP_PENDING,
|
|
305
|
+
SERVICE_STOPPED,
|
|
306
|
+
SERVICE_START_PENDING
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
transition_service_state(service_name, valid_initial_states, SERVICE_RUNNING, timeout) do |service|
|
|
261
310
|
if StartServiceW(service, 0, FFI::Pointer::NULL) == FFI::WIN32_FALSE
|
|
262
|
-
raise Puppet::Util::Windows::Error
|
|
263
|
-
end
|
|
264
|
-
unless wait_for_pending_transition(service, SERVICE_START_PENDING, SERVICE_RUNNING)
|
|
265
|
-
raise Puppet::Error.new(_("Failed to start the service, after calling StartService the service is not in SERVICE_START_PENDING or SERVICE_RUNNING"))
|
|
311
|
+
raise Puppet::Util::Windows::Error, _("Failed to start the service")
|
|
266
312
|
end
|
|
267
313
|
end
|
|
314
|
+
|
|
315
|
+
Puppet.debug _("Successfully started the %{service_name} service") % { service_name: service_name }
|
|
268
316
|
end
|
|
269
317
|
module_function :start
|
|
270
318
|
|
|
271
|
-
#
|
|
319
|
+
# Stop a windows service
|
|
272
320
|
#
|
|
273
|
-
# @param [
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if ControlService(service, SERVICE_CONTROL_STOP, status) == FFI::WIN32_FALSE
|
|
283
|
-
raise Puppet::Util::Windows::Error.new(_("Failed to send stop control to service, current state is %{current_state}. Failed with") % { current_state: status[:dwCurrentState].to_s })
|
|
284
|
-
end
|
|
285
|
-
unless wait_for_pending_transition(service, SERVICE_STOP_PENDING, SERVICE_STOPPED)
|
|
286
|
-
raise Puppet::Error.new(_("Failed to stop the service, after calling ControlService the service is not in SERVICE_STOP_PENDING or SERVICE_STOPPED"))
|
|
287
|
-
end
|
|
288
|
-
end
|
|
321
|
+
# @param [String] service_name name of the service to stop
|
|
322
|
+
# @param optional [Integer] timeout the minumum number of seconds to wait before timing out
|
|
323
|
+
def stop(service_name, timeout: DEFAULT_TIMEOUT)
|
|
324
|
+
Puppet.debug _("Stopping the %{service_name} service. Timeout set to: %{timeout} seconds") % { service_name: service_name, timeout: timeout }
|
|
325
|
+
|
|
326
|
+
valid_initial_states = SERVICE_STATES.keys - [SERVICE_STOPPED]
|
|
327
|
+
|
|
328
|
+
transition_service_state(service_name, valid_initial_states, SERVICE_STOPPED, timeout) do |service|
|
|
329
|
+
send_service_control_signal(service, SERVICE_CONTROL_STOP)
|
|
289
330
|
end
|
|
331
|
+
|
|
332
|
+
Puppet.debug _("Successfully stopped the %{service_name} service") % { service_name: service_name }
|
|
290
333
|
end
|
|
291
334
|
module_function :stop
|
|
292
335
|
|
|
336
|
+
# Resume a paused windows service
|
|
337
|
+
#
|
|
338
|
+
# @param [String] service_name name of the service to resume
|
|
339
|
+
# @param optional [Integer] :timeout the minumum number of seconds to wait before timing out
|
|
340
|
+
def resume(service_name, timeout: DEFAULT_TIMEOUT)
|
|
341
|
+
Puppet.debug _("Resuming the %{service_name} service. Timeout set to: %{timeout} seconds") % { service_name: service_name, timeout: timeout }
|
|
342
|
+
|
|
343
|
+
valid_initial_states = [
|
|
344
|
+
SERVICE_PAUSE_PENDING,
|
|
345
|
+
SERVICE_PAUSED,
|
|
346
|
+
SERVICE_CONTINUE_PENDING
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
transition_service_state(service_name, valid_initial_states, SERVICE_RUNNING, timeout) do |service|
|
|
350
|
+
# The SERVICE_CONTROL_CONTINUE signal can only be sent when
|
|
351
|
+
# the service is in the SERVICE_PAUSED state
|
|
352
|
+
wait_on_pending_state(service, SERVICE_PAUSE_PENDING, timeout)
|
|
353
|
+
|
|
354
|
+
send_service_control_signal(service, SERVICE_CONTROL_CONTINUE)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
Puppet.debug _("Successfully resumed the %{service_name} service") % { service_name: service_name }
|
|
358
|
+
end
|
|
359
|
+
module_function :resume
|
|
360
|
+
|
|
293
361
|
# Query the state of a service using QueryServiceStatusEx
|
|
294
362
|
#
|
|
295
|
-
# @param [
|
|
363
|
+
# @param [string] service_name name of the service to query
|
|
296
364
|
# @return [string] the status of the service
|
|
297
365
|
def service_state(service_name)
|
|
298
|
-
|
|
366
|
+
state = nil
|
|
299
367
|
open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_STATUS) do |service|
|
|
300
|
-
|
|
368
|
+
query_status(service) do |status|
|
|
369
|
+
state = SERVICE_STATES[status[:dwCurrentState]]
|
|
370
|
+
end
|
|
301
371
|
end
|
|
302
|
-
state = SERVICE_STATES[status[:dwCurrentState]]
|
|
303
372
|
if state.nil?
|
|
304
|
-
raise Puppet::Error.new(_("Unknown Service state '%{current_state}' for '%{service_name}'") % { current_state:
|
|
373
|
+
raise Puppet::Error.new(_("Unknown Service state '%{current_state}' for '%{service_name}'") % { current_state: state.to_s, service_name: service_name})
|
|
305
374
|
end
|
|
306
375
|
state
|
|
307
376
|
end
|
|
@@ -309,16 +378,17 @@ module Puppet::Util::Windows
|
|
|
309
378
|
|
|
310
379
|
# Query the configuration of a service using QueryServiceConfigW
|
|
311
380
|
#
|
|
312
|
-
# @param [
|
|
381
|
+
# @param [String] service_name name of the service to query
|
|
313
382
|
# @return [QUERY_SERVICE_CONFIGW.struct] the configuration of the service
|
|
314
383
|
def service_start_type(service_name)
|
|
315
|
-
|
|
384
|
+
start_type = nil
|
|
316
385
|
open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_CONFIG) do |service|
|
|
317
|
-
|
|
386
|
+
query_config(service) do |config|
|
|
387
|
+
start_type = SERVICE_START_TYPES[config[:dwStartType]]
|
|
388
|
+
end
|
|
318
389
|
end
|
|
319
|
-
start_type = SERVICE_START_TYPES[config[:dwStartType]]
|
|
320
390
|
if start_type.nil?
|
|
321
|
-
raise Puppet::Error.new(_("Unknown start type '%{start_type}' for '%{service_name}'") % { start_type:
|
|
391
|
+
raise Puppet::Error.new(_("Unknown start type '%{start_type}' for '%{service_name}'") % { start_type: start_type.to_s, service_name: service_name})
|
|
322
392
|
end
|
|
323
393
|
start_type
|
|
324
394
|
end
|
|
@@ -456,13 +526,18 @@ module Puppet::Util::Windows
|
|
|
456
526
|
# @param [Integer] service_access code corresponding to the access type requested for the service
|
|
457
527
|
# @yieldparam [:handle] service the windows native handle used to access
|
|
458
528
|
# the service
|
|
529
|
+
# @return the result of the block
|
|
459
530
|
def open_service(service_name, scm_access, service_access, &block)
|
|
460
531
|
service = FFI::Pointer::NULL_HANDLE
|
|
532
|
+
|
|
533
|
+
result = nil
|
|
461
534
|
open_scm(scm_access) do |scm|
|
|
462
535
|
service = OpenServiceW(scm, wide_string(service_name), service_access)
|
|
463
536
|
raise Puppet::Util::Windows::Error.new(_("Failed to open a handle to the service")) if service == FFI::Pointer::NULL_HANDLE
|
|
464
|
-
yield service
|
|
537
|
+
result = yield service
|
|
465
538
|
end
|
|
539
|
+
|
|
540
|
+
result
|
|
466
541
|
ensure
|
|
467
542
|
CloseServiceHandle(service)
|
|
468
543
|
end
|
|
@@ -482,6 +557,79 @@ module Puppet::Util::Windows
|
|
|
482
557
|
end
|
|
483
558
|
private :open_scm
|
|
484
559
|
|
|
560
|
+
# @api private
|
|
561
|
+
# Transition the service to the specified state. The block should perform
|
|
562
|
+
# the actual transition.
|
|
563
|
+
#
|
|
564
|
+
# @param [String] service_name the name of the service to transition
|
|
565
|
+
# @param [[Integer]] valid_initial_states an array of valid states that the service can transition from
|
|
566
|
+
# @param [Integer] final_state the state that the service will transition to
|
|
567
|
+
# @param [Integer] timeout the minumum number of seconds to wait before timing out
|
|
568
|
+
def transition_service_state(service_name, valid_initial_states, final_state, timeout, &block)
|
|
569
|
+
service_access = SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS
|
|
570
|
+
open_service(service_name, SC_MANAGER_CONNECT, service_access) do |service|
|
|
571
|
+
query_status(service) do |status|
|
|
572
|
+
initial_state = status[:dwCurrentState]
|
|
573
|
+
# If the service is already in the final_state, then
|
|
574
|
+
# no further work needs to be done
|
|
575
|
+
if initial_state == final_state
|
|
576
|
+
Puppet.debug _("The service is already in the %{final_state} state. No further work needs to be done.") % { final_state: SERVICE_STATES[final_state] }
|
|
577
|
+
|
|
578
|
+
next
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
# Check that initial_state corresponds to a valid
|
|
582
|
+
# initial state
|
|
583
|
+
unless valid_initial_states.include?(initial_state)
|
|
584
|
+
valid_initial_states_str = valid_initial_states.map do |state|
|
|
585
|
+
SERVICE_STATES[state]
|
|
586
|
+
end.join(", ")
|
|
587
|
+
|
|
588
|
+
raise Puppet::Error, _("The service must be in one of the %{valid_initial_states} states to perform this transition. It is currently in the %{current_state} state.") % { valid_initial_states: valid_initial_states_str, current_state: SERVICE_STATES[initial_state] }
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
# Check if there's a pending transition to the final_state. If so, then wait for
|
|
592
|
+
# that transition to finish.
|
|
593
|
+
possible_pending_states = FINAL_STATES.keys.select do |pending_state|
|
|
594
|
+
# SERVICE_RUNNING has two pending states, SERVICE_START_PENDING and
|
|
595
|
+
# SERVICE_CONTINUE_PENDING. That is why we need the #select here
|
|
596
|
+
FINAL_STATES[pending_state] == final_state
|
|
597
|
+
end
|
|
598
|
+
if possible_pending_states.include?(initial_state)
|
|
599
|
+
Puppet.debug _("There is already a pending transition to the %{final_state} state for the %{service_name} service.") % { final_state: SERVICE_STATES[final_state], service_name: service_name }
|
|
600
|
+
wait_on_pending_state(service, initial_state, timeout)
|
|
601
|
+
|
|
602
|
+
next
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
# If we are in an unsafe pending state like SERVICE_START_PENDING
|
|
606
|
+
# or SERVICE_STOP_PENDING, then we want to wait for that pending
|
|
607
|
+
# transition to finish before transitioning the service state.
|
|
608
|
+
# The reason we do this is because SERVICE_START_PENDING is when
|
|
609
|
+
# the service thread is being created and initialized, while
|
|
610
|
+
# SERVICE_STOP_PENDING is when the service thread is being cleaned
|
|
611
|
+
# up and destroyed. Thus there is a chance that when the service is
|
|
612
|
+
# in either of these states, its service thread may not yet be ready
|
|
613
|
+
# to perform the state transition (it may not even exist).
|
|
614
|
+
if UNSAFE_PENDING_STATES.include?(initial_state)
|
|
615
|
+
Puppet.debug _("The service is in the %{pending_state} state, which is an unsafe pending state.") % { pending_state: SERVICE_STATES[initial_state] }
|
|
616
|
+
wait_on_pending_state(service, initial_state, timeout)
|
|
617
|
+
initial_state = FINAL_STATES[initial_state]
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
Puppet.debug _("Transitioning the %{service_name} service from %{initial_state} to %{final_state}") % { service_name: service_name, initial_state: SERVICE_STATES[initial_state], final_state: SERVICE_STATES[final_state] }
|
|
621
|
+
|
|
622
|
+
yield service
|
|
623
|
+
|
|
624
|
+
Puppet.debug _("Waiting for the transition to finish")
|
|
625
|
+
wait_on_state_transition(service, initial_state, final_state, timeout)
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
rescue => detail
|
|
629
|
+
raise Puppet::Error, _("Failed to transition the %{service_name} service to the %{final_state} state. Detail: %{detail}") % { service_name: service_name, final_state: SERVICE_STATES[final_state], detail: detail }, detail.backtrace
|
|
630
|
+
end
|
|
631
|
+
private :transition_service_state
|
|
632
|
+
|
|
485
633
|
# @api private
|
|
486
634
|
# perform QueryServiceStatusEx on a windows service and return the
|
|
487
635
|
# result
|
|
@@ -519,9 +667,9 @@ module Puppet::Util::Windows
|
|
|
519
667
|
if success == FFI::WIN32_FALSE
|
|
520
668
|
raise Puppet::Util::Windows::Error.new(_("Service query failed"))
|
|
521
669
|
end
|
|
670
|
+
yield status
|
|
522
671
|
end
|
|
523
672
|
end
|
|
524
|
-
status
|
|
525
673
|
end
|
|
526
674
|
private :query_status
|
|
527
675
|
|
|
@@ -531,7 +679,7 @@ module Puppet::Util::Windows
|
|
|
531
679
|
#
|
|
532
680
|
# @param [:handle] service handle of the service to query
|
|
533
681
|
# @return [QUERY_SERVICE_CONFIGW struct] the result of the query
|
|
534
|
-
def query_config(service)
|
|
682
|
+
def query_config(service, &block)
|
|
535
683
|
config = nil
|
|
536
684
|
size_required = nil
|
|
537
685
|
# Fetch the bytes of memory required to be allocated
|
|
@@ -555,52 +703,124 @@ module Puppet::Util::Windows
|
|
|
555
703
|
if success == FFI::WIN32_FALSE
|
|
556
704
|
raise Puppet::Util::Windows::Error.new(_("Service query failed"))
|
|
557
705
|
end
|
|
706
|
+
yield config
|
|
558
707
|
end
|
|
559
708
|
end
|
|
560
|
-
config
|
|
561
709
|
end
|
|
562
710
|
private :query_config
|
|
563
711
|
|
|
564
712
|
# @api private
|
|
565
|
-
#
|
|
566
|
-
#
|
|
713
|
+
# Sends a service control signal to a service
|
|
714
|
+
#
|
|
715
|
+
# @param [:handle] service handle to the service
|
|
716
|
+
# @param [Integer] signal the service control signal to send
|
|
717
|
+
def send_service_control_signal(service, signal)
|
|
718
|
+
FFI::MemoryPointer.new(SERVICE_STATUS.size) do |status_ptr|
|
|
719
|
+
status = SERVICE_STATUS.new(status_ptr)
|
|
720
|
+
if ControlService(service, signal, status) == FFI::WIN32_FALSE
|
|
721
|
+
raise Puppet::Util::Windows::Error, _("Failed to send the %{control_signal} signal to the service. Its current state is %{current_state}. Reason for failure:") % { control_signal: SERVICE_CONTROL_SIGNALS[signal], current_state: SERVICE_STATES[status[:dwCurrentState]] }
|
|
722
|
+
end
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
# @api private
|
|
727
|
+
# Waits for a service to transition from one state to
|
|
728
|
+
# another state.
|
|
567
729
|
#
|
|
568
730
|
# @param [:handle] service handle to the service to wait on
|
|
569
|
-
# @param [Integer]
|
|
570
|
-
# @param [Integer] final_state the state
|
|
571
|
-
# @
|
|
572
|
-
|
|
573
|
-
|
|
731
|
+
# @param [Integer] initial_state the state that the service is transitioning from.
|
|
732
|
+
# @param [Integer] final_state the state that the service is transitioning to
|
|
733
|
+
# @param [Integer] timeout the minumum number of seconds to wait before timing out
|
|
734
|
+
def wait_on_state_transition(service, initial_state, final_state, timeout)
|
|
735
|
+
# Get the pending state for this transition. Note that SERVICE_RUNNING
|
|
736
|
+
# has two possible pending states, which is why we need this logic.
|
|
737
|
+
if final_state != SERVICE_RUNNING
|
|
738
|
+
pending_state = FINAL_STATES.key(final_state)
|
|
739
|
+
elsif initial_state == SERVICE_STOPPED
|
|
740
|
+
# SERVICE_STOPPED => SERVICE_RUNNING
|
|
741
|
+
pending_state = SERVICE_START_PENDING
|
|
742
|
+
else
|
|
743
|
+
# SERVICE_PAUSED => SERVICE_RUNNING
|
|
744
|
+
pending_state = SERVICE_CONTINUE_PENDING
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
# Wait for the transition to finish
|
|
748
|
+
state = nil
|
|
749
|
+
elapsed_time = 0
|
|
750
|
+
while elapsed_time <= timeout
|
|
751
|
+
|
|
752
|
+
query_status(service) do |status|
|
|
753
|
+
state = status[:dwCurrentState]
|
|
754
|
+
return if state == final_state
|
|
755
|
+
if state == pending_state
|
|
756
|
+
Puppet.debug _("The service transitioned to the %{pending_state} state.") % { pending_state: SERVICE_STATES[pending_state] }
|
|
757
|
+
wait_on_pending_state(service, pending_state, timeout)
|
|
758
|
+
return
|
|
759
|
+
end
|
|
760
|
+
sleep(1)
|
|
761
|
+
elapsed_time += 1
|
|
762
|
+
end
|
|
763
|
+
end
|
|
764
|
+
# Timed out while waiting for the transition to finish. Raise an error
|
|
765
|
+
# We can still use the state variable read from the FFI struct because
|
|
766
|
+
# FFI creates new Integer objects during an assignment of an integer value
|
|
767
|
+
# stored in an FFI struct. We verified that the '=' operater is safe
|
|
768
|
+
# from the freed memory since the new ruby object created during the
|
|
769
|
+
# assignment will remain in ruby memory and remain immutable and constant.
|
|
770
|
+
raise Puppet::Error, _("Timed out while waiting for the service to transition from %{initial_state} to %{final_state} OR from %{initial_state} to %{pending_state} to %{final_state}. The service's current state is %{current_state}.") % { initial_state: SERVICE_STATES[initial_state], final_state: SERVICE_STATES[final_state], pending_state: SERVICE_STATES[pending_state], current_state: SERVICE_STATES[state] }
|
|
771
|
+
end
|
|
772
|
+
private :wait_on_state_transition
|
|
773
|
+
|
|
774
|
+
# @api private
|
|
775
|
+
# Waits for a service to finish transitioning from
|
|
776
|
+
# a pending state. The service must be in the pending state
|
|
777
|
+
# before invoking this routine.
|
|
778
|
+
#
|
|
779
|
+
# @param [:handle] service handle to the service to wait on
|
|
780
|
+
# @param [Integer] pending_state the pending state
|
|
781
|
+
# @param [Integer] timeout the minumum number of seconds to wait before timing out
|
|
782
|
+
def wait_on_pending_state(service, pending_state, timeout)
|
|
783
|
+
final_state = FINAL_STATES[pending_state]
|
|
784
|
+
|
|
785
|
+
Puppet.debug _("Waiting for the pending transition to the %{final_state} state to finish.") % { final_state: SERVICE_STATES[final_state] }
|
|
786
|
+
|
|
574
787
|
elapsed_time = 0
|
|
575
788
|
last_checkpoint = -1
|
|
576
789
|
loop do
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
790
|
+
query_status(service) do |status|
|
|
791
|
+
state = status[:dwCurrentState]
|
|
792
|
+
checkpoint = status[:dwCheckPoint]
|
|
793
|
+
wait_hint = status[:dwWaitHint]
|
|
794
|
+
# Check if our service has finished transitioning to
|
|
795
|
+
# the final_state OR if an unexpected transition
|
|
796
|
+
# has occurred
|
|
797
|
+
return if state == final_state
|
|
798
|
+
unless state == pending_state
|
|
799
|
+
raise Puppet::Error, _("Unexpected transition to the %{current_state} state while waiting for the pending transition from %{pending_state} to %{final_state} to finish.") % { current_state: SERVICE_STATES[state], pending_state: SERVICE_STATES[pending_state], final_state: SERVICE_STATES[final_state] }
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
# Check if any progress has been made since our last sleep
|
|
803
|
+
# using the dwCheckPoint. If no progress has been made then
|
|
804
|
+
# check if we've timed out, and raise an error if so
|
|
805
|
+
if checkpoint > last_checkpoint
|
|
806
|
+
elapsed_time = 0
|
|
807
|
+
last_checkpoint = checkpoint
|
|
808
|
+
else
|
|
809
|
+
wait_hint = milliseconds_to_seconds(status[:dwWaitHint])
|
|
810
|
+
timeout = wait_hint < timeout ? timeout : wait_hint
|
|
811
|
+
|
|
812
|
+
if elapsed_time >= timeout
|
|
813
|
+
raise Puppet::Error, _("Timed out while waiting for the pending transition from %{pending_state} to %{final_state} to finish. The current state is %{current_state}.") % { pending_state: SERVICE_STATES[pending_state], final_state: SERVICE_STATES[final_state], current_state: SERVICE_STATES[state] }
|
|
814
|
+
end
|
|
596
815
|
end
|
|
816
|
+
wait_time = wait_hint_to_wait_time(wait_hint)
|
|
817
|
+
# Wait a bit before rechecking the service's state
|
|
818
|
+
sleep(wait_time)
|
|
819
|
+
elapsed_time += wait_time
|
|
597
820
|
end
|
|
598
|
-
last_checkpoint = status[:dwCheckPoint]
|
|
599
|
-
sleep(time_to_wait)
|
|
600
|
-
elapsed_time += time_to_wait
|
|
601
821
|
end
|
|
602
822
|
end
|
|
603
|
-
private :
|
|
823
|
+
private :wait_on_pending_state
|
|
604
824
|
|
|
605
825
|
# @api private
|
|
606
826
|
#
|
|
@@ -8,13 +8,11 @@ module Puppet::Util::Windows::User
|
|
|
8
8
|
extend FFI::Library
|
|
9
9
|
|
|
10
10
|
def admin?
|
|
11
|
-
|
|
11
|
+
return false unless check_token_membership
|
|
12
12
|
|
|
13
13
|
# if Vista or later, check for unrestricted process token
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# otherwise 2003 or less
|
|
17
|
-
check_token_membership
|
|
14
|
+
elevated_supported = Puppet::Util::Windows::Process.supports_elevated_security?
|
|
15
|
+
return elevated_supported ? Puppet::Util::Windows::Process.elevated_security? : true
|
|
18
16
|
end
|
|
19
17
|
module_function :admin?
|
|
20
18
|
|
data/lib/puppet/util.rb
CHANGED
|
@@ -478,9 +478,13 @@ module Util
|
|
|
478
478
|
|
|
479
479
|
def safe_posix_fork(stdin=$stdin, stdout=$stdout, stderr=$stderr, &block)
|
|
480
480
|
child_pid = Kernel.fork do
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
481
|
+
STDIN.reopen(stdin)
|
|
482
|
+
STDOUT.reopen(stdout)
|
|
483
|
+
STDERR.reopen(stderr)
|
|
484
|
+
|
|
485
|
+
$stdin = STDIN
|
|
486
|
+
$stdout = STDOUT
|
|
487
|
+
$stderr = STDERR
|
|
484
488
|
|
|
485
489
|
begin
|
|
486
490
|
Dir.foreach('/proc/self/fd') do |f|
|
data/lib/puppet/version.rb
CHANGED
data/lib/puppet.rb
CHANGED