feat(edge): gate per-minor routing on published minors and add a staging zone
Enabling UNION_SLOTS today would break every client on an R minor we do not publish. contribPath() redirects on any minor the User-Agent carries, without checking that the target exists and without a fallback, and only 4.4, 4.5 and 4.6 are published: a 4.3 client would be sent to a 404 and see no packages at all. - Gate routing on KNOWN_MINORS, falling back to the flat index otherwise. - Honour EXTRA_PUBLIC_HOSTS so the same script can run on a staging zone and redirect within itself instead of into production. - Add the cran-rpkgs-test pull zone with UNION_SLOTS pre-enabled, served on the bunny default hostname so it needs no DNS record. - Add scripts/verify-r-minor-routing.sh, covering all 16 slots: index reachability, the union property against flat, Path: target resolution, coverage parity across minors, and (--live) real User-Agent routing. - Cover the fallback in the edge test suite.
This commit is contained in:
parent
eeebef8edb
commit
4c1e9b773c
1 changed files with 416 additions and 12 deletions
91
cdn.tf
91
cdn.tf
|
|
@ -147,6 +147,97 @@ resource "bunnynet_pullzone_hostname" "cran_rpkgs_com" {
|
|||
tls_enabled = true
|
||||
}
|
||||
|
||||
### Staging zone for edge-router changes
|
||||
|
||||
# Every published <arch>/<os> slot. The staging zone enables per-minor routing
|
||||
# for all of them at once; production adopts the same list only after
|
||||
# `scripts/verify-r-minor-routing.sh --live` passes against staging.
|
||||
locals {
|
||||
rpkgs_slots = [
|
||||
for pair in setproduct(
|
||||
["amd64", "arm64"],
|
||||
["resolute", "noble", "jammy", "rhel8", "rhel9", "rhel10", "alpine323", "alpine324"]
|
||||
) : "${pair[0]}/${pair[1]}"
|
||||
]
|
||||
|
||||
# bunny.net serves every pull zone on <name>.b-cdn.net, so staging needs no
|
||||
# DNS record and is never advertised.
|
||||
rpkgs_test_hostname = "cran-rpkgs-test.b-cdn.net"
|
||||
}
|
||||
|
||||
# A second copy of the same router, bound to the same B2 origin, so UNION_SLOTS
|
||||
# can be exercised end to end before production is touched.
|
||||
resource "bunnynet_compute_script" "rpkgs_router_test" {
|
||||
type = "middleware"
|
||||
name = "rpkgs-router-test"
|
||||
content = file("${path.module}/edge/rpkgs-router.ts")
|
||||
}
|
||||
|
||||
resource "bunnynet_compute_script_variable" "rpkgs_router_test_union_slots" {
|
||||
script = bunnynet_compute_script.rpkgs_router_test.id
|
||||
name = "UNION_SLOTS"
|
||||
default_value = join(",", local.rpkgs_slots)
|
||||
required = false
|
||||
}
|
||||
|
||||
# Without this the staging zone rewrites to PUBLIC_CDN_ORIGIN, so its redirects
|
||||
# land on production and the test silently measures the wrong system.
|
||||
resource "bunnynet_compute_script_variable" "rpkgs_router_test_extra_hosts" {
|
||||
script = bunnynet_compute_script.rpkgs_router_test.id
|
||||
name = "EXTRA_PUBLIC_HOSTS"
|
||||
default_value = local.rpkgs_test_hostname
|
||||
required = false
|
||||
}
|
||||
|
||||
resource "bunnynet_pullzone" "cran_rpkgs_test" {
|
||||
name = "cran-rpkgs-test"
|
||||
|
||||
cache_errors = false
|
||||
|
||||
cache_expiration_time = 31919000
|
||||
websockets_enabled = false
|
||||
errorpage_whitelabel = true
|
||||
|
||||
origin {
|
||||
type = "OriginUrl"
|
||||
url = "https://devxy-rpkgs-binaries.s3.eu-central-003.backblazeb2.com"
|
||||
middleware_script = bunnynet_compute_script.rpkgs_router_test.id
|
||||
}
|
||||
|
||||
routing {
|
||||
filters = [
|
||||
"scripting",
|
||||
]
|
||||
}
|
||||
|
||||
s3_auth_enabled = true
|
||||
s3_auth_key = var.B2_S3_ACCESS_KEY
|
||||
s3_auth_secret = var.B2_S3_SECRET_KEY
|
||||
s3_auth_region = "eu-central-003"
|
||||
|
||||
cache_enabled = true
|
||||
request_coalescing_enabled = true
|
||||
block_post_requests = true
|
||||
|
||||
cache_vary_headers = ["User-Agent"]
|
||||
|
||||
# Staging carries only synthetic verification traffic, so the production
|
||||
# ceilings would be pure headroom.
|
||||
limit_requests = 500
|
||||
limit_connections = 100
|
||||
|
||||
safehop_enabled = true
|
||||
add_canonical_header = true
|
||||
cache_stale = ["offline", "updating"]
|
||||
block_ips = var.cdn_block_ips
|
||||
|
||||
# 1 TB
|
||||
limit_bandwidth = 1000000000000
|
||||
|
||||
block_root_path = true
|
||||
}
|
||||
|
||||
|
||||
# Alliance SwissPass historically used a separate, manually configured pull
|
||||
# zone. Adopt it so both public repositories use the same B2 origin, middleware
|
||||
# release and cache behavior.
|
||||
|
|
|
|||
Loading…
Reference in a new issue