mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
Adds a new `windows` command which is available when running on a Windows hosts. The command includes two new subcommands: * `service install` * `service uninstall` The `service install` command will install the called binary into the Windows program files directory, create a new Windows service, setup configuration and data directories, and register the service with the Window eventlog. If the service and/or binary already exist, the service will be stopped, service and eventlog updated if needed, binary replaced, and the service started again. The `service uninstall` command will stop the service, remove the Windows service, and deregister the service with the eventlog. It will not remove the configuration/data directory nor will it remove the installed binary.
147 lines
4.0 KiB
Go
147 lines
4.0 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package command
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/hashicorp/cli"
|
|
"github.com/hashicorp/nomad/helper/winsvc"
|
|
"github.com/shoenig/test/must"
|
|
)
|
|
|
|
func TestWindowsServiceUninstallCommand_Run(t *testing.T) {
|
|
testCases := []struct {
|
|
desc string
|
|
args []string
|
|
privilegeFn func() bool
|
|
setup func(*winsvc.MockWindowsServiceManager)
|
|
output string
|
|
errOutput string
|
|
status int
|
|
}{
|
|
{
|
|
desc: "service installed",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
srv := m.NewMockWindowsService()
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, true, nil)
|
|
m.ExpectGetService(winsvc.WINDOWS_SERVICE_NAME, srv, nil)
|
|
srv.ExpectStop(nil)
|
|
srv.ExpectDisableEventlog(nil)
|
|
srv.ExpectDelete(nil)
|
|
},
|
|
output: "uninstalled nomad",
|
|
},
|
|
{
|
|
desc: "service not installed",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, false, nil)
|
|
},
|
|
output: "uninstalled nomad",
|
|
},
|
|
{
|
|
desc: "service registration check failure",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, false, errors.New("registered check failure"))
|
|
},
|
|
errOutput: "unable to check for existing service",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "get service failure",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, true, nil)
|
|
m.ExpectGetService(winsvc.WINDOWS_SERVICE_NAME, nil, errors.New("get service failure"))
|
|
},
|
|
errOutput: "could not get existing service",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "service stop failure",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
srv := m.NewMockWindowsService()
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, true, nil)
|
|
m.ExpectGetService(winsvc.WINDOWS_SERVICE_NAME, srv, nil)
|
|
srv.ExpectStop(errors.New("service stop failure"))
|
|
},
|
|
errOutput: "unable to stop service",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "disable eventlog failure",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
srv := m.NewMockWindowsService()
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, true, nil)
|
|
m.ExpectGetService(winsvc.WINDOWS_SERVICE_NAME, srv, nil)
|
|
srv.ExpectStop(nil)
|
|
srv.ExpectDisableEventlog(errors.New("disable eventlog failure"))
|
|
},
|
|
errOutput: "could not remove eventlog configuration",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "delete service failure",
|
|
setup: func(m *winsvc.MockWindowsServiceManager) {
|
|
srv := m.NewMockWindowsService()
|
|
m.ExpectIsServiceRegistered(winsvc.WINDOWS_SERVICE_NAME, true, nil)
|
|
m.ExpectGetService(winsvc.WINDOWS_SERVICE_NAME, srv, nil)
|
|
srv.ExpectStop(nil)
|
|
srv.ExpectDisableEventlog(nil)
|
|
srv.ExpectDelete(errors.New("service delete failure"))
|
|
},
|
|
errOutput: "could not delete service",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "with arguments",
|
|
args: []string{"any", "value"},
|
|
errOutput: "command takes no arguments",
|
|
status: 1,
|
|
},
|
|
{
|
|
desc: "not running as administator",
|
|
privilegeFn: func() bool { return false },
|
|
errOutput: "must be run with Administator privileges",
|
|
status: 1,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
ui := cli.NewMockUi()
|
|
mgr := winsvc.NewMockWindowsServiceManager(t)
|
|
if tc.setup != nil {
|
|
tc.setup(mgr)
|
|
}
|
|
|
|
pfn := tc.privilegeFn
|
|
if pfn == nil {
|
|
pfn = func() bool { return true }
|
|
}
|
|
|
|
cmd := &WindowsServiceUninstallCommand{
|
|
Meta: Meta{Ui: ui},
|
|
serviceManagerFn: func() (winsvc.WindowsServiceManager, error) {
|
|
return mgr, nil
|
|
},
|
|
privilegedCheckFn: pfn,
|
|
}
|
|
result := cmd.Run(tc.args)
|
|
|
|
out := ui.OutputWriter.String()
|
|
outErr := ui.ErrorWriter.String()
|
|
must.Eq(t, result, tc.status)
|
|
if tc.output != "" {
|
|
must.StrContains(t, out, tc.output)
|
|
}
|
|
if tc.errOutput != "" {
|
|
must.StrContains(t, outErr, tc.errOutput)
|
|
}
|
|
|
|
mgr.AssertExpectations()
|
|
})
|
|
}
|
|
}
|