diff --git a/docker_machine.tf b/docker_machine.tf index cd5d255d2..e83324aa6 100644 --- a/docker_machine.tf +++ b/docker_machine.tf @@ -1,41 +1,3 @@ -locals { - template_runner_docker_machine = templatefile("${path.module}/template/runner-docker-machine-config.tftpl", - { - runners_idle_count = var.runner_worker_docker_machine_instance.idle_count - runners_idle_time = var.runner_worker_docker_machine_instance.idle_time - runners_max_builds = local.runners_max_builds_string - docker_machine_name = format("%s-%s", local.runner_tags_merged["Name"], "%s") # %s is always needed - runners_instance_types = var.runner_worker_docker_machine_instance.types - aws_region = data.aws_region.current.name - runners_aws_zone = data.aws_availability_zone.runners.name_suffix - runners_userdata = var.runner_worker_docker_machine_instance.start_script - - runners_vpc_id = var.vpc_id - runners_subnet_id = var.subnet_id - runners_subnet_ids = length(var.runner_worker_docker_machine_instance.subnet_ids) > 0 ? var.runner_worker_docker_machine_instance.subnet_ids : [var.subnet_id] - runners_instance_profile = var.runner_worker.type == "docker+machine" ? aws_iam_instance_profile.docker_machine[0].name : "" - - runners_use_private_address_only = var.runner_worker_docker_machine_instance.private_address_only - runners_use_private_address = !var.runner_worker_docker_machine_instance.private_address_only - runners_request_spot_instance = var.runner_worker_docker_machine_instance_spot.enable - runners_spot_price_bid = var.runner_worker_docker_machine_instance_spot.max_price == "on-demand-price" || var.runner_worker_docker_machine_instance_spot.max_price == null ? "" : var.runner_worker_docker_machine_instance_spot.max_price - runners_security_group_name = var.runner_worker.type == "docker+machine" ? aws_security_group.docker_machine[0].name : "" - - runners_tags = replace(replace(local.runner_tags_string, ",,", ","), "/,$/", "") - runners_ebs_optimized = var.runner_worker_docker_machine_instance.ebs_optimized - runners_monitoring = var.runner_worker_docker_machine_instance.monitoring - runners_iam_instance_profile_name = var.runner_worker_docker_machine_role.profile_name - runners_root_size = var.runner_worker_docker_machine_instance.root_size - runners_volume_type = var.runner_worker_docker_machine_instance.volume_type - runners_ami = var.runner_worker.type == "docker+machine" ? (length(var.runner_worker_docker_machine_ami_id) > 0 ? var.runner_worker_docker_machine_ami_id : data.aws_ami.docker_machine_by_filter[0].id) : "" - use_fleet = var.runner_worker_docker_machine_fleet.enable - launch_template = var.runner_worker_docker_machine_fleet.enable == true ? aws_launch_template.fleet_gitlab_runner[0].name : "" - docker_machine_options = length(local.docker_machine_options_string) == 1 ? "" : local.docker_machine_options_string - runners_max_growth_rate = var.runner_worker_docker_machine_instance.max_growth_rate - runners_volume_kms_key = local.kms_key_arn - }) -} - resource "aws_iam_instance_profile" "docker_machine" { count = var.runner_worker.type == "docker+machine" ? 1 : 0 name = "${local.name_iam_objects}-docker-machine" diff --git a/locals.tf b/locals.tf index a4e089bf0..455048d2c 100644 --- a/locals.tf +++ b/locals.tf @@ -44,27 +44,6 @@ locals { ) aws_iam_role_instance_arn = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:role/${local.aws_iam_role_instance_name}" - # Convert list to a string separated and prepend by a comma - docker_machine_options_string = format( - ",\"amazonec2-metadata-token=${var.runner_worker_docker_machine_ec2_metadata_options.http_tokens}\", \"amazonec2-metadata-token-response-hop-limit=${var.runner_worker_docker_machine_ec2_metadata_options.http_put_response_hop_limit}\",%s", - join(",", formatlist("%q", concat(var.runner_worker_docker_machine_ec2_options, local.runners_docker_registry_mirror_option))), - ) - - runners_docker_registry_mirror_option = var.runner_worker_docker_machine_instance.docker_registry_mirror_url == "" ? [] : ["engine-registry-mirror=${var.runner_worker_docker_machine_instance.docker_registry_mirror_url}"] - - runners_docker_options_toml = templatefile("${path.module}/template/runners_docker_options.tftpl", { - options = merge({ - for key, value in var.runner_worker_docker_options : key => value if value != null && key != "volumes" && key != "pull_policies" - }, { - pull_policy = var.runner_worker_docker_options.pull_policies - volumes = local.runners_volumes - }) - } - ) - - # Ensure max builds is optional - runners_max_builds_string = var.runner_worker_docker_machine_instance.destroy_after_max_builds == 0 ? "" : format("MaxBuilds = %d", var.runner_worker_docker_machine_instance.destroy_after_max_builds) - # Define key for runner token for SSM secure_parameter_store_runner_token_key = "${var.environment}-${var.runner_gitlab_token_secure_parameter_store}" secure_parameter_store_runner_sentry_dsn = "${var.environment}-${var.runner_sentry_secure_parameter_store_name}" @@ -74,24 +53,6 @@ locals { name_sg = var.security_group_prefix == "" ? local.tags["Name"] : var.security_group_prefix name_iam_objects = var.iam_object_prefix == "" ? local.tags["Name"] : var.iam_object_prefix - runners_volumes = concat(var.runner_worker_docker_options.volumes, var.runner_worker_docker_add_dind_volumes ? ["/certs/client", "/builds", "/var/run/docker.sock:/var/run/docker.sock"] : []) - - runners_docker_services = templatefile("${path.module}/template/runners_docker_services.tftpl", { - runners_docker_services = var.runner_worker_docker_services - } - ) - - /* determines if the docker machine executable adds the Name tag automatically (versions >= 0.16.2) */ - # make sure to skip pre-release stuff in the semver by ignoring everything after "-" - docker_machine_version_used = split(".", split("-", var.runner_install.docker_machine_version)[0]) - docker_machine_version_with_name_tag = split(".", "0.16.2") - docker_machine_version_test = [ - for i, j in reverse(range(length(local.docker_machine_version_used))) - : signum(local.docker_machine_version_with_name_tag[i] - local.docker_machine_version_used[i]) * pow(10, j) - ] - - docker_machine_adds_name_tag = signum(sum(local.docker_machine_version_test)) <= 0 - runner_worker_graceful_terminate_heartbeat_timeout = (var.runner_terminate_ec2_lifecycle_timeout_duration == null ? min(7200, tonumber(coalesce(var.runner_gitlab_registration_config.maximum_timeout, 0)) + 300) : var.runner_terminate_ec2_lifecycle_timeout_duration) diff --git a/main.tf b/main.tf index 423a09b00..b9e0ffb2f 100644 --- a/main.tf +++ b/main.tf @@ -1,5 +1,6 @@ # Parameter value is managed by the user-data script of the gitlab runner instance resource "aws_ssm_parameter" "runner_registration_token" { + # checkov:skip=CKV_AWS_337:KMS key can be enabled by the user name = local.secure_parameter_store_runner_token_key type = "SecureString" value = "null" @@ -14,6 +15,7 @@ resource "aws_ssm_parameter" "runner_registration_token" { } resource "aws_ssm_parameter" "runner_sentry_dsn" { + # checkov:skip=CKV_AWS_337:KMS key can be enabled by the user name = local.secure_parameter_store_runner_sentry_dsn type = "SecureString" value = "null" @@ -85,67 +87,63 @@ locals { fleeting_plugin_version = var.runner_worker_docker_autoscaler.fleeting_plugin_version }) - template_runner_docker_autoscaler = templatefile("${path.module}/template/runner-docker-autoscaler-config.tftpl", + template_runner_config = templatefile("${path.module}/template/runner-agent.tftpl", { - docker_autoscaling_name = var.runner_worker.type == "docker-autoscaler" ? aws_autoscaling_group.autoscaler[0].name : "" - connector_config_user = var.runner_worker_docker_autoscaler.connector_config_user - runners_capacity_per_instance = var.runner_worker_docker_autoscaler.capacity_per_instance - runners_max_use_count = var.runner_worker_docker_autoscaler.max_use_count - runners_max_instances = var.runner_worker.max_jobs + prometheus_listen_address = var.runner_manager.prometheus_listen_address + runners_check_interval = var.runner_manager.gitlab_check_interval + runners_concurrent = var.runner_manager.maximum_concurrent_jobs + sentry_dsn = var.runner_manager.sentry_dsn - runners_update_interval = var.runner_worker_docker_autoscaler.update_interval - runners_update_interval_when_expecting = var.runner_worker_docker_autoscaler.update_interval_when_expecting - - runners_instance_ready_command = var.runner_worker_docker_autoscaler.instance_ready_command - - use_private_key = var.runner_worker.use_private_key && var.runner_worker.type == "docker-autoscaler" - - runners_autoscaling = [for config in var.runner_worker_docker_autoscaler_autoscaling_options : { - for key, value in config : - # Convert key from snake_case to PascalCase which is the casing for this section. - key => jsonencode(value) if value != null - }] - }) - - template_runner_config = templatefile("${path.module}/template/runner-config.tftpl", - { - aws_region = data.aws_region.current.name - gitlab_url = var.runner_gitlab.url - gitlab_clone_url = var.runner_gitlab.url_clone - tls_ca_file = length(var.runner_gitlab.certificate) > 0 ? "tls-ca-file=\"/etc/gitlab-runner/certs/gitlab.crt\"" : "" - runners_machine_autoscaling = [for config in var.runner_worker_docker_machine_autoscaling_options : { - for key, value in config : - # Convert key from snake_case to PascalCase which is the casing for this section. - join("", [for subkey in split("_", key) : title(subkey)]) => jsonencode(value) if value != null - }] - - runners_name = var.runner_instance.name - runners_token = var.runner_gitlab.registration_token - runners_executor = var.runner_worker.type - runners_limit = var.runner_worker.max_jobs - runners_concurrent = var.runner_manager.maximum_concurrent_jobs - runners_environment_vars = jsonencode(var.runner_worker.environment_variables) - runners_pre_build_script = var.runner_worker_gitlab_pipeline.pre_build_script - runners_post_build_script = var.runner_worker_gitlab_pipeline.post_build_script - runners_pre_clone_script = var.runner_worker_gitlab_pipeline.pre_clone_script - runners_request_concurrency = var.runner_worker.request_concurrency - runners_output_limit = var.runner_worker.output_limit - runners_check_interval = var.runner_manager.gitlab_check_interval - runners_volumes_tmpfs = join("\n", [for v in var.runner_worker_docker_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) - runners_services_volumes_tmpfs = join("\n", [for v in var.runner_worker_docker_services_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) - runners_docker_services = local.runners_docker_services - runners_docker_options = local.runners_docker_options_toml - bucket_name = local.bucket_name - shared_cache = var.runner_worker_cache.shared - sentry_dsn = var.runner_manager.sentry_dsn - prometheus_listen_address = var.runner_manager.prometheus_listen_address - auth_type = var.runner_worker_cache.authentication_type - runners_docker_autoscaler = var.runner_worker.type == "docker-autoscaler" ? local.template_runner_docker_autoscaler : "" - runners_docker_machine = var.runner_worker.type == "docker+machine" ? local.template_runner_docker_machine : "" + runners = [module.runner.runner_config] } ) } +module "runner" { + source = "./modules/runner-config" + + vpc_id = var.vpc_id + subnet_id = var.subnet_id + + suppressed_tags = var.suppressed_tags + kms_key_arn = local.kms_key_arn + + runner_instance = var.runner_instance + runner_worker = var.runner_worker + runner_install = var.runner_install + runner_gitlab = var.runner_gitlab + + cache = var.runner_worker_cache + cache_bucket_name = local.bucket_name + + gitlab_pipeline = var.runner_worker_gitlab_pipeline + + docker_autoscaler = var.runner_worker_docker_autoscaler + docker_autoscaler_asg_name = var.runner_worker.type == "docker-autoscaler" ? aws_autoscaling_group.autoscaler[0].name : "" + docker_autoscaler_autoscaling_options = var.runner_worker_docker_autoscaler_autoscaling_options + + docker_machine_runner_name = local.runner_tags_merged["Name"] + docker_machine_availability_zone_name = data.aws_availability_zone.runners.name_suffix + docker_machine_instance_profile_name = var.runner_worker.type == "docker+machine" ? aws_iam_instance_profile.docker_machine[0].name : "" + docker_machine_security_group_name = var.runner_worker.type == "docker+machine" ? aws_security_group.docker_machine[0].name : "" + docker_machine_ami_id = data.aws_ami.docker_machine_by_filter[0].id + docker_machine_fleet_launch_template_name = var.runner_worker_docker_machine_fleet.enable == true ? aws_launch_template.fleet_gitlab_runner[0].name : "" + docker_machine_tags = local.runner_tags_merged + docker_machine_instance = var.runner_worker_docker_machine_instance + docker_machine_ec2_options = var.runner_worker_docker_machine_ec2_options + docker_machine_ec2_metadata_options = var.runner_worker_docker_machine_ec2_metadata_options + docker_machine_fleet = var.runner_worker_docker_machine_fleet + docker_machine_role = var.runner_worker_docker_machine_role + docker_machine_instance_spot = var.runner_worker_docker_machine_instance_spot + docker_machine_autoscaling_options = var.runner_worker_docker_machine_autoscaling_options + + docker_add_dind_volumes = var.runner_worker_docker_add_dind_volumes + docker_options = var.runner_worker_docker_options + docker_services = var.runner_worker_docker_services + docker_services_volumes_tmpfs = var.runner_worker_docker_services_volumes_tmpfs + docker_volumes_tmpfs = var.runner_worker_docker_volumes_tmpfs +} + # ignores: Autoscaling Groups Supply Tags --> we use a "dynamic" block to create the tags # ignores: Auto Scaling Group With No Associated ELB --> that's simply not true, as the EC2 instance contacts GitLab. So no ELB needed here. # kics-scan ignore-line diff --git a/modules/runner-config/locals.tf b/modules/runner-config/locals.tf new file mode 100644 index 000000000..7674127db --- /dev/null +++ b/modules/runner-config/locals.tf @@ -0,0 +1,138 @@ +locals { + template_runner_worker_config = templatefile("${path.module}/template/runner-definition.tftpl", + { + aws_region = data.aws_region.current.name + gitlab_url = var.runner_gitlab.url + gitlab_clone_url = var.runner_gitlab.url_clone + tls_ca_file = length(var.runner_gitlab.certificate) > 0 ? "tls-ca-file=\"/etc/gitlab-runner/certs/gitlab.crt\"" : "" + runners_machine_autoscaling = [for config in var.docker_machine_autoscaling_options : { + for key, value in config : + # Convert key from snake_case to PascalCase which is the casing for this section. + join("", [for subkey in split("_", key) : title(subkey)]) => jsonencode(value) if value != null + }] + + runners_name = var.runner_instance.name + runners_token = var.runner_gitlab.registration_token + runners_executor = var.runner_worker.type + runners_limit = var.runner_worker.max_jobs + runners_environment_vars = jsonencode(var.runner_worker.environment_variables) + runners_pre_build_script = var.gitlab_pipeline.pre_build_script + runners_post_build_script = var.gitlab_pipeline.post_build_script + runners_pre_clone_script = var.gitlab_pipeline.pre_clone_script + runners_request_concurrency = var.runner_worker.request_concurrency + runners_output_limit = var.runner_worker.output_limit + runners_volumes_tmpfs = join("\n", [for v in var.docker_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) + runners_services_volumes_tmpfs = join("\n", [for v in var.docker_services_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) + runners_docker_services = local.runners_docker_services + runners_docker_options = local.runners_docker_options_toml + bucket_name = var.cache_bucket_name + shared_cache = var.cache.shared + auth_type = var.cache.authentication_type + runners_docker_autoscaler = var.runner_worker.type == "docker-autoscaler" ? local.template_runner_docker_autoscaler : "" + runners_docker_machine = var.runner_worker.type == "docker+machine" ? local.template_runner_docker_machine : "" + } + ) + + template_runner_docker_autoscaler = templatefile("${path.module}/template/runner-docker-autoscaler-config.tftpl", + { + docker_autoscaling_name = var.docker_autoscaler_asg_name + connector_config_user = var.docker_autoscaler.connector_config_user + runners_capacity_per_instance = var.docker_autoscaler.capacity_per_instance + runners_max_use_count = var.docker_autoscaler.max_use_count + runners_max_instances = var.runner_worker.max_jobs + + runners_update_interval = var.docker_autoscaler.update_interval + runners_update_interval_when_expecting = var.docker_autoscaler.update_interval_when_expecting + + runners_instance_ready_command = var.docker_autoscaler.instance_ready_command + + use_private_key = var.runner_worker.use_private_key && var.runner_worker.type == "docker-autoscaler" + + runners_autoscaling = [for config in var.docker_autoscaler_autoscaling_options : { + for key, value in config : + # Convert key from snake_case to PascalCase which is the casing for this section. + key => jsonencode(value) if value != null + }] + }) + + template_runner_docker_machine = templatefile("${path.module}/template/runner-docker-machine-config.tftpl", + { + runners_idle_count = var.docker_machine_instance.idle_count + runners_idle_time = var.docker_machine_instance.idle_time + runners_max_builds = local.runners_max_builds_string + docker_machine_name = format("%s-%s", var.docker_machine_runner_name, "%s") # the last %s is always needed + runners_instance_types = var.docker_machine_instance.types + aws_region = data.aws_region.current.name + runners_aws_zone = var.docker_machine_availability_zone_name + runners_userdata = var.docker_machine_instance.start_script + + runners_vpc_id = var.vpc_id + runners_subnet_id = var.subnet_id + runners_subnet_ids = length(var.docker_machine_instance.subnet_ids) > 0 ? var.docker_machine_instance.subnet_ids : [var.subnet_id] + runners_instance_profile = var.docker_machine_availability_zone_name + + runners_use_private_address_only = var.docker_machine_instance.private_address_only + runners_use_private_address = !var.docker_machine_instance.private_address_only + runners_request_spot_instance = var.docker_machine_instance_spot.enable + runners_spot_price_bid = var.docker_machine_instance_spot.max_price == "on-demand-price" || var.docker_machine_instance_spot.max_price == null ? "" : var.docker_machine_instance_spot.max_price + runners_security_group_name = var.docker_machine_security_group_name + + runners_tags = replace(replace(local.runner_tags_string, ",,", ","), "/,$/", "") + runners_ebs_optimized = var.docker_machine_instance.ebs_optimized + runners_monitoring = var.docker_machine_instance.monitoring + runners_iam_instance_profile_name = var.docker_machine_role.profile_name + runners_root_size = var.docker_machine_instance.root_size + runners_volume_type = var.docker_machine_instance.volume_type + runners_ami = var.runner_worker.type == "docker+machine" ? (length(var.docker_machine_ami_id) > 0 ? var.docker_machine_ami_id : var.docker_machine_ami_id) : "" + use_fleet = var.docker_machine_fleet.enable + launch_template = var.docker_machine_fleet_launch_template_name + docker_machine_options = length(local.docker_machine_options_string) == 1 ? "" : local.docker_machine_options_string + runners_max_growth_rate = var.docker_machine_instance.max_growth_rate + runners_volume_kms_key = var.kms_key_arn + }) + + runners_docker_services = templatefile("${path.module}/template/runners_docker_services.tftpl", { + runners_docker_services = var.docker_services + } + ) + + runners_docker_options_toml = templatefile("${path.module}/template/runners_docker_options.tftpl", { + options = merge({ + for key, value in var.docker_options : key => value if value != null && key != "volumes" && key != "pull_policies" + }, { + pull_policy = var.docker_options.pull_policies + volumes = local.runners_volumes + }) + } + ) + + # Convert list to a string separated and prepend by a comma + docker_machine_options_string = format( + ",\"amazonec2-metadata-token=${var.docker_machine_ec2_metadata_options.http_tokens}\", \"amazonec2-metadata-token-response-hop-limit=${var.docker_machine_ec2_metadata_options.http_put_response_hop_limit}\",%s", + join(",", formatlist("%q", concat(var.docker_machine_ec2_options, local.runners_docker_registry_mirror_option))), + ) + + runners_volumes = concat(var.docker_options.volumes, var.docker_add_dind_volumes ? ["/certs/client", "/builds", "/var/run/docker.sock:/var/run/docker.sock"] : []) + + runner_tags_string = join(",", flatten([ + for key in keys(local.runner_tags) : [key, local.runner_tags[key]] + ])) + + # remove the `Name` tag in addition if docker+machine adds one to avoid a failure due to a duplicate `Name` tag + runner_tags = local.docker_machine_adds_name_tag ? { for k, v in var.docker_machine_tags : k => v if !contains(concat(var.suppressed_tags, ["Name"]), k) } : var.docker_machine_tags + + # Ensure max builds is optional + runners_max_builds_string = var.docker_machine_instance.destroy_after_max_builds == 0 ? "" : format("MaxBuilds = %d", var.docker_machine_instance.destroy_after_max_builds) + + runners_docker_registry_mirror_option = var.docker_machine_instance.docker_registry_mirror_url == "" ? [] : ["engine-registry-mirror=${var.docker_machine_instance.docker_registry_mirror_url}"] + docker_machine_adds_name_tag = signum(sum(local.docker_machine_version_test)) <= 0 + docker_machine_version_test = [ + for i, j in reverse(range(length(local.docker_machine_version_used))) + : signum(local.docker_machine_version_with_name_tag[i] - local.docker_machine_version_used[i]) * pow(10, j) + ] + + /* determines if the docker machine executable adds the Name tag automatically (versions >= 0.16.2) */ + # make sure to skip pre-release stuff in the semver by ignoring everything after "-" + docker_machine_version_used = split(".", split("-", var.runner_install.docker_machine_version)[0]) + docker_machine_version_with_name_tag = split(".", "0.16.2") +} diff --git a/modules/runner-config/main.tf b/modules/runner-config/main.tf new file mode 100644 index 000000000..2502393bf --- /dev/null +++ b/modules/runner-config/main.tf @@ -0,0 +1 @@ +data "aws_region" "current" {} diff --git a/modules/runner-config/outputs.tf b/modules/runner-config/outputs.tf new file mode 100644 index 000000000..e0c47c7e1 --- /dev/null +++ b/modules/runner-config/outputs.tf @@ -0,0 +1,4 @@ +output "runner_config" { + value = "" + description = "Runner configuration in TOML format for the agent's configuration file" +} diff --git a/template/runner-config.tftpl b/modules/runner-config/template/runner-definition.tftpl similarity index 88% rename from template/runner-config.tftpl rename to modules/runner-config/template/runner-definition.tftpl index aabf0f3de..97d53f1b2 100644 --- a/template/runner-config.tftpl +++ b/modules/runner-config/template/runner-definition.tftpl @@ -1,9 +1,3 @@ -concurrent = ${runners_concurrent} -check_interval = ${runners_check_interval} -sentry_dsn = "${sentry_dsn}" -log_format = "json" -listen_address = "${prometheus_listen_address}" - [[runners]] name = "${runners_name}" url = "${gitlab_url}" @@ -51,4 +45,3 @@ listen_address = "${prometheus_listen_address}" ${key} = ${value} %{~ endfor ~} %{~ endfor ~} - diff --git a/template/runner-docker-autoscaler-config.tftpl b/modules/runner-config/template/runner-docker-autoscaler-config.tftpl similarity index 100% rename from template/runner-docker-autoscaler-config.tftpl rename to modules/runner-config/template/runner-docker-autoscaler-config.tftpl diff --git a/template/runner-docker-machine-config.tftpl b/modules/runner-config/template/runner-docker-machine-config.tftpl similarity index 100% rename from template/runner-docker-machine-config.tftpl rename to modules/runner-config/template/runner-docker-machine-config.tftpl diff --git a/template/runners_docker_options.tftpl b/modules/runner-config/template/runners_docker_options.tftpl similarity index 100% rename from template/runners_docker_options.tftpl rename to modules/runner-config/template/runners_docker_options.tftpl diff --git a/template/runners_docker_services.tftpl b/modules/runner-config/template/runners_docker_services.tftpl similarity index 100% rename from template/runners_docker_services.tftpl rename to modules/runner-config/template/runners_docker_services.tftpl diff --git a/modules/runner-config/variables.tf b/modules/runner-config/variables.tf new file mode 100644 index 000000000..cd68b3147 --- /dev/null +++ b/modules/runner-config/variables.tf @@ -0,0 +1,386 @@ +variable "docker_machine_tags" { + description = "The tags to apply to the docker machine." + type = map(string) +} + +variable "docker_machine_fleet_launch_template_name" { + description = "The name of the launch template for the docker machine fleet." + type = string +} + +variable "docker_machine_security_group_name" { + description = "The name of the security group for the docker machine." + type = string +} + +variable "docker_machine_instance_profile_name" { + description = "The name of the instance profile for the docker machine." + type = string +} + +variable "docker_machine_availability_zone_name" { + description = "The name of the availability zone for the docker machine." + type = string +} + +variable "docker_machine_runner_name" { + description = "The name of the instance." + type = string +} + +variable "docker_autoscaler_asg_name" { + description = "The name of the autoscaling group for the docker autoscaler." + type = string +} + +variable "cache_bucket_name" { + description = "The name of the S3 bucket to use for caching." + type = string +} + +variable "kms_key_arn" { + description = "The ARN of the KMS key to use for encrypting everything." + type = string +} + +# false positive, use_private_key is not a secret +# kics-scan ignore-block +variable "runner_worker" { + description = <<-EOT + For detailed information, check https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section. + + environment_variables = List of environment variables to add to the Runner Worker (environment). + max_jobs = Number of jobs which can be processed in parallel by the Runner Worker. + output_limit = Sets the maximum build log size in kilobytes. Default is 4MB (output_limit). + request_concurrency = Limit number of concurrent requests for new jobs from GitLab (default 1) (request_concurrency). + ssm_access = Allows to connect to the Runner Worker via SSM. + type = The Runner Worker type to use. Currently supports `docker+machine` or `docker` or `docker-autoscaler`. + use_private_key = Use a private key to connect the Runner Manager to the Runner Workers. Ignored when fleeting is enabled (defaults to `true`). + EOT + type = object({ + environment_variables = optional(list(string), []) + max_jobs = optional(number, 0) + output_limit = optional(number, 4096) + request_concurrency = optional(number, 1) + ssm_access = optional(bool, false) + type = optional(string, "docker+machine") + use_private_key = optional(bool, false) + }) +} + +variable "docker_autoscaler" { + description = <<-EOT + fleeting_plugin_version = The version of aws fleeting plugin. + connector_config_user = User to connect to worker machine. + key_pair_name = The name of the key pair used by the Runner to connect to the docker-machine Runner Workers. This variable is only supported when `enables` is set to `true`. + capacity_per_instance = The number of jobs that can be executed concurrently by a single instance. + max_use_count = Max job number that can run on a worker. + update_interval = The interval to check with the fleeting plugin for instance updates. + update_interval_when_expecting = The interval to check with the fleeting plugin for instance updates when expecting a state change. + instance_ready_command = Executes this command on each instance provisioned by the autoscaler to ensure that it is ready for use. A failure results in the instance being removed. + EOT + type = object({ + fleeting_plugin_version = optional(string, "1.0.0") + connector_config_user = optional(string, "ec2-user") + key_pair_name = optional(string, "runner-worker-key") + capacity_per_instance = optional(number, 1) + max_use_count = optional(number, 100) + update_interval = optional(string, "1m") + update_interval_when_expecting = optional(string, "2s") + instance_ready_command = optional(string, "") + }) +} + +variable "gitlab_pipeline" { + description = <<-EOT + post_build_script = Script to execute in the pipeline just after the build, but before executing after_script. + pre_build_script = Script to execute in the pipeline just before the build. + pre_clone_script = Script to execute in the pipeline before cloning the Git repository. this can be used to adjust the Git client configuration first, for example. + EOT + type = object({ + post_build_script = optional(string, "\"\"") + pre_build_script = optional(string, "\"\"") + pre_clone_script = optional(string, "\"\"") + }) +} + +# false positive, registration_token has no secret value here +# kics-scan ignore-block +variable "runner_gitlab" { + description = <<-EOT + certificate = Certificate of the GitLab instance to connect to (PEM format). + registration_token = (deprecated, This is replaced by the `registration_token` in `runner_gitlab_registration_config`.) Registration token to use to register the Runner. + url = URL of the GitLab instance to connect to. + url_clone = URL of the GitLab instance to clone from. Use only if the agent can’t connect to the GitLab URL. + EOT + type = object({ + certificate = optional(string, "") + registration_token = optional(string, "__REPLACED_BY_USER_DATA__") # deprecated, removed in 8.0.0 + url = optional(string, "") + url_clone = optional(string, "") + }) +} + +variable "docker_machine_autoscaling_options" { + description = "Set autoscaling parameters based on periods, see https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section" + type = list(object({ + periods = list(string) + idle_count = optional(number) + idle_scale_factor = optional(number) + idle_count_min = optional(number) + idle_time = optional(number) + timezone = optional(string, "UTC") + })) +} + +variable "runner_instance" { + description = <<-EOT + name = Name of the Runner instance. + EOT + type = object({ + name = string + }) +} + +variable "docker_volumes_tmpfs" { + description = "Mount a tmpfs in Executor container. https://docs.gitlab.com/runner/executors/docker.html#mounting-a-directory-in-ram" + type = list(object({ + volume = string + options = string + })) +} + +variable "docker_services_volumes_tmpfs" { + description = "Mount a tmpfs in gitlab service container. https://docs.gitlab.com/runner/executors/docker.html#mounting-a-directory-in-ram" + type = list(object({ + volume = string + options = string + })) +} + +variable "cache" { + description = <<-EOT + Configuration to control the creation of the cache bucket. By default the bucket will be created and used as shared + cache. To use the same cache across multiple Runner Worker disable the creation of the cache and provide a policy and + bucket name. See the public runner example for more details." + + For detailed documentation check https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section. + + authentication_type = A string that declares the AuthenticationType for [runners.cache.s3]. Can either be 'iam' or 'credentials'. + shared = Boolean used to enable or disable the use of the cache bucket as shared cache. + EOT + type = object({ + authentication_type = optional(string, "iam") + shared = optional(bool, false) + }) +} + +variable "docker_autoscaler_autoscaling_options" { + description = "Set autoscaling parameters based on periods, see https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersautoscalerpolicy-sections" + type = list(object({ + periods = list(string) + timezone = optional(string, "UTC") + idle_count = optional(number) + idle_time = optional(string) + scale_factor = optional(number) + scale_factor_limit = optional(number, 0) + })) +} + +variable "docker_machine_instance_spot" { + description = <<-EOT + enable = Enable spot instances for the Runner Worker. + max_price = The maximum price willing to pay. By default the price is limited by the current on demand price for the instance type chosen. + EOT + type = object({ + enable = optional(bool, true) + max_price = optional(string, "on-demand-price") + }) +} + +variable "docker_machine_role" { + description = <<-EOT + profile_name = Name of the IAM profile to attach to the Runner Workers. + EOT + type = object({ + profile_name = optional(string, "") + }) +} + +variable "docker_machine_fleet" { + description = <<-EOT + enable = Activates the fleet mode on the Runner. https://gitlab.com/cki-project/docker-machine/-/blob/v0.16.2-gitlab.19-cki.2/docs/drivers/aws.md#fleet-mode + key_pair_name = The name of the key pair used by the Runner to connect to the docker-machine Runner Workers. This variable is only supported when `enables` is set to `true`. + EOT + type = object({ + enable = bool + }) +} + +variable "docker_services" { + description = "Starts additional services with the Docker container. All fields must be set (examine the Dockerfile of the service image for the entrypoint - see ./examples/runner-default/main.tf)" + type = list(object({ + name = string + alias = string + entrypoint = list(string) + command = list(string) + })) +} + +variable "docker_options" { + description = < v if !contains(concat(var.suppressed_tags, ["Name"]), k) } : local.runner_tags_merged - - runner_tags_string = join(",", flatten([ - for key in keys(local.runner_tags) : [key, local.runner_tags[key]] - ])) } diff --git a/template/runner-agent.tftpl b/template/runner-agent.tftpl new file mode 100644 index 000000000..dd8141701 --- /dev/null +++ b/template/runner-agent.tftpl @@ -0,0 +1,9 @@ +concurrent = ${runners_concurrent} +check_interval = ${runners_check_interval} +sentry_dsn = "${sentry_dsn}" +log_format = "json" +listen_address = "${prometheus_listen_address}" + +́%{ for runner_config in runners } +${runner_config} +%{ endfor } diff --git a/variables.tf b/variables.tf index 3092ce92e..91950cec8 100644 --- a/variables.tf +++ b/variables.tf @@ -471,9 +471,7 @@ variable "runner_worker" { request_concurrency = optional(number, 1) ssm_access = optional(bool, false) type = optional(string, "docker+machine") - # false positive, use_private_key is not a secret - # kics-scan ignore-line - use_private_key = optional(bool, false) + use_private_key = optional(bool, false) }) default = {}