runner

package
v0.9.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: GPL-3.0 Imports: 43 Imported by: 0

Documentation

Overview

package runner

Runner runs the command inside the executor shell It uses the mvdan.sh shell implementation in Go. injects a custom environment per execution

not all *nix* commands are available, should only be used for a limited number of scenarios

Container Specific implementation runner will use the MobyAPI

Index

Examples

Constants

View Source
const (
	// TODO: potentially re-create the old docker behaviour
	// of a lookup in a directory
	DOCKER_CONFIG string = `DOCKER_CONFIG`

	// REGISTRY_AUTH_FILE is the environment variable name
	// for the file to use with container registry authentication
	REGISTRY_AUTH_FILE string = `REGISTRY_AUTH_FILE`
)

Variables

View Source
var (
	DOCKER_CONFIG_FILE    string = ".docker/config.json"
	CONTAINER_CONFIG_FILE string = ".config/containers/auth.json"
)
View Source
var (
	ErrImagePull                        = errors.New("failed to pull container image")
	ErrRegistryAuth                     = errors.New("failed to auth to registry")
	ErrContainerCreate                  = errors.New("failed to create container")
	ErrContainerAttach                  = errors.New("failed to attach container")
	ErrContainerStart                   = errors.New("failed to start container")
	ErrContainerWait                    = errors.New("failed to wait for container")
	ErrContainerLogs                    = errors.New("failed to get container logs")
	ErrContainerExecCmd                 = errors.New("failed to run cmd in container")
	ErrContainerMultiplexedStdoutStream = errors.New("failed to de-muiltiplex the stream")
)
View Source
var ErrArtifactFailed = errors.New("artifact not processed")
View Source
var ErrMutuallyExclusiveVarSet = errors.New("mutually exclusive vars have been set")

Functions

func AuthLookupFunc added in v0.3.4

func AuthLookupFunc(containerConf *container.Config) func(ctx context.Context) (string, error)

func IsExitStatus

func IsExitStatus(err error) (uint8, bool)

IsExitStatus checks if given `err` is an exit status

Types

type BindVolume added in v0.3.0

type BindVolume struct {
	// SourcePath is the path on the host
	SourcePath string
	// TargetPath is the path in the container
	TargetPath string
}

BindVolume formatted for bindmount

type ContainerContext

type ContainerContext struct {
	Image      string
	Entrypoint []string
	ShellArgs  []string

	// BindMount uses --mount instead of -v
	//
	// when running on Windows mount is default as volume mapping does not work.
	BindMount bool
	// contains filtered or unexported fields
}

func NewContainerContext

func NewContainerContext(name string, opts ...ContainerContextOpt) *ContainerContext

NewContainerContext accepts name of the image

func (*ContainerContext) BindMounts added in v0.3.0

func (c *ContainerContext) BindMounts() []BindVolume

BindMounts returns the volumes in a bind mount format

func (*ContainerContext) ParseContainerArgs added in v0.4.1

func (c *ContainerContext) ParseContainerArgs(cargs []string) (*ContainerContext, error)

func (*ContainerContext) Ports added in v0.7.3

func (c *ContainerContext) Ports() (map[nat.Port]struct{}, map[nat.Port][]nat.PortBinding)

func (*ContainerContext) User added in v0.4.1

func (c *ContainerContext) User() string

func (*ContainerContext) Volumes

func (c *ContainerContext) Volumes() map[string]struct{}

func (*ContainerContext) WithEnvOverride added in v0.3.3

func (c *ContainerContext) WithEnvOverride(env map[string]string) *ContainerContext

func (*ContainerContext) WithVolumes

func (c *ContainerContext) WithVolumes(vols ...string) *ContainerContext

type ContainerContextOpt added in v0.9.5

type ContainerContextOpt func(cc *ContainerContext)

func WithContainerContextPullTimeout added in v0.9.5

func WithContainerContextPullTimeout(p int) ContainerContextOpt

type ContainerExecutor

type ContainerExecutor struct {
	Term Terminal
	// contains filtered or unexported fields
}

func NewContainerExecutor

func NewContainerExecutor(execContext *ExecutionContext, opts ...ContainerOpts) (*ContainerExecutor, error)

NewContainerExecutor initialises an OCI compliant client

It implicitely creates it from `env` any missing vars required to initialise it, will be flagged in the error response.

func (*ContainerExecutor) Execute

func (e *ContainerExecutor) Execute(ctx context.Context, job *Job) ([]byte, error)

Execute executes given job with provided context Returns job output

func (*ContainerExecutor) PullImage

func (e *ContainerExecutor) PullImage(ctx context.Context, containerConf *container.Config) error

Container pull images - all contexts that have a container property

func (*ContainerExecutor) WithReset

func (e *ContainerExecutor) WithReset(doReset bool)

type ContainerExecutorIface

type ContainerExecutorIface interface {
	Close() error
	ImagePull(ctx context.Context, refStr string, options image.PullOptions) (io.ReadCloser, error)
	ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error)
	ContainerStart(ctx context.Context, containerID string, options container.StartOptions) error
	ContainerStop(ctx context.Context, containerID string, options container.StopOptions) error
	ContainerRemove(ctx context.Context, containerID string, options container.RemoveOptions) error
	ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error)
	ContainerLogs(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error)
	ContainerInspect(ctx context.Context, containerID string) (container.InspectResponse, error)
	// Shell
	ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error)
	ContainerResize(ctx context.Context, containerID string, options container.ResizeOptions) error
}

ContainerExecutorIface interface used by this implementation

type ContainerOpts

type ContainerOpts func(*ContainerExecutor)

func WithContainerClient added in v0.3.4

func WithContainerClient(client ContainerExecutorIface) ContainerOpts

type DefaultExecutor

type DefaultExecutor struct {
	// contains filtered or unexported fields
}

DefaultExecutor is a default executor used for jobs Uses `mvdan.cc/sh/v3/interp` under the hood

func (*DefaultExecutor) Execute

func (e *DefaultExecutor) Execute(ctx context.Context, job *Job) ([]byte, error)

Execute executes given job with provided context Returns job output

func (*DefaultExecutor) WithReset

func (e *DefaultExecutor) WithReset(doReset bool)

type ExecutionContext

type ExecutionContext struct {
	SourceFile string
	Executable *utils.Binary

	Dir       string
	Env       *variables.Variables
	Envfile   *utils.Envfile
	Variables *variables.Variables
	// Quote character to use around a command
	// when passed to another executable, e.g. docker
	Quote string
	// contains filtered or unexported fields
}

ExecutionContext allow you to set up execution environment, variables, binary which will run your task, up/down commands etc.

func DefaultContext

func DefaultContext() *ExecutionContext

DefaultContext creates default ExecutionContext instance

func NewExecutionContext

func NewExecutionContext(executable *utils.Binary, dir string,
	env *variables.Variables, envfile *utils.Envfile, up, down, before, after []string,
	options ...ExecutionContextOption) *ExecutionContext

NewExecutionContext creates new ExecutionContext instance

func (*ExecutionContext) After

func (c *ExecutionContext) After() error

After executes tasks defined to run after every usage of the context

func (*ExecutionContext) Before

func (c *ExecutionContext) Before() error

Before executes tasks defined to run before every usage of the context

func (*ExecutionContext) Container

func (c *ExecutionContext) Container() *ContainerContext

func (*ExecutionContext) Down

func (c *ExecutionContext) Down()

Down executes tasks defined to run once after last usage of the context

func (*ExecutionContext) GetExecutorType

func (c *ExecutionContext) GetExecutorType() ExecutorType

func (*ExecutionContext) ProcessEnvfile

func (c *ExecutionContext) ProcessEnvfile(env *variables.Variables) error

ProcessEnvfile processes env and other supplied variables into a single context environment

Example
package main

import (
	"fmt"
	"strings"

	"github.com/Ensono/eirctl/internal/utils"
	"github.com/Ensono/eirctl/runner"
	"github.com/Ensono/eirctl/variables"
)

func helperEnvString(envMap *variables.Variables) string {
	s := &strings.Builder{}
	for _, envPair := range utils.ConvertEnv(utils.ConvertToMapOfStrings(envMap.Map())) {
		s.Write([]byte(envPair))
		s.Write([]byte{'\n'})
	}
	return s.String()
}

func main() {
	osEnvVars := variables.FromMap(map[string]string{"TF_VAR_CAPPED_BY_MSFT": "some value"})
	//  "var2": "original222", "!::": "whatever val will never be added", "incld1": "welcome var", "exclude3": "sadgfddf"})
	userEnvVars := variables.FromMap(map[string]string{})
	envVars := osEnvVars.Merge(userEnvVars)

	ef := utils.NewEnvFile(func(e *utils.Envfile) {
		e.Exclude = append(e.Exclude, []string{"excld1", "exclude3", "userSuppliedButExcluded"}...)
		e.Modify = append(e.Modify, []utils.ModifyEnv{
			{Pattern: "^(?P<keyword>TF_VAR_)(?P<varname>.*)", Operation: "lower"},
		}...)
	})

	execContext := runner.NewExecutionContext(nil, "", envVars, ef, []string{}, []string{}, []string{}, []string{})
	_ = execContext.ProcessEnvfile(envVars)

	// for the purposes of the test example we need to make sure the map is
	// always displayed in same order of keys, which is not a guarantee with a map
	fmt.Println(helperEnvString(execContext.Env))
}
Output:

TF_VAR_capped_by_msft=some value

func (*ExecutionContext) StartupError

func (c *ExecutionContext) StartupError() error

StartUpError reports whether an error exists on startUp

func (*ExecutionContext) Up

func (c *ExecutionContext) Up() error

Up executes tasks defined to run once before first usage of the context

type ExecutionContextOption

type ExecutionContextOption func(c *ExecutionContext)

ExecutionContextOption is a functional option to configure ExecutionContext

func WithContainerOpts

func WithContainerOpts(containerOpts *ContainerContext) ExecutionContextOption

func WithQuote

func WithQuote(quote string) ExecutionContextOption

WithQuote is functional option to set Quote for ExecutionContext

type Executor

type Executor interface {
	Execute(context.Context, *Job) ([]byte, error)
}

type ExecutorIface

type ExecutorIface interface {
	// WithEnv(env []string) ExecutorIface
	WithReset(doReset bool)
	Execute(ctx context.Context, job *Job) ([]byte, error)
}

func GetExecutorFactory

func GetExecutorFactory(execContext *ExecutionContext, job *Job) (ExecutorIface, error)

GetExecutorFactory returns a factory instance of the executor

type ExecutorType

type ExecutorType string
const (
	DefaultExecutorTyp   ExecutorType = "default"
	ContainerExecutorTyp ExecutorType = "container"
)

type Job

type Job struct {
	Command string
	Dir     string
	Env     *variables.Variables
	EnvFile *utils.Envfile
	Vars    *variables.Variables
	Timeout *time.Duration

	Stdout, Stderr io.Writer
	Stdin          io.Reader
	IsShell        bool
	Next           *Job
}

Job is a linked list of jobs to execute by Executor Task can have 1 or more Jobs

func NewJobFromCommand

func NewJobFromCommand(command string) *Job

NewJobFromCommand creates new Job instance from given command

type Opts

type Opts func(*TaskRunner)

Opts is a task runner configuration function.

func WithContexts

func WithContexts(contexts map[string]*ExecutionContext) Opts

WithContexts adds provided contexts to task runner

func WithExecutorFactory added in v0.3.8

func WithExecutorFactory(factory func(execContext *ExecutionContext, job *Job) (ExecutorIface, error)) Opts

func WithGracefulCtx

func WithGracefulCtx(ctx context.Context) Opts

WithGracefulCtx uses the top most context to create child contexts this will ensure the cancellation is propagated properly down.

func WithVariables

func WithVariables(variables *variables.Variables) Opts

WithVariables adds provided variables to task runner

type Runner

type Runner interface {
	Run(t *task.Task) error
	Cancel()
	Finish()
}

Runner describes tasks runner interface

type TaskCompiler

type TaskCompiler struct {
	// contains filtered or unexported fields
}

TaskCompiler compiles tasks into jobs for executor

func NewTaskCompiler

func NewTaskCompiler() *TaskCompiler

NewTaskCompiler create new TaskCompiler instance

func (*TaskCompiler) CompileTask

func (tc *TaskCompiler) CompileTask(t *task.Task, executionContext *ExecutionContext, stdin io.Reader, stdout, stderr io.Writer, env, vars *variables.Variables) (*Job, error)

CompileTask compiles task into Job (linked list of commands) executed by Executor

type TaskRunner

type TaskRunner struct {
	DryRun bool

	Stdin          io.Reader
	Stdout, Stderr io.Writer
	OutputFormat   string
	// contains filtered or unexported fields
}

TaskRunner struct holds the properties and methods for running the tasks inside the given executor

func NewTaskRunner

func NewTaskRunner(opts ...Opts) (*TaskRunner, error)

NewTaskRunner creates new TaskRunner instance

func (*TaskRunner) Cancel

func (r *TaskRunner) Cancel()

Cancel cancels execution

func (*TaskRunner) Finish

func (r *TaskRunner) Finish()

Finish makes cleanup tasks over contexts

func (*TaskRunner) Run

func (r *TaskRunner) Run(t *task.Task) error

Run runs provided task. TaskRunner first compiles task into linked list of Jobs, then passes those jobs to Executor

Env on the runner is global to all tasks it is built using the dotenv output only for now

Example

TODO: What is this, was it meant to be a test?

package main

import (
	"bytes"
	"fmt"

	"github.com/Ensono/eirctl/output"
	"github.com/Ensono/eirctl/runner"

	taskpkg "github.com/Ensono/eirctl/task"
)

func main() {
	t := taskpkg.FromCommands("t1", "go doc github.com/Ensono/eirctl/runner.Runner")
	ob := output.NewSafeWriter(&bytes.Buffer{})
	r, err := runner.NewTaskRunner(func(tr *runner.TaskRunner) {
		tr.Stdout = ob
	})
	if err != nil {
		return
	}
	err = r.Run(t)
	if err != nil {
		fmt.Println(err, t.ExitCode(), t.ErrorMessage())
	}
	fmt.Println(ob.String())
	// indentation is important with the matched output here
	

func (*TaskRunner) SetContexts

func (r *TaskRunner) SetContexts(contexts map[string]*ExecutionContext) *TaskRunner

SetContexts sets task runner's contexts

func (*TaskRunner) SetVariables

func (r *TaskRunner) SetVariables(vars *variables.Variables) *TaskRunner

SetVariables sets task runner's variables

func (*TaskRunner) WithVariable

func (r *TaskRunner) WithVariable(key, value string) *TaskRunner

WithVariable adds variable to task runner's variables list. It creates new instance of variables container.

type Terminal added in v0.3.7

type Terminal interface {
	MakeRaw(fd int) (*term.State, error)
	Restore(fd int, state *term.State) error
	IsTerminal(fd int) bool
	GetSize(fd int) (width, height int, err error)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL