diff --git a/.gitignore b/.gitignore index fff3dec..eb89565 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ sofmani +sofmani.log diff --git a/go.mod b/go.mod index 32725f1..b1cd947 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,16 @@ module github.com/chenasraf/sofmani go 1.23.0 -require github.com/eschao/config v0.1.0 +require ( + github.com/davecgh/go-spew v1.1.1 + github.com/eschao/config v0.1.0 + github.com/fatih/color v1.18.0 +) require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/stretchr/testify v1.9.0 // indirect + golang.org/x/sys v0.25.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 22d434f..6628d85 100644 --- a/go.sum +++ b/go.sum @@ -3,12 +3,23 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/eschao/config v0.1.0 h1:vtlNamzs6dC9pE0zyplqql16PFUUlst3VttQ+IT2/rk= github.com/eschao/config v0.1.0/go.mod h1:XMilcx0dPfk+tlJowGZPZdmdCRnd7AZuFhYA93tYBgA= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/installer/group_installer.go b/installer/group_installer.go index f40ad55..38499a0 100644 --- a/installer/group_installer.go +++ b/installer/group_installer.go @@ -1,9 +1,8 @@ package installer import ( - "fmt" - "github.com/chenasraf/sofmani/appconfig" + "github.com/chenasraf/sofmani/logger" ) type GroupInstaller struct { @@ -13,7 +12,7 @@ type GroupInstaller struct { // Install implements IInstaller. func (i *GroupInstaller) Install() error { - fmt.Printf("Installing group %s\n", i.Info.Name) + logger.Info("Installing group %s", i.Info.Name) for _, step := range *i.Info.Steps { err, installer := GetInstaller(i.Config, &step) if err != nil { diff --git a/installer/installer.go b/installer/installer.go index 2a07a10..82a6828 100644 --- a/installer/installer.go +++ b/installer/installer.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/chenasraf/sofmani/appconfig" + "github.com/chenasraf/sofmani/logger" ) type IInstaller interface { @@ -25,21 +26,21 @@ func GetInstaller(config *appconfig.AppConfig, installer *appconfig.Installer) ( } func RunInstaller(config *appconfig.AppConfig, installer IInstaller) error { - fmt.Printf("Checking if %s is installed\n", installer.GetInfo().Name) + logger.Info("Checking if %s is installed", installer.GetInfo().Name) err, installed := installer.CheckIsInstalled() if err != nil { return err } if installed { - fmt.Printf("%s is already installed\n", installer.GetInfo().Name) + logger.Info("%s is already installed", installer.GetInfo().Name) if config.CheckUpdates { - fmt.Printf("Checking if %s needs an update\n", installer.GetInfo().Name) + logger.Info("Checking if %s needs an update", installer.GetInfo().Name) err, needsUpdate := installer.CheckNeedsUpdate() if err != nil { return err } if needsUpdate { - fmt.Printf("%s needs an update\n", installer.GetInfo().Name) + logger.Info("%s needs an update", installer.GetInfo().Name) installer.Update() } } else { diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..3c29832 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,89 @@ +package logger + +import ( + "fmt" + "log" + "os" + + "github.com/davecgh/go-spew/spew" + "github.com/fatih/color" +) + +type Logger struct { + fileLogger *log.Logger + consoleOut *log.Logger + logFile *os.File +} + +var logger *Logger + +func InitLogger(filePath string) *Logger { + // Open the log file + logFile, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + fmt.Printf("Could not create log file: %v\n", err) + os.Exit(1) + } + + // Create file and console loggers + fileLogger := log.New(logFile, "", log.LstdFlags) + consoleOut := log.New(os.Stdout, "", log.LstdFlags) + + // Initialize the logger + logger = &Logger{ + fileLogger: fileLogger, + consoleOut: consoleOut, + logFile: logFile, + } + + return logger +} + +func (l *Logger) log(level string, colorizer *color.Color, format string, args ...interface{}) { + // Create timestamped message + // timestamp := time.Now().Format("2006-01-02 15:04:05") + message := fmt.Sprintf("[%s] %s", level, fmt.Sprintf(format, args...)) + + // Write to file + l.fileLogger.Println(message) + + // Write to console with color + if colorizer != nil { + l.consoleOut.Println(colorizer.Sprint(message)) + } else { + l.consoleOut.Println(message) + } +} + +func Info(format string, args ...interface{}) { + colorBlue := color.New(color.FgBlue).Add(color.Bold) + logger.log(" INFO", colorBlue, format, args...) +} + +func Warn(format string, args ...interface{}) { + colorYellow := color.New(color.FgYellow).Add(color.Bold) + logger.log(" WARN", colorYellow, format, args...) +} + +func Error(format string, args ...interface{}) { + colorRed := color.New(color.FgRed).Add(color.Bold) + logger.log("ERROR", colorRed, format, args...) +} + +func Debug(format string, args ...interface{}) { + colorGreen := color.New(color.FgGreen).Add(color.Bold) + logger.log("DEBUG", colorGreen, format, args...) +} + +func Spew(v interface{}) { + // Print/debug the passed value (works like spew.Dump) + spewDump := spew.Sdump(v) + Debug("%s", spewDump) +} + +func CloseLogger() { + if logger != nil && logger.logFile != nil { + logger.logFile.Close() + } +} + diff --git a/main.go b/main.go index a2f7570..5aa5571 100644 --- a/main.go +++ b/main.go @@ -1,32 +1,33 @@ package main import ( - "fmt" + "os" "github.com/chenasraf/sofmani/installer" + "github.com/chenasraf/sofmani/logger" ) func main() { + logFile := "sofmani.log" + logger.InitLogger(logFile) cfg, err := LoadConfig() if err != nil { - fmt.Println(fmt.Errorf("Error loading config: %v", err)) + logger.Error("Error loading config: %v", err) return } - fmt.Println("Installing...") + logger.Info("Installing...") for _, i := range cfg.Install { - fmt.Println(fmt.Sprintf("Installing %s", i.Name)) + logger.Info("Installing %s", i.Name) err, installerInstance := installer.GetInstaller(cfg, &i) if err != nil { - fmt.Println(err) + logger.Error("%s", err) return } err = installer.RunInstaller(cfg, installerInstance) if err != nil { - fmt.Println(err) - panic(err) - return + logger.Error("%s", err) + os.Exit(1) } - } }