gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/common/config.go (about) 1 package common 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io/ioutil" 10 "math/big" 11 "os" 12 "path/filepath" 13 "strconv" 14 "strings" 15 "time" 16 17 "github.com/BurntSushi/toml" 18 "github.com/docker/go-units" 19 "github.com/sirupsen/logrus" 20 api "k8s.io/api/core/v1" 21 22 "gitlab.com/gitlab-org/gitlab-runner/helpers" 23 docker_helpers "gitlab.com/gitlab-org/gitlab-runner/helpers/docker" 24 "gitlab.com/gitlab-org/gitlab-runner/helpers/ssh" 25 "gitlab.com/gitlab-org/gitlab-runner/helpers/timeperiod" 26 ) 27 28 type DockerPullPolicy string 29 type DockerSysCtls map[string]string 30 31 const ( 32 PullPolicyAlways = "always" 33 PullPolicyNever = "never" 34 PullPolicyIfNotPresent = "if-not-present" 35 ) 36 37 // Get returns one of the predefined values or returns an error if the value can't match the predefined 38 func (p DockerPullPolicy) Get() (DockerPullPolicy, error) { 39 // Default policy is always 40 if p == "" { 41 return PullPolicyAlways, nil 42 } 43 44 // Verify pull policy 45 if p != PullPolicyNever && 46 p != PullPolicyIfNotPresent && 47 p != PullPolicyAlways { 48 return "", fmt.Errorf("unsupported docker-pull-policy: %v", p) 49 } 50 return p, nil 51 } 52 53 type DockerConfig struct { 54 docker_helpers.DockerCredentials 55 Hostname string `toml:"hostname,omitempty" json:"hostname" long:"hostname" env:"DOCKER_HOSTNAME" description:"Custom container hostname"` 56 Image string `toml:"image" json:"image" long:"image" env:"DOCKER_IMAGE" description:"Docker image to be used"` 57 Runtime string `toml:"runtime,omitempty" json:"runtime" long:"runtime" env:"DOCKER_RUNTIME" description:"Docker runtime to be used"` 58 Memory string `toml:"memory,omitempty" json:"memory" long:"memory" env:"DOCKER_MEMORY" description:"Memory limit (format: <number>[<unit>]). Unit can be one of b, k, m, or g. Minimum is 4M."` 59 MemorySwap string `toml:"memory_swap,omitempty" json:"memory_swap" long:"memory-swap" env:"DOCKER_MEMORY_SWAP" description:"Total memory limit (memory + swap, format: <number>[<unit>]). Unit can be one of b, k, m, or g."` 60 MemoryReservation string `toml:"memory_reservation,omitempty" json:"memory_reservation" long:"memory-reservation" env:"DOCKER_MEMORY_RESERVATION" description:"Memory soft limit (format: <number>[<unit>]). Unit can be one of b, k, m, or g."` 61 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"` 62 CPUS string `toml:"cpus,omitempty" json:"cpus" long:"cpus" env:"DOCKER_CPUS" description:"Number of CPUs"` 63 DNS []string `toml:"dns,omitempty" json:"dns" long:"dns" env:"DOCKER_DNS" description:"A list of DNS servers for the container to use"` 64 DNSSearch []string `toml:"dns_search,omitempty" json:"dns_search" long:"dns-search" env:"DOCKER_DNS_SEARCH" description:"A list of DNS search domains"` 65 Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"DOCKER_PRIVILEGED" description:"Give extended privileges to container"` 66 DisableEntrypointOverwrite bool `toml:"disable_entrypoint_overwrite,omitzero" json:"disable_entrypoint_overwrite" long:"disable-entrypoint-overwrite" env:"DOCKER_DISABLE_ENTRYPOINT_OVERWRITE" description:"Disable the possibility for a container to overwrite the default image entrypoint"` 67 UsernsMode string `toml:"userns_mode,omitempty" json:"userns_mode" long:"userns" env:"DOCKER_USERNS_MODE" description:"User namespace to use"` 68 CapAdd []string `toml:"cap_add" json:"cap_add" long:"cap-add" env:"DOCKER_CAP_ADD" description:"Add Linux capabilities"` 69 CapDrop []string `toml:"cap_drop" json:"cap_drop" long:"cap-drop" env:"DOCKER_CAP_DROP" description:"Drop Linux capabilities"` 70 OomKillDisable bool `toml:"oom_kill_disable,omitzero" json:"oom_kill_disable" long:"oom-kill-disable" env:"DOCKER_OOM_KILL_DISABLE" description:"Do not kill processes in a container if an out-of-memory (OOM) error occurs"` 71 SecurityOpt []string `toml:"security_opt" json:"security_opt" long:"security-opt" env:"DOCKER_SECURITY_OPT" description:"Security Options"` 72 Devices []string `toml:"devices" json:"devices" long:"devices" env:"DOCKER_DEVICES" description:"Add a host device to the container"` 73 DisableCache bool `toml:"disable_cache,omitzero" json:"disable_cache" long:"disable-cache" env:"DOCKER_DISABLE_CACHE" description:"Disable all container caching"` 74 Volumes []string `toml:"volumes,omitempty" json:"volumes" long:"volumes" env:"DOCKER_VOLUMES" description:"Bind-mount a volume and create it if it doesn't exist prior to mounting. Can be specified multiple times once per mountpoint, e.g. --docker-volumes 'test0:/test0' --docker-volumes 'test1:/test1'"` 75 VolumeDriver string `toml:"volume_driver,omitempty" json:"volume_driver" long:"volume-driver" env:"DOCKER_VOLUME_DRIVER" description:"Volume driver to be used"` 76 CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"DOCKER_CACHE_DIR" description:"Directory where to store caches"` 77 ExtraHosts []string `toml:"extra_hosts,omitempty" json:"extra_hosts" long:"extra-hosts" env:"DOCKER_EXTRA_HOSTS" description:"Add a custom host-to-IP mapping"` 78 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"` 79 NetworkMode string `toml:"network_mode,omitempty" json:"network_mode" long:"network-mode" env:"DOCKER_NETWORK_MODE" description:"Add container to a custom network"` 80 Links []string `toml:"links,omitempty" json:"links" long:"links" env:"DOCKER_LINKS" description:"Add link to another container"` 81 Services []string `toml:"services,omitempty" json:"services" long:"services" env:"DOCKER_SERVICES" description:"Add service that is started with container"` 82 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"` 83 AllowedImages []string `toml:"allowed_images,omitempty" json:"allowed_images" long:"allowed-images" env:"DOCKER_ALLOWED_IMAGES" description:"Whitelist allowed images"` 84 AllowedServices []string `toml:"allowed_services,omitempty" json:"allowed_services" long:"allowed-services" env:"DOCKER_ALLOWED_SERVICES" description:"Whitelist allowed services"` 85 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"` 86 ShmSize int64 `toml:"shm_size,omitempty" json:"shm_size" long:"shm-size" env:"DOCKER_SHM_SIZE" description:"Shared memory size for docker images (in bytes)"` 87 Tmpfs map[string]string `toml:"tmpfs,omitempty" json:"tmpfs" long:"tmpfs" env:"DOCKER_TMPFS" description:"A toml table/json object with the format key=values. When set this will mount the specified path in the key as a tmpfs volume in the main container, using the options specified as key. For the supported options, see the documentation for the unix 'mount' command"` 88 ServicesTmpfs map[string]string `toml:"services_tmpfs,omitempty" json:"services_tmpfs" long:"services-tmpfs" env:"DOCKER_SERVICES_TMPFS" description:"A toml table/json object with the format key=values. When set this will mount the specified path in the key as a tmpfs volume in all the service containers, using the options specified as key. For the supported options, see the documentation for the unix 'mount' command"` 89 SysCtls DockerSysCtls `toml:"sysctls,omitempty" json:"sysctls" long:"sysctls" env:"DOCKER_SYSCTLS" description:"Sysctl options, a toml table/json object of key=value. Value is expected to be a string."` 90 HelperImage string `toml:"helper_image,omitempty" json:"helper_image" long:"helper-image" env:"DOCKER_HELPER_IMAGE" description:"[ADVANCED] Override the default helper image used to clone repos and upload artifacts"` 91 } 92 93 type DockerMachine struct { 94 IdleCount int `long:"idle-nodes" env:"MACHINE_IDLE_COUNT" description:"Maximum idle machines"` 95 IdleTime int `toml:"IdleTime,omitzero" long:"idle-time" env:"MACHINE_IDLE_TIME" description:"Minimum time after node can be destroyed"` 96 MaxBuilds int `toml:"MaxBuilds,omitzero" long:"max-builds" env:"MACHINE_MAX_BUILDS" description:"Maximum number of builds processed by machine"` 97 MachineDriver string `long:"machine-driver" env:"MACHINE_DRIVER" description:"The driver to use when creating machine"` 98 MachineName string `long:"machine-name" env:"MACHINE_NAME" description:"The template for machine name (needs to include %s)"` 99 MachineOptions []string `long:"machine-options" env:"MACHINE_OPTIONS" description:"Additional machine creation options"` 100 101 OffPeakPeriods []string `long:"off-peak-periods" env:"MACHINE_OFF_PEAK_PERIODS" description:"Time periods when the scheduler is in the OffPeak mode"` 102 OffPeakTimezone string `long:"off-peak-timezone" env:"MACHINE_OFF_PEAK_TIMEZONE" description:"Timezone for the OffPeak periods (defaults to Local)"` 103 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"` 104 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"` 105 106 offPeakTimePeriods *timeperiod.TimePeriod 107 } 108 109 type ParallelsConfig struct { 110 BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"PARALLELS_BASE_NAME" description:"VM name to be used"` 111 TemplateName string `toml:"template_name,omitempty" json:"template_name" long:"template-name" env:"PARALLELS_TEMPLATE_NAME" description:"VM template to be created"` 112 DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"PARALLELS_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"` 113 TimeServer string `toml:"time_server,omitempty" json:"time_server" long:"time-server" env:"PARALLELS_TIME_SERVER" description:"Timeserver to sync the guests time from. Defaults to time.apple.com"` 114 } 115 116 type VirtualBoxConfig struct { 117 BaseName string `toml:"base_name" json:"base_name" long:"base-name" env:"VIRTUALBOX_BASE_NAME" description:"VM name to be used"` 118 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"` 119 DisableSnapshots bool `toml:"disable_snapshots,omitzero" json:"disable_snapshots" long:"disable-snapshots" env:"VIRTUALBOX_DISABLE_SNAPSHOTS" description:"Disable snapshoting to speedup VM creation"` 120 } 121 122 type KubernetesPullPolicy string 123 124 // Get returns one of the predefined values in kubernetes notation or returns an error if the value can't match the predefined 125 func (p KubernetesPullPolicy) Get() (KubernetesPullPolicy, error) { 126 switch { 127 case p == "": 128 return "", nil 129 case p == PullPolicyAlways: 130 return "Always", nil 131 case p == PullPolicyNever: 132 return "Never", nil 133 case p == PullPolicyIfNotPresent: 134 return "IfNotPresent", nil 135 } 136 return "", fmt.Errorf("unsupported kubernetes-pull-policy: %v", p) 137 } 138 139 type KubernetesConfig struct { 140 Host string `toml:"host" json:"host" long:"host" env:"KUBERNETES_HOST" description:"Optional Kubernetes master host URL (auto-discovery attempted if not specified)"` 141 CertFile string `toml:"cert_file,omitempty" json:"cert_file" long:"cert-file" env:"KUBERNETES_CERT_FILE" description:"Optional Kubernetes master auth certificate"` 142 KeyFile string `toml:"key_file,omitempty" json:"key_file" long:"key-file" env:"KUBERNETES_KEY_FILE" description:"Optional Kubernetes master auth private key"` 143 CAFile string `toml:"ca_file,omitempty" json:"ca_file" long:"ca-file" env:"KUBERNETES_CA_FILE" description:"Optional Kubernetes master auth ca certificate"` 144 BearerTokenOverwriteAllowed bool `toml:"bearer_token_overwrite_allowed" json:"bearer_token_overwrite_allowed" long:"bearer_token_overwrite_allowed" env:"KUBERNETES_BEARER_TOKEN_OVERWRITE_ALLOWED" description:"Bool to authorize builds to specify their own bearer token for creation."` 145 BearerToken string `toml:"bearer_token,omitempty" json:"bearer_token" long:"bearer_token" env:"KUBERNETES_BEARER_TOKEN" description:"Optional Kubernetes service account token used to start build pods."` 146 Image string `toml:"image" json:"image" long:"image" env:"KUBERNETES_IMAGE" description:"Default docker image to use for builds when none is specified"` 147 Namespace string `toml:"namespace" json:"namespace" long:"namespace" env:"KUBERNETES_NAMESPACE" description:"Namespace to run Kubernetes jobs in"` 148 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"` 149 Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"KUBERNETES_PRIVILEGED" description:"Run all containers with the privileged flag enabled"` 150 CPULimit string `toml:"cpu_limit,omitempty" json:"cpu_limit" long:"cpu-limit" env:"KUBERNETES_CPU_LIMIT" description:"The CPU allocation given to build containers"` 151 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"` 152 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"` 153 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"` 154 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"` 155 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"` 156 CPURequest string `toml:"cpu_request,omitempty" json:"cpu_request" long:"cpu-request" env:"KUBERNETES_CPU_REQUEST" description:"The CPU allocation requested for build containers"` 157 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"` 158 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"` 159 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"` 160 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"` 161 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"` 162 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"` 163 NodeSelector map[string]string `toml:"node_selector,omitempty" json:"node_selector" long:"node-selector" env:"KUBERNETES_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."` 164 NodeTolerations map[string]string `toml:"node_tolerations,omitempty" json:"node_tolerations" long:"node-tolerations" env:"KUBERNETES_NODE_TOLERATIONS" description:"A toml table/json object of key=value:effect. Value and effect are expected to be strings. When set, pods will tolerate the given taints. Only one toleration is supported through environment variable configuration."` 165 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"` 166 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"` 167 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."` 168 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"` 169 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)"` 170 PodLabels map[string]string `toml:"pod_labels,omitempty" json:"pod_labels" long:"pod-labels" description:"A toml table/json object of key-value. Value is expected to be a string. When set, this will create pods with the given pod labels. Environment variables will be substituted for values here."` 171 ServiceAccount string `toml:"service_account,omitempty" json:"service_account" long:"service-account" env:"KUBERNETES_SERVICE_ACCOUNT" description:"Executor pods will use this Service Account to talk to kubernetes API"` 172 ServiceAccountOverwriteAllowed string `toml:"service_account_overwrite_allowed" json:"service_account_overwrite_allowed" long:"service_account_overwrite_allowed" env:"KUBERNETES_SERVICE_ACCOUNT_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_SERVICE_ACCOUNT' value"` 173 PodAnnotations map[string]string `toml:"pod_annotations,omitempty" json:"pod_annotations" long:"pod-annotations" description:"A toml table/json object of key-value. Value is expected to be a string. When set, this will create pods with the given annotations. Can be overwritten in build with KUBERNETES_POD_ANNOTATIONS_* variables"` 174 PodAnnotationsOverwriteAllowed string `toml:"pod_annotations_overwrite_allowed" json:"pod_annotations_overwrite_allowed" long:"pod_annotations_overwrite_allowed" env:"KUBERNETES_POD_ANNOTATIONS_OVERWRITE_ALLOWED" description:"Regex to validate 'KUBERNETES_POD_ANNOTATIONS_*' values"` 175 Volumes KubernetesVolumes `toml:"volumes"` 176 } 177 178 type KubernetesVolumes struct { 179 HostPaths []KubernetesHostPath `toml:"host_path" description:"The host paths which will be mounted"` 180 PVCs []KubernetesPVC `toml:"pvc" description:"The persistent volume claims that will be mounted"` 181 ConfigMaps []KubernetesConfigMap `toml:"config_map" description:"The config maps which will be mounted as volumes"` 182 Secrets []KubernetesSecret `toml:"secret" description:"The secret maps which will be mounted"` 183 EmptyDirs []KubernetesEmptyDir `toml:"empty_dir" description:"The empty dirs which will be mounted"` 184 } 185 186 type KubernetesConfigMap struct { 187 Name string `toml:"name" json:"name" description:"The name of the volume and ConfigMap to use"` 188 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 189 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 190 Items map[string]string `toml:"items,omitempty" description:"Key-to-path mapping for keys from the config map that should be used."` 191 } 192 193 type KubernetesHostPath struct { 194 Name string `toml:"name" json:"name" description:"The name of the volume"` 195 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 196 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 197 HostPath string `toml:"host_path,omitempty" description:"Path from the host that should be mounted as a volume"` 198 } 199 200 type KubernetesPVC struct { 201 Name string `toml:"name" json:"name" description:"The name of the volume and PVC to use"` 202 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 203 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 204 } 205 206 type KubernetesSecret struct { 207 Name string `toml:"name" json:"name" description:"The name of the volume and Secret to use"` 208 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 209 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 210 Items map[string]string `toml:"items,omitempty" description:"Key-to-path mapping for keys from the secret that should be used."` 211 } 212 213 type KubernetesEmptyDir struct { 214 Name string `toml:"name" json:"name" description:"The name of the volume and EmptyDir to use"` 215 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 216 Medium string `toml:"medium,omitempty" description:"Set to 'Memory' to have a tmpfs"` 217 } 218 219 type RunnerCredentials struct { 220 URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"` 221 Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"` 222 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"` 223 TLSCertFile string `toml:"tls-cert-file,omitempty" json:"tls-cert-file" long:"tls-cert-file" env:"CI_SERVER_TLS_CERT_FILE" description:"File containing certificate for TLS client auth when using HTTPS"` 224 TLSKeyFile string `toml:"tls-key-file,omitempty" json:"tls-key-file" long:"tls-key-file" env:"CI_SERVER_TLS_KEY_FILE" description:"File containing private key for TLS client auth when using HTTPS"` 225 } 226 227 type CacheGCSCredentials struct { 228 AccessID string `toml:"AccessID,omitempty" long:"access-id" env:"CACHE_GCS_ACCESS_ID" description:"ID of GCP Service Account used to access the storage"` 229 PrivateKey string `toml:"PrivateKey,omitempty" long:"private-key" env:"CACHE_GCS_PRIVATE_KEY" description:"Private key used to sign GCS requests"` 230 } 231 232 type CacheGCSConfig struct { 233 CacheGCSCredentials 234 CredentialsFile string `toml:"CredentialsFile,omitempty" long:"credentials-file" env:"GOOGLE_APPLICATION_CREDENTIALS" description:"File with GCP credentials, containing AccessID and PrivateKey"` 235 BucketName string `toml:"BucketName,omitempty" long:"bucket-name" env:"CACHE_GCS_BUCKET_NAME" description:"Name of the bucket where cache will be stored"` 236 } 237 238 type CacheS3Config struct { 239 ServerAddress string `toml:"ServerAddress,omitempty" long:"server-address" env:"CACHE_S3_SERVER_ADDRESS" description:"A host:port to the used S3-compatible server"` 240 AccessKey string `toml:"AccessKey,omitempty" long:"access-key" env:"CACHE_S3_ACCESS_KEY" description:"S3 Access Key"` 241 SecretKey string `toml:"SecretKey,omitempty" long:"secret-key" env:"CACHE_S3_SECRET_KEY" description:"S3 Secret Key"` 242 BucketName string `toml:"BucketName,omitempty" long:"bucket-name" env:"CACHE_S3_BUCKET_NAME" description:"Name of the bucket where cache will be stored"` 243 BucketLocation string `toml:"BucketLocation,omitempty" long:"bucket-location" env:"CACHE_S3_BUCKET_LOCATION" description:"Name of S3 region"` 244 Insecure bool `toml:"Insecure,omitempty" long:"insecure" env:"CACHE_S3_INSECURE" description:"Use insecure mode (without https)"` 245 } 246 247 type CacheConfig struct { 248 Type string `toml:"Type,omitempty" long:"type" env:"CACHE_TYPE" description:"Select caching method"` 249 Path string `toml:"Path,omitempty" long:"path" env:"CACHE_PATH" description:"Name of the path to prepend to the cache URL"` 250 Shared bool `toml:"Shared,omitempty" long:"shared" env:"CACHE_SHARED" description:"Enable cache sharing between runners."` 251 252 S3 *CacheS3Config `toml:"s3,omitempty" json:"s3" namespace:"s3"` 253 GCS *CacheGCSConfig `toml:"gcs,omitempty" json:"gcs" namespace:"gcs"` 254 255 // TODO: Remove in 12.0 256 S3CachePath string `toml:"-" long:"s3-cache-path" env:"S3_CACHE_PATH" description:"Name of the path to prepend to the cache URL. DEPRECATED"` // DEPRECATED 257 CacheShared bool `toml:"-" long:"cache-shared" description:"Enable cache sharing between runners. DEPRECATED"` // DEPRECATED 258 ServerAddress string `toml:"ServerAddress,omitempty" description:"A host:port to the used S3-compatible server DEPRECATED"` // DEPRECATED 259 AccessKey string `toml:"AccessKey,omitempty" description:"S3 Access Key DEPRECATED"` // DEPRECATED 260 SecretKey string `toml:"SecretKey,omitempty" description:"S3 Secret Key DEPRECATED"` // DEPRECATED 261 BucketName string `toml:"BucketName,omitempty" description:"Name of the bucket where cache will be stored DEPRECATED"` // DEPRECATED 262 BucketLocation string `toml:"BucketLocation,omitempty" description:"Name of S3 region DEPRECATED"` // DEPRECATED 263 Insecure bool `toml:"Insecure,omitempty" description:"Use insecure mode (without https) DEPRECATED"` // DEPRECATED 264 } 265 266 type RunnerSettings struct { 267 Executor string `toml:"executor" json:"executor" long:"executor" env:"RUNNER_EXECUTOR" required:"true" description:"Select executor, eg. shell, docker, etc."` 268 BuildsDir string `toml:"builds_dir,omitempty" json:"builds_dir" long:"builds-dir" env:"RUNNER_BUILDS_DIR" description:"Directory where builds are stored"` 269 CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"RUNNER_CACHE_DIR" description:"Directory where build cache is stored"` 270 CloneURL string `toml:"clone_url,omitempty" json:"clone_url" long:"clone-url" env:"CLONE_URL" description:"Overwrite the default URL used to clone or fetch the git ref"` 271 272 Environment []string `toml:"environment,omitempty" json:"environment" long:"env" env:"RUNNER_ENV" description:"Custom environment variables injected to build environment"` 273 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"` 274 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"` 275 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"` 276 277 DebugTraceDisabled bool `toml:"debug_trace_disabled,omitempty" json:"debug_trace_disabled" long:"debug-trace-disabled" env:"RUNNER_DEBUG_TRACE_DISABLED" description:"When set to true Runner will disable the possibility of using the CI_DEBUG_TRACE feature"` 278 279 Shell string `toml:"shell,omitempty" json:"shell" long:"shell" env:"RUNNER_SHELL" description:"Select bash, cmd or powershell"` 280 281 CustomBuildDir *CustomBuildDir `toml:"custom_build_dir,omitempty" json:"custom_build_dir" group:"custom build dir configuration" namespace:"custom_build_dir"` 282 SSH *ssh.Config `toml:"ssh,omitempty" json:"ssh" group:"ssh executor" namespace:"ssh"` 283 Docker *DockerConfig `toml:"docker,omitempty" json:"docker" group:"docker executor" namespace:"docker"` 284 Parallels *ParallelsConfig `toml:"parallels,omitempty" json:"parallels" group:"parallels executor" namespace:"parallels"` 285 VirtualBox *VirtualBoxConfig `toml:"virtualbox,omitempty" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"` 286 Cache *CacheConfig `toml:"cache,omitempty" json:"cache" group:"cache configuration" namespace:"cache"` 287 Machine *DockerMachine `toml:"machine,omitempty" json:"machine" group:"docker machine provider" namespace:"machine"` 288 Kubernetes *KubernetesConfig `toml:"kubernetes,omitempty" json:"kubernetes" group:"kubernetes executor" namespace:"kubernetes"` 289 } 290 291 type RunnerConfig struct { 292 Name string `toml:"name" json:"name" short:"name" long:"description" env:"RUNNER_NAME" description:"Runner name"` 293 Limit int `toml:"limit,omitzero" json:"limit" long:"limit" env:"RUNNER_LIMIT" description:"Maximum number of builds processed by this runner"` 294 OutputLimit int `toml:"output_limit,omitzero" long:"output-limit" env:"RUNNER_OUTPUT_LIMIT" description:"Maximum build trace size in kilobytes"` 295 RequestConcurrency int `toml:"request_concurrency,omitzero" long:"request-concurrency" env:"RUNNER_REQUEST_CONCURRENCY" description:"Maximum concurrency for job requests"` 296 297 RunnerCredentials 298 RunnerSettings 299 } 300 301 type SessionServer struct { 302 ListenAddress string `toml:"listen_address,omitempty" json:"listen_address" description:"Address that the runner will communicate directly with"` 303 AdvertiseAddress string `toml:"advertise_address,omitempty" json:"advertise_address" description:"Address the runner will expose to the world to connect to the session server"` 304 SessionTimeout int `toml:"session_timeout,omitempty" json:"session_timeout" description:"How long a terminal session can be active after a build completes, in seconds"` 305 } 306 307 type Config struct { 308 ListenAddress string `toml:"listen_address,omitempty" json:"listen_address"` 309 SessionServer SessionServer `toml:"session_server,omitempty" json:"session_server"` 310 311 // TODO: Remove in 12.0 312 MetricsServerAddress string `toml:"metrics_server,omitempty" json:"metrics_server"` // DEPRECATED 313 314 Concurrent int `toml:"concurrent" json:"concurrent"` 315 CheckInterval int `toml:"check_interval" json:"check_interval" description:"Define active checking interval of jobs"` 316 LogLevel *string `toml:"log_level" json:"log_level" description:"Define log level (one of: panic, fatal, error, warning, info, debug)"` 317 LogFormat *string `toml:"log_format" json:"log_format" description:"Define log format (one of: runner, text, json)"` 318 User string `toml:"user,omitempty" json:"user"` 319 Runners []*RunnerConfig `toml:"runners" json:"runners"` 320 SentryDSN *string `toml:"sentry_dsn"` 321 ModTime time.Time `toml:"-"` 322 Loaded bool `toml:"-"` 323 } 324 325 type CustomBuildDir struct { 326 Enabled bool `toml:"enabled,omitempty" json:"enabled" long:"enabled" env:"CUSTOM_BUILD_DIR_ENABLED" description:"Enable job specific build directories"` 327 } 328 329 func getDeprecatedStringSetting(setting string, tomlField string, envVariable string, tomlReplacement string, envReplacement string) string { 330 if setting != "" { 331 logrus.Warningf("%s setting is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", tomlField, tomlReplacement) 332 return setting 333 } 334 335 value := os.Getenv(envVariable) 336 if value != "" { 337 logrus.Warningf("%s environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", envVariable, envReplacement) 338 } 339 340 return value 341 } 342 343 func getDeprecatedBoolSetting(setting bool, tomlField string, envVariable string, tomlReplacement string, envReplacement string) bool { 344 if setting { 345 logrus.Warningf("%s setting is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", tomlField, tomlReplacement) 346 return setting 347 } 348 349 value, _ := strconv.ParseBool(os.Getenv(envVariable)) 350 if value { 351 logrus.Warningf("%s environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", envVariable, envReplacement) 352 } 353 354 return value 355 } 356 357 func (c *CacheS3Config) ShouldUseIAMCredentials() bool { 358 return c.ServerAddress == "" || c.AccessKey == "" || c.SecretKey == "" 359 } 360 361 func (c *CacheConfig) GetPath() string { 362 if c.Path != "" { 363 return c.Path 364 } 365 366 // TODO: Remove in 12.0 367 if c.S3CachePath != "" { 368 logrus.Warning("'--cache-s3-cache-path' command line option and `$S3_CACHE_PATH` environment variables are deprecated and will be removed in GitLab Runner 12.0. Please use '--cache-path' or '$CACHE_PATH' instead") 369 } 370 371 return c.S3CachePath 372 } 373 374 func (c *CacheConfig) GetShared() bool { 375 if c.Shared { 376 return c.Shared 377 } 378 379 // TODO: Remove in 12.0 380 if c.CacheShared { 381 logrus.Warning("'--cache-cache-shared' command line is deprecated and will be removed in GitLab Runner 12.0. Please use '--cache-shared' instead") 382 } 383 384 return c.CacheShared 385 } 386 387 // DEPRECATED 388 // TODO: Remove in 12.0 389 func (c *CacheConfig) GetServerAddress() string { 390 return getDeprecatedStringSetting( 391 c.ServerAddress, 392 "[runners.cache] ServerAddress", 393 "S3_SERVER_ADDRESS", 394 "[runners.cache.s3] ServerAddress", 395 "CACHE_S3_SERVER_ADDRESS") 396 } 397 398 // DEPRECATED 399 // TODO: Remove in 12.0 400 func (c *CacheConfig) GetAccessKey() string { 401 return getDeprecatedStringSetting( 402 c.AccessKey, 403 "[runners.cache] AccessKey", 404 "S3_ACCESS_KEY", 405 "[runners.cache.s3] AccessKey", 406 "CACHE_S3_ACCESS_KEY") 407 } 408 409 // DEPRECATED 410 // TODO: Remove in 12.0 411 func (c *CacheConfig) GetSecretKey() string { 412 return getDeprecatedStringSetting( 413 c.SecretKey, 414 "[runners.cache] SecretKey", 415 "S3_SECRET_KEY", 416 "[runners.cache.s3] SecretKey", 417 "CACHE_S3_SECRET_KEY") 418 } 419 420 // DEPRECATED 421 // TODO: Remove in 12.0 422 func (c *CacheConfig) GetBucketName() string { 423 return getDeprecatedStringSetting( 424 c.BucketName, 425 "[runners.cache] BucketName", 426 "S3_BUCKET_NAME", 427 "[runners.cache.s3] BucketName", 428 "CACHE_S3_BUCKET_NAME") 429 } 430 431 // DEPRECATED 432 // TODO: Remove in 12.0 433 func (c *CacheConfig) GetBucketLocation() string { 434 return getDeprecatedStringSetting( 435 c.BucketLocation, 436 "[runners.cache] BucketLocation", 437 "S3_BUCKET_LOCATION", 438 "[runners.cache.s3] BucketLocation", 439 "CACHE_S3_BUCKET_LOCATION") 440 } 441 442 // DEPRECATED 443 // TODO: Remove in 12.0 444 func (c *CacheConfig) GetInsecure() bool { 445 return getDeprecatedBoolSetting( 446 c.Insecure, 447 "[runners.cache] Insecure", 448 "S3_CACHE_INSECURE", 449 "[runners.cache.s3] Insecure", 450 "CACHE_S3_INSECURE") 451 } 452 453 func (c *SessionServer) GetSessionTimeout() time.Duration { 454 if c.SessionTimeout > 0 { 455 return time.Duration(c.SessionTimeout) * time.Second 456 } 457 458 return DefaultSessionTimeout 459 } 460 461 func (c *DockerConfig) GetNanoCPUs() (int64, error) { 462 if c.CPUS == "" { 463 return 0, nil 464 } 465 466 cpu, ok := new(big.Rat).SetString(c.CPUS) 467 if !ok { 468 return 0, fmt.Errorf("failed to parse %v as a rational number", c.CPUS) 469 } 470 471 nano, _ := cpu.Mul(cpu, big.NewRat(1e9, 1)).Float64() 472 473 return int64(nano), nil 474 } 475 476 func (c *DockerConfig) getMemoryBytes(size string, fieldName string) int64 { 477 if size == "" { 478 return 0 479 } 480 481 bytes, err := units.RAMInBytes(size) 482 if err != nil { 483 logrus.Fatalf("Error parsing docker %s: %s", fieldName, err) 484 } 485 486 return bytes 487 } 488 489 func (c *DockerConfig) GetMemory() int64 { 490 return c.getMemoryBytes(c.Memory, "memory") 491 } 492 493 func (c *DockerConfig) GetMemorySwap() int64 { 494 return c.getMemoryBytes(c.MemorySwap, "memory_swap") 495 } 496 497 func (c *DockerConfig) GetMemoryReservation() int64 { 498 return c.getMemoryBytes(c.MemoryReservation, "memory_reservation") 499 } 500 501 func (c *DockerConfig) GetOomKillDisable() *bool { 502 return &c.OomKillDisable 503 } 504 505 func (c *KubernetesConfig) GetPollAttempts() int { 506 if c.PollTimeout <= 0 { 507 c.PollTimeout = KubernetesPollTimeout 508 } 509 510 return c.PollTimeout / c.GetPollInterval() 511 } 512 513 func (c *KubernetesConfig) GetPollInterval() int { 514 if c.PollInterval <= 0 { 515 c.PollInterval = KubernetesPollInterval 516 } 517 518 return c.PollInterval 519 } 520 521 func (c *KubernetesConfig) GetNodeTolerations() []api.Toleration { 522 var tolerations []api.Toleration 523 524 for toleration, effect := range c.NodeTolerations { 525 newToleration := api.Toleration{ 526 Effect: api.TaintEffect(effect), 527 } 528 529 if strings.Contains(toleration, "=") { 530 parts := strings.Split(toleration, "=") 531 newToleration.Key = parts[0] 532 if len(parts) > 1 { 533 newToleration.Value = parts[1] 534 } 535 newToleration.Operator = api.TolerationOpEqual 536 } else { 537 newToleration.Key = toleration 538 newToleration.Operator = api.TolerationOpExists 539 } 540 541 tolerations = append(tolerations, newToleration) 542 } 543 544 return tolerations 545 } 546 547 func (c *DockerMachine) GetIdleCount() int { 548 if c.isOffPeak() { 549 return c.OffPeakIdleCount 550 } 551 552 return c.IdleCount 553 } 554 555 func (c *DockerMachine) GetIdleTime() int { 556 if c.isOffPeak() { 557 return c.OffPeakIdleTime 558 } 559 560 return c.IdleTime 561 } 562 563 func (c *DockerMachine) isOffPeak() bool { 564 if c.offPeakTimePeriods == nil { 565 c.CompileOffPeakPeriods() 566 } 567 568 return c.offPeakTimePeriods != nil && c.offPeakTimePeriods.InPeriod() 569 } 570 571 func (c *DockerMachine) CompileOffPeakPeriods() (err error) { 572 c.offPeakTimePeriods, err = timeperiod.TimePeriods(c.OffPeakPeriods, c.OffPeakTimezone) 573 if err != nil { 574 err = errors.New(fmt.Sprint("Invalid OffPeakPeriods value: ", err)) 575 } 576 577 return 578 } 579 580 func (c *RunnerCredentials) GetURL() string { 581 return c.URL 582 } 583 584 func (c *RunnerCredentials) GetTLSCAFile() string { 585 return c.TLSCAFile 586 } 587 588 func (c *RunnerCredentials) GetTLSCertFile() string { 589 return c.TLSCertFile 590 } 591 592 func (c *RunnerCredentials) GetTLSKeyFile() string { 593 return c.TLSKeyFile 594 } 595 596 func (c *RunnerCredentials) GetToken() string { 597 return c.Token 598 } 599 600 func (c *RunnerCredentials) ShortDescription() string { 601 return helpers.ShortenToken(c.Token) 602 } 603 604 func (c *RunnerCredentials) UniqueID() string { 605 return c.URL + c.Token 606 } 607 608 func (c *RunnerCredentials) Log() *logrus.Entry { 609 if c.ShortDescription() != "" { 610 return logrus.WithField("runner", c.ShortDescription()) 611 } 612 return logrus.WithFields(logrus.Fields{}) 613 } 614 615 func (c *RunnerCredentials) SameAs(other *RunnerCredentials) bool { 616 return c.URL == other.URL && c.Token == other.Token 617 } 618 619 func (c *RunnerConfig) String() string { 620 return fmt.Sprintf("%v url=%v token=%v executor=%v", c.Name, c.URL, c.Token, c.Executor) 621 } 622 623 func (c *RunnerConfig) GetRequestConcurrency() int { 624 if c.RequestConcurrency <= 0 { 625 return 1 626 } 627 return c.RequestConcurrency 628 } 629 630 func (c *RunnerConfig) GetVariables() JobVariables { 631 var variables JobVariables 632 633 for _, environment := range c.Environment { 634 if variable, err := ParseVariable(environment); err == nil { 635 variable.Internal = true 636 variables = append(variables, variable) 637 } 638 } 639 640 return variables 641 } 642 643 // DeepCopy attempts to make a deep clone of the object 644 func (c *RunnerConfig) DeepCopy() (*RunnerConfig, error) { 645 var r RunnerConfig 646 647 bytes, err := json.Marshal(c) 648 if err != nil { 649 return nil, fmt.Errorf("serialization of runner config failed: %v", err) 650 } 651 652 err = json.Unmarshal(bytes, &r) 653 if err != nil { 654 return nil, fmt.Errorf("deserialization of runner config failed: %v", err) 655 } 656 657 return &r, err 658 } 659 660 func NewConfig() *Config { 661 return &Config{ 662 Concurrent: 1, 663 SessionServer: SessionServer{ 664 SessionTimeout: int(DefaultSessionTimeout.Seconds()), 665 }, 666 } 667 } 668 669 func (c *Config) StatConfig(configFile string) error { 670 _, err := os.Stat(configFile) 671 if err != nil { 672 return err 673 } 674 return nil 675 } 676 677 func (c *Config) LoadConfig(configFile string) error { 678 info, err := os.Stat(configFile) 679 680 // permission denied is soft error 681 if os.IsNotExist(err) { 682 return nil 683 } else if err != nil { 684 return err 685 } 686 687 if _, err = toml.DecodeFile(configFile, c); err != nil { 688 return err 689 } 690 691 for _, runner := range c.Runners { 692 if runner.Machine == nil { 693 continue 694 } 695 696 err := runner.Machine.CompileOffPeakPeriods() 697 if err != nil { 698 return err 699 } 700 } 701 702 c.ModTime = info.ModTime() 703 c.Loaded = true 704 return nil 705 } 706 707 func (c *Config) SaveConfig(configFile string) error { 708 var newConfig bytes.Buffer 709 newBuffer := bufio.NewWriter(&newConfig) 710 711 if err := toml.NewEncoder(newBuffer).Encode(c); err != nil { 712 logrus.Fatalf("Error encoding TOML: %s", err) 713 return err 714 } 715 716 if err := newBuffer.Flush(); err != nil { 717 return err 718 } 719 720 // create directory to store configuration 721 os.MkdirAll(filepath.Dir(configFile), 0700) 722 723 // write config file 724 if err := ioutil.WriteFile(configFile, newConfig.Bytes(), 0600); err != nil { 725 return err 726 } 727 728 c.Loaded = true 729 return nil 730 } 731 732 func (c *Config) GetCheckInterval() time.Duration { 733 if c.CheckInterval > 0 { 734 return time.Duration(c.CheckInterval) * time.Second 735 } 736 return CheckInterval 737 } 738 739 func (c *Config) ListenOrServerMetricAddress() string { 740 if c.ListenAddress != "" { 741 return c.ListenAddress 742 } 743 744 // TODO: Remove in 12.0 745 if c.MetricsServerAddress != "" { 746 logrus.Warnln("'metrics_server' configuration entry is deprecated and will be removed in one of future releases; please use 'listen_address' instead") 747 } 748 749 return c.MetricsServerAddress 750 }