Files
nomad/command/windows_service_uninstall_test.go
Chris Roberts c3dcdb5413 [cli] Add windows service commands (#26442)
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.
2025-09-02 16:40:35 -07:00

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()
})
}
}