package logcfg import ( "testing" "github.com/stretchr/testify/assert" assertapi "github.com/stretchr/testify/assert" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "edge-infra.dev/pkg/edge/api/graph/mapper" ) const ( clusterTestString = "cluster: WARN" fluentTestString = "namespace:fluent-operator: alert" kubeTestString = "namespace:kube-system: ALERT" prometheusTestString = "namespace:prometheus: EMERGENCY" clusterTestStringNoLevel = "cluster: " prometheusTestStringNoLevel = "namespace:prometheus: " fluentTestStringNoLevel = "namespace:fluent-operator: " kubeTestStringNoLevel = "namespace:kube-system: " ) func TestFromLogLeveLsConfigMap(t *testing.T) { assert := assertapi.New(t) cfg := getLogLevelConfigMap() logLevel := FromConfigMap(cfg) assert.Contains(logLevel.LogLevels, clusterTestString) assert.Contains(logLevel.LogLevels, fluentTestString) assert.Contains(logLevel.LogLevels, prometheusTestString) assert.Contains(logLevel.LogLevels, kubeTestString) } func TestToLogLeveLsConfigMap(t *testing.T) { assert := assertapi.New(t) // expected := getLogLevelConfigMap() logLevel := getLogLevel() cfg := logLevel.ToConfigMap() assert.Contains(cfg.Data[LogLevelDataFieldName], clusterTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], fluentTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], prometheusTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], kubeTestString) } func TestBuildLogLevelConfigMap(t *testing.T) { assert := assertapi.New(t) jsonBlob := `[{"namespace":"fluent-operator","level":"alert"},{"namespace":"kube-system","level":"ALERT"},{"namespace":"prometheus","level":"EMERGENCY"}]` namespaceLogLevels, err := mapper.JSONtoNLL(jsonBlob) assert.NoError(err) cfg, err := BuildLogLevelConfigMap("WARN", namespaceLogLevels) assert.NoError(err) assert.NotNil(cfg) assert.NoError(ValidateConfigMap(cfg)) assert.Contains(cfg.Data[LogLevelDataFieldName], clusterTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], fluentTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], prometheusTestString) assert.Contains(cfg.Data[LogLevelDataFieldName], kubeTestString) } func TestNewValidLogLevelConfigMap(t *testing.T) { assert := assertapi.New(t) cfg := getLogLevelConfigMap() logLevel, err := New(cfg) assert.NoError(err) assert.Contains(logLevel.LogLevels, clusterTestString) assert.Contains(logLevel.LogLevels, fluentTestString) assert.Contains(logLevel.LogLevels, prometheusTestString) assert.Contains(logLevel.LogLevels, kubeTestString) } func TestNewInvalidLogLeveLsConfigMap(t *testing.T) { assert := assertapi.New(t) cfg := getLogLevelConfigMap() delete(cfg.Data, LogLevelDataFieldName) logLevel, err := New(cfg) assert.Error(err) assert.Nil(logLevel) } func TestIsLogLevelConfigMap(t *testing.T) { assert := assertapi.New(t) expected := getLogLevelConfigMap() IsLogLevelConfigMap := IsLogLevelConfigMap(expected.ObjectMeta.Name, expected.ObjectMeta.Namespace) assert.True(IsLogLevelConfigMap) } func TestFieldsRequired(t *testing.T) { assert := assertapi.New(t) cfg := &corev1.ConfigMap{} err := ValidateConfigMap(cfg) assert.Error(err) allFields := "log-level configmap invalid, value(s) not provided: " + "log-levels" assert.Equal(err.Error(), allFields) } func TestCreateMultilineString(t *testing.T) { // these test cases should have levels correctTests := map[string]struct { description string cluster string namespaceJSON string expected string }{ "no-namespace": { description: "Should only have cluster", cluster: "WARN", namespaceJSON: "[]", expected: clusterTestString + "\n", }, "single-namespace": { description: "Should only have one cluster and namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"prometheus","level":"EMERGENCY"}]`, expected: clusterTestString + "\n" + prometheusTestString + "\n", }, "multi-namespace": { description: "Should only have one cluster and 3 namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"fluent-operator","level":"alert"},{"namespace":"kube-system","level":"ALERT"},{"namespace":"prometheus","level":"EMERGENCY"}]`, expected: clusterTestString + "\n" + fluentTestString + "\n" + kubeTestString + "\n" + prometheusTestString + "\n", }, } for testName, test := range correctTests { namespaceLogLevels, err := mapper.JSONtoNLL(test.namespaceJSON) assert.NoError(t, err) returnVal, err := CreateMultilineString(test.cluster, namespaceLogLevels) assert.NoError(t, err) if returnVal != test.expected { t.Errorf("%s test was \n%s,\n but was expected to be \n%s", testName, returnVal, test.expected) } } noLevelTest := map[string]struct { description string cluster string namespaceJSON string expected string }{ "no-namespace-noLevel": { description: "Should only have cluster with no level", cluster: "", namespaceJSON: "[]", expected: clusterTestStringNoLevel + "\n", }, "only-namespace-noLevel": { description: "Should only have one namespace with no level", namespaceJSON: `[{"namespace":"prometheus","level":""}]`, expected: clusterTestStringNoLevel + "\n" + prometheusTestStringNoLevel + "\n", }, "single-namespace-noLevel": { description: "Should have no levels for cluster and one namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"prometheus","level":""}]`, expected: clusterTestString + "\n" + prometheusTestStringNoLevel + "\n", }, "multi-namespace-noLevel": { description: "Should have no levels for cluster and 3 namespace", namespaceJSON: `[{"namespace":"fluent-operator","level":""},{"namespace":"kube-system","level":""},{"namespace":"prometheus","level":""}]`, expected: clusterTestStringNoLevel + "\n" + fluentTestStringNoLevel + "\n" + kubeTestStringNoLevel + "\n" + prometheusTestStringNoLevel + "\n", }, "multi-namespace-1-NoLevel": { description: "Should have levels for cluster and 2 namespace, but not 1 namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"fluent-operator","level":"alert"},{"namespace":"kube-system","level":"ALERT"},{"namespace":"prometheus","level":""}]`, expected: clusterTestString + "\n" + fluentTestString + "\n" + kubeTestString + "\n" + prometheusTestStringNoLevel + "\n", }, "multi-namespace-2-NoLevel": { description: "Should have levels for cluster and 2 namespace, but not 1 namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"fluent-operator","level":"alert"},{"namespace":"kube-system","level":""},{"namespace":"prometheus","level":""}]`, expected: clusterTestString + "\n" + fluentTestString + "\n" + kubeTestStringNoLevel + "\n" + prometheusTestStringNoLevel + "\n", }, "multi-namespace-3-noLevel": { description: "Should have cluster and no levels for 3 namespace", cluster: "WARN", namespaceJSON: `[{"namespace":"fluent-operator","level":""},{"namespace":"kube-system","level":""},{"namespace":"prometheus","level":""}]`, expected: clusterTestString + "\n" + fluentTestStringNoLevel + "\n" + kubeTestStringNoLevel + "\n" + prometheusTestStringNoLevel + "\n", }, } for testName, test := range noLevelTest { namespaceLogLevels, err := mapper.JSONtoNLL(test.namespaceJSON) assert.NoError(t, err) returnVal, err := CreateMultilineString(test.cluster, namespaceLogLevels) assert.NoError(t, err) if returnVal != test.expected { t.Errorf("%s test was \n%s,\n but was expected to be \n%s", testName, returnVal, test.expected) } } } // TEST HELPER FUNCTIONS TO MOCK FAKE DATA func getLogLevel() *LogLevelData { jsonBlob := `[{"namespace":"fluent-operator","level":"alert"},{"namespace":"kube-system","level":"ALERT"},{"namespace":"prometheus","level":"EMERGENCY"}]` namespaceLogLevels, _ := mapper.JSONtoNLL(jsonBlob) levels, _ := CreateMultilineString("WARN", namespaceLogLevels) // defer the closing of our jsonFile so that we can parse it later on return &LogLevelData{ LogLevels: levels, } } func getLogLevelConfigMap() *corev1.ConfigMap { // ll is shorthand LogLevel ll := getLogLevel() return &corev1.ConfigMap{ TypeMeta: v1.TypeMeta{ Kind: "ConfigMap", APIVersion: v1.SchemeGroupVersion.String(), }, ObjectMeta: v1.ObjectMeta{ Name: LogLevelConfigMapName, Namespace: LogLevelConfigMapNS, }, Data: map[string]string{ LogLevelDataFieldName: ll.LogLevels, }, } }