Add Windows Services input plugin (#3023)
This commit is contained in:
parent
2a106be2b8
commit
09b1f7e468
2
Godeps
2
Godeps
|
@ -76,7 +76,7 @@ github.com/yuin/gopher-lua 66c871e454fcf10251c61bf8eff02d0978cae75a
|
||||||
github.com/zensqlmonitor/go-mssqldb ffe5510c6fa5e15e6d983210ab501c815b56b363
|
github.com/zensqlmonitor/go-mssqldb ffe5510c6fa5e15e6d983210ab501c815b56b363
|
||||||
golang.org/x/crypto dc137beb6cce2043eb6b5f223ab8bf51c32459f4
|
golang.org/x/crypto dc137beb6cce2043eb6b5f223ab8bf51c32459f4
|
||||||
golang.org/x/net f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
golang.org/x/net f2499483f923065a842d38eb4c7f1927e6fc6e6d
|
||||||
golang.org/x/sys a646d33e2ee3172a661fc09bca23bb4889a41bc8
|
golang.org/x/sys 739734461d1c916b6c72a63d7efda2b27edb369f
|
||||||
golang.org/x/text 506f9d5c962f284575e88337e7d9296d27e729d3
|
golang.org/x/text 506f9d5c962f284575e88337e7d9296d27e729d3
|
||||||
gopkg.in/asn1-ber.v1 4e86f4367175e39f69d9358a5f17b4dda270378d
|
gopkg.in/asn1-ber.v1 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||||
gopkg.in/fatih/pool.v2 6e328e67893eb46323ad06f0e92cb9536babbabc
|
gopkg.in/fatih/pool.v2 6e328e67893eb46323ad06f0e92cb9536babbabc
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -38,6 +38,7 @@ test:
|
||||||
test-windows:
|
test-windows:
|
||||||
go test ./plugins/inputs/ping/...
|
go test ./plugins/inputs/ping/...
|
||||||
go test ./plugins/inputs/win_perf_counters/...
|
go test ./plugins/inputs/win_perf_counters/...
|
||||||
|
go test ./plugins/inputs/win_services/...
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
|
@ -88,6 +88,7 @@ import (
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/varnish"
|
_ "github.com/influxdata/telegraf/plugins/inputs/varnish"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/webhooks"
|
_ "github.com/influxdata/telegraf/plugins/inputs/webhooks"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters"
|
_ "github.com/influxdata/telegraf/plugins/inputs/win_perf_counters"
|
||||||
|
_ "github.com/influxdata/telegraf/plugins/inputs/win_services"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/zfs"
|
_ "github.com/influxdata/telegraf/plugins/inputs/zfs"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/zipkin"
|
_ "github.com/influxdata/telegraf/plugins/inputs/zipkin"
|
||||||
_ "github.com/influxdata/telegraf/plugins/inputs/zookeeper"
|
_ "github.com/influxdata/telegraf/plugins/inputs/zookeeper"
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
# Telegraf Plugin: win_services
|
||||||
|
Input plugin to report Windows services info.
|
||||||
|
|
||||||
|
It requires that Telegraf must be running under the administrator privileges.
|
||||||
|
### Configuration:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[inputs.win_services]]
|
||||||
|
## Names of the services to monitor. Leave empty to monitor all the available services on the host
|
||||||
|
service_names = [
|
||||||
|
"LanmanServer",
|
||||||
|
"TermService",
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Measurements & Fields:
|
||||||
|
|
||||||
|
- win_services
|
||||||
|
- state : integer
|
||||||
|
- startup_mode : integer
|
||||||
|
|
||||||
|
The `state` field can have the following values:
|
||||||
|
- 1 - stopped
|
||||||
|
- 2 - start pending
|
||||||
|
- 3 - stop pending
|
||||||
|
- 4 - running
|
||||||
|
- 5 - continue pending
|
||||||
|
- 6 - pause pending
|
||||||
|
- 7 - paused
|
||||||
|
|
||||||
|
The `startup_mode` field can have the following values:
|
||||||
|
- 0 - boot start
|
||||||
|
- 1 - system start
|
||||||
|
- 2 - auto start
|
||||||
|
- 3 - demand start
|
||||||
|
- 4 - disabled
|
||||||
|
|
||||||
|
### Tags:
|
||||||
|
|
||||||
|
- All measurements have the following tags:
|
||||||
|
- service_name
|
||||||
|
- display_name
|
||||||
|
|
||||||
|
### Example Output:
|
||||||
|
```
|
||||||
|
* Plugin: inputs.win_services, Collection 1
|
||||||
|
> win_services,host=WIN2008R2H401,display_name=Server,service_name=LanmanServer state=4i,startup_mode=2i 1500040669000000000
|
||||||
|
> win_services,display_name=Remote\ Desktop\ Services,service_name=TermService,host=WIN2008R2H401 state=1i,startup_mode=3i 1500040669000000000
|
||||||
|
```
|
||||||
|
### TICK Scripts
|
||||||
|
|
||||||
|
A sample TICK script for a notification about a not running service.
|
||||||
|
It sends a notification whenever any service changes its state to be not _running_ and when it changes that state back to _running_.
|
||||||
|
The notification is sent via an HTTP POST call.
|
||||||
|
|
||||||
|
```
|
||||||
|
stream
|
||||||
|
|from()
|
||||||
|
.database('telegraf')
|
||||||
|
.retentionPolicy('autogen')
|
||||||
|
.measurement('win_services')
|
||||||
|
.groupBy('host','service_name')
|
||||||
|
|alert()
|
||||||
|
.crit(lambda: "state" != 4)
|
||||||
|
.stateChangesOnly()
|
||||||
|
.message('Service {{ index .Tags "service_name" }} on Host {{ index .Tags "host" }} is in state {{ index .Fields "state" }} ')
|
||||||
|
.post('http://localhost:666/alert/service')
|
||||||
|
```
|
|
@ -0,0 +1,183 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package win_services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
"golang.org/x/sys/windows/svc"
|
||||||
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
)
|
||||||
|
|
||||||
|
//WinService provides interface for svc.Service
|
||||||
|
type WinService interface {
|
||||||
|
Close() error
|
||||||
|
Config() (mgr.Config, error)
|
||||||
|
Query() (svc.Status, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//WinServiceManagerProvider sets interface for acquiring manager instance, like mgr.Mgr
|
||||||
|
type WinServiceManagerProvider interface {
|
||||||
|
Connect() (WinServiceManager, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//WinServiceManager provides interface for mgr.Mgr
|
||||||
|
type WinServiceManager interface {
|
||||||
|
Disconnect() error
|
||||||
|
OpenService(name string) (WinService, error)
|
||||||
|
ListServices() ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
//WinSvcMgr is wrapper for mgr.Mgr implementing WinServiceManager interface
|
||||||
|
type WinSvcMgr struct {
|
||||||
|
realMgr *mgr.Mgr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WinSvcMgr) Disconnect() error {
|
||||||
|
return m.realMgr.Disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WinSvcMgr) OpenService(name string) (WinService, error) {
|
||||||
|
return m.realMgr.OpenService(name)
|
||||||
|
}
|
||||||
|
func (m *WinSvcMgr) ListServices() ([]string, error) {
|
||||||
|
return m.realMgr.ListServices()
|
||||||
|
}
|
||||||
|
|
||||||
|
//MgProvider is an implementation of WinServiceManagerProvider interface returning WinSvcMgr
|
||||||
|
type MgProvider struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rmr *MgProvider) Connect() (WinServiceManager, error) {
|
||||||
|
scmgr, err := mgr.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return &WinSvcMgr{scmgr}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
## Names of the services to monitor. Leave empty to monitor all the available services on the host
|
||||||
|
service_names = [
|
||||||
|
"LanmanServer",
|
||||||
|
"TermService",
|
||||||
|
]
|
||||||
|
`
|
||||||
|
|
||||||
|
var description = "Input plugin to report Windows services info."
|
||||||
|
|
||||||
|
//WinServices is an implementation if telegraf.Input interface, providing info about Windows Services
|
||||||
|
type WinServices struct {
|
||||||
|
ServiceNames []string `toml:"service_names"`
|
||||||
|
mgrProvider WinServiceManagerProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceInfo struct {
|
||||||
|
ServiceName string
|
||||||
|
DisplayName string
|
||||||
|
State int
|
||||||
|
StartUpMode int
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WinServices) Description() string {
|
||||||
|
return description
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WinServices) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *WinServices) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
||||||
|
serviceInfos, err := listServices(m.mgrProvider, m.ServiceNames)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, service := range serviceInfos {
|
||||||
|
if service.Error == nil {
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
tags := make(map[string]string)
|
||||||
|
|
||||||
|
//display name could be empty, but still valid service
|
||||||
|
if len(service.DisplayName) > 0 {
|
||||||
|
tags["display_name"] = service.DisplayName
|
||||||
|
}
|
||||||
|
tags["service_name"] = service.ServiceName
|
||||||
|
|
||||||
|
fields["state"] = service.State
|
||||||
|
fields["startup_mode"] = service.StartUpMode
|
||||||
|
|
||||||
|
acc.AddFields("win_services", fields, tags)
|
||||||
|
} else {
|
||||||
|
acc.AddError(service.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//listServices gathers info about given services. If userServices is empty, it return info about all services on current Windows host. Any a critical error is returned.
|
||||||
|
func listServices(mgrProv WinServiceManagerProvider, userServices []string) ([]ServiceInfo, error) {
|
||||||
|
scmgr, err := mgrProv.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not open service manager: %s", err)
|
||||||
|
}
|
||||||
|
defer scmgr.Disconnect()
|
||||||
|
|
||||||
|
var serviceNames []string
|
||||||
|
if len(userServices) == 0 {
|
||||||
|
//Listing service names from system
|
||||||
|
serviceNames, err = scmgr.ListServices()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not list services: %s", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serviceNames = userServices
|
||||||
|
}
|
||||||
|
serviceInfos := make([]ServiceInfo, len(serviceNames))
|
||||||
|
|
||||||
|
for i, srvName := range serviceNames {
|
||||||
|
serviceInfos[i] = collectServiceInfo(scmgr, srvName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceInfos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//collectServiceInfo gathers info about a service from WindowsAPI
|
||||||
|
func collectServiceInfo(scmgr WinServiceManager, serviceName string) (serviceInfo ServiceInfo) {
|
||||||
|
|
||||||
|
serviceInfo.ServiceName = serviceName
|
||||||
|
srv, err := scmgr.OpenService(serviceName)
|
||||||
|
if err != nil {
|
||||||
|
serviceInfo.Error = fmt.Errorf("Could not open service '%s': %s", serviceName, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
srvStatus, err := srv.Query()
|
||||||
|
if err == nil {
|
||||||
|
serviceInfo.State = int(srvStatus.State)
|
||||||
|
} else {
|
||||||
|
serviceInfo.Error = fmt.Errorf("Could not query service '%s': %s", serviceName, err)
|
||||||
|
//finish collecting info on first found error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
srvCfg, err := srv.Config()
|
||||||
|
if err == nil {
|
||||||
|
serviceInfo.DisplayName = srvCfg.DisplayName
|
||||||
|
serviceInfo.StartUpMode = int(srvCfg.StartType)
|
||||||
|
} else {
|
||||||
|
serviceInfo.Error = fmt.Errorf("Could not get config of service '%s': %s", serviceName, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inputs.Add("win_services", func() telegraf.Input { return &WinServices{mgrProvider: &MgProvider{}} })
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
//these tests must be run under administrator account
|
||||||
|
package win_services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var InvalidServices = []string{"XYZ1@", "ZYZ@", "SDF_@#"}
|
||||||
|
var KnownServices = []string{"LanmanServer", "TermService"}
|
||||||
|
|
||||||
|
func TestList(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
services, err := listServices(&MgProvider{}, KnownServices)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, services, 2, "Different number of services")
|
||||||
|
assert.Equal(t, services[0].ServiceName, KnownServices[0])
|
||||||
|
assert.Nil(t, services[0].Error)
|
||||||
|
assert.Equal(t, services[1].ServiceName, KnownServices[1])
|
||||||
|
assert.Nil(t, services[1].Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyList(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
services, err := listServices(&MgProvider{}, []string{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Condition(t, func() bool { return len(services) > 20 }, "Too few service")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListEr(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
services, err := listServices(&MgProvider{}, InvalidServices)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, services, 3, "Different number of services")
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
assert.Equal(t, services[i].ServiceName, InvalidServices[i])
|
||||||
|
assert.NotNil(t, services[i].Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGather(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
ws := &WinServices{KnownServices, &MgProvider{}}
|
||||||
|
assert.Len(t, ws.ServiceNames, 2, "Different number of services")
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
require.NoError(t, ws.Gather(&acc))
|
||||||
|
assert.Len(t, acc.Errors, 0, "There should be no errors after gather")
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
tags := make(map[string]string)
|
||||||
|
si := getServiceInfo(KnownServices[i])
|
||||||
|
fields["state"] = int(si.State)
|
||||||
|
fields["startup_mode"] = int(si.StartUpMode)
|
||||||
|
tags["service_name"] = si.ServiceName
|
||||||
|
tags["display_name"] = si.DisplayName
|
||||||
|
acc.AssertContainsTaggedFields(t, "win_services", fields, tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGatherErrors(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("Skipping integration test in short mode")
|
||||||
|
}
|
||||||
|
ws := &WinServices{InvalidServices, &MgProvider{}}
|
||||||
|
assert.Len(t, ws.ServiceNames, 3, "Different number of services")
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
require.NoError(t, ws.Gather(&acc))
|
||||||
|
assert.Len(t, acc.Errors, 3, "There should be 3 errors after gather")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getServiceInfo(srvName string) *ServiceInfo {
|
||||||
|
|
||||||
|
scmgr, err := mgr.Connect()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer scmgr.Disconnect()
|
||||||
|
|
||||||
|
srv, err := scmgr.OpenService(srvName)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var si ServiceInfo
|
||||||
|
si.ServiceName = srvName
|
||||||
|
srvStatus, err := srv.Query()
|
||||||
|
if err == nil {
|
||||||
|
si.State = int(srvStatus.State)
|
||||||
|
} else {
|
||||||
|
si.Error = err
|
||||||
|
}
|
||||||
|
|
||||||
|
srvCfg, err := srv.Config()
|
||||||
|
if err == nil {
|
||||||
|
si.DisplayName = srvCfg.DisplayName
|
||||||
|
si.StartUpMode = int(srvCfg.StartType)
|
||||||
|
} else {
|
||||||
|
si.Error = err
|
||||||
|
}
|
||||||
|
srv.Close()
|
||||||
|
return &si
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package win_services
|
|
@ -0,0 +1,179 @@
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package win_services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/sys/windows/svc"
|
||||||
|
"golang.org/x/sys/windows/svc/mgr"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//testData is DD wrapper for unit testing of WinServices
|
||||||
|
type testData struct {
|
||||||
|
//collection that will be returned in ListServices if service array passed into WinServices constructor is empty
|
||||||
|
queryServiceList []string
|
||||||
|
mgrConnectError error
|
||||||
|
mgrListServicesError error
|
||||||
|
services []serviceTestInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type serviceTestInfo struct {
|
||||||
|
serviceOpenError error
|
||||||
|
serviceQueryError error
|
||||||
|
serviceConfigError error
|
||||||
|
serviceName string
|
||||||
|
displayName string
|
||||||
|
state int
|
||||||
|
startUpMode int
|
||||||
|
}
|
||||||
|
|
||||||
|
type FakeSvcMgr struct {
|
||||||
|
testData testData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakeSvcMgr) Disconnect() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakeSvcMgr) OpenService(name string) (WinService, error) {
|
||||||
|
for _, s := range m.testData.services {
|
||||||
|
if s.serviceName == name {
|
||||||
|
if s.serviceOpenError != nil {
|
||||||
|
return nil, s.serviceOpenError
|
||||||
|
} else {
|
||||||
|
return &FakeWinSvc{s}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Cannot find service %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakeSvcMgr) ListServices() ([]string, error) {
|
||||||
|
if m.testData.mgrListServicesError != nil {
|
||||||
|
return nil, m.testData.mgrListServicesError
|
||||||
|
} else {
|
||||||
|
return m.testData.queryServiceList, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FakeMgProvider struct {
|
||||||
|
testData testData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakeMgProvider) Connect() (WinServiceManager, error) {
|
||||||
|
if m.testData.mgrConnectError != nil {
|
||||||
|
return nil, m.testData.mgrConnectError
|
||||||
|
} else {
|
||||||
|
return &FakeSvcMgr{m.testData}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FakeWinSvc struct {
|
||||||
|
testData serviceTestInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FakeWinSvc) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (m *FakeWinSvc) Config() (mgr.Config, error) {
|
||||||
|
if m.testData.serviceConfigError != nil {
|
||||||
|
return mgr.Config{}, m.testData.serviceConfigError
|
||||||
|
} else {
|
||||||
|
return mgr.Config{0, uint32(m.testData.startUpMode), 0, "", "", 0, nil, m.testData.serviceName, m.testData.displayName, "", ""}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (m *FakeWinSvc) Query() (svc.Status, error) {
|
||||||
|
if m.testData.serviceQueryError != nil {
|
||||||
|
return svc.Status{}, m.testData.serviceQueryError
|
||||||
|
} else {
|
||||||
|
return svc.Status{svc.State(m.testData.state), 0, 0, 0}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var testErrors = []testData{
|
||||||
|
{nil, errors.New("Fake mgr connect error"), nil, nil},
|
||||||
|
{nil, nil, errors.New("Fake mgr list services error"), nil},
|
||||||
|
{[]string{"Fake service 1", "Fake service 2", "Fake service 3"}, nil, nil, []serviceTestInfo{
|
||||||
|
{errors.New("Fake srv open error"), nil, nil, "Fake service 1", "", 0, 0},
|
||||||
|
{nil, errors.New("Fake srv query error"), nil, "Fake service 2", "", 0, 0},
|
||||||
|
{nil, nil, errors.New("Fake srv config error"), "Fake service 3", "", 0, 0},
|
||||||
|
}},
|
||||||
|
{nil, nil, nil, []serviceTestInfo{
|
||||||
|
{errors.New("Fake srv open error"), nil, nil, "Fake service 1", "", 0, 0},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBasicInfo(t *testing.T) {
|
||||||
|
|
||||||
|
winServices := &WinServices{nil, &FakeMgProvider{testErrors[0]}}
|
||||||
|
assert.NotEmpty(t, winServices.SampleConfig())
|
||||||
|
assert.NotEmpty(t, winServices.Description())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMgrErrors(t *testing.T) {
|
||||||
|
//mgr.connect error
|
||||||
|
winServices := &WinServices{nil, &FakeMgProvider{testErrors[0]}}
|
||||||
|
var acc1 testutil.Accumulator
|
||||||
|
err := winServices.Gather(&acc1)
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), testErrors[0].mgrConnectError.Error())
|
||||||
|
|
||||||
|
////mgr.listServices error
|
||||||
|
winServices = &WinServices{nil, &FakeMgProvider{testErrors[1]}}
|
||||||
|
var acc2 testutil.Accumulator
|
||||||
|
err = winServices.Gather(&acc2)
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), testErrors[1].mgrListServicesError.Error())
|
||||||
|
|
||||||
|
////mgr.listServices error 2
|
||||||
|
winServices = &WinServices{[]string{"Fake service 1"}, &FakeMgProvider{testErrors[3]}}
|
||||||
|
var acc3 testutil.Accumulator
|
||||||
|
err = winServices.Gather(&acc3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, acc3.Errors, 1)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceErrors(t *testing.T) {
|
||||||
|
winServices := &WinServices{nil, &FakeMgProvider{testErrors[2]}}
|
||||||
|
var acc1 testutil.Accumulator
|
||||||
|
require.NoError(t, winServices.Gather(&acc1))
|
||||||
|
assert.Len(t, acc1.Errors, 3)
|
||||||
|
//open service error
|
||||||
|
assert.Contains(t, acc1.Errors[0].Error(), testErrors[2].services[0].serviceOpenError.Error())
|
||||||
|
//query service error
|
||||||
|
assert.Contains(t, acc1.Errors[1].Error(), testErrors[2].services[1].serviceQueryError.Error())
|
||||||
|
//config service error
|
||||||
|
assert.Contains(t, acc1.Errors[2].Error(), testErrors[2].services[2].serviceConfigError.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var testSimpleData = []testData{
|
||||||
|
{[]string{"Service 1", "Service 2"}, nil, nil, []serviceTestInfo{
|
||||||
|
{nil, nil, nil, "Service 1", "Fake service 1", 1, 2},
|
||||||
|
{nil, nil, nil, "Service 2", "Fake service 2", 1, 2},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGather2(t *testing.T) {
|
||||||
|
winServices := &WinServices{nil, &FakeMgProvider{testSimpleData[0]}}
|
||||||
|
var acc1 testutil.Accumulator
|
||||||
|
require.NoError(t, winServices.Gather(&acc1))
|
||||||
|
assert.Len(t, acc1.Errors, 0, "There should be no errors after gather")
|
||||||
|
|
||||||
|
for _, s := range testSimpleData[0].services {
|
||||||
|
fields := make(map[string]interface{})
|
||||||
|
tags := make(map[string]string)
|
||||||
|
fields["state"] = int(s.state)
|
||||||
|
fields["startup_mode"] = int(s.startUpMode)
|
||||||
|
tags["service_name"] = s.serviceName
|
||||||
|
tags["display_name"] = s.displayName
|
||||||
|
acc1.AssertContainsTaggedFields(t, "win_services", fields, tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue