485 lines
16 KiB
Go
485 lines
16 KiB
Go
// 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 config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/dchest/uniuri"
|
|
"github.com/dustin/go-humanize"
|
|
"github.com/kelseyhightower/envconfig"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
// 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 {
|
|
License string `envconfig:"DRONE_LICENSE"`
|
|
|
|
Authn Authentication
|
|
Agent Agent
|
|
Cron Cron
|
|
Cloning Cloning
|
|
Database Database
|
|
Docker Docker
|
|
HTTP HTTP
|
|
Logging Logging
|
|
// Prometheus Prometheus
|
|
Proxy Proxy
|
|
Registration Registration
|
|
Registries Registries
|
|
Repository Repository
|
|
Runner Runner
|
|
Nomad Nomad
|
|
Kube Kubernetes
|
|
RPC RPC
|
|
S3 S3
|
|
Secrets Secrets
|
|
Server Server
|
|
Session Session
|
|
Status Status
|
|
Users Users
|
|
Webhook Webhook
|
|
Yaml Yaml
|
|
|
|
// Remote configurations
|
|
Bitbucket Bitbucket
|
|
Gitea Gitea
|
|
Github Github
|
|
GitLab GitLab
|
|
Gogs Gogs
|
|
Stash Stash
|
|
}
|
|
|
|
// Cloning provides the cloning configuration.
|
|
Cloning struct {
|
|
AlwaysAuth bool `envconfig:"DRONE_GIT_ALWAYS_AUTH"`
|
|
Username string `envconfig:"DRONE_GIT_USERNAME"`
|
|
Password string `envconfig:"DRONE_GIT_PASSWORD"`
|
|
Image string `envconfig:"DRONE_GIT_IMAGE"`
|
|
Pull string `envconfig:"DRONE_GIT_IMAGE_PULL" default:"IfNotExists"`
|
|
}
|
|
|
|
// Cron provides the cron configuration.
|
|
Cron struct {
|
|
Disabled bool `envconfig:"DRONE_CRON_DISABLED"`
|
|
Interval time.Duration `envconfig:"DRONE_CRON_INTERVAL" default:"30m"`
|
|
}
|
|
|
|
// Database provides the database configuration.
|
|
Database struct {
|
|
Driver string `envconfig:"DRONE_DATABASE_DRIVER" default:"sqlite3"`
|
|
Datasource string `envconfig:"DRONE_DATABASE_DATASOURCE" default:"core.sqlite"`
|
|
Secret string `envconfig:"DRONE_DATABASE_SECRET"`
|
|
}
|
|
|
|
// Docker provides docker configuration
|
|
Docker struct {
|
|
Config string `envconfig:"DRONE_DOCKER_CONFIG"`
|
|
}
|
|
|
|
// 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"`
|
|
CPU int `envconfig:"DRONE_NOMAD_DEFAULT_CPU" default:"500"`
|
|
}
|
|
|
|
// License provides license configuration
|
|
License struct {
|
|
Key string `envconfig:"DRONE_LICENSE"`
|
|
Endpoint string `envconfig:"DRONE_LICENSE_ENDPOINT"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|
|
|
|
// Repository provides the repository configuration.
|
|
Repository struct {
|
|
Filter []string `envconfig:"DRONE_REPOSITORY_FILTER"`
|
|
}
|
|
|
|
// 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"`
|
|
}
|
|
|
|
Agent struct {
|
|
Enabled bool `envconfig:"DRONE_AGENTS_ENABLED"`
|
|
}
|
|
|
|
// Runner provides the runner configuration.
|
|
Runner struct {
|
|
Local bool `envconfig:"DRONE_RUNNER_LOCAL"`
|
|
Image string `envconfig:"DRONE_RUNNER_IMAGE" default:"drone/controller:1.0.0-rc.5"`
|
|
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"`
|
|
Port string `envconfig:"DRONE_SERVER_PORT" default:":8080"`
|
|
Proto string `envconfig:"DRONE_SERVER_PROTO" default:"http"`
|
|
Acme bool `envconfig:"DRONE_TLS_AUTOCERT"`
|
|
Cert string `envconfig:"DRONE_TLS_CERT"`
|
|
Key string `envconfig:"DRONE_TLS_KEY"`
|
|
}
|
|
|
|
// Proxy provides proxy server configuration.
|
|
Proxy struct {
|
|
Addr string `envconfig:"-"`
|
|
Host string `envconfig:"DRONE_SERVER_PROXY_HOST"`
|
|
Proto string `envconfig:"DRONE_SERVER_PROXY_PROTO"`
|
|
}
|
|
|
|
// Registration configuration.
|
|
Registration struct {
|
|
Closed bool `envconfig:"DRONE_REGISTRATION_CLOSED"`
|
|
}
|
|
|
|
// Authentication Controller configuration
|
|
Authentication struct {
|
|
Endpoint string `envconfig:"DRONE_AUTHENTICATION_ENDPOINT"`
|
|
Token string `envconfig:"DRONE_AUTHENTICATION_TOKEN"`
|
|
SkipVerify bool `envconfig:"DRONE_AUTHENTICATION_SKIP_VERIFY"`
|
|
}
|
|
|
|
// Session provides the session configuration.
|
|
Session struct {
|
|
Timeout time.Duration `envconfig:"DRONE_COOKIE_TIMEOUT" default:"720h"`
|
|
Secret string `envconfig:"DRONE_COOKIE_SECRET"`
|
|
}
|
|
|
|
// Status provides status configurations.
|
|
Status struct {
|
|
Disabled bool `envconfig:"DRONE_STATUS_DISABLED"`
|
|
Name string `envconfig:"DRONE_STATUS_NAME"`
|
|
}
|
|
|
|
// Users provides the user configuration.
|
|
Users struct {
|
|
Create UserCreate `envconfig:"DRONE_USER_CREATE"`
|
|
Filter []string `envconfig:"DRONE_USER_FILTER"`
|
|
MinAge time.Duration `envconfig:"DRONE_MIN_AGE"`
|
|
}
|
|
|
|
// Webhook provides the webhook configuration.
|
|
Webhook struct {
|
|
Endpoint []string `envconfig:"DRONE_WEBHOOK_ENDPOINT"`
|
|
Secret string `envconfig:"DRONE_WEBHOOK_SECRET"`
|
|
SkipVerify bool `envconfig:"DRONE_WEBHOOK_SKIP_VERIFY"`
|
|
}
|
|
|
|
// Yaml provides the yaml webhook configuration.
|
|
Yaml struct {
|
|
Endpoint string `envconfig:"DRONE_YAML_ENDPOINT"`
|
|
Secret string `envconfig:"DRONE_YAML_SECRET"`
|
|
SkipVerify bool `envconfig:"DRONE_YAML_SKIP_VERIFY"`
|
|
}
|
|
|
|
//
|
|
// Source code management.
|
|
//
|
|
|
|
// Bitbucket provides the bitbucket client configuration.
|
|
Bitbucket struct {
|
|
ClientID string `envconfig:"DRONE_BITBUCKET_CLIENT_ID"`
|
|
ClientSecret string `envconfig:"DRONE_BITBUCKET_CLIENT_SECRET"`
|
|
SkipVerify bool `envconfig:"DRONE_BITBUCKET_SKIP_VERIFY"`
|
|
Debug bool `envconfig:"DRONE_BITBUCKET_DEBUG"`
|
|
}
|
|
|
|
// Gitea provides the gitea client configuration.
|
|
Gitea struct {
|
|
Server string `envconfig:"DRONE_GITEA_SERVER"`
|
|
SkipVerify bool `envconfig:"DRONE_GITEA_SKIP_VERIFY"`
|
|
Debug bool `envconfig:"DRONE_GITEA_DEBUG"`
|
|
}
|
|
|
|
// Github provides the github client configuration.
|
|
Github struct {
|
|
Server string `envconfig:"DRONE_GITHUB_SERVER" default:"https://github.com"`
|
|
APIServer string `envconfig:"DRONE_GITHUB_API_SERVER"`
|
|
ClientID string `envconfig:"DRONE_GITHUB_CLIENT_ID"`
|
|
ClientSecret string `envconfig:"DRONE_GITHUB_CLIENT_SECRET"`
|
|
SkipVerify bool `envconfig:"DRONE_GITHUB_SKIP_VERIFY"`
|
|
Scope []string `envconfig:"DRONE_GITHUB_SCOPE" default:"repo,repo:status,user:email,read:org"`
|
|
RateLimit int `envconfig:"DRONE_GITHUB_USER_RATELIMIT"`
|
|
Debug bool `envconfig:"DRONE_GITHUB_DEBUG"`
|
|
}
|
|
|
|
// GitLab provides the gitlab client configuration.
|
|
GitLab struct {
|
|
Server string `envconfig:"DRONE_GITLAB_SERVER" default:"https://gitlab.com"`
|
|
ClientID string `envconfig:"DRONE_GITLAB_CLIENT_ID"`
|
|
ClientSecret string `envconfig:"DRONE_GITLAB_CLIENT_SECRET"`
|
|
SkipVerify bool `envconfig:"DRONE_GITLAB_SKIP_VERIFY"`
|
|
Debug bool `envconfig:"DRONE_GITLAB_DEBUG"`
|
|
}
|
|
|
|
// Gogs provides the gogs client configuration.
|
|
Gogs struct {
|
|
Server string `envconfig:"DRONE_GOGS_SERVER"`
|
|
SkipVerify bool `envconfig:"DRONE_GOGS_SKIP_VERIFY"`
|
|
Debug bool `envconfig:"DRONE_GOGS_DEBUG"`
|
|
}
|
|
|
|
// Stash provides the stash client configuration.
|
|
Stash struct {
|
|
Server string `envconfig:"DRONE_STASH_SERVER"`
|
|
ConsumerKey string `envconfig:"DRONE_STASH_CONSUMER_KEY"`
|
|
ConsumerSecret string `envconfig:"DRONE_STASH_CONSUMER_SECRET"`
|
|
PrivateKey string `envconfig:"DRONE_STASH_PRIVATE_KEY"`
|
|
SkipVerify bool `envconfig:"DRONE_STASH_SKIP_VERIFY"`
|
|
Debug bool `envconfig:"DRONE_STASH_DEBUG"`
|
|
}
|
|
|
|
// S3 provides the storage configuration.
|
|
S3 struct {
|
|
Bucket string `envconfig:"DRONE_S3_BUCKET"`
|
|
Prefix string `envconfig:"DRONE_S3_PREFIX"`
|
|
}
|
|
|
|
// HTTP provides http configuration.
|
|
HTTP struct {
|
|
AllowedHosts []string `envconfig:"DRONE_HTTP_ALLOWED_HOSTS"`
|
|
HostsProxyHeaders []string `envconfig:"DRONE_HTTP_PROXY_HEADERS"`
|
|
SSLRedirect bool `envconfig:"DRONE_HTTP_SSL_REDIRECT"`
|
|
SSLTemporaryRedirect bool `envconfig:"DRONE_HTTP_SSL_TEMPORARY_REDIRECT"`
|
|
SSLHost string `envconfig:"DRONE_HTTP_SSL_HOST"`
|
|
SSLProxyHeaders map[string]string `envconfig:"DRONE_HTTP_SSL_PROXY_HEADERS"`
|
|
STSSeconds int64 `envconfig:"DRONE_HTTP_STS_SECONDS"`
|
|
STSIncludeSubdomains bool `envconfig:"DRONE_HTTP_STS_INCLUDE_SUBDOMAINS"`
|
|
STSPreload bool `envconfig:"DRONE_HTTP_STS_PRELOAD"`
|
|
ForceSTSHeader bool `envconfig:"DRONE_HTTP_STS_FORCE_HEADER"`
|
|
BrowserXSSFilter bool `envconfig:"DRONE_HTTP_BROWSER_XSS_FILTER" default:"true"`
|
|
FrameDeny bool `envconfig:"DRONE_HTTP_FRAME_DENY" default:"true"`
|
|
ContentTypeNosniff bool `envconfig:"DRONE_HTTP_CONTENT_TYPE_NO_SNIFF"`
|
|
ContentSecurityPolicy string `envconfig:"DRONE_HTTP_CONTENT_SECURITY_POLICY"`
|
|
ReferrerPolicy string `envconfig:"DRONE_HTTP_REFERRER_POLICY"`
|
|
}
|
|
)
|
|
|
|
// Environ returns the settings from the environment.
|
|
func Environ() (Config, error) {
|
|
cfg := Config{}
|
|
err := envconfig.Process("", &cfg)
|
|
defaultAddress(&cfg)
|
|
defaultProxy(&cfg)
|
|
defaultRunner(&cfg)
|
|
defaultSession(&cfg)
|
|
defaultCallback(&cfg)
|
|
configureGithub(&cfg)
|
|
return cfg, err
|
|
}
|
|
|
|
// String returns the configuration in string format.
|
|
func (c *Config) String() string {
|
|
out, _ := yaml.Marshal(c)
|
|
return string(out)
|
|
}
|
|
|
|
func defaultAddress(c *Config) {
|
|
if c.Server.Key != "" || c.Server.Cert != "" || c.Server.Acme {
|
|
c.Server.Port = ":443"
|
|
c.Server.Proto = "https"
|
|
}
|
|
c.Server.Addr = c.Server.Proto + "://" + c.Server.Host
|
|
}
|
|
|
|
func defaultProxy(c *Config) {
|
|
if c.Proxy.Host == "" {
|
|
c.Proxy.Host = c.Server.Host
|
|
}
|
|
if c.Proxy.Proto == "" {
|
|
c.Proxy.Proto = c.Server.Proto
|
|
}
|
|
c.Proxy.Addr = c.Proxy.Proto + "://" + c.Proxy.Host
|
|
}
|
|
|
|
func defaultCallback(c *Config) {
|
|
if c.RPC.Host == "" {
|
|
c.RPC.Host = c.Server.Host
|
|
}
|
|
if c.RPC.Proto == "" {
|
|
c.RPC.Proto = c.Server.Proto
|
|
}
|
|
}
|
|
|
|
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 defaultSession(c *Config) {
|
|
if c.Session.Secret == "" {
|
|
c.Session.Secret = uniuri.NewLen(32)
|
|
}
|
|
}
|
|
|
|
func configureGithub(c *Config) {
|
|
if c.Github.APIServer != "" {
|
|
return
|
|
}
|
|
if c.Github.Server == "https://github.com" {
|
|
c.Github.APIServer = "https://api.github.com"
|
|
} else {
|
|
c.Github.APIServer = strings.TrimSuffix(c.Github.Server, "/") + "/api/v3"
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|