github.com/nilium/gitlab-runner@v12.5.0+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 CustomConfig struct { 123 ConfigExec string `toml:"config_exec,omitempty" json:"config_exec" long:"config-exec" env:"CUSTOM_CONFIG_EXEC" description:"Executable that allows to inject configuration values to the executor"` 124 ConfigArgs []string `toml:"config_args,omitempty" json:"config_args" long:"config-args" description:"Arguments for the config executable"` 125 ConfigExecTimeout *int `toml:"config_exec_timeout,omitempty" json:"config_exec_timeout" long:"config-exec-timeout" env:"CUSTOM_CONFIG_EXEC_TIMEOUT" description:"Timeout for the config executable (in seconds)"` 126 127 PrepareExec string `toml:"prepare_exec,omitempty" json:"prepare_exec" long:"prepare-exec" env:"CUSTOM_PREPARE_EXEC" description:"Executable that prepares executor"` 128 PrepareArgs []string `toml:"prepare_args,omitempty" json:"prepare_args" long:"prepare-args" description:"Arguments for the prepare executable"` 129 PrepareExecTimeout *int `toml:"prepare_exec_timeout,omitempty" json:"prepare_exec_timeout" long:"prepare-exec-timeout" env:"CUSTOM_PREPARE_EXEC_TIMEOUT" description:"Timeout for the prepare executable (in seconds)"` 130 131 RunExec string `toml:"run_exec" json:"run_exec" long:"run-exec" env:"CUSTOM_RUN_EXEC" description:"Executable that runs the job script in executor"` 132 RunArgs []string `toml:"run_args,omitempty" json:"run_args" long:"run-args" description:"Arguments for the run executable"` 133 134 CleanupExec string `toml:"cleanup_exec,omitempty" json:"cleanup_exec" long:"cleanup-exec" env:"CUSTOM_CLEANUP_EXEC" description:"Executable that cleanups after executor run"` 135 CleanupArgs []string `toml:"cleanup_args,omitempty" json:"cleanup_args" long:"cleanup-args" description:"Arguments for the cleanup executable"` 136 CleanupExecTimeout *int `toml:"cleanup_exec_timeout,omitempty" json:"cleanup_exec_timeout" long:"cleanup-exec-timeout" env:"CUSTOM_CLEANUP_EXEC_TIMEOUT" description:"Timeout for the cleanup executable (in seconds)"` 137 138 GracefulKillTimeout *int `toml:"graceful_kill_timeout,omitempty" json:"graceful_kill_timeout" long:"graceful-kill-timeout" env:"CUSTOM_GRACEFUL_KILL_TIMEOUT" description:"Graceful timeout for scripts execution after SIGTERM is sent to the process (in seconds). This limits the time given for scripts to perform the cleanup before exiting"` 139 ForceKillTimeout *int `toml:"force_kill_timeout,omitempty" json:"force_kill_timeout" long:"force-kill-timeout" env:"CUSTOM_FORCE_KILL_TIMEOUT" description:"Force timeout for scripts execution (in seconds). Counted from the force kill call; if process will be not terminated, Runner will abandon process termination and log an error"` 140 } 141 142 type KubernetesPullPolicy string 143 144 // Get returns one of the predefined values in kubernetes notation or returns an error if the value can't match the predefined 145 func (p KubernetesPullPolicy) Get() (KubernetesPullPolicy, error) { 146 switch { 147 case p == "": 148 return "", nil 149 case p == PullPolicyAlways: 150 return "Always", nil 151 case p == PullPolicyNever: 152 return "Never", nil 153 case p == PullPolicyIfNotPresent: 154 return "IfNotPresent", nil 155 } 156 return "", fmt.Errorf("unsupported kubernetes-pull-policy: %v", p) 157 } 158 159 type KubernetesConfig struct { 160 Host string `toml:"host" json:"host" long:"host" env:"KUBERNETES_HOST" description:"Optional Kubernetes master host URL (auto-discovery attempted if not specified)"` 161 CertFile string `toml:"cert_file,omitempty" json:"cert_file" long:"cert-file" env:"KUBERNETES_CERT_FILE" description:"Optional Kubernetes master auth certificate"` 162 KeyFile string `toml:"key_file,omitempty" json:"key_file" long:"key-file" env:"KUBERNETES_KEY_FILE" description:"Optional Kubernetes master auth private key"` 163 CAFile string `toml:"ca_file,omitempty" json:"ca_file" long:"ca-file" env:"KUBERNETES_CA_FILE" description:"Optional Kubernetes master auth ca certificate"` 164 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."` 165 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."` 166 Image string `toml:"image" json:"image" long:"image" env:"KUBERNETES_IMAGE" description:"Default docker image to use for builds when none is specified"` 167 Namespace string `toml:"namespace" json:"namespace" long:"namespace" env:"KUBERNETES_NAMESPACE" description:"Namespace to run Kubernetes jobs in"` 168 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"` 169 Privileged bool `toml:"privileged,omitzero" json:"privileged" long:"privileged" env:"KUBERNETES_PRIVILEGED" description:"Run all containers with the privileged flag enabled"` 170 CPULimit string `toml:"cpu_limit,omitempty" json:"cpu_limit" long:"cpu-limit" env:"KUBERNETES_CPU_LIMIT" description:"The CPU allocation given to build containers"` 171 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"` 172 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"` 173 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"` 174 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"` 175 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"` 176 CPURequest string `toml:"cpu_request,omitempty" json:"cpu_request" long:"cpu-request" env:"KUBERNETES_CPU_REQUEST" description:"The CPU allocation requested for build containers"` 177 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"` 178 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"` 179 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"` 180 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"` 181 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"` 182 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"` 183 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."` 184 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."` 185 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"` 186 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"` 187 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."` 188 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"` 189 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)"` 190 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."` 191 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"` 192 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"` 193 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_ANNOTATION_* variables"` 194 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"` 195 PodSecurityContext KubernetesPodSecurityContext `toml:"pod_security_context,omitempty" namespace:"pod-security-context" description:"A security context attached to each build pod"` 196 Volumes KubernetesVolumes `toml:"volumes"` 197 Services []Service `toml:"services,omitempty" json:"services" long:"services" description:"Add service that is started with container"` 198 } 199 200 type KubernetesVolumes struct { 201 HostPaths []KubernetesHostPath `toml:"host_path" description:"The host paths which will be mounted"` 202 PVCs []KubernetesPVC `toml:"pvc" description:"The persistent volume claims that will be mounted"` 203 ConfigMaps []KubernetesConfigMap `toml:"config_map" description:"The config maps which will be mounted as volumes"` 204 Secrets []KubernetesSecret `toml:"secret" description:"The secret maps which will be mounted"` 205 EmptyDirs []KubernetesEmptyDir `toml:"empty_dir" description:"The empty dirs which will be mounted"` 206 } 207 208 type KubernetesConfigMap struct { 209 Name string `toml:"name" json:"name" description:"The name of the volume and ConfigMap to use"` 210 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 211 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 212 Items map[string]string `toml:"items,omitempty" description:"Key-to-path mapping for keys from the config map that should be used."` 213 } 214 215 type KubernetesHostPath struct { 216 Name string `toml:"name" json:"name" description:"The name of the volume"` 217 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 218 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 219 HostPath string `toml:"host_path,omitempty" description:"Path from the host that should be mounted as a volume"` 220 } 221 222 type KubernetesPVC struct { 223 Name string `toml:"name" json:"name" description:"The name of the volume and PVC to use"` 224 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 225 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 226 } 227 228 type KubernetesSecret struct { 229 Name string `toml:"name" json:"name" description:"The name of the volume and Secret to use"` 230 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 231 ReadOnly bool `toml:"read_only,omitempty" description:"If this volume should be mounted read only"` 232 Items map[string]string `toml:"items,omitempty" description:"Key-to-path mapping for keys from the secret that should be used."` 233 } 234 235 type KubernetesEmptyDir struct { 236 Name string `toml:"name" json:"name" description:"The name of the volume and EmptyDir to use"` 237 MountPath string `toml:"mount_path" description:"Path where volume should be mounted inside of container"` 238 Medium string `toml:"medium,omitempty" description:"Set to 'Memory' to have a tmpfs"` 239 } 240 241 type KubernetesPodSecurityContext struct { 242 FSGroup *int64 `toml:"fs_group,omitempty" long:"fs-group" env:"KUBERNETES_POD_SECURITY_CONTEXT_FS_GROUP" description:"A special supplemental group that applies to all containers in a pod"` 243 RunAsGroup *int64 `toml:"run_as_group,omitempty" long:"run-as-group" env:"KUBERNETES_POD_SECURITY_CONTEXT_RUN_AS_GROUP" description:"The GID to run the entrypoint of the container process"` 244 RunAsNonRoot *bool `toml:"run_as_non_root,omitempty" long:"run-as-non-root" env:"KUBERNETES_POD_SECURITY_CONTEXT_RUN_AS_NON_ROOT" description:"Indicates that the container must run as a non-root user"` 245 RunAsUser *int64 `toml:"run_as_user,omitempty" long:"run-as-user" env:"KUBERNETES_POD_SECURITY_CONTEXT_RUN_AS_USER" description:"The UID to run the entrypoint of the container process"` 246 SupplementalGroups []int64 `toml:"supplemental_groups,omitempty" long:"supplemental-groups" description:"A list of groups applied to the first process run in each container, in addition to the container's primary GID"` 247 } 248 249 type Service struct { 250 Name string `toml:"name" long:"name" description:"The image path for the service"` 251 } 252 253 type RunnerCredentials struct { 254 URL string `toml:"url" json:"url" short:"u" long:"url" env:"CI_SERVER_URL" required:"true" description:"Runner URL"` 255 Token string `toml:"token" json:"token" short:"t" long:"token" env:"CI_SERVER_TOKEN" required:"true" description:"Runner token"` 256 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"` 257 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"` 258 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"` 259 } 260 261 type CacheGCSCredentials struct { 262 AccessID string `toml:"AccessID,omitempty" long:"access-id" env:"CACHE_GCS_ACCESS_ID" description:"ID of GCP Service Account used to access the storage"` 263 PrivateKey string `toml:"PrivateKey,omitempty" long:"private-key" env:"CACHE_GCS_PRIVATE_KEY" description:"Private key used to sign GCS requests"` 264 } 265 266 type CacheGCSConfig struct { 267 CacheGCSCredentials 268 CredentialsFile string `toml:"CredentialsFile,omitempty" long:"credentials-file" env:"GOOGLE_APPLICATION_CREDENTIALS" description:"File with GCP credentials, containing AccessID and PrivateKey"` 269 BucketName string `toml:"BucketName,omitempty" long:"bucket-name" env:"CACHE_GCS_BUCKET_NAME" description:"Name of the bucket where cache will be stored"` 270 } 271 272 type CacheS3Config struct { 273 ServerAddress string `toml:"ServerAddress,omitempty" long:"server-address" env:"CACHE_S3_SERVER_ADDRESS" description:"A host:port to the used S3-compatible server"` 274 AccessKey string `toml:"AccessKey,omitempty" long:"access-key" env:"CACHE_S3_ACCESS_KEY" description:"S3 Access Key"` 275 SecretKey string `toml:"SecretKey,omitempty" long:"secret-key" env:"CACHE_S3_SECRET_KEY" description:"S3 Secret Key"` 276 BucketName string `toml:"BucketName,omitempty" long:"bucket-name" env:"CACHE_S3_BUCKET_NAME" description:"Name of the bucket where cache will be stored"` 277 BucketLocation string `toml:"BucketLocation,omitempty" long:"bucket-location" env:"CACHE_S3_BUCKET_LOCATION" description:"Name of S3 region"` 278 Insecure bool `toml:"Insecure,omitempty" long:"insecure" env:"CACHE_S3_INSECURE" description:"Use insecure mode (without https)"` 279 } 280 281 type CacheConfig struct { 282 Type string `toml:"Type,omitempty" long:"type" env:"CACHE_TYPE" description:"Select caching method"` 283 Path string `toml:"Path,omitempty" long:"path" env:"CACHE_PATH" description:"Name of the path to prepend to the cache URL"` 284 Shared bool `toml:"Shared,omitempty" long:"shared" env:"CACHE_SHARED" description:"Enable cache sharing between runners."` 285 286 S3 *CacheS3Config `toml:"s3,omitempty" json:"s3" namespace:"s3"` 287 GCS *CacheGCSConfig `toml:"gcs,omitempty" json:"gcs" namespace:"gcs"` 288 } 289 290 type RunnerSettings struct { 291 Executor string `toml:"executor" json:"executor" long:"executor" env:"RUNNER_EXECUTOR" required:"true" description:"Select executor, eg. shell, docker, etc."` 292 BuildsDir string `toml:"builds_dir,omitempty" json:"builds_dir" long:"builds-dir" env:"RUNNER_BUILDS_DIR" description:"Directory where builds are stored"` 293 CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"RUNNER_CACHE_DIR" description:"Directory where build cache is stored"` 294 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"` 295 296 Environment []string `toml:"environment,omitempty" json:"environment" long:"env" env:"RUNNER_ENV" description:"Custom environment variables injected to build environment"` 297 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"` 298 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"` 299 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"` 300 301 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"` 302 303 Shell string `toml:"shell,omitempty" json:"shell" long:"shell" env:"RUNNER_SHELL" description:"Select bash, cmd or powershell"` 304 305 CustomBuildDir *CustomBuildDir `toml:"custom_build_dir,omitempty" json:"custom_build_dir" group:"custom build dir configuration" namespace:"custom_build_dir"` 306 SSH *ssh.Config `toml:"ssh,omitempty" json:"ssh" group:"ssh executor" namespace:"ssh"` 307 Docker *DockerConfig `toml:"docker,omitempty" json:"docker" group:"docker executor" namespace:"docker"` 308 Parallels *ParallelsConfig `toml:"parallels,omitempty" json:"parallels" group:"parallels executor" namespace:"parallels"` 309 VirtualBox *VirtualBoxConfig `toml:"virtualbox,omitempty" json:"virtualbox" group:"virtualbox executor" namespace:"virtualbox"` 310 Cache *CacheConfig `toml:"cache,omitempty" json:"cache" group:"cache configuration" namespace:"cache"` 311 Machine *DockerMachine `toml:"machine,omitempty" json:"machine" group:"docker machine provider" namespace:"machine"` 312 Kubernetes *KubernetesConfig `toml:"kubernetes,omitempty" json:"kubernetes" group:"kubernetes executor" namespace:"kubernetes"` 313 Custom *CustomConfig `toml:"custom,omitempty" json:"custom" group:"custom executor" namespace:"custom"` 314 } 315 316 type RunnerConfig struct { 317 Name string `toml:"name" json:"name" short:"name" long:"description" env:"RUNNER_NAME" description:"Runner name"` 318 Limit int `toml:"limit,omitzero" json:"limit" long:"limit" env:"RUNNER_LIMIT" description:"Maximum number of builds processed by this runner"` 319 OutputLimit int `toml:"output_limit,omitzero" long:"output-limit" env:"RUNNER_OUTPUT_LIMIT" description:"Maximum build trace size in kilobytes"` 320 RequestConcurrency int `toml:"request_concurrency,omitzero" long:"request-concurrency" env:"RUNNER_REQUEST_CONCURRENCY" description:"Maximum concurrency for job requests"` 321 322 RunnerCredentials 323 RunnerSettings 324 } 325 326 type SessionServer struct { 327 ListenAddress string `toml:"listen_address,omitempty" json:"listen_address" description:"Address that the runner will communicate directly with"` 328 AdvertiseAddress string `toml:"advertise_address,omitempty" json:"advertise_address" description:"Address the runner will expose to the world to connect to the session server"` 329 SessionTimeout int `toml:"session_timeout,omitempty" json:"session_timeout" description:"How long a terminal session can be active after a build completes, in seconds"` 330 } 331 332 type Config struct { 333 ListenAddress string `toml:"listen_address,omitempty" json:"listen_address"` 334 SessionServer SessionServer `toml:"session_server,omitempty" json:"session_server"` 335 336 Concurrent int `toml:"concurrent" json:"concurrent"` 337 CheckInterval int `toml:"check_interval" json:"check_interval" description:"Define active checking interval of jobs"` 338 LogLevel *string `toml:"log_level" json:"log_level" description:"Define log level (one of: panic, fatal, error, warning, info, debug)"` 339 LogFormat *string `toml:"log_format" json:"log_format" description:"Define log format (one of: runner, text, json)"` 340 User string `toml:"user,omitempty" json:"user"` 341 Runners []*RunnerConfig `toml:"runners" json:"runners"` 342 SentryDSN *string `toml:"sentry_dsn"` 343 ModTime time.Time `toml:"-"` 344 Loaded bool `toml:"-"` 345 } 346 347 type CustomBuildDir struct { 348 Enabled bool `toml:"enabled,omitempty" json:"enabled" long:"enabled" env:"CUSTOM_BUILD_DIR_ENABLED" description:"Enable job specific build directories"` 349 } 350 351 func getDeprecatedStringSetting(setting string, tomlField string, envVariable string, tomlReplacement string, envReplacement string) string { 352 if setting != "" { 353 logrus.Warningf("%s setting is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", tomlField, tomlReplacement) 354 return setting 355 } 356 357 value := os.Getenv(envVariable) 358 if value != "" { 359 logrus.Warningf("%s environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", envVariable, envReplacement) 360 } 361 362 return value 363 } 364 365 func getDeprecatedBoolSetting(setting bool, tomlField string, envVariable string, tomlReplacement string, envReplacement string) bool { 366 if setting { 367 logrus.Warningf("%s setting is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", tomlField, tomlReplacement) 368 return setting 369 } 370 371 value, _ := strconv.ParseBool(os.Getenv(envVariable)) 372 if value { 373 logrus.Warningf("%s environment variables is deprecated and will be removed in GitLab Runner 12.0. Please use %s instead", envVariable, envReplacement) 374 } 375 376 return value 377 } 378 379 func (c *CacheS3Config) ShouldUseIAMCredentials() bool { 380 return c.ServerAddress == "" || c.AccessKey == "" || c.SecretKey == "" 381 } 382 383 func (c *CacheConfig) GetPath() string { 384 return c.Path 385 } 386 387 func (c *CacheConfig) GetShared() bool { 388 return c.Shared 389 } 390 391 func (c *SessionServer) GetSessionTimeout() time.Duration { 392 if c.SessionTimeout > 0 { 393 return time.Duration(c.SessionTimeout) * time.Second 394 } 395 396 return DefaultSessionTimeout 397 } 398 399 func (c *DockerConfig) GetNanoCPUs() (int64, error) { 400 if c.CPUS == "" { 401 return 0, nil 402 } 403 404 cpu, ok := new(big.Rat).SetString(c.CPUS) 405 if !ok { 406 return 0, fmt.Errorf("failed to parse %v as a rational number", c.CPUS) 407 } 408 409 nano, _ := cpu.Mul(cpu, big.NewRat(1e9, 1)).Float64() 410 411 return int64(nano), nil 412 } 413 414 func (c *DockerConfig) getMemoryBytes(size string, fieldName string) int64 { 415 if size == "" { 416 return 0 417 } 418 419 bytes, err := units.RAMInBytes(size) 420 if err != nil { 421 logrus.Fatalf("Error parsing docker %s: %s", fieldName, err) 422 } 423 424 return bytes 425 } 426 427 func (c *DockerConfig) GetMemory() int64 { 428 return c.getMemoryBytes(c.Memory, "memory") 429 } 430 431 func (c *DockerConfig) GetMemorySwap() int64 { 432 return c.getMemoryBytes(c.MemorySwap, "memory_swap") 433 } 434 435 func (c *DockerConfig) GetMemoryReservation() int64 { 436 return c.getMemoryBytes(c.MemoryReservation, "memory_reservation") 437 } 438 439 func (c *DockerConfig) GetOomKillDisable() *bool { 440 return &c.OomKillDisable 441 } 442 443 func (c *KubernetesConfig) GetPollAttempts() int { 444 if c.PollTimeout <= 0 { 445 c.PollTimeout = KubernetesPollTimeout 446 } 447 448 return c.PollTimeout / c.GetPollInterval() 449 } 450 451 func (c *KubernetesConfig) GetPollInterval() int { 452 if c.PollInterval <= 0 { 453 c.PollInterval = KubernetesPollInterval 454 } 455 456 return c.PollInterval 457 } 458 459 func (c *KubernetesConfig) GetNodeTolerations() []api.Toleration { 460 var tolerations []api.Toleration 461 462 for toleration, effect := range c.NodeTolerations { 463 newToleration := api.Toleration{ 464 Effect: api.TaintEffect(effect), 465 } 466 467 if strings.Contains(toleration, "=") { 468 parts := strings.Split(toleration, "=") 469 newToleration.Key = parts[0] 470 if len(parts) > 1 { 471 newToleration.Value = parts[1] 472 } 473 newToleration.Operator = api.TolerationOpEqual 474 } else { 475 newToleration.Key = toleration 476 newToleration.Operator = api.TolerationOpExists 477 } 478 479 tolerations = append(tolerations, newToleration) 480 } 481 482 return tolerations 483 } 484 485 func (c *KubernetesConfig) GetPodSecurityContext() *api.PodSecurityContext { 486 podSecurityContext := c.PodSecurityContext 487 488 if podSecurityContext.FSGroup == nil && 489 podSecurityContext.RunAsGroup == nil && 490 podSecurityContext.RunAsNonRoot == nil && 491 podSecurityContext.RunAsUser == nil && 492 len(podSecurityContext.SupplementalGroups) == 0 { 493 return nil 494 } 495 496 return &api.PodSecurityContext{ 497 FSGroup: podSecurityContext.FSGroup, 498 RunAsGroup: podSecurityContext.RunAsGroup, 499 RunAsNonRoot: podSecurityContext.RunAsNonRoot, 500 RunAsUser: podSecurityContext.RunAsUser, 501 SupplementalGroups: podSecurityContext.SupplementalGroups, 502 } 503 } 504 505 func (c *DockerMachine) GetIdleCount() int { 506 if c.isOffPeak() { 507 return c.OffPeakIdleCount 508 } 509 510 return c.IdleCount 511 } 512 513 func (c *DockerMachine) GetIdleTime() int { 514 if c.isOffPeak() { 515 return c.OffPeakIdleTime 516 } 517 518 return c.IdleTime 519 } 520 521 func (c *DockerMachine) isOffPeak() bool { 522 if c.offPeakTimePeriods == nil { 523 c.CompileOffPeakPeriods() 524 } 525 526 return c.offPeakTimePeriods != nil && c.offPeakTimePeriods.InPeriod() 527 } 528 529 func (c *DockerMachine) CompileOffPeakPeriods() (err error) { 530 c.offPeakTimePeriods, err = timeperiod.TimePeriods(c.OffPeakPeriods, c.OffPeakTimezone) 531 if err != nil { 532 err = errors.New(fmt.Sprint("Invalid OffPeakPeriods value: ", err)) 533 } 534 535 return 536 } 537 538 func (c *RunnerCredentials) GetURL() string { 539 return c.URL 540 } 541 542 func (c *RunnerCredentials) GetTLSCAFile() string { 543 return c.TLSCAFile 544 } 545 546 func (c *RunnerCredentials) GetTLSCertFile() string { 547 return c.TLSCertFile 548 } 549 550 func (c *RunnerCredentials) GetTLSKeyFile() string { 551 return c.TLSKeyFile 552 } 553 554 func (c *RunnerCredentials) GetToken() string { 555 return c.Token 556 } 557 558 func (c *RunnerCredentials) ShortDescription() string { 559 return helpers.ShortenToken(c.Token) 560 } 561 562 func (c *RunnerCredentials) UniqueID() string { 563 return c.URL + c.Token 564 } 565 566 func (c *RunnerCredentials) Log() *logrus.Entry { 567 if c.ShortDescription() != "" { 568 return logrus.WithField("runner", c.ShortDescription()) 569 } 570 return logrus.WithFields(logrus.Fields{}) 571 } 572 573 func (c *RunnerCredentials) SameAs(other *RunnerCredentials) bool { 574 return c.URL == other.URL && c.Token == other.Token 575 } 576 577 func (c *RunnerConfig) String() string { 578 return fmt.Sprintf("%v url=%v token=%v executor=%v", c.Name, c.URL, c.Token, c.Executor) 579 } 580 581 func (c *RunnerConfig) GetRequestConcurrency() int { 582 if c.RequestConcurrency <= 0 { 583 return 1 584 } 585 return c.RequestConcurrency 586 } 587 588 func (c *RunnerConfig) GetVariables() JobVariables { 589 variables := JobVariables{ 590 {Key: "CI_RUNNER_SHORT_TOKEN", Value: c.ShortDescription(), Public: true, Internal: true, File: false}, 591 } 592 593 for _, environment := range c.Environment { 594 if variable, err := ParseVariable(environment); err == nil { 595 variable.Internal = true 596 variables = append(variables, variable) 597 } 598 } 599 600 return variables 601 } 602 603 // DeepCopy attempts to make a deep clone of the object 604 func (c *RunnerConfig) DeepCopy() (*RunnerConfig, error) { 605 var r RunnerConfig 606 607 bytes, err := json.Marshal(c) 608 if err != nil { 609 return nil, fmt.Errorf("serialization of runner config failed: %v", err) 610 } 611 612 err = json.Unmarshal(bytes, &r) 613 if err != nil { 614 return nil, fmt.Errorf("deserialization of runner config failed: %v", err) 615 } 616 617 return &r, err 618 } 619 620 func NewConfig() *Config { 621 return &Config{ 622 Concurrent: 1, 623 SessionServer: SessionServer{ 624 SessionTimeout: int(DefaultSessionTimeout.Seconds()), 625 }, 626 } 627 } 628 629 func (c *Config) StatConfig(configFile string) error { 630 _, err := os.Stat(configFile) 631 if err != nil { 632 return err 633 } 634 return nil 635 } 636 637 func (c *Config) LoadConfig(configFile string) error { 638 info, err := os.Stat(configFile) 639 640 // permission denied is soft error 641 if os.IsNotExist(err) { 642 return nil 643 } else if err != nil { 644 return err 645 } 646 647 if _, err = toml.DecodeFile(configFile, c); err != nil { 648 return err 649 } 650 651 for _, runner := range c.Runners { 652 if runner.Machine == nil { 653 continue 654 } 655 656 err := runner.Machine.CompileOffPeakPeriods() 657 if err != nil { 658 return err 659 } 660 } 661 662 c.ModTime = info.ModTime() 663 c.Loaded = true 664 return nil 665 } 666 667 func (c *Config) SaveConfig(configFile string) error { 668 var newConfig bytes.Buffer 669 newBuffer := bufio.NewWriter(&newConfig) 670 671 if err := toml.NewEncoder(newBuffer).Encode(c); err != nil { 672 logrus.Fatalf("Error encoding TOML: %s", err) 673 return err 674 } 675 676 if err := newBuffer.Flush(); err != nil { 677 return err 678 } 679 680 // create directory to store configuration 681 err := os.MkdirAll(filepath.Dir(configFile), 0700) 682 if err != nil { 683 return err 684 } 685 686 // write config file 687 if err := ioutil.WriteFile(configFile, newConfig.Bytes(), 0600); err != nil { 688 return err 689 } 690 691 c.Loaded = true 692 return nil 693 } 694 695 func (c *Config) GetCheckInterval() time.Duration { 696 if c.CheckInterval > 0 { 697 return time.Duration(c.CheckInterval) * time.Second 698 } 699 return CheckInterval 700 }