diff --git a/.cspell.json b/.cspell.json index 877c3e397..15b42a6cb 100644 --- a/.cspell.json +++ b/.cspell.json @@ -18,9 +18,13 @@ "codeowners", "companys", "concat", + "cpu", + "cpus", + "cpuset", "devskim", "dind", "endfor", + "filesha", "formatlist", "gitter", "glrunners", @@ -45,6 +49,8 @@ "stretchr", "subkey", "substr", + "sysctl", + "sysctls", "templatefile", "terrascan", "terratest", @@ -58,7 +64,9 @@ "trivy", "typecheck", "userdata", - "xanzy" + "userns", + "xanzy", + "xvda" ], "flagWords": [] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d40a29f15..8fa97be2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,8 @@ jobs: run: tflint --init - name: Run TFLint - run: tflint + # assign necessary variables to avoid errors + run: "tflint --var='runner_instance={\"name_prefix\": \"a\", \"name\": \"b\"}'" tfsec: name: tfsec PR commenter diff --git a/.mega-linter.yml b/.mega-linter.yml index a529a0722..be1a8a09f 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -4,6 +4,8 @@ DISABLE_LINTERS: - TERRAFORM_TFLINT # Super slow linter, but useful. We disable it here and run it in parallel to Megalinter saves some minutes. - TERRAFORM_KICS + # has issues with the Terraform code `optional` variable definitions: https://github.com/tenable/terrascan/issues/1532 + - TERRAFORM_TERRASCAN # Nice linter to report CVEs and other cool stuff. But it reports problems with the Terraform code which can't be disabled by # configuration. - REPOSITORY_TRIVY diff --git a/README.md b/README.md index 28d2081ff..c845557d5 100644 --- a/README.md +++ b/README.md @@ -386,13 +386,12 @@ module "runner" { Since spot instances can be taken over by AWS depending on the instance type and AZ you are using, you may want multiple instances types in multiple AZs. This is where spot fleets come in, when there is no capacity on one instance type and one AZ, AWS will take -the next instance type and so on. This update has been possible since the [fork](https://gitlab.com/cki-project/docker-machine/-/tree/v0.16.2-gitlab.19-cki.2) -of docker-machine supports spot fleets. +the next instance type and so on. This update has been possible since the +[fork](https://gitlab.com/cki-project/docker-machine/-/tree/v0.16.2-gitlab.19-cki.2) of docker-machine supports spot fleets. We have seen that the [fork](https://gitlab.com/cki-project/docker-machine/-/tree/v0.16.2-gitlab.19-cki.2) of docker-machine this -module is using consume more RAM using spot fleets. -For comparison, if you launch 50 machines in the same time, it consumes ~1.2GB of RAM. In our case, we had to change the -`instance_type` of the runner from `t3.micro` to `t3.small`. +module is using consume more RAM using spot fleets. For comparison, if you launch 50 machines in the same time, it consumes +~1.2GB of RAM. In our case, we had to change the `instance_type` of the runner from `t3.micro` to `t3.small`. #### Configuration example diff --git a/examples/runner-certificates/README.md b/examples/runner-certificates/README.md index acbbf273a..f22f46a65 100644 --- a/examples/runner-certificates/README.md +++ b/examples/runner-certificates/README.md @@ -32,20 +32,24 @@ Create a PEM-encoded `.crt` file containing the public certificate of your Gitla ```hcl module { - ... + # ... # Public cert of my companys gitlab instance - runners_gitlab_certificate = file("${path.module}/my_gitlab_instance_cert.crt") - ... + runner_gitlab = { + certificate = file("${path.module}/my_gitlab_instance_cert.crt") + } + # ... } ``` Add your CA and intermediary certs to a second PEM-encoded `.crt` file. ```hcl module { - ... + # ... # Other public certs relating to my company. - runners_ca_certificate = file("${path.module}/my_company_ca_cert_bundle.crt") - ... + runner_gitlab = { + ca_certificate = file("${path.module}/my_company_ca_cert_bundle.crt") + } + # ... } ``` @@ -58,15 +62,17 @@ For **user images**, you must: The runner module can be configured to do this step. Configure the module like so: ```terraform - module { + module "runner" { # ... # Mount EC2 host certs in docker so all user docker images can reference them. - runners_additional_volumes = ["/etc/gitlab-runner/certs/:/etc/gitlab-runner/certs:ro"] - - # ... + runner_worker_docker_options = { + volumes = ["/etc/gitlab-runner/certs/:/etc/gitlab-runner/certs:ro"] } - ``` + + # ... + } + ``` 2. Trust the certificates from within the user image. @@ -107,17 +113,18 @@ For **user images**, you must: This avoids maintaining the script in each pipeline file, but expects that all user images use the same OS. ```terraform - module { + module "runner" { # ... - runners_pre_build_script = < 0 ? var.kms_deletion_window_in_days : null - enable_key_rotation = var.kms_deletion_window_in_days > 0 ? true : false + deletion_window_in_days = var.kms_managed_deletion_rotation_window_in_days > 0 ? var.kms_managed_deletion_rotation_window_in_days : null + enable_key_rotation = var.kms_managed_deletion_rotation_window_in_days > 0 ? true : false tags = local.tags policy = templatefile("${path.module}/policies/kms-policy.json", { partition = data.aws_partition.current.partition - aws_region = var.aws_region + aws_region = data.aws_region.current.name account_id = data.aws_caller_identity.current.account_id } ) } resource "aws_kms_alias" "default" { - count = var.enable_kms && var.kms_alias_name != "" ? 1 : 0 - name = "alias/${var.kms_alias_name}" + count = var.enable_managed_kms_key && var.kms_managed_alias_name != "" ? 1 : 0 + name = "alias/${var.kms_managed_alias_name}" target_key_id = aws_kms_key.default[0].key_id } diff --git a/locals.tf b/locals.tf index 3d750667c..179dcff95 100644 --- a/locals.tf +++ b/locals.tf @@ -1,21 +1,21 @@ locals { # Manage certificates pre_install_gitlab_certificate = ( - length(var.runners_gitlab_certificate) > 0 + length(var.runner_gitlab.certificate) > 0 ? <<-EOT mkdir -p /etc/gitlab-runner/certs/ cat <<- EOF > /etc/gitlab-runner/certs/gitlab.crt - ${var.runners_gitlab_certificate} + ${var.runner_gitlab.certificate} EOF EOT : "" ) pre_install_ca_certificate = ( - length(var.runners_ca_certificate) > 0 + length(var.runner_gitlab.ca_certificate) > 0 ? <<-EOT mkdir -p /etc/gitlab-runner/certs/ cat <<- EOF > /etc/gitlab-runner/certs/ca.crt - ${var.runners_ca_certificate} + ${var.runner_gitlab.ca_certificate} EOF EOT : "" @@ -28,7 +28,7 @@ locals { EOT pre_install_certificates = ( # If either (or both) _certificate variables are specified - length(var.runners_gitlab_certificate) + length(var.runners_ca_certificate) > 0 + length(var.runner_gitlab.certificate) + length(var.runner_gitlab.ca_certificate) > 0 ? join("\n", [ local.pre_install_gitlab_certificate, local.pre_install_ca_certificate, @@ -39,51 +39,52 @@ locals { # Determine IAM role for runner instance aws_iam_role_instance_name = coalesce( - var.runner_iam_role_name, + var.runner_role.role_profile_name, "${local.name_iam_objects}-instance" ) 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.docker_machine_instance_metadata_options.http_tokens}\", \"amazonec2-metadata-token-response-hop-limit=${var.docker_machine_instance_metadata_options.http_put_response_hop_limit}\",%s", - join(",", formatlist("%q", concat(var.docker_machine_options, local.runners_docker_registry_mirror_option))), + ",\"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.runners_docker_registry_mirror == "" ? [] : ["engine-registry-mirror=${var.runners_docker_registry_mirror}"] + 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.runners_docker_options : key => value if value != null && key != "volumes" + for key, value in var.runner_worker_docker_options : key => value if value != null && key != "volumes" }, { volumes = local.runners_volumes }) } ) - # Ensure max builds is optional - runners_max_builds_string = var.runners_max_builds == 0 ? "" : format("MaxBuilds = %d", var.runners_max_builds) + 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.secure_parameter_store_runner_token_key}" - secure_parameter_store_runner_sentry_dsn = "${var.environment}-${var.secure_parameter_store_runner_sentry_dsn}" + 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}" # Custom names for runner agent instance, security groups, and IAM objects - name_runner_agent_instance = var.overrides["name_runner_agent_instance"] == "" ? local.tags["Name"] : var.overrides["name_runner_agent_instance"] - name_sg = var.overrides["name_sg"] == "" ? local.tags["Name"] : var.overrides["name_sg"] - name_iam_objects = lookup(var.overrides, "name_iam_objects", "") == "" ? local.tags["Name"] : var.overrides["name_iam_objects"] + name_runner_agent_instance = var.runner_instance.name_prefix == "" ? local.tags["Name"] : var.runner_instance.name_prefix + 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.runners_docker_options.volumes, var.runners_add_dind_volumes ? ["/certs/client", "/builds", "/var/run/docker.sock:/var/run/docker.sock"] : []) + 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.runners_docker_services + runners_docker_services = var.runner_worker_docker_services } ) + runners_pull_policies = "[\"${join("\",\"", var.runner_worker_docker_options.pull_policies)}\"]" + /* 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.docker_machine_version)[0]) + 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))) @@ -94,13 +95,15 @@ locals { } resource "local_file" "config_toml" { - count = var.debug.output_runner_config_to_file ? 1 : 0 + count = var.debug.write_runner_config_to_file ? 1 : 0 + content = local.template_runner_config filename = "${path.root}/debug/${local.name_runner_agent_instance}/runner_config.toml" } resource "local_file" "user_data" { - count = var.debug.output_runner_user_data_to_file ? 1 : 0 + count = var.debug.write_runner_user_data_to_file ? 1 : 0 + content = local.template_user_data filename = "${path.root}/debug/${local.name_runner_agent_instance}/user_data.sh" } diff --git a/logging.tf b/logging.tf index d63c597d7..62ccfde1f 100644 --- a/logging.tf +++ b/logging.tf @@ -1,25 +1,25 @@ resource "aws_iam_role_policy" "instance" { - count = var.enable_cloudwatch_logging && var.create_runner_iam_role ? 1 : 0 + count = var.runner_cloudwatch.enable && var.runner_role.create_role_profile ? 1 : 0 name = "${local.name_iam_objects}-logging" - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy = templatefile("${path.module}/policies/instance-logging-policy.json", { partition = data.aws_partition.current.partition }) } locals { logging_user_data = templatefile("${path.module}/template/logging.tftpl", { - log_group_name = var.log_group_name != null ? var.log_group_name : var.environment + log_group_name = var.runner_cloudwatch.log_group_name != null ? var.runner_cloudwatch.log_group_name : var.environment }) provided_kms_key = var.kms_key_id != "" ? var.kms_key_id : "" - kms_key = local.provided_kms_key == "" && var.enable_kms ? aws_kms_key.default[0].arn : local.provided_kms_key + kms_key = local.provided_kms_key == "" && var.enable_managed_kms_key ? aws_kms_key.default[0].arn : local.provided_kms_key } resource "aws_cloudwatch_log_group" "environment" { - count = var.enable_cloudwatch_logging ? 1 : 0 - name = var.log_group_name != null ? var.log_group_name : var.environment + count = var.runner_cloudwatch.enable ? 1 : 0 + name = var.runner_cloudwatch.log_group_name != null ? var.runner_cloudwatch.log_group_name : var.environment # ignores a false positive: retention_in_days not set # kics-scan ignore-line - retention_in_days = var.cloudwatch_logging_retention_in_days + retention_in_days = var.runner_cloudwatch.retention_days tags = local.tags # ignored as decided by the user diff --git a/main.tf b/main.tf index 68c0ee056..89e31d1f4 100644 --- a/main.tf +++ b/main.tf @@ -1,5 +1,6 @@ data "aws_caller_identity" "current" {} data "aws_partition" "current" {} +data "aws_region" "current" {} data "aws_subnet" "runners" { id = var.subnet_id @@ -37,12 +38,12 @@ resource "aws_ssm_parameter" "runner_sentry_dsn" { locals { template_user_data = templatefile("${path.module}/template/user-data.tftpl", { - eip = var.enable_eip ? local.template_eip : "" - logging = var.enable_cloudwatch_logging ? local.logging_user_data : "" + eip = var.runner_instance.use_eip ? local.template_eip : "" + logging = var.runner_cloudwatch.enable ? local.logging_user_data : "" gitlab_runner = local.template_gitlab_runner - user_data_trace_log = var.enable_runner_user_data_trace_log - yum_update = var.runner_yum_update ? local.file_yum_update : "" - extra_config = var.runner_extra_config + user_data_trace_log = var.debug.trace_runner_user_data + yum_update = var.runner_install.yum_update ? local.file_yum_update : "" + extra_config = var.runner_install.start_script }) file_yum_update = file("${path.module}/template/yum_update.tftpl") @@ -53,128 +54,128 @@ locals { template_gitlab_runner = templatefile("${path.module}/template/gitlab-runner.tftpl", { - gitlab_runner_version = var.gitlab_runner_version - docker_machine_version = var.docker_machine_version - docker_machine_download_url = var.docker_machine_download_url + gitlab_runner_version = var.runner_gitlab.runner_version + docker_machine_version = var.runner_install.docker_machine_version + docker_machine_download_url = var.runner_install.docker_machine_download_url runners_config = local.template_runner_config - runners_userdata = var.runners_userdata - runners_executor = var.runners_executor - runners_install_amazon_ecr_credential_helper = var.runners_install_amazon_ecr_credential_helper - curl_cacert = length(var.runners_gitlab_certificate) > 0 ? "--cacert /etc/gitlab-runner/certs/gitlab.crt" : "" + runners_userdata = var.runner_worker_docker_machine_instance.start_script + runners_executor = var.runner_worker.type + runners_install_amazon_ecr_credential_helper = var.runner_install.amazon_ecr_credential_helper + curl_cacert = length(var.runner_gitlab.certificate) > 0 ? "--cacert /etc/gitlab-runner/certs/gitlab.crt" : "" pre_install_certificates = local.pre_install_certificates - pre_install = var.userdata_pre_install - post_install = var.userdata_post_install - runners_gitlab_url = var.runners_gitlab_url - runners_token = var.runners_token + pre_install = var.runner_install.pre_install_script + post_install = var.runner_install.post_install_script + runners_gitlab_url = var.runner_gitlab.url + runners_token = var.runner_gitlab.registration_token + secure_parameter_store_gitlab_runner_registration_token_name = var.runner_gitlab_registration_token_secure_parameter_store_name secure_parameter_store_runner_token_key = local.secure_parameter_store_runner_token_key secure_parameter_store_runner_sentry_dsn = local.secure_parameter_store_runner_sentry_dsn - secure_parameter_store_gitlab_runner_registration_token_name = var.secure_parameter_store_gitlab_runner_registration_token_name - secure_parameter_store_region = var.aws_region - gitlab_runner_registration_token = lookup(var.gitlab_runner_registration_config, "registration_token", "__GITLAB_REGISTRATION_TOKEN_FROM_SSM__") - gitlab_runner_description = var.gitlab_runner_registration_config["description"] - gitlab_runner_tag_list = var.gitlab_runner_registration_config["tag_list"] - gitlab_runner_locked_to_project = var.gitlab_runner_registration_config["locked_to_project"] - gitlab_runner_run_untagged = var.gitlab_runner_registration_config["run_untagged"] - gitlab_runner_maximum_timeout = var.gitlab_runner_registration_config["maximum_timeout"] - gitlab_runner_access_level = lookup(var.gitlab_runner_registration_config, "access_level", "not_protected") - sentry_dsn = var.sentry_dsn - public_key = var.use_fleet == true ? tls_private_key.fleet[0].public_key_openssh : "" - use_fleet = var.use_fleet - private_key = var.use_fleet == true ? tls_private_key.fleet[0].private_key_pem : "" + secure_parameter_store_region = data.aws_region.current.name + gitlab_runner_registration_token = lookup(var.runner_gitlab_registration_config, "registration_token", "__GITLAB_REGISTRATION_TOKEN_FROM_SSM__") + gitlab_runner_description = var.runner_gitlab_registration_config["description"] + gitlab_runner_tag_list = var.runner_gitlab_registration_config["tag_list"] + gitlab_runner_locked_to_project = var.runner_gitlab_registration_config["locked_to_project"] + gitlab_runner_run_untagged = var.runner_gitlab_registration_config["run_untagged"] + gitlab_runner_maximum_timeout = var.runner_gitlab_registration_config["maximum_timeout"] + gitlab_runner_access_level = lookup(var.runner_gitlab_registration_config, "access_level", "not_protected") + sentry_dsn = var.runner_manager.sentry_dsn + public_key = var.runner_worker_docker_machine_fleet.enable == true ? tls_private_key.fleet[0].public_key_openssh : "" + use_fleet = var.runner_worker_docker_machine_fleet.enable + private_key = var.runner_worker_docker_machine_fleet.enable == true ? tls_private_key.fleet[0].private_key_pem : "" }) template_runner_config = templatefile("${path.module}/template/runner-config.tftpl", { - runners_machine_autoscaling = [for config in var.runners_machine_autoscaling_options : { + 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 }] - - aws_region = var.aws_region - gitlab_url = var.runners_gitlab_url - gitlab_clone_url = var.runners_clone_url - tls_ca_file = length(var.runners_gitlab_certificate) > 0 ? "tls-ca-file=\"/etc/gitlab-runner/certs/gitlab.crt\"" : "" runners_vpc_id = var.vpc_id runners_subnet_id = var.subnet_id - runners_subnet_ids = length(var.fleet_executor_subnet_ids) > 0 ? var.fleet_executor_subnet_ids : [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_aws_zone = data.aws_availability_zone.runners.name_suffix - runners_instance_type = var.docker_machine_instance_type - runners_instance_types = length(var.docker_machine_instance_types_fleet) > 0 ? var.docker_machine_instance_types_fleet : [var.docker_machine_instance_type] - runners_spot_price_bid = var.docker_machine_spot_price_bid == "on-demand-price" || var.docker_machine_spot_price_bid == null ? "" : var.docker_machine_spot_price_bid - runners_ami = var.runners_executor == "docker+machine" ? data.aws_ami.docker-machine[0].id : "" - runners_security_group_name = var.runners_executor == "docker+machine" ? aws_security_group.docker_machine[0].name : "" - runners_monitoring = var.runners_monitoring - runners_ebs_optimized = var.runners_ebs_optimized - runners_instance_profile = var.runners_executor == "docker+machine" ? aws_iam_instance_profile.docker_machine[0].name : "" + runners_instance_types = var.runner_worker_docker_machine_instance.types + 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_ami = var.runner_worker.type == "docker+machine" ? data.aws_ami.docker-machine[0].id : "" + runners_security_group_name = var.runner_worker.type == "docker+machine" ? aws_security_group.docker_machine[0].name : "" + runners_monitoring = var.runner_worker_docker_machine_instance.monitoring + runners_ebs_optimized = var.runner_worker_docker_machine_instance.ebs_optimized + runners_instance_profile = var.runner_worker.type == "docker+machine" ? aws_iam_instance_profile.docker_machine[0].name : "" docker_machine_options = length(local.docker_machine_options_string) == 1 ? "" : local.docker_machine_options_string docker_machine_name = format("%s-%s", local.runner_tags_merged["Name"], "%s") # %s is always needed - runners_name = var.runners_name + runners_name = var.runner_instance.name runners_tags = replace(replace(local.runner_tags_string, ",,", ","), "/,$/", "") - runners_token = var.runners_token - runners_userdata = var.runners_userdata - runners_executor = var.runners_executor - runners_limit = var.runners_limit - runners_concurrent = var.runners_concurrent - runners_idle_count = var.runners_idle_count - runners_idle_time = var.runners_idle_time + runners_token = var.runner_gitlab.registration_token + runners_userdata = var.runner_worker_docker_machine_instance.start_script + runners_executor = var.runner_worker.type + runners_limit = var.runner_worker.max_jobs + runners_concurrent = var.runner_manager.maximum_concurrent_jobs + runners_pull_policies = local.runners_pull_policies + 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 - runners_root_size = var.runners_root_size - runners_volume_type = var.runners_volume_type - runners_iam_instance_profile_name = var.runners_iam_instance_profile_name - runners_use_private_address_only = var.runners_use_private_address - runners_use_private_address = !var.runners_use_private_address - runners_request_spot_instance = var.runners_request_spot_instance - runners_environment_vars = jsonencode(var.runners_environment_vars) - runners_pre_build_script = var.runners_pre_build_script - runners_post_build_script = var.runners_post_build_script - runners_pre_clone_script = var.runners_pre_clone_script - runners_request_concurrency = var.runners_request_concurrency - runners_output_limit = var.runners_output_limit - runners_check_interval = var.runners_check_interval - runners_docker_options = local.runners_docker_options_toml - runners_volumes_tmpfs = join("\n", [for v in var.runners_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) - runners_services_volumes_tmpfs = join("\n", [for v in var.runners_services_volumes_tmpfs : format("\"%s\" = \"%s\"", v.volume, v.options)]) + runners_root_size = var.runner_worker_docker_machine_instance.root_size + runners_volume_type = var.runner_worker_docker_machine_instance.volume_type + runners_iam_instance_profile_name = var.runner_worker_docker_machine_role.profile_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_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.cache_shared - sentry_dsn = var.sentry_dsn - prometheus_listen_address = var.prometheus_listen_address - auth_type = var.auth_type_cache_sr - use_fleet = var.use_fleet - launch_template = var.use_fleet == true ? aws_launch_template.fleet_gitlab_runner[0].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 + 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 : "" } ) } data "aws_ami" "docker-machine" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 most_recent = "true" dynamic "filter" { - for_each = var.runner_ami_filter + for_each = var.runner_worker_docker_machine_ami_filter content { name = filter.key values = filter.value } } - owners = var.runner_ami_owners + owners = var.runner_worker_docker_machine_ami_owners } # 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 resource "aws_autoscaling_group" "gitlab_runner_instance" { - name = var.enable_asg_recreation ? "${aws_launch_template.gitlab_runner_instance.name}-asg" : "${var.environment}-as-group" - vpc_zone_identifier = length(var.fleet_executor_subnet_ids) > 0 ? var.fleet_executor_subnet_ids : [var.subnet_id] + # TODO Please explain how `agent_enable_asg_recreation` works + name = var.runner_enable_asg_recreation ? "${aws_launch_template.gitlab_runner_instance.name}-asg" : "${var.environment}-as-group" + vpc_zone_identifier = length(var.runner_worker_docker_machine_instance.subnet_ids) > 0 ? var.runner_worker_docker_machine_instance.subnet_ids : [var.subnet_id] min_size = "1" max_size = "1" desired_capacity = "1" health_check_grace_period = 0 - max_instance_lifetime = var.asg_max_instance_lifetime - enabled_metrics = var.metrics_autoscaling + max_instance_lifetime = var.runner_instance.max_lifetime_seconds + enabled_metrics = var.runner_instance.collect_autoscaling_metrics dynamic "tag" { for_each = local.agent_tags @@ -200,7 +201,7 @@ resource "aws_autoscaling_group" "gitlab_runner_instance" { } timeouts { - delete = var.asg_delete_timeout + delete = var.runner_terraform_timeout_delete_asg } lifecycle { ignore_changes = [min_size, max_size, desired_capacity] @@ -208,39 +209,39 @@ resource "aws_autoscaling_group" "gitlab_runner_instance" { } resource "aws_autoscaling_schedule" "scale_in" { - count = var.enable_schedule ? 1 : 0 + count = var.runner_schedule_enable ? 1 : 0 autoscaling_group_name = aws_autoscaling_group.gitlab_runner_instance.name scheduled_action_name = "scale_in-${aws_autoscaling_group.gitlab_runner_instance.name}" - recurrence = var.schedule_config["scale_in_recurrence"] - time_zone = try(var.schedule_config["scale_in_time_zone"], "Etc/UTC") - min_size = try(var.schedule_config["scale_in_min_size"], var.schedule_config["scale_in_count"]) - desired_capacity = try(var.schedule_config["scale_in_desired_capacity"], var.schedule_config["scale_in_count"]) - max_size = try(var.schedule_config["scale_in_max_size"], var.schedule_config["scale_in_count"]) + recurrence = var.runner_schedule_config["scale_in_recurrence"] + time_zone = try(var.runner_schedule_config["scale_in_time_zone"], "Etc/UTC") + min_size = try(var.runner_schedule_config["scale_in_min_size"], var.runner_schedule_config["scale_in_count"]) + desired_capacity = try(var.runner_schedule_config["scale_in_desired_capacity"], var.runner_schedule_config["scale_in_count"]) + max_size = try(var.runner_schedule_config["scale_in_max_size"], var.runner_schedule_config["scale_in_count"]) } resource "aws_autoscaling_schedule" "scale_out" { - count = var.enable_schedule ? 1 : 0 + count = var.runner_schedule_enable ? 1 : 0 autoscaling_group_name = aws_autoscaling_group.gitlab_runner_instance.name scheduled_action_name = "scale_out-${aws_autoscaling_group.gitlab_runner_instance.name}" - recurrence = var.schedule_config["scale_out_recurrence"] - time_zone = try(var.schedule_config["scale_out_time_zone"], "Etc/UTC") - min_size = try(var.schedule_config["scale_out_min_size"], var.schedule_config["scale_out_count"]) - desired_capacity = try(var.schedule_config["scale_out_desired_capacity"], var.schedule_config["scale_out_count"]) - max_size = try(var.schedule_config["scale_out_max_size"], var.schedule_config["scale_out_count"]) + recurrence = var.runner_schedule_config["scale_out_recurrence"] + time_zone = try(var.runner_schedule_config["scale_out_time_zone"], "Etc/UTC") + min_size = try(var.runner_schedule_config["scale_out_min_size"], var.runner_schedule_config["scale_out_count"]) + desired_capacity = try(var.runner_schedule_config["scale_out_desired_capacity"], var.runner_schedule_config["scale_out_count"]) + max_size = try(var.runner_schedule_config["scale_out_max_size"], var.runner_schedule_config["scale_out_count"]) } data "aws_ami" "runner" { most_recent = "true" dynamic "filter" { - for_each = var.ami_filter + for_each = var.runner_ami_filter content { name = filter.key values = filter.value } } - owners = var.ami_owners + owners = var.runner_ami_owners } resource "aws_launch_template" "gitlab_runner_instance" { @@ -250,20 +251,20 @@ resource "aws_launch_template" "gitlab_runner_instance" { image_id = data.aws_ami.runner.id user_data = base64gzip(local.template_user_data) - instance_type = var.instance_type + instance_type = var.runner_instance.type update_default_version = true - ebs_optimized = var.runner_instance_ebs_optimized + ebs_optimized = var.runner_instance.ebs_optimized monitoring { - enabled = var.runner_instance_enable_monitoring + enabled = var.runner_instance.monitoring } dynamic "instance_market_options" { - for_each = var.runner_instance_spot_price == null || var.runner_instance_spot_price == "" ? [] : ["spot"] + for_each = var.runner_instance.spot_price == null || var.runner_instance.spot_price == "" ? [] : ["spot"] content { market_type = instance_market_options.value dynamic "spot_options" { - for_each = var.runner_instance_spot_price == "on-demand-price" ? [] : [0] + for_each = var.runner_instance.spot_price == "on-demand-price" ? [] : [0] content { - max_price = var.runner_instance_spot_price + max_price = var.runner_instance.spot_price } } } @@ -272,9 +273,8 @@ resource "aws_launch_template" "gitlab_runner_instance" { name = local.aws_iam_role_instance_name } dynamic "block_device_mappings" { - for_each = [var.runner_root_block_device] + for_each = [var.runner_instance.root_device_config] content { - # cSpell:ignore xvda device_name = lookup(block_device_mappings.value, "device_name", "/dev/xvda") ebs { delete_on_termination = lookup(block_device_mappings.value, "delete_on_termination", true) @@ -288,8 +288,8 @@ resource "aws_launch_template" "gitlab_runner_instance" { } } network_interfaces { - security_groups = concat([aws_security_group.runner.id], var.extra_security_group_ids_runner_agent) - associate_public_ip_address = false == (var.runner_agent_uses_private_address == false ? var.runner_agent_uses_private_address : var.runners_use_private_address) + security_groups = concat([aws_security_group.runner.id], var.runner_networking.security_group_ids) + associate_public_ip_address = false == (var.runner_instance.private_address_only == false ? var.runner_instance.private_address_only : var.runner_worker_docker_machine_instance.private_address_only) } tag_specifications { resource_type = "instance" @@ -300,7 +300,7 @@ resource "aws_launch_template" "gitlab_runner_instance" { tags = local.tags } dynamic "tag_specifications" { - for_each = var.runner_instance_spot_price == null || var.runner_instance_spot_price == "" ? [] : ["spot"] + for_each = var.runner_instance.spot_price == null || var.runner_instance.spot_price == "" ? [] : ["spot"] content { resource_type = "spot-instances-request" tags = local.tags @@ -310,10 +310,10 @@ resource "aws_launch_template" "gitlab_runner_instance" { tags = local.tags metadata_options { - http_endpoint = var.runner_instance_metadata_options.http_endpoint - http_tokens = var.runner_instance_metadata_options.http_tokens - http_put_response_hop_limit = var.runner_instance_metadata_options.http_put_response_hop_limit - instance_metadata_tags = var.runner_instance_metadata_options.instance_metadata_tags + http_endpoint = var.runner_metadata_options.http_endpoint + http_tokens = var.runner_metadata_options.http_tokens + http_put_response_hop_limit = var.runner_metadata_options.http_put_response_hop_limit + instance_metadata_tags = var.runner_metadata_options.instance_metadata_tags } lifecycle { @@ -325,16 +325,16 @@ resource "aws_launch_template" "gitlab_runner_instance" { } resource "tls_private_key" "fleet" { - count = var.use_fleet == true && var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker_docker_machine_fleet.enable == true && var.runner_worker.type == "docker+machine" ? 1 : 0 algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "fleet" { - count = var.use_fleet == true && var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker_docker_machine_fleet.enable == true && var.runner_worker.type == "docker+machine" ? 1 : 0 - key_name = "${var.environment}-${var.fleet_key_pair_name}" + key_name = "${var.environment}-${var.runner_worker_docker_machine_fleet.key_pair_name}" public_key = tls_private_key.fleet[0].public_key_openssh tags = local.tags @@ -343,24 +343,24 @@ resource "aws_key_pair" "fleet" { resource "aws_launch_template" "fleet_gitlab_runner" { # checkov:skip=CKV_AWS_88:User can decide to add a public IP. # checkov:skip=CKV_AWS_79:User can decide to enable Metadata service V2. V2 is the default. - count = var.use_fleet == true && var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker_docker_machine_fleet.enable == true && var.runner_worker.type == "docker+machine" ? 1 : 0 name_prefix = "${local.name_runner_agent_instance}-worker-" key_name = aws_key_pair.fleet[0].key_name image_id = data.aws_ami.docker-machine[0].id - user_data = base64gzip(var.runners_userdata) - instance_type = var.docker_machine_instance_types_fleet[0] # it will be override by the fleet + user_data = base64gzip(var.runner_worker_docker_machine_instance.start_script) + instance_type = var.runner_worker_docker_machine_instance.types[0] # it will be override by the fleet update_default_version = true - ebs_optimized = var.runners_ebs_optimized + ebs_optimized = var.runner_worker_docker_machine_instance.ebs_optimized monitoring { - enabled = var.runners_monitoring + enabled = var.runner_worker_docker_machine_instance.monitoring } block_device_mappings { device_name = "/dev/sda1" ebs { - volume_size = var.runners_root_size - volume_type = var.runners_volume_type + volume_size = var.runner_worker_docker_machine_instance.root_size + volume_type = var.runner_worker_docker_machine_instance.volume_type } } @@ -370,7 +370,7 @@ resource "aws_launch_template" "fleet_gitlab_runner" { network_interfaces { security_groups = [aws_security_group.docker_machine[0].id] - associate_public_ip_address = !var.runners_use_private_address + associate_public_ip_address = !var.runner_worker_docker_machine_instance.private_address_only } tag_specifications { @@ -385,8 +385,8 @@ resource "aws_launch_template" "fleet_gitlab_runner" { tags = local.tags metadata_options { - http_tokens = var.docker_machine_instance_metadata_options.http_tokens - http_put_response_hop_limit = var.docker_machine_instance_metadata_options.http_put_response_hop_limit + http_tokens = var.runner_worker_docker_machine_ec2_metadata_options.http_tokens + http_put_response_hop_limit = var.runner_worker_docker_machine_ec2_metadata_options.http_put_response_hop_limit instance_metadata_tags = "enabled" } @@ -399,25 +399,25 @@ resource "aws_launch_template" "fleet_gitlab_runner" { ### Create cache bucket ################################################################################ locals { - bucket_name = var.cache_bucket["create"] ? module.cache[0].bucket : var.cache_bucket["bucket"] - bucket_policy = var.cache_bucket["create"] ? module.cache[0].policy_arn : var.cache_bucket["policy"] + bucket_name = var.runner_worker_cache["create"] ? module.cache[0].bucket : var.runner_worker_cache["bucket"] + bucket_policy = var.runner_worker_cache["create"] ? module.cache[0].policy_arn : var.runner_worker_cache["policy"] } module "cache" { - count = var.cache_bucket["create"] ? 1 : 0 + count = var.runner_worker_cache["create"] ? 1 : 0 source = "./modules/cache" environment = var.environment tags = local.tags - cache_bucket_prefix = var.cache_bucket_prefix - cache_bucket_name_include_account_id = var.cache_bucket_name_include_account_id - cache_bucket_set_random_suffix = var.cache_bucket_set_random_suffix - cache_bucket_versioning = var.cache_bucket_versioning - cache_expiration_days = var.cache_expiration_days - cache_lifecycle_prefix = var.cache_shared ? "project/" : "runner/" - cache_logging_bucket = var.cache_logging_bucket - cache_logging_bucket_prefix = var.cache_logging_bucket_prefix + cache_bucket_prefix = var.runner_worker_cache.bucket_prefix + cache_bucket_name_include_account_id = var.runner_worker_cache.include_account_id + cache_bucket_set_random_suffix = var.runner_worker_cache.random_suffix + cache_bucket_versioning = var.runner_worker_cache.versioning + cache_expiration_days = var.runner_worker_cache.expiration_days + cache_lifecycle_prefix = var.runner_worker_cache.shared ? "project/" : "runner/" + cache_logging_bucket = var.runner_worker_cache.access_log_bucket_id + cache_logging_bucket_prefix = var.runner_worker_cache.access_log_bucket_prefix kms_key_id = local.kms_key @@ -428,7 +428,7 @@ module "cache" { ### Trust policy ################################################################################ resource "aws_iam_instance_profile" "instance" { - count = var.create_runner_iam_role ? 1 : 0 + count = var.runner_role.create_role_profile ? 1 : 0 name = local.aws_iam_role_instance_name role = local.aws_iam_role_instance_name @@ -437,27 +437,27 @@ resource "aws_iam_instance_profile" "instance" { } resource "aws_iam_role" "instance" { - count = var.create_runner_iam_role ? 1 : 0 + count = var.runner_role.create_role_profile ? 1 : 0 name = local.aws_iam_role_instance_name - assume_role_policy = length(var.instance_role_json) > 0 ? var.instance_role_json : templatefile("${path.module}/policies/instance-role-trust-policy.json", {}) - permissions_boundary = var.permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.permissions_boundary}" + assume_role_policy = length(var.runner_role.assume_role_policy_json) > 0 ? var.runner_role.assume_role_policy_json : templatefile("${path.module}/policies/instance-role-trust-policy.json", {}) + permissions_boundary = var.iam_permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.iam_permissions_boundary}" - tags = merge(local.tags, var.role_tags) + tags = merge(local.tags, var.runner_role.additional_tags) } ################################################################################ ### Policy for the instance to use the KMS key ################################################################################ resource "aws_iam_policy" "instance_kms_policy" { - count = var.enable_kms ? 1 : 0 + count = var.enable_managed_kms_key ? 1 : 0 name = "${local.name_iam_objects}-kms" path = "/" description = "Allow runner instance the ability to use the KMS key." policy = templatefile("${path.module}/policies/instance-kms-policy.json", { - kms_key_arn = var.enable_kms && var.kms_key_id == "" ? aws_kms_key.default[0].arn : var.kms_key_id + kms_key_arn = var.enable_managed_kms_key && var.kms_key_id == "" ? aws_kms_key.default[0].arn : var.kms_key_id } ) @@ -465,9 +465,9 @@ resource "aws_iam_policy" "instance_kms_policy" { } resource "aws_iam_role_policy_attachment" "instance_kms_policy" { - count = var.enable_kms ? 1 : 0 + count = var.enable_managed_kms_key ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = aws_iam_policy.instance_kms_policy[0].arn } @@ -478,7 +478,7 @@ resource "aws_iam_role_policy_attachment" "instance_kms_policy" { ### iam:PassRole To pass the role from the agent to the docker machine runners ################################################################################ resource "aws_iam_policy" "instance_docker_machine_policy" { - count = var.runners_executor == "docker+machine" && var.create_runner_iam_role ? 1 : 0 + count = var.runner_worker.type == "docker+machine" && var.runner_role.create_role_profile ? 1 : 0 name = "${local.name_iam_objects}-docker-machine" path = "/" @@ -492,7 +492,7 @@ resource "aws_iam_policy" "instance_docker_machine_policy" { } resource "aws_iam_role_policy_attachment" "instance_docker_machine_policy" { - count = var.runners_executor == "docker+machine" && var.create_runner_iam_role ? 1 : 0 + count = var.runner_worker.type == "docker+machine" && var.runner_role.create_role_profile ? 1 : 0 role = aws_iam_role.instance[0].name policy_arn = aws_iam_policy.instance_docker_machine_policy[0].arn @@ -502,7 +502,7 @@ resource "aws_iam_role_policy_attachment" "instance_docker_machine_policy" { ### Policies for runner agent instance to allow connection via Session Manager ################################################################################ resource "aws_iam_policy" "instance_session_manager_policy" { - count = var.enable_runner_ssm_access ? 1 : 0 + count = var.runner_instance.ssm_access ? 1 : 0 name = "${local.name_iam_objects}-session-manager" path = "/" @@ -513,16 +513,16 @@ resource "aws_iam_policy" "instance_session_manager_policy" { } resource "aws_iam_role_policy_attachment" "instance_session_manager_policy" { - count = var.enable_runner_ssm_access ? 1 : 0 + count = var.runner_instance.ssm_access ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = aws_iam_policy.instance_session_manager_policy[0].arn } resource "aws_iam_role_policy_attachment" "instance_session_manager_aws_managed" { - count = var.enable_runner_ssm_access ? 1 : 0 + count = var.runner_instance.ssm_access ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" } @@ -530,10 +530,10 @@ resource "aws_iam_role_policy_attachment" "instance_session_manager_aws_managed" ### Add user defined policies ################################################################################ resource "aws_iam_role_policy_attachment" "user_defined_policies" { - count = length(var.runner_iam_policy_arns) + count = length(var.runner_role.policy_arns) - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name - policy_arn = var.runner_iam_policy_arns[count.index] + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + policy_arn = var.runner_role.policy_arns[count.index] } ################################################################################ @@ -543,9 +543,9 @@ resource "aws_iam_role_policy_attachment" "docker_machine_cache_instance" { /* If the S3 cache adapter is configured to use an IAM instance profile, the adapter uses the profile attached to the GitLab Runner machine. So do not use aws_iam_role.docker_machine.name here! See https://docs.gitlab.com/runner/configuration/advanced-configuration.html */ - count = var.cache_bucket["create"] || lookup(var.cache_bucket, "policy", "") != "" ? 1 : 0 + count = var.runner_worker_cache["create"] || lookup(var.runner_worker_cache, "policy", "") != "" ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = local.bucket_policy } @@ -553,10 +553,10 @@ resource "aws_iam_role_policy_attachment" "docker_machine_cache_instance" { ### docker machine instance policy ################################################################################ resource "aws_iam_role" "docker_machine" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 name = "${local.name_iam_objects}-docker-machine" - assume_role_policy = length(var.docker_machine_role_json) > 0 ? var.docker_machine_role_json : templatefile("${path.module}/policies/instance-role-trust-policy.json", {}) - permissions_boundary = var.permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.permissions_boundary}" + assume_role_policy = length(var.runner_worker_docker_machine_role.assume_role_policy_json) > 0 ? var.runner_worker_docker_machine_role.assume_role_policy_json : templatefile("${path.module}/policies/instance-role-trust-policy.json", {}) + permissions_boundary = var.iam_permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.iam_permissions_boundary}" tags = local.tags } @@ -564,7 +564,7 @@ resource "aws_iam_role" "docker_machine" { resource "aws_iam_instance_profile" "docker_machine" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 name = "${local.name_iam_objects}-docker-machine" role = aws_iam_role.docker_machine[0].name tags = local.tags @@ -574,15 +574,15 @@ resource "aws_iam_instance_profile" "docker_machine" { ### Add user defined policies ################################################################################ resource "aws_iam_role_policy_attachment" "docker_machine_user_defined_policies" { - count = var.runners_executor == "docker+machine" ? length(var.docker_machine_iam_policy_arns) : 0 + count = var.runner_worker.type == "docker+machine" ? length(var.runner_worker_docker_machine_role.policy_arns) : 0 role = aws_iam_role.docker_machine[0].name - policy_arn = var.docker_machine_iam_policy_arns[count.index] + policy_arn = var.runner_worker_docker_machine_role.policy_arns[count.index] } ################################################################################ resource "aws_iam_role_policy_attachment" "docker_machine_session_manager_aws_managed" { - count = (var.runners_executor == "docker+machine" && var.enable_docker_machine_ssm_access) ? 1 : 0 + count = (var.runner_worker.type == "docker+machine" && var.runner_worker.ssm_access) ? 1 : 0 role = aws_iam_role.docker_machine[0].name policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" @@ -594,7 +594,7 @@ resource "aws_iam_role_policy_attachment" "docker_machine_session_manager_aws_ma ### Service linked policy, optional ################################################################################ resource "aws_iam_policy" "service_linked_role" { - count = var.allow_iam_service_linked_role_creation ? 1 : 0 + count = var.runner_role.allow_iam_service_linked_role_creation ? 1 : 0 name = "${local.name_iam_objects}-service_linked_role" path = "/" @@ -605,15 +605,15 @@ resource "aws_iam_policy" "service_linked_role" { } resource "aws_iam_role_policy_attachment" "service_linked_role" { - count = var.allow_iam_service_linked_role_creation ? 1 : 0 + count = var.runner_role.allow_iam_service_linked_role_creation ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = aws_iam_policy.service_linked_role[0].arn } resource "aws_eip" "gitlab_runner" { # checkov:skip=CKV2_AWS_19:We can't use NAT gateway here as we are contacted from the outside. - count = var.enable_eip ? 1 : 0 + count = var.runner_instance.use_eip ? 1 : 0 tags = local.tags } @@ -631,7 +631,7 @@ resource "aws_iam_policy" "ssm" { } resource "aws_iam_role_policy_attachment" "ssm" { - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = aws_iam_policy.ssm.arn } @@ -639,7 +639,7 @@ resource "aws_iam_role_policy_attachment" "ssm" { ### AWS assign EIP ################################################################################ resource "aws_iam_policy" "eip" { - count = var.enable_eip ? 1 : 0 + count = var.runner_instance.use_eip ? 1 : 0 name = "${local.name_iam_objects}-eip" path = "/" @@ -650,9 +650,9 @@ resource "aws_iam_policy" "eip" { } resource "aws_iam_role_policy_attachment" "eip" { - count = var.enable_eip ? 1 : 0 + count = var.runner_instance.use_eip ? 1 : 0 - role = var.create_runner_iam_role ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name + role = var.runner_role.create_role_profile ? aws_iam_role.instance[0].name : local.aws_iam_role_instance_name policy_arn = aws_iam_policy.eip[0].arn } @@ -662,14 +662,14 @@ resource "aws_iam_role_policy_attachment" "eip" { module "terminate_agent_hook" { source = "./modules/terminate-agent-hook" - name = var.asg_terminate_lifecycle_hook_name == null ? "terminate-instances" : var.asg_terminate_lifecycle_hook_name + name = var.runner_terminate_ec2_lifecycle_hook_name == null ? "terminate-instances" : var.runner_terminate_ec2_lifecycle_hook_name environment = var.environment asg_arn = aws_autoscaling_group.gitlab_runner_instance.arn asg_name = aws_autoscaling_group.gitlab_runner_instance.name - cloudwatch_logging_retention_in_days = var.cloudwatch_logging_retention_in_days + cloudwatch_logging_retention_in_days = var.runner_cloudwatch.retention_days name_iam_objects = local.name_iam_objects name_docker_machine_runners = local.runner_tags_merged["Name"] - role_permissions_boundary = var.permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.permissions_boundary}" + role_permissions_boundary = var.iam_permissions_boundary == "" ? null : "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:policy/${var.iam_permissions_boundary}" kms_key_id = local.kms_key tags = local.tags diff --git a/migrations/migrate-to-7-0-0.sh b/migrations/migrate-to-7-0-0.sh index 540743aa4..dadcc01b0 100755 --- a/migrations/migrate-to-7-0-0.sh +++ b/migrations/migrate-to-7-0-0.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -eu +set -u # # Precondition: The module call has been extracted to a separate file given in "$1". The code is well-formatted. @@ -25,7 +25,7 @@ sed -i '/asg_terminate_lifecycle_lambda_runtime/d' "$converted_file" sed -i '/asg_terminate_lifecycle_lambda_timeout/d' "$converted_file" # -# PR #711 feat!: refactor Docker Machine autoscaling options +# PR #711 feat!: refactor Docker Machine autoscaling options # sed -i 's/runners_machine_autoscaling/runners_machine_autoscaling_options/g' "$converted_file" @@ -37,7 +37,7 @@ sed -i '/runners_pull_policy/d' "$converted_file" # # PR #511 feat!: allow to set all docker options for the Executor # -extracted_variables=$(grep -E '(runners_docker_runtime|runners_helper_image|runners_shm_size|runners_shm_size|runners_extra_hosts|runners_disable_cache|runners_image|runners_privileged)' "$converted_file") +extracted_variables=$(grep -E '(runners_pull_policies|runners_docker_runtime|runners_helper_image|runners_shm_size|runners_shm_size|runners_extra_hosts|runners_disable_cache|runners_image|runners_privileged)' "$converted_file") sed -i '/runners_image/d' "$converted_file" sed -i '/runners_privileged/d' "$converted_file" @@ -46,6 +46,7 @@ sed -i '/runners_extra_hosts/d' "$converted_file" sed -i '/runners_shm_size/d' "$converted_file" sed -i '/runners_docker_runtime/d' "$converted_file" sed -i '/runners_helper_image/d' "$converted_file" +sed -i '/runners_pull_policies/d' "$converted_file" # content to be added to `volumes` volumes=$(grep "runners_additional_volumes" "$converted_file" | cut -d '=' -f 2 | tr -d '[]') @@ -66,16 +67,597 @@ extracted_variables=$(echo "$extracted_variables" | \ sed 's/runners_extra_hosts/extra_hosts/g' | \ sed 's/runners_shm_size/shm_size/g' | \ sed 's/runners_docker_runtime/runtime/g' | \ - sed 's/runners_helper_image/helper_image/g' + sed 's/runners_helper_image/helper_image/g' | \ + sed 's/runners_pull_policies/pull_policies/g' ) # add new block runners_docker_options at the end -echo "$(head -n -1 "$converted_file") -runners_docker_options { - $extracted_variables -} -}" > x +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_docker_options = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +# +# PR #757 refactor!: rename variables and prefix with agent, executor and global scope +# +sed -i '/aws_region/d' "$converted_file" +sed -i '/enable_manage_gitlab_token/d' "$converted_file" + +sed 's/enable_kms/enable_managed_kms_key/g' "$converted_file" | \ +sed 's/kms_alias_name/kms_managed_alias_name/g' | \ +sed 's/kms_deletion_window_in_days/kms_managed_deletion_rotation_window_in_days/g' | \ +sed 's/permission_boundary/iam_permission_boundary/g' | \ +sed 's/extra_security_group_ids_runner_agent/runner_extra_security_group_ids/g' | \ +sed 's/instance_type/runner_instance_type/g' | \ +sed 's/runner_instance_ebs_optimized/runner_ebs_optimized/g' | \ +sed 's/runner_instance_enable_monitoring/runner_enable_monitoring/g' | \ +sed 's/runner_instance_metadata_options/runner_metadata_options/g' | \ +sed 's/runners_userdata/runner_worker_docker_machine_userdata/g' | \ +sed 's/runners_executor/runner_worker_type/g' | \ +sed 's/runners_install_amazon_ecr_credential_helper/runner_install_amazon_ecr_credential_helper/g' | \ +sed 's/runners_clone_url/runner_gitlab_clone_url/g' | \ +sed 's/runners_gitlab_url/runner_gitlab_url/g' | \ +sed 's/runners_max_builds/runner_worker_docker_machine_max_builds/g' | \ +sed 's/runners_idle_count/runner_worker_idle_count/g' | \ +sed 's/runners_idle_time/runner_worker_idle_time/g' | \ +sed 's/runners_concurrent/runner_manager_maximum_concurrent_jobs/g' | \ +sed 's/runners_limit/runner_worker_max_jobs/g' | \ +sed 's/runners_check_interval/runner_manager_gitlab_check_interval/g' | \ +sed 's/sentry_dsn/runner_manager_sentry_dsn/g' | \ +sed 's/prometheus_listen_address/runner_manager_prometheus_listen_address/g' | \ +sed 's/runner_extra_config/runner_user_data_extra/g' | \ +sed 's/runners_ca_certificate/runner_gitlab_ca_certificate/g' | \ +sed 's/runners_yum_update/runner_yum_update/g' | \ +sed 's/runners_gitlab_certificate/runners_gitlab_certificate/g' | \ +sed 's/asg_terminate_lifecycle_hook_name/runner_terminate_ec2_lifecycle_hook_name/g' | \ +sed 's/runner_iam_policy_arns/runner_extra_iam_policy_arns/g' | \ +sed 's/create_runner_iam_role/runner_create_runner_iam_role_profile/g' | \ +sed 's/runner_iam_role_name/runner_iam_role_profile_name/g' | \ +sed 's/enable_eip/runner_enable_eip/g' | \ +sed 's/enable_runner_ssm_access/runner_enable_ssm_access/g' | \ +sed 's/enable_runner_user_data_trace_log/runner_user_data_enable_trace_log/g' | \ +sed 's/enable_schedule/runner_schedule_enable/g' | \ +sed 's/schedule_config/runner_schedule_config/g' | \ +sed 's/runner_root_block_device/runner_root_block_device/g' | \ +sed 's/gitlab_runner_registration_config/runner_gitlab_registration_config/g' | \ +sed 's/[^_]ami_filter/runner_ami_filter/g' | \ +sed 's/[^_]ami_owners/runner_ami_owners/g' | \ +sed 's/runner_ami_filter/runner_worker_docker_machine_ami_filter/g' | \ +sed 's/runner_ami_owners/runner_worker_docker_machine_ami_owners/g' | \ +sed 's/instance_role_json/runner_assume_role_json/g' | \ +sed 's/docker_machine_role_json/runner_worker_docker_machine_assume_role_json/g' | \ +sed 's/role_tags/runner_extra_role_tags/g' | \ +sed 's/runner_tags/runner_worker_docker_machine_extra_role_tags/g' | \ +sed 's/agent_tags/runner_extra_instance_tags/g' | \ +sed 's/enable_ping/runner_ping_enable/g' | \ +sed 's/gitlab_runner_version/runner_gitlab_runner_version/g' | \ +sed 's/gitlab_runner_egress_rules/runner_extra_egress_rules/g' | \ +sed 's/gitlab_runner_security_group_ids/runner_ping_allow_from_security_groups/g' | \ +sed 's/gitlab_runner_security_group_description/runner_security_group_description/g' | \ +sed 's/cache_shared/runner_worker_cache_shared/g' | \ +sed 's/cache_expiration_days/runner_worker_cache_s3_expiration_days/g' | \ +sed 's/cache_bucket_versioning/runner_worker_cache_s3_enable_versioning/g' | \ +sed 's/cache_logging_bucket_prefix/runner_worker_cache_s3_logging_bucket_prefix/g' | \ +sed 's/cache_logging_bucket/runner_worker_cache_s3_logging_bucket_id/g' | \ +sed 's/cache_bucket_set_random_suffix/runner_worker_cache_s3_bucket_enable_random_suffix/g' | \ +sed 's/cache_bucket_name_include_account_id/runner_worker_cache_s3_bucket_name_include_account_id/g' | \ +sed 's/cache_bucket_prefix/runner_worker_cache_s3_bucket_prefix/g' | \ +sed 's/runner_agent_uses_private_address/runner_use_private_address/g' | \ +sed 's/runners_use_private_address/runner_worker_docker_machine_use_private_address/g' | \ +sed 's/runners_request_spot_instance/runner_worker_docker_machine_request_spot_instances/g' | \ +sed 's/userdata_pre_install/runner_userdata_pre_install/g' | \ +sed 's/userdata_post_install/runner_userdata_post_install/g' | \ +sed 's/runners_pre_build_script/runner_worker_pre_build_script/g' | \ +sed 's/runners_post_build_script/runner_worker_post_build_script/g' | \ +sed 's/runners_pre_clone_script/runner_worker_pre_clone_script/g' | \ +sed 's/runners_request_concurrency/runner_worker_request_concurrency/g' | \ +sed 's/runners_output_limit/runner_worker_output_limit/g' | \ +sed 's/runners_environment_vars/runner_worker_extra_environment_variables/g' | \ +sed 's/runners_docker_registry_mirror/runner_worker_docker_machine_docker_registry_mirror_url/g' | \ +sed 's/docker_machine_egress_rules/runner_worker_docker_machine_extra_egress_rules/g' | \ +sed 's/docker_machine_iam_policy_arns/runner_worker_docker_machine_extra_iam_policy_arns/g' | \ +sed 's/enable_cloudwatch_logging/runner_cloudwatch_enable/g' | \ +sed 's/cloudwatch_logging_retention_in_days/runner_cloudwatch_retention_days/g' | \ +sed 's/log_group_name/runner_cloudwatch_log_group_name/g' | \ +sed 's/asg_max_instance_lifetime/runner_max_instance_lifetime_seconds/g' | \ +sed 's/asg_delete_timeout/runner_terraform_timeout_delete_asg/g' | \ +sed 's/enable_docker_machine_ssm_access/runner_worker_enable_ssm_access/g' | \ +sed 's/ cache_bucket/ runner_worker_cache_s3_bucket/g' | \ +sed 's/docker_machine_security_group_description/runner_worker_docker_machine_security_group_description/g' | \ +sed 's/docker_machine_options/runner_worker_docker_machine_ec2_options/g' | \ +sed 's/runners_iam_instance_profile_name/runner_worker_docker_machine_iam_instance_profile_name/g' | \ +sed 's/runners_volume_type/runner_worker_docker_machine_ec2_volume_type/g' | \ +sed 's/runners_ebs_optimized/runner_worker_docker_machine_ec2_ebs_optimized/g' | \ +sed 's/runners_monitoring/runner_worker_docker_machine_enable_monitoring/g' | \ +sed 's/runners_machine_autoscaling_options/runner_worker_docker_machine_autoscaling_options/g' | \ +sed 's/runners_docker_services/runner_worker_docker_services/g' | \ +sed 's/runners_services_volumes_tmpfs/runner_worker_docker_services_volumes_tmpfs/g' | \ +sed 's/runners_volumes_tmpfs/runner_worker_docker_volumes_tmpfs/g' | \ +sed 's/runners_root_size/runner_worker_docker_machine_ec2_root_size/g' | \ +sed 's/enable_asg_recreation/runner_enable_asg_recreation/g' | \ +sed 's/secure_parameter_store_runner_sentry_dsn/runner_sentry_secure_parameter_store_name/g' | \ +sed 's/secure_parameter_store_runner_token_key/runner_gitlab_token_secure_parameter_store/g' | \ +sed 's/secure_parameter_store_gitlab_runner_registration_token_name/runner_gitlab_registration_token_secure_parameter_store_name/g' | \ +sed 's/allow_iam_service_linked_role_creation/runner_allow_iam_service_linked_role_creation/g' | \ +sed 's/runners_add_dind_volumes/runner_worker_docker_add_dind_volumes/g' | \ +sed 's/runners_token/runner_gitlab_token/g' | \ +sed 's/runners_name/runner_gitlab_runner_name/g' | \ +sed 's/docker_machine_version/runner_docker_machine_version/g' | \ +sed 's/docker_machine_download_url/runner_docker_machine_download_url/g' | \ +sed 's/docker_machine_spot_price_bid/runner_worker_docker_machine_ec2_spot_price_bid/g' | \ +sed 's/docker_machine_instance_type/runner_worker_docker_machine_instance_type/g' | \ +sed 's/docker_machine_instance_metadata_options/runner_worker_docker_machine_ec2_metadata_options/g' | \ +sed 's/runner_instance_spot_price/runner_spot_price/g' | \ +sed 's/metrics_autoscaling/runner_collect_autoscaling_metrics/g' | \ +sed 's/auth_type_cache_sr/runner_worker_cache_s3_authentication_type/g' \ +> "$converted_file.tmp" && mv "$converted_file.tmp" "$converted_file" + +# overrides block +extracted_variables=$(grep -E '(name_sg|name_iam_objects|name_runner_agent_instance|name_docker_machine_runners)' "$converted_file") + +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/name_sg/security_group_prefix/g' | \ + sed 's/name_iam_objects/iam_object_prefix/g' | \ + sed 's/name_runner_agent_instance/runner_instance_prefix/g' | \ + sed 's/name_docker_machine_runners/runner_worker_docker_machine_instance_prefix/g' + ) + +sed '/name_sg/d' "$converted_file" | \ +sed '/name_iam_objects/d' | \ +sed '/name_runner_agent_instance/d' | \ +sed '/name_docker_machine_runners/d' | \ +sed '/overrides = {/d' \ +> "$converted_file.tmp" && mv "$converted_file.tmp" "$converted_file" + +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + $extracted_variables + }" > "$converted_file.tmp" && mv "$converted_file.tmp" "$converted_file" +fi + +# +# PR #810 refactor!: group variables for better overview +# +extracted_variables=$(grep -E '(runner_max_instance_lifetime_seconds|runner_enable_eip|runner_collect_autoscaling_metrics|runner_enable_monitoring|runner_gitlab_runner_name|runner_enable_ssm_access|runner_use_private_address|runner_root_block_device|runner_ebs_optimized|runner_spot_price|runner_instance_prefix|runner_instance_type|runner_extra_instance_tags)' "$converted_file") + +sed -i '/runner_root_block_device/d' "$converted_file" +sed -i '/runner_ebs_optimized/d' "$converted_file" +sed -i '/runner_spot_price/d' "$converted_file" +sed -i '/runner_instance_prefix/d' "$converted_file" +sed -i '/runner_instance_type/d' "$converted_file" +sed -i '/runner_extra_instance_tags/d' "$converted_file" +sed -i '/runner_use_private_address/d' "$converted_file" +sed -i '/runner_enable_ssm_access/d' "$converted_file" +sed -i '/runner_gitlab_runner_name/d' "$converted_file" +sed -i '/runner_enable_monitoring/d' "$converted_file" +sed -i '/runner_collect_autoscaling_metrics/d' "$converted_file" +sed -i '/runner_enable_eip/d' "$converted_file" +sed -i '/runner_max_instance_lifetime_seconds/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_root_block_device/root_device_config/g' | \ + sed 's/runner_ebs_optimized/ebs_optimized/g' | \ + sed 's/runner_spot_price/spot_price/g' | \ + sed 's/runner_instance_prefix/name_prefix/g' | \ + sed 's/runner_instance_type/type/g' | \ + sed 's/runner_extra_instance_tags/additional_tags/g' | \ + sed 's/runner_use_private_address/private_address_only/g' | \ + sed 's/runner_gitlab_runner_name/name/g' | \ + sed 's/runner_enable_monitoring/monitoring/g' | \ + sed 's/runner_collect_autoscaling_metrics/collect_autoscaling_metrics/g' | \ + sed 's/runner_enable_eip/use_eip/g' | \ + sed 's/runner_max_instance_lifetime_seconds/max_lifetime_seconds/g' | \ + sed 's/runner_enable_ssm_access/ssm_access/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_instance = { + $extracted_variables + } + " > x && cp x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_allow_iam_service_linked_role_creation|runner_create_runner_iam_role_profile|runner_iam_role_profile_name|runner_extra_role_tags|runner_assume_role_json)|runner_extra_iam_policy_arns)' "$converted_file") + +sed -i '/runner_allow_iam_service_linked_role_creation/d' "$converted_file" +sed -i '/runner_create_runner_iam_role_profile/d' "$converted_file" +sed -i '/runner_iam_role_profile_name/d' "$converted_file" +sed -i '/runner_extra_role_tags/d' "$converted_file" +sed -i '/runner_assume_role_json/d' "$converted_file" +sed -i '/runner_extra_iam_policy_arns/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_allow_iam_service_linked_role_creation/allow_iam_service_linked_role_creation/g' | \ + sed 's/runner_create_runner_iam_role_profile/create_role_profile/g' | \ + sed 's/runner_iam_role_profile_name/role_profile_name/g' | \ + sed 's/runner_extra_role_tags/additional_tags/g' | \ + sed 's/runner_assume_role_json/assume_role_policy_json/g' | \ + sed 's/runner_extra_iam_policy_arns/policy_arns/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_role = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_manager_maximum_concurrent_jobs|runner_manager_sentry_dsn|runner_manager_gitlab_check_interval|runner_manager_prometheus_listen_address)' "$converted_file") + +sed -i '/runner_manager_maximum_concurrent_jobs/d' "$converted_file" +sed -i '/runner_manager_sentry_dsn/d' "$converted_file" +sed -i '/runner_manager_gitlab_check_interval/d' "$converted_file" +sed -i '/runner_manager_prometheus_listen_address/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_manager_maximum_concurrent_jobs/maximum_concurrent_jobs/g' | \ + sed 's/runner_manager_sentry_dsn/sentry_dsn/g' | \ + sed 's/runner_manager_gitlab_check_interval/gitlab_check_interval/g' | \ + sed 's/runner_manager_prometheus_listen_address/prometheus_listen_address/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_manager = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_yum_update|runner_user_data_extra|runner_userdata_post_install|runner_userdata_pre_install|runner_install_amazon_ecr_credential_helper|runner_docker_machine_version|runner_docker_machine_download_url)' "$converted_file") + +sed -i '/runner_docker_machine_download_url/d' "$converted_file" +sed -i '/runner_docker_machine_version/d' "$converted_file" +sed -i '/runner_install_amazon_ecr_credential_helper/d' "$converted_file" +sed -i '/runner_userdata_pre_install/d' "$converted_file" +sed -i '/runner_userdata_post_install/d' "$converted_file" +sed -i '/runner_user_data_extra/d' "$converted_file" +sed -i '/runner_yum_update/d' "$converted_file" + + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_docker_machine_download_url/docker_machine_download_url/g' | \ + sed 's/runner_docker_machine_version/docker_machine_version/g' | \ + sed 's/runner_install_amazon_ecr_credential_helper/amazon_ecr_credential_helper/g' | \ + sed 's/runner_userdata_pre_install/pre_install_script/g' | \ + sed 's/runner_userdata_post_install/post_install_script/g' | \ + sed 's/runner_user_data_extra/start_script/g' | \ + sed 's/runner_yum_update/yum_update/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_install = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_gitlab_clone_url|runner_gitlab_url|runner_gitlab_runner_version|runner_gitlab_token|runner_gitlab_certificate|runner_gitlab_ca_certificate)' "$converted_file") + +sed -i '/runner_gitlab_ca_certificate/d' "$converted_file" +sed -i '/runner_gitlab_certificate/d' "$converted_file" +sed -i '/runner_gitlab_token/d' "$converted_file" +sed -i '/runner_gitlab_runner_version/d' "$converted_file" +sed -i '/runner_gitlab_url/d' "$converted_file" +sed -i '/runner_gitlab_clone_url/d' "$converted_file" + + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_gitlab_ca_certificate/ca_certificate/g' | \ + sed 's/runner_gitlab_certificate/certificate/g' | \ + sed 's/runner_gitlab_token/registration_token/g' | \ + sed 's/runner_gitlab_runner_version/runner_version/g' | \ + sed 's/runner_gitlab_url/url/g' | \ + sed 's/runner_gitlab_clone_url/url_clone/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_gitlab = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(show_user_data_in_plan|runner_user_data_enable_trace_log)' "$converted_file") + +sed -i '/runner_user_data_enable_trace_log/d' "$converted_file" +sed -i '/show_user_data_in_plan/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_user_data_enable_trace_log/trace_runner_user_data/g' | \ + sed 's/show_user_data_in_plan/write_runner_config_to_file/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + debug = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +sed -i 's/output_runner_user_data_to_file/write_runner_user_data_to_file/g' "$converted_file" + +extracted_variables=$(grep -E '(runner_cloudwatch_log_group_name|runner_cloudwatch_retention_days|runner_cloudwatch_enable)' "$converted_file") + +sed -i '/runner_cloudwatch_enable/d' "$converted_file" +sed -i '/runner_cloudwatch_retention_days/d' "$converted_file" +sed -i '/runner_cloudwatch_log_group_name/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_cloudwatch_enable/enable/g' | \ + sed 's/runner_cloudwatch_retention_days/retention_days/g' | \ + sed 's/runner_cloudwatch_log_group_name/log_group_name/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_cloudwatch = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_worker_extra_environment_variables|runner_worker_output_limit|runner_worker_request_concurrency|runner_worker_max_jobs|runner_worker_type|runner_worker_enable_ssm_access)' "$converted_file") + +sed -i '/runner_worker_enable_ssm_access/d' "$converted_file" +sed -i '/runner_worker_type/d' "$converted_file" +sed -i '/runner_worker_max_jobs/d' "$converted_file" +sed -i '/runner_worker_request_concurrency/d' "$converted_file" +sed -i '/runner_worker_output_limit/d' "$converted_file" +sed -i '/runner_worker_extra_environment_variables/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_enable_ssm_access/ssm_access/g' | \ + sed 's/runner_worker_max_jobs/max_jobs/g' | \ + sed 's/runner_worker_request_concurrency/request_concurrency/g' | \ + sed 's/runner_worker_output_limit/output_limit/g' | \ + sed 's/runner_worker_extra_environment_variables/environment_variables/g' | \ + sed 's/runner_worker_type/type/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +# renames the block +sed -i 's/runner_worker_cache_s3_bucket /runner_worker_cache /g' "$converted_file" + +# integrate the new variables into existing block +extracted_variables=$(grep -E '(runner_worker_cache_s3_logging_bucket_prefix|runner_worker_cache_s3_logging_bucket_id|runner_worker_cache_s3_bucket_enable_random_suffix|runner_worker_cache_s3_bucket_name_include_account_id|runner_worker_cache_s3_bucket_prefix|runner_worker_cache_s3_enable_versioning|runner_worker_cache_s3_expiration_days|runner_worker_cache_s3_authentication_type|runner_worker_cache_shared)' "$converted_file") + +sed -i '/runner_worker_cache_shared/d' "$converted_file" +sed -i '/runner_worker_cache_s3_authentication_type/d' "$converted_file" +sed -i '/runner_worker_cache_s3_expiration_days/d' "$converted_file" +sed -i '/runner_worker_cache_s3_enable_versioning/d' "$converted_file" +sed -i '/runner_worker_cache_s3_bucket_prefix/d' "$converted_file" +sed -i '/runner_worker_cache_s3_bucket_name_include_account_id/d' "$converted_file" +sed -i '/runner_worker_cache_s3_bucket_enable_random_suffix/d' "$converted_file" +sed -i '/runner_worker_cache_s3_logging_bucket_id/d' "$converted_file" +sed -i '/runner_worker_cache_s3_logging_bucket_prefix/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_cache_shared/shared/g' | \ + sed 's/runner_worker_cache_s3_authentication_type/authentication_type/g' | \ + sed 's/runner_worker_cache_s3_expiration_days/expiration_days/g' | \ + sed 's/runner_worker_cache_s3_enable_versioning/versioning/g' | \ + sed 's/runner_worker_cache_s3_bucket_prefix/bucket_prefix/g' | \ + sed 's/runner_worker_cache_s3_bucket_name_include_account_id/include_account_id/g' | \ + sed 's/runner_worker_cache_s3_bucket_enable_random_suffix/random_suffix/g' | \ + sed 's/runner_worker_cache_s3_logging_bucket_id/access_log_bucket_id/g' | \ + sed 's/runner_worker_cache_s3_logging_bucket_prefix/access_log_bucket_prefix/g' + ) + +# insert the new variables into the existing block or append new block +if [ -n "$extracted_variables" ]; then + if grep -q "runner_worker_cache = {" "$converted_file"; then + cp "$converted_file" "$converted_file.bak" + sed -i "s/runner_worker_cache = {/runner_worker_cache = { $extracted_variables/g" "$converted_file" + else + echo "$(head -n -1 "$converted_file") + runner_worker_cache = { + $extracted_variables + } + " > x && mv x "$converted_file" + fi +fi + +extracted_variables=$(grep -E '(runner_worker_idle_count|runner_worker_idle_time|runner_worker_docker_machine_use_private_address|runner_worker_docker_machine_instance_type|runner_worker_docker_machine_docker_registry_mirror_url|runner_worker_docker_machine_max_builds|runner_worker_docker_machine_ec2_ebs_optimized|runner_worker_docker_machine_ec2_root_size|runner_worker_docker_machine_ec2_volume_type|runner_worker_docker_machine_userdata|runner_worker_docker_machine_enable_monitoring|runner_worker_enable_ssm_access|runner_worker_docker_machine_instance_prefix)' "$converted_file") + +sed -i '/runner_worker_enable_ssm_access/d' "$converted_file" +sed -i '/runner_worker_docker_machine_instance_prefix/d' "$converted_file" +sed -i '/runner_worker_docker_machine_enable_monitoring/d' "$converted_file" +sed -i '/runner_worker_docker_machine_userdata/d' "$converted_file" +sed -i '/runner_worker_docker_machine_ec2_volume_type/d' "$converted_file" +sed -i '/runner_worker_docker_machine_ec2_root_size/d' "$converted_file" +sed -i '/runner_worker_docker_machine_ec2_ebs_optimized/d' "$converted_file" +sed -i '/runner_worker_docker_machine_max_builds/d' "$converted_file" +sed -i '/runner_worker_docker_machine_docker_registry_mirror_url/d' "$converted_file" +sed -i '/runner_worker_docker_machine_use_private_address/d' "$converted_file" +sed -i '/runner_worker_docker_machine_instance_type/d' "$converted_file" +sed -i '/runner_worker_idle_time/d' "$converted_file" +sed -i '/runner_worker_idle_count/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_docker_machine_use_private_address/private_address_only/g' | \ + sed 's/runner_worker_docker_machine_enable_monitoring/monitoring/g' | \ + sed 's/runner_worker_docker_machine_userdata/start_script/g' | \ + sed 's/runner_worker_docker_machine_ec2_volume_type/volume_type/g' | \ + sed 's/runner_worker_docker_machine_ec2_root_size/root_size/g' | \ + sed 's/runner_worker_docker_machine_ec2_ebs_optimized/ebs_optimized/g' | \ + sed 's/runner_worker_docker_machine_max_builds/destroy_after_max_builds/g' | \ + sed 's/runner_worker_docker_machine_docker_registry_mirror_url/docker_registry_mirror_url/g' | \ + sed 's/runner_worker_docker_machine_instance_type/types/g' | \ + sed 's/runner_worker_idle_time/idle_time/g' | \ + sed 's/runner_worker_idle_count/idle_count/g' | \ + sed 's/runner_worker_docker_machine_instance_prefix/name_prefix/g' + ) + +extracted_fleet_types=$(grep -E '(docker_machine_instance_types_fleet)' "$converted_file" | sed 's/docker_machine_instance_types_fleet/types/g') +extracted_fleet_subnets=$(grep -E '(fleet_executor_subnet_ids)' "$converted_file" | sed 's/fleet_executor_subnet_ids/subnet_ids/g') +sed -i '/docker_machine_instance_types_fleet/d' "$converted_file" +sed -i '/fleet_executor_subnet_ids/d' "$converted_file" + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_docker_machine_instance = { + $extracted_variables + $extracted_fleet_types + $extracted_fleet_subnets + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_worker_docker_machine_request_spot_instances|runner_worker_docker_machine_ec2_spot_price_bid)' "$converted_file") + +sed -i '/runner_worker_docker_machine_ec2_spot_price_bid/d' "$converted_file" +sed -i '/runner_worker_docker_machine_request_spot_instances/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_docker_machine_ec2_spot_price_bid/max_price/g' | \ + sed 's/runner_worker_docker_machine_request_spot_instances/enable/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_docker_machine_instance_spot = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_extra_security_group_ids|runner_security_group_description|runner_ping_allow_from_security_groups|runner_ping_enable)' "$converted_file") + +sed -i '/runner_ping_enable/d' "$converted_file" +sed -i '/runner_ping_allow_from_security_groups/d' "$converted_file" +sed -i '/runner_security_group_description/d' "$converted_file" +sed -i '/runner_extra_security_group_ids/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_ping_enable/allow_incoming_ping/g' | \ + sed 's/runner_security_group_description/security_group_description/g' | \ + sed 's/runner_extra_security_group_ids/security_group_ids/g' | \ + sed 's/runner_ping_allow_from_security_groups/allow_incoming_ping_security_group_ids/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_networking = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +sed -i 's/runner_extra_egress_rules/runner_networking_egress_rules/g' "$converted_file" + +extracted_variables=$(grep -E '(runner_worker_post_build_script|runner_worker_pre_build_script|runner_worker_pre_clone_script)' "$converted_file") + +sed -i '/runner_worker_pre_clone_script/d' "$converted_file" +sed -i '/runner_worker_pre_build_script/d' "$converted_file" +sed -i '/runner_worker_post_build_script/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_pre_clone_script/pre_clone_script/g' | \ + sed 's/runner_worker_pre_build_script/pre_build_script/g' | \ + sed 's/runner_worker_post_build_script/post_build_script/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_gitlab_pipeline = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(runner_worker_docker_machine_extra_iam_policy_arns|runner_worker_docker_machine_assume_role_json|runner_worker_docker_machine_iam_instance_profile_name|runner_worker_docker_machine_extra_role_tags)' "$converted_file") + +sed -i '/runner_worker_docker_machine_extra_role_tags/d' "$converted_file" +sed -i '/runner_worker_docker_machine_iam_instance_profile_name/d' "$converted_file" +sed -i '/runner_worker_docker_machine_assume_role_json/d' "$converted_file" +sed -i '/runner_worker_docker_machine_extra_iam_policy_arns/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/runner_worker_docker_machine_iam_instance_profile_name/profile_name/g' | \ + sed 's/runner_worker_docker_machine_assume_role_json/assume_role_policy_json/g' | \ + sed 's/runner_worker_docker_machine_extra_iam_policy_arns/policy_arns/g' | \ + sed 's/runner_worker_docker_machine_extra_role_tags/additional_tags/g' + ) + +# add new block runners_docker_options at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_docker_machine_role = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +extracted_variables=$(grep -E '(use_fleet|fleet_key_pair_name)' "$converted_file") + +sed -i '/use_fleet/d' "$converted_file" +sed -i '/fleet_key_pair_name/d' "$converted_file" + +# rename the variables +extracted_variables=$(echo "$extracted_variables" | \ + sed 's/use_fleet/enable/g' | \ + sed 's/fleet_key_pair_name/key_pair_name/g' + ) + +# add new block at the end +if [ -n "$extracted_variables" ]; then + echo "$(head -n -1 "$converted_file") + runner_worker_docker_machine_fleet = { + $extracted_variables + } + " > x && mv x "$converted_file" +fi + +# change the module source to cattle-ops +sed -i 's/npalm/cattle-ops/g' "$converted_file" + +cat < 0 && var.enable_ping ? length(var.gitlab_runner_security_group_ids) : 0 + count = length(var.runner_networking.allow_incoming_ping_security_group_ids) > 0 && var.runner_networking.allow_incoming_ping ? length(var.runner_networking.allow_incoming_ping_security_group_ids) : 0 type = "ingress" from_port = -1 to_port = -1 protocol = "icmp" - source_security_group_id = element(var.gitlab_runner_security_group_ids, count.index) + source_security_group_id = element(var.runner_networking.allow_incoming_ping_security_group_ids, count.index) security_group_id = aws_security_group.runner.id description = format( "Allow ICMP traffic from %s to gitlab-runner agent instances in group %s", - element(var.gitlab_runner_security_group_ids, count.index), + element(var.runner_networking.allow_incoming_ping_security_group_ids, count.index), aws_security_group.runner.name ) } @@ -66,14 +66,14 @@ resource "aws_security_group_rule" "runner_ping_group" { resource "aws_security_group" "docker_machine" { # checkov:skip=CKV2_AWS_5:Security group is used within an template and assigned to the docker machines - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 name_prefix = "${local.name_sg}-docker-machine" vpc_id = var.vpc_id - description = var.docker_machine_security_group_description + description = var.runner_worker_docker_machine_security_group_description dynamic "egress" { - for_each = var.docker_machine_egress_rules + for_each = var.runner_worker_docker_machine_extra_egress_rules iterator = each content { @@ -107,7 +107,7 @@ resource "aws_security_group" "docker_machine" { # Allow docker-machine traffic from gitlab-runner agent instances to docker-machine instances resource "aws_security_group_rule" "docker_machine_docker_runner" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 type = "ingress" from_port = 2376 @@ -131,12 +131,12 @@ resource "aws_security_group_rule" "docker_machine_docker_runner" { # Combine runner security group id and additional security group IDs locals { # Only include runner security group id and additional if ping is enabled - security_groups_ping = var.enable_ping && length(var.gitlab_runner_security_group_ids) > 0 ? concat(var.gitlab_runner_security_group_ids, [aws_security_group.runner.id]) : [] + security_groups_ping = var.runner_networking.allow_incoming_ping && length(var.runner_networking.allow_incoming_ping_security_group_ids) > 0 ? concat(var.runner_networking.allow_incoming_ping_security_group_ids, [aws_security_group.runner.id]) : [] } # Allow SSH traffic from gitlab-runner agent instances and security group IDs to docker-machine instances resource "aws_security_group_rule" "docker_machine_ssh_runner" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 type = "ingress" from_port = 22 @@ -155,7 +155,7 @@ resource "aws_security_group_rule" "docker_machine_ssh_runner" { # Allow ICMP traffic from gitlab-runner agent instances and security group IDs to docker-machine instances resource "aws_security_group_rule" "docker_machine_ping_runner" { - count = var.runners_executor == "docker+machine" ? length(local.security_groups_ping) : 0 + count = var.runner_worker.type == "docker+machine" ? length(local.security_groups_ping) : 0 type = "ingress" from_port = -1 @@ -178,7 +178,7 @@ resource "aws_security_group_rule" "docker_machine_ping_runner" { # Allow docker-machine traffic from docker-machine instances to docker-machine instances on port 2376 resource "aws_security_group_rule" "docker_machine_docker_self" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 type = "ingress" from_port = 2376 @@ -196,7 +196,7 @@ resource "aws_security_group_rule" "docker_machine_docker_self" { # Allow SSH traffic from docker-machine instances to docker-machine instances on port 22 resource "aws_security_group_rule" "docker_machine_ssh_self" { - count = var.runners_executor == "docker+machine" ? 1 : 0 + count = var.runner_worker.type == "docker+machine" ? 1 : 0 type = "ingress" from_port = 22 @@ -214,7 +214,7 @@ resource "aws_security_group_rule" "docker_machine_ssh_self" { # Allow ICMP traffic from docker-machine instances to docker-machine instances resource "aws_security_group_rule" "docker_machine_ping_self" { - count = (var.runners_executor == "docker+machine" && var.enable_ping) ? 1 : 0 + count = (var.runner_worker.type == "docker+machine" && var.runner_networking.allow_incoming_ping) ? 1 : 0 type = "ingress" from_port = -1 diff --git a/tags.tf b/tags.tf index aee23bd06..13fc0bd98 100644 --- a/tags.tf +++ b/tags.tf @@ -13,22 +13,24 @@ locals { agent_tags_merged = merge( { + # false positive: TfLint fails with: Call to function "format" failed: unsupported value for "%s" at 0: null value cannot be formatted. + # tflint-ignore: aws_iam_policy_sid_invalid_characters "Name" = format("%s", local.name_runner_agent_instance) }, { "Environment" = format("%s", var.environment) }, var.tags, - var.agent_tags + var.runner_instance.additional_tags ) agent_tags = { for k, v in local.agent_tags_merged : k => v if !contains(var.suppressed_tags, k) } runner_tags_merged = merge( local.tags, - var.runner_tags, + var.runner_worker_docker_machine_role.additional_tags, # overwrites the `Name` key from `local.tags` - var.overrides["name_docker_machine_runners"] == "" ? { Name = substr(format("%s", var.environment), 0, 16) } : { Name = var.overrides["name_docker_machine_runners"] }, + var.runner_worker_docker_machine_instance.name_prefix == "" ? { Name = substr(format("%s", var.environment), 0, 16) } : { Name = var.runner_worker_docker_machine_instance.name_prefix }, ) # remove the `Name` tag in addition if docker+machine adds one to avoid a failure due to a duplicate `Name` tag diff --git a/variables.tf b/variables.tf index 95050e844..118a72328 100644 --- a/variables.tf +++ b/variables.tf @@ -1,80 +1,220 @@ -variable "aws_region" { - description = "AWS region." +/* + * Global variables + */ +variable "vpc_id" { + description = "The VPC used for the runner and runner workers." type = string } -variable "auth_type_cache_sr" { - description = "A string that declares the AuthenticationType for [runners.cache.s3]. Can either be 'iam' or 'credentials'" +variable "subnet_id" { + description = <<-EOT + Subnet id used for the Runner and Runner Workers. Must belong to the `vpc_id`. In case the fleet mode is used, multiple subnets for + the Runner Workers can be provided with runner_worker_docker_machine_instance.subnet_ids. + EOT type = string - default = "iam" } -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." +variable "kms_key_id" { + description = "KMS key id to encrypt the resources. Ensure that CloudWatch and Runner/Runner Workers have access to the provided KMS key." type = string + default = "" } -variable "vpc_id" { - description = "The target VPC for the docker-machine and runner instances." +variable "enable_managed_kms_key" { + description = "Let the module manage a KMS key. Be-aware of the costs of an custom key. Do not specify a `kms_key_id` when `enable_kms` is set to `true`." + type = bool + default = false +} + +variable "kms_managed_alias_name" { + description = "Alias added to the created KMS key." type = string + default = "" } -variable "subnet_id" { - description = "Subnet id used for the runner and executors. Must belong to the VPC specified above." +variable "kms_managed_deletion_rotation_window_in_days" { + description = "Key deletion/rotation window for the created KMS key. Set to 0 for no rotation/deletion window." + type = number + default = 7 +} + +variable "iam_permissions_boundary" { + description = "Name of permissions boundary policy to attach to AWS IAM roles" type = string - default = "" # TODO remove as soon as subnet_id_runners and subnet_ids_gitlab_runner are gone. Variable is mandatory now. + default = "" } -variable "fleet_executor_subnet_ids" { - description = "List of subnets used for executors when the fleet mode is enabled. Must belong to the VPC specified above." - type = list(string) - default = [] +variable "environment" { + description = "A name that identifies the environment, used as prefix and for tagging." + type = string } -variable "extra_security_group_ids_runner_agent" { - description = "Optional IDs of extra security groups to apply to the runner agent. This will not apply to the runners spun up when using the docker+machine executor, which is the default." - type = list(string) - default = [] +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} } -variable "metrics_autoscaling" { - description = "A list of metrics to collect. The allowed values are GroupDesiredCapacity, GroupInServiceCapacity, GroupPendingCapacity, GroupMinSize, GroupMaxSize, GroupInServiceInstances, GroupPendingInstances, GroupStandbyInstances, GroupStandbyCapacity, GroupTerminatingCapacity, GroupTerminatingInstances, GroupTotalCapacity, GroupTotalInstances." +variable "suppressed_tags" { + description = "List of tag keys which are automatically removed and never added as default tag by the module." type = list(string) - default = null + default = [] } -variable "fleet_key_pair_name" { - description = "The name of the key pair used by the runner to connect to the docker-machine executors." +variable "security_group_prefix" { + description = "Set the name prefix and overwrite the `Name` tag for all security groups." type = string - default = "fleet-key" + default = "" } -variable "instance_type" { - description = "Instance type used for the GitLab runner." +variable "iam_object_prefix" { + description = "Set the name prefix of all AWS IAM resources." type = string - default = "t3.micro" + default = "" } -variable "runner_instance_ebs_optimized" { - description = "Enable the GitLab runner instance to be EBS-optimized." - type = bool - default = true +/* + * Runner Manager: A manager which creates multiple Runners (only one Runner supported by this module) which in turn creates + * multiple Runner Workers (e.g. docker-machine). + */ +variable "runner_manager" { + description = <<-EOT + For details check https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section + + gitlab_check_interval = Number of seconds between checking for available jobs (check_interval) + maximum_concurrent_jobs = The maximum number of jobs which can be processed by all Runners at the same time (concurrent). + prometheus_listen_address = Defines an address (:) the Prometheus metrics HTTP server should listen on (listen_address). + sentry_dsn = Sentry DSN of the project for the Runner Manager to use (uses legacy DSN format) (sentry_dsn) + EOT + type = object({ + gitlab_check_interval = optional(number, 3) + maximum_concurrent_jobs = optional(number, 10) + prometheus_listen_address = optional(string, "") + sentry_dsn = optional(string, "__SENTRY_DSN_REPLACED_BY_USER_DATA__") + }) + default = {} } -variable "runner_instance_enable_monitoring" { - description = "Enable the GitLab runner instance to have detailed monitoring." - type = bool - default = true +/* + * Runner: The agent that runs the code on the host platform and displays in the UI. + */ +variable "runner_instance" { + description = <<-EOT + additional_tags = Map of tags that will be added to the Runner instance. + collect_autoscaling_metrics = A list of metrics to collect. The allowed values are GroupDesiredCapacity, GroupInServiceCapacity, GroupPendingCapacity, GroupMinSize, GroupMaxSize, GroupInServiceInstances, GroupPendingInstances, GroupStandbyInstances, GroupStandbyCapacity, GroupTerminatingCapacity, GroupTerminatingInstances, GroupTotalCapacity, GroupTotalInstances. + ebs_optimized = Enable EBS optimization for the Runner instance. + max_lifetime_seconds = The maximum time a Runner should live before it is killed. + monitoring = Enable the detailed monitoring on the Runner instance. + name = Name of the Runner instance. + name_prefix = Set the name prefix and override the `Name` tag for the Runner instance. + private_address_only = Restrict the Runner to use private IP addresses only. If this is set to `true` the Runner will use a private IP address only in case the Runner Workers use private addresses only. + root_device_config = The Runner's root block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id` + spot_price = By setting a spot price bid price the Runner is created via a spot request. Be aware that spot instances can be stopped by AWS. Choose \"on-demand-price\" to pay up to the current on demand price for the instance type chosen. + ssm_access = Allows to connect to the Runner via SSM. + type = EC2 instance type used. + use_eip = Assigns an EIP to the Runner. + EOT + type = object({ + additional_tags = optional(map(string)) + collect_autoscaling_metrics = optional(list(string), null) + ebs_optimized = optional(bool, true) + max_lifetime_seconds = optional(number, null) + monitoring = optional(bool, true) + name = string + name_prefix = optional(string) + private_address_only = optional(bool, true) + root_device_config = optional(map(string)) + spot_price = optional(string, null) + ssm_access = optional(bool, false) + type = optional(string, "t3.micro") + use_eip = optional(bool, false) + }) + default = { + name = "gitlab-runner" + } } -variable "runner_instance_spot_price" { - description = "By setting a spot price bid price the runner agent will be created via a spot request. Be aware that spot instances can be stopped by AWS. Choose \"on-demand-price\" to pay up to the current on demand price for the instance type chosen." - type = string - default = null +variable "runner_ami_filter" { + description = "List of maps used to create the AMI filter for the Runner AMI. Must resolve to an Amazon Linux 1 or 2 image." + type = map(list(string)) + + default = { + name = ["amzn2-ami-hvm-2.*-x86_64-ebs"] + } +} + +variable "runner_ami_owners" { + description = "The list of owners used to select the AMI of the Runner instance." + type = list(string) + default = ["amazon"] +} + +variable "runner_networking" { + description = <<-EOT + allow_incoming_ping = Allow ICMP Ping to the Runner. Specify `allow_incoming_ping_security_group_ids` too! + allow_incoming_ping_security_group_ids = A list of security group ids that are allowed to ping the Runner. + security_group_description = A description for the Runner's security group + security_group_ids = IDs of security groups to add to the Runner. + EOT + type = object({ + allow_incoming_ping = optional(bool, false) + allow_incoming_ping_security_group_ids = optional(list(string), []) + security_group_description = optional(string, "A security group containing gitlab-runner agent instances") + security_group_ids = optional(list(string), []) + }) + default = {} +} + +variable "runner_networking_egress_rules" { + description = "List of egress rules for the Runner." + type = list(object({ + cidr_blocks = list(string) + ipv6_cidr_blocks = list(string) + prefix_list_ids = list(string) + from_port = number + protocol = string + security_groups = list(string) + self = bool + to_port = number + description = string + })) + default = [ + { + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + prefix_list_ids = null + from_port = 0 + protocol = "-1" + security_groups = null + self = null + to_port = 0 + description = null + } + ] +} + +variable "runner_role" { + description = <<-EOT + additional_tags = Map of tags that will be added to the role created. Useful for tag based authorization. + allow_iam_service_linked_role_creation = Boolean used to control attaching the policy to the Runner to create service linked roles. + assume_role_policy_json = The assume role policy for the Runner. + create_role_profile = Whether to create the IAM role/profile for the Runner. If you provide your own role, make sure that it has the required permissions. + policy_arns = List of policy ARNs to be added to the instance profile of the Runner. + role_profile_name = IAM role/profile name for the Runner. If unspecified then `$${var.iam_object_prefix}-instance` is used. + EOT + type = object({ + additional_tags = optional(map(string)) + allow_iam_service_linked_role_creation = optional(bool, true) + assume_role_policy_json = optional(string, "") + create_role_profile = optional(bool, true) + policy_arns = optional(list(string), []) + role_profile_name = optional(string) + }) + default = {} } -variable "runner_instance_metadata_options" { - description = "Enable the Gitlab runner agent instance metadata service." +variable "runner_metadata_options" { + description = "Enable the Runner instance metadata service. IMDSv2 is enabled by default." type = object({ http_endpoint = string http_tokens = string @@ -89,132 +229,260 @@ variable "runner_instance_metadata_options" { } } -variable "docker_machine_instance_metadata_options" { - description = "Enable the docker machine instances metadata service. Requires you use GitLab maintained docker machines." - type = object({ - http_tokens = string - http_put_response_hop_limit = number - }) - default = { - http_tokens = "required" - http_put_response_hop_limit = 2 - } +variable "runner_schedule_enable" { + description = "Set to `true` to enable the auto scaling group schedule for the Runner." + type = bool + default = false } -variable "docker_machine_instance_type" { - description = "Instance type used for the instances hosting docker-machine." - type = string - default = "m5.large" + +variable "runner_enable_asg_recreation" { + description = "Enable automatic redeployment of the Runner's ASG when the Launch Configs change." + default = true + type = bool } -variable "docker_machine_instance_types_fleet" { - description = "Instance types used for the instances hosting docker-machine. This variable is only supported when use_fleet is set to true." - type = list(string) - default = [] +variable "runner_schedule_config" { + description = "Map containing the configuration of the ASG scale-out and scale-in for the Runner. Will only be used if `agent_schedule_enable` is set to `true`. " + type = map(any) + default = { + # Configure optional scale_out scheduled action + scale_out_recurrence = "0 8 * * 1-5" + scale_out_count = 1 # Default for min_size, desired_capacity and max_size + scale_out_time_zone = "Etc/UTC" + # Override using: scale_out_min_size, scale_out_desired_capacity, scale_out_max_size + + # Configure optional scale_in scheduled action + scale_in_recurrence = "0 18 * * 1-5" + scale_in_count = 0 # Default for min_size, desired_capacity and max_size + scale_in_time_zone = "Etc/UTC" + # Override using: scale_out_min_size, scale_out_desired_capacity, scale_out_max_size + } } -variable "docker_machine_spot_price_bid" { - description = "Spot price bid. The maximum price willing to pay. By default the price is limited by the current on demand price for the instance type chosen." - type = string - default = "on-demand-price" +variable "runner_install" { + description = <<-EOT + amazon_ecr_credentials_helper = Install amazon-ecr-credential-helper inside `userdata_pre_install` script + docker_machine_download_url = URL to download docker machine binary. If not set, the docker machine version will be used to download the binary. + docker_machine_version = By default docker_machine_download_url is used to set the docker machine version. This version will be ignored once `docker_machine_download_url` is set. The version number is maintained by the CKI project. Check out at https://gitlab.com/cki-project/docker-machine/-/releases + pre_install_script = Script to run before installing the Runner + post_install_script = Script to run after installing the Runner + start_script = Script to run after starting the Runner + yum_update = Update the yum packages before installing the Runner + EOT + type = object({ + amazon_ecr_credential_helper = optional(bool, false) + docker_machine_download_url = optional(string, "") + docker_machine_version = optional(string, "0.16.2-gitlab.19-cki.2") + pre_install_script = optional(string, "") + post_install_script = optional(string, "") + start_script = optional(string, "") + yum_update = optional(bool, true) + }) + default = {} } -variable "docker_machine_download_url" { - description = "(Optional) By default the module will use `docker_machine_version` to download the CKI maintained version (https://gitlab.com/cki-project/docker-machine) of Docker Machine. Alternative you can set this property to download location of the distribution of for the OS. See also https://docs.gitlab.com/runner/executors/docker_machine.html#install" - type = string - default = "" +variable "runner_cloudwatch" { + description = <<-EOT + enable = Boolean used to enable or disable the CloudWatch logging. + log_group_name = Option to override the default name (`environment`) of the log group. Requires `enable = true`. + retention_days = Retention for cloudwatch logs. Defaults to unlimited. Requires `enable = true`. + EOT + type = object({ + enable = optional(bool, true) + log_group_name = optional(string, null) + retention_days = optional(number, 0) + }) + default = {} } -variable "docker_machine_version" { - description = "By default docker_machine_download_url is used to set the docker machine version. This version will be ignored once `docker_machine_download_url` is set. The version number is maintained by the CKI project. Check out at https://gitlab.com/cki-project/docker-machine/-/releases" - type = string - default = "0.16.2-gitlab.19-cki.2" +variable "runner_gitlab_registration_config" { + description = "Configuration used to register the Runner. See the README for an example, or reference the examples in the examples directory of this repo. There is also a good GitLab documentation available at: https://docs.gitlab.com/ee/ci/runners/configure_runners.html" + type = object({ + registration_token = optional(string, "") + tag_list = optional(string, "") + description = optional(string, "") + locked_to_project = optional(string, "") + run_untagged = optional(string, "") + maximum_timeout = optional(string, "") + access_level = optional(string, "") + }) + + default = {} } -variable "runners_name" { - description = "Name of the runner, will be used in the runner config.toml." - type = string +variable "runner_gitlab" { + description = <<-EOT + ca_certificate = Trusted CA certificate bundle (PEM format). + certificate = Certificate of the GitLab instance to connect to (PEM format). + registration_token = Registration token to use to register the Runner. Do not use. This is replaced by the `registration_token` in `runner_gitlab_registration_config`. + runner_version = Version of the [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/releases). + 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({ + ca_certificate = optional(string, "") + certificate = optional(string, "") + registration_token = optional(string, "__REPLACED_BY_USER_DATA__") + runner_version = optional(string, "15.8.2") + url = optional(string) + url_clone = optional(string) + }) } -variable "runners_userdata" { - description = "Cloud-init user data that will be passed to the runner ec2 instance. Available only for `docker+machine` driver. Should not be base64 encrypted." +variable "runner_gitlab_registration_token_secure_parameter_store_name" { + description = "The name of the SSM parameter to read the GitLab Runner registration token from." type = string - default = "" + default = "gitlab-runner-registration-token" } -variable "runners_executor" { - description = "The executor to use. Currently supports `docker+machine` or `docker`." +variable "runner_gitlab_token_secure_parameter_store" { + description = "Name of the Secure Parameter Store entry to hold the GitLab Runner token." type = string - default = "docker+machine" - - validation { - condition = contains(["docker+machine", "docker"], var.runners_executor) - error_message = "The executor currently supports `docker+machine` or `docker`." - } + default = "runner-token" } -variable "runners_install_amazon_ecr_credential_helper" { - description = "Install amazon-ecr-credential-helper inside `userdata_pre_install` script" - type = bool - default = false +variable "runner_sentry_secure_parameter_store_name" { + description = "The Sentry DSN name used to store the Sentry DSN in Secure Parameter Store" + type = string + default = "sentry-dsn" } -variable "runners_gitlab_url" { - description = "URL of the GitLab instance to connect to." +variable "runner_terminate_ec2_lifecycle_hook_name" { + description = "Specifies a custom name for the ASG terminate lifecycle hook and related resources." type = string + default = null } -variable "runners_clone_url" { - description = "Overwrites the URL for the GitLab instance. Use only if the runner can’t connect to the GitLab URL." +variable "runner_terraform_timeout_delete_asg" { + description = "Timeout when trying to delete the Runner ASG." + default = "10m" type = string - default = "" } -variable "runners_token" { - description = "Token for the runner, will be used in the runner config.toml." - type = string - default = "__REPLACED_BY_USER_DATA__" +/* + * Runner Worker: The process created by the Runner on the host computing platform to run jobs. + */ +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`. + 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") + }) + default = {} + + validation { + condition = contains(["docker+machine", "docker"], var.runner_worker.type) + error_message = "The executor currently supports `docker+machine` and `docker`." + } } -variable "runners_limit" { - description = "Limit for the runners, will be used in the runner config.toml." - type = number - default = 0 +variable "runner_worker_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 + + access_log_bucker_id = The ID of the bucket where the access logs are stored. + access_log_bucket_prefix = The bucket prefix for the access logs. + authentication_type = A string that declares the AuthenticationType for [runners.cache.s3]. Can either be 'iam' or 'credentials' + bucket = Name of the cache bucket. Requires `create = false`. + bucket_prefix = Prefix for s3 cache bucket name. Requires `create = true`. + create = Boolean used to enable or disable the creation of the cache bucket. + expiration_days = Number of days before cache objects expire. Requires `create = true`. + include_account_id = Boolean used to include the account id in the cache bucket name. Requires `create = true`. + policy = Policy to use for the cache bucket. Requires `create = false`. + random_suffix = Boolean used to enable or disable the use of a random string suffix on the cache bucket name. Requires `create = true`. + shared = Boolean used to enable or disable the use of the cache bucket as shared cache. + versioning = Boolean used to enable versioning on the cache bucket. Requires `create = true`. + EOT + type = object({ + access_log_bucket_id = optional(string, null) + access_log_bucket_prefix = optional(string, null) + authentication_type = optional(string, "iam") + bucket = optional(string, "") + bucket_prefix = optional(string, "") + create = optional(bool, true) + expiration_days = optional(number, 1) + include_account_id = optional(bool, true) + policy = optional(string, "") + random_suffix = optional(bool, false) + shared = optional(bool, false) + versioning = optional(bool, false) + }) + default = {} } -variable "runners_concurrent" { - description = "Concurrent value for the runners, will be used in the runner config.toml." - type = number - default = 10 +variable "runner_worker_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, "\"\"") + }) + default = {} } -variable "runners_idle_time" { - description = "Idle time of the runners, will be used in the runner config.toml." - type = number - default = 600 +/* + * Docker Executor variables. + */ +variable "runner_worker_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 + })) + default = [] } -variable "runners_idle_count" { - description = "Idle count of the runners, will be used in the runner config.toml." - type = number - default = 0 +variable "runner_worker_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) + })) + default = [] } -variable "runners_max_builds" { - description = "Max builds for each runner after which it will be removed, will be used in the runner config.toml. By default set to 0, no maxBuilds will be set in the configuration." - type = number - default = 0 +variable "runner_worker_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 + })) + default = [] } -variable "runners_add_dind_volumes" { +variable "runner_worker_docker_add_dind_volumes" { description = "Add certificates and docker.sock to the volumes to support docker-in-docker (dind)" type = bool default = false } -variable "runners_docker_options" { +variable "runner_worker_docker_options" { description = < 0 - ]) - - error_message = "Please specify an attribute that affects Autoscaling." - } - default = [] -} - -variable "runners_root_size" { - description = "Runner instance root size in GB." - type = number - default = 16 + default = [ + { + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + prefix_list_ids = null + from_port = 0 + protocol = "-1" + security_groups = null + self = null + to_port = 0 + description = "Allow all egress traffic for Runner Workers." + } + ] } -variable "runners_volume_type" { - description = "Runner instance volume type" +variable "runner_worker_docker_machine_security_group_description" { + description = "A description for the Runner Worker security group" type = string - default = "gp2" + default = "A security group containing Runner Worker instances" } -variable "runners_iam_instance_profile_name" { - description = "IAM instance profile name of the runners, will be used in the runner config.toml" - type = string - default = "" -} +variable "runner_worker_docker_machine_ami_filter" { + description = "List of maps used to create the AMI filter for the Runner Worker." + type = map(list(string)) -variable "runners_docker_registry_mirror" { - description = "The docker registry mirror to use to avoid rate limiting by hub.docker.com" - type = string - default = "" + default = { + name = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] + } } -variable "runners_environment_vars" { - description = "Environment variables during build execution, e.g. KEY=Value, see runner-public example. Will be used in the runner config.toml" +variable "runner_worker_docker_machine_ami_owners" { + description = "The list of owners used to select the AMI of the Runner Worker." type = list(string) - default = [] -} -variable "runners_pre_build_script" { - description = "Script to execute in the pipeline just before the build, will be used in the runner config.toml" - type = string - default = "\"\"" + # Canonical + default = ["099720109477"] } -variable "runners_post_build_script" { - description = "Commands to be executed on the Runner just after executing the build, but before executing after_script. " - type = string - default = "\"\"" -} +variable "runner_worker_docker_machine_instance" { + description = <<-EOT + For detailed documentation check https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section + + docker_registry_mirror_url = The URL of the Docker registry mirror to use for the Runner Worker. + destroy_after_max_builds = Destroy the instance after the maximum number of builds has been reached. + ebs_optimized = Enable EBS optimization for the Runner Worker. + idle_count = Number of idle Runner Worker instances (not working for the Docker Runner Worker) (IdleCount). + idle_time = Idle time of the Runner Worker before they are destroyed (not working for the Docker Runner Worker) (IdleTime). + monitoring = Enable detailed monitoring for the Runner Worker. + name_prefix = Set the name prefix and override the `Name` tag for the Runner Worker. + private_address_only = Restrict Runner Worker to the use of a private IP address. If `runner_instance.use_private_address_only` is set to `true` (default), `runner_worker_docker_machine_instance.private_address_only` will also apply for the Runner. + root_size = The size of the root volume for the Runner Worker. + start_script = Cloud-init user data that will be passed to the Runner Worker. Should not be base64 encrypted. + subnet_ids = The list of subnet IDs to use for the Runner Worker when the fleet mode is enabled. + types = The type of instance to use for the Runner Worker. In case of fleet mode, multiple instance types are supported. + volume_type = The type of volume to use for the Runner Worker. + EOT + type = object({ + destroy_after_max_builds = optional(number, 0) + docker_registry_mirror_url = optional(string, "") + ebs_optimized = optional(bool, true) + idle_count = optional(number, 0) + idle_time = optional(number, 600) + monitoring = optional(bool, false) + name_prefix = optional(string, "") + private_address_only = optional(bool, true) + root_size = optional(number, 8) + start_script = optional(string, "") + subnet_ids = optional(list(string), []) + types = optional(list(string), ["m5.large"]) + volume_type = optional(string, "gp2") + }) + default = { + } -variable "runners_pre_clone_script" { - description = "Commands to be executed on the Runner before cloning the Git repository. this can be used to adjust the Git client configuration first, for example. " - type = string - default = "\"\"" -} - -variable "runners_request_concurrency" { - description = "Limit number of concurrent requests for new jobs from GitLab (default 1)." - type = number - default = 1 -} - -variable "runners_output_limit" { - description = "Sets the maximum build log size in kilobytes, by default set to 4096 (4MB)." - type = number - default = 4096 -} - -variable "userdata_pre_install" { - description = "User-data script snippet to insert before GitLab runner install" - type = string - default = "" -} - -variable "userdata_post_install" { - description = "User-data script snippet to insert after GitLab runner install" - type = string - default = "" -} - -variable "runners_use_private_address" { - description = "Restrict runners to the use of a private IP address. If `runner_agent_uses_private_address` is set to `true`(default), `runners_use_private_address` will also apply for the agent." - type = bool - default = true -} - -variable "runner_agent_uses_private_address" { - description = "Restrict the runner agent to the use of a private IP address. If `runner_agent_uses_private_address` is set to `false` it will override the `runners_use_private_address` for the agent." - type = bool - default = true -} - -variable "runners_request_spot_instance" { - description = "Whether or not to request spot instances via docker-machine" - type = bool - default = true -} - -variable "runners_check_interval" { - description = "defines the interval length, in seconds, between new jobs check." - type = number - default = 3 -} - -variable "cache_logging_bucket" { - type = string - description = "S3 Bucket ID where the access logs to the cache bucket are stored." - default = null -} - -variable "cache_logging_bucket_prefix" { - type = string - description = "Prefix within the `cache_logging_bucket`." - default = null -} - -variable "cache_bucket_prefix" { - description = "Prefix for s3 cache bucket name." - type = string - default = "" -} - -variable "cache_bucket_name_include_account_id" { - description = "Boolean to add current account ID to cache bucket name." - type = bool - default = true -} - -variable "cache_bucket_set_random_suffix" { - description = "Append the cache bucket name with a random string suffix" - type = bool - default = false -} - -variable "cache_bucket_versioning" { - description = "Boolean used to enable versioning on the cache bucket, false by default." - type = bool - default = false -} - -variable "cache_expiration_days" { - description = "Number of days before cache objects expires." - type = number - default = 1 -} - -variable "cache_shared" { - description = "Enables cache sharing between runners, false by default." - type = bool - default = false -} - -variable "gitlab_runner_version" { - description = "Version of the [GitLab runner](https://gitlab.com/gitlab-org/gitlab-runner/-/releases)." - type = string - default = "15.8.2" -} - -variable "enable_ping" { - description = "Allow ICMP Ping to the ec2 instances." - type = bool - default = false -} - -variable "gitlab_runner_egress_rules" { - description = "List of egress rules for the gitlab runner instance." - type = list(object({ - cidr_blocks = list(string) - ipv6_cidr_blocks = list(string) - prefix_list_ids = list(string) - from_port = number - protocol = string - security_groups = list(string) - self = bool - to_port = number - description = string - })) - default = [{ - cidr_blocks = ["0.0.0.0/0"] - ipv6_cidr_blocks = ["::/0"] - prefix_list_ids = null - from_port = 0 - protocol = "-1" - security_groups = null - self = null - to_port = 0 - description = null - }] -} - -variable "gitlab_runner_security_group_ids" { - description = "A list of security group ids that are allowed to access the gitlab runner agent" - type = list(string) - default = [] -} - -variable "gitlab_runner_security_group_description" { - description = "A description for the gitlab-runner security group" - type = string - default = "A security group containing gitlab-runner agent instances" -} - -variable "enable_cloudwatch_logging" { - description = "Boolean used to enable or disable the CloudWatch logging." - type = bool - default = true -} - -variable "cloudwatch_logging_retention_in_days" { - description = "Retention for cloudwatch logs. Defaults to unlimited" - type = number - default = 0 -} - -variable "tags" { - description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." - type = map(string) - default = {} -} - -variable "agent_tags" { - description = "Map of tags that will be added to agent EC2 instances." - type = map(string) - default = {} -} - -variable "runner_tags" { - description = "Map of tags that will be added to runner EC2 instances." - type = map(string) - default = {} -} - -variable "suppressed_tags" { - description = "List of tag keys which are removed from tags, agent_tags and runner_tags and never added as default tag by the module." - type = list(string) - default = [] -} - -variable "role_tags" { - description = "Map of tags that will be added to the role created. Useful for tag based authorization." - type = map(string) - default = {} -} - -variable "allow_iam_service_linked_role_creation" { - description = "Boolean used to control attaching the policy to a runner instance to create service linked roles." - type = bool - default = true -} - -variable "docker_machine_options" { - # cspell:ignore amazonec - description = "List of additional options for the docker machine config. Each element of this list must be a key=value pair. E.g. '[\"amazonec2-zone=a\"]'" - type = list(string) - default = [] -} - -variable "instance_role_json" { - description = "Default runner instance override policy, expected to be in JSON format." - type = string - default = "" -} - -variable "docker_machine_role_json" { - description = "Docker machine runner instance override policy, expected to be in JSON format." - type = string - default = "" -} - -variable "docker_machine_security_group_description" { - description = "A description for the docker-machine security group" - type = string - default = "A security group containing docker-machine instances" -} - -variable "ami_filter" { - description = "List of maps used to create the AMI filter for the Gitlab runner agent AMI. Must resolve to an Amazon Linux 1 or 2 image." - type = map(list(string)) - - default = { - name = ["amzn2-ami-hvm-2.*-x86_64-ebs"] - } -} - -variable "ami_owners" { - description = "The list of owners used to select the AMI of Gitlab runner agent instances." - type = list(string) - default = ["amazon"] -} - -variable "runner_ami_filter" { - description = "List of maps used to create the AMI filter for the Gitlab runner docker-machine AMI." - type = map(list(string)) - - default = { - name = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] - } -} - -variable "runner_ami_owners" { - description = "The list of owners used to select the AMI of Gitlab runner docker-machine instances." - type = list(string) - - # Canonical - default = ["099720109477"] -} - -variable "gitlab_runner_registration_config" { - description = "Configuration used to register the runner. See the README for an example, or reference the examples in the examples directory of this repo." - type = map(string) - - default = { - registration_token = "" - tag_list = "" - description = "" - locked_to_project = "" - run_untagged = "" - maximum_timeout = "" - access_level = "" + validation { + condition = length(var.runner_worker_docker_machine_instance.name_prefix) <= 28 + error_message = "Maximum length for docker+machine executor name is 28 characters!" } -} - -variable "secure_parameter_store_gitlab_runner_registration_token_name" { - description = "The name of the SSM parameter to read the GitLab Runner registration token from." - type = string - default = "gitlab-runner-registration-token" -} - -variable "secure_parameter_store_runner_token_key" { - description = "The key name used store the Gitlab runner token in Secure Parameter Store" - type = string - default = "runner-token" -} - -variable "secure_parameter_store_runner_sentry_dsn" { - description = "The Sentry DSN name used to store the Sentry DSN in Secure Parameter Store" - type = string - default = "sentry-dsn" -} - -variable "enable_manage_gitlab_token" { - description = "(Deprecated) Boolean to enable the management of the GitLab token in SSM. If `true` the token will be stored in SSM, which means the SSM property is a terraform managed resource. If `false` the Gitlab token will be stored in the SSM by the user-data script during creation of the the instance. However the SSM parameter is not managed by terraform and will remain in SSM after a `terraform destroy`." - type = bool - default = null validation { - # false positive. There is no secret! - # kics-scan ignore-line - condition = anytrue([var.enable_manage_gitlab_token == null]) - error_message = "Deprecated, this variable is no longer in use and can be removed." + condition = var.runner_worker_docker_machine_instance.name_prefix == "" || can(regex("^[a-zA-Z0-9\\.-]+$", var.runner_worker_docker_machine_instance.name_prefix)) + error_message = "Valid characters for the docker+machine executor name are: [a-zA-Z0-9\\.-]." } } -variable "overrides" { +variable "runner_worker_docker_machine_instance_spot" { description = <<-EOT - This map provides the possibility to override some defaults. - The following attributes are supported: - * `name_sg` set the name prefix and overwrite the `Name` tag for all security groups created by this module. - * `name_runner_agent_instance` set the name prefix and override the `Name` tag for the EC2 gitlab runner instances defined in the auto launch configuration. - * `name_docker_machine_runners` override the `Name` tag of EC2 instances created by the runner agent (used as name prefix for `docker_machine_version` >= 0.16.2). - * `name_iam_objects` set the name prefix of all AWS IAM resources created by this module. + 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 = map(string) - - default = { - name_sg = "" - name_iam_objects = "" - name_runner_agent_instance = "" - name_docker_machine_runners = "" - } - - validation { - condition = length(var.overrides["name_docker_machine_runners"]) <= 28 - error_message = "Maximum length for name_docker_machine_runners is 28 characters!" - } - - validation { - condition = var.overrides["name_docker_machine_runners"] == "" || can(regex("^[a-zA-Z0-9\\.-]+$", var.overrides["name_docker_machine_runners"])) - error_message = "Valid characters for the docker machine name are: [a-zA-Z0-9\\.-]." - } -} - -variable "cache_bucket" { - description = "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 runners disable the creation of the cache and provide a policy and bucket name. See the public runner example for more details." - type = map(any) - - default = { - create = true - policy = "" - bucket = "" - } -} - -variable "enable_runner_user_data_trace_log" { - description = "Enable bash trace for the user data script that creates the EC2 instance for the runner agent. Be aware this could log sensitive data such as you GitLab runner token." - type = bool - default = true + type = object({ + enable = optional(bool, true) + max_price = optional(string, "on-demand-price") + }) + default = {} } -variable "enable_schedule" { - description = "Flag used to enable/disable auto scaling group schedule for the runner instance. " - type = bool - default = false +variable "runner_worker_docker_machine_ec2_options" { + description = "List of additional options for the docker+machine config. Each element of this list must be a key=value pair. E.g. '[\"amazonec2-zone=a\"]'" + type = list(string) + default = [] } -variable "schedule_config" { - description = "Map containing the configuration of the ASG scale-out and scale-in for the runner instance. Will only be used if enable_schedule is set to true. " - type = map(any) +variable "runner_worker_docker_machine_ec2_metadata_options" { + description = "Enable the Runner Worker metadata service. Requires you use CKI maintained docker machines." + type = object({ + http_tokens = string + http_put_response_hop_limit = number + }) default = { - # Configure optional scale_out scheduled action - scale_out_recurrence = "0 8 * * 1-5" - scale_out_count = 1 # Default for min_size, desired_capacity and max_size - scale_out_time_zone = "Etc/UTC" - # Override using: scale_out_min_size, scale_out_desired_capacity, scale_out_max_size - - # Configure optional scale_in scheduled action - scale_in_recurrence = "0 18 * * 1-5" - scale_in_count = 0 # Default for min_size, desired_capacity and max_size - scale_in_time_zone = "Etc/UTC" - # Override using: scale_out_min_size, scale_out_desired_capacity, scale_out_max_size + http_tokens = "required" + http_put_response_hop_limit = 2 } } -variable "runner_root_block_device" { - description = "The EC2 instance root block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`" - type = map(string) - default = {} -} - -variable "enable_runner_ssm_access" { - description = "Add IAM policies to the runner agent instance to connect via the Session Manager." - type = bool - default = false -} - -variable "enable_docker_machine_ssm_access" { - description = "Add IAM policies to the docker-machine instances to connect via the Session Manager." - type = bool - default = false -} - -variable "runners_volumes_tmpfs" { - description = "Mount a tmpfs in runner container. https://docs.gitlab.com/runner/executors/docker.html#mounting-a-directory-in-ram" - type = list(object({ - volume = string - options = string - })) - default = [] -} - -variable "runners_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 - })) - default = [] -} - -variable "runners_docker_services" { - description = "adds `runners.docker.services` blocks to config.toml. All fields must be set (examine the Dockerfile of the service image for the entrypoint - see ./examples/runner-default/main.tf)" +variable "runner_worker_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({ - name = string - alias = string - entrypoint = list(string) - command = list(string) + 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") })) default = [] } -variable "kms_key_id" { - description = "KMS key ARN to encrypt the resources. Ensure CloudWatch has access to the provided KMS key (see policies/kms-policy.json)." - type = string - default = "" -} - -variable "enable_kms" { - description = "Let the module manage a KMS key, logs will be encrypted via KMS. Be-aware of the costs of an custom key." - type = bool - default = false -} - -variable "kms_alias_name" { - description = "Alias added to the kms_key (if created and not provided by kms_key_id)" - type = string - default = "" -} - -variable "kms_deletion_window_in_days" { - description = "Key rotation window, set to 0 for no rotation. Only used when `enable_kms` is set to `true`." - type = number - default = 7 -} - -variable "use_fleet" { - description = "Use the fleet mode for agents. https://gitlab.com/cki-project/docker-machine/-/blob/v0.16.2-gitlab.19-cki.2/docs/drivers/aws.md#fleet-mode" - type = bool - default = false -} - -variable "enable_eip" { - description = "Enable the assignment of an EIP to the gitlab runner instance" - default = false - type = bool -} - -variable "enable_asg_recreation" { - description = "Enable automatic redeployment of the Runner ASG when the Launch Configs change." - default = true - type = bool -} - -variable "asg_delete_timeout" { - description = "Timeout when trying to delete the Runner ASG." - default = "10m" - type = string -} - -variable "asg_max_instance_lifetime" { - description = "The seconds before an instance is refreshed in the ASG." - default = null - type = number -} - -variable "permissions_boundary" { - description = "Name of permissions boundary policy to attach to AWS IAM roles" - default = "" - type = string -} - -variable "log_group_name" { - description = "Option to override the default name (`environment`) of the log group, requires `enable_cloudwatch_logging = true`." - default = null - type = string -} - -variable "runner_iam_role_name" { - type = string - description = "IAM role name of the gitlab runner agent EC2 instance. If unspecified then `{name_iam_objects}-instance` is used" - default = "" -} - -variable "create_runner_iam_role" { - type = bool - description = "Whether to create the runner IAM role of the gitlab runner agent EC2 instance." - default = true -} - -variable "runner_iam_policy_arns" { - type = list(string) - description = "List of policy ARNs to be added to the instance profile of the gitlab runner agent ec2 instance." - default = [] -} - -variable "docker_machine_iam_policy_arns" { - type = list(string) - description = "List of policy ARNs to be added to the instance profile of the docker machine runners." - default = [] -} - -variable "sentry_dsn" { - default = "__SENTRY_DSN_REPLACED_BY_USER_DATA__" - description = "Sentry DSN of the project for the runner to use (uses legacy DSN format)" - type = string -} - -variable "prometheus_listen_address" { - default = "" - description = "Defines an address (:) the Prometheus metrics HTTP server should listen on." - type = string -} - -variable "docker_machine_egress_rules" { - description = "List of egress rules for the docker-machine instance(s)." - type = list(object({ - cidr_blocks = list(string) - ipv6_cidr_blocks = list(string) - prefix_list_ids = list(string) - from_port = number - protocol = string - security_groups = list(string) - self = bool - to_port = number - description = string - })) - default = [{ - cidr_blocks = ["0.0.0.0/0"] - ipv6_cidr_blocks = ["::/0"] - prefix_list_ids = null - from_port = 0 - protocol = "-1" - security_groups = null - self = null - to_port = 0 - description = "Allow all egress traffic for docker machine build runners" - }] -} - -variable "asg_terminate_lifecycle_hook_name" { - description = "Specifies a custom name for the ASG terminate lifecycle hook and related resources." - type = string - default = null -} - -variable "runner_yum_update" { - description = "Run a yum update as part of starting the runner" - type = bool - default = true -} - -variable "runners_gitlab_certificate" { - description = "Certificate of the GitLab instance to connect to. Example: `file(\"$${path.module}/my-gitlab.crt\")`" - type = string - default = "" -} - -variable "runners_ca_certificate" { - description = "Trusted CA certificate bundle. Example: `file(\"$${path.module}/ca.crt\")`" - type = string - default = "" -} - -variable "runner_extra_config" { - description = "Extra commands to run as part of starting the runner" - type = string - default = "" -} - -variable "show_user_data_in_plan" { - description = "When enabled, shows the diff for agent configuration files in Terraform plan: `config.toml` and user data script" - type = bool - default = false - validation { - condition = !var.show_user_data_in_plan - error_message = "The variable is deprecated. Please use the 'debug' variable instead." - } -} - variable "debug" { - description = <