remove deprecated schedulers
This commit is contained in:
parent
2255d63532
commit
1fa3daca29
19 changed files with 32 additions and 1581 deletions
|
@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
### Breaking
|
||||
- removed deprecated kubernetes integration in favor of official kubernetes runner.
|
||||
- removed deprecated nomad integration in favor of official nomad runner.
|
||||
|
||||
## [1.10.1]
|
||||
### Added
|
||||
- support for repository-level concurrency limits.
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
||||
// IMPORTANT please do not add new configuration parameters unless it has
|
||||
// been discussed on the mailing list. We are attempting to reduce the
|
||||
// number of configuration parameters, and may reject pull requests that
|
||||
// introduce new parameters. (mailing list https://discourse.drone.io)
|
||||
|
||||
// default runner hostname.
|
||||
var hostname string
|
||||
|
||||
func init() {
|
||||
hostname, _ = os.Hostname()
|
||||
if hostname == "" {
|
||||
hostname = "localhost"
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// Config provides the system configuration.
|
||||
Config struct {
|
||||
Docker Docker
|
||||
Logging Logging
|
||||
Registries Registries
|
||||
Runner Runner
|
||||
RPC RPC
|
||||
Server Server
|
||||
Secrets Secrets
|
||||
}
|
||||
|
||||
// Docker provides docker configuration
|
||||
Docker struct {
|
||||
Config string `envconfig:"DRONE_DOCKER_CONFIG"`
|
||||
}
|
||||
|
||||
// Logging provides the logging configuration.
|
||||
Logging struct {
|
||||
Debug bool `envconfig:"DRONE_LOGS_DEBUG"`
|
||||
Trace bool `envconfig:"DRONE_LOGS_TRACE"`
|
||||
Color bool `envconfig:"DRONE_LOGS_COLOR"`
|
||||
Pretty bool `envconfig:"DRONE_LOGS_PRETTY"`
|
||||
Text bool `envconfig:"DRONE_LOGS_TEXT"`
|
||||
}
|
||||
|
||||
// Registries provides the registry configuration.
|
||||
Registries struct {
|
||||
Endpoint string `envconfig:"DRONE_REGISTRY_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_REGISTRY_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_REGISTRY_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Secrets provides the secret configuration.
|
||||
Secrets struct {
|
||||
Endpoint string `envconfig:"DRONE_SECRET_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_SECRET_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_SECRET_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// RPC provides the rpc configuration.
|
||||
RPC struct {
|
||||
Server string `envconfig:"DRONE_RPC_SERVER"`
|
||||
Secret string `envconfig:"DRONE_RPC_SECRET"`
|
||||
Debug bool `envconfig:"DRONE_RPC_DEBUG"`
|
||||
Host string `envconfig:"DRONE_RPC_HOST"`
|
||||
Proto string `envconfig:"DRONE_RPC_PROTO"`
|
||||
// Hosts map[string]string `envconfig:"DRONE_RPC_EXTRA_HOSTS"`
|
||||
}
|
||||
|
||||
// Runner provides the runner configuration.
|
||||
Runner struct {
|
||||
Platform string `envconfig:"DRONE_RUNNER_PLATFORM" default:"linux/amd64"`
|
||||
OS string `envconfig:"DRONE_RUNNER_OS"`
|
||||
Arch string `envconfig:"DRONE_RUNNER_ARCH"`
|
||||
Kernel string `envconfig:"DRONE_RUNNER_KERNEL"`
|
||||
Variant string `envconfig:"DRONE_RUNNER_VARIANT"`
|
||||
Machine string `envconfig:"DRONE_RUNNER_NAME"`
|
||||
Capacity int `envconfig:"DRONE_RUNNER_CAPACITY" default:"2"`
|
||||
Labels map[string]string `envconfig:"DRONE_RUNNER_LABELS"`
|
||||
Volumes []string `envconfig:"DRONE_RUNNER_VOLUMES"`
|
||||
Networks []string `envconfig:"DRONE_RUNNER_NETWORKS"`
|
||||
Devices []string `envconfig:"DRONE_RUNNER_DEVICES"`
|
||||
Privileged []string `envconfig:"DRONE_RUNNER_PRIVILEGED_IMAGES"`
|
||||
Environ map[string]string `envconfig:"DRONE_RUNNER_ENVIRON"`
|
||||
Limits struct {
|
||||
MemSwapLimit Bytes `envconfig:"DRONE_LIMIT_MEM_SWAP"`
|
||||
MemLimit Bytes `envconfig:"DRONE_LIMIT_MEM"`
|
||||
ShmSize Bytes `envconfig:"DRONE_LIMIT_SHM_SIZE"`
|
||||
CPUQuota int64 `envconfig:"DRONE_LIMIT_CPU_QUOTA"`
|
||||
CPUShares int64 `envconfig:"DRONE_LIMIT_CPU_SHARES"`
|
||||
CPUSet string `envconfig:"DRONE_LIMIT_CPU_SET"`
|
||||
}
|
||||
}
|
||||
|
||||
// Server provides the server configuration.
|
||||
Server struct {
|
||||
Addr string `envconfig:"-"`
|
||||
Host string `envconfig:"DRONE_SERVER_HOST" default:"localhost:8080"`
|
||||
Proto string `envconfig:"DRONE_SERVER_PROTO" default:"http"`
|
||||
}
|
||||
)
|
||||
|
||||
// Environ returns the settings from the environment.
|
||||
func Environ() (Config, error) {
|
||||
cfg := Config{}
|
||||
err := envconfig.Process("", &cfg)
|
||||
defaultRunner(&cfg)
|
||||
defaultCallback(&cfg)
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func defaultRunner(c *Config) {
|
||||
if c.Runner.Machine == "" {
|
||||
c.Runner.Machine = hostname
|
||||
}
|
||||
parts := strings.Split(c.Runner.Platform, "/")
|
||||
if len(parts) == 2 && c.Runner.OS == "" {
|
||||
c.Runner.OS = parts[0]
|
||||
}
|
||||
if len(parts) == 2 && c.Runner.Arch == "" {
|
||||
c.Runner.Arch = parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
func defaultCallback(c *Config) {
|
||||
// this is legacy, remove in a future release
|
||||
if c.RPC.Server != "" {
|
||||
uri, err := url.Parse(c.RPC.Server)
|
||||
if err == nil {
|
||||
c.RPC.Host = uri.Host
|
||||
c.RPC.Proto = uri.Scheme
|
||||
}
|
||||
}
|
||||
if c.RPC.Host == "" {
|
||||
c.RPC.Host = c.Server.Host
|
||||
}
|
||||
if c.RPC.Proto == "" {
|
||||
c.RPC.Proto = c.Server.Proto
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes stores number bytes (e.g. megabytes)
|
||||
type Bytes int64
|
||||
|
||||
// Decode implements a decoder that parses a string representation
|
||||
// of bytes into the number of bytes it represents.
|
||||
func (b *Bytes) Decode(value string) error {
|
||||
v, err := humanize.ParseBytes(value)
|
||||
*b = Bytes(v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value of the Byte.
|
||||
func (b *Bytes) Int64() int64 {
|
||||
return int64(*b)
|
||||
}
|
||||
|
||||
// String returns the string value of the Byte.
|
||||
func (b *Bytes) String() string {
|
||||
return fmt.Sprint(*b)
|
||||
}
|
||||
|
||||
// UserCreate stores account information used to bootstrap
|
||||
// the admin user account when the system initializes.
|
||||
type UserCreate struct {
|
||||
Username string
|
||||
Machine bool
|
||||
Admin bool
|
||||
Token string
|
||||
}
|
||||
|
||||
// Decode implements a decoder that extracts user information
|
||||
// from the environment variable string.
|
||||
func (u *UserCreate) Decode(value string) error {
|
||||
for _, param := range strings.Split(value, ",") {
|
||||
parts := strings.Split(param, ":")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := parts[0]
|
||||
val := parts[1]
|
||||
switch key {
|
||||
case "username":
|
||||
u.Username = val
|
||||
case "token":
|
||||
u.Token = val
|
||||
case "machine":
|
||||
u.Machine = val == "true"
|
||||
case "admin":
|
||||
u.Admin = val == "true"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone-runtime/engine/docker"
|
||||
"github.com/drone/drone/cmd/drone-agent/config"
|
||||
"github.com/drone/drone/operator/manager/rpc"
|
||||
"github.com/drone/drone/operator/runner"
|
||||
"github.com/drone/drone/plugin/registry"
|
||||
"github.com/drone/drone/plugin/secret"
|
||||
"github.com/drone/signal"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var envfile string
|
||||
flag.StringVar(&envfile, "env-file", ".env", "Read in a file of environment variables")
|
||||
flag.Parse()
|
||||
|
||||
godotenv.Load(envfile)
|
||||
config, err := config.Environ()
|
||||
if err != nil {
|
||||
logger := logrus.WithError(err)
|
||||
logger.Fatalln("invalid configuration")
|
||||
}
|
||||
|
||||
initLogging(config)
|
||||
ctx := signal.WithContext(
|
||||
context.Background(),
|
||||
)
|
||||
|
||||
secrets := secret.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
)
|
||||
|
||||
auths := registry.Combine(
|
||||
registry.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
),
|
||||
registry.FileSource(
|
||||
config.Docker.Config,
|
||||
),
|
||||
registry.EndpointSource(
|
||||
config.Registries.Endpoint,
|
||||
config.Registries.Password,
|
||||
config.Registries.SkipVerify,
|
||||
),
|
||||
)
|
||||
|
||||
manager := rpc.NewClient(
|
||||
config.RPC.Proto+"://"+config.RPC.Host,
|
||||
config.RPC.Secret,
|
||||
)
|
||||
if config.RPC.Debug {
|
||||
manager.SetDebug(true)
|
||||
}
|
||||
if config.Logging.Trace {
|
||||
manager.SetDebug(true)
|
||||
}
|
||||
|
||||
engine, err := docker.NewEnv()
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("cannot load the docker engine")
|
||||
}
|
||||
for {
|
||||
err := docker.Ping(ctx, engine)
|
||||
if err == context.Canceled {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Errorln("cannot ping the docker daemon")
|
||||
time.Sleep(time.Second)
|
||||
} else {
|
||||
logrus.Debugln("successfully pinged the docker daemon")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
r := &runner.Runner{
|
||||
Platform: config.Runner.Platform,
|
||||
OS: config.Runner.OS,
|
||||
Arch: config.Runner.Arch,
|
||||
Kernel: config.Runner.Kernel,
|
||||
Variant: config.Runner.Variant,
|
||||
Engine: engine,
|
||||
Manager: manager,
|
||||
Registry: auths,
|
||||
Secrets: secrets,
|
||||
Volumes: config.Runner.Volumes,
|
||||
Networks: config.Runner.Networks,
|
||||
Devices: config.Runner.Devices,
|
||||
Privileged: config.Runner.Privileged,
|
||||
Machine: config.Runner.Machine,
|
||||
Labels: config.Runner.Labels,
|
||||
Environ: config.Runner.Environ,
|
||||
Limits: runner.Limits{
|
||||
MemSwapLimit: int64(config.Runner.Limits.MemSwapLimit),
|
||||
MemLimit: int64(config.Runner.Limits.MemLimit),
|
||||
ShmSize: int64(config.Runner.Limits.ShmSize),
|
||||
CPUQuota: config.Runner.Limits.CPUQuota,
|
||||
CPUShares: config.Runner.Limits.CPUShares,
|
||||
CPUSet: config.Runner.Limits.CPUSet,
|
||||
},
|
||||
}
|
||||
if err := r.Start(ctx, config.Runner.Capacity); err != nil {
|
||||
logrus.WithError(err).
|
||||
Warnln("program terminated")
|
||||
}
|
||||
}
|
||||
|
||||
// helper function configures the logging.
|
||||
func initLogging(c config.Config) {
|
||||
if c.Logging.Debug {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if c.Logging.Trace {
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
if c.Logging.Text {
|
||||
logrus.SetFormatter(&logrus.TextFormatter{
|
||||
ForceColors: c.Logging.Color,
|
||||
DisableColors: !c.Logging.Color,
|
||||
})
|
||||
} else {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
||||
PrettyPrint: c.Logging.Pretty,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
||||
// IMPORTANT please do not add new configuration parameters unless it has
|
||||
// been discussed on the mailing list. We are attempting to reduce the
|
||||
// number of configuration parameters, and may reject pull requests that
|
||||
// introduce new parameters. (mailing list https://discourse.drone.io)
|
||||
|
||||
// default runner hostname.
|
||||
var hostname string
|
||||
|
||||
func init() {
|
||||
hostname, _ = os.Hostname()
|
||||
if hostname == "" {
|
||||
hostname = "localhost"
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// Config provides the system configuration.
|
||||
Config struct {
|
||||
Docker Docker
|
||||
Logging Logging
|
||||
Registries Registries
|
||||
Runner Runner
|
||||
RPC RPC
|
||||
Server Server
|
||||
Secrets Secrets
|
||||
}
|
||||
|
||||
// Docker provides docker configuration
|
||||
Docker struct {
|
||||
Config string `envconfig:"DRONE_DOCKER_CONFIG"`
|
||||
}
|
||||
|
||||
// Logging provides the logging configuration.
|
||||
Logging struct {
|
||||
Debug bool `envconfig:"DRONE_LOGS_DEBUG"`
|
||||
Trace bool `envconfig:"DRONE_LOGS_TRACE"`
|
||||
Color bool `envconfig:"DRONE_LOGS_COLOR"`
|
||||
Pretty bool `envconfig:"DRONE_LOGS_PRETTY"`
|
||||
Text bool `envconfig:"DRONE_LOGS_TEXT"`
|
||||
}
|
||||
|
||||
// Registries provides the registry configuration.
|
||||
Registries struct {
|
||||
Endpoint string `envconfig:"DRONE_REGISTRY_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_REGISTRY_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_REGISTRY_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Secrets provides the secret configuration.
|
||||
Secrets struct {
|
||||
Endpoint string `envconfig:"DRONE_SECRET_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_SECRET_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_SECRET_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// RPC provides the rpc configuration.
|
||||
RPC struct {
|
||||
Server string `envconfig:"DRONE_RPC_SERVER"`
|
||||
Secret string `envconfig:"DRONE_RPC_SECRET"`
|
||||
Debug bool `envconfig:"DRONE_RPC_DEBUG"`
|
||||
Host string `envconfig:"DRONE_RPC_HOST"`
|
||||
Proto string `envconfig:"DRONE_RPC_PROTO"`
|
||||
// Hosts map[string]string `envconfig:"DRONE_RPC_EXTRA_HOSTS"`
|
||||
}
|
||||
|
||||
// Runner provides the runner configuration.
|
||||
Runner struct {
|
||||
Platform string `envconfig:"DRONE_RUNNER_PLATFORM" default:"linux/amd64"`
|
||||
OS string `envconfig:"DRONE_RUNNER_OS"`
|
||||
Arch string `envconfig:"DRONE_RUNNER_ARCH"`
|
||||
Kernel string `envconfig:"DRONE_RUNNER_KERNEL"`
|
||||
Variant string `envconfig:"DRONE_RUNNER_VARIANT"`
|
||||
Machine string `envconfig:"DRONE_RUNNER_NAME"`
|
||||
Capacity int `envconfig:"DRONE_RUNNER_CAPACITY" default:"2"`
|
||||
Labels map[string]string `envconfig:"DRONE_RUNNER_LABELS"`
|
||||
Volumes []string `envconfig:"DRONE_RUNNER_VOLUMES"`
|
||||
Networks []string `envconfig:"DRONE_RUNNER_NETWORKS"`
|
||||
Devices []string `envconfig:"DRONE_RUNNER_DEVICES"`
|
||||
Privileged []string `envconfig:"DRONE_RUNNER_PRIVILEGED_IMAGES"`
|
||||
Environ map[string]string `envconfig:"DRONE_RUNNER_ENVIRON"`
|
||||
Limits struct {
|
||||
MemSwapLimit Bytes `envconfig:"DRONE_LIMIT_MEM_SWAP"`
|
||||
MemLimit Bytes `envconfig:"DRONE_LIMIT_MEM"`
|
||||
ShmSize Bytes `envconfig:"DRONE_LIMIT_SHM_SIZE"`
|
||||
CPUQuota int64 `envconfig:"DRONE_LIMIT_CPU_QUOTA"`
|
||||
CPUShares int64 `envconfig:"DRONE_LIMIT_CPU_SHARES"`
|
||||
CPUSet string `envconfig:"DRONE_LIMIT_CPU_SET"`
|
||||
}
|
||||
}
|
||||
|
||||
// Server provides the server configuration.
|
||||
Server struct {
|
||||
Addr string `envconfig:"-"`
|
||||
Host string `envconfig:"DRONE_SERVER_HOST" default:"localhost:8080"`
|
||||
Proto string `envconfig:"DRONE_SERVER_PROTO" default:"http"`
|
||||
}
|
||||
)
|
||||
|
||||
// Environ returns the settings from the environment.
|
||||
func Environ() (Config, error) {
|
||||
cfg := Config{}
|
||||
err := envconfig.Process("", &cfg)
|
||||
defaultRunner(&cfg)
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func defaultRunner(c *Config) {
|
||||
if c.Runner.Machine == "" {
|
||||
c.Runner.Machine = hostname
|
||||
}
|
||||
parts := strings.Split(c.Runner.Platform, "/")
|
||||
if len(parts) == 2 && c.Runner.OS == "" {
|
||||
c.Runner.OS = parts[0]
|
||||
}
|
||||
if len(parts) == 2 && c.Runner.Arch == "" {
|
||||
c.Runner.Arch = parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes stores number bytes (e.g. megabytes)
|
||||
type Bytes int64
|
||||
|
||||
// Decode implements a decoder that parses a string representation
|
||||
// of bytes into the number of bytes it represents.
|
||||
func (b *Bytes) Decode(value string) error {
|
||||
v, err := humanize.ParseBytes(value)
|
||||
*b = Bytes(v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value of the Byte.
|
||||
func (b *Bytes) Int64() int64 {
|
||||
return int64(*b)
|
||||
}
|
||||
|
||||
// String returns the string value of the Byte.
|
||||
func (b *Bytes) String() string {
|
||||
return fmt.Sprint(*b)
|
||||
}
|
||||
|
||||
// UserCreate stores account information used to bootstrap
|
||||
// the admin user account when the system initializes.
|
||||
type UserCreate struct {
|
||||
Username string
|
||||
Machine bool
|
||||
Admin bool
|
||||
Token string
|
||||
}
|
||||
|
||||
// Decode implements a decoder that extracts user information
|
||||
// from the environment variable string.
|
||||
func (u *UserCreate) Decode(value string) error {
|
||||
for _, param := range strings.Split(value, ",") {
|
||||
parts := strings.Split(param, ":")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := parts[0]
|
||||
val := parts[1]
|
||||
switch key {
|
||||
case "username":
|
||||
u.Username = val
|
||||
case "token":
|
||||
u.Token = val
|
||||
case "machine":
|
||||
u.Machine = val == "true"
|
||||
case "admin":
|
||||
u.Admin = val == "true"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/drone/drone-runtime/engine"
|
||||
"github.com/drone/drone-runtime/engine/docker"
|
||||
"github.com/drone/drone-runtime/engine/kube"
|
||||
"github.com/drone/drone/cmd/drone-controller/config"
|
||||
"github.com/drone/drone/operator/manager/rpc"
|
||||
"github.com/drone/drone/operator/runner"
|
||||
"github.com/drone/drone/plugin/registry"
|
||||
"github.com/drone/drone/plugin/secret"
|
||||
"github.com/drone/signal"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config, err := config.Environ()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatalln("invalid configuration")
|
||||
}
|
||||
|
||||
initLogging(config)
|
||||
ctx := signal.WithContext(
|
||||
context.Background(),
|
||||
)
|
||||
|
||||
secrets := secret.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
)
|
||||
|
||||
auths := registry.Combine(
|
||||
registry.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
),
|
||||
registry.FileSource(
|
||||
config.Docker.Config,
|
||||
),
|
||||
registry.EndpointSource(
|
||||
config.Registries.Endpoint,
|
||||
config.Registries.Password,
|
||||
config.Registries.SkipVerify,
|
||||
),
|
||||
)
|
||||
|
||||
manager := rpc.NewClient(
|
||||
config.RPC.Proto+"://"+config.RPC.Host,
|
||||
config.RPC.Secret,
|
||||
)
|
||||
if config.RPC.Debug {
|
||||
manager.SetDebug(true)
|
||||
}
|
||||
if config.Logging.Trace {
|
||||
manager.SetDebug(true)
|
||||
}
|
||||
|
||||
var engine engine.Engine
|
||||
|
||||
if isKubernetes() {
|
||||
engine, err = kube.NewFile("", "", config.Runner.Machine)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("cannot create the kubernetes client")
|
||||
}
|
||||
} else {
|
||||
engine, err = docker.NewEnv()
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("cannot load the docker engine")
|
||||
}
|
||||
}
|
||||
|
||||
r := &runner.Runner{
|
||||
Platform: config.Runner.Platform,
|
||||
OS: config.Runner.OS,
|
||||
Arch: config.Runner.Arch,
|
||||
Kernel: config.Runner.Kernel,
|
||||
Variant: config.Runner.Variant,
|
||||
Engine: engine,
|
||||
Manager: manager,
|
||||
Registry: auths,
|
||||
Secrets: secrets,
|
||||
Volumes: config.Runner.Volumes,
|
||||
Networks: config.Runner.Networks,
|
||||
Devices: config.Runner.Devices,
|
||||
Privileged: config.Runner.Privileged,
|
||||
Machine: config.Runner.Machine,
|
||||
Labels: config.Runner.Labels,
|
||||
Environ: config.Runner.Environ,
|
||||
Limits: runner.Limits{
|
||||
MemSwapLimit: int64(config.Runner.Limits.MemSwapLimit),
|
||||
MemLimit: int64(config.Runner.Limits.MemLimit),
|
||||
ShmSize: int64(config.Runner.Limits.ShmSize),
|
||||
CPUQuota: config.Runner.Limits.CPUQuota,
|
||||
CPUShares: config.Runner.Limits.CPUShares,
|
||||
CPUSet: config.Runner.Limits.CPUSet,
|
||||
},
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(os.Getenv("DRONE_STAGE_ID"), 10, 64)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("cannot parse stage ID")
|
||||
}
|
||||
if err := r.Run(ctx, id); err != nil {
|
||||
logrus.WithError(err).
|
||||
Warnln("program terminated")
|
||||
}
|
||||
}
|
||||
|
||||
func isKubernetes() bool {
|
||||
return os.Getenv("KUBERNETES_SERVICE_HOST") != ""
|
||||
}
|
||||
|
||||
// helper function configures the logging.
|
||||
func initLogging(c config.Config) {
|
||||
if c.Logging.Debug {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if c.Logging.Trace {
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
if c.Logging.Text {
|
||||
logrus.SetFormatter(&logrus.TextFormatter{
|
||||
ForceColors: c.Logging.Color,
|
||||
DisableColors: !c.Logging.Color,
|
||||
})
|
||||
} else {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
||||
PrettyPrint: c.Logging.Pretty,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -67,8 +67,6 @@ type (
|
|||
Registries Registries
|
||||
Repository Repository
|
||||
Runner Runner
|
||||
Nomad Nomad
|
||||
Kube Kubernetes
|
||||
RPC RPC
|
||||
S3 S3
|
||||
Secrets Secrets
|
||||
|
@ -143,32 +141,6 @@ type (
|
|||
Enabled bool `envconfig:"DRONE_STARLARK_ENABLED"`
|
||||
}
|
||||
|
||||
// Kubernetes provides kubernetes configuration
|
||||
Kubernetes struct {
|
||||
Enabled bool `envconfig:"DRONE_KUBERNETES_ENABLED"`
|
||||
Namespace string `envconfig:"DRONE_KUBERNETES_NAMESPACE"`
|
||||
Path string `envconfig:"DRONE_KUBERNETES_CONFIG_PATH"`
|
||||
URL string `envconfig:"DRONE_KUBERNETES_CONFIG_URL"`
|
||||
TTL int `envconfig:"DRONE_KUBERNETES_TTL_AFTER_FINISHED" default:"300"`
|
||||
ServiceAccountName string `envconfig:"DRONE_KUBERNETES_SERVICE_ACCOUNT"`
|
||||
PullPolicy string `envconfig:"DRONE_KUBERNETES_IMAGE_PULL" default:"Always"`
|
||||
Image string `envconfig:"DRONE_KUBERNETES_IMAGE"`
|
||||
}
|
||||
|
||||
// Nomad configuration.
|
||||
Nomad struct {
|
||||
Enabled bool `envconfig:"DRONE_NOMAD_ENABLED"`
|
||||
Datacenters []string `envconfig:"DRONE_NOMAD_DATACENTER" default:"dc1"`
|
||||
Namespace string `envconfig:"DRONE_NOMAD_NAMESPACE"`
|
||||
Region string `envconfig:"DRONE_NOMAD_REGION"`
|
||||
Prefix string `envconfig:"DRONE_NOMAD_JOB_PREFIX" default:"drone-job-"`
|
||||
Image string `envconfig:"DRONE_NOMAD_IMAGE"`
|
||||
ImagePull bool `envconfig:"DRONE_NOMAD_IMAGE_PULL"`
|
||||
Memory int `envconfig:"DRONE_NOMAD_DEFAULT_RAM" default:"1024"`
|
||||
Labels map[string]string `envconfig:"DRONE_NOMAD_LABELS"`
|
||||
CPU int `envconfig:"DRONE_NOMAD_DEFAULT_CPU" default:"500"`
|
||||
}
|
||||
|
||||
// License provides license configuration
|
||||
License struct {
|
||||
Key string `envconfig:"DRONE_LICENSE"`
|
||||
|
|
|
@ -38,9 +38,9 @@ func provideRunner(
|
|||
registry core.RegistryService,
|
||||
config config.Config,
|
||||
) *runner.Runner {
|
||||
// the local runner is only created when the nomad scheduler,
|
||||
// kubernetes scheduler, and remote agents are disabled
|
||||
if config.Nomad.Enabled || config.Kube.Enabled || (config.Agent.Disabled == false) {
|
||||
// the local runner is only created when remote agents
|
||||
// are disabled
|
||||
if config.Agent.Disabled == false {
|
||||
return nil
|
||||
}
|
||||
engine, err := docker.NewEnv()
|
||||
|
|
|
@ -17,12 +17,9 @@ package main
|
|||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/scheduler/kube"
|
||||
"github.com/drone/drone/scheduler/nomad"
|
||||
"github.com/drone/drone/scheduler/queue"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the scheduler.
|
||||
|
@ -33,97 +30,5 @@ var schedulerSet = wire.NewSet(
|
|||
// provideScheduler is a Wire provider function that returns a
|
||||
// scheduler based on the environment configuration.
|
||||
func provideScheduler(store core.StageStore, config config.Config) core.Scheduler {
|
||||
switch {
|
||||
case config.Kube.Enabled:
|
||||
return provideKubernetesScheduler(config)
|
||||
case config.Nomad.Enabled:
|
||||
return provideNomadScheduler(config)
|
||||
default:
|
||||
return provideQueueScheduler(store, config)
|
||||
}
|
||||
}
|
||||
|
||||
// provideKubernetesScheduler is a Wire provider function that
|
||||
// returns a nomad kubernetes from the environment configuration.
|
||||
func provideKubernetesScheduler(config config.Config) core.Scheduler {
|
||||
logrus.Info("main: kubernetes scheduler enabled")
|
||||
sched, err := kube.FromConfig(kube.Config{
|
||||
Namespace: config.Kube.Namespace,
|
||||
ServiceAccount: config.Kube.ServiceAccountName,
|
||||
ConfigURL: config.Kube.URL,
|
||||
ConfigPath: config.Kube.Path,
|
||||
TTL: config.Kube.TTL,
|
||||
Image: config.Kube.Image,
|
||||
ImagePullPolicy: config.Kube.PullPolicy,
|
||||
ImagePrivileged: config.Runner.Privileged,
|
||||
// LimitMemory: config.Nomad.Memory,
|
||||
// LimitCompute: config.Nomad.CPU,
|
||||
// RequestMemory: config.Nomad.Memory,
|
||||
// RequestCompute: config.Nomad.CPU,
|
||||
CallbackHost: config.RPC.Host,
|
||||
CallbackProto: config.RPC.Proto,
|
||||
CallbackSecret: config.RPC.Secret,
|
||||
SecretToken: config.Secrets.Password,
|
||||
SecretEndpoint: config.Secrets.Endpoint,
|
||||
SecretInsecure: config.Secrets.SkipVerify,
|
||||
RegistryToken: config.Registries.Password,
|
||||
RegistryEndpoint: config.Registries.Endpoint,
|
||||
RegistryInsecure: config.Registries.SkipVerify,
|
||||
LogDebug: config.Logging.Debug,
|
||||
LogTrace: config.Logging.Trace,
|
||||
LogPretty: config.Logging.Pretty,
|
||||
LogText: config.Logging.Text,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create kubernetes client")
|
||||
}
|
||||
return sched
|
||||
}
|
||||
|
||||
// provideNomadScheduler is a Wire provider function that returns
|
||||
// a nomad scheduler from the environment configuration.
|
||||
func provideNomadScheduler(config config.Config) core.Scheduler {
|
||||
logrus.Info("main: nomad scheduler enabled")
|
||||
sched, err := nomad.FromConfig(nomad.Config{
|
||||
Datacenter: config.Nomad.Datacenters,
|
||||
Labels: config.Nomad.Labels,
|
||||
Namespace: config.Nomad.Namespace,
|
||||
Region: config.Nomad.Region,
|
||||
DockerImage: config.Nomad.Image,
|
||||
DockerImagePull: config.Nomad.ImagePull,
|
||||
DockerImagePriv: config.Runner.Privileged,
|
||||
DockerHost: "",
|
||||
DockerHostWin: "",
|
||||
// LimitMemory: config.Nomad.Memory,
|
||||
// LimitCompute: config.Nomad.CPU,
|
||||
RequestMemory: config.Nomad.Memory,
|
||||
RequestCompute: config.Nomad.CPU,
|
||||
CallbackHost: config.RPC.Host,
|
||||
CallbackProto: config.RPC.Proto,
|
||||
CallbackSecret: config.RPC.Secret,
|
||||
SecretToken: config.Secrets.Password,
|
||||
SecretEndpoint: config.Secrets.Endpoint,
|
||||
SecretInsecure: config.Secrets.SkipVerify,
|
||||
RegistryToken: config.Registries.Password,
|
||||
RegistryEndpoint: config.Registries.Endpoint,
|
||||
RegistryInsecure: config.Registries.SkipVerify,
|
||||
LogDebug: config.Logging.Debug,
|
||||
LogTrace: config.Logging.Trace,
|
||||
LogPretty: config.Logging.Pretty,
|
||||
LogText: config.Logging.Text,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create nomad client")
|
||||
}
|
||||
return sched
|
||||
}
|
||||
|
||||
// provideQueueScheduler is a Wire provider function that
|
||||
// returns an in-memory scheduler for use by the built-in
|
||||
// docker runner, and by remote agents.
|
||||
func provideQueueScheduler(store core.StageStore, config config.Config) core.Scheduler {
|
||||
logrus.Info("main: internal scheduler enabled")
|
||||
return queue.New(store)
|
||||
}
|
||||
|
|
|
@ -209,21 +209,19 @@ func provideDatadog(
|
|||
builds,
|
||||
*system,
|
||||
sink.Config{
|
||||
Endpoint: config.Datadog.Endpoint,
|
||||
Token: config.Datadog.Token,
|
||||
License: license.Kind,
|
||||
Licensor: license.Licensor,
|
||||
Subscription: license.Subscription,
|
||||
EnableGithub: config.IsGitHub(),
|
||||
EnableGithubEnt: config.IsGitHubEnterprise(),
|
||||
EnableGitlab: config.IsGitLab(),
|
||||
EnableBitbucket: config.IsBitbucket(),
|
||||
EnableStash: config.IsStash(),
|
||||
EnableGogs: config.IsGogs(),
|
||||
EnableGitea: config.IsGitea(),
|
||||
EnableAgents: !config.Agent.Disabled,
|
||||
EnableNomad: config.Nomad.Enabled,
|
||||
EnableKubernetes: config.Kube.Enabled,
|
||||
Endpoint: config.Datadog.Endpoint,
|
||||
Token: config.Datadog.Token,
|
||||
License: license.Kind,
|
||||
Licensor: license.Licensor,
|
||||
Subscription: license.Subscription,
|
||||
EnableGithub: config.IsGitHub(),
|
||||
EnableGithubEnt: config.IsGitHubEnterprise(),
|
||||
EnableGitlab: config.IsGitLab(),
|
||||
EnableBitbucket: config.IsBitbucket(),
|
||||
EnableStash: config.IsStash(),
|
||||
EnableGogs: config.IsGogs(),
|
||||
EnableGitea: config.IsGitea(),
|
||||
EnableAgents: !config.Agent.Disabled,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,17 +19,15 @@ type Config struct {
|
|||
Endpoint string
|
||||
Token string
|
||||
|
||||
License string
|
||||
Licensor string
|
||||
Subscription string
|
||||
EnableGithub bool
|
||||
EnableGithubEnt bool
|
||||
EnableGitlab bool
|
||||
EnableBitbucket bool
|
||||
EnableStash bool
|
||||
EnableGogs bool
|
||||
EnableGitea bool
|
||||
EnableAgents bool
|
||||
EnableNomad bool
|
||||
EnableKubernetes bool
|
||||
License string
|
||||
Licensor string
|
||||
Subscription string
|
||||
EnableGithub bool
|
||||
EnableGithubEnt bool
|
||||
EnableGitlab bool
|
||||
EnableBitbucket bool
|
||||
EnableStash bool
|
||||
EnableGogs bool
|
||||
EnableGitea bool
|
||||
EnableAgents bool
|
||||
}
|
||||
|
|
|
@ -47,10 +47,6 @@ func createTags(config Config) []string {
|
|||
switch {
|
||||
case config.EnableAgents:
|
||||
tags = append(tags, "scheduler:internal:agents")
|
||||
case config.EnableKubernetes:
|
||||
tags = append(tags, "scheduler:kubernetes")
|
||||
case config.EnableNomad:
|
||||
tags = append(tags, "scheduler:nomad")
|
||||
default:
|
||||
tags = append(tags, "scheduler:internal:local")
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package internal
|
||||
|
||||
var defaultImage = "drone/controller:1"
|
||||
|
||||
// DefaultImage returns the default dispatch image if none
|
||||
// is specified.
|
||||
func DefaultImage(image string) string {
|
||||
if image == "" {
|
||||
return defaultImage
|
||||
}
|
||||
return image
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package kube
|
||||
|
||||
// Config is the configuration for the Kubernetes scheduler.
|
||||
type Config struct {
|
||||
Namespace string
|
||||
ServiceAccount string
|
||||
ConfigURL string
|
||||
ConfigPath string
|
||||
TTL int
|
||||
Image string
|
||||
ImagePullPolicy string
|
||||
ImagePrivileged []string
|
||||
DockerHost string
|
||||
DockerHostWin string
|
||||
LimitMemory int
|
||||
LimitCompute int
|
||||
RequestMemory int
|
||||
RequestCompute int
|
||||
CallbackHost string
|
||||
CallbackProto string
|
||||
CallbackSecret string
|
||||
SecretToken string
|
||||
SecretEndpoint string
|
||||
SecretInsecure bool
|
||||
RegistryToken string
|
||||
RegistryEndpoint string
|
||||
RegistryInsecure bool
|
||||
LogDebug bool
|
||||
LogTrace bool
|
||||
LogPretty bool
|
||||
LogText bool
|
||||
}
|
|
@ -1,259 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package kube
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/scheduler/internal"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
type kubeScheduler struct {
|
||||
client *kubernetes.Clientset
|
||||
config Config
|
||||
}
|
||||
|
||||
// FromConfig returns a new Kubernetes scheduler.
|
||||
func FromConfig(conf Config) (core.Scheduler, error) {
|
||||
config, err := clientcmd.BuildConfigFromFlags(conf.ConfigURL, conf.ConfigPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &kubeScheduler{client: client, config: conf}, nil
|
||||
}
|
||||
|
||||
var _ core.Scheduler = (*kubeScheduler)(nil)
|
||||
|
||||
// Schedule schedules the stage for execution.
|
||||
func (s *kubeScheduler) Schedule(ctx context.Context, stage *core.Stage) error {
|
||||
env := toEnvironment(
|
||||
map[string]string{
|
||||
"DRONE_RUNNER_PRIVILEGED_IMAGES": strings.Join(s.config.ImagePrivileged, ","),
|
||||
"DRONE_LIMIT_MEM": fmt.Sprint(s.config.LimitMemory),
|
||||
"DRONE_LIMIT_CPU": fmt.Sprint(s.config.LimitCompute),
|
||||
"DRONE_STAGE_ID": fmt.Sprint(stage.ID),
|
||||
"DRONE_LOGS_DEBUG": fmt.Sprint(s.config.LogDebug),
|
||||
"DRONE_LOGS_TRACE": fmt.Sprint(s.config.LogTrace),
|
||||
"DRONE_LOGS_PRETTY": fmt.Sprint(s.config.LogPretty),
|
||||
"DRONE_LOGS_TEXT": fmt.Sprint(s.config.LogText),
|
||||
"DRONE_RPC_PROTO": s.config.CallbackProto,
|
||||
"DRONE_RPC_HOST": s.config.CallbackHost,
|
||||
"DRONE_RPC_SECRET": s.config.CallbackSecret,
|
||||
"DRONE_RPC_DEBUG": fmt.Sprint(s.config.LogTrace),
|
||||
"DRONE_REGISTRY_ENDPOINT": s.config.RegistryEndpoint,
|
||||
"DRONE_REGISTRY_SECRET": s.config.RegistryToken,
|
||||
"DRONE_REGISTRY_SKIP_VERIFY": fmt.Sprint(s.config.RegistryInsecure),
|
||||
"DRONE_SECRET_ENDPOINT": s.config.SecretEndpoint,
|
||||
"DRONE_SECRET_SECRET": s.config.SecretToken,
|
||||
"DRONE_SECRET_SKIP_VERIFY": fmt.Sprint(s.config.SecretInsecure),
|
||||
},
|
||||
)
|
||||
|
||||
env = append(env,
|
||||
v1.EnvVar{
|
||||
Name: "KUBERNETES_NODE",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "spec.nodeName",
|
||||
},
|
||||
},
|
||||
},
|
||||
v1.EnvVar{
|
||||
Name: "DRONE_RUNNER_NAME",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
FieldRef: &v1.ObjectFieldSelector{
|
||||
FieldPath: "spec.nodeName",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
var pull v1.PullPolicy
|
||||
switch s.config.ImagePullPolicy {
|
||||
case "IfNotPresent":
|
||||
pull = v1.PullIfNotPresent
|
||||
case "Never":
|
||||
pull = v1.PullNever
|
||||
case "Always":
|
||||
pull = v1.PullAlways
|
||||
}
|
||||
|
||||
rand := strings.ToLower(uniuri.NewLen(12))
|
||||
name := fmt.Sprintf("drone-job-%d-%s", stage.ID, rand)
|
||||
|
||||
var mounts []v1.VolumeMount
|
||||
mount := v1.VolumeMount{
|
||||
Name: name + "-local",
|
||||
MountPath: filepath.Join("/tmp", "drone"),
|
||||
}
|
||||
mounts = append(mounts, mount)
|
||||
|
||||
var volumes []v1.Volume
|
||||
source := v1.HostPathDirectoryOrCreate
|
||||
volume := v1.Volume{
|
||||
Name: name + "-local",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: filepath.Join("/tmp", "drone"),
|
||||
Type: &source,
|
||||
},
|
||||
},
|
||||
}
|
||||
volumes = append(volumes, volume)
|
||||
|
||||
job := &batchv1.Job{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: name,
|
||||
Namespace: s.namespace(),
|
||||
Annotations: map[string]string{
|
||||
"io.drone": "true",
|
||||
"io.drone.stage.created": time.Unix(stage.Created, 0).String(),
|
||||
"io.drone.stage.scheduled": time.Now().String(),
|
||||
"io.drone.stage.id": fmt.Sprint(stage.ID),
|
||||
"io.drone.stage.number": fmt.Sprint(stage.Number),
|
||||
"io.drone.stage.os": fmt.Sprint(stage.OS),
|
||||
"io.drone.stage.arch": fmt.Sprint(stage.Arch),
|
||||
"io.drone.build.id": fmt.Sprint(stage.BuildID),
|
||||
"io.drone.repo.id": fmt.Sprint(stage.RepoID),
|
||||
},
|
||||
},
|
||||
Spec: batchv1.JobSpec{
|
||||
TTLSecondsAfterFinished: int32ptr(int32(s.config.TTL)),
|
||||
Template: v1.PodTemplateSpec{
|
||||
Spec: v1.PodSpec{
|
||||
ServiceAccountName: s.config.ServiceAccount,
|
||||
RestartPolicy: v1.RestartPolicyNever,
|
||||
Containers: []v1.Container{{
|
||||
Name: "drone-controller",
|
||||
Image: internal.DefaultImage(s.config.Image),
|
||||
ImagePullPolicy: pull,
|
||||
Env: env,
|
||||
VolumeMounts: mounts,
|
||||
}},
|
||||
Volumes: volumes,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if len(stage.Labels) > 0 {
|
||||
job.Spec.Template.Spec.NodeSelector = stage.Labels
|
||||
}
|
||||
|
||||
if arch := stage.Arch; arch != "amd64" {
|
||||
if job.Spec.Template.Spec.NodeSelector == nil {
|
||||
job.Spec.Template.Spec.NodeSelector = map[string]string{}
|
||||
}
|
||||
job.Spec.Template.Spec.NodeSelector["beta.kubernetes.io/arch"] = arch
|
||||
}
|
||||
|
||||
log := logrus.WithFields(logrus.Fields{
|
||||
"stage-id": stage.ID,
|
||||
"stage-number": stage.Number,
|
||||
"stage-name": stage.Name,
|
||||
"repo-id": stage.RepoID,
|
||||
"build-id": stage.BuildID,
|
||||
})
|
||||
|
||||
log.Debugf("kubernetes: creating job")
|
||||
job, err := s.client.BatchV1().Jobs(s.namespace()).Create(job)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Errorln("kubernetes: cannot create job")
|
||||
} else {
|
||||
log.Debugf("kubernetes: successfully created job")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Cancel cancels a scheduled or running stage.
|
||||
func (s *kubeScheduler) Cancel(ctx context.Context, id int64) error {
|
||||
prefix := fmt.Sprintf("drone-job-%d-", id)
|
||||
jobs, err := s.client.BatchV1().Jobs(s.namespace()).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var result error
|
||||
for _, job := range jobs.Items {
|
||||
if !strings.HasPrefix(job.Name, prefix) {
|
||||
continue
|
||||
}
|
||||
err = s.client.BatchV1().Jobs(job.Namespace).Delete(job.Name, &metav1.DeleteOptions{
|
||||
// GracePeriodSeconds
|
||||
})
|
||||
if err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) Cancelled(context.Context, int64) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) Request(context.Context, core.Filter) (*core.Stage, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) Stats(_ context.Context) (interface{}, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) Pause(context.Context) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) Resume(context.Context) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *kubeScheduler) namespace() string {
|
||||
namespace := s.config.Namespace
|
||||
if namespace == "" {
|
||||
namespace = metav1.NamespaceDefault
|
||||
}
|
||||
return namespace
|
||||
}
|
||||
|
||||
func int32ptr(x int32) *int32 {
|
||||
return &x
|
||||
}
|
||||
|
||||
func toEnvironment(from map[string]string) []v1.EnvVar {
|
||||
var to []v1.EnvVar
|
||||
for k, v := range from {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
to = append(to, v1.EnvVar{
|
||||
Name: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
return to
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build oss
|
||||
|
||||
package kube
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
type noop struct{}
|
||||
|
||||
// FromConfig returns a no-op Kubernetes scheduler.
|
||||
func FromConfig(conf Config) (core.Scheduler, error) {
|
||||
return new(noop), nil
|
||||
}
|
||||
|
||||
func (noop) Schedule(context.Context, *core.Stage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Request(context.Context, core.Filter) (*core.Stage, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) Cancel(context.Context, int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Cancelled(context.Context, int64) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (noop) Stats(context.Context) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) Pause(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Resume(context.Context) error {
|
||||
return nil
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package nomad
|
||||
|
||||
// Config is the configuration for the Nomad scheduler.
|
||||
type Config struct {
|
||||
Datacenter []string
|
||||
Labels map[string]string
|
||||
Namespace string
|
||||
Region string
|
||||
DockerImage string
|
||||
DockerImagePull bool
|
||||
DockerImagePriv []string
|
||||
DockerHost string
|
||||
DockerHostWin string
|
||||
LimitMemory int
|
||||
LimitCompute int
|
||||
RequestMemory int
|
||||
RequestCompute int
|
||||
CallbackHost string
|
||||
CallbackProto string
|
||||
CallbackSecret string
|
||||
SecretToken string
|
||||
SecretEndpoint string
|
||||
SecretInsecure bool
|
||||
RegistryToken string
|
||||
RegistryEndpoint string
|
||||
RegistryInsecure bool
|
||||
LogDebug bool
|
||||
LogTrace bool
|
||||
LogPretty bool
|
||||
LogText bool
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package nomad
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/scheduler/internal"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var _ core.Scheduler = (*nomadScheduler)(nil)
|
||||
|
||||
// Docker host.
|
||||
const (
|
||||
dockerHostPosix = "/var/run/docker.sock"
|
||||
dockerHostWindows = "////./pipe/docker_engine"
|
||||
)
|
||||
|
||||
type nomadScheduler struct {
|
||||
client *api.Client
|
||||
config Config
|
||||
}
|
||||
|
||||
// FromConfig returns a new Nomad scheduler.
|
||||
func FromConfig(conf Config) (core.Scheduler, error) {
|
||||
config := api.DefaultConfig()
|
||||
client, err := api.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &nomadScheduler{client: client, config: conf}, nil
|
||||
}
|
||||
|
||||
// Schedule schedules the stage for execution.
|
||||
func (s *nomadScheduler) Schedule(ctx context.Context, stage *core.Stage) error {
|
||||
env := map[string]string{
|
||||
"DRONE_RUNNER_PRIVILEGED_IMAGES": strings.Join(s.config.DockerImagePriv, ","),
|
||||
"DRONE_LIMIT_MEM": fmt.Sprint(s.config.LimitMemory),
|
||||
"DRONE_LIMIT_CPU": fmt.Sprint(s.config.LimitCompute),
|
||||
"DRONE_STAGE_ID": fmt.Sprint(stage.ID),
|
||||
"DRONE_LOGS_DEBUG": fmt.Sprint(s.config.LogDebug),
|
||||
"DRONE_LOGS_TRACE": fmt.Sprint(s.config.LogTrace),
|
||||
"DRONE_LOGS_PRETTY": fmt.Sprint(s.config.LogPretty),
|
||||
"DRONE_LOGS_TEXT": fmt.Sprint(s.config.LogText),
|
||||
"DRONE_RPC_PROTO": s.config.CallbackProto,
|
||||
"DRONE_RPC_HOST": s.config.CallbackHost,
|
||||
"DRONE_RPC_SECRET": s.config.CallbackSecret,
|
||||
"DRONE_RPC_DEBUG": fmt.Sprint(s.config.LogTrace),
|
||||
"DRONE_REGISTRY_ENDPOINT": s.config.RegistryEndpoint,
|
||||
"DRONE_REGISTRY_SECRET": s.config.RegistryToken,
|
||||
"DRONE_REGISTRY_SKIP_VERIFY": fmt.Sprint(s.config.RegistryInsecure),
|
||||
"DRONE_SECRET_ENDPOINT": s.config.SecretEndpoint,
|
||||
"DRONE_SECRET_SECRET": s.config.SecretToken,
|
||||
"DRONE_SECRET_SKIP_VERIFY": fmt.Sprint(s.config.SecretInsecure),
|
||||
}
|
||||
|
||||
volume := "/var/run/docker.sock:/var/run/docker.sock"
|
||||
if stage.OS == "windows" {
|
||||
volume = "////./pipe/docker_engine:////./pipe/docker_engine"
|
||||
}
|
||||
|
||||
task := &api.Task{
|
||||
Name: "stage",
|
||||
Driver: "docker",
|
||||
Env: env,
|
||||
Resources: &api.Resources{},
|
||||
Config: map[string]interface{}{
|
||||
"image": internal.DefaultImage(s.config.DockerImage),
|
||||
"force_pull": s.config.DockerImagePull,
|
||||
"volumes": []string{volume},
|
||||
},
|
||||
}
|
||||
|
||||
if i := s.config.RequestCompute; i != 0 {
|
||||
task.Resources.CPU = intToPtr(i)
|
||||
}
|
||||
if i := s.config.RequestMemory; i != 0 {
|
||||
task.Resources.MemoryMB = intToPtr(i)
|
||||
}
|
||||
|
||||
rand := uniuri.NewLen(12)
|
||||
name := fmt.Sprintf("drone-job-%d-%s", stage.BuildID, rand)
|
||||
|
||||
job := &api.Job{
|
||||
ID: stringToPtr(name),
|
||||
Name: stringToPtr(name),
|
||||
Type: stringToPtr("batch"),
|
||||
Datacenters: s.config.Datacenter,
|
||||
TaskGroups: []*api.TaskGroup{
|
||||
&api.TaskGroup{
|
||||
Name: stringToPtr("pipeline"),
|
||||
Tasks: []*api.Task{task},
|
||||
RestartPolicy: &api.RestartPolicy{
|
||||
Mode: stringToPtr("fail"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Meta: map[string]string{
|
||||
"io.drone": "true",
|
||||
"io.drone.stage.created": time.Unix(stage.Created, 0).String(),
|
||||
"io.drone.stage.scheduled": time.Now().String(),
|
||||
"io.drone.stage.id": fmt.Sprint(stage.ID),
|
||||
"io.drone.stage.number": fmt.Sprint(stage.Number),
|
||||
"io.drone.stage.os": fmt.Sprint(stage.OS),
|
||||
"io.drone.stage.arch": fmt.Sprint(stage.Arch),
|
||||
"io.drone.build.id": fmt.Sprint(stage.BuildID),
|
||||
"io.drone.repo.id": fmt.Sprint(stage.RepoID),
|
||||
},
|
||||
}
|
||||
|
||||
if s := s.config.Namespace; s != "" {
|
||||
job.Namespace = stringToPtr(s)
|
||||
}
|
||||
if s := s.config.Region; s != "" {
|
||||
job.Region = stringToPtr(s)
|
||||
}
|
||||
|
||||
// if we are running on darwin we disable os and arch
|
||||
// constraints, since it is possible nomad is running
|
||||
// on the host machine and reports a darwin os, instead
|
||||
// of a linux os.
|
||||
if runtime.GOOS != "darwin" {
|
||||
job.Constraints = []*api.Constraint{
|
||||
{
|
||||
LTarget: "${attr.kernel.name}",
|
||||
RTarget: stage.OS,
|
||||
Operand: "=",
|
||||
},
|
||||
{
|
||||
LTarget: "${attr.cpu.arch}",
|
||||
RTarget: stage.Arch,
|
||||
Operand: "=",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range stage.Labels {
|
||||
job.Constraints = append(job.Constraints, &api.Constraint{
|
||||
LTarget: fmt.Sprintf("${meta.%s}", k),
|
||||
RTarget: v,
|
||||
Operand: "=",
|
||||
})
|
||||
}
|
||||
|
||||
for k, v := range s.config.Labels {
|
||||
job.Constraints = append(job.Constraints, &api.Constraint{
|
||||
LTarget: fmt.Sprintf("${meta.%s}", k),
|
||||
RTarget: v,
|
||||
Operand: "=",
|
||||
})
|
||||
}
|
||||
|
||||
log := logrus.WithFields(logrus.Fields{
|
||||
"stage-id": stage.ID,
|
||||
"stage-number": stage.Number,
|
||||
"stage-name": stage.Name,
|
||||
"repo-id": stage.RepoID,
|
||||
"build-id": stage.BuildID,
|
||||
})
|
||||
|
||||
log.Debugf("nomad: creating job")
|
||||
_, _, err := s.client.Jobs().RegisterOpts(job, &api.RegisterOptions{}, nil)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorln("nomad: cannot create job")
|
||||
} else {
|
||||
log.WithField("job-id", job.ID).Debugf("nomad: successfully created job")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *nomadScheduler) Request(context.Context, core.Filter) (*core.Stage, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// Cancel cancels a scheduled or running stage.
|
||||
func (s *nomadScheduler) Cancel(ctx context.Context, id int64) error {
|
||||
prefix := fmt.Sprintf("drone-job-%d-", id)
|
||||
jobs, _, err := s.client.Jobs().PrefixList(prefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var result error
|
||||
for _, job := range jobs {
|
||||
_, _, err := s.client.Jobs().Deregister(job.ID, false, nil)
|
||||
if err != nil {
|
||||
result = multierror.Append(result, err)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *nomadScheduler) Cancelled(context.Context, int64) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *nomadScheduler) Stats(context.Context) (interface{}, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *nomadScheduler) Pause(context.Context) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (s *nomadScheduler) Resume(context.Context) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// stringToPtr returns the pointer to a string
|
||||
func stringToPtr(str string) *string {
|
||||
return &str
|
||||
}
|
||||
|
||||
// intToPtr returns the pointer to a int
|
||||
func intToPtr(i int) *int {
|
||||
return &i
|
||||
}
|
||||
|
||||
// durationToPtr returns the pointer to a duration
|
||||
func durationToPtr(dur time.Duration) *time.Duration {
|
||||
return &dur
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build oss
|
||||
|
||||
package nomad
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
type noop struct{}
|
||||
|
||||
// FromConfig returns a no-op Nomad scheduler.
|
||||
func FromConfig(conf Config) (core.Scheduler, error) {
|
||||
return new(noop), nil
|
||||
}
|
||||
|
||||
func (noop) Schedule(context.Context, *core.Stage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Request(context.Context, core.Filter) (*core.Stage, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) Cancel(context.Context, int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Cancelled(context.Context, int64) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (noop) Stats(context.Context) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (noop) Pause(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (noop) Resume(context.Context) error {
|
||||
return nil
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package nomad
|
Loading…
Reference in a new issue