package logcfg import ( "encoding/json" "fmt" "strings" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "edge-infra.dev/pkg/edge/api/graph/model" ) // Final Struct to hold the ConfigMaP Data type LogLevelData struct { LogLevels string } // This is what the final Config-Map should like the multi-line // value is a single string it is done in this format since lua // would consider each key value pair to be its own file under // the /log-levels dir and the lua-severity filter prefers // a single file with multiple lines for easier parsing due // the use of REGEX. // Data: // log-levels: | // cluster:warn // namespace: namespace1: Warn // namespace: namespace2: ALERT // ... // BuildLogLevelConfigMap creates an log-level configmap func BuildLogLevelConfigMap(clusterLevel string, namespaceLogLevels []*model.NamespaceLogLevel) (*v1.ConfigMap, error) { levels, err := CreateMultilineString(clusterLevel, namespaceLogLevels) if err != nil { return nil, err } i := &LogLevelData{ LogLevels: levels, } return i.ToConfigMap(), nil } // ToConfigMap create log-levels ConfigMap func (i LogLevelData) ToConfigMap() *v1.ConfigMap { return &v1.ConfigMap{ TypeMeta: metav1.TypeMeta{ Kind: "ConfigMap", APIVersion: v1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ Name: LogLevelConfigMapName, Namespace: LogLevelConfigMapNS, }, Data: map[string]string{ LogLevelDataFieldName: i.LogLevels, }, } } // ValidateConfigMap validates log-level ConfigMap func ValidateConfigMap(cfg *v1.ConfigMap) error { var missing []string if cfg.Data[LogLevelDataFieldName] == "" { missing = append(missing, LogLevelDataFieldName) } if len(missing) > 0 { return fmt.Errorf("log-level configmap invalid, value(s) not provided: %s", strings.Join(missing, ",")) } return nil } // New creates a valid log-level ref func New(cfg *v1.ConfigMap) (*LogLevelData, error) { if err := ValidateConfigMap(cfg); err != nil { return nil, err } return FromConfigMap(cfg), nil } // FromConfigMap util function to create log-level from config map func FromConfigMap(cfg *v1.ConfigMap) *LogLevelData { return (&LogLevelData{}).FromConfigMap(cfg) } // FromConfigMap retrieves data from ConfigMap to log-levels func (i *LogLevelData) FromConfigMap(cfg *v1.ConfigMap) *LogLevelData { i.LogLevels = cfg.Data[LogLevelDataFieldName] return i } // IsLogLevelConfigMap util function to check if object is log level config map func IsLogLevelConfigMap(name, namespace string) bool { hasRequiredName := name == LogLevelConfigMapName inRequiredNamespace := namespace == LogLevelConfigMapNS return hasRequiredName && inRequiredNamespace } // ConfigMapToString converts the provided configmap to a string. func ConfigMapToString(configMap *v1.ConfigMap) ([]byte, error) { return json.Marshal(configMap) } // convert JSON to a single multiline string for the Configmap func CreateMultilineString(clusterLevel string, namespaceLogLevels []*model.NamespaceLogLevel) (string, error) { returnVal := fmt.Sprintf("cluster: %s\n", clusterLevel) if len(namespaceLogLevels) == 0 || namespaceLogLevels == nil { return returnVal, nil } for _, entry := range namespaceLogLevels { returnVal = fmt.Sprintf("%snamespace:%s: %s\n", returnVal, entry.Namespace, entry.Level) } return returnVal, nil }