client: container: support CLI with entrypoint addition (#4126)

This will allow running netbird commands (including debugging) against the daemon and provide a flow similar to non-container usages.

It will by default both log to file and stderr so it can be handled more uniformly in container-native environments.
This commit is contained in:
Krzysztof Nazarewski (kdn)
2025-07-25 11:44:30 +02:00
committed by GitHub
parent 3f82698089
commit af8687579b
29 changed files with 267 additions and 66 deletions

View File

@@ -16,36 +16,54 @@ import (
const defaultLogSize = 15
const (
LogConsole = "console"
LogSyslog = "syslog"
)
var (
SpecialLogs = []string{
LogSyslog,
LogConsole,
}
)
// InitLog parses and sets log-level input
func InitLog(logLevel string, logPath string) error {
func InitLog(logLevel string, logs ...string) error {
level, err := log.ParseLevel(logLevel)
if err != nil {
log.Errorf("Failed parsing log-level %s: %s", logLevel, err)
return err
}
customOutputs := []string{"console", "syslog"}
var writers []io.Writer
logFmt := os.Getenv("NB_LOG_FORMAT")
if logPath != "" && !slices.Contains(customOutputs, logPath) {
maxLogSize := getLogMaxSize()
lumberjackLogger := &lumberjack.Logger{
// Log file absolute path, os agnostic
Filename: filepath.ToSlash(logPath),
MaxSize: maxLogSize, // MB
MaxBackups: 10,
MaxAge: 30, // days
Compress: true,
for _, logPath := range logs {
switch logPath {
case LogSyslog:
AddSyslogHook()
logFmt = "syslog"
case LogConsole:
writers = append(writers, os.Stderr)
case "":
log.Warnf("empty log path received: %#v", logPath)
default:
writers = append(writers, newRotatedOutput(logPath))
}
log.SetOutput(io.Writer(lumberjackLogger))
} else if logPath == "syslog" {
AddSyslogHook()
}
//nolint:gocritic
if os.Getenv("NB_LOG_FORMAT") == "json" {
if len(writers) > 1 {
log.SetOutput(io.MultiWriter(writers...))
} else if len(writers) == 1 {
log.SetOutput(writers[0])
}
switch logFmt {
case "json":
formatter.SetJSONFormatter(log.StandardLogger())
} else if logPath == "syslog" {
case "syslog":
formatter.SetSyslogFormatter(log.StandardLogger())
} else {
default:
formatter.SetTextFormatter(log.StandardLogger())
}
log.SetLevel(level)
@@ -55,6 +73,29 @@ func InitLog(logLevel string, logPath string) error {
return nil
}
// FindFirstLogPath returns the first logs entry that could be a log path, that is neither empty, nor a special value
func FindFirstLogPath(logs []string) string {
for _, logFile := range logs {
if logFile != "" && !slices.Contains(SpecialLogs, logFile) {
return logFile
}
}
return ""
}
func newRotatedOutput(logPath string) io.Writer {
maxLogSize := getLogMaxSize()
lumberjackLogger := &lumberjack.Logger{
// Log file absolute path, os agnostic
Filename: filepath.ToSlash(logPath),
MaxSize: maxLogSize, // MB
MaxBackups: 10,
MaxAge: 30, // days
Compress: true,
}
return lumberjackLogger
}
func setGRPCLibLogger() {
logOut := log.StandardLogger().Writer()
if os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") != "info" {