diff --git a/cli/options.go b/cli/options.go index 69ea5654..a8ba9cc5 100644 --- a/cli/options.go +++ b/cli/options.go @@ -18,13 +18,14 @@ package cli import ( "context" + "fmt" "io" + "log/slog" "os" "path/filepath" "strconv" "strings" - "github.com/sirupsen/logrus" "go.yaml.in/yaml/v4" "github.com/compose-spec/compose-go/v2/consts" @@ -165,16 +166,16 @@ func WithDefaultConfigPath(o *ProjectOptions) error { if len(candidates) > 0 { winner := candidates[0] if len(candidates) > 1 { - logrus.Warnf("Found multiple config files with supported names: %s", strings.Join(candidates, ", ")) - logrus.Warnf("Using %s", winner) + slog.Warn(fmt.Sprintf("Found multiple config files with supported names: %s", strings.Join(candidates, ", "))) + slog.Warn(fmt.Sprintf("Using %s", winner)) } o.ConfigPaths = append(o.ConfigPaths, winner) overrides := findFiles(DefaultOverrideFileNames, pwd) if len(overrides) > 0 { if len(overrides) > 1 { - logrus.Warnf("Found multiple override files with supported names: %s", strings.Join(overrides, ", ")) - logrus.Warnf("Using %s", overrides[0]) + slog.Warn(fmt.Sprintf("Found multiple override files with supported names: %s", strings.Join(overrides, ", "))) + slog.Warn(fmt.Sprintf("Using %s", overrides[0])) } o.ConfigPaths = append(o.ConfigPaths, overrides[0]) } @@ -533,7 +534,7 @@ func withNamePrecedenceLoad(absWorkingDir string, namedInYaml bool, options *Pro dirname := filepath.Base(absWorkingDir) symlink, err := filepath.EvalSymlinks(absWorkingDir) if err == nil && filepath.Base(symlink) != dirname { - logrus.Warnf("project has been loaded without an explicit name from a symlink. Using name %q", dirname) + slog.Warn(fmt.Sprintf("project has been loaded without an explicit name from a symlink. Using name %q", dirname)) } opts.SetProjectName( loader.NormalizeProjectName(dirname), diff --git a/go.mod b/go.mod index 80abf2c8..ab51328c 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/mattn/go-shellwords v1.0.12 github.com/opencontainers/go-digest v1.0.0 github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 - github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.4 github.com/xhit/go-str2duration/v2 v2.1.0 go.yaml.in/yaml/v4 v4.0.0-rc.4 @@ -23,6 +22,5 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.5.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b921dc5f..a877567b 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= @@ -22,10 +21,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= @@ -48,9 +43,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -64,7 +56,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= diff --git a/loader/interpolate.go b/loader/interpolate.go index dc8dc735..01794f32 100644 --- a/loader/interpolate.go +++ b/loader/interpolate.go @@ -18,12 +18,12 @@ package loader import ( "fmt" + "log/slog" "strconv" "strings" interp "github.com/compose-spec/compose-go/v2/interpolation" "github.com/compose-spec/compose-go/v2/tree" - "github.com/sirupsen/logrus" ) var interpolateTypeCastMapping = map[tree.Path]interp.Cast{ @@ -107,10 +107,10 @@ func toBoolean(value string) (interface{}, error) { case "false": return false, nil case "y", "yes", "on": - logrus.Warnf("%q for boolean is not supported by YAML 1.2, please use `true`", value) + slog.Warn(fmt.Sprintf("%q for boolean is not supported by YAML 1.2, please use `true`", value)) return true, nil case "n", "no", "off": - logrus.Warnf("%q for boolean is not supported by YAML 1.2, please use `false`", value) + slog.Warn(fmt.Sprintf("%q for boolean is not supported by YAML 1.2, please use `false`", value)) return false, nil default: return nil, fmt.Errorf("invalid boolean: %s", value) diff --git a/loader/loader.go b/loader/loader.go index 1baa57b9..2fc0c204 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -42,7 +42,8 @@ import ( "github.com/compose-spec/compose-go/v2/types" "github.com/compose-spec/compose-go/v2/validation" "github.com/go-viper/mapstructure/v2" - "github.com/sirupsen/logrus" + "log/slog" + "go.yaml.in/yaml/v4" ) @@ -90,7 +91,7 @@ var versionWarning []string func (o *Options) warnObsoleteVersion(file string) { if !slices.Contains(versionWarning, file) { - logrus.Warning(fmt.Sprintf("%s: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion", file)) + slog.Warn(fmt.Sprintf("%s: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion", file)) } versionWarning = append(versionWarning, file) } @@ -120,7 +121,7 @@ func (o Options) RemoteResourceLoaders() []ResourceLoader { for i, loader := range o.ResourceLoaders { if _, ok := loader.(localResourceLoader); ok { if i != len(o.ResourceLoaders)-1 { - logrus.Warning("misconfiguration of ResourceLoaders: localResourceLoader should be last") + slog.Warn("misconfiguration of ResourceLoaders: localResourceLoader should be last") } continue } diff --git a/loader/loader_test.go b/loader/loader_test.go index 3c7a83c5..cd142982 100644 --- a/loader/loader_test.go +++ b/loader/loader_test.go @@ -20,6 +20,7 @@ import ( "bytes" "context" "fmt" + "log/slog" "os" "path/filepath" "strings" @@ -27,7 +28,6 @@ import ( "time" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/sirupsen/logrus" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -1453,7 +1453,7 @@ services: } func TestLoadVolumesWarnOnDeprecatedExternalName(t *testing.T) { - buf, cleanup := patchLogrus() + buf, cleanup := patchSlog() defer cleanup() project, err := loadYAML(` @@ -1474,11 +1474,12 @@ volumes: assert.Check(t, is.Contains(buf.String(), "volumes.foo: external.name is deprecated. Please set name and external: true")) } -func patchLogrus() (*bytes.Buffer, func()) { +func patchSlog() (*bytes.Buffer, func()) { buf := new(bytes.Buffer) - out := logrus.StandardLogger().Out - logrus.SetOutput(buf) - return buf, func() { logrus.SetOutput(out) } + handler := slog.NewTextHandler(buf, &slog.HandlerOptions{Level: slog.LevelWarn}) + old := slog.Default() + slog.SetDefault(slog.New(handler)) + return buf, func() { slog.SetDefault(old) } } func TestLoadInvalidIsolation(t *testing.T) { @@ -1512,7 +1513,7 @@ secrets: } func TestLoadSecretsWarnOnDeprecatedExternalName(t *testing.T) { - buf, cleanup := patchLogrus() + buf, cleanup := patchSlog() defer cleanup() project, err := loadYAML(` @@ -1534,7 +1535,7 @@ secrets: } func TestLoadNetworksWarnOnDeprecatedExternalName(t *testing.T) { - buf, cleanup := patchLogrus() + buf, cleanup := patchSlog() defer cleanup() project, err := loadYAML(` diff --git a/paths/home.go b/paths/home.go index a5579262..9769539f 100644 --- a/paths/home.go +++ b/paths/home.go @@ -17,18 +17,17 @@ package paths import ( + "log/slog" "os" "path/filepath" "strings" - - "github.com/sirupsen/logrus" ) func ExpandUser(p string) string { if strings.HasPrefix(p, "~") { home, err := os.UserHomeDir() if err != nil { - logrus.Warn("cannot expand '~', because the environment lacks HOME") + slog.Warn("cannot expand '~', because the environment lacks HOME") return p } return filepath.Join(home, p[1:]) diff --git a/template/template.go b/template/template.go index beb61ed8..aa05e69e 100644 --- a/template/template.go +++ b/template/template.go @@ -19,11 +19,10 @@ package template import ( "errors" "fmt" + "log/slog" "regexp" "sort" "strings" - - "github.com/sirupsen/logrus" ) const ( @@ -206,7 +205,7 @@ func DefaultReplacementAppliedFunc(substring string, mapping Mapping, cfg *Confi value, ok := mapping(substitution) if !ok && cfg.logging { - logrus.Warnf("The %q variable is not set. Defaulting to a blank string.", substitution) + slog.Warn(fmt.Sprintf("The %q variable is not set. Defaulting to a blank string.", substitution)) } return value, ok, nil diff --git a/template/template_test.go b/template/template_test.go index 6d6243a4..2bde3db7 100644 --- a/template/template_test.go +++ b/template/template_test.go @@ -17,13 +17,13 @@ package template import ( + "context" "fmt" - "io" + "log/slog" "reflect" + "sync" "testing" - "github.com/sirupsen/logrus" - logrustest "github.com/sirupsen/logrus/hooks/test" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) @@ -568,20 +568,30 @@ func TestValueWithCurlyBracesDefault(t *testing.T) { } } -func captureWarnings(t *testing.T) (*logrustest.Hook, func()) { +type logCapture struct { + mu sync.Mutex + entries []slog.Record +} + +func (c *logCapture) Enabled(_ context.Context, _ slog.Level) bool { return true } +func (c *logCapture) Handle(_ context.Context, r slog.Record) error { + c.mu.Lock() + c.entries = append(c.entries, r) + c.mu.Unlock() + return nil +} +func (c *logCapture) WithAttrs(_ []slog.Attr) slog.Handler { return c } +func (c *logCapture) WithGroup(_ string) slog.Handler { return c } +func (c *logCapture) AllEntries() []slog.Record { + c.mu.Lock() + defer c.mu.Unlock() + return c.entries +} + +func captureWarnings(t *testing.T) (*logCapture, func()) { t.Helper() - logger := logrus.StandardLogger() - oldLevel := logger.Level - oldOut := logger.Out - oldHooks := logger.ReplaceHooks(make(logrus.LevelHooks)) - - logger.SetLevel(logrus.WarnLevel) - logger.SetOutput(io.Discard) - - hook := logrustest.NewGlobal() - return hook, func() { - logger.ReplaceHooks(oldHooks) - logger.SetOutput(oldOut) - logger.SetLevel(oldLevel) - } + capture := &logCapture{} + old := slog.Default() + slog.SetDefault(slog.New(capture)) + return capture, func() { slog.SetDefault(old) } } diff --git a/transform/external.go b/transform/external.go index be718f03..6ed9adcf 100644 --- a/transform/external.go +++ b/transform/external.go @@ -18,9 +18,9 @@ package transform import ( "fmt" + "log/slog" "github.com/compose-spec/compose-go/v2/tree" - "github.com/sirupsen/logrus" ) func transformMaybeExternal(data any, p tree.Path, ignoreParseError bool) (any, error) { @@ -37,7 +37,7 @@ func transformMaybeExternal(data any, p tree.Path, ignoreParseError bool) (any, if external, ok := ext.(map[string]any); ok { resource["external"] = true if extname, extNamed := external["name"]; extNamed { - logrus.Warnf("%s: external.name is deprecated. Please set name and external: true", p) + slog.Warn(fmt.Sprintf("%s: external.name is deprecated. Please set name and external: true", p)) if named && extname != name { return nil, fmt.Errorf("%s: name and external.name conflict; only use name", p) }