From b50f92cc16754bee05a7de7fd4674f5a5e114bea Mon Sep 17 00:00:00 2001 From: Aldo Lacuku Date: Wed, 24 Jan 2024 10:46:54 +0100 Subject: [PATCH] fixup! update(falco/driver)!: use the same names for drivers as falco --- charts/falco/tests/unit/consts.go | 22 ++ charts/falco/tests/unit/doc.go | 17 ++ charts/falco/tests/unit/driverConfig_test.go | 286 ++++++++++++++++++ .../unit/k8smetacollectorDependency_test.go | 43 +-- 4 files changed, 348 insertions(+), 20 deletions(-) create mode 100644 charts/falco/tests/unit/consts.go create mode 100644 charts/falco/tests/unit/doc.go create mode 100644 charts/falco/tests/unit/driverConfig_test.go diff --git a/charts/falco/tests/unit/consts.go b/charts/falco/tests/unit/consts.go new file mode 100644 index 000000000..54c4db5d5 --- /dev/null +++ b/charts/falco/tests/unit/consts.go @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +const ( + releaseName = "rendered-resources" + patternK8sMetacollectorFiles = `# Source: falco/charts/k8s-metacollector/templates/([^\n]+)` + k8sMetaPluginName = "k8smeta" +) diff --git a/charts/falco/tests/unit/doc.go b/charts/falco/tests/unit/doc.go new file mode 100644 index 000000000..244855831 --- /dev/null +++ b/charts/falco/tests/unit/doc.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package unit contains the unit tests for the Falco chart. +package unit diff --git a/charts/falco/tests/unit/driverConfig_test.go b/charts/falco/tests/unit/driverConfig_test.go new file mode 100644 index 000000000..25a5905dc --- /dev/null +++ b/charts/falco/tests/unit/driverConfig_test.go @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "fmt" + "path/filepath" + "testing" + + "github.com/gruntwork-io/terratest/modules/helm" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" +) + +func TestDriverConfigInFalcoConfig(t *testing.T) { + t.Parallel() + + helmChartPath, err := filepath.Abs(chartPath) + require.NoError(t, err) + + testCases := []struct { + name string + values map[string]string + expected func(t *testing.T, config any) + }{ + { + "defaultValues", + nil, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, dropFailedExit, err := getKmodConfig(config) + require.NoError(t, err) + require.Equal(t, "kmod", kind) + require.Equal(t, float64(4), bufSizePreset) + require.False(t, dropFailedExit) + }, + }, + { + "kind=kmod", + map[string]string{ + "driver.kind": "kmod", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, dropFailedExit, err := getKmodConfig(config) + require.NoError(t, err) + require.Equal(t, "kmod", kind) + require.Equal(t, float64(4), bufSizePreset) + require.False(t, dropFailedExit) + }, + }, + { + "kind=module(alias)", + map[string]string{ + "driver.kind": "module", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, dropFailedExit, err := getKmodConfig(config) + require.NoError(t, err) + require.Equal(t, "kmod", kind) + require.Equal(t, float64(4), bufSizePreset) + require.False(t, dropFailedExit) + }, + }, + { + "kmod=onfig", + map[string]string{ + "driver.kmod.bufSizePreset": "6", + "driver.kmod.dropFailedExit": "true", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, dropFailedExit, err := getKmodConfig(config) + require.NoError(t, err) + require.Equal(t, "kmod", kind) + require.Equal(t, float64(6), bufSizePreset) + require.True(t, dropFailedExit) + }, + }, + { + "kind=ebpf", + map[string]string{ + "driver.kind": "ebpf", + "driver.ebpf.bufSizePreset": "6", + "driver.ebpf.dropFailedExit": "true", + "driver.ebpf.path": "testing/Path/ebpf", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, path, bufSizePreset, dropFailedExit, err := getEbpfConfig(config) + require.NoError(t, err) + require.Equal(t, "ebpf", kind) + require.Equal(t, "testing/Path/ebpf", path) + require.Equal(t, float64(6), bufSizePreset) + require.True(t, dropFailedExit) + }, + }, + { + "ebpf=config", + map[string]string{ + "driver.kind": "ebpf", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, path, bufSizePreset, dropFailedExit, err := getEbpfConfig(config) + require.NoError(t, err) + require.Equal(t, "ebpf", kind) + require.Equal(t, "${HOME}/.falco/falco-bpf.o", path) + require.Equal(t, float64(4), bufSizePreset) + require.False(t, dropFailedExit) + }, + }, + { + "kind=modern_ebpf", + map[string]string{ + "driver.kind": "modern_ebpf", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, cpusForEachBuffer, dropFailedExit, err := getModernEbpfConfig(config) + require.NoError(t, err) + require.Equal(t, "modern_ebpf", kind) + require.Equal(t, float64(4), bufSizePreset) + require.Equal(t, float64(2), cpusForEachBuffer) + require.False(t, dropFailedExit) + }, + }, + { + "kind=modern-bpf(alias)", + map[string]string{ + "driver.kind": "modern-bpf", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, cpusForEachBuffer, dropFailedExit, err := getModernEbpfConfig(config) + require.NoError(t, err) + require.Equal(t, "modern_ebpf", kind) + require.Equal(t, float64(4), bufSizePreset) + require.Equal(t, float64(2), cpusForEachBuffer) + require.False(t, dropFailedExit) + }, + }, + { + "modernEbpf=config", + map[string]string{ + "driver.kind": "modern-bpf", + "driver.modernEbpf.bufSizePreset": "6", + "driver.modernEbpf.dropFailedExit": "true", + "driver.modernEbpf.cpusForEachBuffer": "8", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, bufSizePreset, cpusForEachBuffer, dropFailedExit, err := getModernEbpfConfig(config) + require.NoError(t, err) + require.Equal(t, "modern_ebpf", kind) + require.Equal(t, float64(6), bufSizePreset) + require.Equal(t, float64(8), cpusForEachBuffer) + require.True(t, dropFailedExit) + }, + }, + { + "kind=gvisor", + map[string]string{ + "driver.kind": "gvisor", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, config, root, err := getGvisorConfig(config) + require.NoError(t, err) + require.Equal(t, "gvisor", kind) + require.Equal(t, "/gvisor/config/pod-init.json", config) + require.Equal(t, "/host/run/containerd/runsc/k8s.io", root) + }, + }, + { + "gvisor=config", + map[string]string{ + "driver.kind": "gvisor", + "driver.gvisor.runsc.root": "/my/root/test", + }, + func(t *testing.T, config any) { + require.Len(t, config, 2, "should have only two items") + kind, config, root, err := getGvisorConfig(config) + require.NoError(t, err) + require.Equal(t, "gvisor", kind) + require.Equal(t, "/gvisor/config/pod-init.json", config) + require.Equal(t, "/host/my/root/test/k8s.io", root) + }, + }, + } + + for _, testCase := range testCases { + testCase := testCase + + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + options := &helm.Options{SetValues: testCase.values} + output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/configmap.yaml"}) + + var cm corev1.ConfigMap + helm.UnmarshalK8SYaml(t, output, &cm) + var config map[string]interface{} + + helm.UnmarshalK8SYaml(t, cm.Data["falco.yaml"], &config) + engine := config["engine"] + testCase.expected(t, engine) + }) + } +} + +func getKmodConfig(config interface{}) (kind string, bufSizePreset float64, dropFailedExit bool, err error) { + configMap, ok := config.(map[string]interface{}) + if !ok { + err = fmt.Errorf("can't assert type of config") + return + } + + kind = configMap["kind"].(string) + kmod := configMap["kmod"].(map[string]interface{}) + bufSizePreset = kmod["buf_size_preset"].(float64) + dropFailedExit = kmod["drop_failed_exit"].(bool) + + return +} + +func getEbpfConfig(config interface{}) (kind, path string, bufSizePreset float64, dropFailedExit bool, err error) { + configMap, ok := config.(map[string]interface{}) + if !ok { + err = fmt.Errorf("can't assert type of config") + return + } + + kind = configMap["kind"].(string) + ebpf := configMap["ebpf"].(map[string]interface{}) + bufSizePreset = ebpf["buf_size_preset"].(float64) + dropFailedExit = ebpf["drop_failed_exit"].(bool) + path = ebpf["probe"].(string) + + return +} + +func getModernEbpfConfig(config interface{}) (kind string, bufSizePreset, cpusForEachBuffer float64, dropFailedExit bool, err error) { + configMap, ok := config.(map[string]interface{}) + if !ok { + err = fmt.Errorf("can't assert type of config") + return + } + + kind = configMap["kind"].(string) + modernEbpf := configMap["modern_ebpf"].(map[string]interface{}) + bufSizePreset = modernEbpf["buf_size_preset"].(float64) + dropFailedExit = modernEbpf["drop_failed_exit"].(bool) + cpusForEachBuffer = modernEbpf["cpus_for_each_buffer"].(float64) + + return +} + +func getGvisorConfig(cfg interface{}) (kind, config, root string, err error) { + configMap, ok := cfg.(map[string]interface{}) + if !ok { + err = fmt.Errorf("can't assert type of config") + return + } + + kind = configMap["kind"].(string) + gvisor := configMap["gvisor"].(map[string]interface{}) + config = gvisor["config"].(string) + root = gvisor["root"].(string) + + return +} diff --git a/charts/falco/tests/unit/k8smetacollectorDependency_test.go b/charts/falco/tests/unit/k8smetacollectorDependency_test.go index 07e99ab33..4f533aa79 100644 --- a/charts/falco/tests/unit/k8smetacollectorDependency_test.go +++ b/charts/falco/tests/unit/k8smetacollectorDependency_test.go @@ -1,3 +1,18 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 The Falco Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package unit import ( @@ -5,13 +20,13 @@ import ( "fmt" "path/filepath" "regexp" - "slices" "strings" "testing" "github.com/gruntwork-io/terratest/modules/helm" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "slices" ) const chartPath = "../../" @@ -23,16 +38,13 @@ func TestRenderedResourcesWithDefaultValues(t *testing.T) { helmChartPath, err := filepath.Abs(chartPath) require.NoError(t, err) - releaseName := "rendered-resources" - options := &helm.Options{} // Template the chart using the default values.yaml file. output, err := helm.RenderTemplateE(t, options, helmChartPath, releaseName, nil) require.NoError(t, err) // Extract all rendered files from the output. - pattern := `# Source: falco/charts/k8s-metacollector/templates/([^\n]+)` - re := regexp.MustCompile(pattern) + re := regexp.MustCompile(patternK8sMetacollectorFiles) matches := re.FindAllStringSubmatch(output, -1) require.Len(t, matches, 0) @@ -44,8 +56,6 @@ func TestRenderedResourcesWhenNotEnabled(t *testing.T) { helmChartPath, err := filepath.Abs(chartPath) require.NoError(t, err) - releaseName := "rendered-resources" - // Template files that we expect to be rendered. templateFiles := []string{ "clusterrole.yaml", @@ -66,8 +76,7 @@ func TestRenderedResourcesWhenNotEnabled(t *testing.T) { require.NoError(t, err) // Extract all rendered files from the output. - pattern := `# Source: falco/charts/k8s-metacollector/templates/([^\n]+)` - re := regexp.MustCompile(pattern) + re := regexp.MustCompile(patternK8sMetacollectorFiles) matches := re.FindAllStringSubmatch(output, -1) var renderedTemplates []string @@ -92,8 +101,6 @@ func TestPluginConfigurationInFalcoConfig(t *testing.T) { helmChartPath, err := filepath.Abs(chartPath) require.NoError(t, err) - releaseName := "rendered-resources" - testCases := []struct { name string values map[string]string @@ -322,7 +329,7 @@ func TestPluginConfigurationInFalcoConfig(t *testing.T) { found := false // Find the k8smeta plugin configuration. for _, plugin := range pluginsArray { - if name, ok := plugin.(map[string]interface{})["name"]; ok && name == "k8smeta" { + if name, ok := plugin.(map[string]interface{})["name"]; ok && name == k8sMetaPluginName { testCase.expected(t, plugin) found = true } @@ -330,11 +337,11 @@ func TestPluginConfigurationInFalcoConfig(t *testing.T) { if found { // Check that the plugin has been added to the ones that need to be loaded. loadplugins := config["load_plugins"] - require.True(t, slices.Contains(loadplugins.([]interface{}), "k8smeta")) + require.True(t, slices.Contains(loadplugins.([]interface{}), k8sMetaPluginName)) } else { testCase.expected(t, nil) loadplugins := config["load_plugins"] - require.True(t, !slices.Contains(loadplugins.([]interface{}), "k8smeta")) + require.True(t, !slices.Contains(loadplugins.([]interface{}), k8sMetaPluginName)) } }) } @@ -378,8 +385,6 @@ func TestPluginConfigurationUniqueEntries(t *testing.T) { helmChartPath, err := filepath.Abs(chartPath) require.NoError(t, err) - releaseName := "rendered-resources" - options := &helm.Options{SetJsonValues: map[string]string{ "falco.plugins": pluginsJSON, "falco.load_plugins": loadPluginsJSON, @@ -400,7 +405,7 @@ func TestPluginConfigurationUniqueEntries(t *testing.T) { // Find the k8smeta plugin configuration. numConfigK8smeta := 0 for _, plugin := range pluginsArray { - if name, ok := plugin.(map[string]interface{})["name"]; ok && name == "k8smeta" { + if name, ok := plugin.(map[string]interface{})["name"]; ok && name == k8sMetaPluginName { numConfigK8smeta++ } } @@ -410,7 +415,7 @@ func TestPluginConfigurationUniqueEntries(t *testing.T) { // Check that the plugin has been added to the ones that need to be loaded. loadplugins := config["load_plugins"] require.Len(t, loadplugins.([]interface{}), 2) - require.True(t, slices.Contains(loadplugins.([]interface{}), "k8smeta")) + require.True(t, slices.Contains(loadplugins.([]interface{}), k8sMetaPluginName)) } // Test that the helper does not overwrite user's configuration. @@ -496,8 +501,6 @@ func TestFalcoctlRefs(t *testing.T) { helmChartPath, err := filepath.Abs(chartPath) require.NoError(t, err) - releaseName := "rendered-resources" - for _, testCase := range testCases { testCase := testCase