PageRenderTime 99ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/common/config.go

https://gitlab.com/larsla/gitlab-ci-multi-runner
Go | 383 lines | 313 code | 63 blank | 7 comment | 49 complexity | 1d6fec23208f7457f740a04572c73283 MD5 | raw file
  1. package common
  2. import (
  3. "bufio"
  4. "bytes"
  5. "errors"
  6. "io/ioutil"
  7. "os"
  8. "time"
  9. "fmt"
  10. "path/filepath"
  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. "gitlab.com/gitlab-org/gitlab-ci-multi-runner/helpers/timeperiod"
  17. )
  18. type DockerPullPolicy string
  19. const (
  20. PullPolicyAlways = "always"
  21. PullPolicyNever = "never"
  22. PullPolicyIfNotPresent = "if-not-present"
  23. defaultHelperImage = "gitlab/gitlab-runner-helper"
  24. )
  25. // Get returns one of the predefined values or returns an error if the value can't match the predefined
  26. func (p DockerPullPolicy) Get() (DockerPullPolicy, error) {
  27. // Default policy is always
  28. if p == "" {
  29. return PullPolicyAlways, nil
  30. }
  31. // Verify pull policy
  32. if p != PullPolicyNever &&
  33. p != PullPolicyIfNotPresent &&
  34. p != PullPolicyAlways {
  35. return "", fmt.Errorf("unsupported docker-pull-policy: %v", p)
  36. }
  37. return p, nil
  38. }
  39. type DockerConfig struct {
  40. docker_helpers.DockerCredentials
  41. Hostname string `toml:"hostname,omitempty" json:"hostname" long:"hostname" env:"DOCKER_HOSTNAME" description:"Custom container hostname"`
  42. Image string `toml:"image" json:"image" long:"image" env:"DOCKER_IMAGE" description:"Docker image to be used"`
  43. 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"`
  44. DNS []string `toml:"dns,omitempty" json:"dns" long:"dns" env:"DOCKER_DNS" description:"A list of DNS servers for the container to use"`
  45. DNSSearch []string `toml:"dns_search,omitempty" json:"dns_search" long:"dns-search" env:"DOCKER_DNS_SEARCH" description:"A list of DNS search domains"`
  46. Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"DOCKER_PRIVILEGED" description:"Give extended privileges to container"`
  47. CapAdd []string `toml:"cap_add" json:"cap_add" long:"cap-add" env:"DOCKER_CAP_ADD" description:"Add Linux capabilities"`
  48. CapDrop []string `toml:"cap_drop" json:"cap_drop" long:"cap-drop" env:"DOCKER_CAP_DROP" description:"Drop Linux capabilities"`
  49. SecurityOpt []string `toml:"security_opt" json:"security_opt" long:"security-opt" env:"DOCKER_SECURITY_OPT" description:"Security Options"`
  50. Devices []string `toml:"devices" json:"devices" long:"devices" env:"DOCKER_DEVICES" description:"Add a host device to the container"`
  51. DisableCache bool `toml:"disable_cache,omitzero" json:"disable_cache" long:"disable-cache" env:"DOCKER_DISABLE_CACHE" description:"Disable all container caching"`
  52. Volumes []string `toml:"volumes,omitempty" json:"volumes" long:"volumes" env:"DOCKER_VOLUMES" description:"Bind mount a volumes"`
  53. VolumeDriver string `toml:"volume_driver,omitempty" json:"volume_driver" long:"volume-driver" env:"DOCKER_VOLUME_DRIVER" description:"Volume driver to be used"`
  54. CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"DOCKER_CACHE_DIR" description:"Directory where to store caches"`
  55. ExtraHosts []string `toml:"extra_hosts,omitempty" json:"extra_hosts" long:"extra-hosts" env:"DOCKER_EXTRA_HOSTS" description:"Add a custom host-to-IP mapping"`
  56. VolumesFrom []string `toml:"volumes_from,omitempty" json:"volumes_from" long:"volumes-from" env:"DOCKER_VOLUMES_FROM" description:"A list of volumes to inherit from another container"`
  57. NetworkMode string `toml:"network_mode,omitempty" json:"network_mode" long:"network-mode" env:"DOCKER_NETWORK_MODE" description:"Add container to a custom network"`
  58. Links []string `toml:"links,omitempty" json:"links" long:"links" env:"DOCKER_LINKS" description:"Add link to another container"`
  59. Services []string `toml:"services,omitempty" json:"services" long:"services" env:"DOCKER_SERVICES" description:"Add service that is started with container"`
  60. 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"`
  61. AllowedImages []string `toml:"allowed_images,omitempty" json:"allowed_images" long:"allowed-images" env:"DOCKER_ALLOWED_IMAGES" description:"Whitelist allowed images"`
  62. AllowedServices []string `toml:"allowed_services,omitempty" json:"allowed_services" long:"allowed-services" env:"DOCKER_ALLOWED_SERVICES" description:"Whitelist allowed services"`
  63. 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"`
  64. }
  65. type DockerMachine struct {
  66. IdleCount int `long:"idle-nodes" env:"MACHINE_IDLE_COUNT" description:"Maximum idle machines"`
  67. IdleTime int `toml:"IdleTime,omitzero" long:"idle-time" env:"MACHINE_IDLE_TIME" description:"Minimum time after node can be destroyed"`
  68. MaxBuilds int `toml:"MaxBuilds,omitzero" long:"max-builds" env:"MACHINE_MAX_BUILDS" description:"Maximum number of builds processed by machine"`
  69. MachineDriver string `long:"machine-driver" env:"MACHINE_DRIVER" description:"The driver to use when creating machine"`
  70. MachineName string `long:"machine-name" env:"MACHINE_NAME" description:"The template for machine name (needs to include %s)"`
  71. MachineOptions []string `long:"machine-options" env:"MACHINE_OPTIONS" description:"Additional machine creation options"`
  72. OffPeakPeriods []string `long:"off-peak-periods" env:"MACHINE_OFF_PEAK_PERIODS" description:"Time periods when the scheduler is in the OffPeak mode"`
  73. OffPeakTimezone string `long:"off-peak-timezone" env:"MACHINE_OFF_PEAK_TIMEZONE" description:"Timezone for the OffPeak periods (defaults to Local)"`
  74. OffPeakIdleCount int `long:"off-peak-idle-count" env:"MACHINE_OFF_PEAK_IDLE_COUNT" description:"Maximum idle machines when the scheduler is in the OffPeak mode"`
  75. OffPeakIdleTime int `long:"off-peak-idle-time" env:"MACHINE_OFF_PEAK_IDLE_TIME" description:"Minimum time after machine can be destroyed when the scheduler is in the OffPeak mode"`
  76. offPeakTimePeriods *timeperiod.TimePeriod
  77. }
  78. type ParallelsConfig struct {
  79. BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"PARALLELS_BASE_NAME" description:"VM name to be used"`
  80. TemplateName string `toml:"template_name,omitempty" json:"template_name" long:"template-name" env:"PARALLELS_TEMPLATE_NAME" description:"VM template to be created"`
  81. DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"PARALLELS_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"`
  82. }
  83. type VirtualBoxConfig struct {
  84. BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"VIRTUALBOX_BASE_NAME" description:"VM name to be used"`
  85. BaseSnapshot string `toml:"base_snapshot,omitempty" json:"base_snapshot" long:"base-snapshot" env:"VIRTUALBOX_BASE_SNAPSHOT" description:"Name or UUID of a specific VM snapshot to clone"`
  86. DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"VIRTUALBOX_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"`
  87. }
  88. type KubernetesPullPolicy string
  89. // Get returns one of the predefined values in kubernetes notation or returns an error if the value can't match the predefined
  90. func (p KubernetesPullPolicy) Get() (KubernetesPullPolicy, error) {
  91. switch {
  92. case p == "":
  93. return "", nil
  94. case p == PullPolicyAlways:
  95. return "Always", nil
  96. case p == PullPolicyNever:
  97. return "Never", nil
  98. case p == PullPolicyIfNotPresent:
  99. return "IfNotPresent", nil
  100. }
  101. return "", fmt.Errorf("unsupported kubernetes-pull-policy: %v", p)
  102. }
  103. type KubernetesConfig struct {
  104. Host string `toml:"host" json:"host" long:"host" env:"KUBERNETES_HOST" description:"Optional Kubernetes master host URL (auto-discovery attempted if not specified)"`
  105. CertFile string `toml:"cert_file,omitempty" json:"cert_file" long:"cert-file" env:"KUBERNETES_CERT_FILE" description:"Optional Kubernetes master auth certificate"`
  106. KeyFile string `toml:"key_file,omitempty" json:"key_file" long:"key-file" env:"KUBERNETES_KEY_FILE" description:"Optional Kubernetes master auth private key"`
  107. CAFile string `toml:"ca_file,omitempty" json:"ca_file" long:"ca-file" env:"KUBERNETES_CA_FILE" description:"Optional Kubernetes master auth ca certificate"`
  108. Image string `toml:"image" json:"image" long:"image" env:"KUBERNETES_IMAGE" description:"Default docker image to use for builds when none is specified"`
  109. Namespace string `toml:"namespace" json:"namespace" long:"namespace" env:"KUBERNETES_NAMESPACE" description:"Namespace to run Kubernetes jobs in"`
  110. NamespaceOverwriteAllowed string `toml:"namespace_overwrite_allowed" json:"namespace_overwrite_allowed" long:"namespace_overwrite_allowed" env:"KUBERNETES_NAMESPACE_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_NAMESPACE_OVERWRITE' value"`
  111. Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"KUBERNETES_PRIVILEGED" description:"Run all containers with the privileged flag enabled"`
  112. CPUs string `toml:"cpus,omitempty" json:"cpus" long:"cpus" env:"KUBERNETES_CPUS" description:"(deprecated) The CPU allocation given to build containers"`
  113. Memory string `toml:"memory,omitempty" json:"memory" long:"memory" env:"KUBERNETES_MEMORY" description:"(deprecated) The amount of memory allocated to build containers"`
  114. ServiceCPUs string `toml:"service_cpus,omitempty" json:"service_cpus" long:"service-cpus" env:"KUBERNETES_SERVICE_CPUS" description:"(deprecated) The CPU allocation given to build service containers"`
  115. ServiceMemory string `toml:"service_memory,omitempty" json:"service_memory" long:"service-memory" env:"KUBERNETES_SERVICE_MEMORY" description:"(deprecated) The amount of memory allocated to build service containers"`
  116. HelperCPUs string `toml:"helper_cpus,omitempty" json:"helper_cpus" long:"helper-cpus" env:"KUBERNETES_HELPER_CPUS" description:"(deprecated) The CPU allocation given to build helper containers"`
  117. HelperMemory string `toml:"helper_memory,omitempty" json:"helper_memory" long:"helper-memory" env:"KUBERNETES_HELPER_MEMORY" description:"(deprecated) The amount of memory allocated to build helper containers"`
  118. CPULimit string `toml:"cpu_limit,omitempty" json:"cpu_limit" long:"cpu-limit" env:"KUBERNETES_CPU_LIMIT" description:"The CPU allocation given to build containers"`
  119. MemoryLimit string `toml:"memory_limit,omitempty" json:"memory_limit" long:"memory-limit" env:"KUBERNETES_MEMORY_LIMIT" description:"The amount of memory allocated to build containers"`
  120. ServiceCPULimit string `toml:"service_cpu_limit,omitempty" json:"service_cpu_limit" long:"service-cpu-limit" env:"KUBERNETES_SERVICE_CPU_LIMIT" description:"The CPU allocation given to build service containers"`
  121. ServiceMemoryLimit string `toml:"service_memory_limit,omitempty" json:"service_memory_limit" long:"service-memory-limit" env:"KUBERNETES_SERVICE_MEMORY_LIMIT" description:"The amount of memory allocated to build service containers"`
  122. HelperCPULimit string `toml:"helper_cpu_limit,omitempty" json:"helper_cpu_limit" long:"helper-cpu-limit" env:"KUBERNETES_HELPER_CPU_LIMIT" description:"The CPU allocation given to build helper containers"`
  123. HelperMemoryLimit string `toml:"helper_memory_limit,omitempty" json:"helper_memory_limit" long:"helper-memory-limit" env:"KUBERNETES_HELPER_MEMORY_LIMIT" description:"The amount of memory allocated to build helper containers"`
  124. CPURequest string `toml:"cpu_request,omitempty" json:"cpu_request" long:"cpu-request" env:"KUBERNETES_CPU_REQUEST" description:"The CPU allocation requested for build containers"`
  125. MemoryRequest string `toml:"memory_request,omitempty" json:"memory_request" long:"memory-request" env:"KUBERNETES_MEMORY_REQUEST" description:"The amount of memory requested from build containers"`
  126. ServiceCPURequest string `toml:"service_cpu_request,omitempty" json:"service_cpu_request" long:"service-cpu-request" env:"KUBERNETES_SERVICE_CPU_REQUEST" description:"The CPU allocation requested for build service containers"`
  127. ServiceMemoryRequest string `toml:"service_memory_request,omitempty" json:"service_memory_request" long:"service-memory-request" env:"KUBERNETES_SERVICE_MEMORY_REQUEST" description:"The amount of memory requested for build service containers"`
  128. HelperCPURequest string `toml:"helper_cpu_request,omitempty" json:"helper_cpu_request" long:"helper-cpu-request" env:"KUBERNETES_HELPER_CPU_REQUEST" description:"The CPU allocation requested for build helper containers"`
  129. HelperMemoryRequest string `toml:"helper_memory_request,omitempty" json:"helper_memory_request" long:"helper-memory-request" env:"KUBERNETES_HELPER_MEMORY_REQUEST" description:"The amount of memory requested for build helper containers"`
  130. PullPolicy KubernetesPullPolicy `toml:"pull_policy,omitempty" json:"pull_policy" long:"pull-policy" env:"KUBERNETES_PULL_POLICY" description:"Policy for if/when to pull a container image (never, if-not-present, always). The cluster default will be used if not set"`
  131. NodeSelector map[string]string `toml:"node_selector,omitempty" json:"node_selector" long:"node-selector" description:"A toml table/json object of key=value. Value is expected to be a string. When set this will create pods on k8s nodes that match all the key=value pairs."`
  132. ImagePullSecrets []string `toml:"image_pull_secrets,omitempty" json:"image_pull_secrets" long:"image-pull-secrets" env:"KUBERNETES_IMAGE_PULL_SECRETS" description:"A list of image pull secrets that are used for pulling docker image"`
  133. HelperImage string `toml:"helper_image,omitempty" json:"helper_image" long:"helper-image" env:"KUBERNETES_HELPER_IMAGE" description:"[ADVANCED] Override the default helper image used to clone repos and upload artifacts"`
  134. TerminationGracePeriodSeconds int64 `toml:"terminationGracePeriodSeconds,omitzero" json:"terminationGracePeriodSeconds" long:"terminationGracePeriodSeconds" env:"KUBERNETES_TERMINATIONGRACEPERIODSECONDS" description:"Duration after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal."`
  135. PollInterval int `toml:"poll_interval,omitzero" json:"poll_interval" long:"poll-interval" env:"KUBERNETES_POLL_INTERVAL" description:"How frequently, in seconds, the runner will poll the Kubernetes pod it has just created to check its status"`
  136. PollTimeout int `toml:"poll_timeout,omitzero" json:"poll_timeout" long:"poll-timeout" env:"KUBERNETES_POLL_TIMEOUT" description:"The total amount of time, in seconds, that needs to pass before the runner will timeout attempting to connect to the pod it has just created (useful for queueing more builds that the cluster can handle at a time)"`
  137. }
  138. type RunnerCredentials struct {
  139. URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"`
  140. Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"`
  141. 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"`
  142. }
  143. type CacheConfig struct {
  144. Type string `toml:"Type,omitempty" long:"type" env:"CACHE_TYPE" description:"Select caching method: s3, to use S3 buckets"`
  145. ServerAddress string `toml:"ServerAddress,omitempty" long:"s3-server-address" env:"S3_SERVER_ADDRESS" description:"A host:port to the used S3-compatible server"`
  146. AccessKey string `toml:"AccessKey,omitempty" long:"s3-access-key" env:"S3_ACCESS_KEY" description:"S3 Access Key"`
  147. SecretKey string `toml:"SecretKey,omitempty" long:"s3-secret-key" env:"S3_SECRET_KEY" description:"S3 Secret Key"`
  148. BucketName string `toml:"BucketName,omitempty" long:"s3-bucket-name" env:"S3_BUCKET_NAME" description:"Name of the bucket where cache will be stored"`
  149. BucketLocation string `toml:"BucketLocation,omitempty" long:"s3-bucket-location" env:"S3_BUCKET_LOCATION" description:"Name of S3 region"`
  150. Insecure bool `toml:"Insecure,omitempty" long:"s3-insecure" env:"S3_CACHE_INSECURE" description:"Use insecure mode (without https)"`
  151. Path string `toml:"Path,omitempty" long:"s3-cache-path" env:"S3_CACHE_PATH" description:"Name of the path to prepend to the cache URL"`
  152. Shared bool `toml:"Shared,omitempty" long:"cache-shared" env:"CACHE_SHARED" description:"Enable cache sharing between runners."`
  153. }
  154. type RunnerSettings struct {
  155. Executor string `toml:"executor" json:"executor" long:"executor" env:"RUNNER_EXECUTOR" required:"true" description:"Select executor, eg. shell, docker, etc."`
  156. BuildsDir string `toml:"builds_dir,omitempty" json:"builds_dir" long:"builds-dir" env:"RUNNER_BUILDS_DIR" description:"Directory where builds are stored"`
  157. CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"RUNNER_CACHE_DIR" description:"Directory where build cache is stored"`
  158. Environment []string `toml:"environment,omitempty" json:"environment" long:"env" env:"RUNNER_ENV" description:"Custom environment variables injected to build environment"`
  159. PreCloneScript string `toml:"pre_clone_script,omitempty" json:"pre_clone_script" long:"pre-clone-script" env:"RUNNER_PRE_CLONE_SCRIPT" description:"Runner-specific command script executed before code is pulled"`
  160. PreBuildScript string `toml:"pre_build_script,omitempty" json:"pre_build_script" long:"pre-build-script" env:"RUNNER_PRE_BUILD_SCRIPT" description:"Runner-specific command script executed after code is pulled, just before build executes"`
  161. PostBuildScript string `toml:"post_build_script,omitempty" json:"post_build_script" long:"post-build-script" env:"RUNNER_POST_BUILD_SCRIPT" description:"Runner-specific command script executed after code is pulled and just after build executes"`
  162. Shell string `toml:"shell,omitempty" json:"shell" long:"shell" env:"RUNNER_SHELL" description:"Select bash, cmd or powershell"`
  163. SSH *ssh.Config `toml:"ssh,omitempty" json:"ssh" group:"ssh executor" namespace:"ssh"`
  164. Docker *DockerConfig `toml:"docker,omitempty" json:"docker" group:"docker executor" namespace:"docker"`
  165. Parallels *ParallelsConfig `toml:"parallels,omitempty" json:"parallels" group:"parallels executor" namespace:"parallels"`
  166. VirtualBox *VirtualBoxConfig `toml:"virtualbox,omitempty" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"`
  167. Cache *CacheConfig `toml:"cache,omitempty" json:"cache" group:"cache configuration" namespace:"cache"`
  168. Machine *DockerMachine `toml:"machine,omitempty" json:"machine" group:"docker machine provider" namespace:"machine"`
  169. Kubernetes *KubernetesConfig `toml:"kubernetes,omitempty" json:"kubernetes" group:"kubernetes executor" namespace:"kubernetes"`
  170. }
  171. type RunnerConfig struct {
  172. Name string `toml:"name" json:"name" short:"name" long:"description" env:"RUNNER_NAME" description:"Runner name"`
  173. Limit int `toml:"limit,omitzero" json:"limit" long:"limit" env:"RUNNER_LIMIT" description:"Maximum number of builds processed by this runner"`
  174. OutputLimit int `toml:"output_limit,omitzero" long:"output-limit" env:"RUNNER_OUTPUT_LIMIT" description:"Maximum build trace size in kilobytes"`
  175. RunnerCredentials
  176. RunnerSettings
  177. }
  178. type Config struct {
  179. MetricsServerAddress string `toml:"metrics_server,omitempty" json:"metrics_server"`
  180. Concurrent int `toml:"concurrent" json:"concurrent"`
  181. CheckInterval int `toml:"check_interval" json:"check_interval" description:"Define active checking interval of jobs"`
  182. User string `toml:"user,omitempty" json:"user"`
  183. Runners []*RunnerConfig `toml:"runners" json:"runners"`
  184. SentryDSN *string `toml:"sentry_dsn"`
  185. ModTime time.Time `toml:"-"`
  186. Loaded bool `toml:"-"`
  187. }
  188. func (c *KubernetesConfig) GetHelperImage() string {
  189. if len(c.HelperImage) > 0 {
  190. return c.HelperImage
  191. }
  192. rev := REVISION
  193. if rev == "HEAD" {
  194. rev = "latest"
  195. }
  196. return fmt.Sprintf("%s:x86_64-%s", defaultHelperImage, rev)
  197. }
  198. func (c *KubernetesConfig) GetPollAttempts() int {
  199. if c.PollTimeout <= 0 {
  200. c.PollTimeout = KubernetesPollTimeout
  201. }
  202. return c.PollTimeout / c.GetPollInterval()
  203. }
  204. func (c *KubernetesConfig) GetPollInterval() int {
  205. if c.PollInterval <= 0 {
  206. c.PollInterval = KubernetesPollInterval
  207. }
  208. return c.PollInterval
  209. }
  210. func (c *DockerMachine) GetIdleCount() int {
  211. if c.isOffPeak() {
  212. return c.OffPeakIdleCount
  213. }
  214. return c.IdleCount
  215. }
  216. func (c *DockerMachine) GetIdleTime() int {
  217. if c.isOffPeak() {
  218. return c.OffPeakIdleTime
  219. }
  220. return c.IdleTime
  221. }
  222. func (c *DockerMachine) isOffPeak() bool {
  223. if c.offPeakTimePeriods == nil {
  224. c.CompileOffPeakPeriods()
  225. }
  226. return c.offPeakTimePeriods != nil && c.offPeakTimePeriods.InPeriod()
  227. }
  228. func (c *DockerMachine) CompileOffPeakPeriods() (err error) {
  229. c.offPeakTimePeriods, err = timeperiod.TimePeriods(c.OffPeakPeriods, c.OffPeakTimezone)
  230. if err != nil {
  231. err = errors.New(fmt.Sprint("Invalid OffPeakPeriods value: ", err))
  232. }
  233. return
  234. }
  235. func (c *RunnerCredentials) ShortDescription() string {
  236. return helpers.ShortenToken(c.Token)
  237. }
  238. func (c *RunnerCredentials) UniqueID() string {
  239. return c.URL + c.Token
  240. }
  241. func (c *RunnerCredentials) Log() *log.Entry {
  242. if c.ShortDescription() != "" {
  243. return log.WithField("runner", c.ShortDescription())
  244. }
  245. return log.WithFields(log.Fields{})
  246. }
  247. func (c *RunnerConfig) String() string {
  248. return fmt.Sprintf("%v url=%v token=%v executor=%v", c.Name, c.URL, c.Token, c.Executor)
  249. }
  250. func (c *RunnerConfig) GetVariables() BuildVariables {
  251. var variables BuildVariables
  252. for _, environment := range c.Environment {
  253. if variable, err := ParseVariable(environment); err == nil {
  254. variable.Internal = true
  255. variables = append(variables, variable)
  256. }
  257. }
  258. return variables
  259. }
  260. func NewConfig() *Config {
  261. return &Config{
  262. Concurrent: 1,
  263. }
  264. }
  265. func (c *Config) StatConfig(configFile string) error {
  266. _, err := os.Stat(configFile)
  267. if err != nil {
  268. return err
  269. }
  270. return nil
  271. }
  272. func (c *Config) LoadConfig(configFile string) error {
  273. info, err := os.Stat(configFile)
  274. // permission denied is soft error
  275. if os.IsNotExist(err) {
  276. return nil
  277. } else if err != nil {
  278. return err
  279. }
  280. if _, err = toml.DecodeFile(configFile, c); err != nil {
  281. return err
  282. }
  283. for _, runner := range c.Runners {
  284. if runner.Machine == nil {
  285. continue
  286. }
  287. err := runner.Machine.CompileOffPeakPeriods()
  288. if err != nil {
  289. return err
  290. }
  291. }
  292. c.ModTime = info.ModTime()
  293. c.Loaded = true
  294. return nil
  295. }
  296. func (c *Config) SaveConfig(configFile string) error {
  297. var newConfig bytes.Buffer
  298. newBuffer := bufio.NewWriter(&newConfig)
  299. if err := toml.NewEncoder(newBuffer).Encode(c); err != nil {
  300. log.Fatalf("Error encoding TOML: %s", err)
  301. return err
  302. }
  303. if err := newBuffer.Flush(); err != nil {
  304. return err
  305. }
  306. // create directory to store configuration
  307. os.MkdirAll(filepath.Dir(configFile), 0700)
  308. // write config file
  309. if err := ioutil.WriteFile(configFile, newConfig.Bytes(), 0600); err != nil {
  310. return err
  311. }
  312. c.Loaded = true
  313. return nil
  314. }
  315. func (c *Config) GetCheckInterval() time.Duration {
  316. if c.CheckInterval > 0 {
  317. return time.Duration(c.CheckInterval) * time.Second
  318. }
  319. return CheckInterval
  320. }