grim/convey

Port from logrus to log/slog
default tip
4 months ago, Elliott Sales de Andrade
c588f9b3f559
Port from logrus to log/slog

This doesn't really take much advantage of structured logging beyond what is already done (`id` and `idColor`), and consequently the log handler does not try to do any handling of anything more than that (i.e., grouping, or arbitrary attributes beyond those defined).

One should maybe have a `Context` available to pass in, but there isn't one, and anyway, the log handler doesn't use it, so I've passed in a `TODO` instead.

Everything else is just normal import/rename changes.

Testing Done:
Ran `go run . run`

Reviewed at https://reviews.imfreedom.org/r/2871/
package podman
import (
"log/slog"
"os"
"path/filepath"
"strings"
"github.com/kballard/go-shellquote"
"github.com/opencontainers/selinux/go-selinux"
"keep.imfreedom.org/grim/convey/environment"
"keep.imfreedom.org/grim/convey/exec"
"keep.imfreedom.org/grim/convey/runtime"
"keep.imfreedom.org/grim/convey/yaml"
)
type Run struct {
Annotations yaml.StringOrSlice `yaml:"annotations"`
Command string `yaml:"command"`
Entrypoint string `yaml:"entrypoint"`
Environment yaml.StringOrSlice `yaml:"environment"`
Hostname string `yaml:"hostname"`
Image string `yaml:"image"`
Script yaml.StringOrSlice `yaml:"script"`
Shell string `yaml:"shell"`
User string `yaml:"user"`
Workdir string `yaml:"workdir"`
Workspace string `yaml:"workspace"`
commandv []string
}
func (r *Run) buildScript(cfgPath string, env environment.Environment) (string, error) {
script := env.Expandv(r.Script)
fp, err := os.CreateTemp(cfgPath, ".convey-script-")
if err != nil {
return "", err
}
if _, err = fp.Write([]byte(strings.Join(script, "\n"))); err != nil {
return "", err
}
if err := fp.Chmod(0700); err != nil {
return "", err
}
if err := fp.Close(); err != nil {
return "", err
}
return fp.Name(), nil
}
func (r *Run) Execute(name string, logger *slog.Logger, stageEnv environment.Environment, rt *runtime.Runtime) error {
// Create a new environment based on the stage's environment. Then merge
// the task's environment overriding anything from the stage. Finally merge
// the runtime environment which holds the environment from the command line.
env := stageEnv.Copy().MergeSlice(r.Environment).Merge(rt.Environment)
// Figure out where we're mounting the workspace. This should be done
// before workdir is expanded as work is typically set to CONVEY_WORKSPACE.
workspace := env.Expand(r.Workspace)
if workspace == "" {
workspace = "/workspace"
}
hostWorkspace, err := rt.Workspace()
if err != nil {
return err
}
env["CONVEY_WORKSPACE"] = workspace
volume := hostWorkspace.Path() + ":" + workspace
if selinux.GetEnabled() {
// We use lower zed because it creates a shared selinux label that can
// be used by multiple containers and this task could be in a stage
// that is running tasks concurrently.
volume += ":z"
}
generator := exec.NewGenerator(
"podman",
"run",
"--rm",
"--volume", volume,
)
// If --cpu-shares was specified on the command line add it now.
if rt.CPUShares != "" {
generator.Append("--cpu-shares", rt.CPUShares)
}
// If --memory was specified on the command line add it now.
if rt.Memory != "" {
generator.Append("--memory", rt.Memory)
}
// If the user provided a script, generate the file and set all of our
// attributes appropriately.
if len(r.Script) > 0 {
// Overwrite any entry point that the user provided. Validate set
// /bin/sh if the user didn't provide one.
r.Entrypoint = r.Shell
scriptFile, err := r.buildScript(rt.ConfigPath, env)
if err != nil {
os.Remove(scriptFile)
return err
}
defer os.Remove(scriptFile)
scriptFileBase := filepath.Base(scriptFile)
r.commandv = []string{"/" + scriptFileBase}
volume := scriptFile + ":/" + scriptFileBase
if selinux.GetEnabled() {
volume += ":z"
}
generator.Append("--volume", volume)
}
// Add any annotations that the user specified.
for _, annotation := range r.Annotations {
generator.Append("--annotation", annotation)
}
// Add the entrypoint is one was specified.
if r.Entrypoint != "" {
generator.Append("--entrypoint", env.Expand(r.Entrypoint))
}
// Now add all the given environment variables
for _, name := range env.All() {
generator.Append("--env", name)
}
// Add the hostname if one was specified.
if r.Hostname != "" {
generator.Append("--hostname", env.Expand(r.Hostname))
}
// Add the user if one was specified.
if r.User != "" {
generator.Append("--user", env.Expand(r.User))
}
// Add the workdir if one was specified.
if r.Workdir != "" {
generator.Append("--workdir", env.Expand(r.Workdir))
}
// Finally append the image name.
generator.Append(env.Expand(r.Image))
if len(r.commandv) > 0 {
generator.Appendv(env.Expandv(r.commandv))
}
return exec.Run(name, generator.Command(), rt.Timeout)
}
func (r *Run) New() runtime.Task {
return &Run{}
}
func (r *Run) Valid() error {
if r.Image == "" {
return ErrNoImage
}
if r.Command != "" {
cmdv, err := shellquote.Split(r.Command)
if err != nil {
return err
}
r.commandv = cmdv
}
if r.Shell == "" {
r.Shell = "/bin/sh"
}
return nil
}
func (r *Run) Deprecated() error {
return nil
}