agent/setupcli/managers/servicemanagers/windowsmanager.go (91 lines of code) (raw):

// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing // permissions and limitations under the License. //go:build windows // +build windows // Package servicemanagers contains functions related to service manager package servicemanagers import ( "fmt" "github.com/aws/amazon-ssm-agent/agent/setupcli/managers/common" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/mgr" ) const ( netExecPath = "C:\\Windows\\System32\\net.exe" serviceName = "AmazonSSMAgent" ) var checkAgentStatus = func(m *windowsManager) (common.AgentStatus, error) { return m.GetAgentStatus() } type windowsManager struct { managerHelper common.IManagerHelper } // StartAgent starts the agent func (m *windowsManager) StartAgent() error { output, err := m.managerHelper.RunCommand(netExecPath, "start", serviceName) if err != nil { // The command will throw an error if the service is already started, so we want to ignore these type of errors if agentStatus, err := checkAgentStatus(m); err == nil && agentStatus == common.Running { // Service is already running return nil } return fmt.Errorf("windows: failed to start agent with output '%s' and error: %v", output, err) } return nil } // StopAgent stops the agent func (m *windowsManager) StopAgent() error { output, err := m.managerHelper.RunCommand(netExecPath, "stop", serviceName) if err != nil { // The command will throw an error if the service is already stopped, so we want to ignore these type of errors if agentStatus, err := checkAgentStatus(m); err == nil && agentStatus == common.Stopped { // Service is already stopped return nil } return fmt.Errorf("windows: failed to stop agent with output '%s' and error: %v", output, err) } return nil } func windowsServiceStatusToString(state svc.State) string { switch state { case svc.Stopped: return "Stopped" case svc.StartPending: return "StartPending" case svc.StopPending: return "StopPending" case svc.Running: return "Running" case svc.ContinuePending: return "ContinuePending" case svc.PausePending: return "PausePending" case svc.Paused: return "Paused" default: return "" } } // GetAgentStatus returns the status of the agent from the perspective of the service manager func (m *windowsManager) GetAgentStatus() (common.AgentStatus, error) { manager, err := mgr.Connect() if err != nil { return common.UndefinedStatus, fmt.Errorf("failed to connect to windows service manager: %v", err) } defer manager.Disconnect() service, err := manager.OpenService(serviceName) if err != nil { return common.UndefinedStatus, fmt.Errorf("failed to open windows service manager: %v", err) } defer service.Close() serviceStatus, err := service.Query() if err != nil { return common.UndefinedStatus, fmt.Errorf("failed to query windows service: %v", err) } if serviceStatus.State == svc.Running { return common.Running, nil } else if serviceStatus.State == svc.Stopped { return common.Stopped, nil } return common.UndefinedStatus, fmt.Errorf("unexpected service status: %s", windowsServiceStatusToString(serviceStatus.State)) } // ReloadManager reloads the service manager configuration files func (m *windowsManager) ReloadManager() error { return nil } // IsManagerEnvironment returns true if all commands required by the package manager are available func (m *windowsManager) IsManagerEnvironment() bool { return true } // GetName returns the service manager name func (m *windowsManager) GetName() string { return "windows" } // GetType returns the service manage type func (m *windowsManager) GetType() ServiceManager { return Windows }