diff --git a/Dockerfile b/Dockerfile index 866693ac65..de129e59dd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.25-alpine AS builder +FROM golang:1.26-alpine AS builder RUN apk --no-cache add gcc musl-dev diff --git a/README.md b/README.md index 6b1cec62ef..09624cee0c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Ofelia - a job scheduler [![GitHub version](https://badge.fury.io/gh/mcuadros%2Fofelia.svg)](https://github.com/mcuadros/ofelia/releases) ![Test](https://github.com/mcuadros/ofelia/workflows/Test/badge.svg) +# Ofelia - a job scheduler [![GitHub version](https://img.shields.io/github/v/release/mcuadros/ofelia?&sort=semver&display_name=release&label=stable&color=green)](https://github.com/mcuadros/ofelia/releases) [![GitHub version](https://img.shields.io/github/v/release/mcuadros/ofelia?include_prereleases&sort=semver&display_name=release&label=edge)](https://github.com/mcuadros/ofelia/releases) ![Test](https://github.com/mcuadros/ofelia/workflows/Test/badge.svg) @@ -144,6 +144,75 @@ services: ``` +#### Docker host configuration + +By default, **Ofelia** connects to the Docker daemon via the default socket (`/var/run/docker.sock` on Linux). However, you can configure it to connect to a different Docker host using environment variables. This is particularly useful when: +- Using a Docker socket proxy for security +- Connecting to a remote Docker daemon +- Using Docker over TCP + +**Ofelia** supports the following Docker environment variables: +- `DOCKER_HOST` - The Docker host to connect to (e.g., `tcp://docker-proxy:2375`, `unix:///custom/docker.sock`) +- `DOCKER_TLS_VERIFY` - Enable TLS verification (set to `1` to enable) +- `DOCKER_CERT_PATH` - Path to TLS certificates directory +- `DOCKER_API_VERSION` - Docker API version to use + +##### Using with a socket proxy + +```sh +docker run -it --rm \ + -e DOCKER_HOST=tcp://docker-proxy:2375 \ + --label ofelia.job-local.my-test-job.schedule="@every 5s" \ + --label ofelia.job-local.my-test-job.command="date" \ + mcuadros/ofelia:latest daemon --docker +``` + +Or with docker-compose: + +```yaml +version: "3" +services: + docker-proxy: + image: tecnativa/docker-socket-proxy + environment: + CONTAINERS: 1 + SERVICES: 1 + TASKS: 1 + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + + ofelia: + image: mcuadros/ofelia:latest + depends_on: + - docker-proxy + - nginx + command: daemon --docker + environment: + DOCKER_HOST: tcp://docker-proxy:2375 + labels: + ofelia.job-local.my-test-job.schedule: "@every 5s" + ofelia.job-local.my-test-job.command: "date" + + nginx: + image: nginx + labels: + ofelia.enabled: "true" + ofelia.job-exec.datecron.schedule: "@every 5s" + ofelia.job-exec.datecron.command: "uname -a" +``` + +##### Using with TLS + +```sh +docker run -it --rm \ + -e DOCKER_HOST=tcp://docker.example.com:2376 \ + -e DOCKER_TLS_VERIFY=1 \ + -e DOCKER_CERT_PATH=/certs \ + -v /path/to/certs:/certs:ro \ + mcuadros/ofelia:latest daemon --config=/path/to/config.ini +``` + + ### Logging **Ofelia** comes with three different logging drivers: - `mail` to send mails diff --git a/cli/config.go b/cli/config.go index c60ab47bb1..590e7a7c4f 100644 --- a/cli/config.go +++ b/cli/config.go @@ -150,7 +150,7 @@ func (c *Config) dockerLabelsUpdate(labels map[string]map[string]string) { newJob.Client = c.dockerHandler.GetInternalDockerClient() newJob.Name = newJobsName if newJob.Hash() != j.Hash() { - c.logger.Debugf("Job %s has changed, restarting", name) + c.logger.Debug("Job has changed, restarting", "job", name) // Remove from the scheduler c.sh.RemoveJob(j) // Add the job back to the scheduler @@ -163,7 +163,7 @@ func (c *Config) dockerLabelsUpdate(labels map[string]map[string]string) { } } if !found { - c.logger.Debugf("Job %s is not found, Removing", name) + c.logger.Debug("Job not found, Removing", "job", name) // Remove the job c.sh.RemoveJob(j) delete(c.ExecJobs, name) diff --git a/cli/config_test.go b/cli/config_test.go index 140e176009..3b846369bb 100644 --- a/cli/config_test.go +++ b/cli/config_test.go @@ -19,11 +19,10 @@ var _ = Suite(&SuiteConfig{}) type TestLogger struct{} -func (*TestLogger) Criticalf(format string, args ...interface{}) {} -func (*TestLogger) Debugf(format string, args ...interface{}) {} -func (*TestLogger) Errorf(format string, args ...interface{}) {} -func (*TestLogger) Noticef(format string, args ...interface{}) {} -func (*TestLogger) Warningf(format string, args ...interface{}) {} +func (*TestLogger) Debug(format string, args ...interface{}) {} +func (*TestLogger) Error(format string, args ...interface{}) {} +func (*TestLogger) Info(format string, args ...interface{}) {} +func (*TestLogger) Warning(format string, args ...interface{}) {} func (s *SuiteConfig) TestBuildFromString(c *C) { conf, err := BuildFromString(` diff --git a/cli/daemon.go b/cli/daemon.go index 804db929ee..8f2dc8dd44 100644 --- a/cli/daemon.go +++ b/cli/daemon.go @@ -44,14 +44,14 @@ func (c *DaemonCommand) boot() (err error) { if !c.DockerLabelConfig { return fmt.Errorf("can't read the config file: %w", err) } else { - c.Logger.Debugf("Config file %v not found. Proceeding to read docker labels...", c.ConfigFile) + c.Logger.Debug("Config file not found. Proceeding to read docker labels...", "config", c.ConfigFile) } } else { - msg := "Found config file %v" + msg := "Found config file" if c.DockerLabelConfig { msg += ". Proceeding to read docker labels as well..." } - c.Logger.Debugf(msg, c.ConfigFile) + c.Logger.Debug(msg, "config", c.ConfigFile) } scheduler := core.NewScheduler(c.Logger) @@ -91,9 +91,7 @@ func (c *DaemonCommand) setSignals() { go func() { sig := <-c.signals - c.Logger.Warningf( - "Signal received: %s, shutting down the process\n", sig, - ) + c.Logger.Warning("Shutting down the process", "signal", sig.String()) c.done <- true }() @@ -105,6 +103,6 @@ func (c *DaemonCommand) shutdown() error { return nil } - c.Logger.Warningf("Waiting running jobs.") + c.Logger.Warning("Waiting for running jobs.") return c.scheduler.Stop() } diff --git a/cli/docker_handler.go b/cli/docker_handler.go index 2ae886a12f..be4ffada69 100644 --- a/cli/docker_handler.go +++ b/cli/docker_handler.go @@ -88,14 +88,14 @@ func (c *DockerHandler) ConfigFromLabelsEnabled() bool { func (c *DockerHandler) watch() { const pollInterval = 10 * time.Second - c.logger.Debugf("Watching for Docker labels changes every %s...", pollInterval) + c.logger.Debug("Watching for Docker labels changes...", "interval", pollInterval) ticker := time.NewTicker(pollInterval) defer ticker.Stop() for range ticker.C { labels, err := c.GetDockerLabels() // Do not print or care if there is no container up right now if err != nil && !errors.Is(err, errNoContainersMatchingFilters) { - c.logger.Debugf("%v", err) + c.logger.Debug("failed to get Docker labels", "error", err) } c.notifier.dockerLabelsUpdate(labels) } @@ -109,20 +109,20 @@ func (c *DockerHandler) WaitForLabels() { // Check if .dockerenv file exists if _, err := os.Stat(dockerEnvFile); os.IsNotExist(err) { - c.logger.Debugf(".dockerenv file not found, ofelia is not running in a Docker container") + c.logger.Debug(".dockerenv file not found, ofelia is not running in a Docker container") return } id, err := getContainerID(mountinfoFilePath) if err != nil { - c.logger.Debugf("Failed to extract ofelia's container ID. Trying with container hostname instead...") + c.logger.Debug("Failed to extract ofelia's container ID. Trying with container hostname instead...") id, _ = os.Hostname() } for attempt := 0; attempt < maxRetries; attempt++ { _, err := c.dockerClient.InspectContainerWithOptions(docker.InspectContainerOptions{ID: id}) if err == nil { - c.logger.Debugf("Found ofelia container with ID: %s", id) + c.logger.Debug("Found ofelia container", "container_id", id) return } diff --git a/cli/validate.go b/cli/validate.go index 23ba2fb6b3..19905a8e7d 100644 --- a/cli/validate.go +++ b/cli/validate.go @@ -12,14 +12,14 @@ type ValidateCommand struct { // Execute runs the validation command func (c *ValidateCommand) Execute(args []string) error { - c.Logger.Debugf("Validating %q ... ", c.ConfigFile) + c.Logger.Debug("Validating config... ", "config", c.ConfigFile) config, err := BuildFromFile(c.ConfigFile, c.Logger) if err != nil { - c.Logger.Errorf("ERROR") + c.Logger.Error("Failed to validate config", "config", c.ConfigFile, "error", err) return err } - c.Logger.Noticef("OK. Found %d jobs.", config.JobsCount()) + c.Logger.Info("OK", "jobs_count", config.JobsCount()) return nil } diff --git a/core/common.go b/core/common.go index 32bdb54d3d..2eb4e06b12 100644 --- a/core/common.go +++ b/core/common.go @@ -24,7 +24,6 @@ var ( const ( // maximum size of a stdout/stderr stream to be kept in memory and optional stored/sent via mail maxStreamSize = 10 * 1024 * 1024 - logPrefix = "[Job %q (%s)] %s" ) type Job interface { @@ -115,22 +114,22 @@ func (c *Context) Stop(err error) { c.Job.NotifyStop() } -func (c *Context) Log(msg string) { - args := []interface{}{c.Job.GetName(), c.Execution.ID, msg} +func (c *Context) Log(msg string, args ...any) { + defaultArgs := []any{"job", c.Job.GetName(), "execution", c.Execution.ID} switch { case c.Execution.Failed: - c.Logger.Errorf(logPrefix, args...) + c.Logger.Error(msg, append(defaultArgs, args...)...) case c.Execution.Skipped: - c.Logger.Warningf(logPrefix, args...) + c.Logger.Warning(msg, append(defaultArgs, args...)...) default: - c.Logger.Noticef(logPrefix, args...) + c.Logger.Info(msg, append(defaultArgs, args...)...) } } -func (c *Context) Warn(msg string) { - args := []interface{}{c.Job.GetName(), c.Execution.ID, msg} - c.Logger.Warningf(logPrefix, args...) +func (c *Context) Warn(msg string, args ...any) { + defaultArgs := []any{"job", c.Job.GetName(), "execution", c.Execution.ID} + c.Logger.Warning(msg, append(defaultArgs, args...)...) } // Execution contains all the information relative to a Job execution. @@ -225,11 +224,10 @@ func (c *middlewareContainer) Middlewares() []Middleware { } type Logger interface { - Criticalf(format string, args ...interface{}) - Debugf(format string, args ...interface{}) - Errorf(format string, args ...interface{}) - Noticef(format string, args ...interface{}) - Warningf(format string, args ...interface{}) + Debug(str string, args ...any) + Error(str string, args ...any) + Info(str string, args ...any) + Warning(str string, args ...any) } func randomID() string { @@ -244,7 +242,7 @@ func randomID() string { func buildFindLocalImageOptions(image string) docker.ListImagesOptions { return docker.ListImagesOptions{ Filters: map[string][]string{ - "reference": []string{image}, + "reference": {image}, }, } } diff --git a/core/common_test.go b/core/common_test.go index ba762fd4af..e9d8ac3d50 100644 --- a/core/common_test.go +++ b/core/common_test.go @@ -311,11 +311,10 @@ func (j *TestJob) Run(ctx *Context) error { type TestLogger struct{} -func (*TestLogger) Criticalf(format string, args ...interface{}) {} -func (*TestLogger) Debugf(format string, args ...interface{}) {} -func (*TestLogger) Errorf(format string, args ...interface{}) {} -func (*TestLogger) Noticef(format string, args ...interface{}) {} -func (*TestLogger) Warningf(format string, args ...interface{}) {} +func (*TestLogger) Debug(format string, args ...any) {} +func (*TestLogger) Error(format string, args ...any) {} +func (*TestLogger) Info(format string, args ...any) {} +func (*TestLogger) Warning(format string, args ...any) {} func (s *SuiteCommon) TestParseRegistry(c *C) { c.Assert(parseRegistry("example.com:port/dir/image"), Equals, "example.com:port") diff --git a/core/cron_utils.go b/core/cron_utils.go index 5f71dec4fb..e236f0464f 100644 --- a/core/cron_utils.go +++ b/core/cron_utils.go @@ -1,9 +1,5 @@ package core -import ( - "log/slog" -) - // Implement the cron logger interface type CronUtils struct { Logger Logger @@ -13,23 +9,10 @@ func NewCronUtils(l Logger) *CronUtils { return &CronUtils{Logger: l} } -func formatKeysAndValues(keysAndValues ...interface{}) string { - r := slog.Record{} - r.Add(keysAndValues...) - - attrs := []slog.Attr{} - r.Attrs(func(a slog.Attr) bool { - attrs = append(attrs, a) - return true - }) - - return slog.GroupValue(attrs...).String() -} - -func (c *CronUtils) Info(msg string, keysAndValues ...interface{}) { - c.Logger.Debugf("%v", formatKeysAndValues(append([]interface{}{"cron", msg}, keysAndValues...)...)) +func (c *CronUtils) Info(msg string, keysAndValues ...any) { + c.Logger.Debug("cron update", append(keysAndValues, "cron", msg)...) } func (c *CronUtils) Error(err error, msg string, keysAndValues ...interface{}) { - c.Logger.Errorf("%v", formatKeysAndValues(append([]interface{}{"cron", msg, "error", err}, keysAndValues...)...)) + c.Logger.Error("cron error", append(keysAndValues, "cron", msg, "error", err)...) } diff --git a/core/logger.go b/core/logger.go new file mode 100644 index 0000000000..12f20d4165 --- /dev/null +++ b/core/logger.go @@ -0,0 +1,50 @@ +package core + +import ( + "io" + "log/slog" + "os" + "strconv" + + "github.com/lmittmann/tint" +) + +type SlogLogger struct { + logger *slog.Logger +} + +func NewSlogLogger(w io.Writer) Logger { + var logLevel slog.Level + l := os.Getenv("LOG_LEVEL") + if err := logLevel.UnmarshalText([]byte(l)); err != nil { + logLevel = slog.LevelInfo + } + + return &SlogLogger{ + logger: slog.New(tint.NewHandler(w, &tint.Options{ + Level: logLevel, + AddSource: false, + NoColor: func() bool { + res, _ := strconv.ParseBool(os.Getenv("LOG_NO_COLOR")) + return res + }(), + })), + } + +} + +func (l *SlogLogger) Debug(str string, args ...any) { + l.logger.Debug(str, args...) +} + +func (l *SlogLogger) Error(str string, args ...any) { + l.logger.Error(str, args...) +} + +func (l *SlogLogger) Info(str string, args ...any) { + l.logger.Info(str, args...) +} + +func (l *SlogLogger) Warning(str string, args ...any) { + l.logger.Warn(str, args...) +} diff --git a/core/runjob.go b/core/runjob.go index 6022c51c86..877d182e0b 100644 --- a/core/runjob.go +++ b/core/runjob.go @@ -57,7 +57,7 @@ func (j *RunJob) Run(ctx *Context) error { // try pulling image first if pull { if pullError = j.pullImage(); pullError == nil { - ctx.Log("Pulled image " + j.Image) + ctx.Logger.Debug("Pulled new image", "image", j.Image, "pull", pull) return nil } } @@ -66,14 +66,14 @@ func (j *RunJob) Run(ctx *Context) error { // try to find image locally first searchErr := j.searchLocalImage() if searchErr == nil { - ctx.Log("Found locally image " + j.Image) + ctx.Logger.Debug("Found image locally", "image", j.Image, "pull", pull) return nil } // if couldn't find image locally, still try to pull if !pull && searchErr == ErrLocalImageNotFound { if pullError = j.pullImage(); pullError == nil { - ctx.Log("Pulled image " + j.Image) + ctx.Logger.Debug("Pulled new image", "image", j.Image, "pull", pull) return nil } } diff --git a/core/runjob_test.go b/core/runjob_test.go index 802d0feb01..da80ef50e6 100644 --- a/core/runjob_test.go +++ b/core/runjob_test.go @@ -3,11 +3,11 @@ package core import ( "archive/tar" "bytes" + "io" "time" docker "github.com/fsouza/go-dockerclient" "github.com/fsouza/go-dockerclient/testing" - logging "github.com/op/go-logging" . "gopkg.in/check.v1" ) @@ -47,8 +47,7 @@ func (s *SuiteRunJob) TestRun(c *C) { ctx := &Context{} ctx.Execution = NewExecution() - logging.SetFormatter(logging.MustStringFormatter(logFormat)) - ctx.Logger = logging.MustGetLogger("ofelia") + ctx.Logger = NewSlogLogger(io.Discard) ctx.Job = job go func() { diff --git a/core/runservice.go b/core/runservice.go index 6c11344b65..88b8648668 100644 --- a/core/runservice.go +++ b/core/runservice.go @@ -42,7 +42,7 @@ func (j *RunServiceJob) Run(ctx *Context) error { return err } - ctx.Logger.Noticef("Created service %s for job %s\n", svc.ID, j.Name) + ctx.Logger.Info("Created new service", "id", svc.ID, "job", j.Name) if err := j.watchContainer(ctx, svc.ID); err != nil { return err @@ -113,7 +113,7 @@ var svcChecker = time.NewTicker(watchDuration) func (j *RunServiceJob) watchContainer(ctx *Context, svcID string) error { exitCode := swarmError - ctx.Logger.Noticef("Checking for service ID %s (%s) termination\n", svcID, j.Name) + ctx.Logger.Info("Checking for service termination", "id", svcID, "job", j.Name) svc, err := j.Client.InspectService(svcID) if err != nil { @@ -144,7 +144,7 @@ func (j *RunServiceJob) watchContainer(ctx *Context, svcID string) error { wg.Wait() - ctx.Logger.Noticef("Service ID %s (%s) has completed with exit code %d\n", svcID, j.Name, exitCode) + ctx.Logger.Info("Service has completed", "id", svcID, "job", j.Name, "exit_code", exitCode) return err } @@ -157,7 +157,7 @@ func (j *RunServiceJob) findtaskstatus(ctx *Context, taskID string) (int, bool) }) if err != nil { - ctx.Logger.Errorf("Failed to find task ID %s. Considering the task terminated: %s\n", taskID, err.Error()) + ctx.Logger.Error("Failed to find task ID. Considering the task terminated.", "id", taskID, "error", err) return 0, false } @@ -208,8 +208,8 @@ func (j *RunServiceJob) deleteService(ctx *Context, svcID string) error { }) if _, is := err.(*docker.NoSuchService); is { - ctx.Logger.Warningf("Service %s cannot be removed. An error may have happened, "+ - "or it might have been removed by another process", svcID) + ctx.Logger.Warning("Service cannot be removed. An error may have happened, "+ + "or it might have been removed by another process", "id", svcID) return nil } diff --git a/core/runservice_test.go b/core/runservice_test.go index a4dfb2050e..c4e0ed1d18 100644 --- a/core/runservice_test.go +++ b/core/runservice_test.go @@ -4,6 +4,7 @@ import ( "archive/tar" "bytes" "fmt" + "io" "strings" "sync" "time" @@ -11,7 +12,6 @@ import ( "github.com/docker/docker/api/types/swarm" docker "github.com/fsouza/go-dockerclient" "github.com/fsouza/go-dockerclient/testing" - logging "github.com/op/go-logging" . "gopkg.in/check.v1" ) @@ -25,16 +25,12 @@ type SuiteRunServiceJob struct { var _ = Suite(&SuiteRunServiceJob{}) -const logFormat = "%{color}%{shortfile} ▶ %{level}%{color:reset} %{message}" - var logger Logger func (s *SuiteRunServiceJob) SetUpTest(c *C) { var err error - logging.SetFormatter(logging.MustStringFormatter(logFormat)) - - logger = logging.MustGetLogger("ofelia") + logger = NewSlogLogger(io.Discard) s.server, err = testing.NewServer("127.0.0.1:0", nil, nil) c.Assert(err, IsNil) diff --git a/core/scheduler.go b/core/scheduler.go index 1d058fbec7..83782ed52e 100644 --- a/core/scheduler.go +++ b/core/scheduler.go @@ -2,7 +2,6 @@ package core import ( "errors" - "fmt" "sync" "github.com/robfig/cron/v3" @@ -45,18 +44,18 @@ func (s *Scheduler) AddJob(j Job) error { id, err := s.cron.AddJob(j.GetSchedule(), &jobWrapper{s, j}) if err != nil { - s.Logger.Warningf("Failed to register job %q - %q - %q. Error: %s", j.GetName(), j.GetCommand(), j.GetSchedule(), err) + s.Logger.Warning("Failed to register job.", "job", j.GetName(), "command", j.GetCommand(), "schedule", j.GetSchedule(), "error", err) return err } j.SetCronJobID(int(id)) j.Use(s.Middlewares()...) - s.Logger.Noticef("New job registered %q - %q - %q - ID: %v", j.GetName(), j.GetCommand(), j.GetSchedule(), id) + s.Logger.Info("New job registered", "job", j.GetName(), "command", j.GetCommand(), "schedule", j.GetSchedule(), "id", id) return nil } func (s *Scheduler) RemoveJob(j Job) error { - s.Logger.Noticef("Job deregistered (will not fire again) %q - %q - %q - ID: %v", j.GetName(), j.GetCommand(), j.GetSchedule(), j.GetCronJobID()) + s.Logger.Info("Job deregistered (will not fire again)", "job", j.GetName(), "command", j.GetCommand(), "schedule", j.GetSchedule(), "cron_id", j.GetCronJobID()) s.cron.Remove(cron.EntryID(j.GetCronJobID())) return nil } @@ -66,7 +65,7 @@ func (s *Scheduler) CronJobs() []cron.Entry { } func (s *Scheduler) Start() error { - s.Logger.Debugf("Starting scheduler with %d jobs", len(s.CronJobs())) + s.Logger.Debug("Starting scheduler", "jobs_count", len(s.CronJobs())) s.isRunning = true s.cron.Start() @@ -104,29 +103,26 @@ func (w *jobWrapper) Run() { func (w *jobWrapper) start(ctx *Context) { ctx.Start() - ctx.Log("Started - " + ctx.Job.GetCommand()) + ctx.Log("Job start", "command", ctx.Job.GetCommand()) } func (w *jobWrapper) stop(ctx *Context, err error) { ctx.Stop(err) - errText := "none" + args := []any{} if ctx.Execution.Error != nil { - errText = ctx.Execution.Error.Error() + args = append(args, "error", ctx.Execution.Error) } if ctx.Execution.OutputStream.TotalWritten() > 0 { - ctx.Log("StdOut: " + ctx.Execution.OutputStream.String()) + args = append(args, "stdout", ctx.Execution.OutputStream) } if ctx.Execution.ErrorStream.TotalWritten() > 0 { - ctx.Log("StdErr: " + ctx.Execution.ErrorStream.String()) + args = append(args, "stderr", ctx.Execution.ErrorStream) } - msg := fmt.Sprintf( - "Finished in %q, failed: %t, skipped: %t, error: %s", - ctx.Execution.Duration, ctx.Execution.Failed, ctx.Execution.Skipped, errText, - ) + args = append(args, "duration", ctx.Execution.Duration, "failed", ctx.Execution.Failed, "skipped", ctx.Execution.Skipped) - ctx.Log(msg) + ctx.Log("Job stop", args...) } diff --git a/go.mod b/go.mod index e1dbf88b5c..71c05823f7 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,21 @@ module github.com/mcuadros/ofelia -go 1.24.0 +go 1.25.0 -toolchain go1.25.5 +toolchain go1.26.1 require ( github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625 github.com/docker/docker v28.5.2+incompatible - github.com/fsouza/go-dockerclient v1.12.3 - github.com/go-viper/mapstructure/v2 v2.4.0 + github.com/fsouza/go-dockerclient v1.12.4 + github.com/go-viper/mapstructure/v2 v2.5.0 github.com/gobs/args v0.0.0-20210311043657-b8c0b223be93 github.com/gohugoio/hashstructure v0.6.0 github.com/jessevdk/go-flags v1.6.1 - github.com/magefile/mage v1.15.0 + github.com/lmittmann/tint v1.1.3 + github.com/magefile/mage v1.16.1 github.com/mcuadros/go-defaults v1.2.0 - github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/robfig/cron/v3 v3.0.1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/gcfg.v1 v1.2.3 @@ -26,15 +26,16 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/docker/go-connections v0.5.0 // indirect + github.com/creack/pty v1.1.24 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.3 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/go-archive v0.1.0 // indirect + github.com/moby/go-archive v0.2.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/user v0.4.0 // indirect @@ -43,10 +44,11 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/stretchr/testify v1.10.0 // indirect - golang.org/x/sys v0.38.0 // indirect + github.com/sirupsen/logrus v1.9.4 // indirect + github.com/stretchr/testify v1.11.1 // indirect + golang.org/x/sys v0.40.0 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 2e08c5d674..455e09a496 100644 --- a/go.sum +++ b/go.sum @@ -13,41 +13,22 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -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/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I= -github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA= -github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= -github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk= -github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= +github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= +github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= +github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/fsouza/go-dockerclient v1.12.1 h1:FMoLq+Zhv9Oz/rFmu6JWkImfr6CBgZOPcL+bHW4gS0o= -github.com/fsouza/go-dockerclient v1.12.1/go.mod h1:OqsgJJcpCwqyM3JED7TdfM9QVWS5O7jSYwXxYKmOooY= -github.com/fsouza/go-dockerclient v1.12.2 h1:+pbP/SacoHfqaVZuiudvcdYGd9jzU7y9EcgoBOHivEI= -github.com/fsouza/go-dockerclient v1.12.2/go.mod h1:ZGCkAsnBGjnTRG9wV6QaICPJ5ig2KlaxTccDQy5WQ38= -github.com/fsouza/go-dockerclient v1.12.3 h1:CEsX4/msyMEekHAR9Pf8XniZBtwGo0Kl+mLPQ/AnSys= -github.com/fsouza/go-dockerclient v1.12.3/go.mod h1:gl0t2KUfrsLbm4tw5/ySsJkkFpi7Fz9gXzY2BKLEvZA= -github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= -github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/fsouza/go-dockerclient v1.12.4 h1:I8s8nsjDRE4fuym6k80Cs50lQLAKxT4e7b1Yph9ii+I= +github.com/fsouza/go-dockerclient v1.12.4/go.mod h1:CLBdACQr/Q6hnzAjKpfCcqPx0dOK7gbNnrL09DHo6a4= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobs/args v0.0.0-20210311043657-b8c0b223be93 h1:70jFzur8/dg4E5NKFMOPLAxk4wSyGm3vQ+7PuBEoHzE= github.com/gobs/args v0.0.0-20210311043657-b8c0b223be93/go.mod h1:ZpqkpUmnBz2Jz7hMGSPRbHtYC82FP/IZ1Y7A2riYH0s= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg= -github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec= github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -56,10 +37,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -67,14 +46,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= -github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/lmittmann/tint v1.1.3 h1:Hv4EaHWXQr+GTFnOU4VKf8UvAtZgn0VuKT+G0wFlO3I= +github.com/lmittmann/tint v1.1.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/magefile/mage v1.16.1 h1:j5UwkdA48xTlGs0Hcm1Q3sSAcxBorntQjiewDNMsqlo= +github.com/magefile/mage v1.16.1/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mcuadros/go-defaults v1.2.0 h1:FODb8WSf0uGaY8elWJAkoLL0Ri6AlZ1bFlenk56oZtc= github.com/mcuadros/go-defaults v1.2.0/go.mod h1:WEZtHEVIGYVDqkKSWBdWKUVdRyKlMfulPaGDWIVeCWY= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= -github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= +github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8= +github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -88,66 +69,29 @@ github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFL github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/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.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -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= +github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= +github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -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= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -157,7 +101,6 @@ gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AW gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -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.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q= diff --git a/integration/test-run-exec/docker-compose.yml b/integration/test-run-exec/docker-compose.yml index 36d159c388..202bee42ca 100644 --- a/integration/test-run-exec/docker-compose.yml +++ b/integration/test-run-exec/docker-compose.yml @@ -1,7 +1,7 @@ # Run this with: docker compose up --build --exit-code-from sleep1 services: sleep1: - image: &alpine alpine:3.23.2 + image: &alpine alpine:3.23.3 command: sleep ${SLEEP_FOR:-15} environment: OUTPUT_FILE: ${EXEC_OUTPUT_FILE:-sleep.txt} diff --git a/middlewares/common_test.go b/middlewares/common_test.go index ffc40cd241..2591d911ef 100644 --- a/middlewares/common_test.go +++ b/middlewares/common_test.go @@ -64,8 +64,7 @@ func (j *TestJob) Run(ctx *core.Context) error { type TestLogger struct{} -func (*TestLogger) Criticalf(format string, args ...interface{}) {} -func (*TestLogger) Debugf(format string, args ...interface{}) {} -func (*TestLogger) Errorf(format string, args ...interface{}) {} -func (*TestLogger) Noticef(format string, args ...interface{}) {} -func (*TestLogger) Warningf(format string, args ...interface{}) {} +func (*TestLogger) Debug(format string, args ...interface{}) {} +func (*TestLogger) Error(format string, args ...interface{}) {} +func (*TestLogger) Info(format string, args ...interface{}) {} +func (*TestLogger) Warning(format string, args ...interface{}) {} diff --git a/middlewares/mail.go b/middlewares/mail.go index 72a2c621e3..858367b489 100644 --- a/middlewares/mail.go +++ b/middlewares/mail.go @@ -57,7 +57,7 @@ func (m *Mail) Run(ctx *core.Context) error { if ctx.Execution.Failed || !m.MailOnlyOnError { err := m.sendMail(ctx) if err != nil { - ctx.Logger.Errorf("Mail error: %q", err) + ctx.Logger.Error("Mail error", "error", err) } } diff --git a/middlewares/save.go b/middlewares/save.go index 75aa41a970..6d2f14fa37 100644 --- a/middlewares/save.go +++ b/middlewares/save.go @@ -44,7 +44,7 @@ func (m *Save) Run(ctx *core.Context) error { if ctx.Execution.Failed || !m.SaveOnlyOnError { err := m.saveToDisk(ctx) if err != nil { - ctx.Logger.Errorf("Save error: %q", err) + ctx.Logger.Error("Save error", "error", err) } } diff --git a/middlewares/slack.go b/middlewares/slack.go index e4e8e6101a..5011166684 100644 --- a/middlewares/slack.go +++ b/middlewares/slack.go @@ -61,9 +61,9 @@ func (m *Slack) pushMessage(ctx *core.Context) { r, err := http.PostForm(m.SlackWebhook, values) if err != nil { - ctx.Logger.Errorf("Slack error calling %q error: %q", m.SlackWebhook, err) + ctx.Logger.Error("Failed to call slack", "webhook", m.SlackWebhook, "error", err) } else if r.StatusCode != 200 { - ctx.Logger.Errorf("Slack error non-200 status code calling %q", m.SlackWebhook) + ctx.Logger.Error("Slack responded with non-200 status", "webhook", m.SlackWebhook, "status", r.Status) } } diff --git a/ofelia.go b/ofelia.go index 4a71d6cb23..d7ffbd1137 100644 --- a/ofelia.go +++ b/ofelia.go @@ -7,20 +7,13 @@ import ( "github.com/jessevdk/go-flags" "github.com/mcuadros/ofelia/cli" "github.com/mcuadros/ofelia/core" - "github.com/op/go-logging" ) var version string var build string -const logFormat = "%{time} %{color} %{shortfile} ▶ %{level} %{color:reset} %{message}" - func buildLogger() core.Logger { - stdout := logging.NewLogBackend(os.Stdout, "", 0) - // Set the backends to be used. - logging.SetBackend(stdout) - logging.SetFormatter(logging.MustStringFormatter(logFormat)) - return logging.MustGetLogger("ofelia") + return core.NewSlogLogger(os.Stdout) } func main() {