feat(relay): declare Asia spare cell c34 as migration-only (#25336)

Adds a sixth asia-east2 cell at the C31 shape (cap 3000, 6000 request
units, pool 16, e2-standard-4) in asia-east2-c, pinned to the f30b5cb1
cell image. It gets its own topology and registration wave but no
promotion wave, so the admission script and workflow refuse to promote
it; it stays a migration-only landing zone and out of the fleet pool list.

Claude-Session: 1145a80d-dec4-4a9b-9373-bbbb876b9041
This commit is contained in:
Jinwoo Hong
2026-10-05 00:26:33 -04:00
committed by GitHub
parent e347aa4e67
commit b94cfa7fd0
19 changed files with 140 additions and 42 deletions
@@ -21,7 +21,7 @@ const SHAPES = {
domain: 'relay.onorca.dev',
allCells: [
'production-gce-c27', 'production-gce-c28', 'production-gce-c29', 'production-gce-c30',
'production-gce-c31', 'production-gce-c32', 'production-gce-c33'
'production-gce-c31', 'production-gce-c32', 'production-gce-c33', 'production-gce-c34'
],
// The launch set was registered together; each later cell registers alone beside it.
registrationWaves: [
@@ -29,8 +29,10 @@ const SHAPES = {
['production-gce-c30'],
['production-gce-c31'],
['production-gce-c32'],
['production-gce-c33']
['production-gce-c33'],
['production-gce-c34']
],
// C34 is a migration-only spare: no promotion wave until a reviewed change adds one.
promotionWaves: [
['production-gce-c27'],
['production-gce-c28', 'production-gce-c29'],
@@ -553,11 +553,13 @@ test('accepts only reviewed Asia admission waves', () => {
['rollback', 'production-gce-c30'],
['rollback', 'production-gce-c31'],
['rollback', 'production-gce-c27,production-gce-c28,production-gce-c29'],
['rollback', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33'],
['rollback', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33,production-gce-c34'],
...['production-gce-c32', 'production-gce-c33'].flatMap((cellId) => [
'inspect', 'verify', 'register', 'registered', 'promote', 'recover-promotion', 'rollback'
].map((mode) => [mode, cellId])),
['inspect', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33']
...['inspect', 'verify', 'register', 'registered', 'rollback']
.map((mode) => [mode, 'production-gce-c34']),
['inspect', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33,production-gce-c34']
]
for (const [mode, cellIds] of accepted) {
assert.deepEqual(
@@ -586,7 +588,12 @@ test('accepts only reviewed Asia admission waves', () => {
['promote', 'production-gce-c27,production-gce-c30'],
['promote', 'production-gce-c28,production-gce-c29,production-gce-c30'],
['promote', 'production-gce-c30,production-gce-c31'],
// The C34 spare stays migration-only: no reviewed promotion wave names it.
['promote', 'production-gce-c34'],
['recover-promotion', 'production-gce-c34'],
['register', 'production-gce-c33,production-gce-c34'],
['inspect', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33'],
['rollback', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30,production-gce-c31,production-gce-c32,production-gce-c33'],
['rollback', 'production-gce-c27,production-gce-c30'],
['rollback', 'production-gce-c30,production-gce-c31'],
['rollback', 'production-gce-c27,production-gce-c28,production-gce-c29,production-gce-c30'],
@@ -648,6 +655,29 @@ test('registers C31 alone beside the general C27-C30', async () => {
assert.deepEqual(subject.selector().membership.general, general)
})
test('registers the C34 spare alone as migration-only in asia-east2', async () => {
const general = [...launchCells, 'production-gce-c30', 'production-gce-c31']
const subject = harness({
generation: 17,
membership: {
existingOnly: [],
migrationOnly: [],
general: [...general, 'production-gce-c32', 'production-gce-c33']
}
})
const result = await operateRelayAsiaAdmission({
environment: 'production', mode: 'register', cells: ['production-gce-c34'],
expectedGeneration: 17, imageDigest: digest, attemptId: 'asia_register_c34', token: 'not-logged'
}, subject)
const request = subject.requests.find(({ path }) => path.endsWith('/add-migration-cells'))
assert.deepEqual(request.body.cells, [{
cellId: 'production-gce-c34', cellUrl: 'https://c34.relay.onorca.dev', region: 'asia-east2',
capacityRequests: 6_000, connectionHardCap: 3_000, connectionUnobservedBound: 60
}])
assert.deepEqual(result.states, { 'production-gce-c34': 'migration-only' })
assert.equal(subject.selector().membership.general.includes('production-gce-c34'), false)
})
const usRegions = { 'production-gce-c32': 'us-central1', 'production-gce-c33': 'us-central1' }
test('registers C32 and C33 one at a time in us-central1 at the Asia shape', async () => {
@@ -20,7 +20,8 @@ const SHAPES = {
'production-gce-c30': 'asia-east2-a',
'production-gce-c31': 'asia-east2-b',
'production-gce-c32': 'us-central1-a',
'production-gce-c33': 'us-central1-b'
'production-gce-c33': 'us-central1-b',
'production-gce-c34': 'asia-east2-c'
},
// The launch set, then each later additive cell; a plan targets one wave, never live cells.
waves: [
@@ -28,7 +29,8 @@ const SHAPES = {
['production-gce-c30'],
['production-gce-c31'],
// Declared together, so they plan together: a lone C32 plan would hit C33's missing template.
['production-gce-c32', 'production-gce-c33']
['production-gce-c32', 'production-gce-c33'],
['production-gce-c34']
]
}
}
@@ -14,7 +14,8 @@ const productionCells = () => Object.fromEntries([
[30, 'asia-east2-a'],
[31, 'asia-east2-b'],
[32, 'us-central1-a'],
[33, 'us-central1-b']
[33, 'us-central1-b'],
[34, 'asia-east2-c']
].map(([ordinal, zone]) => [`production-gce-c${ordinal}`, {
hostname: `c${ordinal}`, region: zone.slice(0, -2), zone,
machine_type: 'e2-standard-4', boot_disk_gb: 30,
@@ -57,6 +58,14 @@ test('accepts the additive C31 wave in the next zone of the rotation', () => {
assert.equal(result.relay_gce_cells['production-gce-c31'].zone, 'asia-east2-b')
})
test('accepts the additive C34 spare wave in asia-east2-c at the Asia pool', () => {
const result = prepareRelayAsiaTopologyInput({ existingCells: productionCells(),
existingAdditionalRegions: additionalRegions, environment: 'production',
cellIds: 'production-gce-c34', image })
assert.equal(result.relay_gce_cells['production-gce-c34'].zone, 'asia-east2-c')
assert.equal(result.relay_gce_cells['production-gce-c34'].database_pool_max, 16)
})
test('accepts the additive US C32+C33 wave at the default pool only', () => {
const cellIds = 'production-gce-c32,production-gce-c33'
for (const [cellId, zone] of [
@@ -103,7 +112,8 @@ test('matches every committed production Asia cell entry', () => {
'production-gce-c27,production-gce-c28,production-gce-c29',
'production-gce-c30',
'production-gce-c31',
'production-gce-c32,production-gce-c33'
'production-gce-c32,production-gce-c33',
'production-gce-c34'
]) {
const committedImage = committed[wave.split(',')[0]].image
assert.doesNotThrow(() => prepareRelayAsiaTopologyInput({
@@ -116,8 +126,8 @@ test('matches every committed production Asia cell entry', () => {
environment: 'production', cellIds: 'production-gce-c30',
image
}), /differs from the reviewed topology/)
// The US cells launch on the newest digest, the one C31 launched on.
for (const cellId of ['production-gce-c32', 'production-gce-c33']) {
// The US cells and the C34 spare launch on the newest cell digest, the one C31 launched on.
for (const cellId of ['production-gce-c32', 'production-gce-c33', 'production-gce-c34']) {
assert.equal(committed[cellId].image, committed['production-gce-c31'].image, cellId)
}
})
@@ -152,7 +162,8 @@ test('rejects an uncommitted subnet or cell, partial wave, wrong image, and drif
'production-gce-c30,production-gce-c31',
'production-gce-c32',
'production-gce-c33',
'production-gce-c34'
'production-gce-c33,production-gce-c34',
'production-gce-c35'
]) {
assert.throws(() => prepareRelayAsiaTopologyInput({
existingCells: productionCells(), existingAdditionalRegions: additionalRegions,
@@ -101,7 +101,9 @@ describe('production Relay capacity cell admission', () => {
// Migration-only canaries: the US-only capacity rollout never touches them either.
'production-gce-c17', 'production-gce-c18',
// US cells at the Asia shape: the 1,000-cap capacity rollout never touches them.
'production-gce-c32', 'production-gce-c33'
'production-gce-c32', 'production-gce-c33',
// The migration-only Asia spare.
'production-gce-c34'
]) {
const hostname = cellId.slice('production-gce-'.length)
assert.deepEqual(parseProductionCapacityCellArguments([
@@ -118,7 +120,7 @@ describe('production Relay capacity cell admission', () => {
paceWindowMs: 0
})
}
for (const cellId of ['production-gce-c12', 'production-gce-c34']) {
for (const cellId of ['production-gce-c12', 'production-gce-c35']) {
const hostname = cellId.slice('production-gce-'.length)
assert.throws(() => parseProductionCapacityCellArguments([
'--director-origin', 'https://relay.onorca.dev',
@@ -2,9 +2,9 @@ import { pathToFileURL } from 'node:url'
import { fetchAdminOnceMore } from './relay-admin-transient-retry.mjs'
// Every cell that carries the rehome identity: the eighteen US cells and the
// five asia-east2 cells that drain mis-homed hosts back the other way.
// six asia-east2 cells that drain mis-homed hosts back the other way.
const PRODUCTION_CELL =
/^production-gce-c(?:7|8|9|10|13|14|15|16|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33)$/
/^production-gce-c(?:7|8|9|10|13|14|15|16|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34)$/
const DIRECTOR_ORIGIN = 'https://relay.onorca.dev'
export function parseRehomeTrustProbeArguments(argv, environment = process.env) {
@@ -116,7 +116,7 @@ test('fails when both trust-probe attempts return a transient 503', async () =>
test('approves the asia-east2 and US 3,000 rehome sources and still rejects unlisted cells', () => {
for (const cellId of [
'production-gce-c27', 'production-gce-c28', 'production-gce-c29', 'production-gce-c30',
'production-gce-c31', 'production-gce-c32', 'production-gce-c33'
'production-gce-c31', 'production-gce-c32', 'production-gce-c33', 'production-gce-c34'
]) {
const parsed = parseRehomeTrustProbeArguments(
argv.map((value) => (value === 'production-gce-c7' ? cellId : value)),
@@ -124,7 +124,7 @@ test('approves the asia-east2 and US 3,000 rehome sources and still rejects unli
)
assert.equal(parsed.cellId, cellId)
}
for (const cellId of ['production-gce-c1', 'production-gce-c17', 'production-gce-c34']) {
for (const cellId of ['production-gce-c1', 'production-gce-c17', 'production-gce-c35']) {
assert.throws(
() =>
parseRehomeTrustProbeArguments(
@@ -183,7 +183,7 @@ test('approves exactly the committed production rehome source cells', () => {
const sources = new Set(
[...tfvars.slice(start, tfvars.indexOf(']', start)).matchAll(/"([^"]+)"/g)].map(([, cell]) => cell)
)
assert.ok(sources.has('production-gce-c33'))
assert.ok(sources.has('production-gce-c34'))
for (let ordinal = 1; ordinal <= 40; ordinal++) {
const cellId = `production-gce-c${ordinal}`
const approved = (() => {
@@ -50,7 +50,8 @@ test('accepts only the reviewed Asia topology waves', () => {
'production:production-gce-c27,production-gce-c28,production-gce-c29',
'production:production-gce-c30',
'production:production-gce-c31',
'production:production-gce-c32,production-gce-c33'
'production:production-gce-c32,production-gce-c33',
'production:production-gce-c34'
]
)
})
@@ -7,12 +7,12 @@ import {
} from './relay-cloud-sql-connection-budget.mjs'
test('production shared consumers keep allowance and reserve below the ceiling', () => {
// cells: 22 pools at 10 (220, C32/C33 included) + the five asia-east2 pools at 16 (80).
// cells: 22 pools at 10 (220, C32/C33 included) + the six asia-east2 pools at 16 (96).
const report = readRelayCloudSqlConnectionBudget()
assert.deepEqual(report.consumers, { cells: 300, directors: 15, auth: 20, api: 50 })
assert.deepEqual(report.asia, { cells: 5, poolMax: 16 })
assert.equal(report.configuredMaximum, 385)
assert.deepEqual(report.consumers, { cells: 316, directors: 15, auth: 20, api: 50 })
assert.deepEqual(report.asia, { cells: 6, poolMax: 16 })
assert.equal(report.configuredMaximum, 401)
assert.equal(report.rolloutOverlap.relayDirectorCandidate, 30)
assert.equal(report.rolloutOverlap.apiCandidate, 65)
assert.equal(report.rolloutOverlap.authCandidate, 35)
@@ -22,10 +22,10 @@ test('production shared consumers keep allowance and reserve below the ceiling',
assert.equal(report.maintenanceAdminAllowance, 5)
assert.equal(report.explicitReserve, 10)
assert.equal(report.usableCeiling, 490)
assert.equal(report.operatingMaximum, 455)
assert.equal(report.remainingWithinUsableCeiling, 35)
assert.equal(report.budgetedTotal, 465)
assert.equal(report.unallocated, 35)
assert.equal(report.operatingMaximum, 471)
assert.equal(report.remainingWithinUsableCeiling, 19)
assert.equal(report.budgetedTotal, 481)
assert.equal(report.unallocated, 19)
assert.equal(report.withinBudget, true)
})
@@ -4,7 +4,10 @@ import { requireSameEvidenceCode } from './relay-evidence-code-provenance.mjs'
// Migration-only by policy: zero hosts and no reservation, so a wave rolls one without
// displacing anybody. It enters and must leave migration-only, never general.
export const SAME_CAP_MIGRATION_ONLY_CELLS = ['production-gce-c17', 'production-gce-c18']
// C34 is an Asia spare that stays migration-only by policy.
export const SAME_CAP_MIGRATION_ONLY_CELLS = [
'production-gce-c17', 'production-gce-c18', 'production-gce-c34'
]
export const SAME_CAP_CELLS = [
'production-gce-c7', 'production-gce-c8', 'production-gce-c9', 'production-gce-c10',
@@ -63,7 +63,7 @@ test('requires one canary or a bounded reviewed batch', () => {
rollbackDigest,
confirmation: `ROLL_RELAY_SAME_CAP ${targetDigest} production-gce-c31`
}).cells, ['production-gce-c31'])
for (const cellId of ['production-gce-c32', 'production-gce-c33']) {
for (const cellId of ['production-gce-c32', 'production-gce-c33', 'production-gce-c34']) {
assert.deepEqual(validateSameCapWave({
mode: 'canary-apply',
cellIds: cellId,
@@ -74,10 +74,10 @@ test('requires one canary or a bounded reviewed batch', () => {
}
assert.throws(() => validateSameCapWave({
mode: 'canary-apply',
cellIds: 'production-gce-c34',
cellIds: 'production-gce-c35',
targetDigest,
rollbackDigest,
confirmation: `ROLL_RELAY_SAME_CAP ${targetDigest} production-gce-c34`
confirmation: `ROLL_RELAY_SAME_CAP ${targetDigest} production-gce-c35`
}), /cells/)
})
@@ -123,8 +123,11 @@ test('the wave workflow chains exactly ten serial cell jobs', () => {
assert.doesNotMatch(dispatch, /\n cell_11:/)
})
test('lists only C17 and C18 as migration-only now that C32 and C33 are promoted', () => {
assert.deepEqual(SAME_CAP_MIGRATION_ONLY_CELLS, ['production-gce-c17', 'production-gce-c18'])
test('lists the C34 spare as migration-only beside C17 and C18, and C30-C33 as general', () => {
assert.deepEqual(
SAME_CAP_MIGRATION_ONLY_CELLS,
['production-gce-c17', 'production-gce-c18', 'production-gce-c34']
)
for (const cellId of [
'production-gce-c30', 'production-gce-c31', 'production-gce-c32', 'production-gce-c33'
]) {
@@ -263,7 +263,7 @@ describe('same-cap roll scripts accept every same-cap cell', () => {
assert.equal(String(cellShape(cellId).cap), tfvarsHardCap(cellId), cellId)
}
assert.equal(resolveCellShape('production-gce-c12').status, 1)
assert.equal(resolveCellShape('production-gce-c34').status, 1)
assert.equal(resolveCellShape('production-gce-c35').status, 1)
})
@@ -275,9 +275,10 @@ describe('same-cap roll scripts accept every same-cap cell', () => {
const trusted = SAME_CAP_CELLS.filter((cell) => REHOME_SOURCE_CELLS.has(cell))
// Only a declared rehome source may roll at a trusted protocol at all; the job refuses
// the rest before it plans, and the next test covers them at protocol 0.
// The C34 spare is a rehome source that stays migration-only.
assert.deepEqual(
SAME_CAP_CELLS.filter((cell) => !REHOME_SOURCE_CELLS.has(cell)),
SAME_CAP_MIGRATION_ONLY_CELLS
SAME_CAP_MIGRATION_ONLY_CELLS.filter((cell) => cell !== 'production-gce-c34')
)
for (const [cellId, protocol] of trusted.flatMap((cell) => [[cell, 1], [cell, 3]])) {
const { cap, pool } = cellShape(cellId)
@@ -24,14 +24,16 @@ const CELL_SHAPES = {
'production-gce-c30': 'asia-east2-a',
'production-gce-c31': 'asia-east2-b',
'production-gce-c32': 'us-central1-a',
'production-gce-c33': 'us-central1-b'
'production-gce-c33': 'us-central1-b',
'production-gce-c34': 'asia-east2-c'
},
waves: [
['production-gce-c27', 'production-gce-c28', 'production-gce-c29'],
['production-gce-c30'],
['production-gce-c31'],
// Declared together, so they plan together: a lone C32 plan would hit C33's missing template.
['production-gce-c32', 'production-gce-c33']
['production-gce-c32', 'production-gce-c33'],
['production-gce-c34']
]
},
staging: {
@@ -161,6 +161,18 @@ test('accepts the additive production C31 wave only in asia-east2-b', () => {
)
})
test('accepts the additive production C34 spare wave only in asia-east2-c', () => {
const c34Config = { ...productionConfig, cells: ['production-gce-c34'] }
assert.deepEqual(
validateRelayAsiaTopologyPlan({ resource_changes: productionWavePlan('c34', 'asia-east2-c') }, c34Config),
{ environment: 'production', cells: ['production-gce-c34'], changes: 4 }
)
assert.throws(
() => validateRelayAsiaTopologyPlan({ resource_changes: productionWavePlan('c34') }, c34Config),
/fixed-one Asia MIG shape/
)
})
// A US cell joins the root region: no additional-region network, no region label or line, and
// the default pool emits no line, exactly as the startup template renders a root-region cell.
function usCellPlan(hostname, zone) {
@@ -269,7 +281,8 @@ test('accepts only a reviewed Asia topology wave', () => {
'production-gce-c27,production-gce-c28,production-gce-c29',
'production-gce-c29,production-gce-c27,production-gce-c28',
'production-gce-c30',
'production-gce-c31'
'production-gce-c31',
'production-gce-c34'
]) {
assert.doesNotThrow(
() => parseRelayAsiaTopologyPlanArguments(argv('production', cellIds, productionImage)),
@@ -286,7 +299,8 @@ test('accepts only a reviewed Asia topology wave', () => {
'production-gce-c32',
'production-gce-c33',
'production-gce-c32,production-gce-c33,production-gce-c34',
'production-gce-c34'
'production-gce-c33,production-gce-c34',
'production-gce-c35'
]) {
assert.throws(
() => parseRelayAsiaTopologyPlanArguments(argv('production', cellIds, productionImage)),