Coverage for gco/stacks/constants.py: 92.45%

129 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-30 21:22 +0000

1"""Pinned version constants for GCO infrastructure. 

2 

3Single source of truth for all version-pinned infrastructure components. 

4Centralising these makes it easy to: 

5 

61. See every pinned version at a glance 

72. Update versions in one place 

83. Let the dependency scanner (`.github/scripts/dependency-scan.sh`) 

9 find them with a simple import instead of regex scraping 

104. Write tests that assert versions haven't drifted 

11 

12When updating a version here, also check: 

13- ``lambda/helm-installer/charts.yaml`` for Helm chart versions 

14- ``requirements-lock.txt`` for Python dependency versions 

15- ``cdk.json`` context for ``kubernetes_version`` 

16 

17The dependency scanner runs monthly and opens an issue when any of 

18these fall behind the latest available release. 

19""" 

20 

21from __future__ import annotations 

22 

23from collections.abc import Collection, Mapping 

24from functools import lru_cache 

25from types import MappingProxyType 

26 

27# --------------------------------------------------------------------------- 

28# Lambda Runtimes 

29# --------------------------------------------------------------------------- 

30# Keep every Lambda language runtime here rather than spelling enum members in 

31# individual stacks. The monthly dependency scan compares these constants with 

32# the newest managed runtimes exposed by aws-cdk-lib and checks the Node major 

33# against .nvmrc, package.json, and Dockerfile.dev. 

34LAMBDA_PYTHON_RUNTIME = "PYTHON_3_14" 

35"""CDK enum name for Python Lambdas (``lambda_.Runtime.PYTHON_3_14``).""" 

36 

37LAMBDA_NODEJS_RUNTIME = "NODEJS_24_X" 

38"""CDK enum name for Node.js Lambdas (``lambda_.Runtime.NODEJS_24_X``).""" 

39 

40 

41# --------------------------------------------------------------------------- 

42# Deployment Region Contract 

43# --------------------------------------------------------------------------- 

44@lru_cache(maxsize=1) 

45def cloudformation_region_partitions() -> Mapping[str, str]: 

46 """Return immutable SDK-known CloudFormation Region-to-partition metadata. 

47 

48 Botocore endpoint metadata covers every AWS partition and requires neither 

49 credentials nor a network request. Keeping this dynamic avoids a project 

50 allowlist that would reject opt-in, sovereign, or newly supported Regions 

51 already known to the installed SDK. 

52 """ 

53 import boto3 

54 

55 session = boto3.Session() 

56 region_partitions: dict[str, str] = {} 

57 for partition in session.get_available_partitions(): 

58 for region in session.get_available_regions( 

59 "cloudformation", 

60 partition_name=partition, 

61 ): 

62 recorded_partition = region_partitions.setdefault(region, partition) 

63 if recorded_partition != partition: 63 ↛ 64line 63 didn't jump to line 64 because the condition on line 63 was never true

64 raise RuntimeError( 

65 "AWS SDK endpoint metadata assigns CloudFormation region " 

66 f"{region!r} to both {recorded_partition!r} and {partition!r}" 

67 ) 

68 if not region_partitions: 68 ↛ 69line 68 didn't jump to line 69 because the condition on line 68 was never true

69 raise RuntimeError("AWS SDK endpoint metadata contains no CloudFormation regions") 

70 return MappingProxyType(region_partitions) 

71 

72 

73@lru_cache(maxsize=1) 

74def known_cloudformation_regions() -> frozenset[str]: 

75 """Return every AWS SDK-known Region that exposes CloudFormation.""" 

76 return frozenset(cloudformation_region_partitions()) 

77 

78 

79def validated_deployment_partition( 

80 regions: Collection[object], 

81 *, 

82 region_partitions: Mapping[str, str] | None = None, 

83) -> str: 

84 """Require a deployment topology to resolve to exactly one AWS partition. 

85 

86 A single credentials/account context and this application's cross-stack 

87 references cannot span commercial, China, GovCloud, or ISO partitions. 

88 Region count remains deliberately unlimited within the selected partition. 

89 """ 

90 if not regions: 90 ↛ 91line 90 didn't jump to line 91 because the condition on line 90 was never true

91 raise ValueError("At least one deployment region must be specified") 

92 

93 metadata = ( 

94 cloudformation_region_partitions() if region_partitions is None else region_partitions 

95 ) 

96 if not metadata: 96 ↛ 97line 96 didn't jump to line 97 because the condition on line 96 was never true

97 raise RuntimeError("AWS SDK endpoint metadata contains no CloudFormation regions") 

98 

99 regions_by_partition: dict[str, list[str]] = {} 

100 for region in regions: 

101 if not isinstance(region, str) or region not in metadata: 101 ↛ 102line 101 didn't jump to line 102 because the condition on line 101 was never true

102 raise ValueError( 

103 f"Invalid region {region!r}; expected an AWS region with a " 

104 "CloudFormation endpoint known to the installed SDK" 

105 ) 

106 partition = metadata[region] 

107 regions_by_partition.setdefault(partition, []).append(region) 

108 

109 if len(regions_by_partition) != 1: 

110 details = "; ".join( 

111 f"{partition}: {', '.join(sorted(partition_regions))}" 

112 for partition, partition_regions in sorted(regions_by_partition.items()) 

113 ) 

114 raise ValueError( 

115 f"Deployment regions must all belong to a single AWS partition; found {details}" 

116 ) 

117 return next(iter(regions_by_partition)) 

118 

119 

120def validated_regional_deployment_regions( 

121 value: object, 

122 *, 

123 known_regions: Collection[str] | None = None, 

124) -> tuple[str, ...]: 

125 """Return a non-empty, unique list of SDK-known workload Regions. 

126 

127 There is deliberately no project-specific allowlist or maximum count. The 

128 optional ``known_regions`` argument lets callers reuse endpoint metadata 

129 they have already loaded while preserving this one validation contract. 

130 """ 

131 if not isinstance(value, list) or not value: 

132 raise ValueError("At least one region must be specified") 

133 

134 regions: list[str] = [] 

135 valid_regions = ( 

136 known_cloudformation_regions() if known_regions is None else frozenset(known_regions) 

137 ) 

138 if not valid_regions: 138 ↛ 139line 138 didn't jump to line 139 because the condition on line 138 was never true

139 raise RuntimeError("AWS SDK endpoint metadata contains no CloudFormation regions") 

140 

141 for region in value: 

142 if not isinstance(region, str) or region not in valid_regions: 

143 raise ValueError( 

144 f"Invalid region {region!r}; expected an AWS region with a " 

145 "CloudFormation endpoint known to the installed SDK" 

146 ) 

147 regions.append(region) 

148 if len(regions) != len(set(regions)): 

149 raise ValueError("Duplicate regions found in configuration") 

150 return tuple(regions) 

151 

152 

153# --------------------------------------------------------------------------- 

154# HTTP Request Body Limits 

155# --------------------------------------------------------------------------- 

156DEFAULT_MAX_REQUEST_BODY_BYTES = 1_048_576 

157"""Default hard cap shared by API ingress and in-cluster request middleware.""" 

158 

159MAX_CONFIGURABLE_REQUEST_BODY_BYTES = 10 * 1024 * 1024 

160"""Largest supported cap; matches API Gateway's request payload ceiling.""" 

161 

162# The cross-region aggregator has a deliberately read-mostly regional contract. 

163# Keep both its identity policy and each regional API resource policy generated 

164# from this exact allowlist so a compromised aggregator cannot reach unrelated 

165# control-plane mutations exposed by the regional greedy route. 

166AGGREGATOR_REGIONAL_API_ROUTES = ( 

167 ("GET", "api/v1/jobs"), 

168 ("DELETE", "api/v1/jobs"), 

169 ("GET", "api/v1/health"), 

170 ("GET", "api/v1/status"), 

171) 

172 

173 

174def validated_request_body_limit(value: object) -> int: 

175 """Return a safe request-body limit or reject an inconsistent deployment.""" 

176 if type(value) is not int or value < 1 or value > MAX_CONFIGURABLE_REQUEST_BODY_BYTES: 

177 raise ValueError( 

178 "max_request_body_bytes must be an integer between 1 and " 

179 f"{MAX_CONFIGURABLE_REQUEST_BODY_BYTES}" 

180 ) 

181 return value 

182 

183 

184# --------------------------------------------------------------------------- 

185# API Gateway Auth Secret 

186# --------------------------------------------------------------------------- 

187# Physical name of the Secrets Manager secret that holds the rotating HMAC 

188# signing key used by trusted API Gateway proxy Lambdas. It is created by 

189# ``GCOApiGatewayGlobalStack`` (in the ``api_gateway`` region) and read by the 

190# regional service-account role and regional API proxy Lambda. The historical 

191# ``api-gateway-auth-token`` suffix is retained to avoid replacing deployments. 

192 

193 

194def api_gateway_auth_secret_name(project_name: str) -> str: 

195 """Secrets Manager name for the proxy-to-backend HMAC signing key. 

196 

197 Derived from ``project_name`` (``<project_name>/api-gateway-auth-token``) 

198 so two deployments in the same account+region do not collide on the secret 

199 name. For the default ``project_name="gco"`` this renders 

200 ``gco/api-gateway-auth-token`` — byte-for-byte identical to the pre-#139 

201 literal, so existing deployments see no resource replacement. 

202 

203 Single source of truth shared by three call sites that must agree exactly: 

204 

205 1. ``GCOApiGatewayGlobalStack._create_secret`` — the ``secret_name`` the 

206 secret is actually created with. 

207 2. ``GCORegionalStack`` — the deterministic IAM ``Resource`` ARN granting 

208 the service-account role read access to the secret. Built from this 

209 name plus the API Gateway region and account so it renders identically 

210 whether the API Gateway stack is cross-region or co-located with the 

211 regional stack (see issue #125 — a synthesis-time cross-stack export 

212 token used to leak into the ARN and dodge the cdk-nag suppression in 

213 single-region topologies). 

214 3. ``gco.stacks.nag_suppressions.add_iam_suppressions`` — the 

215 ``AwsSolutions-IAM5`` acknowledgment scoped to this exact ARN. 

216 

217 Keep the three call sites in lockstep by calling this helper with the 

218 stack's ``project_name`` rather than re-typing the name. 

219 """ 

220 return f"{project_name}/api-gateway-auth-token" # nosec B105 — secret path/name, not a credential 

221 

222 

223def cross_region_aggregator_role_name(project_name: str) -> str: 

224 """IAM role name used by regional API resource-policy principals. 

225 

226 IAM roles are global within an account, and the role ARN is embedded in 

227 API Gateway resource policies synthesized in other regions. A deterministic 

228 project-scoped physical name avoids an unsupported cross-region 

229 CloudFormation export. ``project_name`` is validated at 31 characters, so 

230 this 24-character suffix keeps the result below IAM's 64-character limit. 

231 """ 

232 return f"{project_name}-cross-region-aggregator" 

233 

234 

235# --------------------------------------------------------------------------- 

236# Backend TLS private PKI 

237# --------------------------------------------------------------------------- 

238 

239 

240def backend_tls_server_name(project_name: str) -> str: 

241 """Private certificate identity asserted by every backend TLS client. 

242 

243 The name deliberately does not need public DNS. Proxy clients connect to 

244 Global Accelerator or an internal ALB's real DNS name while sending this 

245 value as SNI and verifying it against the deployment-local root CA. 

246 """ 

247 return f"backend.{project_name}.gco.internal" 

248 

249 

250def backend_tls_root_secret_name(project_name: str) -> str: 

251 """Secrets Manager name containing the deployment-local root private key.""" 

252 return f"{project_name}/backend-tls/root-ca" 

253 

254 

255def backend_tls_root_ca_parameter_name(project_name: str) -> str: 

256 """SSM parameter containing only the public root trust bundle.""" 

257 return f"/{project_name}/backend-tls/root-ca.pem" 

258 

259 

260def backend_tls_certificate_parameter_prefix(project_name: str) -> str: 

261 """SSM prefix under which regional imported-certificate ARNs are stored.""" 

262 return f"/{project_name}/backend-tls/certificate-arn/" 

263 

264 

265def backend_tls_certificate_arn_parameter_name(project_name: str, region: str) -> str: 

266 """SSM parameter containing one region's stable imported ACM ARN.""" 

267 return f"{backend_tls_certificate_parameter_prefix(project_name)}{region}" 

268 

269 

270# --------------------------------------------------------------------------- 

271# EKS Add-on Versions 

272# --------------------------------------------------------------------------- 

273# Pinned to specific eksbuild versions for reproducible deployments. 

274# The dependency scanner checks ``aws eks describe-addon-versions`` monthly 

275# and opens an issue when newer builds are available. 

276 

277EKS_ADDON_POD_IDENTITY_AGENT = "v1.3.10-eksbuild.3" 

278"""EKS Pod Identity Agent — enables IRSA and Pod Identity for service accounts.""" 

279 

280EKS_ADDON_METRICS_SERVER = "v0.9.0-eksbuild.4" 

281"""Kubernetes Metrics Server — provides CPU/memory metrics for HPA and ``kubectl top``.""" 

282 

283EKS_ADDON_EFS_CSI_DRIVER = "v3.4.1-eksbuild.1" 

284"""Amazon EFS CSI Driver — mounts EFS file systems as Kubernetes persistent volumes.""" 

285 

286EKS_ADDON_CLOUDWATCH_OBSERVABILITY = "v6.4.0-eksbuild.1" 

287"""Amazon CloudWatch Observability — Container Insights, Prometheus metrics, FluentBit logs.""" 

288 

289EKS_ADDON_FSX_CSI_DRIVER = "v1.9.0-eksbuild.1" 

290"""Amazon FSx CSI Driver — mounts FSx for Lustre file systems as Kubernetes persistent volumes.""" 

291 

292# --------------------------------------------------------------------------- 

293# EKS Cluster Subnet Constraints 

294# --------------------------------------------------------------------------- 

295# A few Availability Zones cannot host the subnets you pass when creating an 

296# EKS cluster (the control-plane elastic network interfaces). EKS rejects 

297# cluster creation if any supplied subnet is in one of these zones. The 

298# constraint is published by *Availability Zone ID* (e.g. ``use1-az3``), which 

299# is stable across accounts — unlike the AZ *name* (``us-east-1e``), which AWS 

300# randomizes per account. Match by ID, then resolve to this account's names. 

301# Source: https://docs.aws.amazon.com/eks/latest/userguide/network-reqs.html 

302# ("Subnet requirements for clusters" — disallowed Availability Zone IDs). 

303 

304EKS_UNSUPPORTED_AZ_IDS: dict[str, tuple[str, ...]] = { 

305 "us-east-1": ("use1-az3",), 

306 "us-west-1": ("usw1-az2",), 

307 "ca-central-1": ("cac1-az3",), 

308} 

309"""AWS-region → Availability Zone IDs that cannot hold EKS cluster subnets. 

310 

311The regional VPC deliberately spans every AZ in the region (one public + one 

312private subnet each), but the EKS cluster's control-plane subnet selection must 

313exclude any subnet in these zones or ``CreateCluster`` fails with 

314``InvalidParameterException``. Regions absent from this map have no such 

315restriction. Keep in sync with the AWS EKS networking requirements doc. 

316""" 

317 

318# --------------------------------------------------------------------------- 

319# Aurora PostgreSQL Engine Version 

320# --------------------------------------------------------------------------- 

321# Pinned to a specific minor version. The dependency scanner checks 

322# ``aws rds describe-db-engine-versions`` monthly for newer releases 

323# within the same major line. 

324 

325AURORA_POSTGRES_VERSION = "VER_17_9" 

326"""CDK enum name for the Aurora PostgreSQL engine version (e.g. ``rds.AuroraPostgresEngineVersion.VER_17_9``).""" 

327 

328AURORA_POSTGRES_VERSION_DISPLAY = "17.9" 

329"""Human-readable version string for documentation and logging.""" 

330# --------------------------------------------------------------------------- 

331# Analytics Environment Constants 

332# --------------------------------------------------------------------------- 

333# Pinned values consumed by the optional analytics environment (SageMaker 

334# Studio, EMR Serverless, Cognito hosted UI, and the always-on 

335# Cluster_Shared_Bucket in ``GCOGlobalStack``). Keeping them here lets the 

336# analytics stack, the regional stack, the global stack, and the tests import 

337# from a single source of truth. 

338 

339EMR_SERVERLESS_RELEASE_LABEL = "emr-7.13.0" 

340"""EMR Serverless Spark release label used for ``emrserverless.CfnApplication``. 

341 

342Pinned to a stable Spark release so analytics workloads get a reproducible 

343runtime across deployments. Update alongside the EKS add-ons above when a 

344newer EMR release is validated against the studio notebooks. 

345""" 

346 

347SAGEMAKER_ROLE_NAME_PREFIX = "AmazonSageMaker" 

348"""Required prefix for the SageMaker Studio execution role name. 

349 

350Amazon SageMaker requires execution roles used by Studio domains to have a 

351name that starts with ``AmazonSageMaker`` so that AWS-managed policies and 

352service-linked trust relationships resolve correctly. Any role name generated 

353for ``SageMaker_Execution_Role`` must begin with this prefix. 

354""" 

355 

356 

357def cognito_domain_prefix_default(project_name: str) -> str: 

358 """Default prefix for the Cognito hosted-UI domain. 

359 

360 Derived from ``project_name`` (``<project_name>-studio``). The full domain 

361 prefix is assembled at synth time by appending the account id (e.g. 

362 ``gco-studio-123456789012``) so it stays globally unique within 

363 ``cognito.UserPoolDomain``. Operators may override the prefix through the 

364 ``analytics_environment.cognito.domain_prefix`` field in ``cdk.json``. 

365 

366 For ``project_name="gco"`` this renders ``gco-studio`` — identical to the 

367 pre-#139 literal. 

368 """ 

369 return f"{project_name}-studio" 

370 

371 

372STUDIO_PRESIGNED_URL_EXPIRY_SECONDS = 300 

373"""Default expiry (in seconds) for SageMaker Studio presigned domain URLs. 

374 

375Five minutes matches the shortest window accepted by 

376``CreatePresignedDomainUrl`` while still giving a user enough time to click 

377the link after the ``/studio/login`` Lambda returns it. The presigned-URL 

378Lambda reads this through the ``URL_EXPIRES_SECONDS`` environment variable 

379and callers may override it per-request. 

380""" 

381 

382 

383def cluster_shared_bucket_name_prefix(project_name: str) -> str: 

384 """Name prefix for the always-on ``Cluster_Shared_Bucket`` in ``GCOGlobalStack``. 

385 

386 Derived from ``project_name``. The full bucket name is 

387 ``<project_name>-cluster-shared-<account>-<global-region>``. The prefix is 

388 what IAM policies and cdk-nag allow-list assertions scope against, so both 

389 the bucket and the assertions must be built from the same ``project_name``. 

390 For ``project_name="gco"`` this renders ``gco-cluster-shared`` — identical 

391 to the pre-#139 literal. 

392 """ 

393 return f"{project_name}-cluster-shared" 

394 

395 

396def cluster_shared_ssm_parameter_prefix(project_name: str) -> str: 

397 """SSM parameter namespace for the cluster-shared bucket metadata. 

398 

399 Derived from ``project_name`` (``/<project_name>/cluster-shared-bucket``). 

400 ``GCOGlobalStack`` writes ``<prefix>/name``, ``<prefix>/arn``, and 

401 ``<prefix>/region`` under this path; ``GCORegionalStack`` (always) and 

402 ``GCOAnalyticsStack`` (when enabled) read them back via 

403 ``cr.AwsCustomResource`` against the global region. Treat the full paths as 

404 the contract. For ``project_name="gco"`` this renders 

405 ``/gco/cluster-shared-bucket``. 

406 """ 

407 return f"/{project_name}/cluster-shared-bucket" 

408 

409 

410def regional_shared_bucket_name_prefix(project_name: str) -> str: 

411 """Name prefix for the always-on general-purpose regional bucket. 

412 

413 Derived from ``project_name``. The full bucket name is 

414 ``<project_name>-regional-shared-<account>-<region>``. Each 

415 ``GCORegionalStack`` provisions exactly one such bucket per region, 

416 unconditionally — there is no ``cdk.json`` toggle and no feature flag 

417 gating its existence. It is general purpose (usable by any in-region 

418 workload) and is in addition to the always-on central buckets owned by 

419 ``GCOGlobalStack`` (the model bucket and the cluster-shared bucket). The 

420 prefix is what IAM policies and cdk-nag allow-list assertions scope 

421 against. For ``project_name="gco"`` this renders ``gco-regional-shared`` — 

422 identical to the pre-#139 literal. 

423 """ 

424 return f"{project_name}-regional-shared" 

425 

426 

427def regional_shared_ssm_parameter_prefix(project_name: str) -> str: 

428 """SSM parameter namespace for the regional general-purpose bucket metadata. 

429 

430 Derived from ``project_name`` (``/<project_name>/regional-shared-bucket``). 

431 Each ``GCORegionalStack`` writes ``<prefix>/name``, ``<prefix>/arn``, and 

432 ``<prefix>/region`` under this path **in its own region's** parameter 

433 store, exactly as the model bucket and cluster-shared bucket publish 

434 theirs. In-region workloads (and the regional upload surface) read them 

435 back to resolve the always-on regional bucket without hardcoding 

436 account/region into the name. 

437 

438 The per-region inference monitor builds the same path at runtime from its 

439 injected ``PROJECT_NAME`` environment variable rather than importing this 

440 helper (it needs no CDK imports at runtime), so keep the two in lockstep. 

441 For ``project_name="gco"`` this renders ``/gco/regional-shared-bucket``. 

442 """ 

443 return f"/{project_name}/regional-shared-bucket" 

444 

445 

446MOONCAKE_COLD_TIER_KEY_PREFIX = "mooncake-kv" 

447"""Object-key prefix for Mooncake cold-tier KV objects in the regional bucket. 

448 

449The per-region inference monitor resolves an endpoint's cold-tier object-store 

450URI to ``s3://gco-regional-shared-<account>-<region>/mooncake-kv/<endpoint>/``, 

451and the ``gco inference populate-kv`` upload surface writes under the same 

452prefix, so operator-supplied warm-up objects land exactly where an endpoint's 

453pods read them. This is the shared contract between the two sides; the monitor 

454keeps a local copy of this value so it needs no CDK imports at runtime, so keep 

455the two in lockstep if the prefix ever changes. 

456""" 

457 

458# --------------------------------------------------------------------------- 

459# Cost Monitoring Constants 

460# --------------------------------------------------------------------------- 

461# Shared contract between the monitoring stack (which owns the cost report 

462# bucket, Glue database/table, and Athena workgroup), the regional stacks 

463# (which grant the cost-monitor service write access by deterministic ARN), 

464# the cost-monitor service (which writes Parquet reports), and the CLI (which 

465# queries Athena). Everything below is derived from ``project_name`` so two 

466# deployments in one account never collide. 

467 

468COST_REPORT_SCHEDULED_PREFIX = "reports" 

469"""Object-key prefix for scheduled cost allocation reports. 

470 

471The cost-monitor service writes Hive-partitioned Parquet objects under 

472``reports/region=<region>/date=<YYYY-MM-DD>/...`` and the Glue table's 

473partition projection reads the same layout — keep the two in lockstep. 

474""" 

475 

476COST_REPORT_ADHOC_PREFIX = "adhoc" 

477"""Object-key prefix for ad-hoc (user-requested) cost reports. 

478 

479Kept out of the scheduled ``reports/`` prefix so an ad-hoc report whose 

480window overlaps a scheduled window can never double-count in Athena 

481aggregations over the scheduled table. 

482""" 

483 

484COST_ATHENA_RESULTS_PREFIX = "athena-results" 

485"""Object-key prefix for Athena query results inside the cost report bucket.""" 

486 

487 

488def cost_report_bucket_name_prefix(project_name: str) -> str: 

489 """Name prefix for the cost report bucket in ``GCOMonitoringStack``. 

490 

491 Derived from ``project_name``. The full bucket name is 

492 ``<project_name>-cost-reports-<account>-<monitoring-region>`` — fully 

493 deterministic at synth time, which lets every regional stack grant its 

494 cost-monitor role write access by literal ARN without a cross-region 

495 SSM read (and without inverting the regional-before-monitoring deploy 

496 order). The prefix is what IAM policies and cdk-nag allow-list 

497 assertions scope against. 

498 """ 

499 return f"{project_name}-cost-reports" 

500 

501 

502def cost_report_bucket_name(project_name: str, account: str, monitoring_region: str) -> str: 

503 """Deterministic physical name of the cost report bucket. 

504 

505 Single source of truth shared by the monitoring stack (which creates the 

506 bucket), the regional stacks (which inject the name into the cost-monitor 

507 service environment and grant S3 access by literal ARN), and the CLI 

508 (which resolves the bucket for Athena result downloads and report 

509 listings). 

510 """ 

511 return f"{cost_report_bucket_name_prefix(project_name)}-{account}-{monitoring_region}" 

512 

513 

514def cost_glue_database_name(project_name: str) -> str: 

515 """Glue database name for cost analytics. 

516 

517 Glue database names must not contain hyphens, so the project name's 

518 hyphens are folded to underscores (``gco`` renders ``gco_cost``). 

519 """ 

520 return f"{project_name.replace('-', '_')}_cost" 

521 

522 

523COST_GLUE_ALLOCATION_TABLE = "allocation_reports" 

524"""Glue table over the scheduled cost allocation reports.""" 

525 

526 

527def cost_athena_workgroup_name(project_name: str) -> str: 

528 """Athena workgroup name for cost analytics queries.""" 

529 return f"{project_name}-cost" 

530 

531 

532MOONCAKE_MASTER_DEFAULT_IMAGE = "vllm/vllm-openai:v0.26.0" 

533"""Default container image for the shared per-region Mooncake master. 

534 

535The master StatefulSet runs the ``mooncake_master`` daemon (RPC + built-in HTTP 

536metadata server). That binary ships in the ``mooncake-transfer-engine`` package 

537that the upstream vLLM OpenAI server image already bundles, so the same pinned 

538image used for disaggregated prefill/decode pods also serves the master without 

539a separate build. The inference monitor reads this through the 

540``MOONCAKE_MASTER_IMAGE`` environment variable and a per-endpoint 

541``spec.mooncake.store.master_image`` overrides it. 

542 

543Keep this tag in lockstep with ``cli/images.py:_DISAGGREGATED_DEFAULT_IMAGE`` 

544(the disaggregated role-pod default); bump both together when validating a new 

545vLLM release and never use a mutable/rolling tag such as ``latest``. 

546"""