diff --git a/pkg/kopia/command/common.go b/pkg/kopia/command/common.go index 11a5f02cfc..2d9d284554 100644 --- a/pkg/kopia/command/common.go +++ b/pkg/kopia/command/common.go @@ -15,16 +15,48 @@ package command import ( + "os" + "github.com/kanisterio/kanister/pkg/field" "github.com/kanisterio/kanister/pkg/log" "github.com/kanisterio/kanister/pkg/logsafe" ) +const ( + // LogLevelVarName is the environment variable that controls datastore log level. + LogLevelVarName = "DATA_STORE_LOG_LEVEL" + // FileLogLevelVarName is the environment variable that controls datastore file log level. + FileLogLevelVarName = "DATA_STORE_FILE_LOG_LEVEL" +) + +func NonEmptyOrDefault[T comparable](t T, def T) T { + var empty T + if t != empty { + return t + } + return def +} + +func GetEnvOrDefault(name, def string) string { + return NonEmptyOrDefault(os.Getenv(name), def) +} + +// LogLevel will return either value from env or "error" as default value +func LogLevel() string { + return GetEnvOrDefault(LogLevelVarName, LogLevelError) +} + +// FileLogLevel will return value from env +func FileLogLevel() string { + return os.Getenv(FileLogLevelVarName) +} + type CommandArgs struct { RepoPassword string ConfigFilePath string LogDirectory string LogLevel string + FileLogLevel string } func bashCommand(args logsafe.Cmd) []string { @@ -40,10 +72,12 @@ func stringSliceCommand(args logsafe.Cmd) []string { func commonArgs(cmdArgs *CommandArgs) logsafe.Cmd { c := logsafe.NewLoggable(kopiaCommand) - if cmdArgs.LogLevel != "" { - c = c.AppendLoggableKV(logLevelFlag, cmdArgs.LogLevel) - } else { - c = c.AppendLoggableKV(logLevelFlag, LogLevelError) + logLevel := NonEmptyOrDefault(cmdArgs.LogLevel, LogLevel()) + c = c.AppendLoggableKV(logLevelFlag, logLevel) + + fileLogLevel := NonEmptyOrDefault(cmdArgs.FileLogLevel, FileLogLevel()) + if fileLogLevel != "" { + c = c.AppendLoggableKV(fileLogLevelFlag, fileLogLevel) } if cmdArgs.ConfigFilePath != "" { diff --git a/pkg/kopia/command/common_test.go b/pkg/kopia/command/common_test.go new file mode 100644 index 0000000000..159f319d79 --- /dev/null +++ b/pkg/kopia/command/common_test.go @@ -0,0 +1,134 @@ +// Copyright 2024 The Kanister 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 command + +import ( + "os" + + "gopkg.in/check.v1" +) + +type CommonUtilsSuite struct{} + +var _ = check.Suite(&CommonUtilsSuite{}) + +func (s *CommonUtilsSuite) TestCommonArgs(c *check.C) { + for _, tc := range []struct { + setup func() func() + arg *CommandArgs + expectedCmd []string + comment string + }{ + { + setup: func() func() { return func() {} }, + comment: "Default log settings", + arg: &CommandArgs{ + RepoPassword: "pass123", + ConfigFilePath: "/tmp/config.file", + LogDirectory: "/tmp/log.dir", + }, + expectedCmd: []string{"kopia", + "--log-level=error", + "--config-file=/tmp/config.file", + "--log-dir=/tmp/log.dir", + "--password=pass123", + }, + }, { + setup: func() func() { return func() {} }, + comment: "Custom log level passed via args, default file log level", + arg: &CommandArgs{ + LogLevel: "info", + RepoPassword: "pass123", + ConfigFilePath: "/tmp/config.file", + LogDirectory: "/tmp/log.dir", + }, + expectedCmd: []string{"kopia", + "--log-level=info", + "--config-file=/tmp/config.file", + "--log-dir=/tmp/log.dir", + "--password=pass123", + }, + }, { + setup: func() func() { return func() {} }, + comment: "Custom log level and file log level, both passed via args", + arg: &CommandArgs{ + LogLevel: "info", + FileLogLevel: "info", + RepoPassword: "pass123", + ConfigFilePath: "/tmp/config.file", + LogDirectory: "/tmp/log.dir", + }, + expectedCmd: []string{"kopia", + "--log-level=info", + "--file-log-level=info", + "--config-file=/tmp/config.file", + "--log-dir=/tmp/log.dir", + "--password=pass123", + }, + }, { + setup: func() func() { + origLogLevel := os.Getenv(LogLevelVarName) + os.Setenv(LogLevelVarName, "debug") + return func() { + os.Setenv(LogLevelVarName, origLogLevel) + } + }, + comment: "Custom log level passed via env variable, file log level passed via args", + arg: &CommandArgs{ + FileLogLevel: "info", + RepoPassword: "pass123", + ConfigFilePath: "/tmp/config.file", + LogDirectory: "/tmp/log.dir", + }, + expectedCmd: []string{"kopia", + "--log-level=debug", + "--file-log-level=info", + "--config-file=/tmp/config.file", + "--log-dir=/tmp/log.dir", + "--password=pass123", + }, + }, { + setup: func() func() { + origLogLevel := os.Getenv(LogLevelVarName) + origFileLogLevel := os.Getenv(FileLogLevelVarName) + os.Setenv(LogLevelVarName, "debug") + os.Setenv(FileLogLevelVarName, "debug") + return func() { + os.Setenv(LogLevelVarName, origLogLevel) + os.Setenv(FileLogLevelVarName, origFileLogLevel) + } + }, + comment: "Custom log level and file log level both passed via env variable", + arg: &CommandArgs{ + RepoPassword: "pass123", + ConfigFilePath: "/tmp/config.file", + LogDirectory: "/tmp/log.dir", + }, + expectedCmd: []string{"kopia", + "--log-level=debug", + "--file-log-level=debug", + "--config-file=/tmp/config.file", + "--log-dir=/tmp/log.dir", + "--password=pass123", + }, + }, + } { + c.Log(tc.comment) + cleanup := tc.setup() + defer cleanup() + cmd := stringSliceCommand(commonArgs(tc.arg)) + c.Assert(cmd, check.DeepEquals, tc.expectedCmd) + } +} diff --git a/pkg/kopia/command/const.go b/pkg/kopia/command/const.go index 8cf3eec6b8..d7c0d963a3 100644 --- a/pkg/kopia/command/const.go +++ b/pkg/kopia/command/const.go @@ -41,6 +41,7 @@ const ( jsonFlag = "--json" logDirectoryFlag = "--log-dir" logLevelFlag = "--log-level" + fileLogLevelFlag = "--file-log-level" LogLevelError = "error" LogLevelInfo = "info" parallelFlag = "--parallel"