abstract polling and execution to runner-go library
This commit is contained in:
@@ -4,6 +4,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- abstract polling and execution to runner-go library
|
||||||
- use trace level logging for context errors
|
- use trace level logging for context errors
|
||||||
- prefix docker resource names
|
- prefix docker resource names
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/drone/runner-go/environ"
|
"github.com/drone/runner-go/environ"
|
||||||
"github.com/drone/runner-go/environ/provider"
|
"github.com/drone/runner-go/environ/provider"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
|
|
||||||
@@ -90,8 +91,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error {
|
|||||||
// lint the pipeline and return an error if any
|
// lint the pipeline and return an error if any
|
||||||
// linting rules are broken
|
// linting rules are broken
|
||||||
lint := linter.New()
|
lint := linter.New()
|
||||||
opts := linter.Opts{Trusted: c.Repo.Trusted}
|
err = lint.Lint(resource, c.Repo)
|
||||||
err = lint.Lint(resource, opts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error {
|
|||||||
comp.Mount, _ = os.Getwd()
|
comp.Mount, _ = os.Getwd()
|
||||||
}
|
}
|
||||||
|
|
||||||
args := compiler.Args{
|
args := runtime.CompilerArgs{
|
||||||
Pipeline: resource,
|
Pipeline: resource,
|
||||||
Manifest: manifest,
|
Manifest: manifest,
|
||||||
Build: c.Build,
|
Build: c.Build,
|
||||||
|
|||||||
@@ -13,15 +13,16 @@ import (
|
|||||||
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/match"
|
"github.com/drone-runners/drone-runner-docker/internal/match"
|
||||||
"github.com/drone-runners/drone-runner-docker/runtime"
|
|
||||||
|
|
||||||
"github.com/drone/runner-go/client"
|
"github.com/drone/runner-go/client"
|
||||||
"github.com/drone/runner-go/environ/provider"
|
"github.com/drone/runner-go/environ/provider"
|
||||||
"github.com/drone/runner-go/handler/router"
|
"github.com/drone/runner-go/handler/router"
|
||||||
"github.com/drone/runner-go/logger"
|
"github.com/drone/runner-go/logger"
|
||||||
loghistory "github.com/drone/runner-go/logger/history"
|
loghistory "github.com/drone/runner-go/logger/history"
|
||||||
"github.com/drone/runner-go/pipeline/history"
|
"github.com/drone/runner-go/pipeline/reporter/history"
|
||||||
"github.com/drone/runner-go/pipeline/remote"
|
"github.com/drone/runner-go/pipeline/reporter/remote"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
|
"github.com/drone/runner-go/poller"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
"github.com/drone/runner-go/server"
|
"github.com/drone/runner-go/server"
|
||||||
@@ -107,13 +108,12 @@ func (c *daemonCommand) run(*kingpin.ParseContext) error {
|
|||||||
hook := loghistory.New()
|
hook := loghistory.New()
|
||||||
logrus.AddHook(hook)
|
logrus.AddHook(hook)
|
||||||
|
|
||||||
poller := &runtime.Poller{
|
runner := &runtime.Runner{
|
||||||
Client: cli,
|
|
||||||
Runner: &runtime.Runner{
|
|
||||||
Client: cli,
|
Client: cli,
|
||||||
Machine: config.Runner.Name,
|
Machine: config.Runner.Name,
|
||||||
Reporter: tracer,
|
Reporter: tracer,
|
||||||
Linter: linter.New(),
|
Lookup: resource.Lookup,
|
||||||
|
Lint: linter.New().Lint,
|
||||||
Match: match.Func(
|
Match: match.Func(
|
||||||
config.Limit.Repos,
|
config.Limit.Repos,
|
||||||
config.Limit.Events,
|
config.Limit.Events,
|
||||||
@@ -161,13 +161,17 @@ func (c *daemonCommand) run(*kingpin.ParseContext) error {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
Execer: runtime.NewExecer(
|
Exec: runtime.NewExecer(
|
||||||
tracer,
|
tracer,
|
||||||
remote,
|
remote,
|
||||||
engine,
|
engine,
|
||||||
config.Runner.Procs,
|
config.Runner.Procs,
|
||||||
),
|
).Exec,
|
||||||
},
|
}
|
||||||
|
|
||||||
|
poller := &poller.Poller{
|
||||||
|
Client: cli,
|
||||||
|
Dispatch: runner.Run,
|
||||||
Filter: &client.Filter{
|
Filter: &client.Filter{
|
||||||
Kind: resource.Kind,
|
Kind: resource.Kind,
|
||||||
Type: resource.Type,
|
Type: resource.Type,
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/drone-runners/drone-runner-docker/engine/compiler"
|
"github.com/drone-runners/drone-runner-docker/engine/compiler"
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
"github.com/drone-runners/drone-runner-docker/runtime"
|
|
||||||
"github.com/drone/drone-go/drone"
|
"github.com/drone/drone-go/drone"
|
||||||
"github.com/drone/envsubst"
|
"github.com/drone/envsubst"
|
||||||
"github.com/drone/runner-go/environ"
|
"github.com/drone/runner-go/environ"
|
||||||
@@ -26,7 +25,8 @@ import (
|
|||||||
"github.com/drone/runner-go/logger"
|
"github.com/drone/runner-go/logger"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
"github.com/drone/runner-go/pipeline"
|
"github.com/drone/runner-go/pipeline"
|
||||||
"github.com/drone/runner-go/pipeline/console"
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
|
"github.com/drone/runner-go/pipeline/streamer/console"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
"github.com/drone/signal"
|
"github.com/drone/signal"
|
||||||
@@ -102,7 +102,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
|
|
||||||
// a configuration can contain multiple pipelines.
|
// a configuration can contain multiple pipelines.
|
||||||
// get a specific pipeline resource for execution.
|
// get a specific pipeline resource for execution.
|
||||||
resource, err := resource.Lookup(c.Stage.Name, manifest)
|
res, err := resource.Lookup(c.Stage.Name, manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -110,8 +110,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
// lint the pipeline and return an error if any
|
// lint the pipeline and return an error if any
|
||||||
// linting rules are broken
|
// linting rules are broken
|
||||||
lint := linter.New()
|
lint := linter.New()
|
||||||
opts := linter.Opts{Trusted: c.Repo.Trusted}
|
err = lint.Lint(res, c.Repo)
|
||||||
err = lint.Lint(resource, opts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -137,8 +136,8 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
comp.Mount, _ = os.Getwd()
|
comp.Mount, _ = os.Getwd()
|
||||||
}
|
}
|
||||||
|
|
||||||
args := compiler.Args{
|
args := runtime.CompilerArgs{
|
||||||
Pipeline: resource,
|
Pipeline: res,
|
||||||
Manifest: manifest,
|
Manifest: manifest,
|
||||||
Build: c.Build,
|
Build: c.Build,
|
||||||
Netrc: c.Netrc,
|
Netrc: c.Netrc,
|
||||||
@@ -146,7 +145,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
Stage: c.Stage,
|
Stage: c.Stage,
|
||||||
System: c.System,
|
System: c.System,
|
||||||
}
|
}
|
||||||
spec := comp.Compile(nocontext, args)
|
spec := comp.Compile(nocontext, args).(*engine.Spec)
|
||||||
|
|
||||||
// include only steps that are in the include list,
|
// include only steps that are in the include list,
|
||||||
// if the list in non-empty.
|
// if the list in non-empty.
|
||||||
@@ -161,7 +160,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
continue I
|
continue I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
step.RunPolicy = engine.RunNever
|
step.RunPolicy = runtime.RunNever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +174,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
}
|
}
|
||||||
for _, name := range c.Exclude {
|
for _, name := range c.Exclude {
|
||||||
if step.Name == name {
|
if step.Name == name {
|
||||||
step.RunPolicy = engine.RunNever
|
step.RunPolicy = runtime.RunNever
|
||||||
continue E
|
continue E
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +183,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
|
|||||||
|
|
||||||
// create a step object for each pipeline step.
|
// create a step object for each pipeline step.
|
||||||
for _, step := range spec.Steps {
|
for _, step := range spec.Steps {
|
||||||
if step.RunPolicy == engine.RunNever {
|
if step.RunPolicy == runtime.RunNever {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.Stage.Steps = append(c.Stage.Steps, &drone.Step{
|
c.Stage.Steps = append(c.Stage.Steps, &drone.Step{
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/drone-runners/drone-runner-docker/engine"
|
"github.com/drone-runners/drone-runner-docker/engine"
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// default name of the clone step.
|
// default name of the clone step.
|
||||||
@@ -47,7 +48,7 @@ func createClone(src *resource.Pipeline) *engine.Step {
|
|||||||
return &engine.Step{
|
return &engine.Step{
|
||||||
Name: cloneStepName,
|
Name: cloneStepName,
|
||||||
Image: cloneImage(src.Platform),
|
Image: cloneImage(src.Platform),
|
||||||
RunPolicy: engine.RunAlways,
|
RunPolicy: runtime.RunAlways,
|
||||||
Envs: cloneParams(src.Clone),
|
Envs: cloneParams(src.Clone),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/drone/drone-go/drone"
|
"github.com/drone/drone-go/drone"
|
||||||
"github.com/drone/runner-go/environ/provider"
|
"github.com/drone/runner-go/environ/provider"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func TestClone(t *testing.T) {
|
|||||||
Image: "drone/git:latest",
|
Image: "drone/git:latest",
|
||||||
Name: "clone",
|
Name: "clone",
|
||||||
Pull: engine.PullIfNotExists,
|
Pull: engine.PullIfNotExists,
|
||||||
RunPolicy: engine.RunAlways,
|
RunPolicy: runtime.RunAlways,
|
||||||
WorkingDir: "/drone/src",
|
WorkingDir: "/drone/src",
|
||||||
Volumes: []*engine.VolumeMount{
|
Volumes: []*engine.VolumeMount{
|
||||||
&engine.VolumeMount{
|
&engine.VolumeMount{
|
||||||
@@ -88,7 +89,7 @@ func TestCloneCreate(t *testing.T) {
|
|||||||
want := &engine.Step{
|
want := &engine.Step{
|
||||||
Name: "clone",
|
Name: "clone",
|
||||||
Image: "drone/git:latest",
|
Image: "drone/git:latest",
|
||||||
RunPolicy: engine.RunAlways,
|
RunPolicy: runtime.RunAlways,
|
||||||
Envs: map[string]string{"PLUGIN_DEPTH": "50"},
|
Envs: map[string]string{"PLUGIN_DEPTH": "50"},
|
||||||
}
|
}
|
||||||
src := &resource.Pipeline{Clone: manifest.Clone{Depth: 50}}
|
src := &resource.Pipeline{Clone: manifest.Clone{Depth: 50}}
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ import (
|
|||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
||||||
|
|
||||||
"github.com/drone/drone-go/drone"
|
|
||||||
"github.com/drone/runner-go/clone"
|
"github.com/drone/runner-go/clone"
|
||||||
"github.com/drone/runner-go/environ"
|
"github.com/drone/runner-go/environ"
|
||||||
"github.com/drone/runner-go/environ/provider"
|
"github.com/drone/runner-go/environ/provider"
|
||||||
"github.com/drone/runner-go/labels"
|
"github.com/drone/runner-go/labels"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/registry/auths"
|
"github.com/drone/runner-go/registry/auths"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
@@ -52,51 +52,9 @@ type Resources struct {
|
|||||||
CPUSet []string
|
CPUSet []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Args provides compiler arguments.
|
|
||||||
type Args struct {
|
|
||||||
// Manifest provides the parsed manifest.
|
|
||||||
Manifest *manifest.Manifest
|
|
||||||
|
|
||||||
// Pipeline provides the parsed pipeline. This pipeline is
|
|
||||||
// the compiler source and is converted to the intermediate
|
|
||||||
// representation by the Compile method.
|
|
||||||
Pipeline *resource.Pipeline
|
|
||||||
|
|
||||||
// Build provides the compiler with stage information that
|
|
||||||
// is converted to environment variable format and passed to
|
|
||||||
// each pipeline step. It is also used to clone the commit.
|
|
||||||
Build *drone.Build
|
|
||||||
|
|
||||||
// Stage provides the compiler with stage information that
|
|
||||||
// is converted to environment variable format and passed to
|
|
||||||
// each pipeline step.
|
|
||||||
Stage *drone.Stage
|
|
||||||
|
|
||||||
// Repo provides the compiler with repo information. This
|
|
||||||
// repo information is converted to environment variable
|
|
||||||
// format and passed to each pipeline step. It is also used
|
|
||||||
// to clone the repository.
|
|
||||||
Repo *drone.Repo
|
|
||||||
|
|
||||||
// System provides the compiler with system information that
|
|
||||||
// is converted to environment variable format and passed to
|
|
||||||
// each pipeline step.
|
|
||||||
System *drone.System
|
|
||||||
|
|
||||||
// Netrc provides netrc parameters that can be used by the
|
|
||||||
// default clone step to authenticate to the remote
|
|
||||||
// repository.
|
|
||||||
Netrc *drone.Netrc
|
|
||||||
|
|
||||||
// Secret returns a named secret value that can be injected
|
|
||||||
// into the pipeline step.
|
|
||||||
Secret secret.Provider
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compiler compiles the Yaml configuration file to an
|
// Compiler compiles the Yaml configuration file to an
|
||||||
// intermediate representation optimized for simple execution.
|
// intermediate representation optimized for simple execution.
|
||||||
type Compiler struct {
|
type Compiler struct {
|
||||||
|
|
||||||
// Environ provides a set of environment variables that
|
// Environ provides a set of environment variables that
|
||||||
// should be added to each pipeline step by default.
|
// should be added to each pipeline step by default.
|
||||||
Environ provider.Provider
|
Environ provider.Provider
|
||||||
@@ -139,11 +97,12 @@ type Compiler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile compiles the configuration file.
|
// Compile compiles the configuration file.
|
||||||
func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runtime.Spec {
|
||||||
os := args.Pipeline.Platform.OS
|
pipeline := args.Pipeline.(*resource.Pipeline)
|
||||||
|
os := pipeline.Platform.OS
|
||||||
|
|
||||||
// create the workspace paths
|
// create the workspace paths
|
||||||
base, path, full := createWorkspace(args.Pipeline)
|
base, path, full := createWorkspace(pipeline)
|
||||||
|
|
||||||
// if the source code is mounted from the host, the
|
// if the source code is mounted from the host, the
|
||||||
// target mount path inside the container must be the
|
// target mount path inside the container must be the
|
||||||
@@ -197,10 +156,10 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Platform: engine.Platform{
|
Platform: engine.Platform{
|
||||||
OS: args.Pipeline.Platform.OS,
|
OS: pipeline.Platform.OS,
|
||||||
Arch: args.Pipeline.Platform.Arch,
|
Arch: pipeline.Platform.Arch,
|
||||||
Variant: args.Pipeline.Platform.Variant,
|
Variant: pipeline.Platform.Variant,
|
||||||
Version: args.Pipeline.Platform.Version,
|
Version: pipeline.Platform.Version,
|
||||||
},
|
},
|
||||||
Volumes: []*engine.Volume{volume},
|
Volumes: []*engine.Volume{volume},
|
||||||
}
|
}
|
||||||
@@ -215,7 +174,7 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
envs = environ.Combine(
|
envs = environ.Combine(
|
||||||
envs,
|
envs,
|
||||||
args.Build.Params,
|
args.Build.Params,
|
||||||
args.Pipeline.Environment,
|
pipeline.Environment,
|
||||||
environ.Proxy(),
|
environ.Proxy(),
|
||||||
environ.System(args.System),
|
environ.System(args.System),
|
||||||
environ.Repo(args.Repo),
|
environ.Repo(args.Repo),
|
||||||
@@ -223,8 +182,8 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
environ.Stage(args.Stage),
|
environ.Stage(args.Stage),
|
||||||
environ.Link(args.Repo, args.Build, args.System),
|
environ.Link(args.Repo, args.Build, args.System),
|
||||||
clone.Environ(clone.Config{
|
clone.Environ(clone.Config{
|
||||||
SkipVerify: args.Pipeline.Clone.SkipVerify,
|
SkipVerify: pipeline.Clone.SkipVerify,
|
||||||
Trace: args.Pipeline.Clone.Trace,
|
Trace: pipeline.Clone.Trace,
|
||||||
User: clone.User{
|
User: clone.User{
|
||||||
Name: args.Build.AuthorName,
|
Name: args.Build.AuthorName,
|
||||||
Email: args.Build.AuthorEmail,
|
Email: args.Build.AuthorEmail,
|
||||||
@@ -272,8 +231,8 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create the clone step
|
// create the clone step
|
||||||
if args.Pipeline.Clone.Disable == false {
|
if pipeline.Clone.Disable == false {
|
||||||
step := createClone(args.Pipeline)
|
step := createClone(pipeline)
|
||||||
step.ID = random()
|
step.ID = random()
|
||||||
step.Envs = environ.Combine(envs, step.Envs)
|
step.Envs = environ.Combine(envs, step.Envs)
|
||||||
step.WorkingDir = full
|
step.WorkingDir = full
|
||||||
@@ -291,13 +250,13 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
// if the repository is mounted from a local
|
// if the repository is mounted from a local
|
||||||
// volume we should disable cloning.
|
// volume we should disable cloning.
|
||||||
if c.Mount != "" {
|
if c.Mount != "" {
|
||||||
step.RunPolicy = engine.RunNever
|
step.RunPolicy = runtime.RunNever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create steps
|
// create steps
|
||||||
for _, src := range args.Pipeline.Services {
|
for _, src := range pipeline.Services {
|
||||||
dst := createStep(args.Pipeline, src)
|
dst := createStep(pipeline, src)
|
||||||
dst.Detach = true
|
dst.Detach = true
|
||||||
dst.Envs = environ.Combine(envs, dst.Envs)
|
dst.Envs = environ.Combine(envs, dst.Envs)
|
||||||
dst.Volumes = append(dst.Volumes, mount)
|
dst.Volumes = append(dst.Volumes, mount)
|
||||||
@@ -309,13 +268,13 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
// if the pipeline step has unmet conditions the step is
|
// if the pipeline step has unmet conditions the step is
|
||||||
// automatically skipped.
|
// automatically skipped.
|
||||||
if !src.When.Match(match) {
|
if !src.When.Match(match) {
|
||||||
dst.RunPolicy = engine.RunNever
|
dst.RunPolicy = runtime.RunNever
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create steps
|
// create steps
|
||||||
for _, src := range args.Pipeline.Steps {
|
for _, src := range pipeline.Steps {
|
||||||
dst := createStep(args.Pipeline, src)
|
dst := createStep(pipeline, src)
|
||||||
dst.Envs = environ.Combine(envs, dst.Envs)
|
dst.Envs = environ.Combine(envs, dst.Envs)
|
||||||
dst.Volumes = append(dst.Volumes, mount)
|
dst.Volumes = append(dst.Volumes, mount)
|
||||||
dst.Labels = labels
|
dst.Labels = labels
|
||||||
@@ -326,7 +285,7 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
// if the pipeline step has unmet conditions the step is
|
// if the pipeline step has unmet conditions the step is
|
||||||
// automatically skipped.
|
// automatically skipped.
|
||||||
if !src.When.Match(match) {
|
if !src.When.Match(match) {
|
||||||
dst.RunPolicy = engine.RunNever
|
dst.RunPolicy = runtime.RunNever
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the pipeline step has an approved image, it is
|
// if the pipeline step has an approved image, it is
|
||||||
@@ -339,9 +298,9 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
|
|
||||||
if isGraph(spec) == false {
|
if isGraph(spec) == false {
|
||||||
configureSerial(spec)
|
configureSerial(spec)
|
||||||
} else if args.Pipeline.Clone.Disable == false {
|
} else if pipeline.Clone.Disable == false {
|
||||||
configureCloneDeps(spec)
|
configureCloneDeps(spec)
|
||||||
} else if args.Pipeline.Clone.Disable == true {
|
} else if pipeline.Clone.Disable == true {
|
||||||
removeCloneDeps(spec)
|
removeCloneDeps(spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +324,7 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get registry credentials from secrets
|
// get registry credentials from secrets
|
||||||
for _, name := range args.Pipeline.PullSecrets {
|
for _, name := range pipeline.PullSecrets {
|
||||||
secret, ok := c.findSecret(ctx, args, name)
|
secret, ok := c.findSecret(ctx, args, name)
|
||||||
if ok {
|
if ok {
|
||||||
parsed, err := auths.ParseString(secret)
|
parsed, err := auths.ParseString(secret)
|
||||||
@@ -425,7 +384,7 @@ func (c *Compiler) Compile(ctx context.Context, args Args) *engine.Spec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// append volumes
|
// append volumes
|
||||||
for _, v := range args.Pipeline.Volumes {
|
for _, v := range pipeline.Volumes {
|
||||||
id := random()
|
id := random()
|
||||||
src := new(engine.Volume)
|
src := new(engine.Volume)
|
||||||
if v.EmptyDir != nil {
|
if v.EmptyDir != nil {
|
||||||
@@ -478,7 +437,7 @@ func (c *Compiler) isPrivileged(step *resource.Step) bool {
|
|||||||
|
|
||||||
// helper function attempts to find and return the named secret.
|
// helper function attempts to find and return the named secret.
|
||||||
// from the secret provider.
|
// from the secret provider.
|
||||||
func (c *Compiler) findSecret(ctx context.Context, args Args, name string) (s string, ok bool) {
|
func (c *Compiler) findSecret(ctx context.Context, args runtime.CompilerArgs, name string) (s string, ok bool) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/drone/drone-go/drone"
|
"github.com/drone/drone-go/drone"
|
||||||
"github.com/drone/runner-go/environ/provider"
|
"github.com/drone/runner-go/environ/provider"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
"github.com/drone/runner-go/registry"
|
"github.com/drone/runner-go/registry"
|
||||||
"github.com/drone/runner-go/secret"
|
"github.com/drone/runner-go/secret"
|
||||||
|
|
||||||
@@ -65,10 +66,10 @@ func TestCompile_CloneDisabled_Graph(t *testing.T) {
|
|||||||
// defined in the when block are not satisfied.
|
// defined in the when block are not satisfied.
|
||||||
func TestCompile_Match(t *testing.T) {
|
func TestCompile_Match(t *testing.T) {
|
||||||
ir := testCompile(t, "testdata/match.yml", "testdata/match.json")
|
ir := testCompile(t, "testdata/match.yml", "testdata/match.json")
|
||||||
if ir.Steps[0].RunPolicy != engine.RunOnSuccess {
|
if ir.Steps[0].RunPolicy != runtime.RunOnSuccess {
|
||||||
t.Errorf("Expect run on success")
|
t.Errorf("Expect run on success")
|
||||||
}
|
}
|
||||||
if ir.Steps[1].RunPolicy != engine.RunNever {
|
if ir.Steps[1].RunPolicy != runtime.RunNever {
|
||||||
t.Errorf("Expect run never")
|
t.Errorf("Expect run never")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,7 @@ func TestCompile_Match(t *testing.T) {
|
|||||||
// success or failure are configured to always run.
|
// success or failure are configured to always run.
|
||||||
func TestCompile_RunAlways(t *testing.T) {
|
func TestCompile_RunAlways(t *testing.T) {
|
||||||
ir := testCompile(t, "testdata/run_always.yml", "testdata/run_always.json")
|
ir := testCompile(t, "testdata/run_always.yml", "testdata/run_always.json")
|
||||||
if ir.Steps[0].RunPolicy != engine.RunAlways {
|
if ir.Steps[0].RunPolicy != runtime.RunAlways {
|
||||||
t.Errorf("Expect run always")
|
t.Errorf("Expect run always")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,7 @@ func TestCompile_RunAlways(t *testing.T) {
|
|||||||
// are configured to run on failure.
|
// are configured to run on failure.
|
||||||
func TestCompile_RunFailure(t *testing.T) {
|
func TestCompile_RunFailure(t *testing.T) {
|
||||||
ir := testCompile(t, "testdata/run_failure.yml", "testdata/run_failure.json")
|
ir := testCompile(t, "testdata/run_failure.yml", "testdata/run_failure.json")
|
||||||
if ir.Steps[0].RunPolicy != engine.RunOnFailure {
|
if ir.Steps[0].RunPolicy != runtime.RunOnFailure {
|
||||||
t.Errorf("Expect run on failure")
|
t.Errorf("Expect run on failure")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/encoder"
|
"github.com/drone-runners/drone-runner-docker/internal/encoder"
|
||||||
|
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createStep(spec *resource.Pipeline, src *resource.Step) *engine.Step {
|
func createStep(spec *resource.Pipeline, src *resource.Step) *engine.Step {
|
||||||
@@ -94,9 +96,9 @@ func createStep(spec *resource.Pipeline, src *resource.Step) *engine.Step {
|
|||||||
// success by default, but may be optionally configured
|
// success by default, but may be optionally configured
|
||||||
// to run on failure.
|
// to run on failure.
|
||||||
if isRunAlways(src) {
|
if isRunAlways(src) {
|
||||||
dst.RunPolicy = engine.RunAlways
|
dst.RunPolicy = runtime.RunAlways
|
||||||
} else if isRunOnFailure(src) {
|
} else if isRunOnFailure(src) {
|
||||||
dst.RunPolicy = engine.RunOnFailure
|
dst.RunPolicy = runtime.RunOnFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst
|
return dst
|
||||||
|
|||||||
@@ -61,58 +61,3 @@ func (p *PullPolicy) UnmarshalJSON(b []byte) error {
|
|||||||
*p = pullPolicyName[s]
|
*p = pullPolicyName[s]
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPolicy defines the policy for starting containers
|
|
||||||
// based on the point-in-time pass or fail state of
|
|
||||||
// the pipeline.
|
|
||||||
type RunPolicy int
|
|
||||||
|
|
||||||
// RunPolicy enumeration.
|
|
||||||
const (
|
|
||||||
RunOnSuccess RunPolicy = iota
|
|
||||||
RunOnFailure
|
|
||||||
RunAlways
|
|
||||||
RunNever
|
|
||||||
)
|
|
||||||
|
|
||||||
func (r RunPolicy) String() string {
|
|
||||||
return runPolicyID[r]
|
|
||||||
}
|
|
||||||
|
|
||||||
var runPolicyID = map[RunPolicy]string{
|
|
||||||
RunOnSuccess: "on-success",
|
|
||||||
RunOnFailure: "on-failure",
|
|
||||||
RunAlways: "always",
|
|
||||||
RunNever: "never",
|
|
||||||
}
|
|
||||||
|
|
||||||
var runPolicyName = map[string]RunPolicy{
|
|
||||||
"": RunOnSuccess,
|
|
||||||
"on-success": RunOnSuccess,
|
|
||||||
"on-failure": RunOnFailure,
|
|
||||||
"always": RunAlways,
|
|
||||||
"never": RunNever,
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON marshals the string representation of the
|
|
||||||
// run type to JSON.
|
|
||||||
func (r *RunPolicy) MarshalJSON() ([]byte, error) {
|
|
||||||
buffer := bytes.NewBufferString(`"`)
|
|
||||||
buffer.WriteString(runPolicyID[*r])
|
|
||||||
buffer.WriteString(`"`)
|
|
||||||
return buffer.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals the json representation of the
|
|
||||||
// run type from a string value.
|
|
||||||
func (r *RunPolicy) UnmarshalJSON(b []byte) error {
|
|
||||||
// unmarshal as string
|
|
||||||
var s string
|
|
||||||
err := json.Unmarshal(b, &s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// lookup value
|
|
||||||
*r = runPolicyName[s]
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,121 +10,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
//
|
|
||||||
// runtime policy unit tests.
|
|
||||||
//
|
|
||||||
|
|
||||||
func TestRunPolicy_Marshal(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
policy RunPolicy
|
|
||||||
data string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
policy: RunAlways,
|
|
||||||
data: `"always"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnFailure,
|
|
||||||
data: `"on-failure"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnSuccess,
|
|
||||||
data: `"on-success"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunNever,
|
|
||||||
data: `"never"`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
data, err := json.Marshal(&test.policy)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if bytes.Equal([]byte(test.data), data) == false {
|
|
||||||
t.Errorf("Failed to marshal policy %s", test.policy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunPolicy_Unmarshal(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
policy RunPolicy
|
|
||||||
data string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
policy: RunAlways,
|
|
||||||
data: `"always"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnFailure,
|
|
||||||
data: `"on-failure"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnSuccess,
|
|
||||||
data: `"on-success"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunNever,
|
|
||||||
data: `"never"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// no policy should default to on-success
|
|
||||||
policy: RunOnSuccess,
|
|
||||||
data: `""`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
var policy RunPolicy
|
|
||||||
err := json.Unmarshal([]byte(test.data), &policy)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if got, want := policy, test.policy; got != want {
|
|
||||||
t.Errorf("Want policy %q, got %q", want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunPolicy_UnmarshalTypeError(t *testing.T) {
|
|
||||||
var policy RunPolicy
|
|
||||||
err := json.Unmarshal([]byte("[]"), &policy)
|
|
||||||
if _, ok := err.(*json.UnmarshalTypeError); !ok {
|
|
||||||
t.Errorf("Expect unmarshal error return when JSON invalid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunPolicy_String(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
policy RunPolicy
|
|
||||||
value string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
policy: RunAlways,
|
|
||||||
value: "always",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnFailure,
|
|
||||||
value: "on-failure",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
policy: RunOnSuccess,
|
|
||||||
value: "on-success",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
if got, want := test.policy.String(), test.value; got != want {
|
|
||||||
t.Errorf("Want policy string %q, got %q", want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// pull policy unit tests.
|
|
||||||
//
|
|
||||||
|
|
||||||
func TestPullPolicy_Marshal(t *testing.T) {
|
func TestPullPolicy_Marshal(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
policy PullPolicy
|
policy PullPolicy
|
||||||
|
|||||||
293
engine/engine.go
293
engine/engine.go
@@ -7,17 +7,288 @@ package engine
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/drone-runners/drone-runner-docker/internal/docker/errors"
|
||||||
|
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
||||||
|
"github.com/drone-runners/drone-runner-docker/internal/docker/jsonmessage"
|
||||||
|
"github.com/drone-runners/drone-runner-docker/internal/docker/stdcopy"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
|
"github.com/drone/runner-go/registry/auths"
|
||||||
|
|
||||||
|
"docker.io/go-docker"
|
||||||
|
"docker.io/go-docker/api/types"
|
||||||
|
"docker.io/go-docker/api/types/network"
|
||||||
|
"docker.io/go-docker/api/types/volume"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Engine is the interface that must be implemented by a
|
// Opts configures the Docker engine.
|
||||||
// pipeline execution engine.
|
type Opts struct {
|
||||||
type Engine interface {
|
HidePull bool
|
||||||
// Setup the pipeline environment.
|
}
|
||||||
Setup(context.Context, *Spec) error
|
|
||||||
|
// Docker implements a Docker pipeline engine.
|
||||||
// Destroy the pipeline environment.
|
type Docker struct {
|
||||||
Destroy(context.Context, *Spec) error
|
client docker.APIClient
|
||||||
|
hidePull bool
|
||||||
// Run runs the pipeine step.
|
}
|
||||||
Run(context.Context, *Spec, *Step, io.Writer) (*State, error)
|
|
||||||
|
// New returns a new engine.
|
||||||
|
func New(client docker.APIClient, opts Opts) *Docker {
|
||||||
|
return &Docker{
|
||||||
|
client: client,
|
||||||
|
hidePull: opts.HidePull,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEnv returns a new Engine from the environment.
|
||||||
|
func NewEnv(opts Opts) (*Docker, error) {
|
||||||
|
cli, err := docker.NewEnvClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return New(cli, opts), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping pings the Docker daemon.
|
||||||
|
func (e *Docker) Ping(ctx context.Context) error {
|
||||||
|
_, err := e.client.Ping(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the pipeline environment.
|
||||||
|
func (e *Docker) Setup(ctx context.Context, specv runtime.Spec) error {
|
||||||
|
spec := specv.(*Spec)
|
||||||
|
|
||||||
|
// creates the default temporary (local) volumes
|
||||||
|
// that are mounted into each container step.
|
||||||
|
for _, vol := range spec.Volumes {
|
||||||
|
if vol.EmptyDir == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err := e.client.VolumeCreate(ctx, volume.VolumesCreateBody{
|
||||||
|
Name: vol.EmptyDir.ID,
|
||||||
|
Driver: "local",
|
||||||
|
Labels: vol.EmptyDir.Labels,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return errors.TrimExtraInfo(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates the default pod network. All containers
|
||||||
|
// defined in the pipeline are attached to this network.
|
||||||
|
driver := "bridge"
|
||||||
|
if spec.Platform.OS == "windows" {
|
||||||
|
driver = "nat"
|
||||||
|
}
|
||||||
|
_, err := e.client.NetworkCreate(ctx, spec.Network.ID, types.NetworkCreate{
|
||||||
|
Driver: driver,
|
||||||
|
Labels: spec.Network.Labels,
|
||||||
|
})
|
||||||
|
|
||||||
|
return errors.TrimExtraInfo(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the pipeline environment.
|
||||||
|
func (e *Docker) Destroy(ctx context.Context, specv runtime.Spec) error {
|
||||||
|
spec := specv.(*Spec)
|
||||||
|
|
||||||
|
removeOpts := types.ContainerRemoveOptions{
|
||||||
|
Force: true,
|
||||||
|
RemoveLinks: false,
|
||||||
|
RemoveVolumes: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop all containers
|
||||||
|
for _, step := range spec.Steps {
|
||||||
|
e.client.ContainerKill(ctx, step.ID, "9")
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup all containers
|
||||||
|
for _, step := range spec.Steps {
|
||||||
|
e.client.ContainerRemove(ctx, step.ID, removeOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup all volumes
|
||||||
|
for _, vol := range spec.Volumes {
|
||||||
|
if vol.EmptyDir == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// tempfs volumes do not have a volume entry,
|
||||||
|
// and therefore do not require removal.
|
||||||
|
if vol.EmptyDir.Medium == "memory" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
e.client.VolumeRemove(ctx, vol.EmptyDir.ID, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup the network
|
||||||
|
e.client.NetworkRemove(ctx, spec.Network.ID)
|
||||||
|
|
||||||
|
// notice that we never collect or return any errors.
|
||||||
|
// this is because we silently ignore cleanup failures
|
||||||
|
// and instead ask the system admin to periodically run
|
||||||
|
// `docker prune` commands.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run runs the pipeline step.
|
||||||
|
func (e *Docker) Run(ctx context.Context, specv runtime.Spec, stepv runtime.Step, output io.Writer) (*runtime.State, error) {
|
||||||
|
spec := specv.(*Spec)
|
||||||
|
step := stepv.(*Step)
|
||||||
|
|
||||||
|
// create the container
|
||||||
|
err := e.create(ctx, spec, step, output)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.TrimExtraInfo(err)
|
||||||
|
}
|
||||||
|
// start the container
|
||||||
|
err = e.start(ctx, step.ID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.TrimExtraInfo(err)
|
||||||
|
}
|
||||||
|
// tail the container
|
||||||
|
err = e.tail(ctx, step.ID, output)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.TrimExtraInfo(err)
|
||||||
|
}
|
||||||
|
// wait for the response
|
||||||
|
return e.wait(ctx, step.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// emulate docker commands
|
||||||
|
//
|
||||||
|
|
||||||
|
func (e *Docker) create(ctx context.Context, spec *Spec, step *Step, output io.Writer) error {
|
||||||
|
// create pull options with encoded authorization credentials.
|
||||||
|
pullopts := types.ImagePullOptions{}
|
||||||
|
if step.Auth != nil {
|
||||||
|
pullopts.RegistryAuth = auths.Header(
|
||||||
|
step.Auth.Username,
|
||||||
|
step.Auth.Password,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// automatically pull the latest version of the image if requested
|
||||||
|
// by the process configuration, or if the image is :latest
|
||||||
|
if step.Pull == PullAlways ||
|
||||||
|
(step.Pull == PullDefault && image.IsLatest(step.Image)) {
|
||||||
|
rc, pullerr := e.client.ImagePull(ctx, step.Image, pullopts)
|
||||||
|
if pullerr == nil {
|
||||||
|
if e.hidePull {
|
||||||
|
io.Copy(ioutil.Discard, rc)
|
||||||
|
} else {
|
||||||
|
jsonmessage.Copy(rc, output)
|
||||||
|
}
|
||||||
|
rc.Close()
|
||||||
|
}
|
||||||
|
if pullerr != nil {
|
||||||
|
return pullerr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := e.client.ContainerCreate(ctx,
|
||||||
|
toConfig(spec, step),
|
||||||
|
toHostConfig(spec, step),
|
||||||
|
toNetConfig(spec, step),
|
||||||
|
step.ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
// automatically pull and try to re-create the image if the
|
||||||
|
// failure is caused because the image does not exist.
|
||||||
|
if docker.IsErrImageNotFound(err) && step.Pull != PullNever {
|
||||||
|
rc, pullerr := e.client.ImagePull(ctx, step.Image, pullopts)
|
||||||
|
if pullerr != nil {
|
||||||
|
return pullerr
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.hidePull {
|
||||||
|
io.Copy(ioutil.Discard, rc)
|
||||||
|
} else {
|
||||||
|
jsonmessage.Copy(rc, output)
|
||||||
|
}
|
||||||
|
rc.Close()
|
||||||
|
|
||||||
|
// once the image is successfully pulled we attempt to
|
||||||
|
// re-create the container.
|
||||||
|
_, err = e.client.ContainerCreate(ctx,
|
||||||
|
toConfig(spec, step),
|
||||||
|
toHostConfig(spec, step),
|
||||||
|
toNetConfig(spec, step),
|
||||||
|
step.ID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// attach the container to user-defined networks.
|
||||||
|
// primarily used to attach global user-defined networks.
|
||||||
|
if step.Network == "" {
|
||||||
|
for _, net := range step.Networks {
|
||||||
|
err = e.client.NetworkConnect(ctx, net, step.ID, &network.EndpointSettings{
|
||||||
|
Aliases: []string{net},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function emulates the `docker start` command.
|
||||||
|
func (e *Docker) start(ctx context.Context, id string) error {
|
||||||
|
return e.client.ContainerStart(ctx, id, types.ContainerStartOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function emulates the `docker wait` command, blocking
|
||||||
|
// until the container stops and returning the exit code.
|
||||||
|
func (e *Docker) wait(ctx context.Context, id string) (*runtime.State, error) {
|
||||||
|
wait, errc := e.client.ContainerWait(ctx, id, "")
|
||||||
|
select {
|
||||||
|
case <-wait:
|
||||||
|
case <-errc:
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := e.client.ContainerInspect(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if info.State.Running {
|
||||||
|
// TODO(bradrydewski) if the state is still running
|
||||||
|
// we should call wait again.
|
||||||
|
}
|
||||||
|
|
||||||
|
return &runtime.State{
|
||||||
|
Exited: true,
|
||||||
|
ExitCode: info.State.ExitCode,
|
||||||
|
OOMKilled: info.State.OOMKilled,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function emulates the `docker logs -f` command, streaming
|
||||||
|
// all container logs until the container stops.
|
||||||
|
func (e *Docker) tail(ctx context.Context, id string, output io.Writer) error {
|
||||||
|
opts := types.ContainerLogsOptions{
|
||||||
|
Follow: true,
|
||||||
|
ShowStdout: true,
|
||||||
|
ShowStderr: true,
|
||||||
|
Details: false,
|
||||||
|
Timestamps: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
logs, err := e.client.ContainerLogs(ctx, id, opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
stdcopy.StdCopy(output, output, logs)
|
||||||
|
logs.Close()
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package engine
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/errors"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/image"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/jsonmessage"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/internal/docker/stdcopy"
|
|
||||||
"github.com/drone/runner-go/registry/auths"
|
|
||||||
|
|
||||||
"docker.io/go-docker"
|
|
||||||
"docker.io/go-docker/api/types"
|
|
||||||
"docker.io/go-docker/api/types/network"
|
|
||||||
"docker.io/go-docker/api/types/volume"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Opts configures the Docker engine.
|
|
||||||
type Opts struct {
|
|
||||||
HidePull bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Docker implements a Docker pipeline engine.
|
|
||||||
type Docker struct {
|
|
||||||
client docker.APIClient
|
|
||||||
hidePull bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new engine.
|
|
||||||
func New(client docker.APIClient, opts Opts) *Docker {
|
|
||||||
return &Docker{
|
|
||||||
client: client,
|
|
||||||
hidePull: opts.HidePull,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEnv returns a new Engine from the environment.
|
|
||||||
func NewEnv(opts Opts) (*Docker, error) {
|
|
||||||
cli, err := docker.NewEnvClient()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return New(cli, opts), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ping pings the Docker daemon.
|
|
||||||
func (e *Docker) Ping(ctx context.Context) error {
|
|
||||||
_, err := e.client.Ping(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the pipeline environment.
|
|
||||||
func (e *Docker) Setup(ctx context.Context, spec *Spec) error {
|
|
||||||
// creates the default temporary (local) volumes
|
|
||||||
// that are mounted into each container step.
|
|
||||||
for _, vol := range spec.Volumes {
|
|
||||||
if vol.EmptyDir == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_, err := e.client.VolumeCreate(ctx, volume.VolumesCreateBody{
|
|
||||||
Name: vol.EmptyDir.ID,
|
|
||||||
Driver: "local",
|
|
||||||
Labels: vol.EmptyDir.Labels,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.TrimExtraInfo(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// creates the default pod network. All containers
|
|
||||||
// defined in the pipeline are attached to this network.
|
|
||||||
driver := "bridge"
|
|
||||||
if spec.Platform.OS == "windows" {
|
|
||||||
driver = "nat"
|
|
||||||
}
|
|
||||||
_, err := e.client.NetworkCreate(ctx, spec.Network.ID, types.NetworkCreate{
|
|
||||||
Driver: driver,
|
|
||||||
Labels: spec.Network.Labels,
|
|
||||||
})
|
|
||||||
|
|
||||||
return errors.TrimExtraInfo(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the pipeline environment.
|
|
||||||
func (e *Docker) Destroy(ctx context.Context, spec *Spec) error {
|
|
||||||
removeOpts := types.ContainerRemoveOptions{
|
|
||||||
Force: true,
|
|
||||||
RemoveLinks: false,
|
|
||||||
RemoveVolumes: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop all containers
|
|
||||||
for _, step := range spec.Steps {
|
|
||||||
e.client.ContainerKill(ctx, step.ID, "9")
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup all containers
|
|
||||||
for _, step := range spec.Steps {
|
|
||||||
e.client.ContainerRemove(ctx, step.ID, removeOpts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup all volumes
|
|
||||||
for _, vol := range spec.Volumes {
|
|
||||||
if vol.EmptyDir == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// tempfs volumes do not have a volume entry,
|
|
||||||
// and therefore do not require removal.
|
|
||||||
if vol.EmptyDir.Medium == "memory" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e.client.VolumeRemove(ctx, vol.EmptyDir.ID, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup the network
|
|
||||||
e.client.NetworkRemove(ctx, spec.Network.ID)
|
|
||||||
|
|
||||||
// notice that we never collect or return any errors.
|
|
||||||
// this is because we silently ignore cleanup failures
|
|
||||||
// and instead ask the system admin to periodically run
|
|
||||||
// `docker prune` commands.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run runs the pipeline step.
|
|
||||||
func (e *Docker) Run(ctx context.Context, spec *Spec, step *Step, output io.Writer) (*State, error) {
|
|
||||||
// create the container
|
|
||||||
err := e.create(ctx, spec, step, output)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.TrimExtraInfo(err)
|
|
||||||
}
|
|
||||||
// start the container
|
|
||||||
err = e.start(ctx, step.ID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.TrimExtraInfo(err)
|
|
||||||
}
|
|
||||||
// tail the container
|
|
||||||
err = e.tail(ctx, step.ID, output)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.TrimExtraInfo(err)
|
|
||||||
}
|
|
||||||
// wait for the response
|
|
||||||
return e.wait(ctx, step.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// emulate docker commands
|
|
||||||
//
|
|
||||||
|
|
||||||
func (e *Docker) create(ctx context.Context, spec *Spec, step *Step, output io.Writer) error {
|
|
||||||
// create pull options with encoded authorization credentials.
|
|
||||||
pullopts := types.ImagePullOptions{}
|
|
||||||
if step.Auth != nil {
|
|
||||||
pullopts.RegistryAuth = auths.Header(
|
|
||||||
step.Auth.Username,
|
|
||||||
step.Auth.Password,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// automatically pull the latest version of the image if requested
|
|
||||||
// by the process configuration, or if the image is :latest
|
|
||||||
if step.Pull == PullAlways ||
|
|
||||||
(step.Pull == PullDefault && image.IsLatest(step.Image)) {
|
|
||||||
rc, pullerr := e.client.ImagePull(ctx, step.Image, pullopts)
|
|
||||||
if pullerr == nil {
|
|
||||||
if e.hidePull {
|
|
||||||
io.Copy(ioutil.Discard, rc)
|
|
||||||
} else {
|
|
||||||
jsonmessage.Copy(rc, output)
|
|
||||||
}
|
|
||||||
rc.Close()
|
|
||||||
}
|
|
||||||
if pullerr != nil {
|
|
||||||
return pullerr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := e.client.ContainerCreate(ctx,
|
|
||||||
toConfig(spec, step),
|
|
||||||
toHostConfig(spec, step),
|
|
||||||
toNetConfig(spec, step),
|
|
||||||
step.ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
// automatically pull and try to re-create the image if the
|
|
||||||
// failure is caused because the image does not exist.
|
|
||||||
if docker.IsErrImageNotFound(err) && step.Pull != PullNever {
|
|
||||||
rc, pullerr := e.client.ImagePull(ctx, step.Image, pullopts)
|
|
||||||
if pullerr != nil {
|
|
||||||
return pullerr
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.hidePull {
|
|
||||||
io.Copy(ioutil.Discard, rc)
|
|
||||||
} else {
|
|
||||||
jsonmessage.Copy(rc, output)
|
|
||||||
}
|
|
||||||
rc.Close()
|
|
||||||
|
|
||||||
// once the image is successfully pulled we attempt to
|
|
||||||
// re-create the container.
|
|
||||||
_, err = e.client.ContainerCreate(ctx,
|
|
||||||
toConfig(spec, step),
|
|
||||||
toHostConfig(spec, step),
|
|
||||||
toNetConfig(spec, step),
|
|
||||||
step.ID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach the container to user-defined networks.
|
|
||||||
// primarily used to attach global user-defined networks.
|
|
||||||
if step.Network == "" {
|
|
||||||
for _, net := range step.Networks {
|
|
||||||
err = e.client.NetworkConnect(ctx, net, step.ID, &network.EndpointSettings{
|
|
||||||
Aliases: []string{net},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function emulates the `docker start` command.
|
|
||||||
func (e *Docker) start(ctx context.Context, id string) error {
|
|
||||||
return e.client.ContainerStart(ctx, id, types.ContainerStartOptions{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function emulates the `docker wait` command, blocking
|
|
||||||
// until the container stops and returning the exit code.
|
|
||||||
func (e *Docker) wait(ctx context.Context, id string) (*State, error) {
|
|
||||||
wait, errc := e.client.ContainerWait(ctx, id, "")
|
|
||||||
select {
|
|
||||||
case <-wait:
|
|
||||||
case <-errc:
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := e.client.ContainerInspect(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if info.State.Running {
|
|
||||||
// TODO(bradrydewski) if the state is still running
|
|
||||||
// we should call wait again.
|
|
||||||
}
|
|
||||||
|
|
||||||
return &State{
|
|
||||||
Exited: true,
|
|
||||||
ExitCode: info.State.ExitCode,
|
|
||||||
OOMKilled: info.State.OOMKilled,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function emulates the `docker logs -f` command, streaming
|
|
||||||
// all container logs until the container stops.
|
|
||||||
func (e *Docker) tail(ctx context.Context, id string, output io.Writer) error {
|
|
||||||
opts := types.ContainerLogsOptions{
|
|
||||||
Follow: true,
|
|
||||||
ShowStdout: true,
|
|
||||||
ShowStderr: true,
|
|
||||||
Details: false,
|
|
||||||
Timestamps: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
logs, err := e.client.ContainerLogs(ctx, id, opts)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
stdcopy.StdCopy(output, output, logs)
|
|
||||||
logs.Close()
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
|
"github.com/drone/drone-go/drone"
|
||||||
|
"github.com/drone/runner-go/manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrDuplicateStepName is returned when two Pipeline steps
|
// ErrDuplicateStepName is returned when two Pipeline steps
|
||||||
@@ -43,8 +45,8 @@ func New() *Linter {
|
|||||||
|
|
||||||
// Lint executes the linting rules for the pipeline
|
// Lint executes the linting rules for the pipeline
|
||||||
// configuration.
|
// configuration.
|
||||||
func (l *Linter) Lint(pipeline *resource.Pipeline, opts Opts) error {
|
func (l *Linter) Lint(pipeline manifest.Resource, repo *drone.Repo) error {
|
||||||
return checkPipeline(pipeline, opts.Trusted)
|
return checkPipeline(pipeline.(*resource.Pipeline), repo.Trusted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPipeline(pipeline *resource.Pipeline, trusted bool) error {
|
func checkPipeline(pipeline *resource.Pipeline, trusted bool) error {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
||||||
|
"github.com/drone/drone-go/drone"
|
||||||
"github.com/drone/runner-go/manifest"
|
"github.com/drone/runner-go/manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -212,7 +213,7 @@ func TestLint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lint := New()
|
lint := New()
|
||||||
opts := Opts{Trusted: test.trusted}
|
opts := &drone.Repo{Trusted: test.trusted}
|
||||||
err = lint.Lint(resources.Resources[0].(*resource.Pipeline), opts)
|
err = lint.Lint(resources.Resources[0].(*resource.Pipeline), opts)
|
||||||
if err == nil && test.invalid == true {
|
if err == nil && test.invalid == true {
|
||||||
t.Logf("yaml: %s", test.path)
|
t.Logf("yaml: %s", test.path)
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package replacer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine"
|
|
||||||
)
|
|
||||||
|
|
||||||
const maskedf = "[secret:%s]"
|
|
||||||
|
|
||||||
// Replacer is an io.Writer that finds and masks sensitive data.
|
|
||||||
type Replacer struct {
|
|
||||||
w io.WriteCloser
|
|
||||||
r *strings.Replacer
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a replacer that wraps writer w.
|
|
||||||
func New(w io.WriteCloser, secrets []*engine.Secret) io.WriteCloser {
|
|
||||||
var oldnew []string
|
|
||||||
for _, secret := range secrets {
|
|
||||||
if len(secret.Data) == 0 || secret.Mask == false {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.ToLower(secret.Name)
|
|
||||||
masked := fmt.Sprintf(maskedf, name)
|
|
||||||
oldnew = append(oldnew, string(secret.Data))
|
|
||||||
oldnew = append(oldnew, masked)
|
|
||||||
}
|
|
||||||
if len(oldnew) == 0 {
|
|
||||||
return w
|
|
||||||
}
|
|
||||||
return &Replacer{
|
|
||||||
w: w,
|
|
||||||
r: strings.NewReplacer(oldnew...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes p to the base writer. The method scans for any
|
|
||||||
// sensitive data in p and masks before writing.
|
|
||||||
func (r *Replacer) Write(p []byte) (n int, err error) {
|
|
||||||
_, err = r.w.Write([]byte(r.r.Replace(string(p))))
|
|
||||||
return len(p), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the base writer.
|
|
||||||
func (r *Replacer) Close() error {
|
|
||||||
return r.w.Close()
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package replacer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestReplace(t *testing.T) {
|
|
||||||
secrets := []*engine.Secret{
|
|
||||||
{Name: "DOCKER_USERNAME", Data: []byte("octocat"), Mask: false},
|
|
||||||
{Name: "DOCKER_PASSWORD", Data: []byte("correct-horse-batter-staple"), Mask: true},
|
|
||||||
{Name: "DOCKER_EMAIL", Data: []byte(""), Mask: true},
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
w := New(&nopCloser{buf}, secrets)
|
|
||||||
w.Write([]byte("username octocat password correct-horse-batter-staple"))
|
|
||||||
w.Close()
|
|
||||||
|
|
||||||
if got, want := buf.String(), "username octocat password [secret:docker_password]"; got != want {
|
|
||||||
t.Errorf("Want masked string %s, got %s", want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this test verifies that if there are no secrets to scan and
|
|
||||||
// mask, the io.WriteCloser is returned as-is.
|
|
||||||
func TestReplaceNone(t *testing.T) {
|
|
||||||
secrets := []*engine.Secret{
|
|
||||||
{Name: "DOCKER_USERNAME", Data: []byte("octocat"), Mask: false},
|
|
||||||
{Name: "DOCKER_PASSWORD", Data: []byte("correct-horse-batter-staple"), Mask: false},
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
w := &nopCloser{buf}
|
|
||||||
r := New(w, secrets)
|
|
||||||
if w != r {
|
|
||||||
t.Errorf("Expect buffer returned with no replacer")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type nopCloser struct {
|
|
||||||
io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*nopCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Lookup returns the named pipeline from the Manifest.
|
// Lookup returns the named pipeline from the Manifest.
|
||||||
func Lookup(name string, manifest *manifest.Manifest) (*Pipeline, error) {
|
func Lookup(name string, manifest *manifest.Manifest) (manifest.Resource, error) {
|
||||||
for _, resource := range manifest.Resources {
|
for _, resource := range manifest.Resources {
|
||||||
if !isNameMatch(resource.GetName(), name) {
|
if !isNameMatch(resource.GetName(), name) {
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -4,7 +4,13 @@
|
|||||||
|
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/runner-go/environ"
|
||||||
|
"github.com/drone/runner-go/pipeline/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
|
||||||
// Spec provides the pipeline spec. This provides the
|
// Spec provides the pipeline spec. This provides the
|
||||||
// required instructions for reproducible pipeline
|
// required instructions for reproducible pipeline
|
||||||
// execution.
|
// execution.
|
||||||
@@ -44,7 +50,7 @@ type (
|
|||||||
Networks []string `json:"networks,omitempty"`
|
Networks []string `json:"networks,omitempty"`
|
||||||
Privileged bool `json:"privileged,omitempty"`
|
Privileged bool `json:"privileged,omitempty"`
|
||||||
Pull PullPolicy `json:"pull,omitempty"`
|
Pull PullPolicy `json:"pull,omitempty"`
|
||||||
RunPolicy RunPolicy `json:"run_policy,omitempty"`
|
RunPolicy runtime.RunPolicy `json:"run_policy,omitempty"`
|
||||||
Secrets []*Secret `json:"secrets,omitempty"`
|
Secrets []*Secret `json:"secrets,omitempty"`
|
||||||
ShmSize int64 `json:"shm_size,omitempty"`
|
ShmSize int64 `json:"shm_size,omitempty"`
|
||||||
User string `json:"user,omitempty"`
|
User string `json:"user,omitempty"`
|
||||||
@@ -52,14 +58,6 @@ type (
|
|||||||
WorkingDir string `json:"working_dir,omitempty"`
|
WorkingDir string `json:"working_dir,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Platform defines the target platform.
|
|
||||||
Platform struct {
|
|
||||||
OS string `json:"os,omitempty"`
|
|
||||||
Arch string `json:"arch,omitempty"`
|
|
||||||
Variant string `json:"variant,omitempty"`
|
|
||||||
Version string `json:"version,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Secret represents a secret variable.
|
// Secret represents a secret variable.
|
||||||
Secret struct {
|
Secret struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
@@ -68,11 +66,12 @@ type (
|
|||||||
Mask bool `json:"mask,omitempty"`
|
Mask bool `json:"mask,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// State represents the process state.
|
// Platform defines the target platform.
|
||||||
State struct {
|
Platform struct {
|
||||||
ExitCode int // Container exit code
|
OS string `json:"os,omitempty"`
|
||||||
Exited bool // Container exited
|
Arch string `json:"arch,omitempty"`
|
||||||
OOMKilled bool // Container is oom killed
|
Variant string `json:"variant,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volume that can be mounted by containers.
|
// Volume that can be mounted by containers.
|
||||||
@@ -128,3 +127,38 @@ type (
|
|||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// implements the Spec interface
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *Spec) StepLen() int { return len(s.Steps) }
|
||||||
|
func (s *Spec) StepAt(i int) runtime.Step { return s.Steps[i] }
|
||||||
|
|
||||||
|
//
|
||||||
|
// implements the Secret interface
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *Secret) GetName() string { return s.Name }
|
||||||
|
func (s *Secret) GetValue() string { return string(s.Data) }
|
||||||
|
func (s *Secret) IsMasked() bool { return s.Mask }
|
||||||
|
|
||||||
|
//
|
||||||
|
// implements the Step interface
|
||||||
|
//
|
||||||
|
|
||||||
|
func (s *Step) GetName() string { return s.Name }
|
||||||
|
func (s *Step) GetDependencies() []string { return s.DependsOn }
|
||||||
|
func (s *Step) GetEnviron() map[string]string { return s.Envs }
|
||||||
|
func (s *Step) SetEnviron(env map[string]string) { s.Envs = env }
|
||||||
|
func (s *Step) GetErrPolicy() runtime.ErrPolicy { return runtime.ErrFail }
|
||||||
|
func (s *Step) GetRunPolicy() runtime.RunPolicy { return s.RunPolicy }
|
||||||
|
func (s *Step) GetSecretAt(i int) runtime.Secret { return s.Secrets[i] }
|
||||||
|
func (s *Step) GetSecretLen() int { return len(s.Secrets) }
|
||||||
|
func (s *Step) IsDetached() bool { return s.Detach }
|
||||||
|
func (s *Step) Clone() runtime.Step {
|
||||||
|
dst := new(Step)
|
||||||
|
*dst = *s
|
||||||
|
dst.Envs = environ.Combine(s.Envs)
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|||||||
8
go.mod
8
go.mod
@@ -4,19 +4,17 @@ go 1.12
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
docker.io/go-docker v1.0.0
|
docker.io/go-docker v1.0.0
|
||||||
github.com/Microsoft/go-winio v0.4.11 // indirect
|
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf // indirect
|
||||||
github.com/buildkite/yaml v2.1.0+incompatible
|
github.com/buildkite/yaml v2.1.0+incompatible
|
||||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
|
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.7.1+incompatible
|
||||||
github.com/docker/go-connections v0.3.0 // indirect
|
|
||||||
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79
|
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79
|
||||||
|
github.com/drone/drone-runtime v1.1.0
|
||||||
github.com/drone/envsubst v1.0.2
|
github.com/drone/envsubst v1.0.2
|
||||||
github.com/drone/runner-go v1.4.1-0.20191119212738-c0d9268011a7
|
github.com/drone/runner-go v1.4.1-0.20191206210533-80bb9688cb0c
|
||||||
github.com/drone/signal v1.0.0
|
github.com/drone/signal v1.0.0
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 // indirect
|
|
||||||
github.com/golang/mock v1.3.1
|
github.com/golang/mock v1.3.1
|
||||||
github.com/google/go-cmp v0.3.0
|
github.com/google/go-cmp v0.3.0
|
||||||
github.com/hashicorp/go-multierror v1.0.0
|
github.com/hashicorp/go-multierror v1.0.0
|
||||||
@@ -25,8 +23,6 @@ require (
|
|||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.8
|
github.com/mattn/go-isatty v0.0.8
|
||||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4
|
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
|
||||||
github.com/pkg/errors v0.8.1 // indirect
|
github.com/pkg/errors v0.8.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
|
|||||||
42
go.sum
42
go.sum
@@ -21,10 +21,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 h1:74lLNRzvsdIlkTgfDSMuaPjBr4cf6k7pwQQANm/yLKU=
|
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 h1:74lLNRzvsdIlkTgfDSMuaPjBr4cf6k7pwQQANm/yLKU=
|
||||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
|
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
|
||||||
|
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
|
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
|
||||||
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
|
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/drone/drone-go v1.0.5-0.20190504210458-4d6116b897ba h1:GKiT4UPBligLXJAP1zRllHvTUygAAlgS3t9LM9aasp0=
|
github.com/drone/drone-go v1.0.5-0.20190504210458-4d6116b897ba h1:GKiT4UPBligLXJAP1zRllHvTUygAAlgS3t9LM9aasp0=
|
||||||
@@ -32,6 +34,8 @@ github.com/drone/drone-go v1.0.5-0.20190504210458-4d6116b897ba/go.mod h1:GxyeGCl
|
|||||||
github.com/drone/drone-go v1.1.0 h1:2mritc5b7PhQWvILNyzaImZMRWVbMmmZ5Q0UDwwO7SI=
|
github.com/drone/drone-go v1.1.0 h1:2mritc5b7PhQWvILNyzaImZMRWVbMmmZ5Q0UDwwO7SI=
|
||||||
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79 h1:jW+dJ8HrZ1CbazlsYoriOOCQnVJ2NkfNczLHs6UMU6I=
|
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79 h1:jW+dJ8HrZ1CbazlsYoriOOCQnVJ2NkfNczLHs6UMU6I=
|
||||||
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
|
github.com/drone/drone-go v1.1.1-0.20191119212130-1d2e07e87e79/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
|
||||||
|
github.com/drone/drone-runtime v1.1.0 h1:IsKbwiLY6+ViNBzX0F8PERJVZZcEJm9rgxEh3uZP5IE=
|
||||||
|
github.com/drone/drone-runtime v1.1.0/go.mod h1:+osgwGADc/nyl40J0fdsf8Z09bgcBZXvXXnLOY48zYs=
|
||||||
github.com/drone/envsubst v1.0.2 h1:dpYLMAspQHW0a8dZpLRKe9jCNvIGZPhCPrycZzIHdqo=
|
github.com/drone/envsubst v1.0.2 h1:dpYLMAspQHW0a8dZpLRKe9jCNvIGZPhCPrycZzIHdqo=
|
||||||
github.com/drone/envsubst v1.0.2/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0=
|
github.com/drone/envsubst v1.0.2/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0=
|
||||||
github.com/drone/runner-go v1.2.2 h1:fwYgjyJl6KdjQGEUFof9+HLtNpK3iHq7UuR+/aYNyDk=
|
github.com/drone/runner-go v1.2.2 h1:fwYgjyJl6KdjQGEUFof9+HLtNpK3iHq7UuR+/aYNyDk=
|
||||||
@@ -46,23 +50,39 @@ github.com/drone/runner-go v1.3.0/go.mod h1:61VgQWhZbNPXp01lBuR7PAztTMySGLnMzK/4
|
|||||||
github.com/drone/runner-go v1.4.0 h1:zAeYtlKQGvJr2ehfLzQWblzWzvfdkNaapbr6x536fLA=
|
github.com/drone/runner-go v1.4.0 h1:zAeYtlKQGvJr2ehfLzQWblzWzvfdkNaapbr6x536fLA=
|
||||||
github.com/drone/runner-go v1.4.1-0.20191119212738-c0d9268011a7 h1:iNLp8xT0rMcV/tT2J3fCuEbWLqoP7CiL3WR8W3i3HpQ=
|
github.com/drone/runner-go v1.4.1-0.20191119212738-c0d9268011a7 h1:iNLp8xT0rMcV/tT2J3fCuEbWLqoP7CiL3WR8W3i3HpQ=
|
||||||
github.com/drone/runner-go v1.4.1-0.20191119212738-c0d9268011a7/go.mod h1:IqwuMbIoeH45k4NemcNPwymm+l386EeyBC166UElURw=
|
github.com/drone/runner-go v1.4.1-0.20191119212738-c0d9268011a7/go.mod h1:IqwuMbIoeH45k4NemcNPwymm+l386EeyBC166UElURw=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206074106-b546cbadce98 h1:281h7RjcgHLOsqP0abNrS8ESVhtNks2i/WWW0+S0HWw=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206074106-b546cbadce98/go.mod h1:ZIhsNU4EHG7R7J+OXeXuwwAxlxOBYLCc0gCkbbhWb/o=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206204642-f16a481b8b8f h1:TC1w5LWTOEbbatXnx92vRqsEsiIenzwWMmIqEvYqo+U=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206204642-f16a481b8b8f/go.mod h1:ZIhsNU4EHG7R7J+OXeXuwwAxlxOBYLCc0gCkbbhWb/o=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206210533-80bb9688cb0c h1:T3CIdRKiTiaNbInLmtPOoY/9BNUPaL2ipBr2jHzaJsE=
|
||||||
|
github.com/drone/runner-go v1.4.1-0.20191206210533-80bb9688cb0c/go.mod h1:ZIhsNU4EHG7R7J+OXeXuwwAxlxOBYLCc0gCkbbhWb/o=
|
||||||
github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI=
|
github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI=
|
||||||
github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc=
|
github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 h1:zDlw+wgyXdfkRuvFCdEDUiPLmZp2cvf/dWHazY0a5VM=
|
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 h1:zDlw+wgyXdfkRuvFCdEDUiPLmZp2cvf/dWHazY0a5VM=
|
||||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
|
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
|
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
@@ -72,33 +92,47 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 h1:dnMxwus89s86tI8rcGVp2HwZzlz7c5o92VOy7dSckBQ=
|
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 h1:dnMxwus89s86tI8rcGVp2HwZzlz7c5o92VOy7dSckBQ=
|
||||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4/go.mod h1:cojhOHk1gbMeklOyDP2oKKLftefXoJreOQGOrXk+Z38=
|
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4/go.mod h1:cojhOHk1gbMeklOyDP2oKKLftefXoJreOQGOrXk+Z38=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
|
github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4=
|
||||||
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
|
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4 h1:ydJNl0ENAG67pFbB+9tfhiL2pYqLhfoaZFw/cjLhY4A=
|
||||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 h1:uESlIz09WIHT2I+pasSXcpLYqYK8wHcdCetU3VuMBJE=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -106,11 +140,19 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/p
|
|||||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
k8s.io/api v0.0.0-20181130031204-d04500c8c3dd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||||
|
k8s.io/apimachinery v0.0.0-20181201231028-18a5ff3097b4/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
|
||||||
|
k8s.io/client-go v9.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||||
|
k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
|||||||
@@ -1,242 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/replacer"
|
|
||||||
"github.com/drone/drone-go/drone"
|
|
||||||
"github.com/drone/runner-go/environ"
|
|
||||||
"github.com/drone/runner-go/logger"
|
|
||||||
"github.com/drone/runner-go/pipeline"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/natessilva/dag"
|
|
||||||
"golang.org/x/sync/semaphore"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Execer is the execution context for executing the intermediate
|
|
||||||
// representation of a pipeline.
|
|
||||||
type Execer interface {
|
|
||||||
Exec(context.Context, *engine.Spec, *pipeline.State) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type execer struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
engine engine.Engine
|
|
||||||
reporter pipeline.Reporter
|
|
||||||
streamer pipeline.Streamer
|
|
||||||
sem *semaphore.Weighted
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewExecer returns a new execer used
|
|
||||||
func NewExecer(
|
|
||||||
reporter pipeline.Reporter,
|
|
||||||
streamer pipeline.Streamer,
|
|
||||||
engine engine.Engine,
|
|
||||||
procs int64,
|
|
||||||
) Execer {
|
|
||||||
exec := &execer{
|
|
||||||
reporter: reporter,
|
|
||||||
streamer: streamer,
|
|
||||||
engine: engine,
|
|
||||||
}
|
|
||||||
if procs > 0 {
|
|
||||||
// optional semaphor that limits the number of steps
|
|
||||||
// that can execute concurrently.
|
|
||||||
exec.sem = semaphore.NewWeighted(procs)
|
|
||||||
}
|
|
||||||
return exec
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exec executes the intermediate representation of the pipeline
|
|
||||||
// and returns an error if execution fails.
|
|
||||||
func (e *execer) Exec(ctx context.Context, spec *engine.Spec, state *pipeline.State) error {
|
|
||||||
defer e.engine.Destroy(noContext, spec)
|
|
||||||
|
|
||||||
if err := e.engine.Setup(noContext, spec); err != nil {
|
|
||||||
state.FailAll(err)
|
|
||||||
return e.reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a directed graph, where each vertex in the graph
|
|
||||||
// is a pipeline step.
|
|
||||||
var d dag.Runner
|
|
||||||
for _, s := range spec.Steps {
|
|
||||||
step := s
|
|
||||||
d.AddVertex(step.Name, func() error {
|
|
||||||
return e.exec(ctx, state, spec, step)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the vertex edges from the values configured in the
|
|
||||||
// depends_on attribute.
|
|
||||||
for _, s := range spec.Steps {
|
|
||||||
for _, dep := range s.DependsOn {
|
|
||||||
d.AddEdge(dep, s.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var result error
|
|
||||||
if err := d.Run(); err != nil {
|
|
||||||
multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// once pipeline execution completes, notify the state
|
|
||||||
// manageer that all steps are finished.
|
|
||||||
state.FinishAll()
|
|
||||||
if err := e.reporter.ReportStage(noContext, state); err != nil {
|
|
||||||
multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *execer) exec(ctx context.Context, state *pipeline.State, spec *engine.Spec, step *engine.Step) error {
|
|
||||||
var result error
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
state.Cancel()
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
log := logger.FromContext(ctx)
|
|
||||||
log = log.WithField("step.name", step.Name)
|
|
||||||
ctx = logger.WithContext(ctx, log)
|
|
||||||
|
|
||||||
if e.sem != nil {
|
|
||||||
// the semaphore limits the number of steps that can run
|
|
||||||
// concurrently. acquire the semaphore and release when
|
|
||||||
// the pipeline completes.
|
|
||||||
if err := e.sem.Acquire(ctx, 1); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
// recover from a panic to ensure the semaphore is
|
|
||||||
// released to prevent deadlock. we do not expect a
|
|
||||||
// panic, however, we are being overly cautious.
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
// TODO(bradrydzewsi) log the panic.
|
|
||||||
}
|
|
||||||
// release the semaphore
|
|
||||||
e.sem.Release(1)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case state.Skipped():
|
|
||||||
return nil
|
|
||||||
case state.Cancelled():
|
|
||||||
return nil
|
|
||||||
case step.RunPolicy == engine.RunNever:
|
|
||||||
return nil
|
|
||||||
case step.RunPolicy == engine.RunAlways:
|
|
||||||
break
|
|
||||||
case step.RunPolicy == engine.RunOnFailure && state.Failed() == false:
|
|
||||||
state.Skip(step.Name)
|
|
||||||
return e.reporter.ReportStep(noContext, state, step.Name)
|
|
||||||
case step.RunPolicy == engine.RunOnSuccess && state.Failed():
|
|
||||||
state.Skip(step.Name)
|
|
||||||
return e.reporter.ReportStep(noContext, state, step.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Start(step.Name)
|
|
||||||
err := e.reporter.ReportStep(noContext, state, step.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
copy := cloneStep(step)
|
|
||||||
|
|
||||||
// the pipeline environment variables need to be updated to
|
|
||||||
// reflect the current state of the build and stage.
|
|
||||||
state.Lock()
|
|
||||||
copy.Envs = environ.Combine(
|
|
||||||
copy.Envs,
|
|
||||||
environ.Build(state.Build),
|
|
||||||
environ.Stage(state.Stage),
|
|
||||||
environ.Step(findStep(state, step.Name)),
|
|
||||||
)
|
|
||||||
state.Unlock()
|
|
||||||
|
|
||||||
// writer used to stream build logs.
|
|
||||||
wc := e.streamer.Stream(noContext, state, step.Name)
|
|
||||||
wc = replacer.New(wc, step.Secrets)
|
|
||||||
|
|
||||||
// if the step is configured as a daemon, it is detached
|
|
||||||
// from the main process and executed separately.
|
|
||||||
// todo(bradrydzewski) this code is still experimental.
|
|
||||||
if step.Detach {
|
|
||||||
go func() {
|
|
||||||
e.engine.Run(ctx, spec, copy, wc)
|
|
||||||
wc.Close()
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
exited, err := e.engine.Run(ctx, spec, copy, wc)
|
|
||||||
|
|
||||||
// close the stream. If the session is a remote session, the
|
|
||||||
// full log buffer is uploaded to the remote server.
|
|
||||||
if err := wc.Close(); err != nil {
|
|
||||||
multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if exited != nil {
|
|
||||||
state.Finish(step.Name, exited.ExitCode)
|
|
||||||
err := e.reporter.ReportStep(noContext, state, step.Name)
|
|
||||||
if err != nil {
|
|
||||||
multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
// if the exit code is 78 the system will skip all
|
|
||||||
// subsequent pending steps in the pipeline.
|
|
||||||
if exited.ExitCode == 78 {
|
|
||||||
state.SkipAll()
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
switch err {
|
|
||||||
case context.Canceled, context.DeadlineExceeded:
|
|
||||||
state.Cancel()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the step failed with an internal error (as oppsed to a
|
|
||||||
// runtime error) the step is failed.
|
|
||||||
state.Fail(step.Name, err)
|
|
||||||
err = e.reporter.ReportStep(noContext, state, step.Name)
|
|
||||||
if err != nil {
|
|
||||||
multierror.Append(result, err)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function to clone a step. The runner mutates a step to
|
|
||||||
// update the environment variables to reflect the current
|
|
||||||
// pipeline state.
|
|
||||||
func cloneStep(src *engine.Step) *engine.Step {
|
|
||||||
dst := new(engine.Step)
|
|
||||||
*dst = *src
|
|
||||||
dst.Envs = environ.Combine(src.Envs)
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper function returns the named step from the state.
|
|
||||||
func findStep(state *pipeline.State, name string) *drone.Step {
|
|
||||||
for _, step := range state.Stage.Steps {
|
|
||||||
if step.Name == name {
|
|
||||||
return step
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("step not found: " + name)
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExec(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_NonZeroExit(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_Exit78(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_Error(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_CtxError(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_ReportError(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExec_SkipCtxDone(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/drone/runner-go/client"
|
|
||||||
"github.com/drone/runner-go/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
var noContext = context.Background()
|
|
||||||
|
|
||||||
// Poller polls the server for pending stages and dispatches
|
|
||||||
// for execution by the Runner.
|
|
||||||
type Poller struct {
|
|
||||||
Client client.Client
|
|
||||||
Filter *client.Filter
|
|
||||||
Runner *Runner
|
|
||||||
}
|
|
||||||
|
|
||||||
// Poll opens N connections to the server to poll for pending
|
|
||||||
// stages for execution. Pending stages are dispatched to a
|
|
||||||
// Runner for execution.
|
|
||||||
func (p *Poller) Poll(ctx context.Context, n int) {
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
wg.Add(1)
|
|
||||||
go func(i int) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
wg.Done()
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
p.poll(ctx, i+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
// poll requests a stage for execution from the server, and then
|
|
||||||
// dispatches for execution.
|
|
||||||
func (p *Poller) poll(ctx context.Context, thread int) error {
|
|
||||||
log := logger.FromContext(ctx).WithField("thread", thread)
|
|
||||||
log.WithField("thread", thread).Debug("request stage from remote server")
|
|
||||||
|
|
||||||
// request a new build stage for execution from the central
|
|
||||||
// build server.
|
|
||||||
stage, err := p.Client.Request(ctx, p.Filter)
|
|
||||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
|
||||||
log.WithError(err).Trace("no stage returned")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot request stage")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// exit if a nil or empty stage is returned from the system
|
|
||||||
// and allow the runner to retry.
|
|
||||||
if stage == nil || stage.ID == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.Runner.Run(
|
|
||||||
logger.WithContext(noContext, log), stage)
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPoll(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPoll_NilStage(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPoll_EmptyStage(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPoll_RequestError(t *testing.T) {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/compiler"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/linter"
|
|
||||||
"github.com/drone-runners/drone-runner-docker/engine/resource"
|
|
||||||
|
|
||||||
"github.com/drone/drone-go/drone"
|
|
||||||
"github.com/drone/envsubst"
|
|
||||||
"github.com/drone/runner-go/client"
|
|
||||||
"github.com/drone/runner-go/environ"
|
|
||||||
"github.com/drone/runner-go/logger"
|
|
||||||
"github.com/drone/runner-go/manifest"
|
|
||||||
"github.com/drone/runner-go/pipeline"
|
|
||||||
"github.com/drone/runner-go/secret"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Runner runs the pipeline.
|
|
||||||
type Runner struct {
|
|
||||||
// Client is the remote client responsible for interacting
|
|
||||||
// with the central server.
|
|
||||||
Client client.Client
|
|
||||||
|
|
||||||
// Compiler is responsible for compiling the pipeline
|
|
||||||
// configuration to the intermediate representation.
|
|
||||||
Compiler *compiler.Compiler
|
|
||||||
|
|
||||||
// Execer is responsible for executing intermediate
|
|
||||||
// representation of the pipeline and returns its results.
|
|
||||||
Execer Execer
|
|
||||||
|
|
||||||
// Linter is responsible for linting the pipeline
|
|
||||||
// and failing if any rules are broken.
|
|
||||||
Linter *linter.Linter
|
|
||||||
|
|
||||||
// Machine provides the runner with the name of the host
|
|
||||||
// machine executing the pipeline.
|
|
||||||
Machine string
|
|
||||||
|
|
||||||
// Match is an optional function that returns true if the
|
|
||||||
// repository or build match user-defined criteria. This is
|
|
||||||
// intended as a security measure to prevent a runner from
|
|
||||||
// processing an unwanted pipeline.
|
|
||||||
Match func(*drone.Repo, *drone.Build) bool
|
|
||||||
|
|
||||||
// Reporter reports pipeline status and logs back to the
|
|
||||||
// remote server.
|
|
||||||
Reporter pipeline.Reporter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run runs the pipeline stage.
|
|
||||||
func (s *Runner) Run(ctx context.Context, stage *drone.Stage) error {
|
|
||||||
log := logger.FromContext(ctx).
|
|
||||||
WithField("stage.id", stage.ID).
|
|
||||||
WithField("stage.name", stage.Name).
|
|
||||||
WithField("stage.number", stage.Number)
|
|
||||||
|
|
||||||
log.Debug("stage received")
|
|
||||||
|
|
||||||
// delivery to a single agent is not guaranteed, which means
|
|
||||||
// we need confirm receipt. The first agent that confirms
|
|
||||||
// receipt of the stage can assume ownership.
|
|
||||||
|
|
||||||
stage.Machine = s.Machine
|
|
||||||
err := s.Client.Accept(ctx, stage)
|
|
||||||
if err != nil && err == client.ErrOptimisticLock {
|
|
||||||
log.Debug("stage accepted by another runner")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot accept stage")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("stage accepted")
|
|
||||||
|
|
||||||
data, err := s.Client.Detail(ctx, stage)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot get stage details")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log = log.WithField("repo.id", data.Repo.ID).
|
|
||||||
WithField("repo.namespace", data.Repo.Namespace).
|
|
||||||
WithField("repo.name", data.Repo.Name).
|
|
||||||
WithField("build.id", data.Build.ID).
|
|
||||||
WithField("build.number", data.Build.Number)
|
|
||||||
|
|
||||||
log.Debug("stage details fetched")
|
|
||||||
|
|
||||||
ctxdone, cancel := context.WithCancel(ctx)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
timeout := time.Duration(data.Repo.Timeout) * time.Minute
|
|
||||||
ctxtimeout, cancel := context.WithTimeout(ctxdone, timeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ctxcancel, cancel := context.WithCancel(ctxtimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
// next we opens a connection to the server to watch for
|
|
||||||
// cancellation requests. If a build is cancelled the running
|
|
||||||
// stage should also be cancelled.
|
|
||||||
go func() {
|
|
||||||
done, _ := s.Client.Watch(ctxdone, data.Build.ID)
|
|
||||||
if done {
|
|
||||||
cancel()
|
|
||||||
log.Debugln("received cancellation")
|
|
||||||
} else {
|
|
||||||
log.Debugln("done listening for cancellations")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
envs := environ.Combine(
|
|
||||||
environ.System(data.System),
|
|
||||||
environ.Repo(data.Repo),
|
|
||||||
environ.Build(data.Build),
|
|
||||||
environ.Stage(stage),
|
|
||||||
environ.Link(data.Repo, data.Build, data.System),
|
|
||||||
data.Build.Params,
|
|
||||||
)
|
|
||||||
|
|
||||||
// string substitution function ensures that string
|
|
||||||
// replacement variables are escaped and quoted if they
|
|
||||||
// contain a newline character.
|
|
||||||
subf := func(k string) string {
|
|
||||||
v := envs[k]
|
|
||||||
if strings.Contains(v, "\n") {
|
|
||||||
v = fmt.Sprintf("%q", v)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
state := &pipeline.State{
|
|
||||||
Build: data.Build,
|
|
||||||
Stage: stage,
|
|
||||||
Repo: data.Repo,
|
|
||||||
System: data.System,
|
|
||||||
}
|
|
||||||
|
|
||||||
// evaluates whether or not the agent can process the
|
|
||||||
// pipeline. An agent may choose to reject a repository
|
|
||||||
// or build for security reasons.
|
|
||||||
if s.Match != nil && s.Match(data.Repo, data.Build) == false {
|
|
||||||
log.Error("cannot process stage, access denied")
|
|
||||||
state.FailAll(errors.New("insufficient permission to run the pipeline"))
|
|
||||||
return s.Reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// evaluates string replacement expressions and returns an
|
|
||||||
// update configuration file string.
|
|
||||||
config, err := envsubst.Eval(string(data.Config.Data), subf)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot emulate bash substitution")
|
|
||||||
state.FailAll(err)
|
|
||||||
return s.Reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the yaml configuration file.
|
|
||||||
manifest, err := manifest.ParseString(config)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot parse configuration file")
|
|
||||||
state.FailAll(err)
|
|
||||||
return s.Reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the named stage in the yaml configuration file.
|
|
||||||
resource, err := resource.Lookup(stage.Name, manifest)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot find pipeline resource")
|
|
||||||
state.FailAll(err)
|
|
||||||
return s.Reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
// lint the pipeline configuration and fail the build
|
|
||||||
// if any linting rules are broken.
|
|
||||||
err = s.Linter.Lint(resource, linter.Opts{Trusted: data.Repo.Trusted})
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("cannot accept configuration")
|
|
||||||
state.FailAll(err)
|
|
||||||
return s.Reporter.ReportStage(noContext, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
secrets := secret.Combine(
|
|
||||||
secret.Static(data.Secrets),
|
|
||||||
secret.Encrypted(),
|
|
||||||
// s.Secret,
|
|
||||||
)
|
|
||||||
|
|
||||||
// compile the yaml configuration file to an intermediate
|
|
||||||
// representation, and then
|
|
||||||
args := compiler.Args{
|
|
||||||
Pipeline: resource,
|
|
||||||
Manifest: manifest,
|
|
||||||
Build: data.Build,
|
|
||||||
Stage: stage,
|
|
||||||
Repo: data.Repo,
|
|
||||||
System: data.System,
|
|
||||||
Netrc: data.Netrc,
|
|
||||||
Secret: secrets,
|
|
||||||
}
|
|
||||||
|
|
||||||
spec := s.Compiler.Compile(ctx, args)
|
|
||||||
for _, src := range spec.Steps {
|
|
||||||
// steps that are skipped are ignored and are not stored
|
|
||||||
// in the drone database, nor displayed in the UI.
|
|
||||||
if src.RunPolicy == engine.RunNever {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
stage.Steps = append(stage.Steps, &drone.Step{
|
|
||||||
Name: src.Name,
|
|
||||||
Number: len(stage.Steps) + 1,
|
|
||||||
StageID: stage.ID,
|
|
||||||
Status: drone.StatusPending,
|
|
||||||
ErrIgnore: src.IgnoreErr,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
stage.Started = time.Now().Unix()
|
|
||||||
stage.Status = drone.StatusRunning
|
|
||||||
if err := s.Client.Update(ctx, stage); err != nil {
|
|
||||||
log.WithError(err).Error("cannot update stage")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("updated stage to running")
|
|
||||||
|
|
||||||
ctxcancel = logger.WithContext(ctxcancel, log)
|
|
||||||
err = s.Execer.Exec(ctxcancel, spec, state)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Debug("stage failed")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Debug("updated stage to complete")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
// Code generated automatically. DO NOT EDIT.
|
|
||||||
|
|
||||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
|
||||||
// Use of this source code is governed by the Polyform License
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package runtime
|
|
||||||
Reference in New Issue
Block a user