runner

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Mar 12, 2025 License: GPL-3.0 Imports: 27 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

This section is empty.

Variables

View Source
var (
	ErrImagePull        = errors.New("failed to pull container image")
	ErrContainerCreate  = errors.New("failed to create 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")
)
View Source
var ErrArtifactFailed = errors.New("artifact not processed")
View Source
var ErrMutuallyExclusiveVarSet = errors.New("mutually exclusive vars have been set")

Functions

func IsExitStatus

func IsExitStatus(err error) (uint8, bool)

IsExitStatus checks if given `err` is an exit status

Types

type ContainerContext

type ContainerContext struct {
	Name       string
	Entrypoint []string
	ShellArgs  []string
	// contains filtered or unexported fields
}

func NewContainerContext

func NewContainerContext(name string) *ContainerContext

func (*ContainerContext) Volumes

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

func (*ContainerContext) VolumesFromArgs

func (c *ContainerContext) VolumesFromArgs(cargs []string) *ContainerContext

func (*ContainerContext) WithVolumes

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

type ContainerExecutor

type ContainerExecutor struct {
	// 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, name string, dstOutput io.Writer) 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
	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)
}

ContainerExecutorIface interface used by this implementation

type ContainerOpts

type ContainerOpts func(*ContainerExecutor)

func WithClient

func WithClient(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 {
	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)

type ExecutorType

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

type Job

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

	Stdout, Stderr io.Writer
	Stdin          io.Reader

	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 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) CompileCommand

func (tc *TaskCompiler) CompileCommand(
	taskName string,
	command string,
	executionCtx *ExecutionContext,
	dir string,
	timeout *time.Duration,
	stdin io.Reader,
	stdout, stderr io.Writer,
	env, vars *variables.Variables,
) (*Job, error)

CompileCommand compiles command into Job

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 {
	Executor Executor
	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
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.

Jump to

Keyboard shortcuts

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