package analyzer import ( "testing" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" "github.com/stretchr/testify/assert" ) func TestParseSysctlParameters(t *testing.T) { parameters := ` /proc/sys/net/ipv4/ip_forward = 1 /proc/sys/net/ipv4/ip_local_port_range = 32768 60999 /proc/sys/net/bridge/bridge-nf-call-iptables = 0 /proc/sys/vm/max_map_count = 65530 ` got := parseSysctlParameters([]byte(parameters)) expect := map[string]string{ "net.ipv4.ip_forward": "1", "net.ipv4.ip_local_port_range": "32768 60999", "net.bridge.bridge-nf-call-iptables": "0", "vm.max_map_count": "65530", } assert.Equal(t, expect, got) } func TestEvalSysctlWhen(t *testing.T) { tests := []struct { name string when string nodeParams map[string]map[string]string expect []string expectErr bool }{ { name: "One node with IP forwarding disabled", when: "net.ipv4.ip_forward = 0", nodeParams: map[string]map[string]string{ "node-a": {"net.ipv4.ip_forward": "0"}, }, expect: []string{"node-a"}, expectErr: false, }, { name: "All nodes have IP forwarding disabled", when: "net.ipv4.ip_forward = 0", nodeParams: map[string]map[string]string{ "node-a": {"net.ipv4.ip_forward": "0"}, "node-b": {"net.ipv4.ip_forward": "0"}, }, expect: []string{"node-a", "node-b"}, expectErr: false, }, { name: "No nodes have net.ipv4.ip_forward", when: "net.ipv4.ip_forward = 0", nodeParams: map[string]map[string]string{ "node-a": {}, }, expect: []string{}, expectErr: false, }, { name: "One node has IP forwarding enabled, one disabled", when: "net.ipv4.ip_forward = 0", nodeParams: map[string]map[string]string{ "node-a": {"net.ipv4.ip_forward": "1"}, "node-b": {"net.ipv4.ip_forward": "0"}, }, expect: []string{"node-b"}, expectErr: false, }, { name: "No nodes have max map count > 65530", when: "vm.max_map_count > 65530", nodeParams: map[string]map[string]string{ "node-a": {"vm.max_map_count": "65530"}, "node-b": {"vm.max_map_count": "65530"}, }, expect: []string{}, expectErr: false, }, { name: "One node has max map count > 65530", when: "vm.max_map_count > 65530", nodeParams: map[string]map[string]string{ "node-a": {"vm.max_map_count": "65530"}, "node-b": {"vm.max_map_count": "262144"}, }, expect: []string{"node-b"}, expectErr: false, }, { name: "All nodes have max map count > 65530", when: "vm.max_map_count > 65530", nodeParams: map[string]map[string]string{ "node-a": {"vm.max_map_count": "262144"}, "node-b": {"vm.max_map_count": "262144"}, }, expect: []string{"node-a", "node-b"}, expectErr: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { got, err := evalSysctlWhen(test.nodeParams, test.when) if test.expectErr { assert.Error(t, err) return } assert.NoError(t, err) assert.ElementsMatch(t, test.expect, got) }) } } func TestAnalyzeSysctl(t *testing.T) { var tests = []struct { name string files map[string][]byte analyzer *troubleshootv1beta2.SysctlAnalyze expect *AnalyzeResult }{ { name: "Fail IP forwarding disabled on one node", files: map[string][]byte{ "a": []byte(` /proc/sys/net/ipv4/ip_forward = 1 `), "b": []byte(` /proc/sys/net/ipv4/ip_forward = 0 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0 ", Message: "IP forwarding disabled", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ Message: "IP forwarding enabled", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsFail: true, Message: "Node b: IP forwarding disabled", }, }, { name: "Fail IP forwarding disabled on all nodes", files: map[string][]byte{ "a": []byte(` /proc/sys/net/ipv4/ip_forward = 0 `), "b": []byte(` /proc/sys/net/ipv4/ip_forward = 0 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0", Message: "IP forwarding disabled", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ Message: "IP forwarding enabled", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsFail: true, Message: "Nodes a, b: IP forwarding disabled", }, }, { name: "Pass IP forwarding disabled on all nodes", files: map[string][]byte{ "a": []byte(` /proc/sys/net/ipv4/ip_forward = 1 `), "b": []byte(` /proc/sys/net/ipv4/ip_forward = 1 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0", Message: "IP forwarding disabled", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 1", Message: "IP forwarding enabled", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsPass: true, Message: "Nodes a, b: IP forwarding enabled", }, }, { name: "Pass IP forwarding enabled on one node", files: map[string][]byte{ "a": []byte{}, "b": []byte(` /proc/sys/net/ipv4/ip_forward = 1 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0", Message: "IP forwarding disabled", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 1", Message: "IP forwarding enabled", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsPass: true, Message: "Node b: IP forwarding enabled", }, }, { name: "Default warn with empty when", files: map[string][]byte{ "a": []byte{}, "b": []byte{}, }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0", Message: "IP forwarding disabled", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 1", Message: "IP forwarding enabled", }, }, { Warn: &troubleshootv1beta2.SingleOutcome{ When: "", Message: "IP forwarding kernel parameters not found", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsWarn: true, Message: "IP forwarding kernel parameters not found", }, }, { name: "No result", files: map[string][]byte{ "a": []byte(` /proc/sys/net/ipv4/ip_forward = 1 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "net.ipv4.ip_forward = 0", Message: "IP forwarding disabled", }, }, }, }, expect: nil, }, { name: "Fail one node too low on max map count", files: map[string][]byte{ "a": []byte(` /proc/sys/vm/max_map_count = 65530 `), "b": []byte(` /proc/sys/vm/max_map_count = 262144 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "vm.max_map_count < 262144 ", Message: "Max map count too low", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ Message: "Max map count sufficient", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsFail: true, Message: "Node a: Max map count too low", }, }, { name: "Fail two nodes too low on max map count", files: map[string][]byte{ "a": []byte(` /proc/sys/vm/max_map_count = 65530 `), "b": []byte(` /proc/sys/vm/max_map_count = 65530 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "vm.max_map_count < 262144 ", Message: "Max map count too low", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ Message: "Max map count sufficient", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsFail: true, Message: "Nodes a, b: Max map count too low", }, }, { name: "Pass sufficient max map count on both nodes", files: map[string][]byte{ "a": []byte(` /proc/sys/vm/max_map_count = 262144 `), "b": []byte(` /proc/sys/vm/max_map_count = 262144 `), }, analyzer: &troubleshootv1beta2.SysctlAnalyze{ Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "vm.max_map_count < 262144 ", Message: "Max map count too low", }, }, { Pass: &troubleshootv1beta2.SingleOutcome{ When: "vm.max_map_count >= 262144 ", Message: "Max map count sufficient", }, }, }, }, expect: &AnalyzeResult{ Title: "Sysctl", IsPass: true, Message: "Nodes a, b: Max map count sufficient", }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { var findFiles = func(glob string, _ []string) (map[string][]byte, error) { return test.files, nil } a := AnalyzeSysctl{ analyzer: test.analyzer, } got, err := a.analyzeSysctl(test.analyzer, findFiles) assert.NoError(t, err) assert.Equal(t, test.expect, got) }) } }