diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index 7600c32..0cbb5e8 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -2,109 +2,45 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.50.0" - constraints = ">= 2.0.0, >= 3.0.0, ~> 4.0" + version = "5.100.0" + constraints = ">= 5.0.0, ~> 5.0, < 6.0.0" hashes = [ - "h1:g7fn+osqp+sxM2ExA4CfKLEBxBmkPWctKnsIRmq0l+E=", - "h1:jYbnOsQkAQ2O2eiZU3B5LACcEz0eoqX4cZNEjzMar8Q=", - "zh:03a5795ea9ed3eb80e0d5e0c5234dc76455aa4437e5546399127939c24a60973", - "zh:24556a15eb4a69955857b3a52322f099e68031e6f9a3df2cfdb6f6351cc4885e", - "zh:2c2a18f3da3c06f9da5f2aca485d0b324c8510f2afb70fc1470bcb31485db061", - "zh:37f194e62f7b433b7235b6e4f6954dd9352554ad044007802d3fa9b80a7a7331", - "zh:4591157be7c8ec8160186a74789c44f214c7142f400e2c147b710e25abe15be0", - "zh:53e0f9ca106a9691c20535500cdcf9e4255993536e19ef2fc4c6353bfc7e2e5b", - "zh:54eb4c288adfafe866b3b1fcc0550ddd025f59843cfa6dd3310fed85c766b950", - "zh:56e887eba5bb6dd60eb2c72d09eba34232b59a0c83ac1f3693e4064ebd2af02f", - "zh:57858a160b5dc3c454697798d38e528662c9234f9ab1742f6c5b3bd0414e0578", - "zh:6ce0a31d9b1bf2dc069414c7aeae0a660aa60b58a59e97a1c575786b120a0104", + "h1:Ijt7pOlB7Tr7maGQIqtsLFbl7pSMIj06TVdkoSBcYOw=", + "zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644", + "zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2", + "zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274", + "zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b", + "zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862", + "zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b70d22fa41bb30536fb1be5242701b19b0be8bb50ec6ba03bb5396be3cdac8c6", - "zh:ece8726967858c44a5ae458f7a8438e825128d356fbf1893d41ccb172bb263d9", - "zh:f0f2a8be772add8d0cdadf77fda7ed1c0dfbbeab9801a0d2d8820148653aa8f4", - "zh:fc93015058e9592810aa4b3e7834df1717ba8d6aec4679997d16c030c885d6fc", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.3.0" - constraints = ">= 2.2.1" - hashes = [ - "h1:7y8CXQKtfyvrMCSWgCkCclNN9L161u6jO1dEGVaB5RQ=", - "h1:U+DbBqKnXSIqC2z7qIko2dy8w6wwuZd89orPvfeqHk0=", - "zh:1f1920b3f78c31c6b69cdfe1e016a959667c0e2d01934e1a084b94d5a02cd9d2", - "zh:550a3cdae0ddb350942624e7b2e8b31d28bc15c20511553432413b1f38f4b214", - "zh:68d1d9ccbfce2ce56b28a23b22833a5369d4c719d6d75d50e101a8a8dbe33b9b", - "zh:6ae3ad6d865a906920c313ec2f413d080efe32c230aca711fd106b4cb9022ced", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:a0f413d50f54124057ae3dcd9353a797b84e91dc34bcf85c34a06f8aef1f9b12", - "zh:a2ac6d4088ceddcd73d88505e18b8226a6e008bff967b9e2d04254ef71b4ac6b", - "zh:a851010672e5218bdd4c4ea1822706c9025ef813a03da716d647dd6f8e2cffb0", - "zh:aa797561755041ef2fad99ee9ffc12b5e724e246bb019b21d7409afc2ece3232", - "zh:c6afa960a20d776f54bb1fc260cd13ead17280ebd87f05b9abcaa841ed29d289", - "zh:df0975e86b30bb89717b8c8d6d4690b21db66de06e79e6d6cfda769f3304afe6", - "zh:f0d3cc3da72135efdbe8f4cfbfb0f2f7174827887990a5545e6db1981f0d3a7c", + "zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93", + "zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2", + "zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e", + "zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421", + "zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4", + "zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9", + "zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9", + "zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70", ] } provider "registry.terraform.io/hashicorp/null" { - version = "3.2.1" - constraints = ">= 2.0.0, >= 2.1.0, 3.2.1" - hashes = [ - "h1:tSj1mL6OQ8ILGqR2mDu7OYYYWf+hoir0pf9KAQ8IzO8=", - "h1:ydA0/SNRVB1o95btfshvYsmxA+jZFRZcvKzZSB+4S1M=", - "zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840", - "zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb", - "zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5", - "zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238", - "zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc", - "zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970", - "zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2", - "zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5", - "zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f", - "zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.4.3" - constraints = "~> 3.0" + version = "3.3.0" + constraints = ">= 3.0.0" hashes = [ - "h1:saZR+mhthL0OZl4SyHXZraxyaBNVMxiZzks78nWcZ2o=", - "h1:tL3katm68lX+4lAncjQA9AXL4GR/VM+RPwqYf4D2X8Q=", - "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", - "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", - "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", + "h1:a14TKo7Xvg4W8+H1VA6p+oLZTLxVQnYUD8LOaOs14A8=", + "zh:021748b5ea3b5f6956f2e75c42c5cdc113b391fb98ac71364a4965d23b37000f", + "zh:3b27956f8541d46704fda234e0d535c2ae2a4b33411848b1ee262a1ec03568b0", + "zh:3de4ed47d6d0f4d8edba4a5092c7c9799950eda63989d8d0d2586e6afcb0aa20", + "zh:57ed8935c7d56dbc91cf2673534582cacfaab7a2f105f51d9f797e99df0c0c47", + "zh:58e176ba1d142827089e30e0711e007309a9f2726e8881986da5026e9778fdf4", + "zh:5949c4a3d4a93f841f155cdb7e991c087e637145c1630572e21948224f8f4923", + "zh:76d60f366b743003c1b085afa769b45b2198ee919927e45807d7d44fb42c067d", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", - "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", - "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", - "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", - "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", - "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", - "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", - "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", - ] -} - -provider "registry.terraform.io/hashicorp/tls" { - version = "4.0.4" - constraints = ">= 2.0.0" - hashes = [ - "h1:GZcFizg5ZT2VrpwvxGBHQ/hO9r6g0vYdQqx3bFD3anY=", - "h1:Wd3RqmQW60k2QWPN4sK5CtjGuO1d+CRNXgC+D4rKtXc=", - "zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55", - "zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848", - "zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be", - "zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5", - "zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe", - "zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e", - "zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48", - "zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8", - "zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60", - "zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e", - "zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316", - "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:79cd1bab1261a07f84e917191d7ddc4340ac5f5524283767256f7ffd7f87caf0", + "zh:8ec9083038cf710b30e319eaa467c9df7fa52bbd9969b61053a35bc2cdd2e0a6", + "zh:a6e502cb579685ab7aeb886c2bb11ddd9cfed74b41008592d57cbc3351a9218b", + "zh:acb74d6b4f66ff6acfcda315df802a7432170ef3955c9b432cb4580767004006", + "zh:f0ce55d8d9ffdb33dab612b1246f9bab060a9d54fc32ce2b4a038646155660af", ] } diff --git a/locals.tf b/locals.tf index 2359684..9513166 100644 --- a/locals.tf +++ b/locals.tf @@ -8,6 +8,10 @@ locals { } ] - runner_name = var.runner_name != null ? var.runner_name : "${var.namespace}-${var.environment}-github-runner-${random_string.runner.result}" + # Name for the EC2 instance and its derived IAM/SG/SSM resources. Kept + # deterministic (no random suffix): arc-ec2 uses this name inside a for_each + # key for its inline IAM policies, so it must be known at plan time. + ec2_name = "${var.namespace}-${var.environment}-github-runner" + runner_name = var.runner_name != null ? var.runner_name : local.ec2_name aws_friendly_runner_labels = replace(var.runner_labels, ",", " + ") } diff --git a/main.tf b/main.tf index 742e1c7..eba3965 100644 --- a/main.tf +++ b/main.tf @@ -7,12 +7,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.0" - } - - random = { - source = "hashicorp/random" - version = ">= 3.0" + version = ">= 5.0, < 6.0" } null = { @@ -22,218 +17,98 @@ terraform { } } -resource "random_string" "runner" { - length = 4 - lower = true - numeric = true - min_numeric = 1 - special = false - upper = false -} - ################################################################################ ## lookups ################################################################################ data "aws_caller_identity" "this" {} -data "aws_ssm_parameter" "runner_token" { - name = "/${var.namespace}/${var.environment}/github-runner/token" - - depends_on = [ - null_resource.prepare - ] -} - ################################################################################ -## ssh -################################################################################ -module "ssh_key_pair" { - source = "git::https://github.com/cloudposse/terraform-aws-key-pair?ref=0.18.3" - - namespace = var.namespace - stage = var.environment - name = "github-runner-${random_string.runner.result}" - ssh_public_key_path = "${path.root}/secrets" - generate_ssh_key = "true" - private_key_extension = ".pem" - public_key_extension = ".pub" - - tags = var.tags -} - -################################################################################ -## ec2 +## ec2 — self-hosted GitHub Actions runner (SourceFuse arc-ec2) ################################################################################ module "runner" { - source = "git::https://github.com/cloudposse/terraform-aws-ec2-instance?ref=0.45.2" + source = "sourcefuse/arc-ec2/aws" + version = "0.0.5" - name = "github-runner-${random_string.runner.result}" - namespace = var.namespace - stage = var.environment - ssh_key_pair = module.ssh_key_pair.key_name - vpc_id = var.vpc_id - subnet = var.subnet_id - - ## ami / size - ami = var.ami.id - ami_owner = var.ami.owner_id + name = local.ec2_name + vpc_id = var.vpc_id + subnet_id = var.subnet_id + ami_id = var.ami.id instance_type = var.instance_type - ## monitoring / ssm / volume - monitoring = var.monitoring_enabled - ssm_patch_manager_enabled = var.ssm_patch_manager_enabled - associate_public_ip_address = var.associate_public_ip_address - root_block_device_encrypted = var.root_block_device_encrypted - root_block_device_kms_key_id = var.root_block_device_kms_key_id - root_volume_size = var.root_volume_size - root_volume_type = var.root_volume_type - volume_tags_enabled = var.volume_tags_enabled - - ## security - security_group_rules = var.security_group_rules + associate_public_ip_address = var.associate_public_ip_address + enable_detailed_monitoring = var.monitoring_enabled - tags = merge(var.tags, tomap({ - GitHubRunnerName = local.runner_name - GitHubRunnerLabels = local.aws_friendly_runner_labels - })) -} - -################################################################################ -## s3 -################################################################################ -## s3 -resource "aws_s3_bucket" "runner" { - bucket = module.runner.name - - object_lock_enabled = true - - tags = merge(var.tags, tomap({ - Name = module.runner.name - })) -} - -resource "aws_s3_bucket_server_side_encryption_configuration" "runner" { - bucket = aws_s3_bucket.runner.bucket - - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } + root_block_device_data = { + volume_size = var.root_volume_size + volume_type = var.root_volume_type + encrypted = var.root_block_device_encrypted + kms_key_id = var.root_block_device_kms_key_id } -} -resource "aws_s3_bucket_public_access_block" "runner" { - bucket = aws_s3_bucket.runner.id - - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} - -resource "aws_s3_bucket_logging" "runner" { - bucket = aws_s3_bucket.runner.id - - target_bucket = aws_s3_bucket.runner.id - target_prefix = "log/" -} - -resource "aws_s3_bucket_acl" "runner" { - bucket = aws_s3_bucket.runner.id - acl = "private" -} - -resource "aws_s3_bucket_versioning" "runner" { - bucket = aws_s3_bucket.runner.id - - versioning_configuration { - status = "Enabled" + # Egress-only security group. The runner reaches GitHub / SSM / package repos + # outbound; there is no inbound path (access is via SSM Session Manager, not SSH). + security_group_data = { + create = true + name = "${local.ec2_name}-sg" + description = "Self-hosted GitHub Actions runner" + ingress_rules = [] + egress_rules = [ + { + description = "All outbound (GitHub, SSM, package repositories)" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + ] } -} -resource "aws_s3_object" "docker_compose" { - bucket = aws_s3_bucket.runner.id - key = "docker-compose.yml" + # Instance role (arc-ec2 builds the role + instance profile): + # - managed: SSM core, so the instance is SSM-managed (used for all provisioning) + # - inline: read the registration token from SSM Parameter Store at runtime + # (SecureString -> AWS-managed SSM key, hence kms:Decrypt) + instance_profile_data = { + create = true + managed_policy_arns = var.ec2_runner_iam_role_policy_arns + policy_documents = [ + { + name = "${local.ec2_name}-token-read" + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = ["ssm:GetParameter"], + Resource = "arn:aws:ssm:${var.region}:${data.aws_caller_identity.this.account_id}:parameter/${var.namespace}/${var.environment}/github-runner/token" + }, + { + Effect = "Allow", + Action = ["kms:Decrypt"], + Resource = "arn:aws:kms:${var.region}:${data.aws_caller_identity.this.account_id}:alias/aws/ssm" + } + ] + }) + } + ] + } - content_base64 = base64encode(templatefile("${path.module}/templates/docker-compose.yml.tftpl", { - runner_token = data.aws_ssm_parameter.runner_token.value - runner_owner = var.github_owner - runner_name = local.runner_name - runner_user = var.runner_user - runner_image = var.runner_image - runner_labels = var.runner_labels - repos_or_orgs = var.repos_or_orgs + tags = merge(var.tags, tomap({ + GitHubRunnerName = local.runner_name + GitHubRunnerLabels = local.aws_friendly_runner_labels })) - - depends_on = [ - module.runner, - null_resource.prepare - ] -} - -## iam access -resource "aws_iam_policy" "runner_bucket_access" { - name = "${aws_s3_bucket.runner.id}-access" - - policy = jsonencode( - { - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Action = [ - "kms:DescribeKey", - "kms:GenerateDataKey", - "kms:Encrypt", - "kms:Decrypt" - ], - Resource = "arn:aws:kms:${var.region}:${data.aws_caller_identity.this.account_id}:alias/aws/s3" // s3 aws managed - }, - { - Effect = "Allow", - Action = [ - "s3:ListBucket", - "s3:GetBucketLocation" - ], - Resource = aws_s3_bucket.runner.arn - }, - { - Effect = "Allow", - Action = [ - "s3:GetObjectAttributes", - "s3:GetObject", - "s3:PutObject", - "s3:ListMultipartUploadParts", - "s3:AbortMultipartUpload" - ], - Resource = "${aws_s3_bucket.runner.arn}/*" - } - ] - } - ) -} - -resource "aws_iam_role_policy_attachment" "runner_bucket_access" { - role = module.runner.role - policy_arn = aws_iam_policy.runner_bucket_access.arn -} - -################################################################################ -## iam -################################################################################ -resource "aws_iam_role_policy_attachment" "runner" { - for_each = toset(var.ec2_runner_iam_role_policy_arns) - - role = module.runner.role - policy_arn = each.value } ################################################################################ ## configuration ################################################################################ -## get token for the runner +## Mint a fresh GitHub registration token and store it in SSM Parameter Store. resource "null_resource" "prepare" { triggers = { + # Refresh the runner registration token on EVERY apply. GitHub registration + # tokens expire in ~1h; with static triggers this ran only on the first + # apply, so re-registration later failed with 404. timestamp() forces a + # fresh token each apply. + always_run = timestamp() namespace = var.namespace environment = var.environment github_token = var.github_token @@ -259,15 +134,17 @@ resource "null_resource" "prepare" { } } -## install host dependencies +## Install host dependencies plus the tooling the pipeline jobs need +## (aws, kubectl, helm, terraform, git, node, docker). Runs immediately via the +## association below. resource "aws_ssm_document" "dependencies" { - name = "${module.runner.name}-dependencies" + name = "${local.ec2_name}-dependencies" document_type = "Command" target_type = "/AWS::EC2::Instance" content = jsonencode({ schemaVersion = "2.2" - description = "Install host dependencies." + description = "Install runner host dependencies and CI tooling." mainSteps = [ { @@ -275,21 +152,27 @@ resource "aws_ssm_document" "dependencies" { action = "aws:runShellScript" inputs = { runCommand = [ + "set -eux", "export DEBIAN_FRONTEND=noninteractive", - "export DOCKER_COMPOSE_URL=https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s | tr A-Z a-z)-$(uname -m)", - "sudo su -", "apt-get update", - "apt-get install -y ca-certificates curl gnupg lsb-release unzip", - "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg", - "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" | tee /etc/apt/sources.list.d/docker.list > /dev/null", - "apt-get update", - "apt-get install -y docker-ce docker-ce-cli containerd.io", - "curl -L \"$DOCKER_COMPOSE_URL\" -o /usr/local/bin/docker-compose", - "chmod +x /usr/local/bin/docker-compose", - "cd /tmp", - "curl \"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip\" -o \"awscliv2.zip\"", - "unzip awscliv2.zip", - "[ -f \"/usr/local/bin/aws\" ] || ./aws/install" + # Runner runtime deps (libicu for .NET) + general CI utilities. + "apt-get install -y ca-certificates curl gnupg lsb-release unzip jq git tar libicu70 || apt-get install -y ca-certificates curl gnupg lsb-release unzip jq git tar libicu-dev", + # Node.js — required on the host PATH by the hashicorp/setup-terraform + # wrapper (a #!/usr/bin/env node script). GitHub-hosted runners ship node; + # a self-hosted host does not, so without this every setup-terraform job + # fails with "/usr/bin/env: 'node': No such file or directory" (exit 127). + "if ! command -v node >/dev/null; then curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && apt-get install -y nodejs; fi", + # AWS CLI v2 + "if ! command -v aws >/dev/null; then cd /tmp && curl -fsSL 'https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip' -o awscliv2.zip && unzip -o awscliv2.zip && ./aws/install --update; fi", + # kubectl (latest stable) + "if ! command -v kubectl >/dev/null; then KV=$(curl -fsSL https://dl.k8s.io/release/stable.txt); curl -fsSL \"https://dl.k8s.io/release/$KV/bin/linux/amd64/kubectl\" -o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl; fi", + # helm + "if ! command -v helm >/dev/null; then curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash; fi", + # terraform + "if ! command -v terraform >/dev/null; then curl -fsSL https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg && echo \"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" > /etc/apt/sources.list.d/hashicorp.list && apt-get update && apt-get install -y terraform; fi", + # docker (for jobs that build/run containers) + "if ! command -v docker >/dev/null; then curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg && echo \"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" > /etc/apt/sources.list.d/docker.list && apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io && usermod -aG docker ${var.runner_user} || true; fi", + "systemctl enable --now docker || true" ] } }, @@ -297,7 +180,7 @@ resource "aws_ssm_document" "dependencies" { }) tags = merge(var.tags, tomap({ - Name = "${module.runner.name}-dependencies" + Name = "${local.ec2_name}-dependencies" })) depends_on = [ @@ -317,28 +200,53 @@ resource "aws_ssm_association" "dependencies" { } } -## download docker-compose then start container -resource "aws_ssm_document" "runner_compose" { - name = module.runner.name +## Download the official GitHub Actions runner, register it, and install it as a +## systemd service. We pin a current runner version and let systemd supervise it +## (config persists its own auto-refreshing credentials after the first register, +## so the short-lived registration token is only needed once). This avoids the +## container-image self-update failure that left the runner permanently Offline. +resource "aws_ssm_document" "runner_install" { + name = local.ec2_name document_type = "Command" target_type = "/AWS::EC2::Instance" content = jsonencode({ schemaVersion = "2.2" - description = "Download docker-compose.yml from S3 and start container." + description = "Install and start the GitHub Actions runner as a systemd service." mainSteps = [ { - name = "downloadThenStart" + name = "installRunner" action = "aws:runShellScript" inputs = { runCommand = [ + "set -eux", + "RUNNER_DIR=/opt/actions-runner", + "RUNNER_USER=${var.runner_user}", + "RUNNER_VERSION=${var.runner_version}", + "GH_URL=https://github.com/${var.github_owner}", + # Already configured (e.g. re-run of the association) -> ensure the service is up and exit. + "if [ -f \"$RUNNER_DIR/.runner\" ]; then (cd \"$RUNNER_DIR\" && ./svc.sh start || true); exit 0; fi", + # Install the essentials the runner needs to download/register AND that + # actions/checkout needs (git) BEFORE the runner comes Online. This makes + # registration self-sufficient regardless of when the separate CI-tooling + # association (aws/kubectl/helm/terraform) finishes, so the first job's + # checkout can never lose a race against tool installation. "export DEBIAN_FRONTEND=noninteractive", - "sudo su -", - "mkdir -p /opt/github-runner", - "cd /opt/github-runner/", - "aws s3 cp s3://${aws_s3_bucket.runner.id}/docker-compose.yml .", - "docker-compose rm -fs && docker-compose up -d" // TODO - do something better + "apt-get update -qq || true", + "apt-get install -y -qq git curl tar unzip jq ca-certificates || true", + "id -u \"$RUNNER_USER\" >/dev/null 2>&1 || useradd -m -s /bin/bash \"$RUNNER_USER\"", + "mkdir -p \"$RUNNER_DIR\" && cd \"$RUNNER_DIR\"", + "curl -fsSL -o runner.tar.gz \"https://github.com/actions/runner/releases/download/v$${RUNNER_VERSION}/actions-runner-linux-x64-$${RUNNER_VERSION}.tar.gz\"", + "tar xzf runner.tar.gz && rm -f runner.tar.gz", + "./bin/installdependencies.sh", + "chown -R \"$RUNNER_USER\":\"$RUNNER_USER\" \"$RUNNER_DIR\"", + # Fetch the fresh registration token minted by null_resource.prepare. + "REG_TOKEN=$(aws ssm get-parameter --region ${var.region} --name /${var.namespace}/${var.environment}/github-runner/token --with-decryption --query Parameter.Value --output text)", + "sudo -u \"$RUNNER_USER\" ./config.sh --unattended --replace --url \"$GH_URL\" --token \"$REG_TOKEN\" --name '${local.runner_name}' --labels '${var.runner_labels}' --work _work", + # Install + start as a systemd service owned by the runner user. + "./svc.sh install \"$RUNNER_USER\"", + "./svc.sh start" ] } }, @@ -346,30 +254,28 @@ resource "aws_ssm_document" "runner_compose" { }) tags = merge(var.tags, tomap({ - Name = module.runner.name + Name = local.ec2_name })) } -resource "aws_ssm_association" "runner_compose" { - name = aws_ssm_document.runner_compose.name - association_name = aws_ssm_document.runner_compose.name +resource "aws_ssm_association" "runner_install" { + name = aws_ssm_document.runner_install.name + association_name = aws_ssm_document.runner_install.name apply_only_at_cron_interval = true - schedule_expression = "at(${trimsuffix(timeadd(timestamp(), "150s"), "Z")})" # TODO - do something better + schedule_expression = "at(${trimsuffix(timeadd(timestamp(), "150s"), "Z")})" targets { key = "InstanceIds" values = [module.runner.id] } - # - # lifecycle { - # ignore_changes = [ - # schedule_expression - # ] - # } + + depends_on = [ + aws_ssm_association.dependencies + ] } -## remove runner from github +## remove runner from github on destroy resource "null_resource" "cleanup" { triggers = { github_token = var.github_token @@ -396,6 +302,6 @@ resource "null_resource" "cleanup" { } depends_on = [ - aws_ssm_association.runner_compose + aws_ssm_association.runner_install ] } diff --git a/outputs.tf b/outputs.tf index 1d24c1f..e3b8bc5 100644 --- a/outputs.tf +++ b/outputs.tf @@ -5,15 +5,15 @@ output "ec2_runner_instance_id" { output "ec2_runner_instance_name" { description = "Instance Name of the EC2 Runner" - value = module.runner.name + value = local.ec2_name } output "ec2_runner_role" { - description = "Instance role name" - value = module.runner.role + description = "Instance role name (created by arc-ec2 as -role)" + value = "${local.ec2_name}-role" } output "ec2_runner_role_arn" { description = "Instance role ARN" - value = module.runner.role_arn + value = "arn:aws:iam::${data.aws_caller_identity.this.account_id}:role/${local.ec2_name}-role" } diff --git a/templates/docker-compose.yml.tftpl b/templates/docker-compose.yml.tftpl deleted file mode 100644 index 010d189..0000000 --- a/templates/docker-compose.yml.tftpl +++ /dev/null @@ -1,25 +0,0 @@ -version: "3.9" -name: "${runner_name}" -services: - runner: - image: ${runner_image} - user: ${runner_user} - deploy: - replicas: 1 - restart_policy: - condition: on-failure - delay: 5s - max_attempts: 3 - window: 45s - environment: - %{ if repos_or_orgs == "orgs" } - RUNNER_ORGANIZATION_URL: "https://github.com/${runner_owner}" - %{ else } - RUNNER_REPOSITORY_URL: "https://github.com/${runner_owner}" - %{ endif } - RUNNER_TOKEN: "${runner_token}" - RUNNER_NAME: "${runner_name}" - RUNNER_LABELS: "${runner_labels}" - RUNNER_REPLACE_EXISTING: "true" - volumes: - - /var/run/docker.sock:/var/run/docker.sock diff --git a/test/go.mod b/test/go.mod index 938d55a..212a89f 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,55 +1,43 @@ module github.com/sourcefuse/terraform-aws-refarch-github-runner -go 1.18 +go 1.26.0 + +require ( + github.com/gruntwork-io/terratest v1.0.1 + github.com/stretchr/testify v1.11.1 +) require ( - cloud.google.com/go v0.83.0 // indirect - cloud.google.com/go/storage v1.10.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/aws/aws-sdk-go v1.40.56 // indirect + github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect - github.com/gruntwork-io/terratest v0.41.9 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.6.1 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/go-getter/v2 v2.2.3 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-safetemp v1.0.0 // indirect - github.com/hashicorp/go-version v1.3.0 // indirect - github.com/hashicorp/hcl/v2 v2.9.1 // indirect - github.com/hashicorp/terraform-json v0.13.0 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/hashicorp/hcl/v2 v2.22.0 // indirect + github.com/hashicorp/terraform-json v0.23.0 // indirect github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect - github.com/klauspost/compress v1.13.0 // indirect + github.com/klauspost/compress v1.18.5 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.7.0 // indirect - github.com/tmccombs/hcl2json v0.3.3 // indirect - github.com/ulikunitz/xz v0.5.8 // indirect - github.com/zclconf/go-cty v1.9.1 // indirect - go.opencensus.io v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.4.2 // indirect - golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect - golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect - golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect - golang.org/x/text v0.3.6 // indirect - golang.org/x/tools v0.1.2 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.47.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/grpc v1.38.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect + github.com/tmccombs/hcl2json v0.6.4 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect + github.com/zclconf/go-cty v1.15.0 // indirect + golang.org/x/crypto v0.54.0 // indirect + golang.org/x/mod v0.37.0 // indirect + golang.org/x/sync v0.22.0 // indirect + golang.org/x/sys v0.47.0 // indirect + golang.org/x/text v0.40.0 // indirect + golang.org/x/tools v0.47.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/test/go.sum b/test/go.sum new file mode 100644 index 0000000..87ec575 --- /dev/null +++ b/test/go.sum @@ -0,0 +1,86 @@ +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= +github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/gruntwork-io/terratest v1.0.1 h1:5CCp4Matgw5S42t5VW79mLN3YcaN5cEqNpTprVjuzIQ= +github.com/gruntwork-io/terratest v1.0.1/go.mod h1:2lK9XvvGJ+GhsvA6tO7LpALWG34nu+1QecgexHKAGZ8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk= +github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= +github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M= +github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA= +github.com/hashicorp/terraform-json v0.23.0 h1:sniCkExU4iKtTADReHzACkk8fnpQXrdD2xoR+lppBkI= +github.com/hashicorp/terraform-json v0.23.0/go.mod h1:MHdXbBAbSg0GvzuWazEGKAn/cyNfIB7mN6y7KJN6y2c= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= +github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= +github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= +github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= +github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= +github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/tmccombs/hcl2json v0.6.4 h1:/FWnzS9JCuyZ4MNwrG4vMrFrzRgsWEOVi+1AyYUVLGw= +github.com/tmccombs/hcl2json v0.6.4/go.mod h1:+ppKlIW3H5nsAsZddXPy2iMyvld3SHxyjswOZhavRDk= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/zclconf/go-cty v1.15.0 h1:tTCRWxsexYUmtt/wVxgDClUe+uQusuI443uL6e+5sXQ= +github.com/zclconf/go-cty v1.15.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= +github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= +golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= +golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ= +golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0= +golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= +golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0= +golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q= +golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/variables.tf b/variables.tf index db4f9a8..6a7799c 100644 --- a/variables.tf +++ b/variables.tf @@ -62,12 +62,6 @@ variable "monitoring_enabled" { default = true } -variable "ssm_patch_manager_enabled" { - description = "Whether to enable SSM Patch manager" - type = bool - default = true -} - variable "associate_public_ip_address" { description = "Associate a public IP address with the instance" type = bool @@ -98,12 +92,6 @@ variable "root_volume_type" { default = "gp2" } -variable "volume_tags_enabled" { - description = "Whether or not to copy instance tags to root and EBS volumes" - type = bool - default = true -} - ################################################################################ ## runner ################################################################################ @@ -125,16 +113,20 @@ variable "runner_name" { default = null } -variable "runner_image" { - description = "Name of the image to use for the Actions Runner." +variable "runner_version" { + description = <<-EOT + Version of the official GitHub Actions runner (github.com/actions/runner) to + install on the host. Pin at or above GitHub's current minimum so the runner + is never forced into a self-update. See the releases page for the latest tag. + EOT type = string - default = "sourcefuse/github-runner:0.3.0" + default = "2.336.0" } variable "runner_user" { - description = "Name of the user to run the container as." + description = "OS user that owns and runs the runner systemd service. Created if it does not exist." type = string - default = "runner" + default = "ubuntu" } variable "runner_labels" { @@ -163,26 +155,6 @@ variable "github_token" { type = string } -variable "security_group_rules" { - description = "Security group rules for the EC2 instance running the GitHub Runner" - type = list(object({ - type = string - from_port = number - to_port = number - protocol = string - cidr_blocks = list(string) - })) - default = [ - { - type = "egress" - from_port = 0 - to_port = 65535 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - ] -} - variable "ec2_runner_iam_role_policy_arns" { type = list(string) description = "IAM role policies to attach to the Runner instance"