Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lib): configurable log file location #2380

Merged
merged 3 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/cmd/common/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
package common

import (
"io"
"os"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/pterm/pterm"
)

// LogLevelCLI holds the log level as input from a command
Expand Down Expand Up @@ -49,6 +51,14 @@ func SetupCLI() {
}

if !config.SkipLogFile {
message.UseLogFile()
logFile, err := message.UseLogFile("")
if err != nil {
message.WarnErr(err, "Error saving a log file to a temporary directory")
return
}

pterm.SetDefaultOutput(io.MultiWriter(os.Stderr, logFile))
location := message.LogFileLocation()
message.Notef("Saving log file to %s", location)
}
}
25 changes: 10 additions & 15 deletions src/pkg/message/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package message

import (
"fmt"
"os"
"strings"

"github.com/defenseunicorns/zarf/src/config"
Expand All @@ -31,8 +30,11 @@ func PrintCredentialTable(state *types.ZarfState, componentsToDeploy []types.Dep
componentsToDeploy = []types.DeployedComponent{{Name: "logging"}, {Name: "git-server"}}
}

// Set output to os.Stderr to avoid creds being printed in logs
pterm.SetDefaultOutput(os.Stderr)
// Pause the logfile's output to avoid credentials being printed to the log file
if logFile != nil {
logFile.pause()
defer logFile.resume()
}

loginData := [][]string{}
if state.RegistryInfo.InternalRegistry {
Expand Down Expand Up @@ -61,11 +63,6 @@ func PrintCredentialTable(state *types.ZarfState, componentsToDeploy []types.Dep
header := []string{"Application", "Username", "Password", "Connect", "Get-Creds Key"}
Table(header, loginData)
}

// Restore the log file if it was specified
if !config.SkipLogFile {
UseLogFile()
}
}

// PrintComponentCredential displays credentials for a single component
Expand Down Expand Up @@ -96,8 +93,11 @@ func PrintComponentCredential(state *types.ZarfState, componentName string) {

// PrintCredentialUpdates displays credentials that will be updated
func PrintCredentialUpdates(oldState *types.ZarfState, newState *types.ZarfState, services []string) {
// Set output to os.Stderr to avoid creds being printed in logs
pterm.SetDefaultOutput(os.Stderr)
// Pause the logfile's output to avoid credentials being printed to the log file
if logFile != nil {
logFile.pause()
defer logFile.resume()
}

for _, service := range services {

Expand Down Expand Up @@ -144,11 +144,6 @@ func PrintCredentialUpdates(oldState *types.ZarfState, newState *types.ZarfState
}

pterm.Println()

// Restore the log file if it was specified
if !config.SkipLogFile {
UseLogFile()
}
}

func compareStrings(old string, new string, secret bool) string {
Expand Down
16 changes: 0 additions & 16 deletions src/pkg/message/generic.go

This file was deleted.

52 changes: 24 additions & 28 deletions src/pkg/message/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,11 @@ var NoProgress bool
// RuleLine creates a line of ━ as wide as the terminal
var RuleLine = strings.Repeat("━", TermWidth)

// LogWriter is the stream to write logs to.
var LogWriter io.Writer = os.Stderr

// logLevel holds the pterm compatible log level integer
var logLevel = InfoLevel

// logFile acts as a buffer for logFile generation
var logFile *os.File

// useLogFile controls whether to use the log file or not
var useLogFile bool
var logFile *pausableLogFile

// DebugWriter represents a writer interface that writes to message.Debug
type DebugWriter struct{}
Expand Down Expand Up @@ -83,27 +77,29 @@ func init() {
}

// UseLogFile writes output to stderr and a logFile.
func UseLogFile() {
func UseLogFile(dir string) (io.Writer, error) {
// Prepend the log filename with a timestamp.
ts := time.Now().Format("2006-01-02-15-04-05")

var err error
if logFile != nil {
// Use the existing log file if logFile is set
LogWriter = io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(LogWriter)
} else {
// Try to create a temp log file if one hasn't been made already
if logFile, err = os.CreateTemp("", fmt.Sprintf("zarf-%s-*.log", ts)); err != nil {
WarnErr(err, "Error saving a log file to a temporary directory")
} else {
useLogFile = true
LogWriter = io.MultiWriter(os.Stderr, logFile)
pterm.SetDefaultOutput(LogWriter)
message := fmt.Sprintf("Saving log file to %s", logFile.Name())
Note(message)
}
f, err := os.CreateTemp(dir, fmt.Sprintf("zarf-%s-*.log", ts))
if err != nil {
return nil, err
}

logFile = &pausableLogFile{
wr: f,
f: f,
}

return logFile, nil
}

// LogFileLocation returns the location of the log file.
func LogFileLocation() string {
if logFile == nil {
return ""
}
return logFile.f.Name()
}

// SetLogLevel sets the log level.
Expand Down Expand Up @@ -223,8 +219,8 @@ func Question(text string) {

// Questionf prints a user prompt description message with a given format.
func Questionf(format string, a ...any) {
pterm.Println()
message := Paragraph(format, a...)
pterm.Println()
pterm.FgLightGreen.Println(message)
}

Expand All @@ -235,7 +231,6 @@ func Note(text string) {

// Notef prints a note message with a given format.
func Notef(format string, a ...any) {
pterm.Println()
message := Paragraphn(TermWidth-7, format, a...)
notePrefix := pterm.PrefixPrinter{
MessageStyle: &pterm.ThemeDefault.InfoMessageStyle,
Expand All @@ -244,6 +239,7 @@ func Notef(format string, a ...any) {
Text: "NOTE",
},
}
pterm.Println()
notePrefix.Println(message)
}

Expand All @@ -256,10 +252,10 @@ func Title(title string, help string) {

// HeaderInfof prints a large header with a formatted message.
func HeaderInfof(format string, a ...any) {
pterm.Println()
message := Truncate(fmt.Sprintf(format, a...), TermWidth, false)
// Ensure the text is consistent for the header width
padding := TermWidth - len(message)
pterm.Println()
pterm.DefaultHeader.
WithBackgroundStyle(pterm.NewStyle(pterm.BgDarkGray)).
WithTextStyle(pterm.NewStyle(pterm.FgLightWhite)).
Expand Down Expand Up @@ -366,7 +362,7 @@ func debugPrinter(offset int, a ...any) {
printer.Println(a...)

// Always write to the log file
if useLogFile {
if logFile != nil {
pterm.Debug.
WithShowLineNumber(true).
WithLineNumberOffset(offset).
Expand Down
31 changes: 31 additions & 0 deletions src/pkg/message/pausable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package message provides a rich set of functions for displaying messages to the user.
package message

import (
"io"
"os"
)

// pausableLogFile is a pausable log file
type pausableLogFile struct {
wr io.Writer
f *os.File
}

// pause the log file
func (l *pausableLogFile) pause() {
l.wr = io.Discard
}

// resume the log file
func (l *pausableLogFile) resume() {
l.wr = l.f
}

// Write writes the data to the log file
func (l *pausableLogFile) Write(p []byte) (n int, err error) {
return l.wr.Write(p)
}
3 changes: 3 additions & 0 deletions src/pkg/message/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package message

import (
"os"

"github.com/pterm/pterm"
)

Expand All @@ -28,6 +30,7 @@ func NewProgressBar(total int64, text string) *ProgressBar {
WithTitle(padding + text).
WithRemoveWhenDone(true).
WithMaxWidth(TermWidth).
WithWriter(os.Stderr).
Start()
}

Expand Down