diff --git a/.env.example b/.env.example-d similarity index 100% rename from .env.example rename to .env.example-d diff --git a/config.local.yaml b/config.local.yaml index b474300..6a681a3 100644 --- a/config.local.yaml +++ b/config.local.yaml @@ -5,9 +5,15 @@ jobs: - name: Test Job tasks: - - command: ip a -pt - retries: 5 + - command: php -v retry-delay: 5s + connections: + - image: docker-mysql-database-phpmyadmin + volumes: + - "/home/motalleb/Downloads:/var/local/test" + env: + SHELL: /bin/bash + schedulers: - on-init: true - interval: 10m10s diff --git a/config/config.go b/config/config.go index 86827fb..a0a3bb3 100644 --- a/config/config.go +++ b/config/config.go @@ -64,6 +64,11 @@ type ( OnFail []Task `mapstructure:"on-fail" json:"on_fail,omitempty"` } TaskConnection struct { - Local bool + Local bool `mapstructure:"local" json:"local,omitempty"` + DockerConnection string `mapstructure:"docker" json:"docker,omitempty"` + ContainerName string `mapstructure:"container" json:"container,omitempty"` + ImageName string `mapstructure:"image" json:"image,omitempty"` + Volumes []string `mapstructure:"volumes" json:"volumes,omitempty"` + Networks []string `mapstructure:"networks" json:"networks,omitempty"` } ) diff --git a/config/validators.go b/config/validators.go index f04b4ac..8a8fd07 100644 --- a/config/validators.go +++ b/config/validators.go @@ -74,7 +74,7 @@ func (t *Task) Validate(log *logrus.Entry) error { ) } if err := credential.Validate(log, t.UserName, t.GroupName); err != nil { - return err + log.WithError(err).Warn("Be careful when using credentials, in local mode you cant use credentials unless running as root") } if t.Command != "" && (t.Data != nil || t.Headers != nil) { return fmt.Errorf("command cannot have data or headers field, violating command: `%s`", t.Command) diff --git a/core/cmd_connection/compiler.go b/core/cmd_connection/compiler.go index 1d20409..03eb460 100644 --- a/core/cmd_connection/compiler.go +++ b/core/cmd_connection/compiler.go @@ -1,18 +1,27 @@ +// Package connection package connection import ( - "log" - "github.com/sirupsen/logrus" "github.com/FMotalleb/crontab-go/abstraction" "github.com/FMotalleb/crontab-go/config" ) +// CompileConnection compiles the task connection based on the provided configuration and logger. +// It returns an abstraction.CmdConnection interface based on the type of connection specified in the configuration. +// If the connection type is not recognized or invalid, it logs a fatal error and returns nil. func CompileConnection(conn *config.TaskConnection, logger *logrus.Entry) abstraction.CmdConnection { - if conn.Local { + logger.Warn(conn) + switch { + case conn.Local: return NewLocalCMDConn(logger) + case conn.ContainerName != "" && conn.ImageName == "": + return NewDockerAttachConnection(logger, conn) + case conn.ImageName != "": + return NewDockerCreateConnection(logger, conn) } - log.Fatalln("cannot compile given taskConnection", conn) + + logger.WithField("taskConnection", conn).Error("cannot compile given taskConnection") return nil } diff --git a/core/cmd_connection/docker_attach.go b/core/cmd_connection/docker_attach.go new file mode 100644 index 0000000..1a3fe8f --- /dev/null +++ b/core/cmd_connection/docker_attach.go @@ -0,0 +1,125 @@ +package connection + +import ( + "bytes" + "context" + "io" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/sirupsen/logrus" + + "github.com/FMotalleb/crontab-go/abstraction" + "github.com/FMotalleb/crontab-go/config" +) + +type DockerAttachConnection struct { + conn *config.TaskConnection + log *logrus.Entry + cli *client.Client + execCFG *types.ExecConfig + containerID string + ctx context.Context +} + +// NewDockerAttachConnection creates a new DockerAttachConnection instance. +// It initializes the connection configuration and logging fields. +// Parameters: +// - log: A logrus.Entry instance for logging purposes. +// - conn: A TaskConnection instance containing the connection configuration. +// Returns: +// - A new instance of DockerAttachConnection implementing the CmdConnection interface. +func NewDockerAttachConnection(log *logrus.Entry, conn *config.TaskConnection) abstraction.CmdConnection { + return &DockerAttachConnection{ + conn: conn, + log: log.WithFields( + logrus.Fields{ + "connection": "docker", + "docker-mode": "attach", + }, + ), + } +} + +// Prepare sets up the DockerAttachConnection for executing a task. +// It reshapes the environment variables, sets the context, and creates an exec configuration. +// Parameters: +// - ctx: A context.Context instance for managing the request lifetime. +// - task: A Task instance containing the task configuration. +// Returns: +// - An error if the preparation fails, otherwise nil. +func (d *DockerAttachConnection) Prepare(ctx context.Context, task *config.Task) error { + shell, shellArgs, env := reshapeEnviron(task, d.log) + d.ctx = ctx + // Specify the container ID or name + d.containerID = d.conn.ContainerName + if d.conn.DockerConnection == "" { + d.log.Debug("No explicit docker connection specified, using default: `unix:///var/run/docker.sock`") + d.conn.DockerConnection = "unix:///var/run/docker.sock" + } + cmd := append( + []string{shell}, + append(shellArgs, task.Command)..., + ) + // Create an exec configuration + d.execCFG = &types.ExecConfig{ + AttachStdout: true, + AttachStderr: true, + Privileged: true, + Env: env, + WorkingDir: task.WorkingDirectory, + User: task.UserName, + Cmd: cmd, + } + return nil +} + +// Connect establishes a connection to the Docker daemon. +// It initializes the Docker client with the specified connection settings. +// Returns: +// - An error if the connection fails, otherwise nil. +func (d *DockerAttachConnection) Connect() error { + cli, err := client.NewClientWithOpts( + client.WithHost(d.conn.DockerConnection), + ) + if err != nil { + return err + } + d.cli = cli + return nil +} + +// Execute runs the command in the Docker container and captures the output. +// It creates an exec instance, attaches to it, and reads the command output. +// Returns: +// - A byte slice containing the command output. +// - An error if the execution fails, otherwise nil. +func (d *DockerAttachConnection) Execute() ([]byte, error) { + // Create the exec instance + exec, err := d.cli.ContainerExecCreate(d.ctx, d.containerID, *d.execCFG) + if err != nil { + return nil, err + } + + // Attach to the exec instance + resp, err := d.cli.ContainerExecAttach(d.ctx, exec.ID, types.ExecStartCheck{}) + if err != nil { + return nil, err + } + defer resp.Close() + + writer := bytes.NewBuffer([]byte{}) + // Print the command output + _, err = io.Copy(writer, resp.Reader) + if err != nil { + return nil, err + } + return writer.Bytes(), nil +} + +// Disconnect closes the connection to the Docker daemon. +// Returns: +// - An error if the disconnection fails, otherwise nil. +func (d *DockerAttachConnection) Disconnect() error { + return d.cli.Close() +} diff --git a/core/cmd_connection/docker_create.go b/core/cmd_connection/docker_create.go new file mode 100644 index 0000000..7326509 --- /dev/null +++ b/core/cmd_connection/docker_create.go @@ -0,0 +1,180 @@ +package connection + +import ( + "bytes" + "context" + "io" + "strings" + + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/client" + "github.com/sirupsen/logrus" + + "github.com/FMotalleb/crontab-go/abstraction" + "github.com/FMotalleb/crontab-go/config" +) + +// DockerCreateConnection is a struct that manages the creation and execution of Docker containers. +type DockerCreateConnection struct { + conn *config.TaskConnection + log *logrus.Entry + cli *client.Client + imageName string + containerConfig *container.Config + hostConfig *container.HostConfig + networkConfig *network.NetworkingConfig + ctx context.Context +} + +// NewDockerCreateConnection initializes a new DockerCreateConnection instance. +// Parameters: +// - log: A logrus.Entry instance for logging. +// - conn: A TaskConnection instance containing the connection configuration. +// Returns: +// - A new instance of DockerCreateConnection. +func NewDockerCreateConnection(log *logrus.Entry, conn *config.TaskConnection) abstraction.CmdConnection { + return &DockerCreateConnection{ + conn: conn, + log: log.WithFields( + logrus.Fields{ + "connection": "docker", + "docker-mode": "create", + }, + ), + } +} + +// Prepare sets up the Docker container configuration based on the provided task. +// Parameters: +// - ctx: A context.Context instance for managing the lifecycle of the container. +// - task: A Task instance containing the task configuration. +// Returns: +// - An error if the preparation fails, otherwise nil. +func (d *DockerCreateConnection) Prepare(ctx context.Context, task *config.Task) error { + shell, shellArgs, env := reshapeEnviron(task, d.log) + d.ctx = ctx + if d.conn.DockerConnection == "" { + d.log.Debug("No explicit docker connection specified, using default: `unix:///var/run/docker.sock`") + d.conn.DockerConnection = "unix:///var/run/docker.sock" + } + cmd := append( + []string{shell}, + append(shellArgs, task.Command)..., + ) + volumes := make(map[string]struct{}) + for _, volume := range d.conn.Volumes { + inContainer := strings.Split(volume, ":")[1] + volumes[inContainer] = struct{}{} + } + // Create an exec configuration + d.containerConfig = &container.Config{ + AttachStdout: true, + AttachStderr: true, + Env: env, + WorkingDir: task.WorkingDirectory, + User: task.UserName, + Cmd: cmd, + Image: d.conn.ImageName, + Volumes: volumes, + Entrypoint: []string{}, + Shell: []string{}, + } + d.hostConfig = &container.HostConfig{ + Binds: d.conn.Volumes, + // AutoRemove: true, + } + endpointsConfig := make(map[string]*network.EndpointSettings) + for _, networkName := range d.conn.Networks { + endpointsConfig[networkName] = &network.EndpointSettings{} + } + d.networkConfig = &network.NetworkingConfig{ + EndpointsConfig: endpointsConfig, + } + return nil +} + +// Connect establishes a connection to the Docker daemon. +// Returns: +// - An error if the connection fails, otherwise nil. +func (d *DockerCreateConnection) Connect() error { + cli, err := client.NewClientWithOpts( + client.WithHost(d.conn.DockerConnection), + ) + if err != nil { + return err + } + d.cli = cli + return nil +} + +// Execute creates, starts, and logs the output of the Docker container. +// Returns: +// - A byte slice containing the command output. +// - An error if the execution fails, otherwise nil. +func (d *DockerCreateConnection) Execute() ([]byte, error) { + ctx := d.ctx + // Create the exec instance + exec, err := d.cli.ContainerCreate( + ctx, + d.containerConfig, + d.hostConfig, + d.networkConfig, + nil, + d.conn.ContainerName, + ) + d.log.Debugf("container created: %v, warnings: %v", exec, exec.Warnings) + if err != nil { + return nil, err + } + defer d.cli.ContainerRemove(ctx, exec.ID, + container.RemoveOptions{ + Force: true, + }, + ) + err = d.cli.ContainerStart(d.log.Context, exec.ID, + container.StartOptions{}, + ) + d.log.Debugf("container started: %v", exec) + if err != nil { + return nil, err + } + starting := true + for starting { + _, err := d.cli.ContainerStats(ctx, exec.ID, false) + if err == nil { + starting = false + } + } + d.log.Debugf("container ready to attach: %v", exec) + // Attach to the exec instance + resp, err := d.cli.ContainerLogs( + ctx, + exec.ID, + container.LogsOptions{ + ShowStdout: true, + ShowStderr: true, + Follow: false, + Details: true, + }, + ) + if err != nil { + return nil, err + } + defer resp.Close() + + writer := bytes.NewBuffer([]byte{}) + // Print the command output + _, err = io.Copy(writer, resp) + if err != nil { + return writer.Bytes(), err + } + return writer.Bytes(), nil +} + +// Disconnect closes the connection to the Docker daemon. +// Returns: +// - An error if the disconnection fails, otherwise nil. +func (d *DockerCreateConnection) Disconnect() error { + return d.cli.Close() +} diff --git a/core/cmd_connection/helpers.go b/core/cmd_connection/helpers.go new file mode 100644 index 0000000..613d376 --- /dev/null +++ b/core/cmd_connection/helpers.go @@ -0,0 +1,44 @@ +package connection + +import ( + "fmt" + "os" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/FMotalleb/crontab-go/cmd" + "github.com/FMotalleb/crontab-go/config" +) + +// reshapeEnviron modifies the environment variables for a given task. +// It allows overriding the global shell and shell arguments with task-specific values. +// +// Parameters: +// - task: A pointer to a config.Task struct containing the task-specific environment variables. +// - log: A logrus.Entry used for logging information about environment variable overrides. +// +// Returns: +// - string: The shell to be used for the task, either the global shell or the overridden shell. +// - []string: The shell arguments to be used for the task, either the global shell arguments or the overridden shell arguments. +// - []string: The complete set of environment variables for the task, including any task-specific overrides. +func reshapeEnviron(task *config.Task, log *logrus.Entry) (string, []string, []string) { + shell := cmd.CFG.Shell + shellArgs := cmd.CFG.ShellArgs + env := os.Environ() + log.Trace("Initial environment variables: ", env) + for key, val := range task.Env { + env = append(env, fmt.Sprintf("%s=%s", key, val)) + log.Debugf("Adding environment variable: %s=%s", key, val) + switch strings.ToLower(key) { + case "shell": + log.Info("you've used `SHELL` env variable in command environments, overriding the global shell with:", val) + shell = val + case "shell_args": + log.Info("you've used `SHELL_ARGS` env variable in command environments, overriding the global shell_args with: ", val) + shellArgs = strings.Split(val, ";") + } + } + log.Trace("Final environment variables: ", env) + return shell, shellArgs, env +} diff --git a/core/cmd_connection/local.go b/core/cmd_connection/local.go index 8f5448c..39e7ac2 100644 --- a/core/cmd_connection/local.go +++ b/core/cmd_connection/local.go @@ -11,16 +11,17 @@ import ( "github.com/sirupsen/logrus" "github.com/FMotalleb/crontab-go/abstraction" - "github.com/FMotalleb/crontab-go/cmd" "github.com/FMotalleb/crontab-go/config" credential "github.com/FMotalleb/crontab-go/core/os_credential" ) +// Local represents a local command connection. type Local struct { log *logrus.Entry cmd *exec.Cmd } +// NewLocalCMDConn creates a new instance of Local command connection. func NewLocalCMDConn(log *logrus.Entry) abstraction.CmdConnection { return &Local{ log: log.WithField( @@ -29,22 +30,11 @@ func NewLocalCMDConn(log *logrus.Entry) abstraction.CmdConnection { } } -// Prepare implements abstraction.CmdConnection. +// Prepare prepares the command for execution. +// It sets up the command with the provided context, task, and environment. +// It returns an error if the preparation fails. func (l *Local) Prepare(ctx context.Context, task *config.Task) error { - shell := cmd.CFG.Shell - shellArgs := cmd.CFG.ShellArgs - env := os.Environ() - for key, val := range task.Env { - env = append(env, fmt.Sprintf("%s=%s", key, val)) - switch strings.ToLower(key) { - case "shell": - l.log.Info("you've used `SHELL` env variable in command environments, overriding the global shell with:", val) - shell = val - case "shell_args": - l.log.Info("you've used `SHELL_ARGS` env variable in command environments, overriding the global shell_args with: ", val) - shellArgs = strings.Split(val, ";") - } - } + shell, shellArgs, env := reshapeEnviron(task, l.log) workingDir := task.WorkingDirectory if workingDir == "" { var e error @@ -69,32 +59,46 @@ func (l *Local) Prepare(ctx context.Context, task *config.Task) error { l.cmd.Env = env l.cmd.Dir = workingDir + // Add additional logging fields if needed + l.log.WithFields(logrus.Fields{ + "working_directory": workingDir, + "shell": shell, + "shell_args": shellArgs, + "task": task, + }).Debug("command prepared") + return nil } -// Connect implements abstraction.CmdConnection. +// Connect establishes the command connection. +// It returns an error if the connection cannot be established. func (l *Local) Connect() error { return nil } -// Disconnect implements abstraction.CmdConnection. +// Disconnect closes the command connection. +// It returns an error if the disconnection process fails. func (l *Local) Disconnect() error { return nil } -// Execute implements abstraction.CmdConnection. +// Execute executes the command and returns the output. +// It captures the command's standard output and standard error. +// It returns the output and an error, if any. func (l *Local) Execute() ([]byte, error) { var res bytes.Buffer l.cmd.Stdout = &res l.cmd.Stderr = &res if err := l.cmd.Start(); err != nil { - l.log.Warn("failed to start the command ", err) + l.log.WithError(err).Warn("failed to start the command") return []byte{}, err } else if err := l.cmd.Wait(); err != nil { - l.log.Warnf("command failed with answer: %s", strings.TrimSpace(res.String())) - l.log.Warn("failed to execute the command", err) - return res.Bytes(), err + output := res.Bytes() + l.log.WithError(err).WithField("output", strings.TrimSpace(res.String())).Warn("command execution failed") + l.log.WithField("output", strings.TrimSpace(res.String())).Debug("command output") + return output, err } else { + l.log.WithField("output", strings.TrimSpace(res.String())).Debug("command output") return res.Bytes(), nil } } diff --git a/core/task/command.go b/core/task/command.go index 581d9de..bd7c4e7 100644 --- a/core/task/command.go +++ b/core/task/command.go @@ -64,16 +64,16 @@ func (c *Command) Execute(ctx context.Context) (e error) { cmdCtx, cancel := c.ApplyTimeout(ctx) c.SetCancel(cancel) - if err := connection.Connect(); err != nil { - log.Warn("error when tried to connect, exiting current remote", err) + if err := connection.Prepare(cmdCtx, c.task); err != nil { + log.Warn("cannot prepare command: ", err) ctx = addFailedConnections(ctx, conn) + connection.Disconnect() continue } - err := connection.Prepare(cmdCtx, c.task) - if err != nil { - log.Warn("cannot prepare command: ", err) + + if err := connection.Connect(); err != nil { + log.Warn("error when tried to connect, exiting current remote", err) ctx = addFailedConnections(ctx, conn) - connection.Disconnect() continue } ans, err := connection.Execute() diff --git a/core/task/helper.go b/core/task/helper.go index fdc0598..e4be1a8 100644 --- a/core/task/helper.go +++ b/core/task/helper.go @@ -1,6 +1,7 @@ package task import ( + "bytes" "context" "fmt" "net/http" @@ -13,7 +14,7 @@ import ( func logHTTPResponse(r *http.Response) logrus.LogFunction { return func() []any { - result := &ResponseWriter{} + result := bytes.NewBuffer([]byte{}) err := r.Write(result) return []any{ fmt.Sprintf("error: %v", err), @@ -39,18 +40,3 @@ func addFailedConnections(ctx context.Context, con config.TaskConnection) contex current := getFailedConnections(ctx) return context.WithValue(ctx, ctxutils.FailedRemotes, append(current, con)) } - -type ResponseWriter struct { - buffer []byte -} - -// Write implements io.Writer. -func (r *ResponseWriter) Write(p []byte) (n int, err error) { - initial := len(r.buffer) - r.buffer = append(r.buffer, p...) - return len(r.buffer) - initial, nil -} - -func (r *ResponseWriter) String() string { - return string(r.buffer) -} diff --git a/go.mod b/go.mod index 7247510..93ab0f9 100644 --- a/go.mod +++ b/go.mod @@ -3,20 +3,37 @@ module github.com/FMotalleb/crontab-go go 1.22 require ( + github.com/docker/docker v26.1.4+incompatible github.com/joho/godotenv v1.5.1 + github.com/robfig/cron/v3 v3.0.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.19.0 - github.com/robfig/cron/v3 v3.0.1 ) require ( + github.com/Microsoft/go-winio v0.6.2 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/distribution/reference v0.6.0 // indirect + github.com/docker/go-connections v0.5.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/term v0.5.0 // indirect + github.com/morikuni/aec v1.0.0 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -24,11 +41,19 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.27.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/sdk v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + gotest.tools/v3 v3.5.1 // indirect ) diff --git a/go.sum b/go.sum index 679bfef..695e320 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,81 @@ +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= +github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= +github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+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-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +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/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= +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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +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/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +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.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= +github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= @@ -64,22 +108,80 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= +go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= +go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +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/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +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/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +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= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +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.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +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= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291 h1:AgADTJarZTBqgjiUzRgfaBchgYB3/WFTC80GPwsMcRI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240515191416-fc5f0ca64291/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= +gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/schema.json b/schema.json index 22ce8e0..0e13c7a 100644 --- a/schema.json +++ b/schema.json @@ -204,6 +204,13 @@ "data": { "$ref": "#/definitions/Data", "description": "A Data object that defines the data to be sent with the request." + }, + "connections": { + "type": "array", + "items": { + "$ref": "#/definitions/TaskConnection" + }, + "description": "Connection config." } }, "required": [], @@ -215,6 +222,45 @@ "required": [], "title": "Data" }, + "TaskConnection": { + "type": "object", + "additionalProperties": false, + "properties": { + "local": { + "type": "boolean", + "title": "Local environment" + }, + "docker": { + "type": "string", + "title": "docker connection string" + }, + "container": { + "type": "string", + "title": "container name/id matcher", + "description": "Should match only one container, if matches two or more container the command will fail" + }, + "image": { + "type": "string", + "title": "Image name/id" + }, + "volumes": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Volumes" + }, + "networks": { + "type": "array", + "items": { + "type": "string" + }, + "title": "Networks" + } + }, + "required": [], + "title": "Data" + }, "Env": { "type": "object", "additionalProperties": true,