executor.go 2.85 KB
Newer Older
Kamil Trzciński's avatar
Kamil Trzciński committed
1 2
package common

Kamil Trzciński's avatar
Kamil Trzciński committed
3
import (
4
	"context"
5
	"errors"
Kamil Trzciński's avatar
Kamil Trzciński committed
6
	"fmt"
Kamil Trzciński's avatar
Kamil Trzciński committed
7

8
	"github.com/sirupsen/logrus"
Kamil Trzciński's avatar
Kamil Trzciński committed
9 10
)

11 12
type ExecutorData interface{}

13
type ExecutorCommand struct {
14
	Script     string
Kamil Trzciński's avatar
Kamil Trzciński committed
15
	Stage      BuildStage
16
	Predefined bool
17
	Context    context.Context
18 19
}

20 21 22 23 24 25 26 27 28
type ExecutorStage string

const (
	ExecutorStageCreated ExecutorStage = "created"
	ExecutorStagePrepare ExecutorStage = "prepare"
	ExecutorStageFinish  ExecutorStage = "finish"
	ExecutorStageCleanup ExecutorStage = "cleanup"
)

29
type ExecutorPrepareOptions struct {
30 31 32 33 34
	Config  *RunnerConfig
	Build   *Build
	Trace   JobTrace
	User    string
	Context context.Context
35 36
}

Kamil Trzciński's avatar
Kamil Trzciński committed
37
type Executor interface {
38
	Shell() *ShellScriptInfo
39
	Prepare(options ExecutorPrepareOptions) error
40
	Run(cmd ExecutorCommand) error
41
	Finish(err error)
Kamil Trzciński's avatar
Kamil Trzciński committed
42
	Cleanup()
43 44
	GetCurrentStage() ExecutorStage
	SetCurrentStage(stage ExecutorStage)
Kamil Trzciński's avatar
Kamil Trzciński committed
45 46
}

47 48 49
type ExecutorProvider interface {
	CanCreate() bool
	Create() Executor
50
	Acquire(config *RunnerConfig) (ExecutorData, error)
51
	Release(config *RunnerConfig, data ExecutorData)
52 53
	GetFeatures(features *FeaturesInfo) error
	GetDefaultShell() string
54 55
}

Kamil Trzciński's avatar
Kamil Trzciński committed
56
type BuildError struct {
Shinya Maeda's avatar
Shinya Maeda committed
57
	Inner         error
58
	FailureReason JobFailureReason
Kamil Trzciński's avatar
Kamil Trzciński committed
59 60 61 62 63 64 65 66 67 68
}

func (b *BuildError) Error() string {
	if b.Inner == nil {
		return "error"
	}

	return b.Inner.Error()
}

69 70 71 72 73 74
func MakeBuildError(format string, args ...interface{}) error {
	return &BuildError{
		Inner: fmt.Errorf(format, args...),
	}
}

75 76 77
type ExecutorProvidersMap map[string]ExecutorProvider

var executors ExecutorProvidersMap
Kamil Trzciński's avatar
Kamil Trzciński committed
78

79 80 81 82 83
func validateExecutorProvider(provider ExecutorProvider) error {
	if provider.GetDefaultShell() == "" {
		return errors.New("default shell not implemented")
	}

84
	if !provider.CanCreate() {
85 86 87
		return errors.New("cannot create executor")
	}

Kamil Trzciński's avatar
Kamil Trzciński committed
88 89
	if err := provider.GetFeatures(&FeaturesInfo{}); err != nil {
		return fmt.Errorf("cannot get features: %v", err)
90 91 92 93 94
	}

	return nil
}

95
func RegisterExecutor(executor string, provider ExecutorProvider) {
96
	logrus.Debugln("Registering", executor, "executor...")
Kamil Trzciński's avatar
Kamil Trzciński committed
97

98 99 100 101
	if err := validateExecutorProvider(provider); err != nil {
		panic("Executor cannot be registered: " + err.Error())
	}

Kamil Trzciński's avatar
Kamil Trzciński committed
102
	if executors == nil {
103
		executors = make(map[string]ExecutorProvider)
Kamil Trzciński's avatar
Kamil Trzciński committed
104
	}
105
	if _, ok := executors[executor]; ok {
Kamil Trzciński's avatar
Kamil Trzciński committed
106 107
		panic("Executor already exist: " + executor)
	}
108
	executors[executor] = provider
Kamil Trzciński's avatar
Kamil Trzciński committed
109 110
}

111
func GetExecutor(executor string) ExecutorProvider {
112 113 114 115
	if executors == nil {
		return nil
	}

116 117 118
	provider, _ := executors[executor]
	return provider
}
119

120 121 122 123 124 125
func GetExecutors() []string {
	names := []string{}
	if executors != nil {
		for name := range executors {
			names = append(names, name)
		}
126
	}
127
	return names
128 129
}

130
func GetExecutorProviders() (providers ExecutorProvidersMap) {
131
	if executors != nil {
132
		return executors
133
	}
134 135

	return make(ExecutorProvidersMap)
136 137
}

138
func NewExecutor(executor string) Executor {
139
	provider := GetExecutor(executor)
140 141
	if provider != nil {
		return provider.Create()
Kamil Trzciński's avatar
Kamil Trzciński committed
142 143
	}

144
	return nil
Kamil Trzciński's avatar
Kamil Trzciński committed
145
}