Skip to content

Commit 197f6de

Browse files
authored
feat(host_analyzer): add host sysctl analyzer (#1681)
* feat(host_analyzer): add host sysctl analyzer * chore: add e2e tests to support bundle collection * chore: missing spec e2e test update * chore: cleanup remote collector and use parse operator * chore: update schemas
1 parent 2f62240 commit 197f6de

17 files changed

+832
-4
lines changed

config/crds/troubleshoot.sh_analyzers.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,55 @@ spec:
26552655
required:
26562656
- outcomes
26572657
type: object
2658+
sysctl:
2659+
properties:
2660+
annotations:
2661+
additionalProperties:
2662+
type: string
2663+
type: object
2664+
checkName:
2665+
type: string
2666+
collectorName:
2667+
type: string
2668+
exclude:
2669+
type: BoolString
2670+
outcomes:
2671+
items:
2672+
properties:
2673+
fail:
2674+
properties:
2675+
message:
2676+
type: string
2677+
uri:
2678+
type: string
2679+
when:
2680+
type: string
2681+
type: object
2682+
pass:
2683+
properties:
2684+
message:
2685+
type: string
2686+
uri:
2687+
type: string
2688+
when:
2689+
type: string
2690+
type: object
2691+
warn:
2692+
properties:
2693+
message:
2694+
type: string
2695+
uri:
2696+
type: string
2697+
when:
2698+
type: string
2699+
type: object
2700+
type: object
2701+
type: array
2702+
strict:
2703+
type: BoolString
2704+
required:
2705+
- outcomes
2706+
type: object
26582707
systemPackages:
26592708
properties:
26602709
annotations:

config/crds/troubleshoot.sh_hostcollectors.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,55 @@ spec:
895895
required:
896896
- outcomes
897897
type: object
898+
sysctl:
899+
properties:
900+
annotations:
901+
additionalProperties:
902+
type: string
903+
type: object
904+
checkName:
905+
type: string
906+
collectorName:
907+
type: string
908+
exclude:
909+
type: BoolString
910+
outcomes:
911+
items:
912+
properties:
913+
fail:
914+
properties:
915+
message:
916+
type: string
917+
uri:
918+
type: string
919+
when:
920+
type: string
921+
type: object
922+
pass:
923+
properties:
924+
message:
925+
type: string
926+
uri:
927+
type: string
928+
when:
929+
type: string
930+
type: object
931+
warn:
932+
properties:
933+
message:
934+
type: string
935+
uri:
936+
type: string
937+
when:
938+
type: string
939+
type: object
940+
type: object
941+
type: array
942+
strict:
943+
type: BoolString
944+
required:
945+
- outcomes
946+
type: object
898947
systemPackages:
899948
properties:
900949
annotations:

config/crds/troubleshoot.sh_hostpreflights.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,55 @@ spec:
895895
required:
896896
- outcomes
897897
type: object
898+
sysctl:
899+
properties:
900+
annotations:
901+
additionalProperties:
902+
type: string
903+
type: object
904+
checkName:
905+
type: string
906+
collectorName:
907+
type: string
908+
exclude:
909+
type: BoolString
910+
outcomes:
911+
items:
912+
properties:
913+
fail:
914+
properties:
915+
message:
916+
type: string
917+
uri:
918+
type: string
919+
when:
920+
type: string
921+
type: object
922+
pass:
923+
properties:
924+
message:
925+
type: string
926+
uri:
927+
type: string
928+
when:
929+
type: string
930+
type: object
931+
warn:
932+
properties:
933+
message:
934+
type: string
935+
uri:
936+
type: string
937+
when:
938+
type: string
939+
type: object
940+
type: object
941+
type: array
942+
strict:
943+
type: BoolString
944+
required:
945+
- outcomes
946+
type: object
898947
systemPackages:
899948
properties:
900949
annotations:

config/crds/troubleshoot.sh_supportbundles.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19542,6 +19542,55 @@ spec:
1954219542
required:
1954319543
- outcomes
1954419544
type: object
19545+
sysctl:
19546+
properties:
19547+
annotations:
19548+
additionalProperties:
19549+
type: string
19550+
type: object
19551+
checkName:
19552+
type: string
19553+
collectorName:
19554+
type: string
19555+
exclude:
19556+
type: BoolString
19557+
outcomes:
19558+
items:
19559+
properties:
19560+
fail:
19561+
properties:
19562+
message:
19563+
type: string
19564+
uri:
19565+
type: string
19566+
when:
19567+
type: string
19568+
type: object
19569+
pass:
19570+
properties:
19571+
message:
19572+
type: string
19573+
uri:
19574+
type: string
19575+
when:
19576+
type: string
19577+
type: object
19578+
warn:
19579+
properties:
19580+
message:
19581+
type: string
19582+
uri:
19583+
type: string
19584+
when:
19585+
type: string
19586+
type: object
19587+
type: object
19588+
type: array
19589+
strict:
19590+
type: BoolString
19591+
required:
19592+
- outcomes
19593+
type: object
1954519594
systemPackages:
1954619595
properties:
1954719596
annotations:

examples/preflight/host/sysctl.yaml

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ metadata:
55
spec:
66
collectors:
77
- sysctl:
8-
collectorName: sysctl
9-
#TODO add analyzer once implemented
10-
analyzers: []
8+
collectorName: host sysctl
9+
analyzers:
10+
- sysctl:
11+
collectorName: host sysctl
12+
outcomes:
13+
- warn:
14+
when: 'kern.ostype == Darwin'
15+
message: "Running sysctl on a Darwin host"
16+
- pass:
17+
when: 'net.ipv4.conf.default.arp_ignore > 0'
18+
message: "ARP ignore is enabled for the default interfaces interfaces on the host."

pkg/analyze/host_analyzer.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func GetHostAnalyzer(analyzer *troubleshootv1beta2.HostAnalyze) (HostAnalyzer, b
6363
return &AnalyzeHostJsonCompare{analyzer.JsonCompare}, true
6464
case analyzer.NetworkNamespaceConnectivity != nil:
6565
return &AnalyzeHostNetworkNamespaceConnectivity{analyzer.NetworkNamespaceConnectivity}, true
66+
case analyzer.Sysctl != nil:
67+
return &AnalyzeHostSysctl{analyzer.Sysctl}, true
6668
default:
6769
return nil, false
6870
}

pkg/analyze/host_sysctl.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package analyzer
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/pkg/errors"
9+
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
10+
"github.com/replicatedhq/troubleshoot/pkg/collect"
11+
)
12+
13+
// Ensure `AnalyzeHostSysctl` implements `HostAnalyzer` interface at compile time.
14+
var _ HostAnalyzer = (*AnalyzeHostSysctl)(nil)
15+
16+
type AnalyzeHostSysctl struct {
17+
hostAnalyzer *troubleshootv1beta2.HostSysctlAnalyze
18+
}
19+
20+
func (a *AnalyzeHostSysctl) Title() string {
21+
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Sysctl")
22+
}
23+
24+
func (a *AnalyzeHostSysctl) IsExcluded() (bool, error) {
25+
return isExcluded(a.hostAnalyzer.Exclude)
26+
}
27+
28+
func (a *AnalyzeHostSysctl) Analyze(
29+
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
30+
) ([]*AnalyzeResult, error) {
31+
result := AnalyzeResult{Title: a.Title()}
32+
33+
// Use the generic function to collect both local and remote data
34+
collectedContents, err := retrieveCollectedContents(
35+
getCollectedFileContents,
36+
collect.HostSysctlPath, // Local path
37+
collect.NodeInfoBaseDir, // Remote base directory
38+
collect.HostSysctlFileName, // Remote file name
39+
)
40+
if err != nil {
41+
return []*AnalyzeResult{&result}, err
42+
}
43+
44+
results, err := analyzeHostCollectorResults(collectedContents, a.hostAnalyzer.Outcomes, a.CheckCondition, a.Title())
45+
if err != nil {
46+
return nil, errors.Wrap(err, "failed to analyze sysctl output")
47+
}
48+
49+
return results, nil
50+
}
51+
52+
// checkCondition checks the condition of the when clause
53+
func (a *AnalyzeHostSysctl) CheckCondition(when string, data []byte) (bool, error) {
54+
55+
sysctl := map[string]string{}
56+
if err := json.Unmarshal(data, &sysctl); err != nil {
57+
return false, errors.Wrap(err, "failed to unmarshal data")
58+
}
59+
60+
// <1:key> <2:operator> <3:value>
61+
matches := sysctlWhenRX.FindStringSubmatch(when)
62+
if len(matches) < 4 {
63+
return false, fmt.Errorf("expected 3 parts in when %q", when)
64+
}
65+
66+
param := matches[1]
67+
expected := matches[3]
68+
opString := matches[2]
69+
operator, err := ParseComparisonOperator(opString)
70+
if err != nil {
71+
return false, errors.Wrap(err, fmt.Sprintf("failed to parse comparison operator %q", opString))
72+
}
73+
74+
if _, ok := sysctl[param]; !ok {
75+
return false, fmt.Errorf("kernel parameter %q does not exist on collected sysctl output", param)
76+
}
77+
78+
switch operator {
79+
case Equal:
80+
return expected == sysctl[param], nil
81+
}
82+
83+
// operator used is an inequality operator, the only valid inputs should be ints, if not we'll error out
84+
value, err := strconv.Atoi(sysctl[param])
85+
if err != nil {
86+
return false, fmt.Errorf("collected sysctl param %q has value %q, cannot be used with provided operator %q", param, sysctl[param], opString)
87+
}
88+
expectedInt, err := strconv.Atoi(expected)
89+
if err != nil {
90+
return false, fmt.Errorf("expected value for sysctl param %q has value %q, cannot be used with provided operator %q", param, expected, opString)
91+
}
92+
93+
switch operator {
94+
case LessThan:
95+
return value < expectedInt, nil
96+
case LessThanOrEqual:
97+
return value <= expectedInt, nil
98+
case GreaterThan:
99+
return value > expectedInt, nil
100+
case GreaterThanOrEqual:
101+
return value >= expectedInt, nil
102+
default:
103+
return false, fmt.Errorf("unsupported operator %q", opString)
104+
}
105+
106+
}

0 commit comments

Comments
 (0)