infra/burst/workers/aws/tests/aws.tftest.hcl (4165 bytes)
1 # terraform test with a mock provider: no account and no cost. 2 3 mock_provider "aws" {} 4 5 override_data { 6 target = data.terraform_remote_state.state 7 values = { 8 outputs = { 9 worker = { 10 web_server_ip = "198.44.53.27" 11 ssh_port = 22 12 known_hosts = "198.44.53.27 ssh-ed25519 AAAAhostkey" 13 tunnel_private_key = "-----BEGIN OPENSSH PRIVATE KEY-----\nTUNNELKEY\n-----END OPENSSH PRIVATE KEY-----\n" 14 database_url = "postgresql+psycopg://subplz:pgpw@127.0.0.1:5432/subplz" 15 redis_url = "redis://:redispw@127.0.0.1:6379/0" 16 bucket = "subplz-files" 17 s3_prefix = "jobs/" 18 storage_env = "AWS_ACCESS_KEY_ID=kid\nAWS_SECRET_ACCESS_KEY=secret\nAWS_ENDPOINT_URL_S3=https://acct.r2.cloudflarestorage.com\nAWS_DEFAULT_REGION=auto\n" 19 } 20 } 21 } 22 } 23 24 variables { 25 workers = { 26 "subplz-burst-1790000000-0" = { ref = "0123456789abcdef0123456789abcdef01234567", machine = "c6a.xlarge", zone = "us-west-2a" } 27 "subplz-burst-1790000000-1" = { ref = "89abcdef0123456789abcdef0123456789abcdef", machine = "c7g.xlarge", zone = "us-west-2b" } 28 } 29 } 30 31 run "one_spot_instance_for_each_worker" { 32 command = plan 33 34 assert { 35 condition = length(aws_instance.worker) == 2 36 error_message = "Expected one instance for each worker." 37 } 38 assert { 39 condition = alltrue([for n, i in aws_instance.worker : 40 i.instance_type == var.workers[n].machine 41 && i.instance_market_options[0].market_type == "spot" 42 && i.instance_market_options[0].spot_options[0].max_price == "0.0625" 43 && i.instance_initiated_shutdown_behavior == "terminate" 44 ]) 45 error_message = "Each worker must be a spot instance of its type, with a price limit, that ends when it powers off." 46 } 47 assert { 48 condition = local.arch["subplz-burst-1790000000-0"] == "amd64" && local.arch["subplz-burst-1790000000-1"] == "arm64" 49 error_message = "A Graviton type must get the arm64 image, the others the amd64 image." 50 } 51 assert { 52 condition = length(aws_security_group.worker.ingress) == 0 53 error_message = "A worker must take no inbound connection." 54 } 55 } 56 57 run "the_cloud_config_names_the_host_and_opens_the_tunnel" { 58 command = plan 59 60 assert { 61 condition = alltrue([for n, i in aws_instance.worker : yamldecode(i.user_data).hostname == n]) 62 error_message = "The host name must be the machine name: the controller matches rq workers by host name." 63 } 64 assert { 65 condition = alltrue([for n, i in aws_instance.worker : 66 strcontains(i.user_data, "releases/${var.workers[n].ref}.tar.gz") 67 && strcontains(i.user_data, "SUBPLZ_WEB_WORKER_QUEUES=paid\n") 68 && strcontains(i.user_data, "-L 127.0.0.1:5432:127.0.0.1:5432 -L 127.0.0.1:6379:127.0.0.1:6379 subplz-tunnel@198.44.53.27") 69 && strcontains(i.user_data, "AWS_ENDPOINT_URL_S3=https://acct.r2.cloudflarestorage.com\n") 70 ]) 71 error_message = "Each worker must run its own commit, take paid jobs, reach the databases through the tunnel, and use the bucket." 72 } 73 assert { 74 condition = alltrue([for i in aws_instance.worker : 75 contains([for f in yamldecode(i.user_data).write_files : f.content], 76 "-----BEGIN OPENSSH PRIVATE KEY-----\nTUNNELKEY\n-----END OPENSSH PRIVATE KEY-----\n") 77 ]) 78 error_message = "The tunnel key must be written whole." 79 } 80 assert { 81 condition = alltrue([for i in aws_instance.worker : 82 strcontains(one([for f in yamldecode(i.user_data).write_files : f.content if f.path == "/opt/subplz-install/idle-check.sh"]), 83 "-ge 9 ]")]) 84 error_message = "The idle check must power off after var.idle_checks idle checks." 85 } 86 } 87 88 run "no_workers_means_no_instances" { 89 command = plan 90 91 variables { 92 workers = {} 93 } 94 95 assert { 96 condition = length(aws_instance.worker) == 0 97 error_message = "An empty set must make no instances." 98 } 99 } 100 101 run "a_name_without_the_prefix_is_refused" { 102 command = plan 103 104 variables { 105 workers = { "web-1" = { ref = "0123456789abcdef0123456789abcdef01234567", machine = "c6a.xlarge", zone = "us-west-2a" } } 106 } 107 108 expect_failures = [var.workers] 109 }