From 5e892d8bbc7ffc525be92d38898dd4b9f7163f10 Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Wed, 29 Dec 2021 11:40:12 +1300 Subject: [PATCH 01/10] feat: configure logging via commandline arguments --- .gitignore | 2 + cmd/terramate/cli/cli.go | 85 ++++++++++++++++++++++++++++++++++++++++ go.mod | 9 +++-- go.sum | 22 +++++++++-- hack/mod-check | 52 ++++++++++++------------ 5 files changed, 136 insertions(+), 34 deletions(-) mode change 100755 => 100644 hack/mod-check diff --git a/.gitignore b/.gitignore index 95a793d21..c5f8e4c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ coverage.txt .terraform .terraform.lock.hcl /cmd/terramate/terramate + +.vscode/ diff --git a/cmd/terramate/cli/cli.go b/cmd/terramate/cli/cli.go index 407e3e677..5b6e6a837 100644 --- a/cmd/terramate/cli/cli.go +++ b/cmd/terramate/cli/cli.go @@ -36,6 +36,8 @@ import ( "github.com/mineiros-io/terramate/hcl" "github.com/mineiros-io/terramate/stack" "github.com/posener/complete" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/willabides/kongplete" ) @@ -52,11 +54,18 @@ const ( defaultBranchBaseRef = "HEAD^" ) +const ( + LogLevelDefault = "none" + LogFmtDefault = "json" +) + type cliSpec struct { Version struct{} `cmd:"" help:"Terramate version."` Chdir string `short:"C" optional:"true" help:"sets working directory."` GitChangeBase string `short:"B" optional:"true" help:"git base ref for computing changes."` Changed bool `short:"c" optional:"true" help:"filter by changed infrastructure"` + LogLevel string `optional:"true" help:"sets the log level. Possible values are: 'trace', 'debug', 'none'. The default is 'none'."` + LogFmt string `optional:"true" help:"sets the log format. Possible values are: 'json', 'text'. The default is 'text'."` Run struct { Quiet bool `short:"q" help:"Don't print any information other than the command output."` @@ -117,6 +126,10 @@ func Run( stdout io.Writer, stderr io.Writer, ) error { + if err := configureLogging(LogLevelDefault, LogFmtDefault, stderr); err != nil { + return err + } + c, err := newCLI(args, inheritEnv, stdin, stdout, stderr) if err != nil { return err @@ -192,6 +205,23 @@ func newCLI( return nil, fmt.Errorf("failed to parse cli args %v: %v", args, err) } + logLevel := parsedArgs.LogLevel + logFmt := parsedArgs.LogFmt + + if logLevel != "" || logFmt != "" { + if logLevel == "" { + logLevel = LogLevelDefault + } + + if logFmt == "" { + logFmt = LogFmtDefault + } + + if err := configureLogging(logLevel, logFmt, stderr); err != nil { + return nil, err + } + } + wd := parsedArgs.Chdir if wd == "" { wd, err = os.Getwd() @@ -824,3 +854,58 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { return nil } + +func configureLogging(logLevel string, logFmt string, output io.Writer) error { + zloglevel, err := getzlogLevel(logLevel) + if err != nil { + return err + } + + logwriter, err := getzlogWriter(logFmt, output) + if err != nil { + return err + } + + zerolog.SetGlobalLevel(zloglevel) + log.Logger = zerolog.New(logwriter).With().Timestamp().Logger() + return nil +} + +func lookupEnv(name, def string) string { + if v, ok := os.LookupEnv(name); ok { + return v + } + return def +} + +func getzlogLevel(level string) (zerolog.Level, error) { + switch level { + case "trace": + return zerolog.TraceLevel, nil + case "debug": + return zerolog.DebugLevel, nil + case "info": + return zerolog.InfoLevel, nil + case "warn": + return zerolog.WarnLevel, nil + case "error": + return zerolog.ErrorLevel, nil + case "none": + return zerolog.Disabled, nil + default: + return zerolog.NoLevel, fmt.Errorf("unknown log level %q", level) + } +} + +func getzlogWriter(format string, output io.Writer) (io.Writer, error) { + switch format { + case "text": + color := lookupEnv("TM_LOG_COLOR", "ON") + return zerolog.ConsoleWriter{Out: output, NoColor: color != "ON"}, nil + case "json": + // Default is JSON on zlog + return output, nil + default: + return nil, fmt.Errorf("unknown log format %q", format) + } +} diff --git a/go.mod b/go.mod index ad4cc60d9..54f3390ad 100644 --- a/go.mod +++ b/go.mod @@ -28,10 +28,11 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/rs/zerolog v1.26.1 github.com/zclconf/go-cty-yaml v1.0.2 // indirect - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 // indirect - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect - golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect - golang.org/x/text v0.3.5 // indirect + golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e // indirect + golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect + golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect + golang.org/x/text v0.3.6 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/go.sum b/go.sum index 574d861be..688e431b5 100644 --- a/go.sum +++ b/go.sum @@ -117,6 +117,7 @@ github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -158,6 +159,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -400,6 +402,9 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= @@ -441,6 +446,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= @@ -472,8 +478,9 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e h1:1SzTfNOXwIS2oWiMF+6qu0OUDKb0dauo6MoDUQyu+yU= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -504,6 +511,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -543,8 +551,9 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -560,6 +569,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -601,8 +611,10 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= @@ -614,8 +626,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -664,6 +677,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/hack/mod-check b/hack/mod-check old mode 100755 new mode 100644 index 65cfe73a0..bf7271cf3 --- a/hack/mod-check +++ b/hack/mod-check @@ -1,26 +1,26 @@ -#!/bin/bash - -set -o errexit -set -o nounset - -# We need this script because Go doesn't support a nice/non-destructive way -# to check for modules tidyness: https://github.com/golang/go/issues/27005 - -changes="$(git status --porcelain)" - -if [[ ! -z "${changes}" ]] -then - echo "project already has changes, this should be run on a clean repo" - exit 1 -fi - -go mod tidy -changes="$(git status --porcelain)" -git checkout . - -if [[ ! -z "${changes}" ]] -then - echo "changes detected after tidying modules:" - echo "${changes}" - exit 1 -fi +#!/bin/bash + +set -o errexit +set -o nounset + +# We need this script because Go doesn't support a nice/non-destructive way +# to check for modules tidyness: https://github.com/golang/go/issues/27005 + +changes="$(git status --porcelain)" + +if [[ ! -z "${changes}" ]] +then + echo "project already has changes, this should be run on a clean repo" + exit 1 +fi + +go mod tidy +changes="$(git status --porcelain)" +git checkout . + +if [[ ! -z "${changes}" ]] +then + echo "changes detected after tidying modules:" + echo "${changes}" + exit 1 +fi From c63b69cf43f5c89a757b40f0ffaeeac54d773e13 Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Mon, 3 Jan 2022 10:51:40 +1300 Subject: [PATCH 02/10] feat: add cli logging --- cmd/terramate/cli/cli.go | 349 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 327 insertions(+), 22 deletions(-) diff --git a/cmd/terramate/cli/cli.go b/cmd/terramate/cli/cli.go index 5b6e6a837..91fe177e6 100644 --- a/cmd/terramate/cli/cli.go +++ b/cmd/terramate/cli/cli.go @@ -22,6 +22,7 @@ import ( "os/exec" "path/filepath" "strings" + "time" "github.com/mineiros-io/terramate/dag" "github.com/mineiros-io/terramate/generate" @@ -55,8 +56,8 @@ const ( ) const ( - LogLevelDefault = "none" - LogFmtDefault = "json" + defaultLogLevel = "none" + defaultLogFmt = "json" ) type cliSpec struct { @@ -126,10 +127,6 @@ func Run( stdout io.Writer, stderr io.Writer, ) error { - if err := configureLogging(LogLevelDefault, LogFmtDefault, stderr); err != nil { - return err - } - c, err := newCLI(args, inheritEnv, stdin, stdout, stderr) if err != nil { return err @@ -208,20 +205,13 @@ func newCLI( logLevel := parsedArgs.LogLevel logFmt := parsedArgs.LogFmt - if logLevel != "" || logFmt != "" { - if logLevel == "" { - logLevel = LogLevelDefault - } - - if logFmt == "" { - logFmt = LogFmtDefault - } - - if err := configureLogging(logLevel, logFmt, stderr); err != nil { - return nil, err - } + if err := configureLogging(logLevel, logFmt, stderr); err != nil { + return nil, err } + log.Trace(). + Str("actionContext", "newCli()"). + Msg("Get working directory.") wd := parsedArgs.Chdir if wd == "" { wd, err = os.Getwd() @@ -230,21 +220,37 @@ func newCLI( } } + log.Trace(). + Str("actionContext", "newCli()"). + Str("stack", wd). + Msg(fmt.Sprintf("Evaluate symbolic links for %q.", wd)) wd, err = filepath.EvalSymlinks(wd) if err != nil { return nil, fmt.Errorf("failed evaluating symlinks for %q: %w", wd, err) } + log.Trace(). + Str("actionContext", "newCli()"). + Str("stack", wd). + Msg(fmt.Sprintf("Get absolute file path of %q.", wd)) wd, err = filepath.Abs(wd) if err != nil { return nil, fmt.Errorf("getting absolute path of %q: %w", wd, err) } + log.Trace(). + Str("actionContext", "newCli()"). + Str("stack", wd). + Msg(fmt.Sprintf("Change working directory to %q.", wd)) err = os.Chdir(wd) if err != nil { return nil, fmt.Errorf("failed to change working directory to %q: %w", wd, err) } + log.Trace(). + Str("actionContext", "newCli()"). + Str("stack", wd). + Msg(fmt.Sprintf("Look up project in %q.", wd)) prj, foundRoot, err := lookupProject(wd) if err != nil { return nil, fmt.Errorf("failed to lookup project root from %q: %w", wd, err) @@ -254,6 +260,10 @@ func newCLI( return nil, fmt.Errorf("project root not found") } + log.Trace(). + Str("actionContext", "newCli()"). + Str("stack", wd). + Msg("Set defaults from parsed command line arguments.") err = prj.setDefaults(&parsedArgs) if err != nil { return nil, fmt.Errorf("setting configuration: %w", err) @@ -281,45 +291,116 @@ func (c *cli) run() error { } if c.parsedArgs.Changed { + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("`Changed` flag was set.") + + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Create new git wrapper.") git, err := newGit(c.root(), c.inheritEnv, true) if err != nil { return err } + + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Check git default remote.") if err := c.checkDefaultRemote(git); err != nil { return err } + + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Check git default branch was updated.") if err := c.checkLocalDefaultIsUpdated(git); err != nil { return err } } + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle input command.") switch c.ctx.Command() { case "version": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Get terramate version.") c.log(terramate.Version()) case "plan graph": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `plan graph`.") return c.generateGraph() case "plan run-order": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Print run-order.") return c.printRunOrder() case "stacks init": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle stacks init command.") return c.initStack([]string{c.wd()}) case "stacks list": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Print list of stacks.") return c.printStacks() case "stacks init ": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle stacks init command.") return c.initStack(c.parsedArgs.Stacks.Init.StackDirs) case "stacks globals": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle stacks global command.") return c.printStacksGlobals() case "run": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `run` command.") if len(c.parsedArgs.Run.Command) == 0 { return errors.New("no command specified") } fallthrough case "run ": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `run ` command.") return c.runOnStacks() case "generate": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `generate` command.") return generate.Do(c.root()) case "metadata": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `metadata` command.") return c.printMetadata() case "install-completions": + log.Trace(). + Str("actionContext", "cli()"). + Str("stack", c.wd()). + Msg("Handle `install-completions` command.") return c.parsedArgs.InstallCompletions.Run(c.ctx) default: return fmt.Errorf("unexpected command sequence: %s", c.ctx.Command()) @@ -330,11 +411,24 @@ func (c *cli) run() error { func (c *cli) initStack(dirs []string) error { var errmsgs []string + log.Trace(). + Str("actionContext", "initStack()"). + Str("stack", c.wd()). + Msg("Init stacks.") for _, d := range dirs { if !filepath.IsAbs(d) { + log.Trace(). + Str("actionContext", "initStack()"). + Str("stack", fmt.Sprintf("%s%s", c.wd(), strings.Trim(d, "."))). + Msg("Make file path absolute.") d = filepath.Join(c.wd(), d) } + log.Trace(). + Str("actionContext", "initStack()"). + Str("stack", fmt.Sprintf("%s%s", c.wd(), strings.Trim(d, "."))). + Msg("Init stack.") + err := terramate.Init(c.root(), d, c.parsedArgs.Stacks.Init.Force) if err != nil { c.logerr("warn: failed to initialize stack: %v", err) @@ -351,19 +445,35 @@ func (c *cli) initStack(dirs []string) error { func (c *cli) listStacks(mgr *terramate.Manager, isChanged bool) ([]terramate.Entry, error) { if isChanged { + log.Trace(). + Str("actionContext", "listStacks()"). + Str("stack", c.wd()). + Msg("`Changed` flag was set. List changed stacks.") return mgr.ListChanged() } - return mgr.List() } func (c *cli) printStacks() error { + log.Trace(). + Str("actionContext", "printStacks()"). + Str("stack", c.wd()). + Msg("Create a new stack manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) + + log.Trace(). + Str("actionContext", "printStacks()"). + Str("stack", c.wd()). + Msg("Get stack list.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) if err != nil { return err } + log.Trace(). + Str("actionContext", "printStacks()"). + Str("stack", c.wd()). + Msg("Print stacks.") for _, entry := range entries { stack := entry.Stack stackRepr, ok := c.friendlyFmtDir(stack.Dir) @@ -371,6 +481,11 @@ func (c *cli) printStacks() error { continue } + log.Trace(). + Str("actionContext", "printStacks()"). + Str("stack", c.wd()+stack.Dir). + Msg("Print stack.") + if c.parsedArgs.Stacks.List.Why { c.log("%s - %s", stackRepr, entry.Reason) } else { @@ -383,10 +498,22 @@ func (c *cli) printStacks() error { func (c *cli) generateGraph() error { var getLabel func(s stack.S) string + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Handle graph label command line argument.") switch c.parsedArgs.Plan.Graph.Label { case "stack.name": + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Set label to stack name.") getLabel = func(s stack.S) string { return s.Name() } case "stack.dir": + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Set label stack directory.") getLabel = func(s stack.S) string { return s.Dir } default: return fmt.Errorf("-label expects the values \"stack.name\" or \"stack.dir\"") @@ -396,6 +523,10 @@ func (c *cli) generateGraph() error { return err } + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Create new graph.") loader := stack.NewLoader(c.root()) dotGraph := dot.NewGraph(dot.Directed) graph := dag.New() @@ -424,11 +555,23 @@ func (c *cli) generateGraph() error { } } + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Set output of graph.") outFile := c.parsedArgs.Plan.Graph.Outfile var out io.Writer if outFile == "" { + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Set output to stdout.") out = c.stdout } else { + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Set output to file.") f, err := os.Create(outFile) if err != nil { return fmt.Errorf("opening file %q: %w", outFile, err) @@ -439,6 +582,10 @@ func (c *cli) generateGraph() error { out = f } + log.Trace(). + Str("actionContext", "generateGraph()"). + Str("stack", c.wd()). + Msg("Write graph to output.") _, err = out.Write([]byte(dotGraph.String())) if err != nil { return fmt.Errorf("writing output to %q: %w", outFile, err) @@ -485,18 +632,40 @@ func generateDot( } func (c *cli) printRunOrder() error { + log.Trace(). + Str("actionContext", "printRunOrder()"). + Str("stack", c.wd()). + Msg("Create new terramate manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) + + log.Trace(). + Str("actionContext", "printRunOrder()"). + Str("stack", c.wd()). + Msg("Get list of stacks.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) if err != nil { return err } + log.Trace(). + Str("actionContext", "printRunOrder()"). + Str("stack", c.wd()). + Msg("Filter stacks by working directory.") entries = c.filterStacksByWorkingDir(entries) + + log.Trace(). + Str("actionContext", "printRunOrder()"). + Str("stack", c.wd()). + Msg("Create stack array.") stacks := make([]stack.S, len(entries)) for i, e := range entries { stacks[i] = e.Stack } + log.Trace(). + Str("actionContext", "printRunOrder()"). + Str("stack", c.wd()). + Msg("Get run order.") order, reason, err := terramate.RunOrder(c.root(), stacks, c.parsedArgs.Changed) if err != nil { if errors.Is(err, dag.ErrCycleDetected) { @@ -543,14 +712,26 @@ func (c *cli) printStacksGlobals() error { } func (c *cli) printMetadata() error { + log.Trace(). + Str("actionContext", "printMetadata()"). + Str("stack", c.wd()). + Msg("Load metadata.") metadata, err := terramate.LoadMetadata(c.root()) if err != nil { return err } + log.Trace(). + Str("actionContext", "printMetadata()"). + Str("stack", c.wd()). + Msg("Log metadata.") c.log("Available metadata:") for _, stack := range metadata.Stacks { + log.Trace(). + Str("actionContext", "printMetadata()"). + Str("stack", c.wd()+stack.Path). + Msg("Print metadata for individual stack.") c.log("\nstack %q:", stack.Path) c.log("\tterramate.name=%q", stack.Name) c.log("\tterramate.path=%q", stack.Path) @@ -560,7 +741,16 @@ func (c *cli) printMetadata() error { } func (c *cli) runOnStacks() error { + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Create new terramate manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) + + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Get list of stacks.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) if err != nil { return err @@ -572,12 +762,25 @@ func (c *cli) runOnStacks() error { c.log("Running on all stacks:") } + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Filter stacks by working directory.") entries = c.filterStacksByWorkingDir(entries) + + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Create array of stacks.") stacks := make([]stack.S, len(entries)) for i, e := range entries { stacks[i] = e.Stack } + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Get command to run.") cmdName := c.parsedArgs.Run.Command[0] args := c.parsedArgs.Run.Command[1:] cmd := exec.Command(cmdName, args...) @@ -585,6 +788,10 @@ func (c *cli) runOnStacks() error { cmd.Stdout = c.stdout cmd.Stderr = c.stderr + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Get order of stacks to run command on.") order, reason, err := terramate.RunOrder(c.root(), stacks, c.parsedArgs.Changed) if err != nil { if errors.Is(err, dag.ErrCycleDetected) { @@ -595,6 +802,10 @@ func (c *cli) runOnStacks() error { } if c.parsedArgs.Run.DryRun { + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Do a dry run - get order without actually running command.") if len(order) > 0 { c.log("The stacks will be executed using order below:") @@ -609,6 +820,10 @@ func (c *cli) runOnStacks() error { return nil } + log.Trace(). + Str("actionContext", "runOnStacks()"). + Str("stack", c.wd()). + Msg("Run command.") err = terramate.Run(c.root(), order, cmd) if err != nil { c.logerr("warn: failed to execute command: %v", err) @@ -629,6 +844,10 @@ func (c *cli) logerr(format string, args ...interface{}) { } func (c *cli) checkDefaultRemote(g *git.Git) error { + log.Trace(). + Str("actionContext", "checkDefaultRemote()"). + Str("stack", c.wd()). + Msg("Get list of configured git remotes.") remotes, err := g.Remotes() if err != nil { return fmt.Errorf("checking if remote %q exists: %v", defaultRemote, err) @@ -636,6 +855,10 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { var defRemote *git.Remote + log.Trace(). + Str("actionContext", "checkDefaultRemote()"). + Str("stack", c.wd()). + Msg("Find default git remote.") for _, remote := range remotes { if remote.Name == defaultRemote { defRemote = &remote @@ -651,6 +874,10 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { ) } + log.Trace(). + Str("actionContext", "checkDefaultRemote()"). + Str("stack", c.wd()). + Msg("Find default git branch.") for _, branch := range defRemote.Branches { if branch == defaultBranch { return nil @@ -667,6 +894,10 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { } func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error { + log.Trace(). + Str("actionContext", "checkLocalDefaultIsUpdated()"). + Str("stack", c.wd()). + Msg("Get current git branch.") branch, err := g.CurrentBranch() if err != nil { return fmt.Errorf("checking local branch is updated: %v", err) @@ -679,12 +910,20 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error { c.logerr("current branch %q is the default branch, checking if it is updated.", branch) c.logerr("retrieving info from remote branch: %s/%s ...", defaultRemote, defaultBranch) + log.Trace(). + Str("actionContext", "checkLocalDefaultIsUpdated()"). + Str("stack", c.wd()). + Msg("Fetch remote reference.") remoteRef, err := g.FetchRemoteRev(defaultRemote, defaultBranch) if err != nil { return fmt.Errorf("checking local branch %q is update: %v", branch, err) } c.logerr("retrieved info from remote branch: %s/%s.", defaultRemote, defaultBranch) + log.Trace(). + Str("actionContext", "checkLocalDefaultIsUpdated()"). + Str("stack", c.wd()). + Msg("Get local commit ID.") localCommitID, err := g.RevParse(branch) if err != nil { return fmt.Errorf("checking local branch %q is update: %v", branch, err) @@ -713,8 +952,16 @@ func (c *cli) friendlyFmtDir(dir string) (string, bool) { } func (c *cli) filterStacksByWorkingDir(stacks []terramate.Entry) []terramate.Entry { + log.Trace(). + Str("actionContext", "filterStacksByWorkingDir()"). + Str("stack", c.wd()). + Msg("Get relative working directory.") relwd := prj.RelPath(c.root(), c.wd()) + log.Trace(). + Str("actionContext", "filterStacksByWorkingDir()"). + Str("stack", c.wd()). + Msg("Get filtered stacks.") filtered := []terramate.Entry{} for _, e := range stacks { if strings.HasPrefix(e.Stack.Dir, relwd) { @@ -726,6 +973,9 @@ func (c *cli) filterStacksByWorkingDir(stacks []terramate.Entry) []terramate.Ent } func newGit(basedir string, inheritEnv bool, checkrepo bool) (*git.Git, error) { + log.Trace(). + Str("actionContext", "newGit()"). + Msg("Create new git wrapper providing config.") g, err := git.WithConfig(git.Config{ WorkingDir: basedir, InheritEnv: inheritEnv, @@ -746,15 +996,32 @@ func lookupProject(wd string) (prj project, found bool, err error) { prj = project{ wd: wd, } + + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Create new git wrapper.") gw, err := newGit(wd, false, false) if err == nil { + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Get root of git repo.") gitdir, err := gw.Root() if err == nil { + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Get absolute path of git directory.") gitabs, err := filepath.Abs(gitdir) if err != nil { return project{}, false, fmt.Errorf("getting absolute path of %q: %w", gitdir, err) } + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Evaluate symbolic links.") gitabs, err = filepath.EvalSymlinks(gitabs) if err != nil { return project{}, false, fmt.Errorf("failed evaluating symlinks of %q: %w", @@ -762,6 +1029,11 @@ func lookupProject(wd string) (prj project, found bool, err error) { } root := filepath.Dir(gitabs) + + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Load root config.") cfg, _, err := config.TryLoadRootConfig(root) if err != nil { return project{}, false, err @@ -778,6 +1050,10 @@ func lookupProject(wd string) (prj project, found bool, err error) { dir := wd for { + log.Trace(). + Str("actionContext", "lookupProject()"). + Str("stack", wd). + Msg("Load root config.") cfg, ok, err := config.TryLoadRootConfig(dir) if err != nil { return project{}, false, err @@ -804,14 +1080,23 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { if p.rootcfg.Terramate == nil { // if config has no terramate block we create one with default // configurations. + log.Trace(). + Str("actionContext", "setDefaults()"). + Str("stack", p.wd). + Str("configFile", p.root+"/terramate.tm.hcl"). + Msg("Create terramate block.") p.rootcfg.Terramate = &hcl.Terramate{} } + log.Trace(). + Str("actionContext", "setDefaults()"). + Str("stack", p.wd). + Str("configFile", p.root+"/terramate.tm.hcl"). + Msg("Set defaults.") cfg := &p.rootcfg if cfg.Terramate.RootConfig == nil { p.rootcfg.Terramate.RootConfig = &hcl.RootConfig{} } - gitOpt := &cfg.Terramate.RootConfig.Git if gitOpt.BaseRef == "" { @@ -834,11 +1119,21 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { if baseRef == "" { baseRef = gitOpt.BaseRef if p.isRepo { + log.Trace(). + Str("actionContext", "setDefaults()"). + Str("stack", p.wd). + Str("configFile", p.root+"/terramate.tm.hcl"). + Msg("Create new git wrapper.") gw, err := newGit(p.wd, false, false) if err != nil { return err } + log.Trace(). + Str("actionContext", "setDefaults()"). + Str("stack", p.wd). + Str("configFile", p.root+"/terramate.tm.hcl"). + Msg("Get current branch.") branch, err := gw.CurrentBranch() if err != nil { return fmt.Errorf("failed to get current git branch: %v", err) @@ -856,6 +1151,15 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { } func configureLogging(logLevel string, logFmt string, output io.Writer) error { + + if logLevel == "" { + logLevel = defaultLogLevel + } + + if logFmt == "" { + logFmt = defaultLogFmt + } + zloglevel, err := getzlogLevel(logLevel) if err != nil { return err @@ -867,7 +1171,7 @@ func configureLogging(logLevel string, logFmt string, output io.Writer) error { } zerolog.SetGlobalLevel(zloglevel) - log.Logger = zerolog.New(logwriter).With().Timestamp().Logger() + log.Logger = zerolog.New(logwriter).With().Timestamp().Caller().Logger() return nil } @@ -901,9 +1205,10 @@ func getzlogWriter(format string, output io.Writer) (io.Writer, error) { switch format { case "text": color := lookupEnv("TM_LOG_COLOR", "ON") - return zerolog.ConsoleWriter{Out: output, NoColor: color != "ON"}, nil + return zerolog.ConsoleWriter{Out: output, NoColor: color != "ON", TimeFormat: time.RFC3339}, nil case "json": // Default is JSON on zlog + zerolog.TimeFieldFormat = zerolog.TimeFormatUnix return output, nil default: return nil, fmt.Errorf("unknown log format %q", format) From 2bcef395c4cb225c8096980947259459eb628ea7 Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 09:55:20 +1300 Subject: [PATCH 03/10] fix: revert mod-check file permissions --- hack/mod-check | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hack/mod-check diff --git a/hack/mod-check b/hack/mod-check old mode 100644 new mode 100755 From 3c4d1ec2c1c83dbd354db4e2af7b2099993e4f5c Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 10:09:57 +1300 Subject: [PATCH 04/10] fix: fix mod-check file permission --- hack/mod-check | 52 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/hack/mod-check b/hack/mod-check index bf7271cf3..65cfe73a0 100755 --- a/hack/mod-check +++ b/hack/mod-check @@ -1,26 +1,26 @@ -#!/bin/bash - -set -o errexit -set -o nounset - -# We need this script because Go doesn't support a nice/non-destructive way -# to check for modules tidyness: https://github.com/golang/go/issues/27005 - -changes="$(git status --porcelain)" - -if [[ ! -z "${changes}" ]] -then - echo "project already has changes, this should be run on a clean repo" - exit 1 -fi - -go mod tidy -changes="$(git status --porcelain)" -git checkout . - -if [[ ! -z "${changes}" ]] -then - echo "changes detected after tidying modules:" - echo "${changes}" - exit 1 -fi +#!/bin/bash + +set -o errexit +set -o nounset + +# We need this script because Go doesn't support a nice/non-destructive way +# to check for modules tidyness: https://github.com/golang/go/issues/27005 + +changes="$(git status --porcelain)" + +if [[ ! -z "${changes}" ]] +then + echo "project already has changes, this should be run on a clean repo" + exit 1 +fi + +go mod tidy +changes="$(git status --porcelain)" +git checkout . + +if [[ ! -z "${changes}" ]] +then + echo "changes detected after tidying modules:" + echo "${changes}" + exit 1 +fi From 8c18eaa3d31b447fa9d1c9925f75f9b66e8874bf Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 10:48:57 +1300 Subject: [PATCH 05/10] feat: add sub-logger to reduce duplication --- cmd/terramate/cli/cli.go | 308 ++++++++++++++++----------------------- 1 file changed, 125 insertions(+), 183 deletions(-) diff --git a/cmd/terramate/cli/cli.go b/cmd/terramate/cli/cli.go index 91fe177e6..8255a22d1 100644 --- a/cmd/terramate/cli/cli.go +++ b/cmd/terramate/cli/cli.go @@ -210,7 +210,7 @@ func newCLI( } log.Trace(). - Str("actionContext", "newCli()"). + Str("action", "newCli()"). Msg("Get working directory.") wd := parsedArgs.Chdir if wd == "" { @@ -220,37 +220,34 @@ func newCLI( } } - log.Trace(). - Str("actionContext", "newCli()"). + logger := log.With(). + Str("action", "newCli()"). Str("stack", wd). - Msg(fmt.Sprintf("Evaluate symbolic links for %q.", wd)) + Logger() + + logger.Trace(). + Msgf("Evaluate symbolic links for %q.", wd) wd, err = filepath.EvalSymlinks(wd) if err != nil { return nil, fmt.Errorf("failed evaluating symlinks for %q: %w", wd, err) } - log.Trace(). - Str("actionContext", "newCli()"). - Str("stack", wd). - Msg(fmt.Sprintf("Get absolute file path of %q.", wd)) + logger.Trace(). + Msgf("Get absolute file path of %q.", wd) wd, err = filepath.Abs(wd) if err != nil { return nil, fmt.Errorf("getting absolute path of %q: %w", wd, err) } - log.Trace(). - Str("actionContext", "newCli()"). - Str("stack", wd). - Msg(fmt.Sprintf("Change working directory to %q.", wd)) + logger.Trace(). + Msgf("Change working directory to %q.", wd) err = os.Chdir(wd) if err != nil { return nil, fmt.Errorf("failed to change working directory to %q: %w", wd, err) } - log.Trace(). - Str("actionContext", "newCli()"). - Str("stack", wd). - Msg(fmt.Sprintf("Look up project in %q.", wd)) + logger.Trace(). + Msgf("Look up project in %q.", wd) prj, foundRoot, err := lookupProject(wd) if err != nil { return nil, fmt.Errorf("failed to lookup project root from %q: %w", wd, err) @@ -260,9 +257,7 @@ func newCLI( return nil, fmt.Errorf("project root not found") } - log.Trace(). - Str("actionContext", "newCli()"). - Str("stack", wd). + logger.Trace(). Msg("Set defaults from parsed command line arguments.") err = prj.setDefaults(&parsedArgs) if err != nil { @@ -290,47 +285,40 @@ func (c *cli) run() error { return nil } + logger := log.With(). + Str("action", "run()"). + Str("stack", c.wd()). + Logger() + if c.parsedArgs.Changed { - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("`Changed` flag was set.") - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Create new git wrapper.") git, err := newGit(c.root(), c.inheritEnv, true) if err != nil { return err } - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Check git default remote.") if err := c.checkDefaultRemote(git); err != nil { return err } - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Check git default branch was updated.") if err := c.checkLocalDefaultIsUpdated(git); err != nil { return err } } - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle input command.") switch c.ctx.Command() { case "version": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get terramate version.") c.log(terramate.Version()) case "plan graph": @@ -370,36 +358,26 @@ func (c *cli) run() error { Msg("Handle stacks global command.") return c.printStacksGlobals() case "run": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle `run` command.") if len(c.parsedArgs.Run.Command) == 0 { return errors.New("no command specified") } fallthrough case "run ": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle `run ` command.") return c.runOnStacks() case "generate": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle `generate` command.") return generate.Do(c.root()) case "metadata": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle `metadata` command.") return c.printMetadata() case "install-completions": - log.Trace(). - Str("actionContext", "cli()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Handle `install-completions` command.") return c.parsedArgs.InstallCompletions.Run(c.ctx) default: @@ -411,21 +389,22 @@ func (c *cli) run() error { func (c *cli) initStack(dirs []string) error { var errmsgs []string - log.Trace(). - Str("actionContext", "initStack()"). - Str("stack", c.wd()). + + logger := log.With(). + Str("action", "initStack()"). + Logger() + + logger.Trace(). Msg("Init stacks.") for _, d := range dirs { if !filepath.IsAbs(d) { log.Trace(). - Str("actionContext", "initStack()"). Str("stack", fmt.Sprintf("%s%s", c.wd(), strings.Trim(d, "."))). Msg("Make file path absolute.") d = filepath.Join(c.wd(), d) } log.Trace(). - Str("actionContext", "initStack()"). Str("stack", fmt.Sprintf("%s%s", c.wd(), strings.Trim(d, "."))). Msg("Init stack.") @@ -446,7 +425,7 @@ func (c *cli) initStack(dirs []string) error { func (c *cli) listStacks(mgr *terramate.Manager, isChanged bool) ([]terramate.Entry, error) { if isChanged { log.Trace(). - Str("actionContext", "listStacks()"). + Str("action", "listStacks()"). Str("stack", c.wd()). Msg("`Changed` flag was set. List changed stacks.") return mgr.ListChanged() @@ -455,14 +434,16 @@ func (c *cli) listStacks(mgr *terramate.Manager, isChanged bool) ([]terramate.En } func (c *cli) printStacks() error { - log.Trace(). - Str("actionContext", "printStacks()"). + logger := log.With(). + Str("action", "printStacks()"). + Logger() + + logger.Trace(). Str("stack", c.wd()). Msg("Create a new stack manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) - log.Trace(). - Str("actionContext", "printStacks()"). + logger.Trace(). Str("stack", c.wd()). Msg("Get stack list.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) @@ -470,8 +451,7 @@ func (c *cli) printStacks() error { return err } - log.Trace(). - Str("actionContext", "printStacks()"). + logger.Trace(). Str("stack", c.wd()). Msg("Print stacks.") for _, entry := range entries { @@ -481,8 +461,7 @@ func (c *cli) printStacks() error { continue } - log.Trace(). - Str("actionContext", "printStacks()"). + logger.Trace(). Str("stack", c.wd()+stack.Dir). Msg("Print stack.") @@ -498,21 +477,20 @@ func (c *cli) printStacks() error { func (c *cli) generateGraph() error { var getLabel func(s stack.S) string - log.Trace(). - Str("actionContext", "generateGraph()"). + logger := log.With(). + Str("action", "generateGraph()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Handle graph label command line argument.") switch c.parsedArgs.Plan.Graph.Label { case "stack.name": - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Set label to stack name.") getLabel = func(s stack.S) string { return s.Name() } case "stack.dir": - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Set label stack directory.") getLabel = func(s stack.S) string { return s.Dir } default: @@ -523,9 +501,7 @@ func (c *cli) generateGraph() error { return err } - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Create new graph.") loader := stack.NewLoader(c.root()) dotGraph := dot.NewGraph(dot.Directed) @@ -555,22 +531,16 @@ func (c *cli) generateGraph() error { } } - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Set output of graph.") outFile := c.parsedArgs.Plan.Graph.Outfile var out io.Writer if outFile == "" { - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Set output to stdout.") out = c.stdout } else { - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Set output to file.") f, err := os.Create(outFile) if err != nil { @@ -582,9 +552,7 @@ func (c *cli) generateGraph() error { out = f } - log.Trace(). - Str("actionContext", "generateGraph()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Write graph to output.") _, err = out.Write([]byte(dotGraph.String())) if err != nil { @@ -632,39 +600,34 @@ func generateDot( } func (c *cli) printRunOrder() error { - log.Trace(). - Str("actionContext", "printRunOrder()"). + logger := log.With(). + Str("action", "printRunOrder()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Create new terramate manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) - log.Trace(). - Str("actionContext", "printRunOrder()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get list of stacks.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) if err != nil { return err } - log.Trace(). - Str("actionContext", "printRunOrder()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Filter stacks by working directory.") entries = c.filterStacksByWorkingDir(entries) - log.Trace(). - Str("actionContext", "printRunOrder()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Create stack array.") stacks := make([]stack.S, len(entries)) for i, e := range entries { stacks[i] = e.Stack } - log.Trace(). - Str("actionContext", "printRunOrder()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get run order.") order, reason, err := terramate.RunOrder(c.root(), stacks, c.parsedArgs.Changed) if err != nil { @@ -712,8 +675,11 @@ func (c *cli) printStacksGlobals() error { } func (c *cli) printMetadata() error { - log.Trace(). - Str("actionContext", "printMetadata()"). + logger := log.With(). + Str("action", "printMetadata()"). + Logger() + + logger.Trace(). Str("stack", c.wd()). Msg("Load metadata.") metadata, err := terramate.LoadMetadata(c.root()) @@ -721,15 +687,13 @@ func (c *cli) printMetadata() error { return err } - log.Trace(). - Str("actionContext", "printMetadata()"). + logger.Trace(). Str("stack", c.wd()). Msg("Log metadata.") c.log("Available metadata:") for _, stack := range metadata.Stacks { - log.Trace(). - Str("actionContext", "printMetadata()"). + logger.Trace(). Str("stack", c.wd()+stack.Path). Msg("Print metadata for individual stack.") c.log("\nstack %q:", stack.Path) @@ -741,15 +705,16 @@ func (c *cli) printMetadata() error { } func (c *cli) runOnStacks() error { - log.Trace(). - Str("actionContext", "runOnStacks()"). + logger := log.With(). + Str("action", "runOnStacks()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Create new terramate manager.") mgr := terramate.NewManager(c.root(), c.prj.baseRef) - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get list of stacks.") entries, err := c.listStacks(mgr, c.parsedArgs.Changed) if err != nil { @@ -762,24 +727,18 @@ func (c *cli) runOnStacks() error { c.log("Running on all stacks:") } - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Filter stacks by working directory.") entries = c.filterStacksByWorkingDir(entries) - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Create array of stacks.") stacks := make([]stack.S, len(entries)) for i, e := range entries { stacks[i] = e.Stack } - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get command to run.") cmdName := c.parsedArgs.Run.Command[0] args := c.parsedArgs.Run.Command[1:] @@ -788,9 +747,7 @@ func (c *cli) runOnStacks() error { cmd.Stdout = c.stdout cmd.Stderr = c.stderr - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get order of stacks to run command on.") order, reason, err := terramate.RunOrder(c.root(), stacks, c.parsedArgs.Changed) if err != nil { @@ -802,9 +759,7 @@ func (c *cli) runOnStacks() error { } if c.parsedArgs.Run.DryRun { - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Do a dry run - get order without actually running command.") if len(order) > 0 { c.log("The stacks will be executed using order below:") @@ -820,9 +775,7 @@ func (c *cli) runOnStacks() error { return nil } - log.Trace(). - Str("actionContext", "runOnStacks()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Run command.") err = terramate.Run(c.root(), order, cmd) if err != nil { @@ -844,9 +797,12 @@ func (c *cli) logerr(format string, args ...interface{}) { } func (c *cli) checkDefaultRemote(g *git.Git) error { - log.Trace(). - Str("actionContext", "checkDefaultRemote()"). + logger := log.With(). + Str("action", "checkDefaultRemote()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Get list of configured git remotes.") remotes, err := g.Remotes() if err != nil { @@ -855,9 +811,7 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { var defRemote *git.Remote - log.Trace(). - Str("actionContext", "checkDefaultRemote()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Find default git remote.") for _, remote := range remotes { if remote.Name == defaultRemote { @@ -874,9 +828,7 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { ) } - log.Trace(). - Str("actionContext", "checkDefaultRemote()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Find default git branch.") for _, branch := range defRemote.Branches { if branch == defaultBranch { @@ -894,9 +846,12 @@ func (c *cli) checkDefaultRemote(g *git.Git) error { } func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error { - log.Trace(). - Str("actionContext", "checkLocalDefaultIsUpdated()"). + logger := log.With(). + Str("action", "checkLocalDefaultIsUpdated()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Get current git branch.") branch, err := g.CurrentBranch() if err != nil { @@ -910,9 +865,7 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error { c.logerr("current branch %q is the default branch, checking if it is updated.", branch) c.logerr("retrieving info from remote branch: %s/%s ...", defaultRemote, defaultBranch) - log.Trace(). - Str("actionContext", "checkLocalDefaultIsUpdated()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Fetch remote reference.") remoteRef, err := g.FetchRemoteRev(defaultRemote, defaultBranch) if err != nil { @@ -920,9 +873,7 @@ func (c *cli) checkLocalDefaultIsUpdated(g *git.Git) error { } c.logerr("retrieved info from remote branch: %s/%s.", defaultRemote, defaultBranch) - log.Trace(). - Str("actionContext", "checkLocalDefaultIsUpdated()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get local commit ID.") localCommitID, err := g.RevParse(branch) if err != nil { @@ -952,15 +903,16 @@ func (c *cli) friendlyFmtDir(dir string) (string, bool) { } func (c *cli) filterStacksByWorkingDir(stacks []terramate.Entry) []terramate.Entry { - log.Trace(). - Str("actionContext", "filterStacksByWorkingDir()"). + logger := log.With(). + Str("action", "filterStacksByWorkingDir()"). Str("stack", c.wd()). + Logger() + + logger.Trace(). Msg("Get relative working directory.") relwd := prj.RelPath(c.root(), c.wd()) - log.Trace(). - Str("actionContext", "filterStacksByWorkingDir()"). - Str("stack", c.wd()). + logger.Trace(). Msg("Get filtered stacks.") filtered := []terramate.Entry{} for _, e := range stacks { @@ -974,7 +926,7 @@ func (c *cli) filterStacksByWorkingDir(stacks []terramate.Entry) []terramate.Ent func newGit(basedir string, inheritEnv bool, checkrepo bool) (*git.Git, error) { log.Trace(). - Str("actionContext", "newGit()"). + Str("action", "newGit()"). Msg("Create new git wrapper providing config.") g, err := git.WithConfig(git.Config{ WorkingDir: basedir, @@ -997,30 +949,27 @@ func lookupProject(wd string) (prj project, found bool, err error) { wd: wd, } - log.Trace(). - Str("actionContext", "lookupProject()"). + logger := log.With(). + Str("action", "lookupProject()"). Str("stack", wd). + Logger() + + logger.Trace(). Msg("Create new git wrapper.") gw, err := newGit(wd, false, false) if err == nil { - log.Trace(). - Str("actionContext", "lookupProject()"). - Str("stack", wd). + logger.Trace(). Msg("Get root of git repo.") gitdir, err := gw.Root() if err == nil { - log.Trace(). - Str("actionContext", "lookupProject()"). - Str("stack", wd). + logger.Trace(). Msg("Get absolute path of git directory.") gitabs, err := filepath.Abs(gitdir) if err != nil { return project{}, false, fmt.Errorf("getting absolute path of %q: %w", gitdir, err) } - log.Trace(). - Str("actionContext", "lookupProject()"). - Str("stack", wd). + logger.Trace(). Msg("Evaluate symbolic links.") gitabs, err = filepath.EvalSymlinks(gitabs) if err != nil { @@ -1030,9 +979,7 @@ func lookupProject(wd string) (prj project, found bool, err error) { root := filepath.Dir(gitabs) - log.Trace(). - Str("actionContext", "lookupProject()"). - Str("stack", wd). + logger.Trace(). Msg("Load root config.") cfg, _, err := config.TryLoadRootConfig(root) if err != nil { @@ -1050,9 +997,7 @@ func lookupProject(wd string) (prj project, found bool, err error) { dir := wd for { - log.Trace(). - Str("actionContext", "lookupProject()"). - Str("stack", wd). + logger.Trace(). Msg("Load root config.") cfg, ok, err := config.TryLoadRootConfig(dir) if err != nil { @@ -1077,20 +1022,21 @@ func lookupProject(wd string) (prj project, found bool, err error) { } func (p *project) setDefaults(parsedArgs *cliSpec) error { + logger := log.With(). + Str("action", "setDefaults()"). + Str("stack", p.wd). + Logger() + if p.rootcfg.Terramate == nil { // if config has no terramate block we create one with default // configurations. - log.Trace(). - Str("actionContext", "setDefaults()"). - Str("stack", p.wd). + logger.Trace(). Str("configFile", p.root+"/terramate.tm.hcl"). Msg("Create terramate block.") p.rootcfg.Terramate = &hcl.Terramate{} } - log.Trace(). - Str("actionContext", "setDefaults()"). - Str("stack", p.wd). + logger.Trace(). Str("configFile", p.root+"/terramate.tm.hcl"). Msg("Set defaults.") cfg := &p.rootcfg @@ -1119,9 +1065,7 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { if baseRef == "" { baseRef = gitOpt.BaseRef if p.isRepo { - log.Trace(). - Str("actionContext", "setDefaults()"). - Str("stack", p.wd). + logger.Trace(). Str("configFile", p.root+"/terramate.tm.hcl"). Msg("Create new git wrapper.") gw, err := newGit(p.wd, false, false) @@ -1129,9 +1073,7 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { return err } - log.Trace(). - Str("actionContext", "setDefaults()"). - Str("stack", p.wd). + logger.Trace(). Str("configFile", p.root+"/terramate.tm.hcl"). Msg("Get current branch.") branch, err := gw.CurrentBranch() From f9a208b7b88b4bc76b89d7238528a014a18b5373 Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 11:11:35 +1300 Subject: [PATCH 06/10] feat: add config.go logging --- config/config.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/config/config.go b/config/config.go index 75626707c..49d5bef6f 100644 --- a/config/config.go +++ b/config/config.go @@ -19,6 +19,7 @@ import ( "path/filepath" "github.com/mineiros-io/terramate/hcl" + "github.com/rs/zerolog/log" ) const ( @@ -31,14 +32,26 @@ const ( // Exists tells if path has a terramate config file. func Exists(path string) bool { + logger := log.With(). + Str("action", "Exists()"). + Str("stack", path). + Logger() + + logger.Trace(). + Msg("Get path info.") st, err := os.Stat(path) if err != nil { return false } + + logger.Trace(). + Msg("Check if path is directory.") if !st.IsDir() { return false } + logger.Trace(). + Msg("Look for config file within directory.") fname := filepath.Join(path, Filename) info, err := os.Stat(fname) if err != nil { @@ -49,6 +62,14 @@ func Exists(path string) bool { } func TryLoadRootConfig(dir string) (cfg hcl.Config, found bool, err error) { + logger := log.With(). + Str("action", "TryLoadRootConfig()"). + Str("stack", dir). + Str("configFile", dir+Filename). + Logger() + + logger.Trace(). + Msg("Check if file exists.") path := filepath.Join(dir, Filename) _, err = os.Stat(path) if err != nil { @@ -59,6 +80,8 @@ func TryLoadRootConfig(dir string) (cfg hcl.Config, found bool, err error) { return hcl.Config{}, false, err } + logger.Trace(). + Msg("Parse file.") cfg, err = hcl.ParseFile(path) if err != nil { return hcl.Config{}, false, err From d410587944e63b074e6d74be86a9013b6eeff29b Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 14:51:11 +1300 Subject: [PATCH 07/10] feat: add logging for git.go --- git/git.go | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/git/git.go b/git/git.go index 569659a58..4fc8d0e40 100644 --- a/git/git.go +++ b/git/git.go @@ -21,6 +21,8 @@ import ( "os/exec" "sort" "strings" + + "github.com/rs/zerolog/log" ) type ( @@ -112,6 +114,9 @@ func NewConfig(username, email string) Config { // NewConfigWithPath calls NewConfig but also sets the git program path. func NewConfigWithPath(username, email, programPath string) Config { + log.Trace(). + Str("action", "NewConfigWithPath()"). + Msg("Make new config.") config := NewConfig(username, email) config.ProgramPath = programPath return config @@ -124,28 +129,51 @@ func NewWrapper(user, email string) (*Git, error) { // WithConfig creates a new git wrapper by providing the config. func WithConfig(cfg Config) (*Git, error) { + logger := log.With(). + Str("action", "WithConfig()"). + Str("stack", cfg.WorkingDir). + Logger() + + logger.Trace(). + Msg("Construct new config.") git := &Git{ config: cfg, } + logger.Trace(). + Msg("Apply defaults.") err := git.applyDefaults() if err != nil { return nil, fmt.Errorf("applying default config values: %w", err) } + logger.Trace(). + Msg("Validate git config.") err = git.validate() if err != nil { return nil, err } + logger.Trace(). + Msg("Get git version.") _, err = git.Version() return git, err } func (git *Git) applyDefaults() error { + logger := log.With(). + Str("action", "applyDefaults()"). + Str("stack", git.config.WorkingDir). + Logger() + cfg := &git.config if cfg.ProgramPath == "" { + logger.Trace(). + Msg("Config program path was null.") + + logger.Trace(). + Msg("Look for path 'git'.") programPath, err := exec.LookPath("git") if err != nil { return fmt.Errorf("%w: %v", ErrGitNotFound, err) @@ -155,6 +183,11 @@ func (git *Git) applyDefaults() error { } if cfg.WorkingDir == "" { + logger.Trace(). + Msg("Working directory was null.") + + logger.Trace(). + Msg("Get working directory.") wd, err := os.Getwd() if err != nil { return fmt.Errorf("failed to get working directory: %w", err) @@ -164,10 +197,14 @@ func (git *Git) applyDefaults() error { } if cfg.DefaultBranch == "" { + logger.Trace(). + Msg("Default branch was null. Set default to 'main'.") cfg.DefaultBranch = "main" } if cfg.DefaultRemote == "" { + logger.Trace(). + Msg("Default remote was null. Set default to 'origin'.") cfg.DefaultRemote = "origin" } @@ -177,6 +214,13 @@ func (git *Git) applyDefaults() error { func (git *Git) validate() error { cfg := git.config + logger := log.With(). + Str("action", "validate()"). + Str("stack", git.config.WorkingDir). + Logger() + + logger.Trace(). + Msgf("Get path program path information for: %s.", cfg.ProgramPath) _, err := os.Stat(cfg.ProgramPath) if err != nil { return fmt.Errorf("failed to stat git program path \"%s\": %w: %v", @@ -192,6 +236,13 @@ func (git *Git) validate() error { // Version of the git program. func (git *Git) Version() (string, error) { + logger := log.With(). + Str("action", "Version()"). + Str("stack", git.config.WorkingDir). + Logger() + + logger.Trace(). + Msg("Get git version.") out, err := git.exec("version") if err != nil { return "", err @@ -212,6 +263,11 @@ func (git *Git) Version() (string, error) { // store revisions. // Beware: Init is a porcelain method. func (git *Git) Init(dir string, bare bool) error { + logger := log.With(). + Str("action", "Init()"). + Str("stack", git.config.WorkingDir). + Logger() + if !git.config.AllowPorcelain { return fmt.Errorf("Init: %w", ErrDenyPorcelain) } @@ -224,6 +280,8 @@ func (git *Git) Init(dir string, bare bool) error { args = append(args, "--bare") } + logger.Trace(). + Msg("Append arguments to init command and execute.") args = append(args, dir) _, err := git.exec("init", args...) if err != nil { @@ -239,6 +297,8 @@ func (git *Git) Init(dir string, bare bool) error { git.config.WorkingDir = dir if git.config.Username != "" { + logger.Trace(). + Msg("Username was set. Configure username.") _, err = git.exec("config", "--local", "user.name", git.config.Username) if err != nil { return err @@ -246,6 +306,8 @@ func (git *Git) Init(dir string, bare bool) error { } if git.config.Email != "" { + logger.Trace(). + Msg("Email was set. Configure email.") _, err = git.exec("config", "--local", "user.email", git.config.Email) if err != nil { return err @@ -268,6 +330,13 @@ func (git *Git) RemoteAdd(name string, url string) error { func (git *Git) Remotes() ([]Remote, error) { const refprefix = "refs/remotes/" + logger := log.With(). + Str("action", "Remotes()"). + Str("stack", git.config.WorkingDir). + Logger() + + logger.Trace(). + Msg("Get all remote references.") res, err := git.exec("for-each-ref", "--format", "%(refname)", refprefix) if err != nil { @@ -280,7 +349,11 @@ func (git *Git) Remotes() ([]Remote, error) { references := map[string][]string{} + logger.Trace(). + Msg("Range over references.") for _, rawref := range strings.Split(res, "\n") { + logger.Trace(). + Msgf("Format reference: %s.", rawref) trimmedref := strings.TrimPrefix(rawref, refprefix) parsed := strings.Split(trimmedref, "/") if len(parsed) < 2 { @@ -289,15 +362,21 @@ func (git *Git) Remotes() ([]Remote, error) { name := parsed[0] branch := strings.Join(parsed[1:], "/") branches := references[name] + logger.Trace(). + Msgf("Append formatted reference to branches array: %s.", branch) references[name] = append(branches, branch) } var remotes remoteSorter + logger.Trace(). + Msg("Create remotes array.") for name, branches := range references { remotes = append(remotes, Remote{Name: name, Branches: branches}) } + logger.Trace(). + Msg("Sort remotes.") sort.Stable(remotes) return remotes, nil } @@ -308,13 +387,24 @@ func (git *Git) Remotes() ([]Remote, error) { // // It returns only the first line of the commit message. func (git *Git) LogSummary(revs ...string) ([]LogLine, error) { + logger := log.With(). + Str("action", "LogSummary()"). + Str("stack", git.config.WorkingDir). + Logger() + if len(revs) == 0 { + logger.Trace(). + Msg("Length of revisions was 0. Append 'HEAD'.") revs = append(revs, "HEAD") } + logger.Trace(). + Msg("Append `-pretty-oneline` argument.") args := append([]string{}, "--pretty=oneline") args = append(args, revs...) + logger.Trace(). + Msg("Get list of revs.") out, err := git.exec("rev-list", args...) if err != nil { return nil, err @@ -323,6 +413,9 @@ func (git *Git) LogSummary(revs ...string) ([]LogLine, error) { logs := []LogLine{} lines := strings.Split(out, "\n") + + logger.Trace(). + Msg("Range over revs.") for _, line := range lines { l := strings.TrimSpace(line) if len(l) == 0 { @@ -334,6 +427,8 @@ func (git *Git) LogSummary(revs ...string) ([]LogLine, error) { return nil, fmt.Errorf("malformed log line") } + logger.Trace(). + Msg("Append rev to logs.") logs = append(logs, LogLine{ CommitID: l[0:index], Message: l[index+1:], @@ -349,6 +444,11 @@ func (git *Git) Add(files ...string) error { if !git.config.AllowPorcelain { return fmt.Errorf("Add: %w", ErrDenyPorcelain) } + + log.Trace(). + Str("action", "Add()"). + Str("stack", git.config.WorkingDir). + Msg("Add file to current staged index.") _, err := git.exec("add", files...) return err } @@ -357,10 +457,17 @@ func (git *Git) Add(files ...string) error { // The args are extra flags and/or arguments to git commit command line. // Beware: Commit is a porcelain method. func (git *Git) Commit(msg string, args ...string) error { + logger := log.With(). + Str("action", "Commit()"). + Str("stack", git.config.WorkingDir). + Logger() + if !git.config.AllowPorcelain { return fmt.Errorf("Commit: %w", ErrDenyPorcelain) } + logger.Trace(). + Msg("Range args.") for _, arg := range args { if arg == "-m" { return fmt.Errorf("the -m argument is already implicitly set") @@ -373,6 +480,8 @@ func (git *Git) Commit(msg string, args ...string) error { vargs = append(vargs, args...) + logger.Trace(). + Msg("Commit with args.") _, err := git.exec("commit", vargs...) return err } @@ -388,6 +497,13 @@ func (git *Git) RevParse(rev string) (string, error) { // for the given remote and reference. This will make use of the network // to fetch data from the remote configured on the git repo. func (git *Git) FetchRemoteRev(remote, ref string) (Ref, error) { + logger := log.With(). + Str("action", "FetchRemoteRev()"). + Str("stack", git.config.WorkingDir). + Logger() + + logger.Trace(). + Msg("List references in remote repository.") output, err := git.exec("ls-remote", remote, ref) if err != nil { return Ref{}, fmt.Errorf( @@ -432,17 +548,28 @@ func (git *Git) Status() (string, error) { // recurse is set, then it walks into child trees as well. If // relative is set, then only show local changes of current dir. func (git *Git) DiffTree(from, to string, relative, nameOnly, recurse bool) (string, error) { + logger := log.With(). + Str("action", "DiffTree()"). + Str("stack", git.config.WorkingDir). + Logger() + args := []string{from, to} if relative { + logger.Trace(). + Msg("Set `--relative` command line arg.") args = append(args, "--relative") } if nameOnly { + logger.Trace(). + Msg("Set `--name-only` command line arg.") args = append(args, "--name-only") } if recurse { + logger.Trace(). + Msg("Set `--r` command line arg.") args = append(args, "-r") // git help shows no long flag name } @@ -453,6 +580,10 @@ func (git *Git) DiffTree(from, to string, relative, nameOnly, recurse bool) (str // commit ids differences and return all the file names containing differences // relative to configuration WorkingDir. func (git *Git) DiffNames(from, to string) ([]string, error) { + log.Trace(). + Str("action", "DiffNames()"). + Str("stack", git.config.WorkingDir). + Msgf("Get tree differences from `%s` to `%s`.", from, to) diff, err := git.DiffTree(from, to, true, true, true) if err != nil { return nil, fmt.Errorf("diff-tree: %w", err) @@ -463,20 +594,38 @@ func (git *Git) DiffNames(from, to string) ([]string, error) { // NewBranch creates a new branch reference pointing to current HEAD. func (git *Git) NewBranch(name string) error { + log.Trace(). + Str("action", "NewBranch()"). + Str("stack", git.config.WorkingDir). + Msgf("Get commit ID of: %s.", name) _, err := git.RevParse(name) if err == nil { return fmt.Errorf("branch \"%s\" already exists", name) } + + log.Trace(). + Str("action", "NewBranch()"). + Str("stack", git.config.WorkingDir). + Msgf("Update ref: %s.", name) _, err = git.exec("update-ref", "refs/heads/"+name, "HEAD") return err } // DeleteBranch deletes the branch. func (git *Git) DeleteBranch(name string) error { + log.Trace(). + Str("action", "DeleteBranch()"). + Str("stack", git.config.WorkingDir). + Msgf("Get commit ID of: %s.", name) _, err := git.RevParse(name) if err != nil { return fmt.Errorf("branch \"%s\" doesn't exist", name) } + + log.Trace(). + Str("action", "DeleteBranch()"). + Str("stack", git.config.WorkingDir). + Msgf("Delete branch: %s.", name) _, err = git.exec("update-ref", "-d", "refs/heads/"+name) return err } @@ -487,16 +636,24 @@ func (git *Git) DeleteBranch(name string) error { // Beware: Checkout is a porcelain method. func (git *Git) Checkout(rev string, create bool) error { if !git.config.AllowPorcelain { - return fmt.Errorf("Checkout: %w", ErrDenyPorcelain) + return fmt.Errorf("Checkout: %w.", ErrDenyPorcelain) } if create { + log.Trace(). + Str("action", "Checkout()"). + Str("stack", git.config.WorkingDir). + Msgf("Create new branch: %s.", rev) err := git.NewBranch(rev) if err != nil { return err } } + log.Trace(). + Str("action", "Checkout()"). + Str("stack", git.config.WorkingDir). + Msgf("Checkout: %s.", rev) _, err := git.exec("checkout", rev) return err } @@ -509,6 +666,10 @@ func (git *Git) Merge(branch string) error { return fmt.Errorf("Merge: %w", ErrDenyPorcelain) } + log.Trace(). + Str("action", "Merge()"). + Str("stack", git.config.WorkingDir). + Msgf("Merge: %s.", branch) _, err := git.exec("merge", "--no-ff", branch) return err } @@ -519,6 +680,10 @@ func (git *Git) Push(remote, branch string) error { return fmt.Errorf("Push: %w", ErrDenyPorcelain) } + log.Trace(). + Str("action", "Push()"). + Str("stack", git.config.WorkingDir). + Msgf("Push: %s to: %s.", branch, remote) _, err := git.exec("push", remote, branch) return err } @@ -529,6 +694,10 @@ func (git *Git) Pull(remote, branch string) error { return fmt.Errorf("Pull: %w", ErrDenyPorcelain) } + log.Trace(). + Str("action", "Pull()"). + Str("stack", git.config.WorkingDir). + Msgf("Pull from: %s to: %s.", remote, branch) _, err := git.exec("pull", remote, branch) return err } @@ -541,6 +710,10 @@ func (git *Git) FFMerge(branch string) error { return fmt.Errorf("FFMerge: %w", ErrDenyPorcelain) } + log.Trace(). + Str("action", "FFMerge()"). + Str("stack", git.config.WorkingDir). + Msgf("Fast forward merge branch: %s.", branch) _, err := git.exec("merge", "--ff", branch) return err } @@ -556,6 +729,10 @@ func (git *Git) ListUntracked(dirs ...string) ([]string, error) { args = append(args, dirs...) } + log.Trace(). + Str("action", "ListUntracked()"). + Str("stack", git.config.WorkingDir). + Msg("List untracked files.") out, err := git.exec("ls-files", args...) if err != nil { return nil, fmt.Errorf("ls-files: %w", err) @@ -576,6 +753,10 @@ func (git *Git) ListUncommitted(dirs ...string) ([]string, error) { args = append(args, dirs...) } + log.Trace(). + Str("action", "ListUncommitted()"). + Str("stack", git.config.WorkingDir). + Msg("List uncommitted files.") out, err := git.exec("ls-files", args...) if err != nil { return nil, fmt.Errorf("ls-files: %w", err) @@ -611,6 +792,13 @@ func (git *Git) CurrentBranch() (string, error) { } func (git *Git) exec(command string, args ...string) (string, error) { + logger := log.With(). + Str("action", "exec()"). + Str("stack", git.config.WorkingDir). + Logger() + + logger.Trace(). + Msg("Create cmd to execute.") cmd := exec.Cmd{ Path: git.config.ProgramPath, Args: []string{git.config.ProgramPath, command}, @@ -618,13 +806,19 @@ func (git *Git) exec(command string, args ...string) (string, error) { Env: []string{}, } + logger.Trace(). + Msg("Append arguments.") cmd.Args = append(cmd.Args, args...) if git.config.InheritEnv { + logger.Trace(). + Msg("Get environment.") cmd.Env = os.Environ() } if git.config.Isolated { + logger.Trace(). + Msg("Add git config environment variables.") cmd.Env = append(cmd.Env, "GIT_CONFIG_SYSTEM=/dev/null") cmd.Env = append(cmd.Env, "GIT_CONFIG_GLOBAL=/dev/null") cmd.Env = append(cmd.Env, "GIT_CONFIG_NOGLOBAL=1") // back-compat @@ -632,6 +826,8 @@ func (git *Git) exec(command string, args ...string) (string, error) { cmd.Env = append(cmd.Env, "GIT_ATTR_NOSYSTEM=1") } + logger.Trace(). + Msg("Run command.") stdout, err := cmd.Output() if err != nil { stderr := []byte{} @@ -703,6 +899,9 @@ func (r remoteSorter) Swap(i, j int) { } func removeEmptyLines(lines []string) []string { + log.Trace(). + Str("action", "removeEmptyLines()"). + Msg("Remove empty lines.") outlines := make([]string, 0, len(lines)) for _, line := range lines { line = strings.TrimSpace(line) From 945783ea23322aa0f704e2c8ee12e98d64481ccb Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 14:53:39 +1300 Subject: [PATCH 08/10] feat: add logging for project.go --- project/project.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/project/project.go b/project/project.go index 367851257..eaf38ca16 100644 --- a/project/project.go +++ b/project/project.go @@ -17,10 +17,16 @@ package project import ( "path/filepath" "strings" + + "github.com/rs/zerolog/log" ) // RelPath returns the dir relative to project's root. func RelPath(root, dir string) string { + log.Trace(). + Str("action", "RelPath()"). + Str("stack", root). + Msg("Trim path to get relative dir.") d := strings.TrimPrefix(dir, root) if d == "" { d = "/" @@ -36,11 +42,19 @@ func AbsPath(root, dir string) string { // FriendlyFmtDir formats the directory in a friendly way for tooling output. func FriendlyFmtDir(root, wd, dir string) (string, bool) { + log.Trace(). + Str("action", "FriendlyFmtDir()"). + Str("stack", wd). + Msg("Get relative path.") trimPart := RelPath(root, wd) if !strings.HasPrefix(dir, trimPart) { return "", false } + log.Trace(). + Str("action", "FriendlyFmtDir()"). + Str("stack", wd). + Msg("Friendly format.") dir = strings.TrimPrefix(dir, trimPart) if dir == "" { dir = "." From 26a4fd96e7c548004463d62cf86d5c0816b720f1 Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Tue, 4 Jan 2022 15:22:52 +1300 Subject: [PATCH 09/10] feat: add logging for loader.go --- stack/loader.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/stack/loader.go b/stack/loader.go index 20f4cde12..7f076ad94 100644 --- a/stack/loader.go +++ b/stack/loader.go @@ -24,6 +24,7 @@ import ( "github.com/mineiros-io/terramate/config" "github.com/mineiros-io/terramate/hcl" "github.com/mineiros-io/terramate/project" + "github.com/rs/zerolog/log" ) // Loader is a stack loader. @@ -43,12 +44,23 @@ func NewLoader(root string) Loader { // Load loads a stack from dir directory. If the stack was previously loaded, it // returns the cached one. func (l Loader) Load(dir string) (S, error) { + logger := log.With(). + Str("action", "Load()"). + Str("stack", dir). + Logger() + + logger.Trace(). + Msg("Get relative path to root directory.") stackpath := project.RelPath(l.root, dir) if s, ok := l.stacks[stackpath]; ok { return s, nil } fname := filepath.Join(dir, config.Filename) + + logger.Trace(). + Str("configFile", fname). + Msg("Parse config file.") cfg, err := hcl.ParseFile(fname) if err != nil { return S{}, err @@ -67,6 +79,8 @@ func (l Loader) Load(dir string) (S, error) { return S{}, fmt.Errorf("stack %q is not a leaf directory", dir) } + logger.Trace(). + Msg("Set stack path and stack config.") l.set(stackpath, cfg.Stack) return l.stacks[stackpath], nil } @@ -75,10 +89,18 @@ func (l Loader) Load(dir string) (S, error) { // only in the case that path contains a stack and it was correctly parsed. // It caches the stack for later use. func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { + logger := log.With(). + Str("action", "TryLoad()"). + Str("stack", dir). + Logger() + if !strings.HasPrefix(dir, l.root) { return S{}, false, fmt.Errorf("directory %q is not inside project root %q", dir, l.root) } + + logger.Trace(). + Msg("Get relative stack path to root directory.") stackpath := project.RelPath(l.root, dir) if s, ok := l.stacks[stackpath]; ok { return s, true, nil @@ -88,6 +110,10 @@ func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { return S{}, false, err } fname := filepath.Join(dir, config.Filename) + + logger.Trace(). + Str("configFile", fname). + Msg("Parse config file.") cfg, err := hcl.ParseFile(fname) if err != nil { @@ -107,6 +133,8 @@ func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { return S{}, false, fmt.Errorf("stack %q is not a leaf stack", dir) } + logger.Trace(). + Msg("Set stack path and stack config.") l.set(stackpath, cfg.Stack) return l.stacks[stackpath], true, nil } @@ -114,6 +142,13 @@ func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { // TryLoadChanged is like TryLoad but sets the stack as changed if loaded // successfully. func (l Loader) TryLoadChanged(root, dir string) (stack S, found bool, err error) { + logger := log.With(). + Str("action", "TryLoadChanged()"). + Str("stack", dir). + Logger() + + logger.Trace(). + Msgf("Try load: %s", dir) s, ok, err := l.TryLoad(dir) if ok { s.changed = true @@ -123,12 +158,20 @@ func (l Loader) TryLoadChanged(root, dir string) (stack S, found bool, err error func (l Loader) set(path string, block *hcl.Stack) { var name string + log.Trace(). + Str("action", "set()"). + Str("stack", path). + Msg("Set stack name.") if block.Name != "" { name = block.Name } else { name = filepath.Base(path) } + log.Trace(). + Str("action", "set()"). + Str("stack", path). + Msg("Set stack information.") l.stacks[path] = S{ name: name, Dir: path, @@ -145,14 +188,24 @@ func (l Loader) Set(dir string, s S) { // LoadAll loads all the stacks in the dirs directories. If dirs are relative // paths, then basedir is used as base. func (l Loader) LoadAll(root string, basedir string, dirs ...string) ([]S, error) { + logger := log.With(). + Str("action", "LoadAll()"). + Str("stack", root). + Logger() + stacks := []S{} absbase := filepath.Join(root, basedir) + logger.Trace(). + Msg("Range over directories.") for _, d := range dirs { if !filepath.IsAbs(d) { d = filepath.Join(absbase, d) } + + logger.Trace(). + Msgf("Load stack: %s.", d) stack, err := l.Load(d) if err != nil { return nil, err @@ -165,6 +218,10 @@ func (l Loader) LoadAll(root string, basedir string, dirs ...string) ([]S, error func (l Loader) IsLeafStack(dir string) (bool, error) { isValid := true + log.Trace(). + Str("action", "IsLeafStack()"). + Str("stack", dir). + Msg("Walk directory.") err := filepath.Walk( dir, func(path string, info fs.FileInfo, err error) error { @@ -182,6 +239,10 @@ func (l Loader) IsLeafStack(dir string) (bool, error) { return filepath.SkipDir } + log.Trace(). + Str("action", "IsLeafStack()"). + Str("stack", dir). + Msgf("Try load: %s", path) _, found, err := l.TryLoad(path) if err != nil { return err @@ -206,6 +267,10 @@ func (l Loader) lookupParentStack(dir string) (stack S, found bool, err error) { } d := filepath.Dir(dir) for { + log.Trace(). + Str("action", "lookupParentStack()"). + Str("stack", dir). + Msgf("Try load directory: %s.", d) stack, ok, err := l.TryLoad(d) if err != nil { return S{}, false, fmt.Errorf("looking for parent stacks: %w", err) @@ -219,6 +284,10 @@ func (l Loader) lookupParentStack(dir string) (stack S, found bool, err error) { break } + log.Trace(). + Str("action", "lookupParentStack()"). + Str("stack", dir). + Msg("Get git path.") gitpath := filepath.Join(d, ".git") if _, err := os.Stat(gitpath); err == nil { // if reached root of git project, abort scanning From ceb1a94b4ad9626a3338dcdd1a353ecb6fa55dfc Mon Sep 17 00:00:00 2001 From: Kassian Houben Date: Wed, 5 Jan 2022 23:49:22 +1300 Subject: [PATCH 10/10] chore: make msgf type messages context fields --- cmd/terramate/cli/cli.go | 40 +++++++++++----------- git/git.go | 72 ++++++++++++++++++++++++---------------- stack/loader.go | 28 +++++++++------- 3 files changed, 79 insertions(+), 61 deletions(-) diff --git a/cmd/terramate/cli/cli.go b/cmd/terramate/cli/cli.go index 8255a22d1..574f7cf37 100644 --- a/cmd/terramate/cli/cli.go +++ b/cmd/terramate/cli/cli.go @@ -314,11 +314,11 @@ func (c *cli) run() error { } } - logger.Trace(). + logger.Debug(). Msg("Handle input command.") switch c.ctx.Command() { case "version": - logger.Trace(). + logger.Debug(). Msg("Get terramate version.") c.log(terramate.Version()) case "plan graph": @@ -358,26 +358,26 @@ func (c *cli) run() error { Msg("Handle stacks global command.") return c.printStacksGlobals() case "run": - logger.Trace(). + logger.Debug(). Msg("Handle `run` command.") if len(c.parsedArgs.Run.Command) == 0 { return errors.New("no command specified") } fallthrough case "run ": - logger.Trace(). + logger.Debug(). Msg("Handle `run ` command.") return c.runOnStacks() case "generate": - logger.Trace(). + logger.Debug(). Msg("Handle `generate` command.") return generate.Do(c.root()) case "metadata": - logger.Trace(). + logger.Debug(). Msg("Handle `metadata` command.") return c.printMetadata() case "install-completions": - logger.Trace(). + logger.Debug(). Msg("Handle `install-completions` command.") return c.parsedArgs.InstallCompletions.Run(c.ctx) default: @@ -394,7 +394,7 @@ func (c *cli) initStack(dirs []string) error { Str("action", "initStack()"). Logger() - logger.Trace(). + logger.Debug(). Msg("Init stacks.") for _, d := range dirs { if !filepath.IsAbs(d) { @@ -404,7 +404,7 @@ func (c *cli) initStack(dirs []string) error { d = filepath.Join(c.wd(), d) } - log.Trace(). + log.Debug(). Str("stack", fmt.Sprintf("%s%s", c.wd(), strings.Trim(d, "."))). Msg("Init stack.") @@ -461,7 +461,7 @@ func (c *cli) printStacks() error { continue } - logger.Trace(). + logger.Debug(). Str("stack", c.wd()+stack.Dir). Msg("Print stack.") @@ -486,11 +486,11 @@ func (c *cli) generateGraph() error { Msg("Handle graph label command line argument.") switch c.parsedArgs.Plan.Graph.Label { case "stack.name": - logger.Trace(). + logger.Debug(). Msg("Set label to stack name.") getLabel = func(s stack.S) string { return s.Name() } case "stack.dir": - logger.Trace(). + logger.Debug(). Msg("Set label stack directory.") getLabel = func(s stack.S) string { return s.Dir } default: @@ -501,7 +501,7 @@ func (c *cli) generateGraph() error { return err } - logger.Trace(). + logger.Debug(). Msg("Create new graph.") loader := stack.NewLoader(c.root()) dotGraph := dot.NewGraph(dot.Directed) @@ -531,7 +531,7 @@ func (c *cli) generateGraph() error { } } - logger.Trace(). + logger.Debug(). Msg("Set output of graph.") outFile := c.parsedArgs.Plan.Graph.Outfile var out io.Writer @@ -552,7 +552,7 @@ func (c *cli) generateGraph() error { out = f } - logger.Trace(). + logger.Debug(). Msg("Write graph to output.") _, err = out.Write([]byte(dotGraph.String())) if err != nil { @@ -627,7 +627,7 @@ func (c *cli) printRunOrder() error { stacks[i] = e.Stack } - logger.Trace(). + logger.Debug(). Msg("Get run order.") order, reason, err := terramate.RunOrder(c.root(), stacks, c.parsedArgs.Changed) if err != nil { @@ -693,7 +693,7 @@ func (c *cli) printMetadata() error { c.log("Available metadata:") for _, stack := range metadata.Stacks { - logger.Trace(). + logger.Debug(). Str("stack", c.wd()+stack.Path). Msg("Print metadata for individual stack.") c.log("\nstack %q:", stack.Path) @@ -775,7 +775,7 @@ func (c *cli) runOnStacks() error { return nil } - logger.Trace(). + logger.Debug(). Msg("Run command.") err = terramate.Run(c.root(), order, cmd) if err != nil { @@ -925,7 +925,7 @@ func (c *cli) filterStacksByWorkingDir(stacks []terramate.Entry) []terramate.Ent } func newGit(basedir string, inheritEnv bool, checkrepo bool) (*git.Git, error) { - log.Trace(). + log.Debug(). Str("action", "newGit()"). Msg("Create new git wrapper providing config.") g, err := git.WithConfig(git.Config{ @@ -1036,7 +1036,7 @@ func (p *project) setDefaults(parsedArgs *cliSpec) error { p.rootcfg.Terramate = &hcl.Terramate{} } - logger.Trace(). + logger.Debug(). Str("configFile", p.root+"/terramate.tm.hcl"). Msg("Set defaults.") cfg := &p.rootcfg diff --git a/git/git.go b/git/git.go index 4fc8d0e40..8195490e0 100644 --- a/git/git.go +++ b/git/git.go @@ -114,7 +114,7 @@ func NewConfig(username, email string) Config { // NewConfigWithPath calls NewConfig but also sets the git program path. func NewConfigWithPath(username, email, programPath string) Config { - log.Trace(). + log.Debug(). Str("action", "NewConfigWithPath()"). Msg("Make new config.") config := NewConfig(username, email) @@ -220,7 +220,8 @@ func (git *Git) validate() error { Logger() logger.Trace(). - Msgf("Get path program path information for: %s.", cfg.ProgramPath) + Str("path", cfg.ProgramPath). + Msg("Get path program path information.") _, err := os.Stat(cfg.ProgramPath) if err != nil { return fmt.Errorf("failed to stat git program path \"%s\": %w: %v", @@ -241,7 +242,7 @@ func (git *Git) Version() (string, error) { Str("stack", git.config.WorkingDir). Logger() - logger.Trace(). + logger.Debug(). Msg("Get git version.") out, err := git.exec("version") if err != nil { @@ -353,7 +354,8 @@ func (git *Git) Remotes() ([]Remote, error) { Msg("Range over references.") for _, rawref := range strings.Split(res, "\n") { logger.Trace(). - Msgf("Format reference: %s.", rawref) + Str("reference", rawref). + Msg("Format reference.") trimmedref := strings.TrimPrefix(rawref, refprefix) parsed := strings.Split(trimmedref, "/") if len(parsed) < 2 { @@ -363,7 +365,8 @@ func (git *Git) Remotes() ([]Remote, error) { branch := strings.Join(parsed[1:], "/") branches := references[name] logger.Trace(). - Msgf("Append formatted reference to branches array: %s.", branch) + Str("reference", branch). + Msg("Append formatted reference to branches array.") references[name] = append(branches, branch) } @@ -445,7 +448,7 @@ func (git *Git) Add(files ...string) error { return fmt.Errorf("Add: %w", ErrDenyPorcelain) } - log.Trace(). + log.Debug(). Str("action", "Add()"). Str("stack", git.config.WorkingDir). Msg("Add file to current staged index.") @@ -480,7 +483,7 @@ func (git *Git) Commit(msg string, args ...string) error { vargs = append(vargs, args...) - logger.Trace(). + logger.Debug(). Msg("Commit with args.") _, err := git.exec("commit", vargs...) return err @@ -502,7 +505,7 @@ func (git *Git) FetchRemoteRev(remote, ref string) (Ref, error) { Str("stack", git.config.WorkingDir). Logger() - logger.Trace(). + logger.Debug(). Msg("List references in remote repository.") output, err := git.exec("ls-remote", remote, ref) if err != nil { @@ -583,7 +586,8 @@ func (git *Git) DiffNames(from, to string) ([]string, error) { log.Trace(). Str("action", "DiffNames()"). Str("stack", git.config.WorkingDir). - Msgf("Get tree differences from `%s` to `%s`.", from, to) + Str("reference", fmt.Sprintf("from `%s` to `%s`", from, to)). + Msg("Get tree differences.") diff, err := git.DiffTree(from, to, true, true, true) if err != nil { return nil, fmt.Errorf("diff-tree: %w", err) @@ -597,16 +601,18 @@ func (git *Git) NewBranch(name string) error { log.Trace(). Str("action", "NewBranch()"). Str("stack", git.config.WorkingDir). - Msgf("Get commit ID of: %s.", name) + Str("reference", name). + Msg("Get commit ID.") _, err := git.RevParse(name) if err == nil { return fmt.Errorf("branch \"%s\" already exists", name) } - log.Trace(). + log.Debug(). Str("action", "NewBranch()"). Str("stack", git.config.WorkingDir). - Msgf("Update ref: %s.", name) + Str("reference", name). + Msg("Create new branch.") _, err = git.exec("update-ref", "refs/heads/"+name, "HEAD") return err } @@ -616,16 +622,18 @@ func (git *Git) DeleteBranch(name string) error { log.Trace(). Str("action", "DeleteBranch()"). Str("stack", git.config.WorkingDir). - Msgf("Get commit ID of: %s.", name) + Str("reference", name). + Msg("Get commit ID.") _, err := git.RevParse(name) if err != nil { return fmt.Errorf("branch \"%s\" doesn't exist", name) } - log.Trace(). + log.Debug(). Str("action", "DeleteBranch()"). Str("stack", git.config.WorkingDir). - Msgf("Delete branch: %s.", name) + Str("reference", name). + Msg("Delete branch.") _, err = git.exec("update-ref", "-d", "refs/heads/"+name) return err } @@ -643,17 +651,19 @@ func (git *Git) Checkout(rev string, create bool) error { log.Trace(). Str("action", "Checkout()"). Str("stack", git.config.WorkingDir). - Msgf("Create new branch: %s.", rev) + Str("reference", rev). + Msg("Create new branch.") err := git.NewBranch(rev) if err != nil { return err } } - log.Trace(). + log.Debug(). Str("action", "Checkout()"). Str("stack", git.config.WorkingDir). - Msgf("Checkout: %s.", rev) + Str("reference", rev). + Msg("Checkout.") _, err := git.exec("checkout", rev) return err } @@ -666,10 +676,11 @@ func (git *Git) Merge(branch string) error { return fmt.Errorf("Merge: %w", ErrDenyPorcelain) } - log.Trace(). + log.Debug(). Str("action", "Merge()"). Str("stack", git.config.WorkingDir). - Msgf("Merge: %s.", branch) + Str("reference", branch). + Msg("Merge.") _, err := git.exec("merge", "--no-ff", branch) return err } @@ -680,10 +691,11 @@ func (git *Git) Push(remote, branch string) error { return fmt.Errorf("Push: %w", ErrDenyPorcelain) } - log.Trace(). + log.Debug(). Str("action", "Push()"). Str("stack", git.config.WorkingDir). - Msgf("Push: %s to: %s.", branch, remote) + Str("reference", fmt.Sprintf("from `%s` to `%s`", branch, remote)). + Msg("Git push.") _, err := git.exec("push", remote, branch) return err } @@ -694,10 +706,11 @@ func (git *Git) Pull(remote, branch string) error { return fmt.Errorf("Pull: %w", ErrDenyPorcelain) } - log.Trace(). + log.Debug(). Str("action", "Pull()"). Str("stack", git.config.WorkingDir). - Msgf("Pull from: %s to: %s.", remote, branch) + Str("reference", fmt.Sprintf("from `%s` to `%s`", remote, branch)). + Msg("Git pull.") _, err := git.exec("pull", remote, branch) return err } @@ -710,10 +723,11 @@ func (git *Git) FFMerge(branch string) error { return fmt.Errorf("FFMerge: %w", ErrDenyPorcelain) } - log.Trace(). + log.Debug(). Str("action", "FFMerge()"). Str("stack", git.config.WorkingDir). - Msgf("Fast forward merge branch: %s.", branch) + Str("reference", branch). + Msg("Fast forward merge branch.") _, err := git.exec("merge", "--ff", branch) return err } @@ -729,7 +743,7 @@ func (git *Git) ListUntracked(dirs ...string) ([]string, error) { args = append(args, dirs...) } - log.Trace(). + log.Debug(). Str("action", "ListUntracked()"). Str("stack", git.config.WorkingDir). Msg("List untracked files.") @@ -753,7 +767,7 @@ func (git *Git) ListUncommitted(dirs ...string) ([]string, error) { args = append(args, dirs...) } - log.Trace(). + log.Debug(). Str("action", "ListUncommitted()"). Str("stack", git.config.WorkingDir). Msg("List uncommitted files.") @@ -826,7 +840,7 @@ func (git *Git) exec(command string, args ...string) (string, error) { cmd.Env = append(cmd.Env, "GIT_ATTR_NOSYSTEM=1") } - logger.Trace(). + logger.Debug(). Msg("Run command.") stdout, err := cmd.Output() if err != nil { diff --git a/stack/loader.go b/stack/loader.go index 7f076ad94..8c35a07ff 100644 --- a/stack/loader.go +++ b/stack/loader.go @@ -58,7 +58,7 @@ func (l Loader) Load(dir string) (S, error) { fname := filepath.Join(dir, config.Filename) - logger.Trace(). + logger.Debug(). Str("configFile", fname). Msg("Parse config file.") cfg, err := hcl.ParseFile(fname) @@ -111,7 +111,7 @@ func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { } fname := filepath.Join(dir, config.Filename) - logger.Trace(). + logger.Debug(). Str("configFile", fname). Msg("Parse config file.") cfg, err := hcl.ParseFile(fname) @@ -133,7 +133,7 @@ func (l Loader) TryLoad(dir string) (stack S, found bool, err error) { return S{}, false, fmt.Errorf("stack %q is not a leaf stack", dir) } - logger.Trace(). + logger.Debug(). Msg("Set stack path and stack config.") l.set(stackpath, cfg.Stack) return l.stacks[stackpath], true, nil @@ -147,8 +147,9 @@ func (l Loader) TryLoadChanged(root, dir string) (stack S, found bool, err error Str("stack", dir). Logger() - logger.Trace(). - Msgf("Try load: %s", dir) + logger.Debug(). + Str("path", dir). + Msg("Try load.") s, ok, err := l.TryLoad(dir) if ok { s.changed = true @@ -158,7 +159,7 @@ func (l Loader) TryLoadChanged(root, dir string) (stack S, found bool, err error func (l Loader) set(path string, block *hcl.Stack) { var name string - log.Trace(). + log.Debug(). Str("action", "set()"). Str("stack", path). Msg("Set stack name.") @@ -190,7 +191,6 @@ func (l Loader) Set(dir string, s S) { func (l Loader) LoadAll(root string, basedir string, dirs ...string) ([]S, error) { logger := log.With(). Str("action", "LoadAll()"). - Str("stack", root). Logger() stacks := []S{} @@ -198,14 +198,16 @@ func (l Loader) LoadAll(root string, basedir string, dirs ...string) ([]S, error absbase := filepath.Join(root, basedir) logger.Trace(). + Str("stack", root). Msg("Range over directories.") for _, d := range dirs { if !filepath.IsAbs(d) { d = filepath.Join(absbase, d) } - logger.Trace(). - Msgf("Load stack: %s.", d) + logger.Debug(). + Str("stack", d). + Msg("Load stack.") stack, err := l.Load(d) if err != nil { return nil, err @@ -242,7 +244,8 @@ func (l Loader) IsLeafStack(dir string) (bool, error) { log.Trace(). Str("action", "IsLeafStack()"). Str("stack", dir). - Msgf("Try load: %s", path) + Str("path", path). + Msg("Try load.") _, found, err := l.TryLoad(path) if err != nil { return err @@ -267,10 +270,11 @@ func (l Loader) lookupParentStack(dir string) (stack S, found bool, err error) { } d := filepath.Dir(dir) for { - log.Trace(). + log.Debug(). Str("action", "lookupParentStack()"). Str("stack", dir). - Msgf("Try load directory: %s.", d) + Str("path", d). + Msg("Try load directory.") stack, ok, err := l.TryLoad(d) if err != nil { return S{}, false, fmt.Errorf("looking for parent stacks: %w", err)