mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 00:02:29 +00:00
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:
@@ -78,6 +78,7 @@ jobs:
|
||||
production:production-gce-c30) ;;
|
||||
production:production-gce-c31) ;;
|
||||
production:production-gce-c32,production-gce-c33) target_region=us-central1 ;;
|
||||
production:production-gce-c34) ;;
|
||||
*) echo "cell-ids do not match the reviewed environment topology" >&2; exit 1 ;;
|
||||
esac
|
||||
echo "TARGET_REGION=${target_region}" >> "${GITHUB_ENV}"
|
||||
|
||||
@@ -194,7 +194,7 @@ jobs:
|
||||
EXPECTED_REGION=us-central1
|
||||
EXPECTED_DATABASE_POOL_MAX=
|
||||
;;
|
||||
c27|c28|c29|c30|c31)
|
||||
c27|c28|c29|c30|c31|c34)
|
||||
EXPECTED_HARD_CAP=3000
|
||||
EXPECTED_REGION=asia-east2
|
||||
EXPECTED_DATABASE_POOL_MAX=16
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -218,6 +218,16 @@ to the general list. The shadow gate's fleet pool list tracks the 16-connection
|
||||
whether a US cell belongs there is decided at promotion, not assumed. Both were promoted to general
|
||||
on 2026-10-01, so the same-cap job now rolls them as general cells. They stay out of the fleet pool
|
||||
list because their pool is the US default of 10.
|
||||
|
||||
C34 is an Asia spare at the C31 shape in `asia-east2-c`, so the six Asia cells spread 2/2/2. It is
|
||||
its own topology wave and registers alone as migration-only, then the director is configured with
|
||||
`cell-ids` set to C34. It has no promotion wave: the Asia admission script and workflow refuse
|
||||
`promote` for it, and placement and regional rehome select only general cells. It is a
|
||||
migration-only landing zone that only an explicit evacuation or migration naming it can target.
|
||||
Do not name it in the multi-target `promote-general-cell` or `retire-migration-cell` modes, which
|
||||
accept any migration-only cell. It is a declared rehome source, sits in the same-cap migration-only
|
||||
list, and stays out of the fleet pool list. Promoting it later takes its own reviewed change adding a
|
||||
promotion wave and canary entry.
|
||||
Rollback returns
|
||||
Asia cells to migration-only; it does not destroy the network or use
|
||||
existing-only. The production topology dispatch remains unavailable until the
|
||||
|
||||
@@ -332,7 +332,7 @@ cell templates/MIGs/backends, and exact shared URL-map host additions. It
|
||||
rejects deletes, replacements, loss of an existing host route, US-resource
|
||||
changes, and unrelated drift. Do not add production C27-C29 until the
|
||||
compatible image has been published and each entry can pin its immutable
|
||||
digest. A later cell, such as C30 or C31, is its own reviewed wave. The shared URL map
|
||||
digest. A later cell, such as C30, C31 or the C34 spare, is its own reviewed wave. The shared URL map
|
||||
pulls every live cell into its plan, so the workflow plans each live cell at the
|
||||
image its state template already serves, and the validator rejects any change
|
||||
to a cell outside the wave. US C32 and C33 use the same workflow at the same
|
||||
|
||||
@@ -450,6 +450,21 @@ relay_gce_cells = {
|
||||
connection_hard_cap = 3000
|
||||
connection_unobserved_bound = 60
|
||||
}
|
||||
# Asia spare: registered migration-only as a drain landing zone; c completes the 2/2/2 zone spread.
|
||||
"production-gce-c34" = {
|
||||
hostname = "c34"
|
||||
region = "asia-east2"
|
||||
zone = "asia-east2-c"
|
||||
machine_type = "e2-standard-4"
|
||||
boot_disk_gb = 30
|
||||
boot_image = "https://www.googleapis.com/compute/v1/projects/cos-cloud/global/images/cos-stable-121-18867-528-21"
|
||||
capacity_requests = 6000
|
||||
database_pool_max = 16 # 176 ms from us-central1 Postgres saturates 10 (94-156 waiters).
|
||||
image = "us-central1-docker.pkg.dev/onorca-cloud/orca-cloud/relay@sha256:f30b5cb1ec52b6b6145efecfa1b8be9e3d309403beffd8abcc64197a2087e269"
|
||||
initially_enabled = false
|
||||
connection_hard_cap = 3000
|
||||
connection_unobserved_bound = 60
|
||||
}
|
||||
}
|
||||
|
||||
relay_region_rehome_source_cell_ids = [
|
||||
@@ -476,7 +491,8 @@ relay_region_rehome_source_cell_ids = [
|
||||
"production-gce-c30",
|
||||
"production-gce-c31",
|
||||
"production-gce-c32",
|
||||
"production-gce-c33"
|
||||
"production-gce-c33",
|
||||
"production-gce-c34"
|
||||
]
|
||||
|
||||
# Slack #orca-relay-alerts, created out of band on 2026-08-05. Declared here because an apply
|
||||
|
||||
Reference in New Issue
Block a user