github.com/ssube/gitlab-ci-multi-runner@v1.2.1-0.20160607142738-b8d1285632e6/common/config.go (about) 1 package common 2 3 import ( 4 "bufio" 5 "bytes" 6 "io/ioutil" 7 "os" 8 "time" 9 10 "fmt" 11 "github.com/BurntSushi/toml" 12 log "github.com/Sirupsen/logrus" 13 "gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers" 14 "gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers/docker" 15 "gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers/ssh" 16 "path/filepath" 17 ) 18 19 type DockerPullPolicy string 20 21 const ( 22 DockerPullPolicyAlways DockerPullPolicy = "always" 23 DockerPullPolicyNever = "never" 24 DockerPullPolicyIfNotPresent = "if-not-present" 25 ) 26 27 // Get returns one of the predefined values or returns an error if the value can't match the predefined 28 func (p DockerPullPolicy) Get() (DockerPullPolicy, error) { 29 // Default policy is always 30 if p == "" { 31 return DockerPullPolicyAlways, nil 32 } 33 34 // Verify pull policy 35 if p != DockerPullPolicyNever && 36 p != DockerPullPolicyIfNotPresent && 37 p != DockerPullPolicyAlways { 38 return "", fmt.Errorf("unsupported docker-pull-policy: %v", p) 39 } 40 return p, nil 41 } 42 43 type DockerConfig struct { 44 docker_helpers.DockerCredentials 45 Hostname string `toml:"hostname,omitempty" json:"hostname" long:"hostname" env:"DOCKER_HOSTNAME" description:"Custom container hostname"` 46 Image string `toml:"image" json:"image" long:"image" env:"DOCKER_IMAGE" description:"Docker image to be used"` 47 CPUSetCPUs string `toml:"cpuset_cpus,omitempty" json:"cpuset_cpus" long:"cpuset-cpus" env:"DOCKER_CPUSET_CPUS" description:"String value containing the cgroups CpusetCpus to use"` 48 DNS []string `toml:"dns,omitempty" json:"dns" long:"dns" env:"DOCKER_DNS" description:"A list of DNS servers for the container to use"` 49 DNSSearch []string `toml:"dns_search,omitempty" json:"dns_search" long:"dns-search" env:"DOCKER_DNS_SEARCH" description:"A list of DNS search domains"` 50 Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"DOCKER_PRIVILEGED" description:"Give extended privileges to container"` 51 CapAdd []string `toml:"cap_add" json:"cap_add" long:"cap-add" env:"DOCKER_CAP_ADD" description:"Add Linux capabilities"` 52 CapDrop []string `toml:"cap_drop" json:"cap_drop" long:"cap-drop" env:"DOCKER_CAP_DROP" description:"Drop Linux capabilities"` 53 Devices []string `toml:"devices" json:"devices" long:"devices" env:"DOCKER_DEVICES" description:"Add a host device to the container"` 54 DisableCache bool `toml:"disable_cache,omitzero" json:"disable_cache" long:"disable-cache" env:"DOCKER_DISABLE_CACHE" description:"Disable all container caching"` 55 Volumes []string `toml:"volumes,omitempty" json:"volumes" long:"volumes" env:"DOCKER_VOLUMES" description:"Bind mount a volumes"` 56 CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"DOCKER_CACHE_DIR" description:"Directory where to store caches"` 57 ExtraHosts []string `toml:"extra_hosts,omitempty" json:"extra_hosts" long:"extra-hosts" env:"DOCKER_EXTRA_HOSTS" description:"Add a custom host-to-IP mapping"` 58 NetworkMode string `toml:"network_mode,omitempty" json:"network_mode" long:"network-mode" env:"DOCKER_NETWORK_MODE" description:"Add container to a custom network"` 59 Links []string `toml:"links,omitempty" json:"links" long:"links" env:"DOCKER_LINKS" description:"Add link to another container"` 60 Services []string `toml:"services,omitempty" json:"services" long:"services" env:"DOCKER_SERVICES" description:"Add service that is started with container"` 61 WaitForServicesTimeout int `toml:"wait_for_services_timeout,omitzero" json:"wait_for_services_timeout" long:"wait-for-services-timeout" env:"DOCKER_WAIT_FOR_SERVICES_TIMEOUT" description:"How long to wait for service startup"` 62 AllowedImages []string `toml:"allowed_images,omitempty" json:"allowed_images" long:"allowed-images" env:"DOCKER_ALLOWED_IMAGES" description:"Whitelist allowed images"` 63 AllowedServices []string `toml:"allowed_services,omitempty" json:"allowed_services" long:"allowed-services" env:"DOCKER_ALLOWED_SERVICES" description:"Whitelist allowed services"` 64 PullPolicy DockerPullPolicy `toml:"pull_policy,omitempty" json:"pull_policy" long:"pull-policy" env:"DOCKER_PULL_POLICY" description:"Image pull policy: never, if-not-present, always"` 65 } 66 67 type DockerMachine struct { 68 IdleCount int `long:"idle-nodes" env:"MACHINE_IDLE_COUNT" description:"Maximum idle machines"` 69 IdleTime int `toml:"IdleTime,omitzero" long:"idle-time" env:"MACHINE_IDLE_TIME" description:"Minimum time after node can be destroyed"` 70 MaxBuilds int `toml:"MaxBuilds,omitzero" long:"max-builds" env:"MACHINE_MAX_BUILDS" description:"Maximum number of builds processed by machine"` 71 MachineDriver string `long:"machine-driver" env:"MACHINE_DRIVER" description:"The driver to use when creating machine"` 72 MachineName string `long:"machine-name" env:"MACHINE_NAME" description:"The template for machine name (needs to include %s)"` 73 MachineOptions []string `long:"machine-options" env:"MACHINE_OPTIONS" description:"Additional machine creation options"` 74 } 75 76 type ParallelsConfig struct { 77 BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"PARALLELS_BASE_NAME" description:"VM name to be used"` 78 TemplateName string `toml:"template_name,omitempty" json:"template_name" long:"template-name" env:"PARALLELS_TEMPLATE_NAME" description:"VM template to be created"` 79 DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"PARALLELS_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"` 80 } 81 82 type VirtualBoxConfig struct { 83 BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"VIRTUALBOX_BASE_NAME" description:"VM name to be used"` 84 DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"VIRTUALBOX_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"` 85 } 86 87 type RunnerCredentials struct { 88 URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"` 89 Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"` 90 TLSCAFile string `toml:"tls-ca-file,omitempty" json:"tls-ca-file" long:"tls-ca-file" env:"CI_SERVER_TLS_CA_FILE" description:"File containing the certificates to verify the peer when using HTTPS"` 91 } 92 93 type CacheConfig struct { 94 Type string `toml:"Type,omitempty" long:"type" env:"CACHE_TYPE" description:"Select caching method: s3, to use S3 buckets"` 95 ServerAddress string `toml:"ServerAddress,omitempty" long:"s3-server-address" env:"S3_SERVER_ADDRESS" description:"S3 Server Address"` 96 AccessKey string `toml:"AccessKey,omitempty" long:"s3-access-key" env:"S3_ACCESS_KEY" description:"S3 Access Key"` 97 SecretKey string `toml:"SecretKey,omitempty" long:"s3-secret-key" env:"S3_SECRET_KEY" description:"S3 Secret Key"` 98 BucketName string `toml:"BucketName,omitempty" long:"s3-bucket-name" env:"S3_BUCKET_NAME" description:"S3 bucket name"` 99 BucketLocation string `toml:"BucketLocation,omitempty" long:"s3-bucket-location" env:"S3_BUCKET_LOCATION" description:"S3 location"` 100 Insecure bool `toml:"Insecure,omitempty" long:"s3-insecure" env:"S3_CACHE_INSECURE" description:"Use insecure mode (without https)"` 101 } 102 103 type RunnerSettings struct { 104 Executor string `toml:"executor" json:"executor" long:"executor" env:"RUNNER_EXECUTOR" required:"true" description:"Select executor, eg. shell, docker, etc."` 105 BuildsDir string `toml:"builds_dir,omitempty" json:"builds_dir" long:"builds-dir" env:"RUNNER_BUILDS_DIR" description:"Directory where builds are stored"` 106 CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"RUNNER_CACHE_DIR" description:"Directory where build cache is stored"` 107 108 Environment []string `toml:"environment,omitempty" json:"environment" long:"env" env:"RUNNER_ENV" description:"Custom environment variables injected to build environment"` 109 110 Shell string `toml:"shell,omitempty" json:"shell" long:"shell" env:"RUNNER_SHELL" description:"Select bash, cmd or powershell"` 111 112 SSH *ssh.Config `toml:"ssh" json:"ssh" group:"ssh executor" namespace:"ssh"` 113 Docker *DockerConfig `toml:"docker" json:"docker" group:"docker executor" namespace:"docker"` 114 Parallels *ParallelsConfig `toml:"parallels" json:"parallels" group:"parallels executor" namespace:"parallels"` 115 VirtualBox *VirtualBoxConfig `toml:"virtualbox" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"` 116 Cache *CacheConfig `toml:"cache" json:"cache" group:"cache configuration" namespace:"cache"` 117 Machine *DockerMachine `toml:"machine" json:"machine" group:"docker machine provider" namespace:"machine"` 118 } 119 120 type RunnerConfig struct { 121 Name string `toml:"name" json:"name" short:"name" long:"description" env:"RUNNER_NAME" description:"Runner name"` 122 Limit int `toml:"limit,omitzero" json:"limit" long:"limit" env:"RUNNER_LIMIT" description:"Maximum number of builds processed by this runner"` 123 OutputLimit int `toml:"output_limit,omitzero" long:"output-limit" env:"RUNNER_OUTPUT_LIMIT" description:"Maximum build trace size"` 124 125 RunnerCredentials 126 RunnerSettings 127 } 128 129 type Config struct { 130 Concurrent int `toml:"concurrent" json:"concurrent"` 131 User string `toml:"user,omitempty" json:"user"` 132 Runners []*RunnerConfig `toml:"runners" json:"runners"` 133 ModTime time.Time `toml:"-"` 134 Loaded bool `toml:"-"` 135 } 136 137 func (c *RunnerCredentials) ShortDescription() string { 138 return helpers.ShortenToken(c.Token) 139 } 140 141 func (c *RunnerCredentials) UniqueID() string { 142 return c.URL + c.Token 143 } 144 145 func (c *RunnerCredentials) Log() *log.Entry { 146 if c.ShortDescription() != "" { 147 return log.WithField("runner", c.ShortDescription()) 148 } 149 return log.WithFields(log.Fields{}) 150 } 151 152 func (c *RunnerConfig) String() string { 153 return fmt.Sprintf("%v url=%v token=%v executor=%v", c.Name, c.URL, c.Token, c.Executor) 154 } 155 156 func (c *RunnerConfig) GetVariables() BuildVariables { 157 var variables BuildVariables 158 159 for _, environment := range c.Environment { 160 if variable, err := ParseVariable(environment); err == nil { 161 variable.Internal = true 162 variables = append(variables, variable) 163 } 164 } 165 166 return variables 167 } 168 169 func NewConfig() *Config { 170 return &Config{ 171 Concurrent: 1, 172 } 173 } 174 175 func (c *Config) StatConfig(configFile string) error { 176 _, err := os.Stat(configFile) 177 if err != nil { 178 return err 179 } 180 return nil 181 } 182 183 func (c *Config) LoadConfig(configFile string) error { 184 info, err := os.Stat(configFile) 185 186 // permission denied is soft error 187 if os.IsNotExist(err) { 188 return nil 189 } else if err != nil { 190 return err 191 } 192 193 if _, err = toml.DecodeFile(configFile, c); err != nil { 194 return err 195 } 196 197 c.ModTime = info.ModTime() 198 c.Loaded = true 199 return nil 200 } 201 202 func (c *Config) SaveConfig(configFile string) error { 203 var newConfig bytes.Buffer 204 newBuffer := bufio.NewWriter(&newConfig) 205 206 if err := toml.NewEncoder(newBuffer).Encode(c); err != nil { 207 log.Fatalf("Error encoding TOML: %s", err) 208 return err 209 } 210 211 if err := newBuffer.Flush(); err != nil { 212 return err 213 } 214 215 // create directory to store configuration 216 os.MkdirAll(filepath.Dir(configFile), 0700) 217 218 // write config file 219 if err := ioutil.WriteFile(configFile, newConfig.Bytes(), 0600); err != nil { 220 return err 221 } 222 223 c.Loaded = true 224 return nil 225 }