Coverage for scripts / example_job_validation / static_checks.py: 100.00%

266 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-10-28 16:19 +0000

1"""Offline validation of every example against its documented contract. 

2 

3Runs with no AWS access and no cluster: parses each example, checks the 

4spec registry's symmetry with the ``examples/`` directory and the 

5``gco_mcp`` catalog, and — for examples documented to travel the API/SQS 

6submission paths — proves every document clears the exact transport gates 

7(kind/GVK allowlist, image-source trust, target namespace) that the 

8deployed services enforce. This is the half that runs in CI on every PR 

9(``tests/test_example_job_validation.py``); the live half in ``drivers.py`` 

10builds on the same parse. 

11""" 

12 

13from __future__ import annotations 

14 

15import copy 

16import re 

17from dataclasses import dataclass, field 

18from pathlib import Path 

19from typing import Any 

20 

21import yaml 

22 

23from .specs import ( 

24 CAPABILITY_TYPES, 

25 COMPANION, 

26 DAG_RUN, 

27 EXAMPLE_SPECS, 

28 SUBMISSION_PATHS, 

29 SUBMIT_API, 

30 SUBMIT_DIRECT, 

31 SUBMIT_SQS, 

32 ExampleSpec, 

33) 

34 

35#: Namespaces the platform provisions for user workloads. 

36_WORKLOAD_NAMESPACES = frozenset({"gco-jobs", "gco-inference"}) 

37 

38#: This repository's clone URLs. An Argo CD example must source one of them so 

39#: the offline checks (and the live waiter) can read exactly what it syncs. 

40THIS_REPOSITORY_URLS = frozenset( 

41 { 

42 "https://github.com/aws-solutions-library-samples/global-capacity-orchestrator-on-aws", 

43 "https://github.com/aws-solutions-library-samples/global-capacity-orchestrator-on-aws.git", 

44 } 

45) 

46 

47#: The self-managed Argo CD's namespace, fenced project and in-cluster server 

48#: (gco/argocd_config.py; post-helm-argocd-access.yaml). 

49_ARGOCD_NAMESPACE = "argocd" 

50_ARGOCD_PROJECT = "gco-tenants" 

51_IN_CLUSTER_SERVER = "https://kubernetes.default.svc" 

52 

53#: A whole-line Go template action (``{{ if ... }}`` / ``{{ end }}``). The 

54#: static read drops these lines; inline actions sit inside quoted YAML 

55#: strings, so what is left parses as the YAML the function renders. 

56_TEMPLATE_ACTION_LINE = re.compile(r"^[ \t]*\{\{.*\}\}[ \t]*$", re.MULTILINE) 

57 

58 

59@dataclass 

60class StaticFinding: 

61 """One offline check outcome for one example.""" 

62 

63 example: str 

64 check: str 

65 passed: bool 

66 detail: str = "" 

67 

68 

69@dataclass 

70class ParsedExample: 

71 """An example file parsed into documents plus its spec.""" 

72 

73 name: str 

74 path: Path 

75 spec: ExampleSpec 

76 documents: list[dict[str, Any]] = field(default_factory=list) 

77 

78 

79def examples_dir(repo_root: Path) -> Path: 

80 return repo_root / "examples" 

81 

82 

83def example_names(repo_root: Path) -> list[str]: 

84 return sorted(path.stem for path in examples_dir(repo_root).glob("*.yaml")) 

85 

86 

87def parse_example(repo_root: Path, name: str) -> ParsedExample: 

88 """Parse one example's YAML documents (raises on unknown name or bad YAML).""" 

89 spec = EXAMPLE_SPECS.get(name) 

90 if spec is None: 

91 raise KeyError(f"No validation spec for example {name!r} (add one in specs.py)") 

92 path = examples_dir(repo_root) / f"{name}.yaml" 

93 documents = [ 

94 doc for doc in yaml.safe_load_all(path.read_text(encoding="utf-8")) if doc is not None 

95 ] 

96 return ParsedExample(name=name, path=path, spec=spec, documents=documents) 

97 

98 

99def _catalog_metadata(repo_root: Path) -> dict[str, dict[str, Any]]: 

100 """Read ``gco_mcp``'s EXAMPLE_METADATA literal without executing the module. 

101 

102 ``gco_mcp/resources/docs.py`` imports flat sibling modules (the MCP server 

103 puts ``gco_mcp/`` itself on ``sys.path``), so importing it from here would 

104 require path surgery. The catalog is a pure literal dict, so an AST read 

105 is sufficient — and side-effect free. 

106 """ 

107 import ast 

108 

109 docs_path = repo_root / "gco_mcp" / "resources" / "docs.py" 

110 tree = ast.parse(docs_path.read_text(encoding="utf-8")) 

111 for node in ast.walk(tree): 

112 value: ast.expr | None = None 

113 targets: list[ast.expr] = [] 

114 if isinstance(node, ast.Assign): 

115 targets, value = node.targets, node.value 

116 elif isinstance(node, ast.AnnAssign) and node.value is not None: 

117 targets, value = [node.target], node.value 

118 for target in targets: 

119 if isinstance(target, ast.Name) and target.id == "EXAMPLE_METADATA": 

120 assert value is not None 

121 catalog = ast.literal_eval(value) 

122 if not isinstance(catalog, dict): 

123 raise RuntimeError("EXAMPLE_METADATA is not a dict literal") 

124 return catalog 

125 raise RuntimeError(f"EXAMPLE_METADATA literal not found in {docs_path}") 

126 

127 

128def check_registry_symmetry(repo_root: Path) -> list[StaticFinding]: 

129 """Specs, files, and the MCP catalog must describe the same example set.""" 

130 findings: list[StaticFinding] = [] 

131 files = set(example_names(repo_root)) 

132 specs = set(EXAMPLE_SPECS) 

133 catalog = set(_catalog_metadata(repo_root)) 

134 findings.append( 

135 StaticFinding( 

136 example="*", 

137 check="spec/file symmetry", 

138 passed=files == specs, 

139 detail=( 

140 f"only in examples/: {sorted(files - specs)}; only in specs: {sorted(specs - files)}" 

141 if files != specs 

142 else "" 

143 ), 

144 ) 

145 ) 

146 findings.append( 

147 StaticFinding( 

148 example="*", 

149 check="spec/catalog symmetry", 

150 passed=catalog == specs, 

151 detail=( 

152 f"only in catalog: {sorted(catalog - specs)}; only in specs: {sorted(specs - catalog)}" 

153 if catalog != specs 

154 else "" 

155 ), 

156 ) 

157 ) 

158 return findings 

159 

160 

161def check_submission_matches_catalog(repo_root: Path, name: str) -> StaticFinding: 

162 """The spec's submission path must agree with the catalog's documented command.""" 

163 meta = _catalog_metadata(repo_root).get(name, {}) 

164 documented = str(meta.get("submission", "")) 

165 spec = EXAMPLE_SPECS[name] 

166 expectations = { 

167 SUBMIT_DIRECT: "gco jobs submit-direct", 

168 SUBMIT_SQS: "gco jobs submit-sqs", 

169 SUBMIT_API: "gco jobs submit ", 

170 DAG_RUN: "gco dag run", 

171 } 

172 if spec.submission == SUBMIT_DIRECT: 

173 # Inference examples document `gco inference deploy` as the 

174 # recommended path and manifest-direct submission as the alternative; 

175 # both are valid documented shapes for a submit-direct spec. 

176 ok = "gco jobs submit-direct" in documented or "gco inference deploy" in documented 

177 detail = "" if ok else f"catalog documents {documented!r}, spec says {spec.submission}" 

178 elif spec.submission in expectations: 

179 ok = expectations[spec.submission] in documented 

180 detail = "" if ok else f"catalog documents {documented!r}, spec says {spec.submission}" 

181 elif spec.submission == COMPANION: 

182 ok = True 

183 detail = "" 

184 else: # kubectl-apply 

185 ok = "kubectl apply" in documented or documented == "" 

186 detail = "" if ok else f"catalog documents {documented!r}, spec says kubectl-apply" 

187 return StaticFinding(example=name, check="documented submission path", passed=ok, detail=detail) 

188 

189 

190def check_transport_acceptance(parsed: ParsedExample) -> list[StaticFinding]: 

191 """API/SQS-documented examples must clear the deployed validation gates.""" 

192 if parsed.spec.submission not in {SUBMIT_DIRECT, SUBMIT_SQS, SUBMIT_API}: 

193 return [] 

194 # Module-level pure functions: no Kubernetes client construction, so the 

195 # checks run on machines with no kubeconfig (CI runners, fresh laptops). 

196 from gco.services.manifest_processor import validate_image_sources, validate_resource_kind 

197 

198 findings: list[StaticFinding] = [] 

199 for doc in parsed.documents: 

200 label = f"{doc.get('kind')}/{(doc.get('metadata') or {}).get('name')}" 

201 if parsed.spec.submission in {SUBMIT_SQS, SUBMIT_API}: 

202 # Only the SQS/API services enforce the kind allowlist; 

203 # submit-direct is client-side kubectl and takes any kind. 

204 kind_ok, kind_reason = validate_resource_kind(doc) 

205 findings.append( 

206 StaticFinding( 

207 example=parsed.name, 

208 check=f"transport kind allowlist ({label})", 

209 passed=kind_ok, 

210 detail=kind_reason or "", 

211 ) 

212 ) 

213 image_ok, image_reason = validate_image_sources(doc) 

214 findings.append( 

215 StaticFinding( 

216 example=parsed.name, 

217 check=f"trusted image sources ({label})", 

218 passed=image_ok, 

219 detail=image_reason or "", 

220 ) 

221 ) 

222 return findings 

223 

224 

225def _is_argocd_application(doc: dict[str, Any]) -> bool: 

226 return doc.get("kind") == "Application" and str(doc.get("apiVersion", "")).startswith( 

227 "argoproj.io/" 

228 ) 

229 

230 

231def application_source_documents(repo_root: Path, doc: dict[str, Any]) -> list[dict[str, Any]]: 

232 """The manifests an Argo CD Application syncs from this repository, as Argo CD applies them. 

233 

234 Documents without a namespace get the Application's destination namespace 

235 (what Argo CD does). Returns ``[]`` when the Application sources another 

236 repository or a path outside this checkout: there is nothing to read. 

237 """ 

238 spec = doc.get("spec") or {} 

239 source = spec.get("source") or {} 

240 if str(source.get("repoURL", "")) not in THIS_REPOSITORY_URLS: 

241 return [] 

242 root = repo_root.resolve() 

243 directory = (root / str(source.get("path", ""))).resolve() 

244 if not directory.is_relative_to(root) or not directory.is_dir(): 

245 return [] 

246 destination = str((spec.get("destination") or {}).get("namespace", "")) 

247 documents: list[dict[str, Any]] = [] 

248 for path in sorted([*directory.glob("*.yaml"), *directory.glob("*.yml")]): 

249 for loaded in yaml.safe_load_all(path.read_text(encoding="utf-8")): 

250 if not isinstance(loaded, dict): 

251 continue 

252 item = copy.deepcopy(loaded) 

253 metadata = item.setdefault("metadata", {}) 

254 if not metadata.get("namespace"): 

255 metadata["namespace"] = destination 

256 documents.append(item) 

257 return documents 

258 

259 

260def _tenant_namespace(namespace: object) -> object: 

261 """A CEL / Go-template namespace expression resolves to the instance's tenant namespace. 

262 

263 Instances live in gco-jobs or gco-inference; gco-jobs carries the 

264 governance, so the offline checks evaluate templated namespaces there. 

265 """ 

266 if namespace is None or ( 

267 isinstance(namespace, str) and ("${" in namespace or "{{" in namespace) 

268 ): 

269 return "gco-jobs" 

270 return namespace 

271 

272 

273def embedded_workload_documents(repo_root: Path, doc: dict[str, Any]) -> list[dict[str, Any]]: 

274 """What an Application, a kro RGD or a go-templating Composition will create. 

275 

276 * Argo CD Application: the manifests at its Git path in this checkout. 

277 * kro ResourceGraphDefinition: each ``resources[].template``. 

278 * Crossplane Composition: each document an inline ``GoTemplate`` renders 

279 (the composite's own status document excluded). 

280 

281 Templated namespaces resolve to gco-jobs (see :func:`_tenant_namespace`). 

282 """ 

283 kind = doc.get("kind") 

284 api_version = str(doc.get("apiVersion", "")) 

285 spec = doc.get("spec") or {} 

286 if _is_argocd_application(doc): 

287 return application_source_documents(repo_root, doc) 

288 templates: list[dict[str, Any]] = [] 

289 if kind == "ResourceGraphDefinition" and api_version.startswith("kro.run/"): 

290 templates = [ 

291 copy.deepcopy(resource["template"]) 

292 for resource in spec.get("resources") or [] 

293 if isinstance(resource, dict) and isinstance(resource.get("template"), dict) 

294 ] 

295 elif kind == "Composition" and api_version.startswith("apiextensions.crossplane.io/"): 

296 composite = spec.get("compositeTypeRef") or {} 

297 for step in spec.get("pipeline") or []: 

298 step_input = (step or {}).get("input") or {} 

299 if step_input.get("kind") != "GoTemplate" or step_input.get("source") != "Inline": 

300 continue 

301 text = _TEMPLATE_ACTION_LINE.sub( 

302 "", str((step_input.get("inline") or {}).get("template", "")) 

303 ) 

304 templates.extend( 

305 item 

306 for item in yaml.safe_load_all(text) 

307 if isinstance(item, dict) 

308 and (item.get("apiVersion"), item.get("kind")) 

309 != (composite.get("apiVersion"), composite.get("kind")) 

310 ) 

311 for template in templates: 

312 metadata = template.setdefault("metadata", {}) 

313 metadata["namespace"] = _tenant_namespace(metadata.get("namespace")) 

314 return templates 

315 

316 

317def check_namespaces(parsed: ParsedExample) -> list[StaticFinding]: 

318 """Namespaced example documents must target a provisioned workload namespace. 

319 

320 An Argo CD Application is the one exception: it lives in the argocd 

321 namespace by design, so it must instead stay inside the fence — the 

322 gco-tenants project, the in-cluster server and a tenant destination. 

323 """ 

324 findings: list[StaticFinding] = [] 

325 for doc in parsed.documents: 

326 metadata = doc.get("metadata") or {} 

327 namespace = metadata.get("namespace") 

328 kind = str(doc.get("kind", "")) 

329 if kind in {"ResourceFlavor", "ClusterQueue"}: # cluster-scoped 

330 continue 

331 if _is_argocd_application(doc): 

332 spec = doc.get("spec") or {} 

333 destination = spec.get("destination") or {} 

334 problems = [ 

335 problem 

336 for problem, failed in ( 

337 ( 

338 f"namespace {namespace!r} is not {_ARGOCD_NAMESPACE!r}", 

339 namespace != _ARGOCD_NAMESPACE, 

340 ), 

341 ( 

342 f"project {spec.get('project')!r} is not {_ARGOCD_PROJECT!r}", 

343 spec.get("project") != _ARGOCD_PROJECT, 

344 ), 

345 ( 

346 f"destination server {destination.get('server')!r} is not the in-cluster server", 

347 destination.get("server") != _IN_CLUSTER_SERVER, 

348 ), 

349 ( 

350 f"destination namespace {destination.get('namespace')!r} is not a workload namespace", 

351 destination.get("namespace") not in _WORKLOAD_NAMESPACES, 

352 ), 

353 ) 

354 if failed 

355 ] 

356 findings.append( 

357 StaticFinding( 

358 example=parsed.name, 

359 check=f"Argo CD fence ({kind}/{metadata.get('name')})", 

360 passed=not problems, 

361 detail="; ".join(problems), 

362 ) 

363 ) 

364 continue 

365 if namespace is None: 

366 continue 

367 findings.append( 

368 StaticFinding( 

369 example=parsed.name, 

370 check=f"workload namespace ({kind}/{metadata.get('name')})", 

371 passed=namespace in _WORKLOAD_NAMESPACES, 

372 detail="" if namespace in _WORKLOAD_NAMESPACES else f"namespace {namespace!r}", 

373 ) 

374 ) 

375 return findings 

376 

377 

378def check_spec_shape(name: str) -> StaticFinding: 

379 """Spec fields must use known enumerations and name real companions.""" 

380 spec = EXAMPLE_SPECS[name] 

381 problems: list[str] = [] 

382 if spec.submission not in SUBMISSION_PATHS: 

383 problems.append(f"unknown submission path {spec.submission!r}") 

384 unknown_capabilities = sorted(set(spec.capability_overrides) - set(CAPABILITY_TYPES)) 

385 if unknown_capabilities: 

386 problems.append(f"unknown EKS capability type(s) {unknown_capabilities}") 

387 if spec.ack_iam_policy_arns and "ack" not in spec.capability_overrides: 

388 problems.append("ack_iam_policy_arns needs capability_overrides to include 'ack'") 

389 if spec.companion: 

390 companion = EXAMPLE_SPECS.get(spec.companion) 

391 if companion is None or companion.submission != COMPANION: 

392 problems.append(f"companion {spec.companion!r} is not a companion-artifact spec") 

393 return StaticFinding( 

394 example=name, 

395 check="spec shape", 

396 passed=not problems, 

397 detail="; ".join(problems), 

398 ) 

399 

400 

401def check_embedded_workloads(repo_root: Path, parsed: ParsedExample) -> list[StaticFinding]: 

402 """What an Application syncs, or an RGD / Composition composes, meets the example rules. 

403 

404 These workloads never cross the GCO API, so nothing else checks them 

405 before they reach a cluster: they must land in a workload namespace, pull 

406 from trusted image sources and fit the default gco-jobs governance. An 

407 Application must also source a non-empty path of this repository. 

408 """ 

409 from gco.services.manifest_processor import validate_image_sources 

410 

411 findings: list[StaticFinding] = [] 

412 for doc in parsed.documents: 

413 embedded = embedded_workload_documents(repo_root, doc) 

414 label = f"{doc.get('kind')}/{(doc.get('metadata') or {}).get('name')}" 

415 if _is_argocd_application(doc): 

416 findings.append( 

417 StaticFinding( 

418 example=parsed.name, 

419 check=f"Git source resolves ({label})", 

420 passed=bool(embedded), 

421 detail="" 

422 if embedded 

423 else "the Application must source a non-empty directory of this repository", 

424 ) 

425 ) 

426 for item in embedded: 

427 item_label = f"{label} -> {item.get('kind')}/{(item.get('metadata') or {}).get('name')}" 

428 namespace = (item.get("metadata") or {}).get("namespace") 

429 findings.append( 

430 StaticFinding( 

431 example=parsed.name, 

432 check=f"embedded workload namespace ({item_label})", 

433 passed=namespace in _WORKLOAD_NAMESPACES, 

434 detail="" if namespace in _WORKLOAD_NAMESPACES else f"namespace {namespace!r}", 

435 ) 

436 ) 

437 image_ok, image_reason = validate_image_sources(item) 

438 findings.append( 

439 StaticFinding( 

440 example=parsed.name, 

441 check=f"trusted image sources ({item_label})", 

442 passed=image_ok, 

443 detail=image_reason or "", 

444 ) 

445 ) 

446 findings.extend(_governance_findings(parsed, embedded)) 

447 return findings 

448 

449 

450#: Container resource dimensions governed by the gco-jobs LimitRange, mapped 

451#: to their per-container default ceiling key in DEFAULT_RESOURCE_QUOTA. 

452_LIMIT_RANGE_DIMENSIONS = { 

453 "cpu": "container_max_cpu", 

454 "memory": "container_max_memory", 

455 "nvidia.com/gpu": "container_max_gpu", 

456} 

457 

458#: Aggregate request dimensions governed by the gco-jobs ResourceQuota. 

459_QUOTA_DIMENSIONS = { 

460 "cpu": "max_cpu", 

461 "memory": "max_memory", 

462 "nvidia.com/gpu": "max_gpu", 

463} 

464 

465 

466def check_resource_governance_fit(parsed: ParsedExample) -> list[StaticFinding]: 

467 """Every example must be admissible under the default gco-jobs governance. 

468 

469 A container exceeding the LimitRange maxima is rejected at pod creation 

470 with only namespace events explaining why, and the Job sits podless until 

471 the caller gives up — the previous defaults rejected the platform's own 

472 EFA training example exactly that way (live run ex241-df723811). Proving 

473 the fit offline keeps the shipped examples and the shipped guardrails 

474 from contradicting each other again. Only gco-jobs-namespaced pod specs 

475 are checked: the LimitRange and ResourceQuota bind that namespace. 

476 """ 

477 return _governance_findings(parsed, parsed.documents) 

478 

479 

480def _governance_findings( 

481 parsed: ParsedExample, documents: list[dict[str, Any]] 

482) -> list[StaticFinding]: 

483 """LimitRange / ResourceQuota (and front-door cap) fit for ``documents``.""" 

484 from gco.stacks.constants import DEFAULT_RESOURCE_QUOTA, parse_k8s_quantity 

485 

486 findings: list[StaticFinding] = [] 

487 for doc in documents: 

488 kind = str(doc.get("kind", "")) 

489 metadata = doc.get("metadata") or {} 

490 if metadata.get("namespace", "gco-jobs") != "gco-jobs": 

491 continue 

492 pod_spec, replicas = _pod_spec_and_parallelism(doc, kind) 

493 if pod_spec is None: 

494 continue 

495 containers = list(pod_spec.get("containers") or []) + list( 

496 pod_spec.get("initContainers") or [] 

497 ) 

498 aggregate: dict[str, float] = dict.fromkeys(_QUOTA_DIMENSIONS, 0.0) 

499 for container in containers: 

500 resources = container.get("resources") or {} 

501 requests = resources.get("requests") or {} 

502 limits = resources.get("limits") or {} 

503 for dimension, ceiling_key in _LIMIT_RANGE_DIMENSIONS.items(): 

504 ceiling = parse_k8s_quantity(DEFAULT_RESOURCE_QUOTA[ceiling_key]) 

505 for source_name, source in (("requests", requests), ("limits", limits)): 

506 if dimension not in source: 

507 continue 

508 value = parse_k8s_quantity(source[dimension]) 

509 findings.append( 

510 StaticFinding( 

511 example=parsed.name, 

512 check=( 

513 f"LimitRange fit ({kind}/{metadata.get('name')}: " 

514 f"{container.get('name')} {source_name}.{dimension})" 

515 ), 

516 passed=value <= ceiling, 

517 detail="" 

518 if value <= ceiling 

519 else ( 

520 f"{source[dimension]} exceeds the default per-container " 

521 f"ceiling {DEFAULT_RESOURCE_QUOTA[ceiling_key]} " 

522 f"({ceiling_key})" 

523 ), 

524 ) 

525 ) 

526 for dimension in _QUOTA_DIMENSIONS: 

527 if dimension in requests: 

528 aggregate[dimension] += parse_k8s_quantity(requests[dimension]) 

529 for dimension, quota_key in _QUOTA_DIMENSIONS.items(): 

530 total = aggregate[dimension] * replicas 

531 quota = parse_k8s_quantity(DEFAULT_RESOURCE_QUOTA[quota_key]) 

532 findings.append( 

533 StaticFinding( 

534 example=parsed.name, 

535 check=( 

536 f"ResourceQuota fit ({kind}/{metadata.get('name')}: " 

537 f"{replicas}x pod requests.{dimension})" 

538 ), 

539 passed=total <= quota, 

540 detail="" 

541 if total <= quota 

542 else ( 

543 f"aggregate {total:g} exceeds the default namespace quota " 

544 f"{DEFAULT_RESOURCE_QUOTA[quota_key]} ({quota_key})" 

545 ), 

546 ) 

547 ) 

548 if parsed.spec.submission in {SUBMIT_API, SUBMIT_SQS}: 

549 findings.extend( 

550 _manifest_cap_findings(parsed, kind, str(metadata.get("name")), aggregate, replicas) 

551 ) 

552 return findings 

553 

554 

555#: Front-door budget dimensions (manifest/queue processor caps) by 

556#: DEFAULT_MANIFEST_RESOURCE_CAPS key. 

557_MANIFEST_CAP_DIMENSIONS = { 

558 "cpu": "max_cpu_per_manifest", 

559 "memory": "max_memory_per_manifest", 

560 "nvidia.com/gpu": "max_gpu_per_manifest", 

561} 

562 

563 

564def _manifest_cap_findings( 

565 parsed: ParsedExample, 

566 kind: str, 

567 name: str, 

568 aggregate: dict[str, float], 

569 replicas: int, 

570) -> list[StaticFinding]: 

571 """API/SQS-submitted manifests must also fit the front-door budget. 

572 

573 The manifest and queue processors cap what one submitted manifest may 

574 total; an example the front door rejects while kubectl admits it (or 

575 vice versa) means the layers contradict each other. 

576 """ 

577 from gco.stacks.constants import DEFAULT_MANIFEST_RESOURCE_CAPS, parse_k8s_quantity 

578 

579 findings: list[StaticFinding] = [] 

580 for dimension, cap_key in _MANIFEST_CAP_DIMENSIONS.items(): 

581 total = aggregate[dimension] * replicas 

582 cap = parse_k8s_quantity(DEFAULT_MANIFEST_RESOURCE_CAPS[cap_key]) 

583 findings.append( 

584 StaticFinding( 

585 example=parsed.name, 

586 check=f"manifest-cap fit ({kind}/{name}: {replicas}x pod requests.{dimension})", 

587 passed=total <= cap, 

588 detail="" 

589 if total <= cap 

590 else ( 

591 f"aggregate {total:g} exceeds the default per-manifest cap " 

592 f"{DEFAULT_MANIFEST_RESOURCE_CAPS[cap_key]} ({cap_key})" 

593 ), 

594 ) 

595 ) 

596 return findings 

597 

598 

599def _pod_spec_and_parallelism(doc: dict[str, Any], kind: str) -> tuple[dict[str, Any] | None, int]: 

600 """Extract the pod template spec and concurrent-pod count for a workload.""" 

601 spec = doc.get("spec") or {} 

602 if kind == "Job": 

603 template_spec = ((spec.get("template") or {}).get("spec")) or None 

604 return template_spec, int(spec.get("parallelism", 1) or 1) 

605 if kind in {"Deployment", "StatefulSet"}: 

606 template_spec = ((spec.get("template") or {}).get("spec")) or None 

607 return template_spec, int(spec.get("replicas", 1) or 1) 

608 if kind == "Pod": 

609 return spec or None, 1 

610 if kind == "TrainJob": 

611 # A TrainJob runs its spec.trainer view once per node; the shared 

612 # decomposition builds the same synthetic pod spec the deployed 

613 # validators check, so the offline governance math matches theirs. 

614 from gco.services.manifest_processor import extract_trainjob_pod_specs 

615 

616 trainjob_specs = extract_trainjob_pod_specs(doc) 

617 return trainjob_specs.trainer, trainjob_specs.num_nodes 

618 return None, 1 

619 

620 

621def run_static_checks(repo_root: Path, names: list[str] | None = None) -> list[StaticFinding]: 

622 """Run every offline check; returns findings (all must pass).""" 

623 findings = check_registry_symmetry(repo_root) 

624 for name in names or example_names(repo_root): 

625 findings.append(check_spec_shape(name)) 

626 if EXAMPLE_SPECS.get(name) is None: 

627 continue 

628 parsed = parse_example(repo_root, name) 

629 findings.append(check_submission_matches_catalog(repo_root, name)) 

630 findings.extend(check_transport_acceptance(parsed)) 

631 findings.extend(check_namespaces(parsed)) 

632 findings.extend(check_resource_governance_fit(parsed)) 

633 findings.extend(check_embedded_workloads(repo_root, parsed)) 

634 return findings