diff --git a/command/compile.go b/command/compile.go index 7ec6d31..32cf377 100644 --- a/command/compile.go +++ b/command/compile.go @@ -33,6 +33,7 @@ type compileCommand struct { Environ map[string]string Labels map[string]string Secrets map[string]string + Resources compiler.Resources } func (c *compileCommand) run(*kingpin.ParseContext) error { @@ -102,6 +103,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error { System: c.System, Environ: c.Environ, Labels: c.Labels, + Resources: c.Resources, Privileged: append(c.Privileged, compiler.Privileged...), Networks: c.Networks, Volumes: c.Volumes, @@ -149,6 +151,27 @@ func registerCompile(app *kingpin.Application) { cmd.Flag("privileged", "privileged docker images"). StringsVar(&c.Privileged) + cmd.Flag("cpu-period", "container cpu period"). + Int64Var(&c.Resources.CPUPeriod) + + cmd.Flag("cpu-quota", "container cpu quota"). + Int64Var(&c.Resources.CPUQuota) + + cmd.Flag("cpu-set", "container cpu set"). + StringsVar(&c.Resources.CPUSet) + + cmd.Flag("cpu-shares", "container cpu shares"). + Int64Var(&c.Resources.CPUShares) + + cmd.Flag("memory", "container memory limit"). + Int64Var(&c.Resources.MemLimit) + + cmd.Flag("memory-swap", "container memory swap limit"). + Int64Var(&c.Resources.MemSwapLimit) + + cmd.Flag("shmsize", "container shm size"). + Int64Var(&c.Resources.ShmSize) + // shared pipeline flags c.Flags = internal.ParseFlags(cmd) } diff --git a/command/exec.go b/command/exec.go index d6ff8a1..b9766fd 100644 --- a/command/exec.go +++ b/command/exec.go @@ -46,6 +46,7 @@ type execCommand struct { Environ map[string]string Labels map[string]string Secrets map[string]string + Resources compiler.Resources Pretty bool Procs int64 Debug bool @@ -122,6 +123,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error { System: c.System, Environ: c.Environ, Labels: c.Labels, + Resources: c.Resources, Privileged: append(c.Privileged, compiler.Privileged...), Networks: c.Networks, Volumes: c.Volumes, @@ -279,6 +281,27 @@ func registerExec(app *kingpin.Application) { cmd.Flag("privileged", "privileged docker images"). StringsVar(&c.Privileged) + cmd.Flag("cpu-period", "container cpu period"). + Int64Var(&c.Resources.CPUPeriod) + + cmd.Flag("cpu-quota", "container cpu quota"). + Int64Var(&c.Resources.CPUQuota) + + cmd.Flag("cpu-set", "container cpu set"). + StringsVar(&c.Resources.CPUSet) + + cmd.Flag("cpu-shares", "container cpu shares"). + Int64Var(&c.Resources.CPUShares) + + cmd.Flag("memory", "container memory limit"). + Int64Var(&c.Resources.MemLimit) + + cmd.Flag("memory-swap", "container memory swap limit"). + Int64Var(&c.Resources.MemSwapLimit) + + cmd.Flag("shmsize", "container shm size"). + Int64Var(&c.Resources.ShmSize) + cmd.Flag("public-key", "public key file path"). ExistingFileVar(&c.PublicKey) diff --git a/engine/compiler/compiler.go b/engine/compiler/compiler.go index 97478eb..68bf440 100644 --- a/engine/compiler/compiler.go +++ b/engine/compiler/compiler.go @@ -16,6 +16,7 @@ import ( "github.com/drone/drone-go/drone" "github.com/drone/runner-go/clone" "github.com/drone/runner-go/environ" + "github.com/drone/runner-go/labels" "github.com/drone/runner-go/manifest" "github.com/drone/runner-go/secret" @@ -36,6 +37,18 @@ var Privileged = []string{ "plugins/heroku", } +// Resources defines container resource constraints. These +// constraints are per-container, not per-pipeline. +type Resources struct { + MemLimit int64 + MemSwapLimit int64 + ShmSize int64 + CPUQuota int64 + CPUPeriod int64 + CPUShares int64 + CPUSet []string +} + // Compiler compiles the Yaml configuration file to an // intermediate representation optimized for simple execution. type Compiler struct { @@ -88,6 +101,10 @@ type Compiler struct { // mounted to each pipeline container. Volumes map[string]string + // Resources provides global resource constraints + // applies to pipeline containers. + Resources Resources + // Netrc provides netrc parameters that can be used by the // default clone step to authenticate to the remote // repository. @@ -111,23 +128,27 @@ func (c *Compiler) Compile(ctx context.Context) *engine.Spec { Path: base, } + // create system labels + labels := labels.Combine( + c.Labels, + labels.FromRepo(c.Repo), + labels.FromBuild(c.Build), + labels.FromStage(c.Stage), + labels.FromSystem(c.System), + labels.WithTimeout(c.Repo), + ) + // create the workspace volume volume := &engine.VolumeEmptyDir{ - ID: random(), - Name: mount.Name, - Labels: environ.Combine( - c.Labels, - createLabels(c.Repo, c.Build, c.Stage), - ), + ID: random(), + Name: mount.Name, + Labels: labels, } spec := &engine.Spec{ Network: engine.Network{ - ID: random(), - Labels: environ.Combine( - c.Labels, - createLabels(c.Repo, c.Build, c.Stage), - ), + ID: random(), + Labels: labels, }, Platform: engine.Platform{ OS: c.Pipeline.Platform.OS, @@ -200,10 +221,7 @@ func (c *Compiler) Compile(ctx context.Context) *engine.Spec { step.ID = random() step.Envs = environ.Combine(envs, step.Envs) step.WorkingDir = full - step.Labels = environ.Combine( - c.Labels, - createLabels(c.Repo, c.Build, c.Stage), - ) + step.Labels = labels step.Volumes = append(step.Volumes, mount) spec.Steps = append(spec.Steps, step) } @@ -214,10 +232,7 @@ func (c *Compiler) Compile(ctx context.Context) *engine.Spec { dst.Detach = true dst.Envs = environ.Combine(envs, dst.Envs) dst.Volumes = append(dst.Volumes, mount) - dst.Labels = environ.Combine( - c.Labels, - createLabels(c.Repo, c.Build, c.Stage), - ) + dst.Labels = labels setupScript(src, dst, os) setupWorkdir(src, dst, full) spec.Steps = append(spec.Steps, dst) @@ -234,10 +249,7 @@ func (c *Compiler) Compile(ctx context.Context) *engine.Spec { dst := createStep(c.Pipeline, src) dst.Envs = environ.Combine(envs, dst.Envs) dst.Volumes = append(dst.Volumes, mount) - dst.Labels = environ.Combine( - c.Labels, - createLabels(c.Repo, c.Build, c.Stage), - ) + dst.Labels = labels setupScript(src, dst, full) setupWorkdir(src, dst, full) spec.Steps = append(spec.Steps, dst) @@ -294,6 +306,17 @@ func (c *Compiler) Compile(ctx context.Context) *engine.Spec { } } + // append global resource limits to steps + for _, step := range spec.Steps { + step.MemSwapLimit = c.Resources.MemSwapLimit + step.MemLimit = c.Resources.MemLimit + step.ShmSize = c.Resources.ShmSize + step.CPUPeriod = c.Resources.CPUPeriod + step.CPUQuota = c.Resources.CPUQuota + step.CPUShares = c.Resources.CPUShares + step.CPUSet = c.Resources.CPUSet + } + // append global networks to the steps. for _, step := range spec.Steps { step.Networks = append(step.Networks, c.Networks...) diff --git a/engine/compiler/label.go b/engine/compiler/label.go deleted file mode 100644 index 53c5cbe..0000000 --- a/engine/compiler/label.go +++ /dev/null @@ -1,33 +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 compiler - -import ( - "fmt" - "time" - - "github.com/drone/drone-go/drone" -) - -func createLabels( - repo *drone.Repo, - build *drone.Build, - stage *drone.Stage, -) map[string]string { - return map[string]string{ - "io.drone": "true", - "io.drone.build.number": fmt.Sprint(build.Number), - "io.drone.repo.namespace": repo.Namespace, - "io.drone.repo.name": repo.Name, - "io.drone.stage.name": stage.Name, - "io.drone.stage.number": fmt.Sprint(stage.Number), - "io.drone.ttl": fmt.Sprint(time.Duration(repo.Timeout) * time.Minute), - "io.drone.expires": fmt.Sprint(time.Now().Add(time.Duration(repo.Timeout)*time.Minute + time.Hour).Unix()), - "io.drone.created": fmt.Sprint(time.Now().Unix()), - "io.drone.protected": "false", - } - // labels["io.drone.step.name"] = step.Name - // labels["io.drone.step.number"] = fmt.Sprint(step.Number) -} diff --git a/engine/spec.go b/engine/spec.go index d80a33b..6f75b57 100644 --- a/engine/spec.go +++ b/engine/spec.go @@ -21,6 +21,10 @@ type ( ID string `json:"id,omitempty"` Auth *Auth `json:"auth,omitempty"` Command []string `json:"args,omitempty"` + CPUPeriod int64 `json:"cpu_period,omitempty"` + CPUQuota int64 `json:"cpu_quota,omitempty"` + CPUShares int64 `json:"cpu_shares,omitempty"` + CPUSet []string `json:"cpu_set,omitempty"` Detach bool `json:"detach,omitempty"` DependsOn []string `json:"depends_on,omitempty"` DNS []string `json:"dns,omitempty"` @@ -34,6 +38,8 @@ type ( IgnoreStderr bool `json:"ignore_stdout,omitempty"` Image string `json:"image,omitempty"` Labels map[string]string `json:"labels,omitempty"` + MemSwapLimit int64 `json:"memswap_limit,omitempty"` + MemLimit int64 `json:"mem_limit,omitempty"` Name string `json:"name,omitempty"` Network string `json:"network,omitempty"` Networks []string `json:"networks,omitempty"` @@ -41,6 +47,7 @@ type ( Pull PullPolicy `json:"pull,omitempty"` RunPolicy RunPolicy `json:"run_policy,omitempty"` Secrets []*Secret `json:"secrets,omitempty"` + ShmSize int64 `json:"shm_size,omitempty"` User string `json:"user,omitempty"` Volumes []*VolumeMount `json:"volumes,omitempty"` WorkingDir string `json:"working_dir,omitempty"` diff --git a/go.mod b/go.mod index 7ee7e24..f5d9791 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/drone/drone-runtime v1.0.7-0.20190729202838-87c84080f4a1 github.com/drone/drone-yaml v1.2.2 github.com/drone/envsubst v1.0.2 - github.com/drone/runner-go v1.2.3-0.20191008184914-35b0486b7f23 + github.com/drone/runner-go v1.2.3-0.20191017212814-48a0db6f4ed7 github.com/drone/signal v1.0.0 github.com/ghodss/yaml v1.0.0 github.com/google/go-cmp v0.3.0 diff --git a/go.sum b/go.sum index 8d778be..d31fc8c 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/drone/runner-go v1.1.1-0.20190716194717-969b4e42cd4b/go.mod h1:GvB5hX github.com/drone/runner-go v1.2.2 h1:fwYgjyJl6KdjQGEUFof9+HLtNpK3iHq7UuR+/aYNyDk= github.com/drone/runner-go v1.2.3-0.20191008184914-35b0486b7f23 h1:sj9myNBjsR7C6HFdR0Lp79KtZw5MHf97FfRIsmoA1Ys= github.com/drone/runner-go v1.2.3-0.20191008184914-35b0486b7f23/go.mod h1:GvB5hX023g0n5UZUjMBmudk6givdDDuLcls7Nolm5v8= +github.com/drone/runner-go v1.2.3-0.20191017212814-48a0db6f4ed7 h1:qGsY45PRwKdbaKZqa2jswjS5nbLEp1sDXFbVaIcbi4I= +github.com/drone/runner-go v1.2.3-0.20191017212814-48a0db6f4ed7/go.mod h1:GvB5hX023g0n5UZUjMBmudk6givdDDuLcls7Nolm5v8= 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/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=