From 292d17266e558278bd45cbd6778101f8dd0dbe38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sch=C3=BCnemann?= Date: Wed, 20 Aug 2025 11:49:29 +0200 Subject: [PATCH 1/3] add logging framework --- cmd/ocmTransfer.go | 5 ++++ cmd/root.go | 21 ++++++------- go.mod | 2 ++ go.sum | 8 +++++ internal/log/logger.go | 68 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 internal/log/logger.go diff --git a/cmd/ocmTransfer.go b/cmd/ocmTransfer.go index f5e157a..c515a82 100644 --- a/cmd/ocmTransfer.go +++ b/cmd/ocmTransfer.go @@ -1,6 +1,7 @@ package cmd import ( + "github.com/openmcp-project/bootstrapper/internal/log" ocmcli "github.com/openmcp-project/bootstrapper/internal/ocm-cli" "github.com/spf13/cobra" @@ -20,6 +21,10 @@ var ocmTransferCmd = &cobra.Command{ "target", }, RunE: func(cmd *cobra.Command, args []string) error { + log := log.GetLogger() + + log.Debugf("Executing ocmTransfer with source: %s, target: %s", args[0], args[1]) + transferCommands := []string{ "transfer", "componentversion", diff --git a/cmd/root.go b/cmd/root.go index 18cd369..1548f26 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,10 +3,11 @@ package cmd import ( "os" + "github.com/openmcp-project/bootstrapper/internal/log" "github.com/spf13/cobra" ) -// rootCmd represents the base command when called without any subcommands +// RootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ Use: "openmcp-bootstrapper", Short: "The openMCP bootstrapper CLI", @@ -27,13 +28,13 @@ func Execute() { } func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.bootstrapper.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - // RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + RootCmd.PersistentFlags().StringP("verbosity", "v", "info", "Set the verbosity level (panic, fatal, error, warn, info, debug, trace)") + cobra.OnInitialize(func() { + verbosity, err := RootCmd.PersistentFlags().GetString("verbosity") + if err != nil { + log.InitLogger("info") + return + } + log.InitLogger(verbosity) + }) } diff --git a/go.mod b/go.mod index 52437fe..771c61b 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,9 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.7 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 349e1a3..3befe5f 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= @@ -8,19 +9,26 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf 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/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE= go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= diff --git a/internal/log/logger.go b/internal/log/logger.go new file mode 100644 index 0000000..8cf830f --- /dev/null +++ b/internal/log/logger.go @@ -0,0 +1,68 @@ +package log + +import ( + "os" + "sync" + + "github.com/sirupsen/logrus" +) + +var ( + logger *logrus.Logger + loggerOnce sync.Once + levelPrintNames = map[logrus.Level]string{ + logrus.PanicLevel: "Panic", + logrus.FatalLevel: "Fatal", + logrus.ErrorLevel: "Error", + logrus.WarnLevel: "Warn", + logrus.InfoLevel: "Info", + logrus.DebugLevel: "Debug", + logrus.TraceLevel: "Trace", + } + levelFlagNames = map[string]logrus.Level{ + "panic": logrus.PanicLevel, + "fatal": logrus.FatalLevel, + "error": logrus.ErrorLevel, + "warn": logrus.WarnLevel, + "info": logrus.InfoLevel, + "debug": logrus.DebugLevel, + "trace": logrus.TraceLevel, + } +) + +// customFormatter implements logrus.Formatter to print errors in the format: Error: message +// and other levels as usual. +type customFormatter struct{} + +func (f *customFormatter) Format(entry *logrus.Entry) ([]byte, error) { + level, ok := levelPrintNames[entry.Level] + if !ok { + level = entry.Level.String() + } + return []byte(level + ": " + entry.Message + "\n"), nil +} + +// GetLogger returns a singleton logrus.Logger instance +func GetLogger() *logrus.Logger { + loggerOnce.Do(func() { + logger = logrus.New() + logger.SetLevel(logrus.InfoLevel) + logger.SetFormatter(&customFormatter{}) + }) + return logger +} + +// SetLevel sets the log level for the logger +func SetLevel(level logrus.Level) { + GetLogger().SetLevel(level) +} + +// InitLogger sets the log level based on the verbosity string and exits on error +func InitLogger(verbosity string) { + level, ok := levelFlagNames[verbosity] + if !ok { + GetLogger().Error("Unknown verbosity level: " + verbosity) + os.Exit(1) + } + SetLevel(level) +} From e9e7e685267b113dafc9baae75675a7b401022af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sch=C3=BCnemann?= Date: Wed, 20 Aug 2025 11:50:50 +0200 Subject: [PATCH 2/3] format --- cmd/root.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/root.go b/cmd/root.go index 1548f26..d090a16 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,8 +3,9 @@ package cmd import ( "os" - "github.com/openmcp-project/bootstrapper/internal/log" "github.com/spf13/cobra" + + "github.com/openmcp-project/bootstrapper/internal/log" ) // RootCmd represents the base command when called without any subcommands From 91d00de076b2c06e6a91f6d037001814665085e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sch=C3=BCnemann?= Date: Wed, 20 Aug 2025 11:52:25 +0200 Subject: [PATCH 3/3] update go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 771c61b..620d2cc 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/openmcp-project/bootstrapper go 1.25.0 require ( + github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.9.1 github.com/stretchr/testify v1.10.0 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 @@ -13,7 +14,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.7 // indirect go.yaml.in/yaml/v2 v2.4.2 // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect