Skip to content

Commit 77c9968

Browse files
JGAntunesbanjoh
andauthored
feat(host_sysctl): add host sysctl collector (#1676)
* feat(host_sysctl): add host sysctl collector * chore: add examples * Update pkg/collect/host_sysctl.go Co-authored-by: Evans Mungai <[email protected]> * chore: use sysctl package vs exec calls * chore: make linter happy * chore: make schemas * chore: go back to sysctl exec * chore: make linter happy --------- Co-authored-by: Evans Mungai <[email protected]>
1 parent 06506ed commit 77c9968

13 files changed

+357
-0
lines changed

config/crds/troubleshoot.sh_collectors.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17393,6 +17393,13 @@ spec:
1739317393
- CIDRRangeAlloc
1739417394
- desiredCIDR
1739517395
type: object
17396+
sysctl:
17397+
properties:
17398+
collectorName:
17399+
type: string
17400+
exclude:
17401+
type: BoolString
17402+
type: object
1739617403
systemPackages:
1739717404
properties:
1739817405
amzn:

config/crds/troubleshoot.sh_hostcollectors.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,13 @@ spec:
17191719
- CIDRRangeAlloc
17201720
- desiredCIDR
17211721
type: object
1722+
sysctl:
1723+
properties:
1724+
collectorName:
1725+
type: string
1726+
exclude:
1727+
type: BoolString
1728+
type: object
17221729
systemPackages:
17231730
properties:
17241731
amzn:

config/crds/troubleshoot.sh_hostpreflights.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,6 +1719,13 @@ spec:
17191719
- CIDRRangeAlloc
17201720
- desiredCIDR
17211721
type: object
1722+
sysctl:
1723+
properties:
1724+
collectorName:
1725+
type: string
1726+
exclude:
1727+
type: BoolString
1728+
type: object
17221729
systemPackages:
17231730
properties:
17241731
amzn:

config/crds/troubleshoot.sh_supportbundles.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20366,6 +20366,13 @@ spec:
2036620366
- CIDRRangeAlloc
2036720367
- desiredCIDR
2036820368
type: object
20369+
sysctl:
20370+
properties:
20371+
collectorName:
20372+
type: string
20373+
exclude:
20374+
type: BoolString
20375+
type: object
2036920376
systemPackages:
2037020377
properties:
2037120378
amzn:

examples/collect/host/sysctl.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: troubleshoot.sh/v1beta2
2+
kind: HostCollector
3+
metadata:
4+
name: sysctl
5+
spec:
6+
collectors:
7+
- sysctl:
8+
collectorName: sysctl

examples/preflight/host/sysctl.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: troubleshoot.sh/v1beta2
2+
kind: HostPreflight
3+
metadata:
4+
name: sysctl
5+
spec:
6+
collectors:
7+
- sysctl:
8+
collectorName: sysctl
9+
#TODO add analyzer once implemented
10+
analyzers: []

pkg/apis/troubleshoot/v1beta2/hostcollector_shared.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ type HostDNS struct {
231231
Hostnames []string `json:"hostnames" yaml:"hostnames"`
232232
}
233233

234+
type HostSysctl struct {
235+
HostCollectorMeta `json:",inline" yaml:",inline"`
236+
}
237+
234238
type HostCollect struct {
235239
CPU *CPU `json:"cpu,omitempty" yaml:"cpu,omitempty"`
236240
Memory *Memory `json:"memory,omitempty" yaml:"memory,omitempty"`
@@ -260,6 +264,7 @@ type HostCollect struct {
260264
HostCGroups *HostCGroups `json:"cgroups,omitempty" yaml:"cgroups,omitempty"`
261265
HostDNS *HostDNS `json:"dns,omitempty" yaml:"dns,omitempty"`
262266
NetworkNamespaceConnectivity *HostNetworkNamespaceConnectivity `json:"networkNamespaceConnectivity,omitempty" yaml:"networkNamespaceConnectivity,omitempty"`
267+
HostSysctl *HostSysctl `json:"sysctl,omitempty" yaml:"sysctl,omitempty"`
263268
}
264269

265270
// GetName gets the name of the collector

pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/collect/host_collector.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ func GetHostCollector(collector *troubleshootv1beta2.HostCollect, bundlePath str
101101
return &CollectHostDNS{collector.HostDNS, bundlePath}, true
102102
case collector.NetworkNamespaceConnectivity != nil:
103103
return &CollectHostNetworkNamespaceConnectivity{collector.NetworkNamespaceConnectivity, bundlePath}, true
104+
case collector.HostSysctl != nil:
105+
return &CollectHostSysctl{collector.HostSysctl, bundlePath}, true
104106
default:
105107
return nil, false
106108
}

pkg/collect/host_sysctl.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package collect
2+
3+
import (
4+
"bufio"
5+
"bytes"
6+
"encoding/json"
7+
"os/exec"
8+
"regexp"
9+
10+
"github.com/pkg/errors"
11+
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
12+
"k8s.io/klog/v2"
13+
)
14+
15+
// Ensure `CollectHostSysctl` implements `HostCollector` interface at compile time.
16+
var _ HostCollector = (*CollectHostSysctl)(nil)
17+
18+
// Helper var to allow stubbing `exec.Command` for tests
19+
var execCommand = exec.Command
20+
21+
const HostSysctlPath = `host-collectors/system/sysctl.json`
22+
23+
type CollectHostSysctl struct {
24+
hostCollector *troubleshootv1beta2.HostSysctl
25+
BundlePath string
26+
}
27+
28+
func (c *CollectHostSysctl) Title() string {
29+
return hostCollectorTitleOrDefault(c.hostCollector.HostCollectorMeta, "Sysctl")
30+
}
31+
32+
func (c *CollectHostSysctl) IsExcluded() (bool, error) {
33+
return isExcluded(c.hostCollector.Exclude)
34+
}
35+
36+
func (c *CollectHostSysctl) Collect(progressChan chan<- interface{}) (map[string][]byte, error) {
37+
klog.V(2).Info("Running sysctl collector")
38+
cmd := execCommand("sysctl", "-a")
39+
out, err := cmd.Output()
40+
if err != nil {
41+
klog.V(2).ErrorS(err, "failed to run sysctl")
42+
if exitErr, ok := err.(*exec.ExitError); ok {
43+
return nil, errors.Wrapf(err, "failed to run sysctl exit-code=%d stderr=%s", exitErr.ExitCode(), exitErr.Stderr)
44+
} else {
45+
return nil, errors.Wrap(err, "failed to run sysctl")
46+
}
47+
}
48+
values := parseSysctlParameters(out)
49+
50+
payload, err := json.Marshal(values)
51+
if err != nil {
52+
klog.V(2).ErrorS(err, "failed to marshal data to json")
53+
return nil, errors.Wrap(err, "failed to marshal data to json")
54+
}
55+
56+
output := NewResult()
57+
output.SaveResult(c.BundlePath, HostSysctlPath, bytes.NewBuffer(payload))
58+
klog.V(2).Info("Finished writing JSON output")
59+
return output, nil
60+
}
61+
62+
// Linux sysctl outputs <key> = <value> where in Darwin you get <key> : <value>
63+
// where <value> can be a string, number or multiple space separated strings
64+
var sysctlLineRegex = regexp.MustCompile(`(\S+)\s*(=|:)\s*(.*)$`)
65+
66+
func parseSysctlParameters(output []byte) map[string]string {
67+
scanner := bufio.NewScanner(bytes.NewReader(output))
68+
69+
result := map[string]string{}
70+
for scanner.Scan() {
71+
l := scanner.Text()
72+
// <1:key> <2:separator> <3:value>
73+
matches := sysctlLineRegex.FindStringSubmatch(l)
74+
75+
switch len(matches) {
76+
// there are no matches for the value and separator, ignore and log
77+
case 0, 1, 2:
78+
klog.V(2).Infof("skipping sysctl line since we found no matches for it: %s", l)
79+
// key exists but value could be empty, register as an empty string value but log something for reference
80+
case 3:
81+
klog.V(2).Infof("found no value for sysctl line, keeping it with an empty value: %s", l)
82+
result[matches[1]] = ""
83+
default:
84+
result[matches[1]] = matches[3]
85+
}
86+
}
87+
return result
88+
}

0 commit comments

Comments
 (0)