Skip to content

Commit

Permalink
Merge branch 'main' of github.com:sni/snclient
Browse files Browse the repository at this point in the history
  • Loading branch information
lausser committed Jun 28, 2023
2 parents 0e7803e + 5662059 commit cc14dca
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ build: vendor go.work snclient.ini server.crt server.key
build-watch: vendor
ls cmd/*/*.go pkg/*/*.go pkg/*/*/*.go snclient.ini | entr -sr "$(MAKE) && ./snclient $(filter-out $@,$(MAKECMDGOALS))"

# run build watch with other build targets, ex.: make build-watch-any -- build-windows-amd64
# run build watch with other build targets, ex.: make build-watch-make -- build-windows-amd64
build-watch-make: vendor
ls cmd/*/*.go pkg/*/*.go pkg/*/*/*.go snclient.ini | entr -sr "$(MAKE) $(filter-out $@,$(MAKECMDGOALS))"

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ X: completed
| check_memory | X | X | X | X |
| check_network | W | W | W | W |
| check_os_version | X | X | X | X |
| check_pagefile | | | | |
| check_process | W | W | W | W |
| check_service | X | | | |
| check_snclient_version | X | | | |
| check_snclient_version | X | X | X | X |
| check_uptime | X | X | X | X |
| check_wmi | W | | | |
| check_wrap | W | W | W | W |
Expand Down
2 changes: 1 addition & 1 deletion pkg/snclient/check_cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (l *CheckCPU) Check(snc *Agent, args []string) (*CheckResult, error) {
check.listData = append(check.listData, map[string]string{
"time": time,
"core": name,
"load": fmt.Sprintf("%f", avg),
"load": fmt.Sprintf("%.0f", utils.ToPrecision(avg, 0)),
})
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
ThresholdName: "load",
Expand Down
81 changes: 54 additions & 27 deletions pkg/snclient/check_service_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,36 +189,11 @@ func (l *CheckService) addService(check *CheckData, ctrlMgr *mgr.Mgr, service st

check.listData = append(check.listData, listEntry)

if len(services) == 0 {
if len(services) == 0 && !check.showAll {
return nil
}

check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Name: service,
Value: float64(statusCode.State),
})
if mem != nil {
check.result.Metrics = append(
check.result.Metrics,
&CheckMetric{
Name: fmt.Sprintf("%s rss", service),
Value: float64(mem.RSS),
Unit: "B",
},
&CheckMetric{
Name: fmt.Sprintf("%s vms", service),
Value: float64(mem.VMS),
Unit: "B",
},
)
}
if cpu != nil {
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Name: fmt.Sprintf("%s cpu", service),
Value: utils.ToPrecision(*cpu, 1),
Unit: "%",
})
}
l.addMetrics(check, service, statusCode, mem, cpu)

return nil
}
Expand Down Expand Up @@ -313,3 +288,55 @@ func (l *CheckService) svcStartType(startType uint32, delayed bool) string {

return "unknown"
}

func (l *CheckService) addMetrics(check *CheckData, service string, statusCode *svc.Status, mem *process.MemoryInfoStat, cpu *float64) {
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Name: service,
Value: float64(statusCode.State),
})
if mem != nil {
check.result.Metrics = append(
check.result.Metrics,
&CheckMetric{
Name: fmt.Sprintf("%s rss", service),
Value: float64(mem.RSS),
Unit: "B",
Warning: check.TransformThreshold(check.warnThreshold, "rss", fmt.Sprintf("%s rss", service), "B", "B", 0),
Critical: check.TransformThreshold(check.warnThreshold, "rss", fmt.Sprintf("%s rss", service), "B", "B", 0),
},
&CheckMetric{
Name: fmt.Sprintf("%s vms", service),
Value: float64(mem.VMS),
Unit: "B",
Warning: check.TransformThreshold(check.warnThreshold, "vms", fmt.Sprintf("%s vms", service), "B", "B", 0),
Critical: check.TransformThreshold(check.warnThreshold, "vms", fmt.Sprintf("%s vms", service), "B", "B", 0),
},
)
} else {
check.result.Metrics = append(
check.result.Metrics,
&CheckMetric{
Name: fmt.Sprintf("%s rss", service),
Value: "U",
},
&CheckMetric{
Name: fmt.Sprintf("%s vms", service),
Value: "U",
},
)
}
if cpu != nil {
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Name: fmt.Sprintf("%s cpu", service),
Value: utils.ToPrecision(*cpu, 1),
Unit: "%",
Warning: check.warnThreshold,
Critical: check.critThreshold,
})
} else {
check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Name: fmt.Sprintf("%s cpu", service),
Value: "U",
})
}
}
5 changes: 3 additions & 2 deletions pkg/snclient/check_uptime.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ func (l *CheckUptime) Check(_ *Agent, args []string) (*CheckResult, error) {
uptime := time.Since(time.Unix(int64(bootTime), 0))

check.listData = append(check.listData, map[string]string{
"uptime": utils.DurationString(uptime.Truncate(time.Minute)),
"boot": time.Unix(int64(bootTime), 0).UTC().Format("2006-01-02 15:04:05"),
"uptime": utils.DurationString(uptime.Truncate(time.Minute)),
"uptime_value": fmt.Sprintf("%.1f", uptime.Seconds()),
"boot": time.Unix(int64(bootTime), 0).UTC().Format("2006-01-02 15:04:05"),
})

check.result.Metrics = append(check.result.Metrics, &CheckMetric{
Expand Down
2 changes: 1 addition & 1 deletion pkg/snclient/check_wrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func (l *CheckWrap) Check(_ *Agent, args []string) (*CheckResult, error) {
log.Debugf("executing command: %s %s", winExecutable, "Set-ExecutionPolicy -Scope Process Unrestricted -Force;"+formattedCommand+"; $LASTEXITCODE")
scriptOutput, err = exec.Command(winExecutable, "Set-ExecutionPolicy -Scope Process Unrestricted -Force;"+formattedCommand+"; $LASTEXITCODE").CombinedOutput()
case "linux":
log.Debugf("executing command: %s", formattedCommand + "; echo $?")
log.Debugf("executing command: %s", formattedCommand+"; echo $?")
scriptOutput, err = exec.Command(formattedCommand + "; echo $?").CombinedOutput()
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/snclient/checkmetric.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ type CheckMetric struct {
func (m *CheckMetric) String() string {
var res bytes.Buffer

// Unknown value
if fmt.Sprintf("%v", m.Value) == "U" {
return fmt.Sprintf("'%s'=U", m.Name)
}

res.WriteString(fmt.Sprintf("'%s'=%s%s", m.Name, convert.Num2String(m.Value), m.Unit))

res.WriteString(";")
Expand Down
21 changes: 21 additions & 0 deletions pkg/snclient/checkmetric_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package snclient

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCheckMetricsString(t *testing.T) {
for _, check := range []struct {
metric CheckMetric
expect string
}{
{CheckMetric{Name: "val", Value: "13", Unit: "B"}, `'val'=13B`},
{CheckMetric{Name: "val", Value: "0.5", Unit: ""}, `'val'=0.5`},
{CheckMetric{Name: "val", Value: "U", Unit: ""}, `'val'=U`},
} {
res := check.metric.String()
assert.Equalf(t, check.expect, res, "CheckMetric.String() ->> %s", res)
}
}
13 changes: 12 additions & 1 deletion pkg/snclient/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,12 @@ func (c *Condition) getVarValue(data map[string]string) (val string, ok bool) {
}
}

varStr, ok := data[c.keyword]
varStr, ok := data[c.keyword+"_value"]
if ok {
return varStr, ok
}

varStr, ok = data[c.keyword]

return varStr, ok
}
Expand Down Expand Up @@ -385,6 +390,12 @@ func conditionNext(token []string) (cond *Condition, remaining []string, err err
}
query := keyword

// trim quotes from keyword
keyword, err = utils.TrimQuotes(keyword)
if err != nil {
return nil, nil, fmt.Errorf("%s", err.Error())
}

cond = &Condition{
keyword: keyword,
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/snclient/condition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ func TestConditionCompare(t *testing.T) {
{"test regex 'a+'", "test", "bbbb", false},
{"test !~ 'a+'", "test", "bbb", true},
{"test !~ 'a+'", "test", "aa", false},
{"'test space' > 5", "test space", "2", false},
{"'test space' < 5", "test space", "2", true},
} {
threshold, err := NewCondition(check.threshold)
assert.NoErrorf(t, err, "parsed threshold")
Expand Down
11 changes: 11 additions & 0 deletions pkg/snclient/listen_web.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ type CheckWebPerfNumber struct {
}

func (n CheckWebPerfNumber) MarshalJSON() ([]byte, error) {
if fmt.Sprintf("%v", n.num) == "U" {
return []byte(`"U"`), nil
}
val, err := convert.Num2StringE(n.num)
if err != nil {
return nil, fmt.Errorf("num2string: %s", err.Error())
Expand Down Expand Up @@ -257,6 +260,10 @@ func (l *HandlerWebLegacy) ServeHTTP(res http.ResponseWriter, req *http.Request)
// check clear text password
if !l.Handler.verifyPassword(req.Header.Get("Password")) {
http.Error(res, http.StatusText(http.StatusForbidden), http.StatusForbidden)
res.Header().Set("Content-Type", "application/json")
LogError(json.NewEncoder(res).Encode(map[string]interface{}{
"error": "permission denied",
}))

return
}
Expand Down Expand Up @@ -310,6 +317,10 @@ func (l *HandlerWebV1) ServeHTTP(res http.ResponseWriter, req *http.Request) {
_, password, _ := req.BasicAuth()
if !l.Handler.verifyPassword(password) {
http.Error(res, http.StatusText(http.StatusForbidden), http.StatusForbidden)
res.Header().Set("Content-Type", "application/json")
LogError(json.NewEncoder(res).Encode(map[string]interface{}{
"error": "permission denied",
}))

return
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,29 @@ func TokenizeBy(str, separator string) []string {
return tokens
}

func TrimQuotes(str string) (res string, err error) {
switch {
case strings.HasPrefix(str, "'"):
if !strings.HasSuffix(str, "'") || len(str) == 1 {
return "", fmt.Errorf("unbalanced quotes in '%s'", str)
}
str = strings.TrimPrefix(str, "'")
str = strings.TrimSuffix(str, "'")
case strings.HasPrefix(str, `"`):
if !strings.HasSuffix(str, `"`) || len(str) == 1 {
return "", fmt.Errorf("unbalanced quotes in '%s'", str)
}
str = strings.TrimPrefix(str, `"`)
str = strings.TrimSuffix(str, `"`)
case strings.HasSuffix(str, "'"):
return "", fmt.Errorf("unbalanced quotes in '%s'", str)
case strings.HasSuffix(str, `"`):
return "", fmt.Errorf("unbalanced quotes in '%s'", str)
}

return str, nil
}

func ParseVersion(str string) (num float64) {
str = strings.TrimPrefix(str, "v")
token := strings.Split(str, ".")
Expand Down
30 changes: 30 additions & 0 deletions pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,33 @@ func TestDurationString(t *testing.T) {
assert.Equalf(t, tst.res, res, "DurationString: %v -> %v", tst.in, res)
}
}

func TestTrimQuotes(t *testing.T) {
tests := []struct {
in string
res string
err bool
}{
{`"test"`, `test`, false},
{`'test'`, `test`, false},
{`'test test'`, `test test`, false},
{`"test test"`, `test test`, false},
{`"test test`, "", true},
{`'test test`, "", true},
{`test"test`, `test"test`, false},
{`test'test`, `test'test`, false},
{`test test'`, "", true},
{`test test"`, "", true},
}

for _, tst := range tests {
res, err := TrimQuotes(tst.in)
switch tst.err {
case true:
assert.Errorf(t, err, "TrimQuotes should error on %s", tst.in)
case false:
assert.Nilf(t, err, "TrimQuotes should not error on %s", tst.in)
assert.Equalf(t, tst.res, res, "TrimQuotes: %v -> %v", tst.in, res)
}
}
}

0 comments on commit cc14dca

Please sign in to comment.