From e14ca2b40ef230b4d04cb5df644ead8dbf84e687 Mon Sep 17 00:00:00 2001 From: tvpartytonight Date: Thu, 6 Jun 2024 10:41:34 -0700 Subject: [PATCH 1/2] (PA-6394) Add integration tests for windows service manager (cherry picked from commit 4c9b3855df9f67dfce376bbd62e283b2db632693) --- .../windows/service_manager_integration.rb | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 acceptance/tests/windows/service_manager_integration.rb diff --git a/acceptance/tests/windows/service_manager_integration.rb b/acceptance/tests/windows/service_manager_integration.rb new file mode 100644 index 00000000000..fca727c4b56 --- /dev/null +++ b/acceptance/tests/windows/service_manager_integration.rb @@ -0,0 +1,51 @@ +test_name 'Test agent state via service control manager' do + + tag 'audit:integration' + + confine :to, platform: 'windows' + + teardown do + agents.each do |agent| + state = query_agent_state(agent) + if state != "STOPPED" + stop_puppet_windows_daemon(agent) + ensure_agent_state(agent, "STOPPED") + end + end + end + + def query_agent_state(host) + on(host, 'sc query puppet').stdout.match(/STATE.+\s{1}(\w+)/)[1] + end + + def start_puppet_windows_daemon(host) + on(host, 'sc start puppet') + end + + def stop_puppet_windows_daemon(host) + on(host, 'sc stop puppet') + end + + def ensure_agent_state(host, state) + retry_attempts = 0 + while retry_attempts < 5 + return if state == query_agent_state(host) + retry_attempts += 1 + sleep 1 + end + fail_test "State not #{state} after 5 tries" + end + + step 'store initial state' do + + agents.each do |agent| + initial_state = query_agent_state(agent) + assert_match("STOPPED", initial_state, "agent daemon should initially be stopped") + + start_puppet_windows_daemon(agent) + ensure_agent_state(agent, "RUNNING") + stop_puppet_windows_daemon(agent) + ensure_agent_state(agent, "STOPPED") + end + end +end From d226f1be114af2cee5532cf6437e7ea6afdad5f4 Mon Sep 17 00:00:00 2001 From: vibe Date: Tue, 7 May 2024 13:00:18 -0700 Subject: [PATCH 2/2] Fixes #9208 - puppet agent windows daemon startup inconsistency (cherry picked from commit d6386ac3698aa665bf6fcec1c158f7840ff6b8d1) --- lib/puppet/util/windows/daemon.rb | 47 ++++++++++--------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/lib/puppet/util/windows/daemon.rb b/lib/puppet/util/windows/daemon.rb index e4a61544317..327fc31183d 100644 --- a/lib/puppet/util/windows/daemon.rb +++ b/lib/puppet/util/windows/daemon.rb @@ -188,25 +188,6 @@ class Daemon end end - ThreadProc = FFI::Function.new(:ulong,[:pointer]) do |lpParameter| - ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRYW, 2) - - s = SERVICE_TABLE_ENTRYW.new(ste[0]) - s[:lpServiceName] = FFI::MemoryPointer.from_string('') - s[:lpServiceProc] = lpParameter - - s = SERVICE_TABLE_ENTRYW.new(ste[1]) - s[:lpServiceName] = nil - s[:lpServiceProc] = nil - - # No service to step, no service handle, no ruby exceptions, just terminate the thread.. - if !StartServiceCtrlDispatcherW(ste) - return 1 - end - - return 0 - end - # This is a shortcut for Daemon.new + Daemon#mainloop. # def self.mainloop @@ -256,26 +237,28 @@ def mainloop raise SystemCallError.new('CreateEvent', FFI.errno) end - hThread = CreateThread(nil, 0, ThreadProc, Service_Main, 0, nil) + hThread = Thread.new do + ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRYW, 2) - if hThread == 0 - raise SystemCallError.new('CreateThread', FFI.errno) - end + s = SERVICE_TABLE_ENTRYW.new(ste[0]) + s[:lpServiceName] = FFI::MemoryPointer.from_string("") + s[:lpServiceProc] = Service_Main - events = FFI::MemoryPointer.new(:pointer, 2) - events.put_pointer(0, FFI::Pointer.new(hThread)) - events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent)) + s = SERVICE_TABLE_ENTRYW.new(ste[1]) + s[:lpServiceName] = nil + s[:lpServiceProc] = nil - while ((index = WaitForMultipleObjects(2, events, 0, 1000)) == WAIT_TIMEOUT) do + # No service to step, no service handle, no ruby exceptions, just terminate the thread.. + StartServiceCtrlDispatcherW(ste) end - if index == WAIT_FAILED - raise SystemCallError.new('WaitForMultipleObjects', FFI.errno) + while (index = WaitForSingleObject(@@hStartEvent, 1000)) == WAIT_TIMEOUT + # The thread exited, so the show is off. + raise "Service_Main thread exited abnormally" unless hThread.alive? end - # The thread exited, so the show is off. - if index == WAIT_OBJECT_0 - raise "Service_Main thread exited abnormally" + if index == WAIT_FAILED + raise SystemCallError.new("WaitForSingleObject", FFI.errno) end thr = Thread.new do