// 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. 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 }