Ephemeral CPU Droplet fleet that horizontally scales the iteration loop:
- infra/terraform/test-fleet: cattle Droplets from a golden image (auto-discovered
by name via digitalocean_images), grouped under the mc:dev DO project, with a
mocked-provider test suite (no token/spend).
- infra/packer: golden-image builder reusing scripts/dev-setup/linux.sh.
- scripts/run/dist.sh: ./run dist:{check,up,sim,train,down} — shard sim/test
batches across workers via autoplay-batch AUTOPLAY_HOST+SEED_OFFSET.
GPU intentionally absent (workload is CPU-bound per docs/ai-production.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
88 lines
2.3 KiB
HCL
88 lines
2.3 KiB
HCL
# No-spend test harness for the fleet module.
|
|
# terraform test (from the module dir)
|
|
# Uses a MOCKED digitalocean provider — no API token, no API calls, no Droplets,
|
|
# no cost. Exercises count expansion, the golden-image branch toggle, and the
|
|
# workers guardrail.
|
|
|
|
mock_provider "digitalocean" {
|
|
# The golden-image data source is computed; give it a non-empty result so the
|
|
# base_image == "" branch (images[0].id) resolves under mocking.
|
|
mock_data "digitalocean_images" {
|
|
defaults = {
|
|
images = [{ id = 123456789 }]
|
|
}
|
|
}
|
|
}
|
|
|
|
variables {
|
|
do_token = "mock-token-unused"
|
|
git_remote = "https://example.com/magic-civilization.git"
|
|
ssh_public_key_path = "./tests/fixtures/id_test.pub"
|
|
}
|
|
|
|
# base_image set -> golden data source is skipped (count 0); fleet expands to N.
|
|
run "fleet_expands_and_skips_golden_when_base_image_set" {
|
|
command = plan
|
|
|
|
variables {
|
|
workers = 3
|
|
base_image = "ubuntu-24-04-x64"
|
|
}
|
|
|
|
assert {
|
|
condition = length(digitalocean_droplet.worker) == 3
|
|
error_message = "expected 3 workers when workers=3"
|
|
}
|
|
|
|
assert {
|
|
condition = length(data.digitalocean_images.golden) == 0
|
|
error_message = "golden data source must be skipped when base_image is set"
|
|
}
|
|
}
|
|
|
|
# base_image empty -> golden image is resolved via the name-substring filter.
|
|
run "golden_image_branch_active_when_base_image_empty" {
|
|
command = plan
|
|
|
|
variables {
|
|
workers = 2
|
|
base_image = ""
|
|
}
|
|
|
|
assert {
|
|
condition = length(data.digitalocean_images.golden) == 1
|
|
error_message = "golden data source must be queried when base_image is empty"
|
|
}
|
|
|
|
assert {
|
|
condition = length(digitalocean_droplet.worker) == 2
|
|
error_message = "expected 2 workers when workers=2"
|
|
}
|
|
}
|
|
|
|
# workers = 0 -> zero Droplets (idle / torn-down state).
|
|
run "zero_workers_is_empty_fleet" {
|
|
command = plan
|
|
|
|
variables {
|
|
workers = 0
|
|
base_image = "ubuntu-24-04-x64"
|
|
}
|
|
|
|
assert {
|
|
condition = length(digitalocean_droplet.worker) == 0
|
|
error_message = "workers=0 must produce no Droplets"
|
|
}
|
|
}
|
|
|
|
# The validation guardrail rejects an oversize fleet — proven without provisioning.
|
|
run "rejects_oversize_fleet" {
|
|
command = plan
|
|
|
|
variables {
|
|
workers = 99
|
|
base_image = "ubuntu-24-04-x64"
|
|
}
|
|
|
|
expect_failures = [var.workers]
|
|
}
|