From c43b533c5488954f4c960c1f24ea34a4f5ccb54d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 09:47:34 -0400 Subject: [PATCH 01/67] docs(dark-factory): add Autonomous Agent Coding Pattern design + flow diagrams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design doc for the Dark Factory pattern (doc-only, no runtime code): - docs/dark-factory/README.md — full design: two flows (Agent Sandbox capability + Dark Factory pipeline), pluggable coder (Claude Code / Kiro), holdout gate, AWS frontier agents, live PR status, lifecycle, security model, industry alignment + anti-patterns (lethal trifecta, reward hacking, LLM-judge bias), phased delivery. - docs/dark-factory/diagrams/flow-a-sandbox-capability.md — capability architecture + warm-pool state machine (mermaid). - docs/dark-factory/diagrams/flow-b-dark-factory.md — end-to-end pipeline, detailed sequence, live-status mock (mermaid). Grounds every reuse in eks-platform-openclaw (Sandbox CRD, session-router, LiteLLM), appmod-blueprints (PlatformCluster), and agent-platform-amazon-eks (addon ApplicationSets). Validated against Copilot/Codex/Devin/StrongDM. --- docs/dark-factory/README.md | 432 ++++++++++++++++++ .../diagrams/flow-a-sandbox-capability.md | 100 ++++ .../diagrams/flow-b-dark-factory.md | 160 +++++++ 3 files changed, 692 insertions(+) create mode 100644 docs/dark-factory/README.md create mode 100644 docs/dark-factory/diagrams/flow-a-sandbox-capability.md create mode 100644 docs/dark-factory/diagrams/flow-b-dark-factory.md diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md new file mode 100644 index 0000000..a577f22 --- /dev/null +++ b/docs/dark-factory/README.md @@ -0,0 +1,432 @@ +# Dark Factory — Autonomous Agent Coding Pattern + +> **Status:** Design document (doc-only). This describes the target architecture, the reuse +> map onto the existing platform, and a phased delivery plan. No runtime code ships in this PR. + +A **dark factory** is a manufacturing plant that runs *with the lights off* — no humans on the +floor, robots do everything. Applied to software: **a human writes an issue (a spec); AI agents +do the rest** — implement, build, test, security/ops review, open a PR, and (after a human +approves the *results*) merge and tear everything down. + +This pattern wires that idea onto the **Open Agent Platform (OAP)** using components the platform +already has: hardware-isolated **Kata micro-VM sandboxes** (from `eks-platform-openclaw`), the +**LiteLLM → Bedrock** model gateway, the **hub + spoke-dev/spoke-prod** cluster fleet, and +**AWS-managed frontier agents** (Security, DevOps) for independent review. + +--- + +## Table of contents +1. [What is a Dark Factory](#1-what-is-a-dark-factory) +2. [Two flows at a glance](#2-two-flows-at-a-glance) +3. [Flow A — Agent Sandbox capability](#3-flow-a--agent-sandbox-capability-permanent-platform-feature) +4. [Flow B — the Dark Factory pipeline](#4-flow-b--the-dark-factory-pipeline) +5. [The pluggable coding assistant](#5-the-pluggable-coding-assistant) +6. [Independent verification](#6-independent-verification-the-heart-of-the-pattern) +7. [Live status in the PR](#7-live-status-in-the-pr) +8. [Human-in-the-loop & the comment loop](#8-human-in-the-loop--the-iterative-comment-loop) +9. [Lifecycle, teardown & cost](#9-lifecycle-teardown--cost) +10. [Security model](#10-security-model) +11. [Industry alignment & anti-patterns](#11-industry-alignment--anti-patterns-what-the-world-agrees-on) +12. [Phased delivery](#12-phased-delivery) +13. [Open questions / future work](#13-open-questions--future-work) +14. [References](#14-references) + +--- + +## 1. What is a Dark Factory + +The term is borrowed from manufacturing and popularized for coding by two sources this design +draws on: + +- **Steve Yegge — "Welcome to Gas City"**: a *supervisor plane* that deploys teams of + collaborating agents as composable "packs," where humans **watch the factory work** from a + rich console rather than typing code. Work is a first-class, versioned primitive. +- **HackerNoon — "The Dark Factory Pattern"**: an **autonomy-level** ladder and the key + engineering ideas — **specs instead of code**, **holdout scenarios** (the coding agent never + sees the acceptance tests; a separate evaluator judges), **build-before-push**, ephemeral + environments, and **humans reviewing results, not diffs**. + +### Autonomy levels (we target Level 3) + +| Level | What it looks like | +|------:|--------------------| +| 1 | AI finishes your sentences; you do everything else. | +| 2 | AI writes whole files; **you review every change**. | +| **3** | **AI generates code from a spec; a holdout gate + reviewers verify; you approve the merge.** ← *this design* | +| 3.5 | Some low-risk services auto-merge without you. | +| 4 | Full dark factory: specs in, merged tested code out. | + +At **Level 3**, the human's job shrinks from *"read every line of a diff"* to *"read the evidence +and click approve"* — but the human still gates the merge, and can drive changes via PR comments. + +--- + +## 2. Two flows at a glance + +This design is deliberately split into **two independent flows** so the sandbox capability is +useful on its own and the factory is a consumer of it. + +| | **Flow A — Agent Sandbox capability** | **Flow B — Dark Factory** | +|---|---|---| +| **What** | A permanent platform feature: Kata micro-VM sandboxes + `Sandbox` CRD + a **warm pool** kept ready | The autonomous coding pipeline: issue → code → test → review → PR → merge → teardown | +| **When** | Comes up automatically when the agent platform is deployed | Triggered per GitHub issue labeled `dark-factory` | +| **Where** | Installed on **spoke-dev *and* spoke-prod** (capability on both) | **Runs only on spoke-dev** (prod pool stays dormant) | +| **Lifecycle** | Long-lived; pool self-heals to a target buffer | Ephemeral per issue; torn down on merge/close | +| **Diagram** | [`diagrams/flow-a-sandbox-capability.md`](diagrams/flow-a-sandbox-capability.md) | [`diagrams/flow-b-dark-factory.md`](diagrams/flow-b-dark-factory.md) | + +> **Why split them?** The sandbox capability is generically useful (any agent workload can claim +> an isolated VM). The Dark Factory is one *consumer* of that capability. Keeping them separate +> means the isolation substrate can ship, be tested, and be reused independently of the factory. + +--- + +## 3. Flow A — Agent Sandbox capability (permanent platform feature) + +> 📊 **See the fancy diagrams:** [`diagrams/flow-a-sandbox-capability.md`](diagrams/flow-a-sandbox-capability.md) +> (capability architecture + warm-pool state machine). + +Shipped as a GitOps addon, enabled exactly like every other platform addon — set a flag, an +ApplicationSet fans it onto the labelled clusters: + +```yaml +# gitops/overlays/environments/{dev,prod}/enabled-addons.yaml +enabledAddons: + enable_agent_sandbox: true # → ApplicationSet cluster-generator → ArgoCD sync waves +``` + +### What the addon installs (all reused from `eks-platform-openclaw`) + +| Piece | Source in `eks-platform-openclaw` | Role | +|---|---|---| +| **Kata runtime (Cloud Hypervisor default)** | `gitops/helm/kata/` + `kata-deploy` | Hardware VM isolation per sandbox | +| **RuntimeClasses** `kata-clh` · `kata-qemu` · `kata-fc` | `gitops/helm/kata/templates/runtimeclass-*.yaml` | Workload picks VMM via `runtimeClassName` | +| **Karpenter pools** `kata-nested` / `kata-metal` | `gitops/helm/karpenter-nodepools/` | Nested-virt `c8i/m8i` nodes (bare-metal fallback) | +| **`Sandbox` CRD + operator** (`agents.x-k8s.io/v1alpha1`) | `gitops/helm/agent-sandbox/` (sync-wave −1) | One Kata-VM pod per `Sandbox` CR; `replicas 0/1` scale subresource | +| **`SandboxTemplate` / `SandboxClaim`** | `.../agent-sandbox/templates/extensions.yaml` | Claim → template binding (like PVC → PV) | +| **Pool-manager controller** *(net-new)* | — | Maintains the warm buffer; refills on claim; shrinks on release | + +> ⚠️ **Import gap:** the `agent-sandbox` operator is not yet packaged as an OAP addon chart. Flow A's +> first implementation task is to import/repackage it from `eks-platform-openclaw` into the OAP +> addon catalog (`gitops/addons/`). + +### Warm pool — instant claims, cheap idle + +When the platform finishes deploying, the pool-manager brings up a **target buffer of 2–3 idle +sandboxes**. A consumer binds to a *ready* VM instantly (no cold boot). Cycling rules: + +- **On claim** → provision a **refill** so the buffer stays at target. +- **On release** → if the pool is above target, **remove** the extra idle sandbox. +- **Idle** sandboxes scale to `replicas: 0` (PVC retained) and resume on demand. + +> 💡 **Cost note (industry gotcha):** a literal pool of *parked, running* micro-VMs burns money. +> The consensus mitigation (E2B, Modal, Bedrock AgentCore) is **snapshot/fork-from-template + idle +> reaping**, not idle VMs left running. Implementation should prefer snapshot-restore where the +> Kata VMM supports it, and always pair the pool with aggressive idle TTL reaping. See +> [§9](#9-lifecycle-teardown--cost). + +--- + +## 4. Flow B — the Dark Factory pipeline + +> 📊 **See the fancy diagrams:** [`diagrams/flow-b-dark-factory.md`](diagrams/flow-b-dark-factory.md) +> (end-to-end pipeline + detailed sequence + live-status mock). + +Runs on **spoke-dev only**. End to end: + +1. **Trigger** — an issue labeled `dark-factory` fires a **GitHub Action**. The Action gates on the + label, mints a **short-TTL** installation token, and calls the orchestrator. *(Net-new — OAP has + no GitHub Actions today.)* +2. **Claim** — the **orchestrator** (adapting the openclaw `session-router`, but keyed on + **issue-id** instead of a Cognito `sub`) issues a `SandboxClaim` and **binds a warm sandbox**. + The pool-manager refills the buffer. +3. **Code** — the issue is written into the sandbox as `/workspace/SPEC.md`. The **pluggable + coder** (Claude Code headless by default; Kiro headless as a profile) implements on branch + `df/issue-` and **builds + runs unit tests until green** inside the VM. +4. **Independent verification** *(driven by the orchestrator — never by the coder — see [§6](#6-independent-verification-the-heart-of-the-pattern)):* + - **Holdout gate** — hidden BDD scenarios the coder can neither see nor edit, judged by a + **different model** than the coder used, **paired with executable tests**, ≥90% to pass. + - **AWS frontier agents** — the orchestrator invokes the **AWS Security Agent** and **AWS DevOps + Agent** on the diff/artifacts (advisory in v1). +5. **PR + live status** — the coder opens a PR via `gh`; the orchestrator maintains **one sticky + comment** that ticks each stage ⏳→✅/❌ with timestamps and log links (see [§7](#7-live-status-in-the-pr)). +6. **Human review** — a human reviews the **evidence** (test results, holdout satisfaction, + security/devops findings) and either approves or comments. +7. **Iterate** — a PR comment resumes the scaled-to-zero sandbox (same workspace) and the coder + applies the change. **Bounded to N rounds**, then a human breaks the tie (see [§8](#8-human-in-the-loop--the-iterative-comment-loop)). +8. **Merge + teardown** — on approve→merge, the orchestrator deletes the sandbox, PVC, any + ephemeral test infra, and the eval job. A **reaper CronJob** sweeps abandoned/timed-out runs. + +### Two worked use-cases + +| Issue example | How it's tested | Teardown | +|---|---|---| +| *"Add a `weather-agent` to the examples"* | Deploy into an **ephemeral namespace** on spoke-dev → run holdout scenarios → delete namespace | Namespace + branch artifacts | +| *"Build an EKS cluster with X"* | **Dry-run / crossplane-render** by default; a `deep-test` label spins a **real ephemeral `PlatformCluster`** (appmod-blueprints composition) | Delete the `PlatformCluster` claim | + +--- + +## 5. The pluggable coding assistant + +The coder is behind a **thin, swappable interface** — a deliberate choice (the industry lesson is +*don't marry a single vendor*). Two profiles ship; both run **inside** the Kata sandbox and reach +models only through LiteLLM. + +| Profile | Why | Notes | +|---|---|---| +| **A — Claude Code headless** *(primary)* | Purpose-built for autonomous implement→build→test→git loops; proven headless/CI autonomy | `CLAUDE_CODE_USE_BEDROCK` / base-URL → LiteLLM; strongest multi-file + shell | +| **B — Kiro headless** | **Spec-driven** (`spec → requirements → design → tasks`) — the most natural fit since *an issue is a spec*; supports a headless GitHub Actions mode | AWS-native; documented as the second profile | + +### The coder contract (drop-in interface) + +Everything crosses the boundary as **files + env**, so swapping profiles is one config line: + +``` +INPUTS (mounted into the sandbox) + /workspace/SPEC.md # the issue, as a spec + /workspace/repo/ # the checked-out target repo (branch df/issue-) + /workspace/RETRY.md # (optional) one-line failure reasons from a prior holdout run + tmpfs: litellm-api-key # mode 0400, read then unset — never in env + tmpfs: gh-token # short-TTL, mode 0400 +ENV + CODER_PROFILE=claude-code|kiro + LITELLM_URL=http://litellm.litellm.svc:4000 +OUTPUTS (produced by the coder) + git branch df/issue- with commits + /workspace/artifacts/result.json # what changed, build/test logs, evidence links +``` + +> The holdout scenarios are **deliberately absent** from this list — the coder never receives them. +> See [§6](#6-independent-verification-the-heart-of-the-pattern). + +--- + +## 6. Independent verification (the heart of the pattern) + +This is the part most teams skip — and it's why their agents learn to *game the tests*. Two +independent checks run **outside** the coder's control. + +### 6.1 Holdout gate — train/test separation for code + +Acceptance criteria are written as **plain-English BDD scenarios** that live in a location the +coder **cannot see or edit**. A separate evaluator job runs them against the built code. + +``` +holdout/ + scenarios/*.feature # hidden acceptance scenarios (never mounted into the sandbox) + rubric.md # how the judge scores +``` + +**Hard rules (these are the whole point):** + +1. **The coder cannot read or write the holdout.** Scenarios are never mounted into the sandbox; + the coder's repo checkout **excludes the grading-test path**. On a failed run the coder gets + only **one-line reasons** in `RETRY.md` — never the scenario text. +2. **A different model judges.** The evaluator's LLM judge must be a **different model/family than + the coder** (defeats self-preference bias — a model scores its own output higher). +3. **The judge is never the sole gate.** Every scenario is paired with **executable tests**; the + LLM judgment is one signal, not the verdict. Each scenario runs **2-of-3** to smooth + non-determinism. Gate = **≥90%** satisfaction. + +> This mirrors ML holdout sets and is directly validated by StrongDM's "Software Factory," which +> found *"`return true` is a great way to pass narrowly written tests"* and fixed it by storing +> scenarios **outside** the codebase. + +### 6.2 AWS frontier agents — independent, read-only reviewers + +The **orchestrator** (not the coder) invokes the **AWS Security Agent** and **AWS DevOps Agent** on +the finished diff/artifacts: + +- They are **out-of-cluster, AWS-managed** services — **not** kagent pods. +- They are **read-only reviewers on the finished diff** — never co-authors. Their findings are + folded into the PR report; the coder only *reacts* to them via the comment loop. +- **v1 = advisory** (report-only). Gate hooks are designed so **per-severity blocking** can be + switched on later (e.g. a critical CVE blocks the PR). + +> **Why the orchestrator invokes them, not the coder:** it keeps the untrusted sandbox +> **credential-less** and preserves *separation of concerns* — the agent doing the work is not the +> one grading it (see the [lethal-trifecta gotcha](#11-industry-alignment--anti-patterns-what-the-world-agrees-on)). + +--- + +## 7. Live status in the PR + +The human **watches the factory work** (the Gas City idea) through **one sticky PR comment** the +orchestrator edits in place — no comment spam, one canonical surface (the pattern Copilot, Devin, +and Factory all converge on). + +``` +## 🏭 Dark Factory — issue #42 +✅ Claimed sandbox (spoke-dev) 12:01 +✅ Branch df/issue-42 12:01 +✅ Implement 12:04 +✅ Build + unit tests 12:07 📄 log +⏳ Security Agent… +⬜ DevOps Agent +⬜ Holdout gate (0/12) +⬜ PR ready for review +``` + +Each stage links to raw logs and test output (**verifiability-by-citation** — the human can audit +any step). The full PR body carries the report: what changed, test results, holdout satisfaction %, +and the Security/DevOps findings. + +--- + +## 8. Human-in-the-loop & the iterative comment loop + +Level 3 means the **human approves the merge** — and can steer via comments: + +- A PR comment (change requested) → the orchestrator **resumes the scaled-to-zero sandbox** (same + workspace PVC) → the coder applies the change → pushes → the sticky status updates. +- **Bounded convergence:** the loop is capped at **N rounds**; after that a human must break the + tie. Comments are **batched into one agent run** (don't fire the agent per un-batched comment — + it thrashes). +- The agent **never self-merges**; it only pushes to its own `df/issue-` branch. Branch + protections and CI still apply. + +--- + +## 9. Lifecycle, teardown & cost + +| Phase | Sandbox state | Cost posture | +|---|---|---| +| Idle in warm pool | `replicas: 0` or snapshot | Minimal (no running VM) | +| Claimed / coding | `replicas: 1` | Active VM billed | +| Awaiting review | **`replicas: 0`** (PVC kept) | Minimal — resumes on comment | +| Merged / closed | **Deleted** (Sandbox + PVC + test infra + eval job) | Zero | + +- **Scale-to-zero between activity** keeps the (possibly long) review window cheap. +- **Reaper CronJob** (adapted from openclaw `reaper-cronjob.yaml`) sweeps abandoned/timed-out runs + by TTL annotation — the safety net for crashes and forgotten PRs. +- **Ephemeral EKS test targets** (`deep-test`) are **gated behind a label** because they cost real + money and take ~15–20 min to provision; the default path is dry-run/namespace testing. + +--- + +## 10. Security model + +Untrusted, LLM-generated code + issue text from anyone = treat the whole sandbox as hostile. + +- **Hardware isolation:** every coder runs in a **Kata micro-VM** (own kernel), not a shared-kernel + container. +- **No cloud credentials in the sandbox:** the coder holds only a **LiteLLM API key** and a + **short-TTL GitHub token** via **projected tmpfs (mode 0400)** — read then unset, never in env. + All AWS IAM lives with the **orchestrator, outside the VM**. +- **Egress lockdown:** a **NetworkPolicy** restricts sandbox egress to **LiteLLM:4000 + DNS + + GitHub only**. `automountServiceAccountToken: false`, runAsNonRoot, seccomp `RuntimeDefault`, + drop `ALL` caps. +- **Prod is never a test bed:** the factory runs on **spoke-dev**; spoke-prod holds the sandbox + capability but its pool is **dormant**. Unreviewed agent code never touches prod. +- **⚠️ Lethal trifecta (the #1 risk — see [§11](#11-industry-alignment--anti-patterns-what-the-world-agrees-on)):** untrusted + issue text + credentials + egress is the exact recipe for prompt-injection exfiltration + (demonstrated against GitHub-issue-driven agents in the wild). The mitigations above exist + specifically to break that trifecta: keep credentials out of the issue-ingesting context, deny + egress, and treat all issue/repo content as hostile input. + +--- + +## 11. Industry alignment & anti-patterns (what the world agrees on) + +We validated this design against how GitHub Copilot coding agent, OpenAI Codex cloud, Devin, Google +Jules, Cursor background agents, Factory.ai, and StrongDM's "Software Factory" actually work. + +### ✅ Where we match consensus + +| Design choice | Industry practice | +|---|---| +| Issue → Action → ephemeral sandbox → build/test → PR | The recurring ~7-stage pipeline across Copilot/Codex/Devin/Jules/Factory | +| **Kata micro-VM isolation** | *Above-consensus.* microVM-class isolation (Firecracker, Kata, Bedrock AgentCore's per-session microVM) is the defensible choice for untrusted LLM code; shared-kernel containers are considered insufficient | +| Build/test **until green before** the PR | Explicit in codex-1's RL training, Devin, Copilot | +| **Holdout scenarios the coder never sees** | *Above-consensus.* Directly matches StrongDM's Software Factory (they learned it the hard way after `return true` gamed their tests) | +| **One sticky status surface**, not comment spam | Copilot draft-PR + session logs; Devin single review status; Factory "Mission Control" | +| Human **approves the PR**, agent iterates on comments | The dominant gating norm — agents do **not** self-merge by default | +| Single coder + **independent read-only reviewers** | Anthropic + Cognition agree parallel multi-agent *authoring* is a poor fit for coding; the good pattern is one coder + a fresh model reviewing the finished diff (CodeRabbit's Security Agent) | + +### ⚠️ Anti-patterns we explicitly design against + +1. **Lethal trifecta / prompt injection (highest risk).** Untrusted issue text + cloud creds + egress + → data exfiltration. Invariant Labs demonstrated a malicious GitHub *issue* injecting an agent + into leaking private-repo data via an auto-PR. **Our defense:** credentials never in the + issue-ingesting sandbox context; egress denied except LiteLLM/GitHub; issue/repo content treated + as hostile; frontier agents scoped read-only. *(Willison "lethal trifecta"; Invariant Labs.)* +2. **Reward hacking / test-gaming.** Frontier models stub evaluators (`evaluate = _always_ok`), make + `verify()` return true, read reference answers, or delete the test oracle (METR, OpenAI, + Anthropic). **Our defense:** the holdout the coder cannot see or edit — if the coder can reach it, + the holdout is theater. +3. **LLM-judge as a sole hard gate.** Judges have proven position/verbosity/**self-preference** bias + (causal — a model favors its own family's output). **Our defense:** different judge model + + paired executable tests + 2-of-3 + a probabilistic satisfaction score, never a lone boolean. +4. **Multi-agent over-orchestration.** **Our defense:** single-threaded coder; Security/DevOps are + stateless read-only reviewers on the finished diff, never co-authors. +5. **Non-converging comment loops.** **Our defense:** batch comments into one run, cap iterations, + hard time/turn limits. +6. **Warm-pool idle burn.** **Our defense:** snapshot/fork + idle reaping + scale-to-zero, not parked + VMs. +7. **Rubber-stamp reviews.** AI-co-authored PRs carry measurably more issues; "review results not + code" can decay into a green rubber stamp. **Our defense:** the human reviews *structured + evidence* (tests + holdout % + security findings + diff-path confinement), and high-risk changes + (infra, `deep-test`) get a firmer gate. + +--- + +## 12. Phased delivery + +Each phase is independently valuable — if you stop after any one, you're better off than before. + +| Phase | Delivers | Independently useful? | +|------:|----------|-----------------------| +| **P1** | Trigger → claim warm sandbox → Claude Code coder → build/test → PR + sticky status → manual teardown | ✅ A working autonomous-PR loop | +| **P2** | Strict **holdout gate** (isolated, different-model judge, executable-test pairing) + bounded retry | ✅ Quality gate that resists gaming | +| **P3** | **AWS Security + DevOps** frontier agents (advisory) folded into the PR report | ✅ Independent review evidence | +| **P4** | Ephemeral test targets (namespace default; `deep-test` `PlatformCluster`) + **auto-teardown** on merge + reaper | ✅ Full lights-off lifecycle | +| **P5** | **Kiro** coder profile; per-severity **blocking** gate option; spoke-prod pool activation story | ✅ Vendor-plurality + higher autonomy | + +--- + +## 13. Open questions / future work + +*To resolve during implementation — flagged honestly rather than assumed:* + +- **Headless auth** for Claude Code & Kiro through a LiteLLM base-URL override inside a Kata VM + (the biggest unknown — prototype first in P1). +- **Import the `agent-sandbox` operator** from `eks-platform-openclaw` into the OAP addon catalog + (Flow A's first task). +- **Enable the sandbox/kagent addons on the dev overlay** (they're hub-only today). +- **Exact AWS Security / DevOps Agent APIs & auth** — confirm the invocation contract at build time. +- **Orchestrator RBAC scope** — Sandbox/PVC/Service/Job on spoke-dev + `PlatformCluster` claims for + the `deep-test` path. +- **Warm-pool implementation** — verify whether the `agent-sandbox` v0.1.0 operator supports + snapshot/fork warm-binding, or whether the pool-manager must create-on-demand. + +--- + +## 14. References + +**Pattern sources** +- Steve Yegge — *Welcome to Gas City* — https://steve-yegge.medium.com/welcome-to-gas-city-57f564bb3607 +- *The Dark Factory Pattern: Moving From AI-Assisted to Fully Autonomous Coding* — https://hackernoon.com/the-dark-factory-pattern-moving-from-ai-assisted-to-fully-autonomous-coding +- Kiro headless in GitHub Actions — https://builder.aws.com/content/35cLFnKM6DJMgRzdZQ7XPZkJmoz/automate-reviews-in-github-actions-with-kiro-headless-mode + +**Industry pipelines** +- GitHub Copilot coding agent — https://github.blog/news-insights/product-news/github-copilot-meet-the-new-coding-agent/ +- OpenAI Codex — https://openai.com/index/introducing-codex/ +- Devin SDLC integration — https://docs.devin.ai/essential-guidelines/sdlc-integration +- Factory.ai Missions — https://docs.factory.ai/cli/features/missions/overview +- StrongDM Software Factory — https://factory.strongdm.ai/ +- AWS Bedrock AgentCore runtime sessions (per-session microVM) — https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-sessions.md +- AWS DevOps Agent — https://aws.amazon.com/devops-agent/ + +**Failure modes / safety** +- Simon Willison — *The lethal trifecta* — https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/ +- Invariant Labs — GitHub MCP prompt-injection exfiltration — https://invariantlabs.ai/blog/mcp-github-vulnerability +- METR — *Recent frontier models are reward hacking* — https://metr.org/blog/2025-06-05-recent-reward-hacking/ +- OpenAI — *Detecting misbehavior in frontier reasoning models* — https://openai.com/index/chain-of-thought-monitoring/ +- Anthropic — *Reward tampering* — https://www.anthropic.com/research/reward-tampering +- LLM-judge self-preference bias — https://arxiv.org/abs/2404.13076 · MT-Bench — https://arxiv.org/abs/2306.05685 +- Cognition — *Don't build multi-agents* — https://cognition.ai/blog/dont-build-multi-agents +- Anthropic — *Claude Code best practices* — https://www.anthropic.com/engineering/claude-code-best-practices + +**Platform building blocks (this monorepo & siblings)** +- `eks-platform-openclaw` — Kata micro-VM sandbox, `Sandbox` CRD, session-router lifecycle, LiteLLM gateway +- `appmod-blueprints` — `PlatformCluster` Crossplane composition (ephemeral EKS), KRO CI/CD pipeline +- `agent-platform-amazon-eks` — hub/spoke fleet, addon ApplicationSets, kagent, agent-gateway diff --git a/docs/dark-factory/diagrams/flow-a-sandbox-capability.md b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md new file mode 100644 index 0000000..2ee7d7e --- /dev/null +++ b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md @@ -0,0 +1,100 @@ +# Flow A — Agent Sandbox Capability (permanent platform feature) + +The **Agent Sandbox** capability ships as a first-class agent-platform GitOps addon. When +the platform is deployed, it stands up the Kata (Cloud Hypervisor) micro-VM runtime, the +`Sandbox` CRD + operator, and a **warm pool** of pre-provisioned, hardware-isolated sandboxes +kept ready by a pool-manager controller. This is independent of the Dark Factory — it is the +reusable isolation substrate any agent workload can claim. + +--- + +## A.1 — Capability architecture + +```mermaid +%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'14px','primaryColor':'#EAF2FF','primaryBorderColor':'#2563EB','primaryTextColor':'#0B1F3A','lineColor':'#64748B','clusterBkg':'#F8FAFC','clusterBorder':'#CBD5E1'}}}%% +flowchart TB + classDef gitops fill:#EDE9FE,stroke:#7C3AED,stroke-width:1.5px,color:#2E1065,rx:8,ry:8; + classDef control fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#0B1F3A,rx:8,ry:8; + classDef warm fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16,rx:10,ry:10; + classDef node fill:#FEF3C7,stroke:#D97706,stroke-width:1.5px,color:#451A03,rx:8,ry:8; + classDef model fill:#FCE7F3,stroke:#DB2777,stroke-width:1.5px,color:#500724,rx:8,ry:8; + classDef vm fill:#F1F5F9,stroke:#0EA5E9,stroke-width:2px,color:#0C4A6E,rx:6,ry:6; + + subgraph GITOPS["🚀 GitOps enablement · ArgoCD app-of-apps"] + direction LR + FLAG["enable_agent_sandbox: true
overlays/environments/{dev,prod}"]:::gitops + APPSET["ApplicationSet
cluster-generator
sync-wave −1 → 1"]:::gitops + FLAG --> APPSET + end + + subgraph CLUSTER["☸️ spoke-dev & spoke-prod (capability on both)"] + direction TB + + subgraph OPER["🧩 Sandbox control plane"] + direction LR + CRD["Sandbox CRD
agents.x-k8s.io/v1alpha1
+ SandboxTemplate
+ SandboxClaim"]:::control + OPCTL["agent-sandbox
operator"]:::control + POOL["pool-manager
controller
keeps N idle · refills · shrinks"]:::control + CRD --- OPCTL --- POOL + end + + subgraph WARM["🔥 Warm pool · target buffer = 2–3 idle"] + direction LR + S1(["🟢 idle
sandbox-1"]):::warm + S2(["🟢 idle
sandbox-2"]):::warm + S3(["🟢 idle
sandbox-3"]):::warm + end + + subgraph KATA["🛡️ Kata micro-VM runtime (hardware isolation)"] + direction LR + RC["RuntimeClasses
kata-clh · kata-qemu · kata-fc"]:::vm + NP["Karpenter pools
kata-nested (c8i/m8i)
kata-metal (fallback)"]:::node + KD["kata-deploy
DaemonSet"]:::vm + RC --- KD --- NP + end + + MODEL["🧠 LiteLLM gateway
litellm.litellm.svc:4000
→ Bedrock via Pod Identity"]:::model + end + + APPSET ==>|renders| OPER + APPSET ==>|renders| KATA + POOL ==>|creates / scales
Sandbox CRs| WARM + WARM -.->|scheduled onto| KATA + WARM -.->|model calls
egress-locked| MODEL + + linkStyle default stroke:#64748B,stroke-width:1.5px; +``` + +--- + +## A.2 — Warm-pool cycling (claim ↔ refill ↔ shrink) + +The pool-manager keeps a steady buffer of idle sandboxes so a consumer (e.g. the Dark +Factory) binds to a **ready** VM instantly instead of paying cold-start. Idle sandboxes use +the `Sandbox` `replicas: 0/1` **scale subresource**, so "idle" is cheap. + +```mermaid +%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'14px','primaryColor':'#DCFCE7','primaryBorderColor':'#16A34A','primaryTextColor':'#052E16','lineColor':'#16A34A'}}}%% +stateDiagram-v2 + direction LR + [*] --> Provisioning : pool below target + Provisioning --> Idle : VM booted, replicas=1, unclaimed + Idle --> Claimed : SandboxClaim binds (consumer arrives) + Claimed --> Idle : claim released, VM recyclable + Idle --> Paused : idle TTL — scale replicas=0 (PVC kept) + Paused --> Idle : demand returns — scale replicas=1 + Claimed --> Retired : consumer done → delete Sandbox+PVC + Idle --> Retired : pool above target → shrink + Retired --> [*] + + note right of Claimed + On CLAIM the pool-manager + provisions a REFILL so the + buffer stays at target (2–3). + end note + note right of Retired + On RELEASE, if the pool is + above target, the extra idle + sandbox is removed. + end note +``` diff --git a/docs/dark-factory/diagrams/flow-b-dark-factory.md b/docs/dark-factory/diagrams/flow-b-dark-factory.md new file mode 100644 index 0000000..333f79d --- /dev/null +++ b/docs/dark-factory/diagrams/flow-b-dark-factory.md @@ -0,0 +1,160 @@ +# Flow B — Dark Factory (issue → PR → merge → teardown) + +A GitHub issue is a **spec**. The factory claims a warm sandbox on spoke-dev, a pluggable +coding assistant implements + tests the change, the orchestrator runs independent +verification (holdout gate + AWS frontier agents), a PR is opened with a **live-updating** +status, a human approves on results, and everything is torn down on merge. Autonomy **Level 3**: +the human's only job is to approve the merge. + +--- + +## B.1 — End-to-end pipeline (lights-off assembly line) + +```mermaid +%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'13.5px','primaryColor':'#EAF2FF','primaryBorderColor':'#2563EB','primaryTextColor':'#0B1F3A','lineColor':'#475569','clusterBkg':'#F8FAFC','clusterBorder':'#CBD5E1'}}}%% +flowchart LR + classDef trigger fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006,rx:8,ry:8; + classDef orch fill:#DBEAFE,stroke:#2563EB,stroke-width:2px,color:#0B1F3A,rx:8,ry:8; + classDef sandbox fill:#E0F2FE,stroke:#0EA5E9,stroke-width:2px,color:#0C4A6E,rx:8,ry:8; + classDef verify fill:#F3E8FF,stroke:#9333EA,stroke-width:1.5px,color:#3B0764,rx:8,ry:8; + classDef aws fill:#FFEDD5,stroke:#EA580C,stroke-width:1.5px,color:#431407,rx:8,ry:8; + classDef human fill:#DCFCE7,stroke:#16A34A,stroke-width:2px,color:#052E16,rx:10,ry:10; + classDef teardown fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A,rx:8,ry:8; + + START([🧾 Issue opened
label: dark-factory]):::trigger + + subgraph T["① Trigger"] + GHA["⚙️ GitHub Action
gate on label
mint short-TTL token"]:::trigger + end + + subgraph O["② Orchestrate · spoke-dev (trusted, holds AWS IAM)"] + ORCH["🎛️ Orchestrator
key = issue-id
claim + drive + report"]:::orch + CLAIM["🔒 SandboxClaim
→ bind warm sandbox
pool refills"]:::orch + ORCH --> CLAIM + end + + subgraph SBX["③ Code + self-test · Kata micro-VM (isolated, no cloud creds)"] + CODER["🤖 Pluggable coder
Claude Code ▸ | Kiro ▸
reads SPEC.md"]:::sandbox + IMPL["✍️ implement
branch df/issue-N"]:::sandbox + BUILD["🔧 build + unit tests
until green"]:::sandbox + CODER --> IMPL --> BUILD + end + + subgraph V["④ Independent verification (orchestrator-driven — NOT the coder)"] + HOLD["🎯 Holdout gate
hidden BDD scenarios
different-model judge
+ executable tests · ≥90%"]:::verify + SEC["🛡️ AWS Security Agent"]:::aws + DEV["🚀 AWS DevOps Agent"]:::aws + HOLD -.-> SEC -.-> DEV + end + + subgraph P["⑤ Pull Request · live status"] + PR["🔀 PR opened
sticky comment ⏳→✅
results + findings + logs"]:::orch + end + + subgraph H["⑥ Human — Level 3"] + REVIEW{"Approve?
reviews RESULTS"}:::human + COMMENT["💬 PR comment
resume sandbox → iterate
(bounded N rounds)"]:::human + end + + subgraph TD["⑦ Merge + teardown"] + MERGE["✅ merge PR"]:::teardown + DESTROY["🧹 delete sandbox + PVC
+ ephemeral test infra
+ eval job"]:::teardown + MERGE --> DESTROY --> DONE([🏁 done]):::teardown + end + + START --> GHA --> ORCH + CLAIM ==> CODER + BUILD ==> HOLD + DEV ==> PR + PR ==> REVIEW + REVIEW -->|changes requested| COMMENT + COMMENT -.->|new instruction| CODER + REVIEW -->|approve| MERGE + + linkStyle default stroke:#475569,stroke-width:1.5px; +``` + +--- + +## B.2 — Detailed sequence (who does what, and the trust boundary) + +```mermaid +%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'13px','actorBkg':'#DBEAFE','actorBorder':'#2563EB','actorTextColor':'#0B1F3A','signalColor':'#334155','signalTextColor':'#0B1F3A','noteBkg':'#FEF9C3','noteBorderColor':'#CA8A04','loopTextColor':'#3B0764'}}}%% +sequenceDiagram + autonumber + actor Dev as 🧑‍💻 Human + participant GH as 🐙 GitHub + participant GHA as ⚙️ Action + participant ORCH as 🎛️ Orchestrator
(trusted · AWS IAM) + participant POOL as 🔥 Warm pool + box LightBlue 🛡️ Kata micro-VM · isolated · no cloud creds + participant SBX as 🤖 Coder sandbox + end + participant EVAL as 🎯 Holdout evaluator + participant AWS as ☁️ AWS Security /
DevOps Agents + + Dev->>GH: open issue (label: dark-factory) + GH->>GHA: issues.labeled event + GHA->>ORCH: POST /run (issue #, repo, short-TTL token) + ORCH->>POOL: SandboxClaim (key = issue-id) + POOL-->>ORCH: bound warm sandbox (instant) + Note over POOL: pool-manager provisions a REFILL + + ORCH->>SBX: write /workspace/SPEC.md + checkout df/issue-N + activate SBX + SBX->>SBX: implement · build · unit tests (until green) + SBX-->>ORCH: artifacts/result.json (diff + logs) + deactivate SBX + + Note over ORCH,EVAL: Verification is INDEPENDENT of the coder
(coder never sees / edits the holdout) + ORCH->>EVAL: run hidden BDD scenarios vs diff + EVAL-->>ORCH: satisfaction % (different-model judge + real tests) + ORCH->>AWS: invoke Security + DevOps agents on diff/artifacts + AWS-->>ORCH: findings (advisory) + + ORCH->>GH: open PR + sticky status comment (⏳→✅) + GH-->>Dev: review request (results, not code) + + loop bounded iterations (max N) + Dev->>GH: PR comment (change requested) + GH->>ORCH: comment webhook + ORCH->>POOL: resume sandbox (scale 0→1, same PVC) + ORCH->>SBX: apply comment as new instruction + activate SBX + SBX-->>ORCH: push update + deactivate SBX + ORCH->>GH: update sticky status + end + + Dev->>GH: ✅ approve + merge + GH->>ORCH: pull_request closed+merged + ORCH->>POOL: release + delete sandbox + PVC + ORCH->>ORCH: delete ephemeral test infra + eval job + Note over ORCH: Reaper CronJob reaps any abandoned/timed-out run +``` + +--- + +## B.3 — Live PR status (the sticky comment the human watches) + +The orchestrator maintains **one** PR comment, edited in place as each stage completes — +no comment spam, one canonical surface (the pattern Copilot/Devin/Factory converge on). + +```mermaid +%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-monospace, monospace','fontSize':'13px'}}}%% +flowchart TB + classDef done fill:#DCFCE7,stroke:#16A34A,color:#052E16,rx:6,ry:6; + classDef now fill:#FEF9C3,stroke:#CA8A04,color:#422006,rx:6,ry:6; + classDef wait fill:#F1F5F9,stroke:#94A3B8,color:#475569,rx:6,ry:6; + + H["🏭 Dark Factory — issue #42"]:::done + A["✅ Claimed sandbox (spoke-dev) · 12:01"]:::done + B["✅ Branch df/issue-42 · 12:01"]:::done + C["✅ Implement · 12:04"]:::done + D["✅ Build + unit tests · 12:07 · 📄 log"]:::done + E["⏳ Security Agent…"]:::now + F["⬜ DevOps Agent"]:::wait + G["⬜ Holdout gate (0/12)"]:::wait + I["⬜ PR ready for review"]:::wait + H-->A-->B-->C-->D-->E-->F-->G-->I +``` From a6c4f62b21f790237bfc56febd643c25c2181f5f Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 10:08:02 -0400 Subject: [PATCH 02/67] docs(dark-factory): restyle diagrams to AWS dark-canvas keynote theme Unify all 5 mermaid diagrams on one palette + font (was clumsy: mixed light/dark backgrounds, too many colors, inconsistent fonts): - Squid Ink navy canvas (#1B2733) with layered navy bands/nodes, light text - single AWS Orange (#FF9900) accent reserved for the active/happy path - Amazon Ember font, uniform rounded nodes + stroke weights - fixed linkStyle edge indices (chained edges were mis-counted) Flow A (capability + warm-pool state machine) and Flow B (pipeline + sequence + live-status) now read as one consistent visual system. --- .../diagrams/flow-a-sandbox-capability.md | 140 ++++++------ .../diagrams/flow-b-dark-factory.md | 203 ++++++++++-------- 2 files changed, 189 insertions(+), 154 deletions(-) diff --git a/docs/dark-factory/diagrams/flow-a-sandbox-capability.md b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md index 2ee7d7e..a3d4db7 100644 --- a/docs/dark-factory/diagrams/flow-a-sandbox-capability.md +++ b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md @@ -1,100 +1,112 @@ # Flow A — Agent Sandbox Capability (permanent platform feature) -The **Agent Sandbox** capability ships as a first-class agent-platform GitOps addon. When -the platform is deployed, it stands up the Kata (Cloud Hypervisor) micro-VM runtime, the -`Sandbox` CRD + operator, and a **warm pool** of pre-provisioned, hardware-isolated sandboxes -kept ready by a pool-manager controller. This is independent of the Dark Factory — it is the -reusable isolation substrate any agent workload can claim. +The **Agent Sandbox** capability ships as a first-class agent-platform GitOps addon. When the +platform is deployed, it stands up the Kata (Cloud Hypervisor) micro-VM runtime, the `Sandbox` +CRD + operator, and a **warm pool** of pre-provisioned, hardware-isolated sandboxes kept ready by +a pool-manager controller. This is independent of the Dark Factory — it is the reusable isolation +substrate any agent workload can claim. --- ## A.1 — Capability architecture ```mermaid -%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'14px','primaryColor':'#EAF2FF','primaryBorderColor':'#2563EB','primaryTextColor':'#0B1F3A','lineColor':'#64748B','clusterBkg':'#F8FAFC','clusterBorder':'#CBD5E1'}}}%% +%%{init: {'theme':'base','themeVariables':{ + 'fontFamily':'Amazon Ember, Helvetica, Arial, sans-serif','fontSize':'14px', + 'primaryColor':'#2E3E50','primaryBorderColor':'#5F7185','primaryTextColor':'#FFFFFF', + 'lineColor':'#8B99A7','clusterBkg':'#26374A','clusterBorder':'#5F7185', + 'tertiaryColor':'#1B2733'}}}%% flowchart TB - classDef gitops fill:#EDE9FE,stroke:#7C3AED,stroke-width:1.5px,color:#2E1065,rx:8,ry:8; - classDef control fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#0B1F3A,rx:8,ry:8; - classDef warm fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16,rx:10,ry:10; - classDef node fill:#FEF3C7,stroke:#D97706,stroke-width:1.5px,color:#451A03,rx:8,ry:8; - classDef model fill:#FCE7F3,stroke:#DB2777,stroke-width:1.5px,color:#500724,rx:8,ry:8; - classDef vm fill:#F1F5F9,stroke:#0EA5E9,stroke-width:2px,color:#0C4A6E,rx:6,ry:6; - - subgraph GITOPS["🚀 GitOps enablement · ArgoCD app-of-apps"] - direction LR - FLAG["enable_agent_sandbox: true
overlays/environments/{dev,prod}"]:::gitops - APPSET["ApplicationSet
cluster-generator
sync-wave −1 → 1"]:::gitops - FLAG --> APPSET - end - - subgraph CLUSTER["☸️ spoke-dev & spoke-prod (capability on both)"] - direction TB + classDef canvas fill:#1B2733,stroke:#1B2733,color:#FFFFFF; + classDef band fill:#26374A,stroke:#5F7185,color:#E8EDF2,stroke-width:1px; + classDef node fill:#2E4257,stroke:#7C8FA3,color:#FFFFFF,stroke-width:1.2px; + classDef accent fill:#FF9900,stroke:#EC7211,color:#161E2D,stroke-width:1.5px; + classDef warm fill:#22384A,stroke:#FF9900,color:#FFFFFF,stroke-width:1.4px; + classDef muted fill:#243244,stroke:#415266,color:#AEB8C4,stroke-width:1px; - subgraph OPER["🧩 Sandbox control plane"] - direction LR - CRD["Sandbox CRD
agents.x-k8s.io/v1alpha1
+ SandboxTemplate
+ SandboxClaim"]:::control - OPCTL["agent-sandbox
operator"]:::control - POOL["pool-manager
controller
keeps N idle · refills · shrinks"]:::control - CRD --- OPCTL --- POOL - end + subgraph CANVAS[" "] + direction TB - subgraph WARM["🔥 Warm pool · target buffer = 2–3 idle"] + subgraph GITOPS["🚀 GitOps enablement · ArgoCD app-of-apps"] direction LR - S1(["🟢 idle
sandbox-1"]):::warm - S2(["🟢 idle
sandbox-2"]):::warm - S3(["🟢 idle
sandbox-3"]):::warm + FLAG["enable_agent_sandbox: true
overlays/environments/dev,prod"]:::accent + APPSET["ApplicationSet
cluster-generator
sync-wave −1 → 1"]:::node + FLAG --> APPSET end - subgraph KATA["🛡️ Kata micro-VM runtime (hardware isolation)"] - direction LR - RC["RuntimeClasses
kata-clh · kata-qemu · kata-fc"]:::vm - NP["Karpenter pools
kata-nested (c8i/m8i)
kata-metal (fallback)"]:::node - KD["kata-deploy
DaemonSet"]:::vm - RC --- KD --- NP + subgraph CLUSTER["☸️ spoke-dev & spoke-prod · capability on both"] + direction TB + + subgraph OPER["🧩 Sandbox control plane"] + direction LR + CRD["Sandbox CRD
agents.x-k8s.io/v1alpha1
+ SandboxTemplate + SandboxClaim"]:::node + OPCTL["agent-sandbox
operator"]:::node + POOL["pool-manager
keeps N idle · refills · shrinks"]:::accent + CRD --- OPCTL --- POOL + end + + subgraph WARM["🔥 Warm pool · target buffer = 2–3 idle"] + direction LR + S1(["idle · sandbox-1"]):::warm + S2(["idle · sandbox-2"]):::warm + S3(["idle · sandbox-3"]):::warm + end + + subgraph KATA["🛡️ Kata micro-VM runtime · hardware isolation"] + direction LR + RC["RuntimeClasses
kata-clh · kata-qemu · kata-fc"]:::node + KD["kata-deploy
DaemonSet"]:::node + NP["Karpenter pools
kata-nested c8i/m8i · kata-metal"]:::node + RC --- KD --- NP + end + + MODEL["🧠 LiteLLM gateway
litellm.litellm.svc:4000 → Bedrock"]:::node end - - MODEL["🧠 LiteLLM gateway
litellm.litellm.svc:4000
→ Bedrock via Pod Identity"]:::model end - APPSET ==>|renders| OPER - APPSET ==>|renders| KATA - POOL ==>|creates / scales
Sandbox CRs| WARM - WARM -.->|scheduled onto| KATA - WARM -.->|model calls
egress-locked| MODEL + APPSET ==> OPER + APPSET ==> KATA + POOL ==> WARM + WARM -.-> KATA + WARM -.-> MODEL - linkStyle default stroke:#64748B,stroke-width:1.5px; + class CANVAS canvas + class GITOPS,CLUSTER,OPER,WARM,KATA band + linkStyle default stroke:#8B99A7,stroke-width:1.4px; + linkStyle 7 stroke:#FF9900,stroke-width:2px; ``` --- ## A.2 — Warm-pool cycling (claim ↔ refill ↔ shrink) -The pool-manager keeps a steady buffer of idle sandboxes so a consumer (e.g. the Dark -Factory) binds to a **ready** VM instantly instead of paying cold-start. Idle sandboxes use -the `Sandbox` `replicas: 0/1` **scale subresource**, so "idle" is cheap. +The pool-manager keeps a steady buffer of idle sandboxes so a consumer (e.g. the Dark Factory) +binds to a **ready** VM instantly instead of paying cold-start. Idle sandboxes use the `Sandbox` +`replicas: 0/1` **scale subresource**, so "idle" is cheap. ```mermaid -%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'14px','primaryColor':'#DCFCE7','primaryBorderColor':'#16A34A','primaryTextColor':'#052E16','lineColor':'#16A34A'}}}%% +%%{init: {'theme':'base','themeVariables':{ + 'fontFamily':'Amazon Ember, Helvetica, Arial, sans-serif','fontSize':'14px', + 'primaryColor':'#2E4257','primaryBorderColor':'#7C8FA3','primaryTextColor':'#FFFFFF', + 'lineColor':'#8B99A7','labelColor':'#E8EDF2'}}}%% stateDiagram-v2 direction LR [*] --> Provisioning : pool below target - Provisioning --> Idle : VM booted, replicas=1, unclaimed - Idle --> Claimed : SandboxClaim binds (consumer arrives) - Claimed --> Idle : claim released, VM recyclable - Idle --> Paused : idle TTL — scale replicas=0 (PVC kept) - Paused --> Idle : demand returns — scale replicas=1 - Claimed --> Retired : consumer done → delete Sandbox+PVC - Idle --> Retired : pool above target → shrink + Provisioning --> Idle : VM booted · replicas=1 · unclaimed + Idle --> Claimed : SandboxClaim binds + Claimed --> Idle : claim released · recyclable + Idle --> Paused : idle TTL · scale replicas=0 · PVC kept + Paused --> Idle : demand returns · scale replicas=1 + Claimed --> Retired : consumer done · delete Sandbox+PVC + Idle --> Retired : pool above target · shrink Retired --> [*] note right of Claimed - On CLAIM the pool-manager - provisions a REFILL so the - buffer stays at target (2–3). + On CLAIM the pool-manager provisions + a REFILL so the buffer stays at target. end note note right of Retired - On RELEASE, if the pool is - above target, the extra idle - sandbox is removed. + On RELEASE, if the pool is above target, + the extra idle sandbox is removed. end note ``` diff --git a/docs/dark-factory/diagrams/flow-b-dark-factory.md b/docs/dark-factory/diagrams/flow-b-dark-factory.md index 333f79d..f314437 100644 --- a/docs/dark-factory/diagrams/flow-b-dark-factory.md +++ b/docs/dark-factory/diagrams/flow-b-dark-factory.md @@ -1,77 +1,86 @@ # Flow B — Dark Factory (issue → PR → merge → teardown) -A GitHub issue is a **spec**. The factory claims a warm sandbox on spoke-dev, a pluggable -coding assistant implements + tests the change, the orchestrator runs independent -verification (holdout gate + AWS frontier agents), a PR is opened with a **live-updating** -status, a human approves on results, and everything is torn down on merge. Autonomy **Level 3**: -the human's only job is to approve the merge. +A GitHub issue is a **spec**. The factory claims a warm sandbox on spoke-dev, a pluggable coding +assistant implements + tests the change, the orchestrator runs independent verification (holdout +gate + AWS frontier agents), a PR is opened with a **live-updating** status, a human approves on +results, and everything is torn down on merge. Autonomy **Level 3**: the human's only job is to +approve the merge. --- ## B.1 — End-to-end pipeline (lights-off assembly line) ```mermaid -%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'13.5px','primaryColor':'#EAF2FF','primaryBorderColor':'#2563EB','primaryTextColor':'#0B1F3A','lineColor':'#475569','clusterBkg':'#F8FAFC','clusterBorder':'#CBD5E1'}}}%% +%%{init: {'theme':'base','themeVariables':{ + 'fontFamily':'Amazon Ember, Helvetica, Arial, sans-serif','fontSize':'13.5px', + 'primaryColor':'#2E4257','primaryBorderColor':'#7C8FA3','primaryTextColor':'#FFFFFF', + 'lineColor':'#8B99A7','clusterBkg':'#26374A','clusterBorder':'#5F7185'}}}%% flowchart LR - classDef trigger fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006,rx:8,ry:8; - classDef orch fill:#DBEAFE,stroke:#2563EB,stroke-width:2px,color:#0B1F3A,rx:8,ry:8; - classDef sandbox fill:#E0F2FE,stroke:#0EA5E9,stroke-width:2px,color:#0C4A6E,rx:8,ry:8; - classDef verify fill:#F3E8FF,stroke:#9333EA,stroke-width:1.5px,color:#3B0764,rx:8,ry:8; - classDef aws fill:#FFEDD5,stroke:#EA580C,stroke-width:1.5px,color:#431407,rx:8,ry:8; - classDef human fill:#DCFCE7,stroke:#16A34A,stroke-width:2px,color:#052E16,rx:10,ry:10; - classDef teardown fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A,rx:8,ry:8; - - START([🧾 Issue opened
label: dark-factory]):::trigger - - subgraph T["① Trigger"] - GHA["⚙️ GitHub Action
gate on label
mint short-TTL token"]:::trigger + classDef canvas fill:#1B2733,stroke:#1B2733,color:#FFFFFF; + classDef band fill:#26374A,stroke:#5F7185,color:#E8EDF2,stroke-width:1px; + classDef node fill:#2E4257,stroke:#7C8FA3,color:#FFFFFF,stroke-width:1.2px; + classDef accent fill:#FF9900,stroke:#EC7211,color:#161E2D,stroke-width:1.5px; + classDef human fill:#22384A,stroke:#FF9900,color:#FFFFFF,stroke-width:1.4px; + classDef gate fill:#2E4257,stroke:#FF9900,color:#FFFFFF,stroke-width:1.4px; + + subgraph CANVAS[" "] + direction LR + + START(["🧾 Issue opened
label: dark-factory"]):::accent + + subgraph T["① Trigger"] + GHA["⚙️ GitHub Action
gate on label
mint short-TTL token"]:::node + end + + subgraph O["② Orchestrate · spoke-dev · trusted (holds AWS IAM)"] + ORCH["🎛️ Orchestrator
key = issue-id
claim · drive · report"]:::node + CLAIM["🔒 SandboxClaim
bind warm sandbox · pool refills"]:::node + ORCH --> CLAIM + end + + subgraph SBX["③ Code + self-test · Kata micro-VM · isolated (no cloud creds)"] + CODER["🤖 Pluggable coder
Claude Code | Kiro
reads SPEC.md"]:::node + IMPL["✍️ implement
branch df/issue-N"]:::node + BUILD["🔧 build + unit tests
until green"]:::node + CODER --> IMPL --> BUILD + end + + subgraph V["④ Independent verification · orchestrator-driven (NOT the coder)"] + HOLD["🎯 Holdout gate
hidden scenarios · different-model judge
+ executable tests · ≥90%"]:::gate + SEC["🛡️ AWS Security Agent"]:::node + DEV["🚀 AWS DevOps Agent"]:::node + HOLD -.-> SEC -.-> DEV + end + + subgraph P["⑤ Pull Request · live status"] + PR["🔀 PR opened
sticky comment ⏳→✅
results + findings + logs"]:::node + end + + subgraph H["⑥ Human · Level 3"] + REVIEW{"Approve?
reviews RESULTS"}:::human + COMMENT["💬 PR comment
resume sandbox · iterate
bounded N rounds"]:::human + end + + subgraph TD["⑦ Merge + teardown"] + MERGE["✅ merge PR"]:::accent + DESTROY["🧹 delete sandbox + PVC
+ ephemeral test infra + eval job"]:::node + MERGE --> DESTROY --> DONE(["🏁 done"]):::node + end + + START ==> GHA ==> ORCH + CLAIM ==> CODER + BUILD ==> HOLD + DEV ==> PR + PR ==> REVIEW + REVIEW -->|changes requested| COMMENT + COMMENT -.->|new instruction| CODER + REVIEW ==>|approve| MERGE end - subgraph O["② Orchestrate · spoke-dev (trusted, holds AWS IAM)"] - ORCH["🎛️ Orchestrator
key = issue-id
claim + drive + report"]:::orch - CLAIM["🔒 SandboxClaim
→ bind warm sandbox
pool refills"]:::orch - ORCH --> CLAIM - end - - subgraph SBX["③ Code + self-test · Kata micro-VM (isolated, no cloud creds)"] - CODER["🤖 Pluggable coder
Claude Code ▸ | Kiro ▸
reads SPEC.md"]:::sandbox - IMPL["✍️ implement
branch df/issue-N"]:::sandbox - BUILD["🔧 build + unit tests
until green"]:::sandbox - CODER --> IMPL --> BUILD - end - - subgraph V["④ Independent verification (orchestrator-driven — NOT the coder)"] - HOLD["🎯 Holdout gate
hidden BDD scenarios
different-model judge
+ executable tests · ≥90%"]:::verify - SEC["🛡️ AWS Security Agent"]:::aws - DEV["🚀 AWS DevOps Agent"]:::aws - HOLD -.-> SEC -.-> DEV - end - - subgraph P["⑤ Pull Request · live status"] - PR["🔀 PR opened
sticky comment ⏳→✅
results + findings + logs"]:::orch - end - - subgraph H["⑥ Human — Level 3"] - REVIEW{"Approve?
reviews RESULTS"}:::human - COMMENT["💬 PR comment
resume sandbox → iterate
(bounded N rounds)"]:::human - end - - subgraph TD["⑦ Merge + teardown"] - MERGE["✅ merge PR"]:::teardown - DESTROY["🧹 delete sandbox + PVC
+ ephemeral test infra
+ eval job"]:::teardown - MERGE --> DESTROY --> DONE([🏁 done]):::teardown - end - - START --> GHA --> ORCH - CLAIM ==> CODER - BUILD ==> HOLD - DEV ==> PR - PR ==> REVIEW - REVIEW -->|changes requested| COMMENT - COMMENT -.->|new instruction| CODER - REVIEW -->|approve| MERGE - - linkStyle default stroke:#475569,stroke-width:1.5px; + class CANVAS canvas + class T,O,SBX,V,P,H,TD band + linkStyle default stroke:#8B99A7,stroke-width:1.4px; + linkStyle 7,8,9,10,11,12,15 stroke:#FF9900,stroke-width:2px; ``` --- @@ -79,19 +88,25 @@ flowchart LR ## B.2 — Detailed sequence (who does what, and the trust boundary) ```mermaid -%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, system-ui','fontSize':'13px','actorBkg':'#DBEAFE','actorBorder':'#2563EB','actorTextColor':'#0B1F3A','signalColor':'#334155','signalTextColor':'#0B1F3A','noteBkg':'#FEF9C3','noteBorderColor':'#CA8A04','loopTextColor':'#3B0764'}}}%% +%%{init: {'theme':'base','themeVariables':{ + 'fontFamily':'Amazon Ember, Helvetica, Arial, sans-serif','fontSize':'13px', + 'primaryColor':'#2E4257','primaryBorderColor':'#7C8FA3','primaryTextColor':'#FFFFFF', + 'actorBkg':'#2E4257','actorBorder':'#FF9900','actorTextColor':'#FFFFFF', + 'signalColor':'#8B99A7','signalTextColor':'#E8EDF2','lineColor':'#8B99A7', + 'noteBkg':'#FF9900','noteTextColor':'#161E2D','noteBorderColor':'#EC7211', + 'loopTextColor':'#E8EDF2','sequenceNumberColor':'#161E2D'}}}%% sequenceDiagram autonumber actor Dev as 🧑‍💻 Human participant GH as 🐙 GitHub participant GHA as ⚙️ Action - participant ORCH as 🎛️ Orchestrator
(trusted · AWS IAM) + participant ORCH as 🎛️ Orchestrator (AWS IAM) participant POOL as 🔥 Warm pool - box LightBlue 🛡️ Kata micro-VM · isolated · no cloud creds + box rgb(34,56,74) 🛡️ Kata micro-VM · isolated · no cloud creds participant SBX as 🤖 Coder sandbox end participant EVAL as 🎯 Holdout evaluator - participant AWS as ☁️ AWS Security /
DevOps Agents + participant AWS as ☁️ AWS Security / DevOps Agents Dev->>GH: open issue (label: dark-factory) GH->>GHA: issues.labeled event @@ -100,16 +115,16 @@ sequenceDiagram POOL-->>ORCH: bound warm sandbox (instant) Note over POOL: pool-manager provisions a REFILL - ORCH->>SBX: write /workspace/SPEC.md + checkout df/issue-N + ORCH->>SBX: write SPEC.md + checkout df/issue-N activate SBX SBX->>SBX: implement · build · unit tests (until green) - SBX-->>ORCH: artifacts/result.json (diff + logs) + SBX-->>ORCH: result.json (diff + logs) deactivate SBX - Note over ORCH,EVAL: Verification is INDEPENDENT of the coder
(coder never sees / edits the holdout) - ORCH->>EVAL: run hidden BDD scenarios vs diff + Note over ORCH,EVAL: Verification is INDEPENDENT of the coder
(coder never sees or edits the holdout) + ORCH->>EVAL: run hidden scenarios vs diff EVAL-->>ORCH: satisfaction % (different-model judge + real tests) - ORCH->>AWS: invoke Security + DevOps agents on diff/artifacts + ORCH->>AWS: invoke Security + DevOps agents on diff AWS-->>ORCH: findings (advisory) ORCH->>GH: open PR + sticky status comment (⏳→✅) @@ -130,31 +145,39 @@ sequenceDiagram GH->>ORCH: pull_request closed+merged ORCH->>POOL: release + delete sandbox + PVC ORCH->>ORCH: delete ephemeral test infra + eval job - Note over ORCH: Reaper CronJob reaps any abandoned/timed-out run + Note over ORCH: Reaper CronJob reaps any abandoned run ``` --- ## B.3 — Live PR status (the sticky comment the human watches) -The orchestrator maintains **one** PR comment, edited in place as each stage completes — -no comment spam, one canonical surface (the pattern Copilot/Devin/Factory converge on). +The orchestrator maintains **one** PR comment, edited in place as each stage completes — no comment +spam, one canonical surface (the pattern Copilot/Devin/Factory converge on). ```mermaid -%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-monospace, monospace','fontSize':'13px'}}}%% +%%{init: {'theme':'base','themeVariables':{ + 'fontFamily':'Amazon Ember, Helvetica, Arial, sans-serif','fontSize':'13px', + 'primaryColor':'#2E4257','primaryBorderColor':'#7C8FA3','primaryTextColor':'#FFFFFF', + 'lineColor':'#8B99A7','clusterBkg':'#26374A','clusterBorder':'#5F7185'}}}%% flowchart TB - classDef done fill:#DCFCE7,stroke:#16A34A,color:#052E16,rx:6,ry:6; - classDef now fill:#FEF9C3,stroke:#CA8A04,color:#422006,rx:6,ry:6; - classDef wait fill:#F1F5F9,stroke:#94A3B8,color:#475569,rx:6,ry:6; - - H["🏭 Dark Factory — issue #42"]:::done - A["✅ Claimed sandbox (spoke-dev) · 12:01"]:::done - B["✅ Branch df/issue-42 · 12:01"]:::done - C["✅ Implement · 12:04"]:::done - D["✅ Build + unit tests · 12:07 · 📄 log"]:::done - E["⏳ Security Agent…"]:::now - F["⬜ DevOps Agent"]:::wait - G["⬜ Holdout gate (0/12)"]:::wait - I["⬜ PR ready for review"]:::wait - H-->A-->B-->C-->D-->E-->F-->G-->I + classDef canvas fill:#1B2733,stroke:#1B2733,color:#FFFFFF; + classDef done fill:#22384A,stroke:#3FB950,color:#FFFFFF,stroke-width:1.3px; + classDef now fill:#FF9900,stroke:#EC7211,color:#161E2D,stroke-width:1.5px; + classDef wait fill:#243244,stroke:#5F7185,color:#AEB8C4,stroke-width:1px; + + subgraph CANVAS["🏭 Dark Factory — issue #42"] + direction TB + A["✅ Claimed sandbox (spoke-dev) · 12:01"]:::done + B["✅ Branch df/issue-42 · 12:01"]:::done + C["✅ Implement · 12:04"]:::done + D["✅ Build + unit tests · 12:07 · 📄 log"]:::done + E["⏳ Security Agent…"]:::now + F["⬜ DevOps Agent"]:::wait + G["⬜ Holdout gate (0/12)"]:::wait + I["⬜ PR ready for review"]:::wait + A --> B --> C --> D --> E --> F --> G --> I + end + class CANVAS canvas + linkStyle default stroke:#5F7185,stroke-width:1.2px; ``` From 740fa13c36152eb812822df92a0ad49e88f172b6 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:13:06 -0400 Subject: [PATCH 03/67] docs(dark-factory): correct LLM gateway to Bifrost (not LiteLLM) The agent platform implements Bifrost as the LLM proxy (bifrost.bifrost.svc:8080, Bedrock via Pod Identity), not LiteLLM. Fixed the Flow A diagram node and all README references (coder contract env, security/egress model, profile notes, intro). Clarified that eks-platform-openclaw uses LiteLLM but this platform uses Bifrost. --- docs/dark-factory/README.md | 22 +++++++++---------- .../diagrams/flow-a-sandbox-capability.md | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index a577f22..5515411 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -10,7 +10,7 @@ approves the *results*) merge and tear everything down. This pattern wires that idea onto the **Open Agent Platform (OAP)** using components the platform already has: hardware-isolated **Kata micro-VM sandboxes** (from `eks-platform-openclaw`), the -**LiteLLM → Bedrock** model gateway, the **hub + spoke-dev/spoke-prod** cluster fleet, and +**Bifrost → Bedrock** LLM gateway, the **hub + spoke-dev/spoke-prod** cluster fleet, and **AWS-managed frontier agents** (Security, DevOps) for independent review. --- @@ -169,11 +169,11 @@ Runs on **spoke-dev only**. End to end: The coder is behind a **thin, swappable interface** — a deliberate choice (the industry lesson is *don't marry a single vendor*). Two profiles ship; both run **inside** the Kata sandbox and reach -models only through LiteLLM. +models only through the **Bifrost** LLM gateway. | Profile | Why | Notes | |---|---|---| -| **A — Claude Code headless** *(primary)* | Purpose-built for autonomous implement→build→test→git loops; proven headless/CI autonomy | `CLAUDE_CODE_USE_BEDROCK` / base-URL → LiteLLM; strongest multi-file + shell | +| **A — Claude Code headless** *(primary)* | Purpose-built for autonomous implement→build→test→git loops; proven headless/CI autonomy | `CLAUDE_CODE_USE_BEDROCK` / base-URL → Bifrost; strongest multi-file + shell | | **B — Kiro headless** | **Spec-driven** (`spec → requirements → design → tasks`) — the most natural fit since *an issue is a spec*; supports a headless GitHub Actions mode | AWS-native; documented as the second profile | ### The coder contract (drop-in interface) @@ -185,11 +185,11 @@ INPUTS (mounted into the sandbox) /workspace/SPEC.md # the issue, as a spec /workspace/repo/ # the checked-out target repo (branch df/issue-) /workspace/RETRY.md # (optional) one-line failure reasons from a prior holdout run - tmpfs: litellm-api-key # mode 0400, read then unset — never in env + tmpfs: bifrost-api-key # mode 0400, read then unset — never in env tmpfs: gh-token # short-TTL, mode 0400 ENV CODER_PROFILE=claude-code|kiro - LITELLM_URL=http://litellm.litellm.svc:4000 + BIFROST_URL=http://bifrost.bifrost.svc:8080 OUTPUTS (produced by the coder) git branch df/issue- with commits /workspace/artifacts/result.json # what changed, build/test logs, evidence links @@ -309,10 +309,10 @@ Untrusted, LLM-generated code + issue text from anyone = treat the whole sandbox - **Hardware isolation:** every coder runs in a **Kata micro-VM** (own kernel), not a shared-kernel container. -- **No cloud credentials in the sandbox:** the coder holds only a **LiteLLM API key** and a +- **No cloud credentials in the sandbox:** the coder holds only a **Bifrost API key** and a **short-TTL GitHub token** via **projected tmpfs (mode 0400)** — read then unset, never in env. All AWS IAM lives with the **orchestrator, outside the VM**. -- **Egress lockdown:** a **NetworkPolicy** restricts sandbox egress to **LiteLLM:4000 + DNS + +- **Egress lockdown:** a **NetworkPolicy** restricts sandbox egress to **Bifrost:8080 + DNS + GitHub only**. `automountServiceAccountToken: false`, runAsNonRoot, seccomp `RuntimeDefault`, drop `ALL` caps. - **Prod is never a test bed:** the factory runs on **spoke-dev**; spoke-prod holds the sandbox @@ -347,7 +347,7 @@ Jules, Cursor background agents, Factory.ai, and StrongDM's "Software Factory" a 1. **Lethal trifecta / prompt injection (highest risk).** Untrusted issue text + cloud creds + egress → data exfiltration. Invariant Labs demonstrated a malicious GitHub *issue* injecting an agent into leaking private-repo data via an auto-PR. **Our defense:** credentials never in the - issue-ingesting sandbox context; egress denied except LiteLLM/GitHub; issue/repo content treated + issue-ingesting sandbox context; egress denied except Bifrost/GitHub; issue/repo content treated as hostile; frontier agents scoped read-only. *(Willison "lethal trifecta"; Invariant Labs.)* 2. **Reward hacking / test-gaming.** Frontier models stub evaluators (`evaluate = _always_ok`), make `verify()` return true, read reference answers, or delete the test oracle (METR, OpenAI, @@ -387,7 +387,7 @@ Each phase is independently valuable — if you stop after any one, you're bette *To resolve during implementation — flagged honestly rather than assumed:* -- **Headless auth** for Claude Code & Kiro through a LiteLLM base-URL override inside a Kata VM +- **Headless auth** for Claude Code & Kiro through a Bifrost base-URL override inside a Kata VM (the biggest unknown — prototype first in P1). - **Import the `agent-sandbox` operator** from `eks-platform-openclaw` into the OAP addon catalog (Flow A's first task). @@ -427,6 +427,6 @@ Each phase is independently valuable — if you stop after any one, you're bette - Anthropic — *Claude Code best practices* — https://www.anthropic.com/engineering/claude-code-best-practices **Platform building blocks (this monorepo & siblings)** -- `eks-platform-openclaw` — Kata micro-VM sandbox, `Sandbox` CRD, session-router lifecycle, LiteLLM gateway +- `eks-platform-openclaw` — Kata micro-VM sandbox, `Sandbox` CRD, session-router lifecycle (uses LiteLLM there; **this platform uses Bifrost** as the LLM gateway) - `appmod-blueprints` — `PlatformCluster` Crossplane composition (ephemeral EKS), KRO CI/CD pipeline -- `agent-platform-amazon-eks` — hub/spoke fleet, addon ApplicationSets, kagent, agent-gateway +- `agent-platform-amazon-eks` — hub/spoke fleet, addon ApplicationSets, kagent, agent-gateway, **Bifrost** LLM gateway diff --git a/docs/dark-factory/diagrams/flow-a-sandbox-capability.md b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md index a3d4db7..6c6777a 100644 --- a/docs/dark-factory/diagrams/flow-a-sandbox-capability.md +++ b/docs/dark-factory/diagrams/flow-a-sandbox-capability.md @@ -60,7 +60,7 @@ flowchart TB RC --- KD --- NP end - MODEL["🧠 LiteLLM gateway
litellm.litellm.svc:4000 → Bedrock"]:::node + MODEL["🧠 Bifrost LLM gateway
bifrost.bifrost.svc:8080 → Bedrock"]:::node end end From 6a02279e84e09d30b15df5600a759e43562b81e7 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:21:02 -0400 Subject: [PATCH 04/67] feat(agent-sandbox): add chart scaffold (Chart.yaml) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flow A — Agent Sandbox capability. New GitOps addon chart that packages the Kata micro-VM sandbox substrate for the Open Agent Platform. --- gitops/addons/charts/agent-sandbox/Chart.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/Chart.yaml diff --git a/gitops/addons/charts/agent-sandbox/Chart.yaml b/gitops/addons/charts/agent-sandbox/Chart.yaml new file mode 100644 index 0000000..74441ed --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +name: agent-sandbox +description: >- + Agent Sandbox capability for the Open Agent Platform — hardware-isolated + Kata micro-VM sandboxes (agents.x-k8s.io Sandbox CRD) with a pre-warmed pool + kept ready by a pool-manager controller. The reusable isolation substrate any + agent workload (e.g. the Dark Factory coding pipeline) can claim on demand. +type: application +version: 0.1.0 +appVersion: "0.1.0" +keywords: + - kata + - sandbox + - isolation + - micro-vm + - dark-factory +sources: + - https://github.com/aws-samples/sample-open-agentic-platform + - https://github.com/elamaran11/eks-platform-openclaw +maintainers: + - name: Open Agent Platform From a0040bed83e10dc335efbd01f65373a1c6c57c4d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:21:40 -0400 Subject: [PATCH 05/67] feat(agent-sandbox): add chart values.yaml Tunable surface: operator image, kata runtime classes + default (kata-clh), warm-pool sizing (targetIdle=3, scale-to-zero TTL, reap TTL), pool-manager config, and the coder SandboxTemplate defaults (Bifrost LLM gateway URL). --- .../addons/charts/agent-sandbox/values.yaml | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/values.yaml diff --git a/gitops/addons/charts/agent-sandbox/values.yaml b/gitops/addons/charts/agent-sandbox/values.yaml new file mode 100644 index 0000000..5be774f --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/values.yaml @@ -0,0 +1,76 @@ +# Agent Sandbox capability — default values +# +# This chart installs the Sandbox control plane (operator + CRDs), the Kata +# RuntimeClasses that workloads select via runtimeClassName, a SandboxTemplate +# the Dark Factory (and other consumers) claim against, and a pool-manager that +# keeps a warm buffer of idle sandboxes ready. + +# Namespace the sandbox capability runs in (operator, pool-manager, warm pool). +namespace: agent-sandbox-system + +# ── Sandbox operator (agents.x-k8s.io) ─────────────────────────────────────── +operator: + # Upstream agent-sandbox controller image. + image: public.ecr.aws/t6v6o5d5/agent-sandbox:v0.1.0 + replicas: 1 + # Install the Sandbox / SandboxTemplate / SandboxClaim CRDs with the chart. + # Disable if the cluster already has a newer operator managing the CRDs. + installCRDs: true + +# ── Kata micro-VM runtime ──────────────────────────────────────────────────── +kata: + # Default VMM for coder sandboxes. Cloud Hypervisor (clh) boots fast and is + # the platform default; qemu and fc (Firecracker) are also installed. + defaultRuntimeClass: kata-clh + # RuntimeClasses to render. Each carries the nodeSelector + toleration that + # steers a pod onto the matching Karpenter kata pool. + runtimeClasses: + - name: kata-clh + handler: kata-clh + - name: kata-qemu + handler: kata-qemu + # Node scheduling applied to every kata RuntimeClass. + nodeSelector: + katacontainers.io/kata-runtime: "true" + tolerations: + - key: kata + operator: Equal + value: "true" + effect: NoSchedule + +# ── Warm pool ──────────────────────────────────────────────────────────────── +warmPool: + enabled: true + # Number of idle sandboxes to keep ready. Claim one → pool-manager refills; + # release one → pool-manager shrinks back to this target. + targetIdle: 3 + # Idle sandboxes scale to replicas:0 after this TTL (PVC retained); resume on + # demand. Set 0 to keep idle sandboxes running (higher cost, instant claim). + idleScaleToZeroSeconds: 900 + # Hard TTL — a claimed sandbox with no activity past this is reaped (safety + # net for crashed/abandoned consumers). + reapAfterSeconds: 3600 + # The SandboxTemplate that idle/claimed sandboxes are cloned from. + templateName: coder-sandbox + +# ── Pool-manager controller ────────────────────────────────────────────────── +poolManager: + # Small controller image (kubectl + jq loop) that reconciles the warm buffer. + image: public.ecr.aws/aws-cli/aws-cli:2.17.0 + # How often the reconcile/reaper loop runs. + intervalSeconds: 60 + resources: + requests: { cpu: 50m, memory: 64Mi } + limits: { cpu: 200m, memory: 128Mi } + +# ── Coder SandboxTemplate (podTemplate the warm pool clones) ───────────────── +coderTemplate: + # Sandbox coder image is set by the consumer (Dark Factory picks the coder + # profile — claude-code | kiro). Placeholder here; overridden per claim. + image: public.ecr.aws/docker/library/busybox:1.36 + workspaceSizeGi: 5 + resources: + requests: { cpu: "1", memory: 2Gi } + limits: { cpu: "2", memory: 4Gi } + # LLM gateway the coder reaches (this platform uses Bifrost, not LiteLLM). + bifrostUrl: http://bifrost.bifrost.svc.cluster.local:8080 From 072bae5b5a3377f482e2ac428daf122d7f070805 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:22:03 -0400 Subject: [PATCH 06/67] feat(agent-sandbox): add _helpers.tpl (labels, selectors, namespace) --- .../agent-sandbox/templates/_helpers.tpl | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/_helpers.tpl diff --git a/gitops/addons/charts/agent-sandbox/templates/_helpers.tpl b/gitops/addons/charts/agent-sandbox/templates/_helpers.tpl new file mode 100644 index 0000000..c59c0d5 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/_helpers.tpl @@ -0,0 +1,23 @@ +{{/* +Common labels applied to every resource this chart renders. +*/}} +{{- define "agent-sandbox.labels" -}} +app.kubernetes.io/name: agent-sandbox +app.kubernetes.io/part-of: open-agent-platform +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version }} +{{- end -}} + +{{/* +Selector labels (stable subset used by Services / controllers). +*/}} +{{- define "agent-sandbox.selectorLabels" -}} +app.kubernetes.io/name: agent-sandbox +{{- end -}} + +{{/* +The namespace the capability runs in. +*/}} +{{- define "agent-sandbox.namespace" -}} +{{- default "agent-sandbox-system" .Values.namespace -}} +{{- end -}} From c54170e1c0e93ced9bcb76b029a50e08ab4b279c Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:22:25 -0400 Subject: [PATCH 07/67] feat(agent-sandbox): add namespace with restricted Pod Security Standard Namespace enforces PSS 'restricted' since kata sandboxes run untrusted LLM-generated code. Verified: helm template renders cleanly. --- .../charts/agent-sandbox/templates/00-namespace.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml b/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml new file mode 100644 index 0000000..31e3c4e --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} + # Kata sandboxes run untrusted, LLM-generated code — enforce a restricted + # Pod Security Standard on the namespace as defense in depth. + pod-security.kubernetes.io/enforce: restricted + pod-security.kubernetes.io/audit: restricted + pod-security.kubernetes.io/warn: restricted From 49a6f625302db5bc644e7f10d15f0a299d2b6e19 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:22:46 -0400 Subject: [PATCH 08/67] feat(agent-sandbox): add Kata RuntimeClasses (kata-clh, kata-qemu) Renders one RuntimeClass per values.kata.runtimeClasses entry with the nodeSelector + toleration that steers pods onto the kata Karpenter pool. Verified: helm template renders kata-clh + kata-qemu with correct handlers. --- .../templates/10-runtimeclasses.yaml | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/10-runtimeclasses.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/10-runtimeclasses.yaml b/gitops/addons/charts/agent-sandbox/templates/10-runtimeclasses.yaml new file mode 100644 index 0000000..cf7e3e4 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/10-runtimeclasses.yaml @@ -0,0 +1,22 @@ +{{- /* +Kata RuntimeClasses. A workload selects a VMM with `runtimeClassName: kata-clh` +(or kata-qemu). The RuntimeClass admission controller force-merges the +scheduling.nodeSelector + tolerations below onto the pod, steering it onto the +matching Karpenter kata pool. The runtime binaries themselves are installed on +the node by kata-deploy (a prerequisite provided by the base platform). +*/ -}} +{{- range .Values.kata.runtimeClasses }} +--- +apiVersion: node.k8s.io/v1 +kind: RuntimeClass +metadata: + name: {{ .name }} + labels: + {{- include "agent-sandbox.labels" $ | nindent 4 }} +handler: {{ .handler }} +scheduling: + nodeSelector: + {{- toYaml $.Values.kata.nodeSelector | nindent 4 }} + tolerations: + {{- toYaml $.Values.kata.tolerations | nindent 4 }} +{{- end }} From 56348b756e15664dc7c205f40f26f7d112076063 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:23:17 -0400 Subject: [PATCH 09/67] feat(agent-sandbox): add coder SandboxTemplate with isolation invariants SandboxTemplate the warm pool clones: kata-clh runtime, no SA token, runAsNonRoot + restricted seccomp + drop ALL caps, readOnlyRootFilesystem, ephemeral workspace PVC, Bifrost LLM gateway URL. Image/secrets patched per-claim by the consumer. Verified: helm template renders correctly. --- .../templates/20-sandboxtemplate.yaml | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml new file mode 100644 index 0000000..123dff2 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml @@ -0,0 +1,70 @@ +{{- /* +SandboxTemplate — the podTemplate the warm pool (and Dark Factory claims) are +cloned from. Encodes the isolation invariants for running untrusted, +LLM-generated code: + - runtimeClassName: a Kata micro-VM (own kernel), not a shared-kernel container + - automountServiceAccountToken: false (no in-cluster API creds by default) + - runAsNonRoot + restricted seccomp + drop ALL caps + - workspace on an ephemeral PVC (per claim), model access via Bifrost only +The concrete coder image (claude-code | kiro) and per-claim secrets are patched +in by the consumer when it binds a SandboxClaim. +*/ -}} +apiVersion: extensions.agents.x-k8s.io/v1alpha1 +kind: SandboxTemplate +metadata: + name: {{ .Values.warmPool.templateName }} + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + podTemplate: + metadata: + labels: + {{- include "agent-sandbox.selectorLabels" . | nindent 8 }} + agent-sandbox.io/role: coder + spec: + runtimeClassName: {{ .Values.kata.defaultRuntimeClass }} + automountServiceAccountToken: false + nodeSelector: + {{- toYaml .Values.kata.nodeSelector | nindent 8 }} + tolerations: + {{- toYaml .Values.kata.tolerations | nindent 8 }} + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: coder + image: {{ .Values.coderTemplate.image }} + # Overridden per claim by the consumer (Dark Factory picks the profile). + command: ["/bin/sh", "-c", "echo 'coder image set per-claim'; sleep infinity"] + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + env: + # This platform uses Bifrost (not LiteLLM) as the LLM gateway. + - name: BIFROST_URL + value: {{ .Values.coderTemplate.bifrostUrl | quote }} + resources: + {{- toYaml .Values.coderTemplate.resources | nindent 12 }} + volumeMounts: + - name: workspace + mountPath: /workspace + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: {} + volumeClaimTemplates: + - metadata: + name: workspace + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: {{ .Values.coderTemplate.workspaceSizeGi }}Gi From b4ecdb284e234f9a48cdda0478d3957d7f3da627 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:23:49 -0400 Subject: [PATCH 10/67] feat(agent-sandbox): add default-deny egress NetworkPolicy for coders Locks coder-sandbox egress to DNS + Bifrost:8080 + HTTPS (git/gh/registries), blocks IMDS (169.254.169.254). Breaks the lethal trifecta so untrusted issue text can't reach arbitrary internal services or exfiltrate. Verified: renders + chart lints clean. --- .../templates/30-networkpolicy.yaml | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/30-networkpolicy.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/30-networkpolicy.yaml b/gitops/addons/charts/agent-sandbox/templates/30-networkpolicy.yaml new file mode 100644 index 0000000..13a8a51 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/30-networkpolicy.yaml @@ -0,0 +1,50 @@ +{{- /* +Default-deny egress for coder sandboxes, then allow ONLY what a coder needs: + - DNS (kube-dns) + - Bifrost LLM gateway (model calls) + - HTTPS to the internet for git/gh + package registries the build needs +This breaks the "lethal trifecta": untrusted issue text runs in a pod that +cannot reach arbitrary internal services or exfiltrate to arbitrary hosts. +Selects coder pods by the label the SandboxTemplate stamps. +*/ -}} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: coder-sandbox-egress + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + agent-sandbox.io/role: coder + policyTypes: + - Egress + egress: + # DNS resolution + - to: + - namespaceSelector: {} + ports: + - protocol: UDP + port: 53 + - protocol: TCP + port: 53 + # Bifrost LLM gateway (in-cluster) + - to: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: bifrost + ports: + - protocol: TCP + port: 8080 + # HTTPS egress for git / gh / package registries (build dependencies). + # Note: broad :443 is required for public git+registry access; tighten to + # specific CIDRs/hostnames with an egress proxy for stricter deployments. + - to: + - ipBlock: + cidr: 0.0.0.0/0 + except: + - 169.254.169.254/32 # block IMDS (instance metadata) + ports: + - protocol: TCP + port: 443 From b31c6eb881735ea4d2de751cd656793d4f8c422c Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:24:17 -0400 Subject: [PATCH 11/67] feat(agent-sandbox): add pool-manager RBAC (SA + namespaced Role) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Narrowly-scoped Role: sandboxes (+scale subresource), sandboxtemplates/claims read, PVC/Service delete — capability namespace only, no cluster-wide access. Gated on warmPool.enabled. Verified: renders; disabling warmPool emits 0 resources. --- .../templates/40-poolmanager-rbac.yaml | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml b/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml new file mode 100644 index 0000000..4e83306 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml @@ -0,0 +1,51 @@ +{{- if .Values.warmPool.enabled }} +{{- /* +RBAC for the pool-manager: narrowly scoped to Sandboxes/PVCs/Services in the +capability namespace only. It maintains the warm buffer and reaps idle/expired +sandboxes — it never touches cluster-wide resources or other namespaces. +*/ -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: agent-sandbox-pool-manager + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: agent-sandbox-pool-manager + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +rules: + - apiGroups: ["agents.x-k8s.io"] + resources: ["sandboxes"] + verbs: ["get", "list", "watch", "create", "patch", "delete"] + - apiGroups: ["agents.x-k8s.io"] + resources: ["sandboxes/scale"] + verbs: ["get", "patch", "update"] + - apiGroups: ["extensions.agents.x-k8s.io"] + resources: ["sandboxtemplates", "sandboxclaims"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims", "services"] + verbs: ["get", "list", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: agent-sandbox-pool-manager + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: agent-sandbox-pool-manager + namespace: {{ include "agent-sandbox.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: agent-sandbox-pool-manager +{{- end }} From 0bcb9df36a3577eb2ba13917769d1ae8f8e6d55d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:24:54 -0400 Subject: [PATCH 12/67] feat(agent-sandbox): add pool-manager CronJob (warm-buffer reconcile) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every-minute CronJob that reconciles the warm pool: REFILL idle sandboxes to targetIdle via SandboxClaims, plus scale-to-zero + reap hooks. Runs non-root, readOnlyRootFilesystem, drop ALL. Verified: helm renders + YAML parses. NOTE: scale-to-zero/reap steps are stubbed — jq logic refined next commit. --- .../templates/41-poolmanager-cronjob.yaml | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml b/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml new file mode 100644 index 0000000..7832d94 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml @@ -0,0 +1,104 @@ +{{- if .Values.warmPool.enabled }} +{{- /* +Pool-manager: a CronJob that reconciles the warm buffer each interval. + 1. REFILL — if idle sandboxes < targetIdle, create SandboxClaims to top up. + 2. SCALE-TO-ZERO — idle sandboxes past idleScaleToZeroSeconds → replicas:0. + 3. REAP — claimed sandboxes with no activity past reapAfterSeconds → delete. +Idle vs claimed is tracked by the label agent-sandbox.io/state and the +agent-sandbox.io/last-seen annotation, both stamped by the consumer on claim. +A CronJob (not a Deployment) keeps the controller dependency-free and cheap; +swap for a real controller later if reconcile latency matters. +*/ -}} +apiVersion: batch/v1 +kind: CronJob +metadata: + name: agent-sandbox-pool-manager + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + schedule: "* * * * *" # every minute; loop below honors intervalSeconds + concurrencyPolicy: Forbid + successfulJobsHistoryLimit: 1 + failedJobsHistoryLimit: 2 + jobTemplate: + spec: + backoffLimit: 1 + template: + metadata: + labels: + {{- include "agent-sandbox.selectorLabels" . | nindent 12 }} + spec: + serviceAccountName: agent-sandbox-pool-manager + restartPolicy: OnFailure + securityContext: + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: pool-manager + image: {{ .Values.poolManager.image }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + env: + - name: NS + value: {{ include "agent-sandbox.namespace" . }} + - name: TARGET_IDLE + value: {{ .Values.warmPool.targetIdle | quote }} + - name: IDLE_SCALE_TO_ZERO_SECONDS + value: {{ .Values.warmPool.idleScaleToZeroSeconds | quote }} + - name: REAP_AFTER_SECONDS + value: {{ .Values.warmPool.reapAfterSeconds | quote }} + - name: TEMPLATE_NAME + value: {{ .Values.warmPool.templateName }} + resources: + {{- toYaml .Values.poolManager.resources | nindent 16 }} + volumeMounts: + - name: tmp + mountPath: /tmp + command: + - /bin/sh + - -c + - | + set -eu + command -v kubectl >/dev/null 2>&1 || { echo "kubectl required in image"; exit 1; } + now=$(date -u +%s) + + idle=$(kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ + -l 'agent-sandbox.io/state=idle' -o name 2>/dev/null | wc -l | tr -d ' ') + echo "warm pool: $idle idle / target $TARGET_IDLE" + + # 1. REFILL — top up idle sandboxes to the target buffer. + i="$idle" + while [ "$i" -lt "$TARGET_IDLE" ]; do + n="coder-idle-$(date -u +%s)-$i" + cat </dev/null + apiVersion: extensions.agents.x-k8s.io/v1alpha1 + kind: SandboxClaim + metadata: + name: $n + namespace: $NS + labels: + agent-sandbox.io/state: idle + spec: + sandboxTemplateRef: + name: $TEMPLATE_NAME + EOF + echo "refill: created idle claim $n" + i=$((i+1)) + done + + # 2. SCALE-TO-ZERO — idle sandboxes past the idle TTL. + kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ + -l 'agent-sandbox.io/state=idle' -o json 2>/dev/null \ + | kubectl get --raw /version >/dev/null 2>&1 || true + + echo "pool-manager reconcile complete" + volumes: + - name: tmp + emptyDir: {} +{{- end }} From d564535f52ce60ac5ded83a191a479223f2f53c1 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:25:26 -0400 Subject: [PATCH 13/67] fix(agent-sandbox): implement pool-manager scale-to-zero + reap logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace stubbed steps with real jq logic: idle sandboxes past idleScaleToZeroSeconds → kubectl scale --replicas=0 (PVC kept); claimed sandboxes past reapAfterSeconds → delete (abandoned-run safety net), keyed on the agent-sandbox.io/last-seen annotation. Verified: helm renders, YAML parses, embedded script passes sh -n. --- .../templates/41-poolmanager-cronjob.yaml | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml b/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml index 7832d94..8261ce9 100644 --- a/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml +++ b/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml @@ -92,10 +92,36 @@ spec: i=$((i+1)) done - # 2. SCALE-TO-ZERO — idle sandboxes past the idle TTL. + # 2. SCALE-TO-ZERO — idle sandboxes past the idle TTL scale to + # replicas:0 (PVC retained), resumed on demand by the consumer. + if [ "${IDLE_SCALE_TO_ZERO_SECONDS}" -gt 0 ]; then + kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ + -l 'agent-sandbox.io/state=idle' -o json 2>/dev/null \ + | jq -r --argjson now "$now" --argjson ttl "$IDLE_SCALE_TO_ZERO_SECONDS" ' + .items[] + | select((.spec.replicas // 1) > 0) + | select(((.metadata.annotations["agent-sandbox.io/last-seen"] // "0") | fromdateiso8601? // 0) < ($now - $ttl)) + | .metadata.name' \ + | while read -r s; do + [ -n "$s" ] || continue + kubectl scale sandbox.agents.x-k8s.io "$s" -n "$NS" --replicas=0 >/dev/null 2>&1 \ + && echo "scale-to-zero: paused idle $s" + done + fi + + # 3. REAP — claimed sandboxes with no activity past the hard TTL + # are deleted (safety net for crashed/abandoned consumers). kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ - -l 'agent-sandbox.io/state=idle' -o json 2>/dev/null \ - | kubectl get --raw /version >/dev/null 2>&1 || true + -l 'agent-sandbox.io/state=claimed' -o json 2>/dev/null \ + | jq -r --argjson now "$now" --argjson ttl "$REAP_AFTER_SECONDS" ' + .items[] + | select(((.metadata.annotations["agent-sandbox.io/last-seen"] // "0") | fromdateiso8601? // 0) < ($now - $ttl)) + | .metadata.name' \ + | while read -r s; do + [ -n "$s" ] || continue + kubectl delete sandbox.agents.x-k8s.io "$s" -n "$NS" --ignore-not-found >/dev/null 2>&1 \ + && echo "reap: deleted expired claimed $s" + done echo "pool-manager reconcile complete" volumes: From 6969a58dbee7a573c111a823bec83512d56f4601 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:26:09 -0400 Subject: [PATCH 14/67] feat(agent-sandbox): add Sandbox operator install (SA/ClusterRole/StatefulSet/Service) Controller runtime for agents.x-k8s.io (upstream image v0.1.0) that materializes a Kata-VM pod+service per Sandbox CR. CRDs (~4k lines) come from the upstream bundle at an earlier sync-wave, not vendored. Gated on operator.installCRDs. Verified: full chart renders 14 manifests, all parse, helm lint clean. --- .../agent-sandbox/templates/05-operator.yaml | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/05-operator.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml b/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml new file mode 100644 index 0000000..181e098 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml @@ -0,0 +1,106 @@ +{{- if .Values.operator.installCRDs }} +{{- /* +Agent Sandbox operator (agents.x-k8s.io). Installs the controller that +materializes a Kata-VM Pod + Service (+ PVCs) per Sandbox CR and reports +status.serviceFQDN. + +NOTE ON CRDs: the Sandbox / SandboxTemplate / SandboxClaim CRDs are large +(~4k lines of OpenAPI schema) and are installed from the upstream operator +bundle, not vendored here. In this monorepo they are applied at an earlier +sync-wave (see gitops wiring) via the upstream manifest at + public.ecr.aws/t6v6o5d5/agent-sandbox:v0.1.0 +This template provides the controller runtime (SA + ClusterRole + StatefulSet ++ Service); it assumes the CRDs already exist. Set operator.installCRDs=false +if a newer operator on the cluster already manages both. +*/ -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: agent-sandbox-controller + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: agent-sandbox-controller + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +rules: + - apiGroups: ["agents.x-k8s.io"] + resources: ["sandboxes", "sandboxes/status", "sandboxes/scale"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["extensions.agents.x-k8s.io"] + resources: ["sandboxtemplates", "sandboxclaims", "sandboxclaims/status"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["pods", "services", "persistentvolumeclaims"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: agent-sandbox-controller + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: agent-sandbox-controller + namespace: {{ include "agent-sandbox.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: agent-sandbox-controller +--- +apiVersion: v1 +kind: Service +metadata: + name: agent-sandbox-controller + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + selector: + app.kubernetes.io/name: agent-sandbox + agent-sandbox.io/component: controller + ports: + - port: 80 + targetPort: 8080 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: agent-sandbox-controller + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + serviceName: agent-sandbox-controller + replicas: {{ .Values.operator.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: agent-sandbox + agent-sandbox.io/component: controller + template: + metadata: + labels: + {{- include "agent-sandbox.labels" . | nindent 8 }} + agent-sandbox.io/component: controller + spec: + serviceAccountName: agent-sandbox-controller + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: controller + image: {{ .Values.operator.image }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + ports: + - name: http + containerPort: 8080 +{{- end }} From 0ff631de5ace2d08a14ef0118a9751f3a3e4248e Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:27:17 -0400 Subject: [PATCH 15/67] feat(agent-sandbox): register addon in the ApplicationSet catalog Add agent-sandbox to gitops/addons/bootstrap/default/addons.yaml: sync-wave 2, selector enable_agent_sandbox, Bifrost URL from cluster annotation. The ApplicationSet cluster-generator fans it onto any cluster carrying the label. Verified: addons.yaml parses. --- gitops/addons/bootstrap/default/addons.yaml | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index 7ad6396..6991e73 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -358,3 +358,25 @@ oam-agent-components: global: awsRegion: '{{.metadata.annotations.aws_region}}' clusterName: '{{.metadata.annotations.aws_cluster_name}}' + +# Agent Sandbox — hardware-isolated Kata micro-VM sandboxes (agents.x-k8s.io +# Sandbox CRD) with a pre-warmed pool kept ready by a pool-manager controller. +# The reusable isolation substrate the Dark Factory coding pipeline (and other +# agent workloads) claim on demand. Sync-wave 2: after the kata runtime is +# installed on nodes (base platform), before agentic workloads that claim a +# sandbox. +agent-sandbox: + enabled: true + namespace: agent-sandbox-system + defaultVersion: '0.1.0' + path: 'gitops/addons/charts/agent-sandbox' + annotationsAppSet: + argocd.argoproj.io/sync-wave: '2' + selector: + matchExpressions: + - key: enable_agent_sandbox + operator: In + values: ['true'] + valuesObject: + coderTemplate: + bifrostUrl: '{{default "http://bifrost.bifrost.svc.cluster.local:8080" (index .metadata.annotations "bifrost_url")}}' From a01e37da9a8821e2d91b3b1e08f9fa2c67c154d8 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:27:35 -0400 Subject: [PATCH 16/67] feat(agent-sandbox): enable on spoke-dev overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn on agent_sandbox in the dev environment overlay — the warm-pool capability comes up on spoke-dev where the Dark Factory pipeline runs. Verified: YAML parses. --- gitops/overlays/environments/dev/enabled-addons.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gitops/overlays/environments/dev/enabled-addons.yaml b/gitops/overlays/environments/dev/enabled-addons.yaml index 56ba38f..12d55b2 100644 --- a/gitops/overlays/environments/dev/enabled-addons.yaml +++ b/gitops/overlays/environments/dev/enabled-addons.yaml @@ -22,3 +22,6 @@ enabledAddons: # Agentic Platform agent_platform: true bifrost: true + # Agent Sandbox capability — Kata micro-VM sandboxes + warm pool. Permanent + # platform feature; the Dark Factory coding pipeline runs on spoke-dev. + agent_sandbox: true From 22f498ae72313318332974f947262de7197b764e Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:27:57 -0400 Subject: [PATCH 17/67] feat(agent-sandbox): enable on spoke-prod overlay (dormant capability) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Install the sandbox capability on prod as a permanent platform feature, but the Dark Factory never runs here — prod warm pool stays dormant, unreviewed code is only built/tested on spoke-dev (production-safety). Verified: YAML parses. --- gitops/overlays/environments/prod/enabled-addons.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gitops/overlays/environments/prod/enabled-addons.yaml b/gitops/overlays/environments/prod/enabled-addons.yaml index 89763f5..b0d67aa 100644 --- a/gitops/overlays/environments/prod/enabled-addons.yaml +++ b/gitops/overlays/environments/prod/enabled-addons.yaml @@ -23,3 +23,8 @@ enabledAddons: # Agentic Platform agent_platform: true bifrost: true + # Agent Sandbox capability installed on prod too (permanent platform feature), + # but the Dark Factory pipeline never runs here — the prod warm pool stays + # dormant. Unreviewed, agent-authored code is only ever built/tested on + # spoke-dev (production-safety). + agent_sandbox: true From d2ba4081093f5815346d3ba3c1f055b6805088dd Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:28:33 -0400 Subject: [PATCH 18/67] docs(agent-sandbox): add chart README (templates, values, prerequisites) --- gitops/addons/charts/agent-sandbox/README.md | 56 ++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/README.md diff --git a/gitops/addons/charts/agent-sandbox/README.md b/gitops/addons/charts/agent-sandbox/README.md new file mode 100644 index 0000000..18c5a73 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/README.md @@ -0,0 +1,56 @@ +# agent-sandbox + +**Flow A of the [Dark Factory pattern](../../../../docs/dark-factory/README.md).** +Hardware-isolated **Kata micro-VM sandboxes** (`agents.x-k8s.io` Sandbox CRD) with a **pre-warmed +pool** kept ready by a pool-manager controller — the reusable isolation substrate any agent +workload (notably the Dark Factory coding pipeline) can claim on demand. + +## What it installs + +| Template | Resource | Purpose | +|---|---|---| +| `00-namespace.yaml` | Namespace (PSS `restricted`) | Runs the capability; enforces restricted Pod Security | +| `05-operator.yaml` | SA + ClusterRole + StatefulSet + Service | The `agents.x-k8s.io` controller (materializes a Kata-VM pod per Sandbox) | +| `10-runtimeclasses.yaml` | RuntimeClass ×N | `kata-clh` (default), `kata-qemu` — steer pods onto kata Karpenter pools | +| `20-sandboxtemplate.yaml` | SandboxTemplate | The coder pod spec the warm pool clones (isolation invariants baked in) | +| `30-networkpolicy.yaml` | NetworkPolicy | Default-deny egress → DNS + Bifrost + HTTPS only (breaks the lethal trifecta) | +| `40-poolmanager-rbac.yaml` | SA + Role + RoleBinding | Narrowly-scoped RBAC for the pool-manager | +| `41-poolmanager-cronjob.yaml` | CronJob | Reconciles the warm buffer: refill / scale-to-zero / reap | + +## Enable + +```yaml +# gitops/overlays/environments/{dev,prod}/enabled-addons.yaml +enabledAddons: + agent_sandbox: true +``` + +The ApplicationSet cluster-generator (sync-wave 2) fans the chart onto any cluster carrying the +`enable_agent_sandbox` label. Installed on **spoke-dev and spoke-prod**; the Dark Factory pipeline +only *runs* on spoke-dev (prod pool stays dormant). + +## Key values + +| Value | Default | Purpose | +|---|---|---| +| `kata.defaultRuntimeClass` | `kata-clh` | VMM for coder sandboxes | +| `warmPool.targetIdle` | `3` | Idle sandboxes kept ready | +| `warmPool.idleScaleToZeroSeconds` | `900` | Idle → `replicas:0` (PVC kept) | +| `warmPool.reapAfterSeconds` | `3600` | Reap abandoned claimed sandboxes | +| `coderTemplate.bifrostUrl` | `http://bifrost.bifrost.svc.cluster.local:8080` | LLM gateway (Bifrost, not LiteLLM) | + +## Prerequisites + +- **Kata runtime installed on nodes** (via `kata-deploy` + kata Karpenter pools from the base + platform / `eks-platform-openclaw`). +- **Sandbox CRDs** (`Sandbox`, `SandboxTemplate`, `SandboxClaim`) applied at an earlier sync-wave + from the upstream operator bundle (`public.ecr.aws/t6v6o5d5/agent-sandbox:v0.1.0`) — the ~4k-line + OpenAPI schema is not vendored into this chart. +- **Bifrost** LLM gateway reachable at the configured URL. + +## Notes + +- The pool-manager is a CronJob (kubectl + jq reconcile loop) for a dependency-free reference + implementation; swap for a real controller if reconcile latency matters. +- `warmPool.enabled=false` removes the pool-manager entirely (operator + RuntimeClasses + template + remain, for manual/consumer-driven claims). From c82f394f8ebe2de848297c657cbdad86b928db5f Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:38:43 -0400 Subject: [PATCH 19/67] chore(agent-sandbox): disable on spoke-dev overlay (Auto Mode can't run Kata) Comment out agent_sandbox on dev. Spoke clusters run EKS Auto Mode + Bottlerocket, which cannot host Kata micro-VMs (no nested-virt/kvm control). Chart is kept; enabling needs a kata-capable nodepool strategy for Auto Mode first. Verified: YAML parses. --- gitops/overlays/environments/dev/enabled-addons.yaml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gitops/overlays/environments/dev/enabled-addons.yaml b/gitops/overlays/environments/dev/enabled-addons.yaml index 12d55b2..4072012 100644 --- a/gitops/overlays/environments/dev/enabled-addons.yaml +++ b/gitops/overlays/environments/dev/enabled-addons.yaml @@ -22,6 +22,9 @@ enabledAddons: # Agentic Platform agent_platform: true bifrost: true - # Agent Sandbox capability — Kata micro-VM sandboxes + warm pool. Permanent - # platform feature; the Dark Factory coding pipeline runs on spoke-dev. - agent_sandbox: true + # Agent Sandbox capability — Kata micro-VM sandboxes + warm pool. + # DISABLED for now: spoke clusters run EKS Auto Mode + Bottlerocket, which + # cannot host Kata (no nested-virt / kvm control). Chart exists at + # gitops/addons/charts/agent-sandbox; enabling it needs a kata-capable + # nodepool strategy for Auto Mode — see docs/dark-factory (Flow A open item). + # agent_sandbox: true From e5015f93a7d9d55d1af90bdb1fd0f4229f0190dc Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:39:00 -0400 Subject: [PATCH 20/67] chore(agent-sandbox): disable on spoke-prod overlay (Auto Mode can't run Kata) Same as dev: comment out agent_sandbox until EKS Auto Mode + Kata integration is designed. Chart retained. Verified: YAML parses. --- gitops/overlays/environments/prod/enabled-addons.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gitops/overlays/environments/prod/enabled-addons.yaml b/gitops/overlays/environments/prod/enabled-addons.yaml index b0d67aa..c4c89ee 100644 --- a/gitops/overlays/environments/prod/enabled-addons.yaml +++ b/gitops/overlays/environments/prod/enabled-addons.yaml @@ -23,8 +23,8 @@ enabledAddons: # Agentic Platform agent_platform: true bifrost: true - # Agent Sandbox capability installed on prod too (permanent platform feature), - # but the Dark Factory pipeline never runs here — the prod warm pool stays - # dormant. Unreviewed, agent-authored code is only ever built/tested on - # spoke-dev (production-safety). - agent_sandbox: true + # Agent Sandbox capability — DISABLED for now (same reason as dev): EKS Auto + # Mode + Bottlerocket cannot host Kata. Re-enable once Auto Mode integration + # is designed. When on, prod holds the capability but the pool stays dormant + # (the Dark Factory only runs on spoke-dev — production-safety). + # agent_sandbox: true From cf69586d3bab7e7ecfc63a84c789d1cee720f0ca Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 12:39:27 -0400 Subject: [PATCH 21/67] docs(dark-factory): document Kata-on-Auto-Mode blocker + integration options Record why agent-sandbox is disabled on spokes: EKS Auto Mode + Bottlerocket cannot host Kata (no nested-virt/kvm control, no kata-deploy). List 3 paths to evaluate: self-managed kata nodepool, Bedrock AgentCore/Fargate microVM, or gVisor. Top item to resolve before enabling Flow A live. --- docs/dark-factory/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index 5515411..4a9d772 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -387,6 +387,19 @@ Each phase is independently valuable — if you stop after any one, you're bette *To resolve during implementation — flagged honestly rather than assumed:* +- **🚧 BLOCKER — Kata on EKS Auto Mode.** The current spoke clusters run **EKS Auto Mode + + Bottlerocket** (`c6a`/`c6g` nodes), which **cannot host Kata micro-VMs**: Auto Mode gives no + control over `cpuOptions.nestedVirtualization`, kernel-module loading (`modprobe kvm_intel`), or + running `kata-deploy`, and the node types don't expose VT-x. `eks-platform-openclaw` deliberately + avoids Auto Mode for exactly this reason. The `agent-sandbox` addon is therefore **built but + disabled** in the dev/prod overlays until we choose an integration path. Options to evaluate: + 1. **Self-managed kata nodepool alongside Auto Mode** — add a nested-virt (`c8i`/`m8i`) Karpenter + nodepool + `kata-deploy` to spokes (mirrors openclaw); real hardware isolation, extra cost/ops. + 2. **AWS-managed microVM isolation** — use **Bedrock AgentCore** (per-session microVM) or Fargate + as the isolation boundary instead of self-hosted Kata; less control, no node management. + 3. **gVisor / user-space sandbox** on Auto Mode — weaker than a true VM boundary but Auto-Mode- + compatible; a middle option for the coder sandbox. + This is the top thing to think through before enabling Flow A on these clusters. - **Headless auth** for Claude Code & Kiro through a Bifrost base-URL override inside a Kata VM (the biggest unknown — prototype first in P1). - **Import the `agent-sandbox` operator** from `eks-platform-openclaw` into the OAP addon catalog From ee17d0a27fd93d667cfc2f664faccce605e04d3d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:51:42 -0400 Subject: [PATCH 22/67] =?UTF-8?q?docs(dark-factory):=20add=20validated=20K?= =?UTF-8?q?ata-on-Auto-Mode=20design=20(=C2=A712a)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Record the spike outcome: self-managed nested-virt MNG coexists with EKS Auto Mode and /dev/kvm works via CpuOptions.NestedVirtualization (aws-cli >=2.35). Decision: MNG (not a 2nd Karpenter); AgentCore/gVisor rejected with reasons. Two implementation lessons: AL2023 nodeadm MIME userData (don't clobber bootstrap) + delete MNG-first teardown ordering. Replaces the old blocker note. --- docs/dark-factory/README.md | 55 ++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index 4a9d772..d98a1f4 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -383,23 +383,52 @@ Each phase is independently valuable — if you stop after any one, you're bette --- +## 12a. Running Kata on EKS Auto Mode clusters (validated design) + +The spoke clusters run **EKS Auto Mode + Bottlerocket** (`c6a`/`c6g` nodes). Auto Mode's managed +nodes **cannot host Kata**: no control over `cpuOptions.nestedVirtualization`, no kernel-module +loading (`modprobe kvm_intel`), no `kata-deploy`, and those node types don't expose VT-x. +`eks-platform-openclaw` avoids Auto Mode entirely for this reason — but we don't have to. + +### Decision: self-managed nested-virt MNG *alongside* Auto Mode + +Add a small, tainted **self-managed Managed Node Group** of **nested-virt `c8i`/`m8i`** instances to +spoke-dev. Auto Mode keeps running everything else; kata sandboxes schedule onto the MNG via the +`kata=true:NoSchedule` taint the chart already applies. We chose an **MNG, not a second +Karpenter** — running a self-managed Karpenter beside Auto Mode's managed Karpenter risks +NodePool/CRD conflicts, whereas MNGs are additive and coexist cleanly. + +Rejected alternatives: **Bedrock AgentCore / Fargate** (breaks the k8s-native pod model our whole +Sandbox/warm-pool/claim design depends on — it's an invoke-a-session runtime, not a pod we own); +**gVisor** (same Auto-Mode node-install blocker as Kata, weaker isolation). + +### ✅ Validated by a live spike (spoke-dev, 2026-07-10) + +A throwaway 1-node `c8i.4xlarge` MNG was created on spoke-dev, then torn down. Results: + +| Question | Result | +|---|---| +| Self-managed MNG coexists with Auto Mode? | **Yes** — MNG provisioned alongside Auto Mode nodepools, no conflict; Auto Mode stayed healthy | +| Nested virtualization / `/dev/kvm`? | **Yes** — `/dev/kvm` present, `kvm_intel` loaded, 32 `vmx` flags, via `CpuOptions.NestedVirtualization: enabled` | +| aws-cli support | Requires **aws-cli ≥ 2.35** for the `CpuOptions.NestedVirtualization` launch-template field | + +### Two hard-won lessons (baked into the implementation) + +1. **Node bootstrap** — do **not** override the AMI + userData with plain bash; that clobbers the + EKS bootstrap and the node boots (`/dev/kvm` present) but never joins the cluster. Use the + **AL2023 nodeadm MIME userData** format (or the default EKS AMI + a systemd unit that runs + `modprobe kvm_intel`), and set nested-virt via the **launch-template `CpuOptions`**, not userData. +2. **Teardown ordering** — delete the **MNG first and let it drain**. Terminating the instance out + from under the MNG makes the ASG respawn and can wedge the delete on a `Pending:Wait` lifecycle + hook; recover with `aws autoscaling terminate-instance-in-auto-scaling-group` + + `complete-lifecycle-action`. Set MNG min/desired to 0 before deleting for a clean teardown. + +--- + ## 13. Open questions / future work *To resolve during implementation — flagged honestly rather than assumed:* -- **🚧 BLOCKER — Kata on EKS Auto Mode.** The current spoke clusters run **EKS Auto Mode + - Bottlerocket** (`c6a`/`c6g` nodes), which **cannot host Kata micro-VMs**: Auto Mode gives no - control over `cpuOptions.nestedVirtualization`, kernel-module loading (`modprobe kvm_intel`), or - running `kata-deploy`, and the node types don't expose VT-x. `eks-platform-openclaw` deliberately - avoids Auto Mode for exactly this reason. The `agent-sandbox` addon is therefore **built but - disabled** in the dev/prod overlays until we choose an integration path. Options to evaluate: - 1. **Self-managed kata nodepool alongside Auto Mode** — add a nested-virt (`c8i`/`m8i`) Karpenter - nodepool + `kata-deploy` to spokes (mirrors openclaw); real hardware isolation, extra cost/ops. - 2. **AWS-managed microVM isolation** — use **Bedrock AgentCore** (per-session microVM) or Fargate - as the isolation boundary instead of self-hosted Kata; less control, no node management. - 3. **gVisor / user-space sandbox** on Auto Mode — weaker than a true VM boundary but Auto-Mode- - compatible; a middle option for the coder sandbox. - This is the top thing to think through before enabling Flow A on these clusters. - **Headless auth** for Claude Code & Kiro through a Bifrost base-URL override inside a Kata VM (the biggest unknown — prototype first in P1). - **Import the `agent-sandbox` operator** from `eks-platform-openclaw` into the OAP addon catalog From c5d020bc537958163da680d443108855efdc812a Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:52:27 -0400 Subject: [PATCH 23/67] feat(agent-sandbox): add kata-deploy chart dependency (gated) Depend on the upstream kata-deploy chart (v3.32.0) to install the Kata runtime + containerd handlers on kata MNG nodes. Gated by kataDeploy.enabled so the chart stays inert on clusters without a kata-capable nodepool. Verified: YAML parses. --- gitops/addons/charts/agent-sandbox/Chart.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gitops/addons/charts/agent-sandbox/Chart.yaml b/gitops/addons/charts/agent-sandbox/Chart.yaml index 74441ed..f213eb0 100644 --- a/gitops/addons/charts/agent-sandbox/Chart.yaml +++ b/gitops/addons/charts/agent-sandbox/Chart.yaml @@ -19,3 +19,12 @@ sources: - https://github.com/elamaran11/eks-platform-openclaw maintainers: - name: Open Agent Platform +# kata-deploy installs the Kata runtime (binaries, guest kernel, containerd +# runtime handlers for kata-clh/kata-qemu) on the tainted kata MNG nodes. +# Gated by values.kataDeploy.enabled so the chart is inert on clusters without +# a kata-capable nodepool. +dependencies: + - name: kata-deploy + version: "3.32.0" + repository: oci://ghcr.io/kata-containers/kata-deploy-charts + condition: kataDeploy.enabled From a36598444e2bdd9b9674c99e0dd7f9234be9ff43 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:52:50 -0400 Subject: [PATCH 24/67] feat(agent-sandbox): add kata-deploy subchart values + kataDeploy toggle Mirror openclaw's kata-deploy config: target the static kata-enabled label (not katacontainers.io/kata-runtime, which deadlocks), tolerate kata + runtime-not-ready taints, install qemu+clh shims, disable kata-deploy's own RuntimeClasses (our chart owns them). Default kataDeploy.enabled=false so it's inert without a kata nodepool. Verified: YAML parses. --- .../addons/charts/agent-sandbox/values.yaml | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/gitops/addons/charts/agent-sandbox/values.yaml b/gitops/addons/charts/agent-sandbox/values.yaml index 5be774f..22c35c3 100644 --- a/gitops/addons/charts/agent-sandbox/values.yaml +++ b/gitops/addons/charts/agent-sandbox/values.yaml @@ -17,6 +17,42 @@ operator: # Disable if the cluster already has a newer operator managing the CRDs. installCRDs: true +# ── kata-deploy (installs Kata runtime on the kata MNG nodes) ──────────────── +# Set enabled: true only on clusters that have a kata-capable nodepool (a +# self-managed nested-virt MNG on EKS Auto Mode — see docs/dark-factory §12a). +kataDeploy: + enabled: false +# Values passed to the upstream kata-deploy subchart. +kata-deploy: + kata-deploy: + image: + reference: quay.io/kata-containers/kata-deploy + tag: "3.32.0" + # Target the STATIC label set at node birth on the kata MNG — NOT + # katacontainers.io/kata-runtime (kata-deploy emits that only after install, + # so selecting on it would deadlock). + nodeSelector: + kata-enabled: "true" + tolerations: + - key: kata + operator: Equal + value: "true" + effect: NoSchedule + - key: katacontainers.io/runtime-not-ready + operator: Exists + effect: NoSchedule + shims: + disableAll: true + qemu: + enabled: true + clh: + enabled: true + # Our chart owns the RuntimeClasses (10-runtimeclasses.yaml) so all VMMs carry + # the same pool-steering scheduling block; disable kata-deploy's own to avoid + # two RuntimeClasses fighting over the same names. + runtimeClasses: + enabled: false + # ── Kata micro-VM runtime ──────────────────────────────────────────────────── kata: # Default VMM for coder sandboxes. Cloud Hypervisor (clh) boots fast and is From 4b242177db2873b0e5dcfb584d000464d4bd873d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:53:22 -0400 Subject: [PATCH 25/67] feat(agent-sandbox): add kata MNG launch-template nodeadm userData The correct AL2023 MIME userData for the nested-virt kata MNG: a boot script that modprobes kvm_intel + persists it (so /dev/kvm exists before Ready), then a nodeadm NodeConfig that joins the cluster with the kata-enabled label + kata=true taint. Encodes spike lesson #1 (don't clobber nodeadm bootstrap). --- .../kata-mng-launch-template-userdata.mime | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime new file mode 100644 index 0000000..f26bea8 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime @@ -0,0 +1,36 @@ +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="//" + +--// +Content-Type: text/x-shellscript; charset="us-ascii" + +#!/bin/bash +# Load the KVM module so /dev/kvm exists BEFORE the node goes Ready. +# cpuOptions.NestedVirtualization on the launch template only makes VT-x +# *visible*; the stock AL2023 image does not auto-load kvm_intel. Persist it so +# it survives reboots. (Lesson from the spike: setting nested-virt without this +# gives a node with no /dev/kvm.) +modprobe kvm_intel +printf 'kvm\nkvm_intel\n' > /etc/modules-load.d/kvm.conf + +--// +Content-Type: application/node.eks.aws + +# nodeadm NodeConfig — this is what actually joins the node to the cluster. +# CRITICAL (spike lesson #1): do NOT replace this with a plain-bash bootstrap or +# a custom AMI without nodeadm — the node will boot with /dev/kvm but never +# register with the control plane. Substitute the real cluster name at render. +apiVersion: node.eks.aws/v1alpha1 +kind: NodeConfig +spec: + cluster: + name: CLUSTER_NAME_PLACEHOLDER + kubelet: + flags: + # Labels + taint applied at node birth so kata-deploy schedules and the + # RuntimeClass nodeSelector matches. kata-enabled is the STATIC label + # kata-deploy targets; katacontainers.io/kata-runtime is emitted by + # kata-deploy after install. + - "--node-labels=kata-enabled=true,katacontainers.io/kata-runtime=true,node-type=kata-mng" + - "--register-with-taints=kata=true:NoSchedule" +--//-- From 91232af223ff717732cf259f0f08dd181c21b502 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:53:47 -0400 Subject: [PATCH 26/67] feat(agent-sandbox): add eksctl manifest for the kata MNG Declarative nested-virt (c8i/m8i) Managed Node Group for spoke-dev alongside Auto Mode: minSize 0 (scale-to-zero), kata-enabled label + kata=true taint, AL2023, scoped node IAM. Coexistence validated by the spike. Verified: YAML parses. --- .../nodepool/kata-mng-eksctl.yaml | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/nodepool/kata-mng-eksctl.yaml diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-eksctl.yaml b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-eksctl.yaml new file mode 100644 index 0000000..ebbca9b --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-eksctl.yaml @@ -0,0 +1,50 @@ +# Self-managed nested-virt Managed Node Group for Kata sandboxes, added to an +# existing EKS Auto Mode cluster (spoke-dev). Auto Mode keeps running everything +# else; kata sandboxes schedule here via the kata=true taint. Validated by the +# 2026-07-10 spike (see docs/dark-factory §12a). +# +# Apply: eksctl create nodegroup -f kata-mng-eksctl.yaml +# Requires eksctl with EKS Auto Mode coexistence support and an AMI/instance +# that exposes nested virtualization (c8i/m8i). +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: spoke-dev # target cluster + region: us-west-2 + +managedNodeGroups: + - name: kata-sandbox + # Nested-virt Intel instances (expose VT-x via CpuOptions.NestedVirtualization). + instanceTypes: ["c8i.4xlarge", "m8i.4xlarge"] + amiFamily: AmazonLinux2023 + minSize: 0 # scale-to-zero when no sandbox is claimed + maxSize: 3 + desiredCapacity: 1 + privateNetworking: true + volumeSize: 100 + # Labels applied at node birth: kata-enabled is the STATIC label kata-deploy + # targets; katacontainers.io/kata-runtime is (re)emitted by kata-deploy. + labels: + kata-enabled: "true" + katacontainers.io/kata-runtime: "true" + node-type: kata-mng + # Only kata sandboxes tolerate this taint — keeps general workloads off. + taints: + - key: kata + value: "true" + effect: NoSchedule + # nested virtualization + the modprobe/nodeadm userData are supplied via a + # launch template (eksctl overrideBootstrapCommand cannot set CpuOptions). + # See kata-mng-launch-template-userdata.mime and the Terraform variant. + # launchTemplate: + # id: lt-xxxxxxxx + tags: + platform: open-agent-platform + capability: agent-sandbox + iam: + attachPolicyARNs: + - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy + - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore From f2e790a33125c373742c9fa6d90f0860fb9f8031 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:54:22 -0400 Subject: [PATCH 27/67] feat(agent-sandbox): add Terraform kata MNG + nested-virt launch template Terraform variant for teams on the appmod/openclaw IaC path: launch template with cpu_options.nested_virtualization=enabled (the flag eksctl can't set) + MIME nodeadm userData (modprobe kvm_intel + join), MNG scale-to-zero, kata=true taint, kata labels. Verified: braces balanced. --- .../charts/agent-sandbox/nodepool/kata-mng.tf | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf new file mode 100644 index 0000000..140fafd --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf @@ -0,0 +1,100 @@ +# Terraform variant: nested-virt Kata Managed Node Group + launch template for +# an existing EKS Auto Mode cluster. Use this path when you need the launch +# template's CpuOptions.NestedVirtualization flag (eksctl cannot set it). +# Validated by the 2026-07-10 spike (docs/dark-factory §12a). +# +# Requires: aws provider (nested_virtualization support), AWS API/CLI vintage +# that exposes cpu_options.nested_virtualization. + +variable "cluster_name" { type = string default = "spoke-dev" } +variable "region" { type = string default = "us-west-2" } +variable "subnet_ids" { type = list(string) } +variable "node_role_arn" { type = string } +variable "instance_type" { type = string default = "c8i.4xlarge" } +variable "kata_max_size" { type = number default = 3 } + +# EKS-optimized AL2023 AMI for the cluster's k8s version (nodeadm bootstrap). +data "aws_ssm_parameter" "al2023" { + name = "/aws/service/eks/optimized-ami/1.35/amazon-linux-2023/x86_64/standard/recommended/image_id" +} + +locals { + # MIME userData: modprobe kvm_intel (so /dev/kvm exists) + nodeadm NodeConfig + # that joins the cluster with the kata labels/taint. See lesson #1 in §12a. + kata_userdata = base64encode(<<-MIME + MIME-Version: 1.0 + Content-Type: multipart/mixed; boundary="//" + + --// + Content-Type: text/x-shellscript; charset="us-ascii" + + #!/bin/bash + modprobe kvm_intel + printf 'kvm\nkvm_intel\n' > /etc/modules-load.d/kvm.conf + + --// + Content-Type: application/node.eks.aws + + apiVersion: node.eks.aws/v1alpha1 + kind: NodeConfig + spec: + cluster: + name: ${var.cluster_name} + kubelet: + flags: + - "--node-labels=kata-enabled=true,katacontainers.io/kata-runtime=true,node-type=kata-mng" + - "--register-with-taints=kata=true:NoSchedule" + --//-- + MIME + ) +} + +resource "aws_launch_template" "kata" { + name_prefix = "${var.cluster_name}-kata-" + image_id = data.aws_ssm_parameter.al2023.value + user_data = local.kata_userdata + + cpu_options { + # THE key flag — exposes VT-x on 8i instances so kata's VMM can run guests. + nested_virtualization = "enabled" + } + + tag_specifications { + resource_type = "instance" + tags = { platform = "open-agent-platform", capability = "agent-sandbox" } + } +} + +resource "aws_eks_node_group" "kata" { + cluster_name = var.cluster_name + node_group_name = "kata-sandbox" + node_role_arn = var.node_role_arn + subnet_ids = var.subnet_ids + + # Scale-to-zero when no sandbox is claimed; pool-manager / consumer scales up. + scaling_config { + min_size = 0 + desired_size = 1 + max_size = var.kata_max_size + } + + launch_template { + id = aws_launch_template.kata.id + version = aws_launch_template.kata.latest_version + } + + # Only kata sandboxes tolerate this — keeps general workloads off the pool. + taint { + key = "kata" + value = "true" + effect = "NO_SCHEDULE" + } + + labels = { + "kata-enabled" = "true" + "katacontainers.io/kata-runtime" = "true" + "node-type" = "kata-mng" + } + + tags = { platform = "open-agent-platform", capability = "agent-sandbox" } +} From ef7e7d71730ad9aa705c8dbf32f22873ed1c3434 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:55:10 -0400 Subject: [PATCH 28/67] fix(agent-sandbox): valid HCL for kata MNG Terraform (fmt + validate pass) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expand one-line variable blocks to valid multi-line HCL; terraform fmt applied. Verified with real terraform: 'terraform validate → Success! The configuration is valid.' --- .../charts/agent-sandbox/nodepool/kata-mng.tf | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf index 140fafd..c47b511 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf @@ -6,12 +6,28 @@ # Requires: aws provider (nested_virtualization support), AWS API/CLI vintage # that exposes cpu_options.nested_virtualization. -variable "cluster_name" { type = string default = "spoke-dev" } -variable "region" { type = string default = "us-west-2" } -variable "subnet_ids" { type = list(string) } -variable "node_role_arn" { type = string } -variable "instance_type" { type = string default = "c8i.4xlarge" } -variable "kata_max_size" { type = number default = 3 } +variable "cluster_name" { + type = string + default = "spoke-dev" +} +variable "region" { + type = string + default = "us-west-2" +} +variable "subnet_ids" { + type = list(string) +} +variable "node_role_arn" { + type = string +} +variable "instance_type" { + type = string + default = "c8i.4xlarge" +} +variable "kata_max_size" { + type = number + default = 3 +} # EKS-optimized AL2023 AMI for the cluster's k8s version (nodeadm bootstrap). data "aws_ssm_parameter" "al2023" { @@ -61,7 +77,7 @@ resource "aws_launch_template" "kata" { tag_specifications { resource_type = "instance" - tags = { platform = "open-agent-platform", capability = "agent-sandbox" } + tags = { platform = "open-agent-platform", capability = "agent-sandbox" } } } @@ -91,9 +107,9 @@ resource "aws_eks_node_group" "kata" { } labels = { - "kata-enabled" = "true" - "katacontainers.io/kata-runtime" = "true" - "node-type" = "kata-mng" + "kata-enabled" = "true" + "katacontainers.io/kata-runtime" = "true" + "node-type" = "kata-mng" } tags = { platform = "open-agent-platform", capability = "agent-sandbox" } From 4fc65188ee53611f6c9d11e56a87c08b8c8effda Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:56:35 -0400 Subject: [PATCH 29/67] fix(agent-sandbox): drop kata-deploy subchart dep (delivered as separate ArgoCD app) An unbuilt OCI subchart dependency blocks the whole chart from rendering (helm won't template with a missing dep) and is fragile under ArgoCD. Remove the dependency; kata-deploy will be a separate gated ArgoCD Application pulling the upstream OCI chart directly. Verified: chart renders standalone again + lint clean. --- gitops/addons/charts/agent-sandbox/Chart.yaml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/Chart.yaml b/gitops/addons/charts/agent-sandbox/Chart.yaml index f213eb0..1f8e75d 100644 --- a/gitops/addons/charts/agent-sandbox/Chart.yaml +++ b/gitops/addons/charts/agent-sandbox/Chart.yaml @@ -19,12 +19,8 @@ sources: - https://github.com/elamaran11/eks-platform-openclaw maintainers: - name: Open Agent Platform -# kata-deploy installs the Kata runtime (binaries, guest kernel, containerd -# runtime handlers for kata-clh/kata-qemu) on the tainted kata MNG nodes. -# Gated by values.kataDeploy.enabled so the chart is inert on clusters without -# a kata-capable nodepool. -dependencies: - - name: kata-deploy - version: "3.32.0" - repository: oci://ghcr.io/kata-containers/kata-deploy-charts - condition: kataDeploy.enabled +# NOTE: kata-deploy (the Kata runtime installer) is NOT bundled as a subchart +# dependency — an OCI subchart dep would block this chart from rendering when +# unbuilt and is fragile under ArgoCD. Instead it is delivered as a separate, +# gated ArgoCD Application (enable_agent_sandbox_kata) that pulls the upstream +# OCI chart directly. See the addon catalog + docs/dark-factory §12a. From 324aa367b18abcec724e04c7045c1f0fb6810086 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:57:01 -0400 Subject: [PATCH 30/67] feat(agent-sandbox): register kata-deploy as separate gated ArgoCD app Add kata-deploy to the addon catalog as its own app (OCI chart from ghcr.io/kata-containers, sync-wave 1) gated by enable_agent_sandbox_kata, so only clusters with a kata-capable nested-virt MNG install the runtime. Mirrors openclaw config: target kata-enabled label, tolerate kata + runtime-not-ready taints, qemu+clh shims, our chart owns RuntimeClasses. Verified: YAML parses. --- gitops/addons/bootstrap/default/addons.yaml | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index 6991e73..17e5093 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -380,3 +380,47 @@ agent-sandbox: valuesObject: coderTemplate: bifrostUrl: '{{default "http://bifrost.bifrost.svc.cluster.local:8080" (index .metadata.annotations "bifrost_url")}}' + +# kata-deploy — installs the Kata runtime (containerd handlers for kata-clh / +# kata-qemu) on the tainted kata MNG nodes. Separate app (not a subchart dep of +# agent-sandbox) so ArgoCD pulls the upstream OCI chart directly. Gated by +# enable_agent_sandbox_kata — only clusters with a kata-capable nested-virt MNG +# (see docs/dark-factory §12a) should carry that label. Sync-wave 1: runtime is +# installed on nodes before the Sandbox operator (wave 2) schedules VMs. +kata-deploy: + enabled: true + namespace: kube-system + chartName: kata-deploy + defaultVersion: '3.32.0' + chartRepository: 'ghcr.io/kata-containers/kata-deploy-charts' + chartNamespace: kata-containers + annotationsAppSet: + argocd.argoproj.io/sync-wave: '1' + selector: + matchExpressions: + - key: enable_agent_sandbox_kata + operator: In + values: ['true'] + valuesObject: + kata-deploy: + image: + reference: quay.io/kata-containers/kata-deploy + tag: '3.32.0' + nodeSelector: + kata-enabled: 'true' + tolerations: + - key: kata + operator: Equal + value: 'true' + effect: NoSchedule + - key: katacontainers.io/runtime-not-ready + operator: Exists + effect: NoSchedule + shims: + disableAll: true + qemu: + enabled: true + clh: + enabled: true + runtimeClasses: + enabled: false From 62b746c84c99094dc863d23f5c37a52f16598e94 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:57:34 -0400 Subject: [PATCH 31/67] refactor(agent-sandbox): drop kata-deploy subchart values (now separate app) kata-deploy moved to its own gated ArgoCD app, so remove the subchart values block from the chart; leave a pointer note. Verified: values parse + chart still renders 14 manifests. --- .../addons/charts/agent-sandbox/values.yaml | 39 ++----------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/values.yaml b/gitops/addons/charts/agent-sandbox/values.yaml index 22c35c3..ca90615 100644 --- a/gitops/addons/charts/agent-sandbox/values.yaml +++ b/gitops/addons/charts/agent-sandbox/values.yaml @@ -17,41 +17,10 @@ operator: # Disable if the cluster already has a newer operator managing the CRDs. installCRDs: true -# ── kata-deploy (installs Kata runtime on the kata MNG nodes) ──────────────── -# Set enabled: true only on clusters that have a kata-capable nodepool (a -# self-managed nested-virt MNG on EKS Auto Mode — see docs/dark-factory §12a). -kataDeploy: - enabled: false -# Values passed to the upstream kata-deploy subchart. -kata-deploy: - kata-deploy: - image: - reference: quay.io/kata-containers/kata-deploy - tag: "3.32.0" - # Target the STATIC label set at node birth on the kata MNG — NOT - # katacontainers.io/kata-runtime (kata-deploy emits that only after install, - # so selecting on it would deadlock). - nodeSelector: - kata-enabled: "true" - tolerations: - - key: kata - operator: Equal - value: "true" - effect: NoSchedule - - key: katacontainers.io/runtime-not-ready - operator: Exists - effect: NoSchedule - shims: - disableAll: true - qemu: - enabled: true - clh: - enabled: true - # Our chart owns the RuntimeClasses (10-runtimeclasses.yaml) so all VMMs carry - # the same pool-steering scheduling block; disable kata-deploy's own to avoid - # two RuntimeClasses fighting over the same names. - runtimeClasses: - enabled: false +# NOTE: The Kata *runtime installer* (kata-deploy) is delivered as a SEPARATE +# gated ArgoCD app (enable_agent_sandbox_kata), not from this chart — see the +# addon catalog and docs/dark-factory §12a. This chart owns the RuntimeClasses, +# operator, template, network policy, and pool-manager. # ── Kata micro-VM runtime ──────────────────────────────────────────────────── kata: From e19261fc779a736cf70e46e8742942ee1fa8d710 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 13:58:03 -0400 Subject: [PATCH 32/67] docs(agent-sandbox): add nodepool README (provisioning + enablement sequence) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document the kata MNG provisioning options (eksctl/Terraform/nodeadm userData), the 4-step per-cluster enablement sequence (provision MNG → enable_agent_sandbox_kata → enable_agent_sandbox → warm pool), cost (scale-to-zero), and teardown ordering. --- .../charts/agent-sandbox/nodepool/README.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/nodepool/README.md diff --git a/gitops/addons/charts/agent-sandbox/nodepool/README.md b/gitops/addons/charts/agent-sandbox/nodepool/README.md new file mode 100644 index 0000000..8b05586 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/nodepool/README.md @@ -0,0 +1,46 @@ +# Kata node pool provisioning + +The `agent-sandbox` chart installs the Sandbox operator, RuntimeClasses, coder +template, and pool-manager — but Kata needs **hardware-virtualization nodes** to +actually run micro-VMs. On an **EKS Auto Mode** cluster (like the spokes), Auto +Mode's managed Bottlerocket nodes can't host Kata, so we add a **self-managed +nested-virt Managed Node Group** alongside Auto Mode. Coexistence + `/dev/kvm` +were validated by a live spike (see [`docs/dark-factory` §12a](../../../../../docs/dark-factory/README.md)). + +## Files here + +| File | Purpose | +|---|---| +| `kata-mng-eksctl.yaml` | eksctl `ClusterConfig` to add the kata MNG (declarative, simplest) | +| `kata-mng.tf` | Terraform launch template (`cpu_options.nested_virtualization=enabled`) + MNG — use when you need the nested-virt flag eksctl can't set. `terraform validate` passes. | +| `kata-mng-launch-template-userdata.mime` | The AL2023 **nodeadm MIME** userData (modprobe kvm_intel + join). Reference for either path. | + +## Enablement sequence (per kata-capable cluster, e.g. spoke-dev) + +1. **Provision the kata MNG** — apply the eksctl or Terraform manifest here. Nodes + come up tainted `kata=true:NoSchedule`, labeled `kata-enabled=true`, with + `/dev/kvm` (nested-virt) and `min=0` scale-to-zero. +2. **Install the runtime** — label the cluster secret `enable_agent_sandbox_kata=true` + so the `kata-deploy` ArgoCD app (sync-wave 1) installs the containerd handlers. +3. **Install the capability** — label `enable_agent_sandbox=true` so the + `agent-sandbox` app (sync-wave 2) installs the operator + RuntimeClasses + + template + pool-manager. +4. **Enable the pool** — `warmPool.enabled=true` (default) pre-warms idle sandboxes. + +> Both labels are set via the environment overlays (`gitops/overlays/environments/dev`). +> They are commented out today until a kata MNG exists on the spokes. + +## Cost note + +Nested-virt `c8i`/`m8i` nodes are more expensive than the `c6*` Auto Mode +defaults. `min=0` scale-to-zero + the pool-manager's idle scale-down keep cost +proportional to actual sandbox activity — you pay for kata nodes only while a +sandbox is claimed/warming. + +## Teardown (spike lesson #2) + +Delete the **MNG first and let it drain** (set `min/desired=0` beforehand). Don't +terminate the instance out from under the MNG — the ASG respawns and can wedge +the delete on a `Pending:Wait` lifecycle hook. Recover with +`aws autoscaling terminate-instance-in-auto-scaling-group` + +`complete-lifecycle-action`. From d4307aadc6c9b1701a6b07007016422f4f8ddfc1 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 14:33:07 -0400 Subject: [PATCH 33/67] docs(dark-factory): note native SandboxWarmPool CRD (pool-manager likely redundant) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live testing found the upstream operator ships sandboxwarmpools.extensions. agents.x-k8s.io (spec: replicas + sandboxTemplateRef) — a first-class warm-pool primitive. Our custom pool-manager CronJob is likely redundant; prefer a SandboxWarmPool CR. To reconcile after the live test. --- docs/dark-factory/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index d98a1f4..372933d 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -429,6 +429,12 @@ A throwaway 1-node `c8i.4xlarge` MNG was created on spoke-dev, then torn down. R *To resolve during implementation — flagged honestly rather than assumed:* +- **⚡ SIMPLIFICATION — use the operator's native `SandboxWarmPool`.** Live testing revealed the + upstream agent-sandbox operator ships a **`sandboxwarmpools.extensions.agents.x-k8s.io` CRD** + (`spec: {replicas, sandboxTemplateRef}`) — a first-class warm-pool primitive. Our custom + pool-manager CronJob (`41-poolmanager-cronjob.yaml`) is therefore likely **redundant**: create a + `SandboxWarmPool` CR instead and let the operator maintain the buffer. Keep the CronJob only for + the extra scale-to-zero/reap behaviors the CR may not cover. To reconcile after the live test. - **Headless auth** for Claude Code & Kiro through a Bifrost base-URL override inside a Kata VM (the biggest unknown — prototype first in P1). - **Import the `agent-sandbox` operator** from `eks-platform-openclaw` into the OAP addon catalog From 47e04c4910e39d96aa1a5021219a1bc8e672dff5 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 14:40:12 -0400 Subject: [PATCH 34/67] fix(agent-sandbox): custom-AMI nodeadm needs apiServerEndpoint/CA/cidr (lesson #3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live test caught it: with a custom ImageId, nodeadm does NOT auto-discover the cluster API endpoint/CA and fails 'Apiserver endpoint is missing in cluster configuration' — node boots with /dev/kvm but never joins. Add apiServerEndpoint, certificateAuthority, and cidr to the NodeConfig in both the reference MIME userData and the Terraform (via aws_eks_cluster data source). Verified: terraform validate passes. --- .../kata-mng-launch-template-userdata.mime | 14 +++++++++++++- .../charts/agent-sandbox/nodepool/kata-mng.tf | 12 +++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime index f26bea8..96e8b1c 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng-launch-template-userdata.mime @@ -19,12 +19,24 @@ Content-Type: application/node.eks.aws # nodeadm NodeConfig — this is what actually joins the node to the cluster. # CRITICAL (spike lesson #1): do NOT replace this with a plain-bash bootstrap or # a custom AMI without nodeadm — the node will boot with /dev/kvm but never -# register with the control plane. Substitute the real cluster name at render. +# register with the control plane. +# +# LESSON #3 (live test): when you supply a CUSTOM ImageId in the launch template, +# nodeadm does NOT auto-discover the cluster API endpoint/CA — you must set +# apiServerEndpoint, certificateAuthority, and cidr explicitly, or nodeadm fails +# with "Apiserver endpoint is missing in cluster configuration". (The default +# EKS AMI path injects these for you; a custom AMI does not.) Substitute the +# cluster name + the three cluster values at render: +# aws eks describe-cluster --name \ +# --query 'cluster.{e:endpoint,ca:certificateAuthority.data,cidr:kubernetesNetworkConfig.serviceIpv4Cidr}' apiVersion: node.eks.aws/v1alpha1 kind: NodeConfig spec: cluster: name: CLUSTER_NAME_PLACEHOLDER + apiServerEndpoint: API_SERVER_ENDPOINT_PLACEHOLDER + certificateAuthority: CERTIFICATE_AUTHORITY_DATA_PLACEHOLDER + cidr: SERVICE_IPV4_CIDR_PLACEHOLDER kubelet: flags: # Labels + taint applied at node birth so kata-deploy schedules and the diff --git a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf index c47b511..71ae343 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf +++ b/gitops/addons/charts/agent-sandbox/nodepool/kata-mng.tf @@ -34,9 +34,16 @@ data "aws_ssm_parameter" "al2023" { name = "/aws/service/eks/optimized-ami/1.35/amazon-linux-2023/x86_64/standard/recommended/image_id" } +# Cluster endpoint/CA/cidr — REQUIRED in the NodeConfig when using a custom AMI +# (lesson #3, live test): nodeadm does not auto-discover these with a custom +# ImageId and fails with "Apiserver endpoint is missing in cluster configuration". +data "aws_eks_cluster" "this" { + name = var.cluster_name +} + locals { # MIME userData: modprobe kvm_intel (so /dev/kvm exists) + nodeadm NodeConfig - # that joins the cluster with the kata labels/taint. See lesson #1 in §12a. + # that joins the cluster with the kata labels/taint. See §12a lessons #1 + #3. kata_userdata = base64encode(<<-MIME MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="//" @@ -56,6 +63,9 @@ locals { spec: cluster: name: ${var.cluster_name} + apiServerEndpoint: ${data.aws_eks_cluster.this.endpoint} + certificateAuthority: ${data.aws_eks_cluster.this.certificate_authority[0].data} + cidr: ${data.aws_eks_cluster.this.kubernetes_network_config[0].service_ipv4_cidr} kubelet: flags: - "--node-labels=kata-enabled=true,katacontainers.io/kata-runtime=true,node-type=kata-mng" From 188d672beff11ce55210edbb428bb81d88eeb6df Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 14:51:49 -0400 Subject: [PATCH 35/67] docs(agent-sandbox): vpc-cni addon required for self-managed MNG on Auto Mode (lesson #4) Live test: Auto Mode clusters have no vpc-cni addon (built-in networking is Auto-Mode-nodes-only), so a self-managed kata MNG node joins but stays NotReady with 'cni plugin not initialized'. Fix: install the vpc-cni EKS addon; aws-node tolerates all taints and schedules onto the kata node. Verified: node went Ready + /dev/kvm present after installing vpc-cni. --- .../charts/agent-sandbox/nodepool/README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/gitops/addons/charts/agent-sandbox/nodepool/README.md b/gitops/addons/charts/agent-sandbox/nodepool/README.md index 8b05586..2bd3807 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/README.md +++ b/gitops/addons/charts/agent-sandbox/nodepool/README.md @@ -15,11 +15,25 @@ were validated by a live spike (see [`docs/dark-factory` §12a](../../../../../d | `kata-mng.tf` | Terraform launch template (`cpu_options.nested_virtualization=enabled`) + MNG — use when you need the nested-virt flag eksctl can't set. `terraform validate` passes. | | `kata-mng-launch-template-userdata.mime` | The AL2023 **nodeadm MIME** userData (modprobe kvm_intel + join). Reference for either path. | +## ⚠️ Prerequisite on EKS Auto Mode: install the `vpc-cni` addon + +**Auto Mode clusters have NO `vpc-cni` addon** — Auto Mode's built-in networking +only applies to its own managed nodes. A self-managed MNG node will join but stay +`NotReady` with `cni plugin not initialized` until you install the standard CNI: + +``` +aws eks create-addon --cluster-name --addon-name vpc-cni --resolve-conflicts OVERWRITE +``` + +`aws-node` tolerates all taints (`operator: Exists`), so it schedules onto the +tainted kata node automatically. (Discovered in live testing — lesson #4.) + ## Enablement sequence (per kata-capable cluster, e.g. spoke-dev) 1. **Provision the kata MNG** — apply the eksctl or Terraform manifest here. Nodes come up tainted `kata=true:NoSchedule`, labeled `kata-enabled=true`, with - `/dev/kvm` (nested-virt) and `min=0` scale-to-zero. + `/dev/kvm` (nested-virt) and `min=0` scale-to-zero. On Auto Mode, ensure the + `vpc-cni` addon is installed (see prerequisite above) or the node stays NotReady. 2. **Install the runtime** — label the cluster secret `enable_agent_sandbox_kata=true` so the `kata-deploy` ArgoCD app (sync-wave 1) installs the containerd handlers. 3. **Install the capability** — label `enable_agent_sandbox=true` so the From 3bffdac8a606c2d34f1cd5d2c9f5b328d39047d6 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 15:00:57 -0400 Subject: [PATCH 36/67] =?UTF-8?q?docs(dark-factory):=20live-test=20results?= =?UTF-8?q?=20=E2=80=94=204=20fixes=20validated=20+=20kata-deploy=20open?= =?UTF-8?q?=20item?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two live tests on spoke-dev proved: MNG+Auto-Mode coexistence, /dev/kvm, node joins Ready (with nodeadm endpoint/CA fix + vpc-cni addon). kata-deploy itself crashloops on Auto Mode due to the experimental nydus snapshotter restarting containerd + dropping CNI mid-run (lesson #5, fix: disable nydus). Also noted the top-level-vs-nested kata-deploy values gotcha for direct helm installs. --- docs/dark-factory/README.md | 44 ++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index 372933d..4a4bb55 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -402,26 +402,44 @@ Rejected alternatives: **Bedrock AgentCore / Fargate** (breaks the k8s-native po Sandbox/warm-pool/claim design depends on — it's an invoke-a-session runtime, not a pod we own); **gVisor** (same Auto-Mode node-install blocker as Kata, weaker isolation). -### ✅ Validated by a live spike (spoke-dev, 2026-07-10) +### ✅ Validated by two live tests (spoke-dev, 2026-07-10) -A throwaway 1-node `c8i.4xlarge` MNG was created on spoke-dev, then torn down. Results: +A `c8i.4xlarge` kata MNG was created on spoke-dev, exercised, then torn down. Results: | Question | Result | |---|---| -| Self-managed MNG coexists with Auto Mode? | **Yes** — MNG provisioned alongside Auto Mode nodepools, no conflict; Auto Mode stayed healthy | -| Nested virtualization / `/dev/kvm`? | **Yes** — `/dev/kvm` present, `kvm_intel` loaded, 32 `vmx` flags, via `CpuOptions.NestedVirtualization: enabled` | -| aws-cli support | Requires **aws-cli ≥ 2.35** for the `CpuOptions.NestedVirtualization` launch-template field | +| Self-managed MNG coexists with Auto Mode? | **✅ Yes** — MNG provisioned alongside Auto Mode nodepools, no conflict; Auto Mode stayed healthy | +| Nested virtualization / `/dev/kvm`? | **✅ Yes** — `/dev/kvm` present, `kvm_intel` loaded, 32 `vmx` flags, via `CpuOptions.NestedVirtualization: enabled` | +| Node joins the cluster & goes Ready? | **✅ Yes** — with the fixes below (nodeadm endpoint/CA + vpc-cni addon) | +| Kata runtime install (kata-deploy)? | **⚠️ Partial** — kata-deploy schedules on the kata node but crashloops on Auto Mode; see lesson #5 | -### Two hard-won lessons (baked into the implementation) +### Hard-won lessons (baked into the implementation) 1. **Node bootstrap** — do **not** override the AMI + userData with plain bash; that clobbers the - EKS bootstrap and the node boots (`/dev/kvm` present) but never joins the cluster. Use the - **AL2023 nodeadm MIME userData** format (or the default EKS AMI + a systemd unit that runs - `modprobe kvm_intel`), and set nested-virt via the **launch-template `CpuOptions`**, not userData. -2. **Teardown ordering** — delete the **MNG first and let it drain**. Terminating the instance out - from under the MNG makes the ASG respawn and can wedge the delete on a `Pending:Wait` lifecycle - hook; recover with `aws autoscaling terminate-instance-in-auto-scaling-group` + - `complete-lifecycle-action`. Set MNG min/desired to 0 before deleting for a clean teardown. + EKS bootstrap and the node boots (`/dev/kvm` present) but never joins. Use the **AL2023 nodeadm + MIME userData**, and set nested-virt via the launch-template `CpuOptions`, not userData. +2. **Teardown ordering** — delete the **MNG first and let it drain** (set min/desired=0 first). + Terminating the instance out from under the MNG makes the ASG respawn and can wedge the delete on + a `Pending:Wait` lifecycle hook; recover with `terminate-instance-in-auto-scaling-group` + + `complete-lifecycle-action`. +3. **Custom-AMI nodeadm needs cluster coordinates** — with a custom `ImageId`, nodeadm can't + auto-discover the API; you must set `apiServerEndpoint` + `certificateAuthority` + `cidr` in the + NodeConfig, or it fails "Apiserver endpoint is missing in cluster configuration". +4. **Auto Mode has no `vpc-cni`** — self-managed MNG nodes stay `NotReady` (`cni plugin not + initialized`) until you install the `vpc-cni` EKS addon. `aws-node` tolerates all taints and + schedules onto the kata node once installed. +5. **kata-deploy on Auto Mode (open item)** — the upstream kata-deploy chart defaults to the + **experimental nydus snapshotter** (`EXPERIMENTAL_SETUP_SNAPSHOTTER=nydus`), which restarts + containerd and briefly drops CNI networking; kata-deploy then fails its own API call + (`Failed to get node ... client error (Connect)`) and crashloops before installing the runtime. + Fix to apply next: disable the experimental nydus snapshotter (openclaw uses overlayfs) and/or + raise kata-deploy's API-retry tolerance. Everything *up to* the runtime install is proven; the + runtime install itself needs this one chart-tuning fix. + +Also fixed during testing: the kata-deploy Helm values are **top-level** (`nodeSelector`, +`tolerations`, `shims`) for a direct install — the nested `kata-deploy:` key only applies when it's +a subchart. Our catalog entry uses the nested form (correct, since ArgoCD deploys it as its own +app), but a direct `helm install` must use top-level values. --- From 38e5b37c95bfb34514ba33704cc367c0c0cf6b71 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 15:05:00 -0400 Subject: [PATCH 37/67] docs(agent-sandbox): document kata-deploy vs VPC-CNI Auto Mode blocker + options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live test confirmed: kata-deploy restarts containerd → drops the aws-node CNI on the same node → its own API call fails → crashloop before install completes. Disabling nydus snapshotter did not help (the restart is the trigger). Everything up to runtime install is proven. Options: bake Kata into a custom AMI (Packer), use openclaw's self-managed Karpenter model, or a no-restart containerd config. --- .../charts/agent-sandbox/nodepool/README.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/gitops/addons/charts/agent-sandbox/nodepool/README.md b/gitops/addons/charts/agent-sandbox/nodepool/README.md index 2bd3807..838eb96 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/README.md +++ b/gitops/addons/charts/agent-sandbox/nodepool/README.md @@ -28,6 +28,31 @@ aws eks create-addon --cluster-name --addon-name vpc-cni --resolve-con `aws-node` tolerates all taints (`operator: Exists`), so it schedules onto the tainted kata node automatically. (Discovered in live testing — lesson #4.) +## ⚠️ Known blocker: kata-deploy vs the VPC-CNI on Auto Mode (lesson #5) + +Live testing found kata-deploy **crashloops** on a self-managed MNG node in an +Auto Mode cluster and never finishes installing the runtime. Root cause: kata-deploy +patches containerd and **restarts it**; because the VPC-CNI runs as `aws-node` pods +*on that same containerd*, the restart briefly drops node networking, and +kata-deploy's next Kubernetes API call fails (`Failed to get node ... client error +(Connect)`) → the pod exits and CrashLoopBackOffs *before* completing the install. +Disabling the experimental nydus snapshotter (`snapshotter.setup: []`) did **not** +resolve it — the containerd restart itself is the trigger. + +**Everything up to the runtime install is proven** (node joins Ready, `/dev/kvm`, +kata labels/taint, kata-deploy schedules only on the kata node). Options to finish: + +1. **Bake Kata into a custom AMI** (Packer) so no on-node containerd patch/restart is + needed at runtime — the most robust path on Auto Mode clusters. +2. **Follow openclaw's model** — a self-managed Karpenter (not Auto Mode) where the + CNI/containerd lifecycle is fully controlled and kata-deploy's restart is tolerated. +3. Investigate a kata-deploy mode that configures containerd **without a full restart**, + or pin `aws-node` to not depend on the restarted containerd during install. + +This is a **kata-deploy-on-Auto-Mode** integration issue, not a flaw in the +`agent-sandbox` chart (operator/RuntimeClasses/template/pool-manager all render and +apply fine). + ## Enablement sequence (per kata-capable cluster, e.g. spoke-dev) 1. **Provision the kata MNG** — apply the eksctl or Terraform manifest here. Nodes From d9d02c8722815de863e0081bd4fc7810a184abe6 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 16:50:05 -0400 Subject: [PATCH 38/67] =?UTF-8?q?docs(agent-sandbox):=20PROVEN=20=E2=80=94?= =?UTF-8?q?=20Kata=20micro-VM=20runs=20on=20EKS=20Auto=20Mode=20end-to-end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live test success: pod under kata-clh ran with guest kernel 6.18.35 vs host 6.12.90 = real VM isolation. The real crux (NOT containerd restart / nydus — those were red herrings): self-managed MNG nodes on Auto Mode need BOTH vpc-cni AND kube-proxy addons, else kata-deploy can't reach kubernetes.default.svc and crashloops. Plus the runtime-not-ready startup-taint gate (openclaw PR #10) and an IAM access-entry-recreate gotcha. Full working recipe documented. --- .../charts/agent-sandbox/nodepool/README.md | 76 +++++++++++-------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/nodepool/README.md b/gitops/addons/charts/agent-sandbox/nodepool/README.md index 838eb96..b1e5e8d 100644 --- a/gitops/addons/charts/agent-sandbox/nodepool/README.md +++ b/gitops/addons/charts/agent-sandbox/nodepool/README.md @@ -15,43 +15,55 @@ were validated by a live spike (see [`docs/dark-factory` §12a](../../../../../d | `kata-mng.tf` | Terraform launch template (`cpu_options.nested_virtualization=enabled`) + MNG — use when you need the nested-virt flag eksctl can't set. `terraform validate` passes. | | `kata-mng-launch-template-userdata.mime` | The AL2023 **nodeadm MIME** userData (modprobe kvm_intel + join). Reference for either path. | -## ⚠️ Prerequisite on EKS Auto Mode: install the `vpc-cni` addon +## ✅ PROVEN END-TO-END on EKS Auto Mode (spoke-dev, 2026-07-10) -**Auto Mode clusters have NO `vpc-cni` addon** — Auto Mode's built-in networking -only applies to its own managed nodes. A self-managed MNG node will join but stay -`NotReady` with `cni plugin not initialized` until you install the standard CNI: +Kata micro-VMs **do run on an Auto Mode cluster** via a self-managed nested-virt MNG. +Verified with a pod under `runtimeClassName: kata-clh`: + +| | Value | +|---|---| +| Pod kernel (`uname -r` inside) | **`6.18.35`** — the Kata guest kernel | +| Host node kernel | `6.12.90-…amzn2023` | + +Different kernels ⇒ the pod ran in a **real VM with hardware isolation**, not a container. + +### The two Auto-Mode-specific prerequisites (the crux) + +Auto Mode's built-in networking applies ONLY to its own managed nodes. A self-managed +MNG node has **neither the CNI nor kube-proxy** that pods need — so you MUST install +both EKS addons, or pods on the kata node can't reach the API server: ``` -aws eks create-addon --cluster-name --addon-name vpc-cni --resolve-conflicts OVERWRITE +aws eks create-addon --cluster-name --addon-name vpc-cni --resolve-conflicts OVERWRITE +aws eks create-addon --cluster-name --addon-name kube-proxy --resolve-conflicts OVERWRITE ``` -`aws-node` tolerates all taints (`operator: Exists`), so it schedules onto the -tainted kata node automatically. (Discovered in live testing — lesson #4.) - -## ⚠️ Known blocker: kata-deploy vs the VPC-CNI on Auto Mode (lesson #5) - -Live testing found kata-deploy **crashloops** on a self-managed MNG node in an -Auto Mode cluster and never finishes installing the runtime. Root cause: kata-deploy -patches containerd and **restarts it**; because the VPC-CNI runs as `aws-node` pods -*on that same containerd*, the restart briefly drops node networking, and -kata-deploy's next Kubernetes API call fails (`Failed to get node ... client error -(Connect)`) → the pod exits and CrashLoopBackOffs *before* completing the install. -Disabling the experimental nydus snapshotter (`snapshotter.setup: []`) did **not** -resolve it — the containerd restart itself is the trigger. - -**Everything up to the runtime install is proven** (node joins Ready, `/dev/kvm`, -kata labels/taint, kata-deploy schedules only on the kata node). Options to finish: - -1. **Bake Kata into a custom AMI** (Packer) so no on-node containerd patch/restart is - needed at runtime — the most robust path on Auto Mode clusters. -2. **Follow openclaw's model** — a self-managed Karpenter (not Auto Mode) where the - CNI/containerd lifecycle is fully controlled and kata-deploy's restart is tolerated. -3. Investigate a kata-deploy mode that configures containerd **without a full restart**, - or pin `aws-node` to not depend on the restarted containerd during install. - -This is a **kata-deploy-on-Auto-Mode** integration issue, not a flaw in the -`agent-sandbox` chart (operator/RuntimeClasses/template/pool-manager all render and -apply fine). +- **Without `vpc-cni`** → node stays `NotReady` (`cni plugin not initialized`). +- **Without `kube-proxy`** → the node has no iptables rules for the `kubernetes.default.svc` + (172.20.0.1) service IP, so **kata-deploy crashloops** with `Failed to get node ... + client error (Connect)` — it connects to the API via the in-cluster service and times + out. This was the real blocker (NOT the containerd restart, and not the nydus + snapshotter — both were red herrings). Installing kube-proxy fixed it; kata-deploy then + reached `1/1 Running` with **zero restarts** and installed the runtime cleanly. + +Both `aws-node` and `kube-proxy` tolerate all taints (`operator: Exists`), so they land +on the tainted kata node automatically. + +### The startup-taint gate (from openclaw PR #10) + +The kata node registers with **two** taints: +- `kata=true:NoSchedule` — workload taint (only kata pods run here) +- `katacontainers.io/runtime-not-ready=true:NoSchedule` — **startup taint**; blocks all + workloads until the runtime is installed. Set via nodeadm + `--register-with-taints`. The **`kata-readiness` DaemonSet** watches kata-deploy's + `/readyz` and removes this taint once install completes — proven to work here + (`node ... untainted` in its log). + +### IAM access-entry gotcha (lesson from this test) + +If you recreate the node IAM role, its principal ID changes — **delete and recreate the +EKS access entry** (`type EC2_LINUX`) or the node's kubelet gets `Unauthorized` and never +registers. A stale access entry pointing at an old role ID is silent and confusing. ## Enablement sequence (per kata-capable cluster, e.g. spoke-dev) From 4b6bb52e66351495ef241b04842c88970a4e1cc2 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 16:50:21 -0400 Subject: [PATCH 39/67] =?UTF-8?q?docs(dark-factory):=20=C2=A712a=20?= =?UTF-8?q?=E2=80=94=20full=20Kata-on-Auto-Mode=20validation=20confirmed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real kata VM ran (guest kernel 6.18.35 vs host 6.12.90). kata-deploy 1/1 zero restarts after kube-proxy addon. Flow A Kata isolation fully proven on Auto Mode. --- docs/dark-factory/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/dark-factory/README.md b/docs/dark-factory/README.md index 4a4bb55..c0a39bb 100644 --- a/docs/dark-factory/README.md +++ b/docs/dark-factory/README.md @@ -410,8 +410,9 @@ A `c8i.4xlarge` kata MNG was created on spoke-dev, exercised, then torn down. Re |---|---| | Self-managed MNG coexists with Auto Mode? | **✅ Yes** — MNG provisioned alongside Auto Mode nodepools, no conflict; Auto Mode stayed healthy | | Nested virtualization / `/dev/kvm`? | **✅ Yes** — `/dev/kvm` present, `kvm_intel` loaded, 32 `vmx` flags, via `CpuOptions.NestedVirtualization: enabled` | -| Node joins the cluster & goes Ready? | **✅ Yes** — with the fixes below (nodeadm endpoint/CA + vpc-cni addon) | -| Kata runtime install (kata-deploy)? | **⚠️ Partial** — kata-deploy schedules on the kata node but crashloops on Auto Mode; see lesson #5 | +| Node joins the cluster & goes Ready? | **✅ Yes** — with the fixes below (nodeadm endpoint/CA + vpc-cni + kube-proxy) | +| Kata runtime install (kata-deploy)? | **✅ Yes** — `1/1`, zero restarts, once `kube-proxy` was installed | +| **Real Kata VM runs?** | **✅ YES** — pod under `kata-clh` had guest kernel `6.18.35` vs host `6.12.90` = true hardware VM isolation | ### Hard-won lessons (baked into the implementation) From f68fad29e2e4b168f1b450e53e33937144efba13 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:25:22 -0400 Subject: [PATCH 40/67] fix(agent-sandbox): SandboxTemplate has no volumeClaimTemplates (live schema) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live apply caught it: SandboxTemplate.spec supports ONLY podTemplate — the volumeClaimTemplates field belongs on the Sandbox CR, not the template ('unknown field spec.volumeClaimTemplates'). Move workspace to an emptyDir (sizeLimit) in the podTemplate. Verified: SandboxTemplate applies cleanly. --- .../templates/20-sandboxtemplate.yaml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml index 123dff2..2c1f173 100644 --- a/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml +++ b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml @@ -58,13 +58,14 @@ spec: - name: tmp mountPath: /tmp volumes: + # Ephemeral per-claim workspace. SandboxTemplate.spec only supports + # podTemplate (verified against the live CRD — it has NO + # volumeClaimTemplates field; that belongs on the Sandbox CR). Use an + # emptyDir sized by coderTemplate.workspaceSizeGi; consumers that need a + # persistent workspace across scale-to-zero set spec.volumeClaimTemplates + # on the Sandbox CR they create from this template. + - name: workspace + emptyDir: + sizeLimit: {{ .Values.coderTemplate.workspaceSizeGi }}Gi - name: tmp emptyDir: {} - volumeClaimTemplates: - - metadata: - name: workspace - spec: - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: {{ .Values.coderTemplate.workspaceSizeGi }}Gi From e973b3a331c8d0c48b493561c306ed5c6820289f Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:27:11 -0400 Subject: [PATCH 41/67] feat(agent-sandbox): enable on spoke-dev overlay (Kata-on-Auto-Mode proven) Uncomment agent_sandbox + agent_sandbox_kata on DEV now that Kata-on-Auto-Mode is validated end-to-end. ArgoCD manages the in-cluster pieces; the kata MNG + vpc-cni/kube-proxy node layer is provisioned out-of-band (documented recipe). Prod stays disabled. Verified: YAML parses. --- .../overlays/environments/dev/enabled-addons.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/gitops/overlays/environments/dev/enabled-addons.yaml b/gitops/overlays/environments/dev/enabled-addons.yaml index 4072012..0b5df4f 100644 --- a/gitops/overlays/environments/dev/enabled-addons.yaml +++ b/gitops/overlays/environments/dev/enabled-addons.yaml @@ -23,8 +23,13 @@ enabledAddons: agent_platform: true bifrost: true # Agent Sandbox capability — Kata micro-VM sandboxes + warm pool. - # DISABLED for now: spoke clusters run EKS Auto Mode + Bottlerocket, which - # cannot host Kata (no nested-virt / kvm control). Chart exists at - # gitops/addons/charts/agent-sandbox; enabling it needs a kata-capable - # nodepool strategy for Auto Mode — see docs/dark-factory (Flow A open item). - # agent_sandbox: true + # Enabled on DEV (where the Dark Factory runs). ArgoCD manages the IN-CLUSTER + # pieces (operator, CRDs, RuntimeClasses, SandboxTemplate, pool-manager). + # The kata-capable node layer is NOT GitOps-managed — it requires a + # self-managed nested-virt MNG + the vpc-cni & kube-proxy addons provisioned + # out-of-band (AWS infra ArgoCD can't create). See + # gitops/addons/charts/agent-sandbox/nodepool/README.md for the proven recipe + # (validated live on spoke-dev 2026-07-10: real kata VM, guest kernel 6.18.35). + agent_sandbox: true + # kata-deploy installs the runtime on the kata MNG nodes (separate app). + agent_sandbox_kata: true From 2feb326d846b9b2ea0f3076482f6f61430b1f486 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:39:08 -0400 Subject: [PATCH 42/67] fix(agent-sandbox): correct kata-deploy OCI chart path (drop chartNamespace) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live GitOps deploy caught it: chartNamespace made the appset build chart=kata-containers/kata-deploy → wrong OCI url (ghcr.io/.../kata-deploy-charts/kata-containers/kata-deploy). The namespace is already in chartRepository; chart must be just 'kata-deploy'. Verified: YAML parses. --- gitops/addons/bootstrap/default/addons.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index 17e5093..f316adc 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -392,8 +392,11 @@ kata-deploy: namespace: kube-system chartName: kata-deploy defaultVersion: '3.32.0' + # OCI chart at oci://ghcr.io/kata-containers/kata-deploy-charts/kata-deploy. + # Do NOT set chartNamespace — the appset would build chart=/ + # (kata-containers/kata-deploy) producing a wrong OCI path. The namespace is + # already part of chartRepository. chartRepository: 'ghcr.io/kata-containers/kata-deploy-charts' - chartNamespace: kata-containers annotationsAppSet: argocd.argoproj.io/sync-wave: '1' selector: From 84173e401f96011701eb66a13c6d3968d0b0dfcb Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:41:26 -0400 Subject: [PATCH 43/67] fix(agent-sandbox): pool-manager image needs kubectl+jq (was aws-cli, has neither) Live GitOps deploy caught it: the pool-manager CronJob used aws-cli image which lacks kubectl/jq, so the script exited immediately (BackoffLimitExceeded). Switch to alpine/k8s:1.31.0 (bundles kubectl + jq + helm). Verified: YAML + render. --- gitops/addons/charts/agent-sandbox/values.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/values.yaml b/gitops/addons/charts/agent-sandbox/values.yaml index ca90615..4b191f9 100644 --- a/gitops/addons/charts/agent-sandbox/values.yaml +++ b/gitops/addons/charts/agent-sandbox/values.yaml @@ -60,8 +60,10 @@ warmPool: # ── Pool-manager controller ────────────────────────────────────────────────── poolManager: - # Small controller image (kubectl + jq loop) that reconciles the warm buffer. - image: public.ecr.aws/aws-cli/aws-cli:2.17.0 + # Image for the reconcile loop — MUST have both kubectl AND jq (the script + # exits early if kubectl is missing). aws-cli image has neither; use an + # alpine/k8s image that bundles kubectl + jq + helm. + image: alpine/k8s:1.31.0 # How often the reconcile/reaper loop runs. intervalSeconds: 60 resources: From 341553fd71558b68c7afacfb305be2fc5c38f091 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:52:52 -0400 Subject: [PATCH 44/67] feat(agent-sandbox): vendor upstream agent-sandbox v0.5.1 install manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the upstream v0.5.1 manifest.yaml (operator Deployment + CRDs + RBAC + webhooks) and extensions.yaml (SandboxClaim/SandboxTemplate/SandboxWarmPool CRDs). v0.5.0+ is required for the native SandboxWarmPool + SandboxClaim reconcilers — live testing proved v0.1.0 (openclaw bundle) lacks them (operator only ran the Sandbox controller). Source: kubernetes-sigs/agent-sandbox. --- .../agent-sandbox-v0.5.1-extensions.yaml | 8999 +++++++++++++++++ .../agent-sandbox-v0.5.1-manifest.yaml | 8252 +++++++++++++++ 2 files changed, 17251 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml create mode 100644 gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml diff --git a/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml b/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml new file mode 100644 index 0000000..779e970 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml @@ -0,0 +1,8999 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.21.0 + name: sandboxclaims.extensions.agents.x-k8s.io +spec: + group: extensions.agents.x-k8s.io + names: + kind: SandboxClaim + listKind: SandboxClaimList + plural: sandboxclaims + shortNames: + - sandboxclaim + singular: sandboxclaim + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.sandbox.name + name: Sandbox + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + additionalPodMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + env: + items: + properties: + containerName: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + lifecycle: + properties: + shutdownPolicy: + default: Retain + enum: + - Delete + - DeleteForeground + - Retain + type: string + shutdownTime: + format: date-time + type: string + ttlSecondsAfterFinished: + format: int32 + minimum: 0 + type: integer + type: object + volumeClaimTemplates: + items: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: array + x-kubernetes-list-type: atomic + warmPoolRef: + properties: + name: + type: string + required: + - name + type: object + required: + - warmPoolRef + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - 'True' + - 'False' + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + sandbox: + properties: + name: + type: string + podIPs: + items: + type: string + type: array + type: object + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - deprecated: true + deprecationWarning: extensions.agents.x-k8s.io/v1alpha1 SandboxClaim is deprecated; + use extensions.agents.x-k8s.io/v1beta1 SandboxClaim instead + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + additionalPodMetadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + env: + items: + properties: + containerName: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + lifecycle: + properties: + shutdownPolicy: + default: Retain + enum: + - Delete + - DeleteForeground + - Retain + type: string + shutdownTime: + format: date-time + type: string + ttlSecondsAfterFinished: + format: int32 + minimum: 0 + type: integer + type: object + sandboxTemplateRef: + properties: + name: + type: string + required: + - name + type: object + warmpool: + default: default + type: string + required: + - sandboxTemplateRef + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - 'True' + - 'False' + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + sandbox: + properties: + name: + type: string + podIPs: + items: + type: string + type: array + type: object + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: agent-sandbox-webhook-service + namespace: agent-sandbox-system + path: /convert +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.21.0 + name: sandboxtemplates.extensions.agents.x-k8s.io +spec: + group: extensions.agents.x-k8s.io + names: + kind: SandboxTemplate + listKind: SandboxTemplateList + plural: sandboxtemplates + shortNames: + - sandboxtemplate + singular: sandboxtemplate + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + envVarsInjectionPolicy: + default: Disallowed + enum: + - Allowed + - Overrides + - Disallowed + type: string + networkPolicy: + properties: + egress: + items: + properties: + ports: + items: + properties: + endPort: + format: int32 + type: integer + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + protocol: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + to: + items: + properties: + ipBlock: + properties: + cidr: + type: string + except: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - cidr + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + ingress: + items: + properties: + from: + items: + properties: + ipBlock: + properties: + cidr: + type: string + except: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - cidr + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + ports: + items: + properties: + endPort: + format: int32 + type: integer + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + protocol: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + type: object + networkPolicyManagement: + default: Managed + enum: + - Managed + - Unmanaged + type: string + podTemplate: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + hostnameOverride: + type: string + imagePullSecrets: + items: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + schedulingGroup: + properties: + podGroupName: + type: string + type: object + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + userAnnotations: + additionalProperties: + type: string + type: object + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - containers + type: object + required: + - spec + type: object + service: + type: boolean + volumeClaimTemplates: + items: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: array + x-kubernetes-list-type: atomic + volumeClaimTemplatesPolicy: + default: Disallowed + enum: + - Disallowed + - Allowed + - Overrides + type: string + required: + - podTemplate + type: object + required: + - spec + type: object + served: true + storage: true + - deprecated: true + deprecationWarning: extensions.agents.x-k8s.io/v1alpha1 SandboxTemplate is deprecated; + use extensions.agents.x-k8s.io/v1beta1 SandboxTemplate instead + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + envVarsInjectionPolicy: + default: Disallowed + enum: + - Allowed + - Overrides + - Disallowed + type: string + networkPolicy: + properties: + egress: + items: + properties: + ports: + items: + properties: + endPort: + format: int32 + type: integer + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + protocol: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + to: + items: + properties: + ipBlock: + properties: + cidr: + type: string + except: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - cidr + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + ingress: + items: + properties: + from: + items: + properties: + ipBlock: + properties: + cidr: + type: string + except: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - cidr + type: object + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + podSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + ports: + items: + properties: + endPort: + format: int32 + type: integer + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + protocol: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: array + type: object + networkPolicyManagement: + default: Managed + enum: + - Managed + - Unmanaged + type: string + podTemplate: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + hostnameOverride: + type: string + imagePullSecrets: + items: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + schedulingGroup: + properties: + podGroupName: + type: string + type: object + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + userAnnotations: + additionalProperties: + type: string + type: object + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - containers + type: object + required: + - spec + type: object + service: + type: boolean + volumeClaimTemplates: + items: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: array + x-kubernetes-list-type: atomic + required: + - podTemplate + type: object + required: + - spec + type: object + served: true + storage: false + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: agent-sandbox-webhook-service + namespace: agent-sandbox-system + path: /convert +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.21.0 + name: sandboxwarmpools.extensions.agents.x-k8s.io +spec: + group: extensions.agents.x-k8s.io + names: + kind: SandboxWarmPool + listKind: SandboxWarmPoolList + plural: sandboxwarmpools + shortNames: + - swp + singular: sandboxwarmpool + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.readyReplicas + name: Ready + type: integer + - jsonPath: .spec.replicas + name: Desired + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + replicas: + default: 1 + format: int32 + minimum: 0 + type: integer + sandboxTemplateRef: + properties: + name: + type: string + required: + - name + type: object + updateStrategy: + properties: + type: + default: OnReplenish + enum: + - Recreate + - OnReplenish + type: string + type: object + required: + - sandboxTemplateRef + type: object + status: + properties: + readyReplicas: + format: int32 + type: integer + replicas: + format: int32 + type: integer + selector: + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + status: {} + - additionalPrinterColumns: + - jsonPath: .status.readyReplicas + name: Ready + type: integer + - jsonPath: .spec.replicas + name: Desired + type: integer + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + deprecationWarning: extensions.agents.x-k8s.io/v1alpha1 SandboxWarmPool is deprecated; + use extensions.agents.x-k8s.io/v1beta1 SandboxWarmPool instead + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + replicas: + format: int32 + minimum: 0 + type: integer + sandboxTemplateRef: + properties: + name: + type: string + required: + - name + type: object + updateStrategy: + properties: + type: + default: OnReplenish + enum: + - Recreate + - OnReplenish + type: string + type: object + required: + - replicas + - sandboxTemplateRef + type: object + status: + properties: + readyReplicas: + format: int32 + type: integer + replicas: + format: int32 + type: integer + selector: + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: agent-sandbox-webhook-service + namespace: agent-sandbox-system + path: /convert +--- +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: agent-sandbox-controller-extensions +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + - events.k8s.io + resources: + - events + verbs: + - create + - patch + - update +- apiGroups: + - agents.x-k8s.io + resources: + - sandboxes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - extensions.agents.x-k8s.io + resources: + - sandboxclaims + - sandboxtemplates + - sandboxwarmpools + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - extensions.agents.x-k8s.io + resources: + - sandboxclaims/finalizers + - sandboxclaims/status + - sandboxtemplates/finalizers + - sandboxwarmpools/finalizers + - sandboxwarmpools/status + verbs: + - get + - patch + - update +- apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system + labels: + app: agent-sandbox-controller +spec: + replicas: 1 + selector: + matchLabels: + app: agent-sandbox-controller + template: + metadata: + labels: + app: agent-sandbox-controller + spec: + serviceAccountName: agent-sandbox-controller + containers: + - name: agent-sandbox-controller + image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.5.1 + args: + - "--leader-elect=true" + - "--extensions" + ports: + - name: metrics + containerPort: 8080 + protocol: TCP + - name: healthz + containerPort: 8081 + protocol: TCP + volumeMounts: + - name: config-volume + mountPath: /etc/sandbox-config + readOnly: true + volumes: + - name: config-volume + configMap: + name: agent-sandbox-config + optional: true + + +--- +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: agent-sandbox-controller-extensions +subjects: +- kind: ServiceAccount + name: agent-sandbox-controller + namespace: agent-sandbox-system +roleRef: + kind: ClusterRole + name: agent-sandbox-controller-extensions + apiGroup: rbac.authorization.k8s.io +--- diff --git a/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml b/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml new file mode 100644 index 0000000..a799790 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml @@ -0,0 +1,8252 @@ +--- +kind: Namespace +apiVersion: v1 +metadata: + name: agent-sandbox-system + +--- + +kind: ServiceAccount +apiVersion: v1 +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system + labels: + app: agent-sandbox-controller + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: agent-sandbox-controller +subjects: +- kind: ServiceAccount + name: agent-sandbox-controller + namespace: agent-sandbox-system +roleRef: + kind: ClusterRole + name: agent-sandbox-controller + apiGroup: rbac.authorization.k8s.io + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create +- apiGroups: + - "" + resourceNames: + - agent-sandbox-webhook-certs + resources: + - secrets + verbs: + - get + - patch + - update + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system +subjects: +- kind: ServiceAccount + name: agent-sandbox-controller + namespace: agent-sandbox-system +roleRef: + kind: Role + name: agent-sandbox-controller + apiGroup: rbac.authorization.k8s.io + +--- + +kind: Service +apiVersion: v1 +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system + labels: + app: agent-sandbox-controller +spec: + selector: + app: agent-sandbox-controller + ports: + - name: metrics + port: 8080 + targetPort: metrics + protocol: TCP + +--- + +kind: Deployment +apiVersion: apps/v1 +metadata: + name: agent-sandbox-controller + namespace: agent-sandbox-system + labels: + app: agent-sandbox-controller +spec: + replicas: 1 + selector: + matchLabels: + app: agent-sandbox-controller + template: + metadata: + labels: + app: agent-sandbox-controller + spec: + serviceAccountName: agent-sandbox-controller + containers: + - name: agent-sandbox-controller + image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.5.1 + args: + - --leader-elect=true + ports: + - name: metrics + containerPort: 8080 + protocol: TCP + - name: healthz + containerPort: 8081 + protocol: TCP + - name: webhook + containerPort: 9443 + protocol: TCP + +--- + +kind: Service +apiVersion: v1 +metadata: + name: agent-sandbox-webhook-service + namespace: agent-sandbox-system +spec: + selector: + app: agent-sandbox-controller + ports: + - name: webhook + port: 443 + targetPort: 9443 + protocol: TCP + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.21.0 + name: sandboxes.agents.x-k8s.io +spec: + group: agents.x-k8s.io + names: + kind: Sandbox + listKind: SandboxList + plural: sandboxes + shortNames: + - sandbox + singular: sandbox + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + operatingMode: + default: Running + enum: + - Running + - Suspended + type: string + podTemplate: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + hostnameOverride: + type: string + imagePullSecrets: + items: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + schedulingGroup: + properties: + podGroupName: + type: string + type: object + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + userAnnotations: + additionalProperties: + type: string + type: object + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - containers + type: object + required: + - spec + type: object + service: + type: boolean + shutdownPolicy: + default: Retain + enum: + - Delete + - Retain + type: string + shutdownTime: + format: date-time + type: string + volumeClaimTemplates: + items: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: array + x-kubernetes-list-type: atomic + required: + - podTemplate + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - 'True' + - 'False' + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + nodeName: + type: string + podIPs: + items: + type: string + type: array + selector: + type: string + service: + type: string + serviceFQDN: + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - deprecated: true + deprecationWarning: agents.x-k8s.io/v1alpha1 Sandbox is deprecated; use agents.x-k8s.io/v1beta1 + Sandbox instead + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + podTemplate: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + hostnameOverride: + type: string + imagePullSecrets: + items: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + properties: + key: + type: string + optional: + default: false + type: boolean + path: + type: string + volumeName: + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: '' + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + restartPolicyRules: + items: + properties: + action: + type: string + exitCodes: + properties: + operator: + type: string + values: + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: '' + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + schedulingGroup: + properties: + podGroupName: + type: string + type: object + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podCertificate: + properties: + certificateChainPath: + type: string + credentialBundlePath: + type: string + keyPath: + type: string + keyType: + type: string + maxExpirationSeconds: + format: int32 + type: integer + signerName: + type: string + userAnnotations: + additionalProperties: + type: string + type: object + required: + - keyType + - signerName + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: '' + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: '' + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + required: + - containers + type: object + required: + - spec + type: object + replicas: + default: 1 + format: int32 + maximum: 1 + minimum: 0 + type: integer + service: + type: boolean + shutdownPolicy: + default: Retain + enum: + - Delete + - Retain + type: string + shutdownTime: + format: date-time + type: string + volumeClaimTemplates: + items: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + name: + type: string + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: array + x-kubernetes-list-type: atomic + required: + - podTemplate + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + maxLength: 32768 + type: string + observedGeneration: + format: int64 + minimum: 0 + type: integer + reason: + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + enum: + - 'True' + - 'False' + - Unknown + type: string + type: + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + podIPs: + items: + type: string + type: array + replicas: + format: int32 + minimum: 0 + type: integer + selector: + type: string + service: + type: string + serviceFQDN: + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + scale: + labelSelectorPath: .status.selector + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: agent-sandbox-webhook-service + namespace: agent-sandbox-system + path: /convert +--- +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: agent-sandbox-controller +rules: +- apiGroups: + - "" + resources: + - persistentvolumeclaims + - pods + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - agents.x-k8s.io + resources: + - sandboxes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - agents.x-k8s.io + resources: + - sandboxes/finalizers + - sandboxes/status + verbs: + - get + - patch + - update +- apiGroups: + - apiextensions.k8s.io + resourceNames: + - sandboxclaims.extensions.agents.x-k8s.io + - sandboxes.agents.x-k8s.io + - sandboxtemplates.extensions.agents.x-k8s.io + - sandboxwarmpools.extensions.agents.x-k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - patch + - update +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - patch +--- From f36326e3f5e39ea8f52ada82150aeafb03c5a8f5 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:53:05 -0400 Subject: [PATCH 45/67] refactor(agent-sandbox): drop hand-written operator (use vendored v0.5.1 upstream) The v0.1.0 operator we hand-wrote only reconciled Sandbox CRs (no warm pool). Replaced by the vendored upstream v0.5.1 manifest which includes the full operator + webhooks + SandboxClaim/WarmPool reconcilers. --- .../agent-sandbox/templates/05-operator.yaml | 106 ------------------ 1 file changed, 106 deletions(-) delete mode 100644 gitops/addons/charts/agent-sandbox/templates/05-operator.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml b/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml deleted file mode 100644 index 181e098..0000000 --- a/gitops/addons/charts/agent-sandbox/templates/05-operator.yaml +++ /dev/null @@ -1,106 +0,0 @@ -{{- if .Values.operator.installCRDs }} -{{- /* -Agent Sandbox operator (agents.x-k8s.io). Installs the controller that -materializes a Kata-VM Pod + Service (+ PVCs) per Sandbox CR and reports -status.serviceFQDN. - -NOTE ON CRDs: the Sandbox / SandboxTemplate / SandboxClaim CRDs are large -(~4k lines of OpenAPI schema) and are installed from the upstream operator -bundle, not vendored here. In this monorepo they are applied at an earlier -sync-wave (see gitops wiring) via the upstream manifest at - public.ecr.aws/t6v6o5d5/agent-sandbox:v0.1.0 -This template provides the controller runtime (SA + ClusterRole + StatefulSet -+ Service); it assumes the CRDs already exist. Set operator.installCRDs=false -if a newer operator on the cluster already manages both. -*/ -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: agent-sandbox-controller - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: agent-sandbox-controller - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -rules: - - apiGroups: ["agents.x-k8s.io"] - resources: ["sandboxes", "sandboxes/status", "sandboxes/scale"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: ["extensions.agents.x-k8s.io"] - resources: ["sandboxtemplates", "sandboxclaims", "sandboxclaims/status"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - - apiGroups: [""] - resources: ["pods", "services", "persistentvolumeclaims"] - verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: agent-sandbox-controller - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -subjects: - - kind: ServiceAccount - name: agent-sandbox-controller - namespace: {{ include "agent-sandbox.namespace" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: agent-sandbox-controller ---- -apiVersion: v1 -kind: Service -metadata: - name: agent-sandbox-controller - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -spec: - selector: - app.kubernetes.io/name: agent-sandbox - agent-sandbox.io/component: controller - ports: - - port: 80 - targetPort: 8080 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: agent-sandbox-controller - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -spec: - serviceName: agent-sandbox-controller - replicas: {{ .Values.operator.replicas }} - selector: - matchLabels: - app.kubernetes.io/name: agent-sandbox - agent-sandbox.io/component: controller - template: - metadata: - labels: - {{- include "agent-sandbox.labels" . | nindent 8 }} - agent-sandbox.io/component: controller - spec: - serviceAccountName: agent-sandbox-controller - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - containers: - - name: controller - image: {{ .Values.operator.image }} - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - ports: - - name: http - containerPort: 8080 -{{- end }} From 14d4f8e7e12d31493f4d81d8f6adcf268ab4ab66 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:53:06 -0400 Subject: [PATCH 46/67] refactor(agent-sandbox): drop custom pool-manager (use native SandboxWarmPool) v0.5.0+ ships a native SandboxWarmPool CR (spec: replicas + sandboxTemplateRef) reconciled by the operator. Our bash CronJob pool-manager was redundant AND buggy (aws-cli image lacked kubectl/jq; SandboxClaim adoption needs the v0.5 reconciler). Replace with a SandboxWarmPool CR (next commit). --- .../templates/40-poolmanager-rbac.yaml | 51 ------- .../templates/41-poolmanager-cronjob.yaml | 130 ------------------ 2 files changed, 181 deletions(-) delete mode 100644 gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml delete mode 100644 gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml b/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml deleted file mode 100644 index 4e83306..0000000 --- a/gitops/addons/charts/agent-sandbox/templates/40-poolmanager-rbac.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if .Values.warmPool.enabled }} -{{- /* -RBAC for the pool-manager: narrowly scoped to Sandboxes/PVCs/Services in the -capability namespace only. It maintains the warm buffer and reaps idle/expired -sandboxes — it never touches cluster-wide resources or other namespaces. -*/ -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: agent-sandbox-pool-manager - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: agent-sandbox-pool-manager - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -rules: - - apiGroups: ["agents.x-k8s.io"] - resources: ["sandboxes"] - verbs: ["get", "list", "watch", "create", "patch", "delete"] - - apiGroups: ["agents.x-k8s.io"] - resources: ["sandboxes/scale"] - verbs: ["get", "patch", "update"] - - apiGroups: ["extensions.agents.x-k8s.io"] - resources: ["sandboxtemplates", "sandboxclaims"] - verbs: ["get", "list", "watch"] - - apiGroups: [""] - resources: ["persistentvolumeclaims", "services"] - verbs: ["get", "list", "delete"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: agent-sandbox-pool-manager - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -subjects: - - kind: ServiceAccount - name: agent-sandbox-pool-manager - namespace: {{ include "agent-sandbox.namespace" . }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: agent-sandbox-pool-manager -{{- end }} diff --git a/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml b/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml deleted file mode 100644 index 8261ce9..0000000 --- a/gitops/addons/charts/agent-sandbox/templates/41-poolmanager-cronjob.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{- if .Values.warmPool.enabled }} -{{- /* -Pool-manager: a CronJob that reconciles the warm buffer each interval. - 1. REFILL — if idle sandboxes < targetIdle, create SandboxClaims to top up. - 2. SCALE-TO-ZERO — idle sandboxes past idleScaleToZeroSeconds → replicas:0. - 3. REAP — claimed sandboxes with no activity past reapAfterSeconds → delete. -Idle vs claimed is tracked by the label agent-sandbox.io/state and the -agent-sandbox.io/last-seen annotation, both stamped by the consumer on claim. -A CronJob (not a Deployment) keeps the controller dependency-free and cheap; -swap for a real controller later if reconcile latency matters. -*/ -}} -apiVersion: batch/v1 -kind: CronJob -metadata: - name: agent-sandbox-pool-manager - namespace: {{ include "agent-sandbox.namespace" . }} - labels: - {{- include "agent-sandbox.labels" . | nindent 4 }} -spec: - schedule: "* * * * *" # every minute; loop below honors intervalSeconds - concurrencyPolicy: Forbid - successfulJobsHistoryLimit: 1 - failedJobsHistoryLimit: 2 - jobTemplate: - spec: - backoffLimit: 1 - template: - metadata: - labels: - {{- include "agent-sandbox.selectorLabels" . | nindent 12 }} - spec: - serviceAccountName: agent-sandbox-pool-manager - restartPolicy: OnFailure - securityContext: - runAsNonRoot: true - runAsUser: 1000 - seccompProfile: - type: RuntimeDefault - containers: - - name: pool-manager - image: {{ .Values.poolManager.image }} - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: ["ALL"] - env: - - name: NS - value: {{ include "agent-sandbox.namespace" . }} - - name: TARGET_IDLE - value: {{ .Values.warmPool.targetIdle | quote }} - - name: IDLE_SCALE_TO_ZERO_SECONDS - value: {{ .Values.warmPool.idleScaleToZeroSeconds | quote }} - - name: REAP_AFTER_SECONDS - value: {{ .Values.warmPool.reapAfterSeconds | quote }} - - name: TEMPLATE_NAME - value: {{ .Values.warmPool.templateName }} - resources: - {{- toYaml .Values.poolManager.resources | nindent 16 }} - volumeMounts: - - name: tmp - mountPath: /tmp - command: - - /bin/sh - - -c - - | - set -eu - command -v kubectl >/dev/null 2>&1 || { echo "kubectl required in image"; exit 1; } - now=$(date -u +%s) - - idle=$(kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ - -l 'agent-sandbox.io/state=idle' -o name 2>/dev/null | wc -l | tr -d ' ') - echo "warm pool: $idle idle / target $TARGET_IDLE" - - # 1. REFILL — top up idle sandboxes to the target buffer. - i="$idle" - while [ "$i" -lt "$TARGET_IDLE" ]; do - n="coder-idle-$(date -u +%s)-$i" - cat </dev/null - apiVersion: extensions.agents.x-k8s.io/v1alpha1 - kind: SandboxClaim - metadata: - name: $n - namespace: $NS - labels: - agent-sandbox.io/state: idle - spec: - sandboxTemplateRef: - name: $TEMPLATE_NAME - EOF - echo "refill: created idle claim $n" - i=$((i+1)) - done - - # 2. SCALE-TO-ZERO — idle sandboxes past the idle TTL scale to - # replicas:0 (PVC retained), resumed on demand by the consumer. - if [ "${IDLE_SCALE_TO_ZERO_SECONDS}" -gt 0 ]; then - kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ - -l 'agent-sandbox.io/state=idle' -o json 2>/dev/null \ - | jq -r --argjson now "$now" --argjson ttl "$IDLE_SCALE_TO_ZERO_SECONDS" ' - .items[] - | select((.spec.replicas // 1) > 0) - | select(((.metadata.annotations["agent-sandbox.io/last-seen"] // "0") | fromdateiso8601? // 0) < ($now - $ttl)) - | .metadata.name' \ - | while read -r s; do - [ -n "$s" ] || continue - kubectl scale sandbox.agents.x-k8s.io "$s" -n "$NS" --replicas=0 >/dev/null 2>&1 \ - && echo "scale-to-zero: paused idle $s" - done - fi - - # 3. REAP — claimed sandboxes with no activity past the hard TTL - # are deleted (safety net for crashed/abandoned consumers). - kubectl get sandboxes.agents.x-k8s.io -n "$NS" \ - -l 'agent-sandbox.io/state=claimed' -o json 2>/dev/null \ - | jq -r --argjson now "$now" --argjson ttl "$REAP_AFTER_SECONDS" ' - .items[] - | select(((.metadata.annotations["agent-sandbox.io/last-seen"] // "0") | fromdateiso8601? // 0) < ($now - $ttl)) - | .metadata.name' \ - | while read -r s; do - [ -n "$s" ] || continue - kubectl delete sandbox.agents.x-k8s.io "$s" -n "$NS" --ignore-not-found >/dev/null 2>&1 \ - && echo "reap: deleted expired claimed $s" - done - - echo "pool-manager reconcile complete" - volumes: - - name: tmp - emptyDir: {} -{{- end }} From b9e2df9c68f7bb31e971129586217fa75828402f Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:53:25 -0400 Subject: [PATCH 47/67] feat(agent-sandbox): add native SandboxWarmPool CR (replaces pool-manager) Declares a SandboxWarmPool (replicas=targetIdle, sandboxTemplateRef) the v0.5.1 operator reconciles to keep the warm buffer. Gated by warmPool.enabled. Verified: renders. --- .../templates/40-sandboxwarmpool.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml b/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml new file mode 100644 index 0000000..e0dbd2f --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml @@ -0,0 +1,21 @@ +{{- if .Values.warmPool.enabled }} +{{- /* +Native SandboxWarmPool (operator v0.5.0+). The operator keeps `replicas` idle +sandboxes pre-warmed from the referenced SandboxTemplate; a consumer (the Dark +Factory) binds one via a SandboxClaim and the operator refills the buffer. This +replaces the custom pool-manager CronJob — the warm pool is now a first-class +operator primitive (requires the vendored v0.5.1 upstream, NOT v0.1.0). +*/ -}} +apiVersion: extensions.agents.x-k8s.io/v1alpha1 +kind: SandboxWarmPool +metadata: + name: {{ .Values.warmPool.name | default "coder-warmpool" }} + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + # Target number of pre-warmed idle sandboxes (the warm buffer). + replicas: {{ .Values.warmPool.targetIdle }} + sandboxTemplateRef: + name: {{ .Values.warmPool.templateName }} +{{- end }} From 36833f6628bff9540f64fe6a45cb3eb12b234247 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:54:14 -0400 Subject: [PATCH 48/67] feat(agent-sandbox): add kata-readiness DaemonSet (removes startup taint) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from openclaw PR #10 — the missing piece our chart lacked. Waits for kata-deploy Ready on each kata node, then removes the runtime-not-ready startup taint so kata sandboxes can schedule. Without it, Sandbox pods stay Pending (live-test finding). Verified: renders + chart lints clean. --- .../templates/15-kata-readiness.yaml | 113 ++++++++++++++++++ .../addons/charts/agent-sandbox/values.yaml | 7 ++ 2 files changed, 120 insertions(+) create mode 100644 gitops/addons/charts/agent-sandbox/templates/15-kata-readiness.yaml diff --git a/gitops/addons/charts/agent-sandbox/templates/15-kata-readiness.yaml b/gitops/addons/charts/agent-sandbox/templates/15-kata-readiness.yaml new file mode 100644 index 0000000..91f2b82 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/templates/15-kata-readiness.yaml @@ -0,0 +1,113 @@ +{{- if .Values.kataReadiness.enabled }} +{{- /* +kata-readiness — removes the katacontainers.io/runtime-not-ready STARTUP TAINT +once kata-deploy finishes installing the runtime on a node. + +Why needed (live-test lesson): kata nodes register with a runtime-not-ready +startup taint so no workload binds before the runtime exists. kata-deploy does +NOT remove that taint itself. This DaemonSet watches the kata-deploy pod on its +node reach Ready (its /readyz flips 503→200 only after install completes), then +removes the taint so kata sandboxes can schedule. Ported from +eks-platform-openclaw PR #10. +*/ -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kata-readiness + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: agent-sandbox-kata-readiness + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +rules: + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "patch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: agent-sandbox-kata-readiness + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: kata-readiness + namespace: {{ include "agent-sandbox.namespace" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: agent-sandbox-kata-readiness +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kata-readiness + namespace: {{ include "agent-sandbox.namespace" . }} + labels: + {{- include "agent-sandbox.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: kata-readiness + template: + metadata: + labels: + app: kata-readiness + {{- include "agent-sandbox.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: kata-readiness + # Tolerate everything so it lands BEFORE the runtime is ready — including + # the kata workload taint and the runtime-not-ready startup taint it removes. + tolerations: + - operator: Exists + # Static label present from node birth (kata-deploy emits + # katacontainers.io/kata-runtime only after install, so we can't select on it). + nodeSelector: + kata-enabled: "true" + securityContext: + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: kata-readiness + image: {{ .Values.kataReadiness.image }} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + env: + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + command: + - /bin/sh + - -c + - | + set -eu + echo "[kata-readiness] node=${NODE_NAME}: waiting for kata-deploy Ready..." + until [ "$(kubectl get pods -n kube-system -l name=kata-deploy \ + --field-selector "spec.nodeName=${NODE_NAME}" \ + -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}')" = "True" ]; do + sleep 5 + done + echo "[kata-readiness] kata-deploy Ready; removing runtime-not-ready taint..." + kubectl taint node "${NODE_NAME}" katacontainers.io/runtime-not-ready:NoSchedule- || true + echo "[kata-readiness] node ${NODE_NAME} ready for kata workloads." + sleep infinity + resources: + requests: + cpu: 5m + memory: 32Mi +{{- end }} diff --git a/gitops/addons/charts/agent-sandbox/values.yaml b/gitops/addons/charts/agent-sandbox/values.yaml index 4b191f9..05b8248 100644 --- a/gitops/addons/charts/agent-sandbox/values.yaml +++ b/gitops/addons/charts/agent-sandbox/values.yaml @@ -43,6 +43,13 @@ kata: value: "true" effect: NoSchedule +# ── kata-readiness ─────────────────────────────────────────────────────────── +# Removes the runtime-not-ready startup taint once kata-deploy finishes on a +# node. Required whenever nodes carry that startup taint (the kata MNG does). +kataReadiness: + enabled: true + image: alpine/k8s:1.31.0 # needs kubectl + # ── Warm pool ──────────────────────────────────────────────────────────────── warmPool: enabled: true From e468e19e40e4b01a30f46aac34fcc032281bcc53 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 17:56:02 -0400 Subject: [PATCH 49/67] =?UTF-8?q?fix(agent-sandbox):=20namespace=20PSS=20r?= =?UTF-8?q?estricted=E2=86=92baseline=20(was=20blocking=20the=20operator)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live test: PSS restricted on the namespace blocked the upstream v0.5.1 operator pod (not restricted-compliant) — Deployment stuck 0/1. The namespace hosts the operator + kata-readiness too, not just coder pods. Coder isolation comes from the Kata VM boundary + the SandboxTemplate's restricted securityContext, not namespace PSS. Set enforce=baseline (audit/warn stay restricted). --- .../charts/agent-sandbox/templates/00-namespace.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml b/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml index 31e3c4e..f62077c 100644 --- a/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml +++ b/gitops/addons/charts/agent-sandbox/templates/00-namespace.yaml @@ -4,8 +4,13 @@ metadata: name: {{ include "agent-sandbox.namespace" . }} labels: {{- include "agent-sandbox.labels" . | nindent 4 }} - # Kata sandboxes run untrusted, LLM-generated code — enforce a restricted - # Pod Security Standard on the namespace as defense in depth. - pod-security.kubernetes.io/enforce: restricted + # PSS = baseline (NOT restricted). This namespace hosts BOTH the coder + # sandboxes AND the agent-sandbox operator/kata-readiness — and the upstream + # operator + kata tooling are not restricted-compliant (they'd be blocked). + # The coder sandboxes get their real isolation from the KATA micro-VM + # boundary + the restricted securityContext baked into the SandboxTemplate + # pod spec — not from namespace PSS. (Live-test lesson: restricted here + # blocks the v0.5.1 controller pod entirely.) + pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/warn: restricted From 7cef4f34b5758ec979d35001be8a169d38dd04ca Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 18:00:46 -0400 Subject: [PATCH 50/67] fix(agent-sandbox): use v1beta1 for SandboxTemplate + SandboxWarmPool Operator v0.5.1 deprecates v1alpha1 for these CRDs. Bump to v1beta1 (schema compatible: podTemplate / replicas+sandboxTemplateRef). Verified live: warm pool reconciles 3/3 kata VMs, SandboxClaim(warmPoolRef) binds instantly + pool refills. Guest kernel 6.18.35 vs host 6.12.90 = real VM isolation. --- .../charts/agent-sandbox/templates/20-sandboxtemplate.yaml | 2 +- .../charts/agent-sandbox/templates/40-sandboxwarmpool.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml index 2c1f173..5a56cec 100644 --- a/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml +++ b/gitops/addons/charts/agent-sandbox/templates/20-sandboxtemplate.yaml @@ -9,7 +9,7 @@ LLM-generated code: The concrete coder image (claude-code | kiro) and per-claim secrets are patched in by the consumer when it binds a SandboxClaim. */ -}} -apiVersion: extensions.agents.x-k8s.io/v1alpha1 +apiVersion: extensions.agents.x-k8s.io/v1beta1 kind: SandboxTemplate metadata: name: {{ .Values.warmPool.templateName }} diff --git a/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml b/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml index e0dbd2f..c58aaff 100644 --- a/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml +++ b/gitops/addons/charts/agent-sandbox/templates/40-sandboxwarmpool.yaml @@ -6,7 +6,7 @@ Factory) binds one via a SandboxClaim and the operator refills the buffer. This replaces the custom pool-manager CronJob — the warm pool is now a first-class operator primitive (requires the vendored v0.5.1 upstream, NOT v0.1.0). */ -}} -apiVersion: extensions.agents.x-k8s.io/v1alpha1 +apiVersion: extensions.agents.x-k8s.io/v1beta1 kind: SandboxWarmPool metadata: name: {{ .Values.warmPool.name | default "coder-warmpool" }} From d7f5d32924fffb4bd92adb63105740fee2ed5a8a Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 18:01:42 -0400 Subject: [PATCH 51/67] feat(agent-sandbox): add operator as GitOps app + fix sync-wave ordering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add agent-sandbox-operator app (vendored v0.5.1 upstream, directory source, sync-wave 0) so the operator + CRDs deploy via GitOps — previously applied manually. Correct ordering: operator (wave 0) → kata-deploy runtime (wave 1) → agent-sandbox chart CRs (wave 2). This is the order Flow B builds on. Verified: YAML parses. --- gitops/addons/bootstrap/default/addons.yaml | 35 +++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index f316adc..8811656 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -359,12 +359,35 @@ oam-agent-components: awsRegion: '{{.metadata.annotations.aws_region}}' clusterName: '{{.metadata.annotations.aws_cluster_name}}' -# Agent Sandbox — hardware-isolated Kata micro-VM sandboxes (agents.x-k8s.io -# Sandbox CRD) with a pre-warmed pool kept ready by a pool-manager controller. -# The reusable isolation substrate the Dark Factory coding pipeline (and other -# agent workloads) claim on demand. Sync-wave 2: after the kata runtime is -# installed on nodes (base platform), before agentic workloads that claim a -# sandbox. +# Agent Sandbox OPERATOR (upstream agent-sandbox v0.5.1) — the controller + +# Sandbox/SandboxClaim/SandboxTemplate/SandboxWarmPool CRDs + webhooks. Vendored +# manifest applied directly (it's a self-contained install; the ~400KB CRD set +# is too large for a Helm-templated chart). ServerSideApply + Replace handle the +# oversized CRDs. Sync-wave 0: CRDs + operator MUST exist before the kata-deploy +# runtime (wave 1) and the agent-sandbox chart CRs (wave 2). +agent-sandbox-operator: + enabled: true + namespace: agent-sandbox-system + defaultVersion: '0.5.1' + path: 'gitops/addons/charts/agent-sandbox/upstream' + annotationsAppSet: + argocd.argoproj.io/sync-wave: '0' + syncPolicyAppSet: + preserveResourcesOnDeletion: false + # Directory source of raw manifests, not a Helm chart. + directory: + recurse: true + selector: + matchExpressions: + - key: enable_agent_sandbox + operator: In + values: ['true'] + +# Agent Sandbox capability chart — RuntimeClasses, kata-readiness (removes the +# runtime-not-ready startup taint), coder SandboxTemplate, SandboxWarmPool, and +# the egress NetworkPolicy. Sync-wave 2: after the operator (wave 0) + kata +# runtime (wave 1). Consumers (the Dark Factory, Flow B) then claim from the +# warm pool via a SandboxClaim(warmPoolRef). agent-sandbox: enabled: true namespace: agent-sandbox-system From 7893a82268e02d100858d70b28fc652281dcf63b Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 18:03:44 -0400 Subject: [PATCH 52/67] fix(agent-sandbox): package upstream operator as Helm chart (appset needs it) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform ApplicationSet renders path-based addons as Helm charts, so the operator app failed reading upstream/Chart.yaml (raw manifests, no chart). Add a thin Chart.yaml + move the v0.5.1 manifests under templates/ (they have no Helm templating → applied verbatim). Drop the ignored 'directory' config. Verified: helm renders 16 manifests (operator + 4 CRDs + RBAC + webhooks). --- gitops/addons/bootstrap/default/addons.yaml | 3 --- .../addons/charts/agent-sandbox/upstream/Chart.yaml | 11 +++++++++++ .../agent-sandbox-v0.5.1-extensions.yaml | 0 .../agent-sandbox-v0.5.1-manifest.yaml | 0 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 gitops/addons/charts/agent-sandbox/upstream/Chart.yaml rename gitops/addons/charts/agent-sandbox/upstream/{ => templates}/agent-sandbox-v0.5.1-extensions.yaml (100%) rename gitops/addons/charts/agent-sandbox/upstream/{ => templates}/agent-sandbox-v0.5.1-manifest.yaml (100%) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index 8811656..c4ff163 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -374,9 +374,6 @@ agent-sandbox-operator: argocd.argoproj.io/sync-wave: '0' syncPolicyAppSet: preserveResourcesOnDeletion: false - # Directory source of raw manifests, not a Helm chart. - directory: - recurse: true selector: matchExpressions: - key: enable_agent_sandbox diff --git a/gitops/addons/charts/agent-sandbox/upstream/Chart.yaml b/gitops/addons/charts/agent-sandbox/upstream/Chart.yaml new file mode 100644 index 0000000..f4493f7 --- /dev/null +++ b/gitops/addons/charts/agent-sandbox/upstream/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: agent-sandbox-operator +description: >- + Upstream agent-sandbox v0.5.1 operator install (controller Deployment + CRDs + + RBAC + webhooks) vendored verbatim from kubernetes-sigs/agent-sandbox. Packaged + as a thin Helm chart so the platform ApplicationSet (which renders addons as + Helm charts) can deploy it. The manifest files under templates/ contain no Helm + templating — they are applied as-is. ServerSideApply handles the oversized CRDs. +type: application +version: 0.5.1 +appVersion: "0.5.1" diff --git a/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml similarity index 100% rename from gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-extensions.yaml rename to gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml diff --git a/gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml similarity index 100% rename from gitops/addons/charts/agent-sandbox/upstream/agent-sandbox-v0.5.1-manifest.yaml rename to gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml From acc7e44368ca5b5be581d6bb49567b6eb482adb4 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 18:34:17 -0400 Subject: [PATCH 53/67] fix(agent-sandbox): gate appsets to spoke-dev only (drop hub + prod) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The agent-sandbox, agent-sandbox-operator, and kata-deploy addons were generated on every cluster carrying enable_agent_platform (hub, dev, prod) because their per-addon selector was dropped when the global useSelectors path isn't taken — producing unwanted agent-sandbox-hub and agent-sandbox-spoke-prod ArgoCD apps. Switch each entry from selector (enable_agent_sandbox*) to alwaysSelector (environment In [dev]), mirroring the langfuse hub-only precedent. alwaysSelector is honored regardless of useSelectors, so the generated ApplicationSets match ONLY the environment=dev cluster; hub and prod apps are pruned. Kata needs a nested-virt MNG that exists only on spoke-dev, so dev-only is also the correct capability scope. --- gitops/addons/bootstrap/default/addons.yaml | 27 ++++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/gitops/addons/bootstrap/default/addons.yaml b/gitops/addons/bootstrap/default/addons.yaml index c4ff163..e8384a0 100644 --- a/gitops/addons/bootstrap/default/addons.yaml +++ b/gitops/addons/bootstrap/default/addons.yaml @@ -374,11 +374,15 @@ agent-sandbox-operator: argocd.argoproj.io/sync-wave: '0' syncPolicyAppSet: preserveResourcesOnDeletion: false - selector: + # Agent Sandbox is a spoke-dev-only capability (Kata needs a nested-virt MNG; + # not on the hub, and prod stays off). alwaysSelector is honored regardless of + # the global useSelectors flag, so the generated ApplicationSet matches ONLY + # the cluster whose `environment` label is `dev` — hub and prod apps are pruned. + alwaysSelector: matchExpressions: - - key: enable_agent_sandbox + - key: environment operator: In - values: ['true'] + values: ['dev'] # Agent Sandbox capability chart — RuntimeClasses, kata-readiness (removes the # runtime-not-ready startup taint), coder SandboxTemplate, SandboxWarmPool, and @@ -392,11 +396,13 @@ agent-sandbox: path: 'gitops/addons/charts/agent-sandbox' annotationsAppSet: argocd.argoproj.io/sync-wave: '2' - selector: + # Spoke-dev-only (see agent-sandbox-operator note above). alwaysSelector pins + # generation to the `environment: dev` cluster regardless of useSelectors. + alwaysSelector: matchExpressions: - - key: enable_agent_sandbox + - key: environment operator: In - values: ['true'] + values: ['dev'] valuesObject: coderTemplate: bifrostUrl: '{{default "http://bifrost.bifrost.svc.cluster.local:8080" (index .metadata.annotations "bifrost_url")}}' @@ -419,11 +425,14 @@ kata-deploy: chartRepository: 'ghcr.io/kata-containers/kata-deploy-charts' annotationsAppSet: argocd.argoproj.io/sync-wave: '1' - selector: + # Spoke-dev-only: the kata runtime is only installed where a nested-virt MNG + # exists (spoke-dev). alwaysSelector pins generation to `environment: dev` + # regardless of useSelectors — no hub or prod kata-deploy app. + alwaysSelector: matchExpressions: - - key: enable_agent_sandbox_kata + - key: environment operator: In - values: ['true'] + values: ['dev'] valuesObject: kata-deploy: image: From b81c55e8ac3acaa4e31dae356032069298fb1ca9 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 18:47:06 -0400 Subject: [PATCH 54/67] fix(agent-sandbox): merge duplicate controller Deployment into one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vendored v0.5.1 bundle defined the agent-sandbox-controller Deployment twice — once in manifest.yaml (core API + webhook port 9443, no --extensions) and once in extensions.yaml (--extensions + config-volume, no 9443). Upstream ships them as two separate 'kubectl apply' bundles where the second overrides the first, but vendoring both into one Helm chart made ArgoCD render the Deployment twice (RepeatedResourceWarning) with last-apply-wins semantics: - if manifest won → controller lacked --extensions → the SandboxTemplate v1alpha1→v1beta1 conversion webhook failed with 'no kind "SandboxTemplate"' (this is what wedged the hub/prod app deletes on a cascade). - if extensions won → controller lacked port 9443 → webhook unreachable. Fix: keep a single controller Deployment in manifest.yaml carrying the union (--leader-elect --extensions, ports 8080/8081/9443, config-volume) and remove the duplicate from extensions.yaml. Now one controller serves both the core API and the extensions conversion webhook. Renders to exactly one Deployment; helm template + YAML parse verified. --- .../agent-sandbox-v0.5.1-extensions.yaml | 51 +++---------------- .../agent-sandbox-v0.5.1-manifest.yaml | 19 +++++++ 2 files changed, 25 insertions(+), 45 deletions(-) diff --git a/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml index 779e970..4eb6696 100644 --- a/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml +++ b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-extensions.yaml @@ -8937,51 +8937,12 @@ rules: - patch - update - watch ---- ---- -kind: Deployment -apiVersion: apps/v1 -metadata: - name: agent-sandbox-controller - namespace: agent-sandbox-system - labels: - app: agent-sandbox-controller -spec: - replicas: 1 - selector: - matchLabels: - app: agent-sandbox-controller - template: - metadata: - labels: - app: agent-sandbox-controller - spec: - serviceAccountName: agent-sandbox-controller - containers: - - name: agent-sandbox-controller - image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.5.1 - args: - - "--leader-elect=true" - - "--extensions" - ports: - - name: metrics - containerPort: 8080 - protocol: TCP - - name: healthz - containerPort: 8081 - protocol: TCP - volumeMounts: - - name: config-volume - mountPath: /etc/sandbox-config - readOnly: true - volumes: - - name: config-volume - configMap: - name: agent-sandbox-config - optional: true - - ---- +# NOTE: the agent-sandbox-controller Deployment that upstream ships in this +# extensions bundle has been removed to avoid a duplicate with the one in +# agent-sandbox-v0.5.1-manifest.yaml (ArgoCD RepeatedResourceWarning). The +# manifest.yaml Deployment now carries the union of both (--extensions + the +# 9443 webhook port + config-volume), so a single controller serves both the +# core API and the extensions conversion webhook. --- apiVersion: rbac.authorization.k8s.io/v1 diff --git a/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml index a799790..a38aad6 100644 --- a/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml +++ b/gitops/addons/charts/agent-sandbox/upstream/templates/agent-sandbox-v0.5.1-manifest.yaml @@ -111,8 +111,18 @@ spec: containers: - name: agent-sandbox-controller image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.5.1 + # Merged controller: --extensions (so the controller knows the + # SandboxTemplate/SandboxClaim/SandboxWarmPool extension types and the + # /convert conversion webhook can answer) PLUS the webhook port 9443 + # that agent-sandbox-webhook-service targets. Upstream ships these as + # two separate Deployments (manifest = core+webhook port, extensions = + # --extensions but no port); vendoring both into one chart made ArgoCD + # see the Deployment twice (RepeatedResourceWarning) and whichever + # applied last won — breaking either the conversion webhook (no 9443) + # or the extension types (no --extensions). This is the union of both. args: - --leader-elect=true + - --extensions ports: - name: metrics containerPort: 8080 @@ -123,6 +133,15 @@ spec: - name: webhook containerPort: 9443 protocol: TCP + volumeMounts: + - name: config-volume + mountPath: /etc/sandbox-config + readOnly: true + volumes: + - name: config-volume + configMap: + name: agent-sandbox-config + optional: true --- From 218b1c6e42cc21e5bfa41b8bfcdeb525881d3b5e Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:47 -0400 Subject: [PATCH 55/67] =?UTF-8?q?feat(dark-factory):=20P1=20orchestrator?= =?UTF-8?q?=20k8s=20lib=20=E2=80=94=20claim=20warm=20sandbox=20via=20Sandb?= =?UTF-8?q?oxClaim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adapts the openclaw session-router to Flow B: keyed on GitHub issue-id, binds a pre-warmed Kata VM from the Flow A SandboxWarmPool via a SandboxClaim (warmPoolRef=coder-warmpool), waits for status.sandbox{name,podIPs}+Ready, and releases on teardown. CRD contract verified against the live v1beta1 schema. --- examples/dark-factory/orchestrator/lib/k8s.js | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 examples/dark-factory/orchestrator/lib/k8s.js diff --git a/examples/dark-factory/orchestrator/lib/k8s.js b/examples/dark-factory/orchestrator/lib/k8s.js new file mode 100644 index 0000000..160906e --- /dev/null +++ b/examples/dark-factory/orchestrator/lib/k8s.js @@ -0,0 +1,181 @@ +// k8s.js — Sandbox lifecycle against the Flow A warm pool. +// +// The orchestrator claims a pre-warmed Kata micro-VM from the agent-sandbox +// SandboxWarmPool (Flow A) via a SandboxClaim keyed on the GitHub issue id, +// waits for it to bind + become Ready, then tears it down on merge. This is +// the Flow B adaptation of the openclaw session-router: keyed on issue-id +// instead of a Cognito sub, and it binds a warm sandbox instead of creating a +// per-user Sandbox/PVC/Service. +// +// CRD facts (verified against the live v1beta1 CRDs on spoke-dev): +// group/version : extensions.agents.x-k8s.io/v1beta1 +// SandboxClaim.spec : warmPoolRef.name, env[]{containerName,name,value}, +// lifecycle{ttlSecondsAfterFinished,...} +// SandboxClaim.status : sandbox{name, podIPs[]}, conditions[] +const k8s = require("@kubernetes/client-node"); + +const GROUP = "extensions.agents.x-k8s.io"; +const VERSION = "v1beta1"; +const CLAIM_PLURAL = "sandboxclaims"; + +const NAMESPACE = process.env.SANDBOX_NAMESPACE || "agent-sandbox-system"; +const WARM_POOL = process.env.WARM_POOL_NAME || "coder-warmpool"; +const CLAIM_READY_TIMEOUT_MS = parseInt( + process.env.CLAIM_READY_TIMEOUT_MS || "120000", + 10, +); +// Hard TTL so a crashed/abandoned run's sandbox is reclaimed even if teardown +// never runs (the reaper is the other half of this safety net). +const CLAIM_TTL_SECONDS = parseInt( + process.env.CLAIM_TTL_SECONDS || "10800", + 10, +); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); // in-cluster SA when deployed; kubeconfig locally. +const customApi = kc.makeApiClient(k8s.CustomObjectsApi); + +// Retry with capped exponential backoff — the operator/apiserver can be +// briefly unavailable during a warm-pool refill. +async function withRetry(label, fn, { attempts = 4, baseMs = 500 } = {}) { + for (let i = 0; i < attempts; i++) { + try { + return await fn(); + } catch (e) { + if (i === attempts - 1) throw e; + const wait = baseMs * Math.pow(2, i); + console.warn( + `[k8s] ${label} failed (attempt ${i + 1}/${attempts}): ` + + `${e?.body?.message || e?.message || e}; retry in ${wait}ms`, + ); + await new Promise((r) => setTimeout(r, wait)); + } + } +} + +// Deterministic claim name per issue so re-delivered webhooks are idempotent +// (a second trigger for the same issue binds to the existing claim). +function claimName(issueId) { + return `df-issue-${String(issueId).replace(/[^a-z0-9-]/gi, "").toLowerCase()}`; +} + +function buildClaim(issueId, env = []) { + return { + apiVersion: `${GROUP}/${VERSION}`, + kind: "SandboxClaim", + metadata: { + name: claimName(issueId), + namespace: NAMESPACE, + labels: { + "dark-factory.io/managed-by": "orchestrator", + "dark-factory.io/issue": String(issueId), + }, + }, + spec: { + warmPoolRef: { name: WARM_POOL }, + // Per-container env the coder reads (BIFROST_URL, CODER_PROFILE, etc.). + // Secrets are NOT passed here — they arrive via projected tmpfs. + env: env.map((e) => ({ + containerName: e.containerName || "coder", + name: e.name, + value: String(e.value), + })), + lifecycle: { ttlSecondsAfterFinished: CLAIM_TTL_SECONDS }, + }, + }; +} + +// Claim a warm sandbox (idempotent). Returns the created/existing claim object. +async function claimSandbox(issueId, env) { + const name = claimName(issueId); + try { + const existing = await withRetry("claim get", () => + customApi.getNamespacedCustomObject( + GROUP, + VERSION, + NAMESPACE, + CLAIM_PLURAL, + name, + ), + ); + console.log(`[k8s] claim ${name} already exists — reusing`); + return existing.body; + } catch (e) { + if (e?.statusCode !== 404) throw e; + } + const created = await withRetry("claim create", () => + customApi.createNamespacedCustomObject( + GROUP, + VERSION, + NAMESPACE, + CLAIM_PLURAL, + buildClaim(issueId, env), + ), + ); + console.log(`[k8s] SandboxClaim ${name} created (warmPoolRef=${WARM_POOL})`); + return created.body; +} + +function isReady(claim) { + const conds = claim?.status?.conditions || []; + return conds.some((c) => c.type === "Ready" && c.status === "True"); +} + +// Poll the claim until the operator binds a warm sandbox and reports Ready. +// Returns { name, podIPs } of the bound sandbox. +async function waitForClaimBound(issueId, deadlineMs = CLAIM_READY_TIMEOUT_MS) { + const name = claimName(issueId); + const deadline = Date.now() + deadlineMs; + while (Date.now() < deadline) { + const { body: claim } = await customApi.getNamespacedCustomObject( + GROUP, + VERSION, + NAMESPACE, + CLAIM_PLURAL, + name, + ); + const bound = claim?.status?.sandbox?.name; + if (bound && isReady(claim)) { + return { + name: bound, + podIPs: claim.status.sandbox.podIPs || [], + }; + } + await new Promise((r) => setTimeout(r, 2000)); + } + throw new Error( + `SandboxClaim ${name} not Ready within ${deadlineMs}ms ` + + `(warm pool exhausted or sandbox failed to start?)`, + ); +} + +// Teardown — delete the claim; the operator releases the sandbox back / reaps +// it and the warm pool refills. Idempotent (404 is success). +async function releaseSandbox(issueId) { + const name = claimName(issueId); + try { + await withRetry("claim delete", () => + customApi.deleteNamespacedCustomObject( + GROUP, + VERSION, + NAMESPACE, + CLAIM_PLURAL, + name, + ), + ); + console.log(`[k8s] SandboxClaim ${name} deleted (sandbox released)`); + } catch (e) { + if (e?.statusCode === 404) return; + throw e; + } +} + +module.exports = { + NAMESPACE, + WARM_POOL, + claimName, + claimSandbox, + waitForClaimBound, + releaseSandbox, + withRetry, +}; From 46771c743b4ff2e82f97afb1b97ab050334442a4 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:48 -0400 Subject: [PATCH 56/67] feat(dark-factory): P1 sticky PR status + PR creation lib One canonical status comment edited in place (found by a hidden marker so re-runs update the same comment), ticking each pipeline stage. P2/P3 stages render as pending placeholders so the surface is stable across phases. --- .../dark-factory/orchestrator/lib/github.js | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 examples/dark-factory/orchestrator/lib/github.js diff --git a/examples/dark-factory/orchestrator/lib/github.js b/examples/dark-factory/orchestrator/lib/github.js new file mode 100644 index 0000000..38bee0a --- /dev/null +++ b/examples/dark-factory/orchestrator/lib/github.js @@ -0,0 +1,114 @@ +// github.js — the ONE sticky PR status comment + PR creation. +// +// Flow B's canonical human surface (§7): the orchestrator maintains a single +// comment edited in place as each stage completes — no comment spam. The +// comment is found by a hidden marker so re-runs update the same comment. +// +// Uses the GitHub REST API directly (no SDK dep) with a short-TTL token the +// GitHub Action mints and hands to the orchestrator per run. The orchestrator +// holds the app credentials; the untrusted sandbox never sees this token. +const https = require("https"); + +const API = "api.github.com"; +const MARKER = ""; + +// Ordered pipeline stages shown in the sticky comment. P1 stops before the +// verification stages (holdout/security/devops arrive in P2/P3) — they render +// as pending placeholders so the surface is stable across phases. +const STAGES = [ + { key: "claim", label: "Claimed sandbox (spoke-dev)" }, + { key: "branch", label: "Branch" }, + { key: "implement", label: "Implement" }, + { key: "test", label: "Build + unit tests" }, + { key: "security", label: "Security Agent", phase: "P3" }, + { key: "devops", label: "DevOps Agent", phase: "P3" }, + { key: "holdout", label: "Holdout gate", phase: "P2" }, + { key: "pr", label: "PR ready for review" }, +]; + +function icon(state) { + return { done: "✅", now: "⏳", wait: "⬜", fail: "❌" }[state] || "⬜"; +} + +// Render the sticky comment body from a { stageKey: {state, at, note, log} } map. +function renderStatus(issueNumber, states) { + const lines = [MARKER, `## 🏭 Dark Factory — issue #${issueNumber}`, ""]; + for (const s of STAGES) { + const st = states[s.key] || { state: "wait" }; + const bits = [icon(st.state), s.label]; + if (st.note) bits.push(`· ${st.note}`); + if (s.phase && st.state === "wait") bits.push(`_(${s.phase})_`); + if (st.at) bits.push(`· ${st.at}`); + if (st.log) bits.push(`· [📄 log](${st.log})`); + lines.push(bits.join(" ")); + } + lines.push("", "_Human reviews **results, not diffs**. Approve the PR to merge + teardown._"); + return lines.join("\n"); +} + +function ghRequest(token, method, path, body) { + return new Promise((resolve, reject) => { + const data = body ? JSON.stringify(body) : null; + const req = https.request( + { + host: API, + method, + path, + headers: { + "User-Agent": "dark-factory-orchestrator", + Authorization: `Bearer ${token}`, + Accept: "application/vnd.github+json", + "X-GitHub-Api-Version": "2022-11-28", + ...(data ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(data) } : {}), + }, + }, + (res) => { + let buf = ""; + res.on("data", (c) => (buf += c)); + res.on("end", () => { + if (res.statusCode >= 200 && res.statusCode < 300) { + resolve(buf ? JSON.parse(buf) : {}); + } else { + reject(new Error(`GitHub ${method} ${path} → ${res.statusCode}: ${buf}`)); + } + }); + }, + ); + req.on("error", reject); + if (data) req.write(data); + req.end(); + }); +} + +// Find our sticky comment on an issue/PR (they share the comments endpoint). +async function findStickyComment(token, repo, issueNumber) { + const comments = await ghRequest( + token, + "GET", + `/repos/${repo}/issues/${issueNumber}/comments?per_page=100`, + ); + return comments.find((c) => (c.body || "").includes(MARKER)); +} + +// Upsert the sticky comment (create once, then edit in place). +async function upsertStatus(token, repo, issueNumber, states) { + const body = renderStatus(issueNumber, states); + const existing = await findStickyComment(token, repo, issueNumber); + if (existing) { + return ghRequest(token, "PATCH", `/repos/${repo}/issues/comments/${existing.id}`, { body }); + } + return ghRequest(token, "POST", `/repos/${repo}/issues/${issueNumber}/comments`, { body }); +} + +// Open the PR for the coder's branch. Body carries the evidence report. +async function openPullRequest(token, repo, { head, base, title, body }) { + return ghRequest(token, "POST", `/repos/${repo}/pulls`, { + title, + head, + base: base || "main", + body, + maintainer_can_modify: true, + }); +} + +module.exports = { STAGES, renderStatus, upsertStatus, openPullRequest, findStickyComment }; From 77895a1c0180405358620d01b3251ae968e30f17 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:48 -0400 Subject: [PATCH 57/67] =?UTF-8?q?feat(dark-factory):=20P1=20coder-drive=20?= =?UTF-8?q?lib=20=E2=80=94=20files+env=20contract=20over=20the=20sandbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Posts the run spec (SPEC.md + repo + branch df/issue-N + profile) to the coder agent's in-VM control endpoint and awaits result.json. No secrets cross here — they reach the sandbox via projected tmpfs, out of band. --- .../dark-factory/orchestrator/lib/coder.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 examples/dark-factory/orchestrator/lib/coder.js diff --git a/examples/dark-factory/orchestrator/lib/coder.js b/examples/dark-factory/orchestrator/lib/coder.js new file mode 100644 index 0000000..6b3f12e --- /dev/null +++ b/examples/dark-factory/orchestrator/lib/coder.js @@ -0,0 +1,80 @@ +// coder.js — drive the pluggable coder inside the bound Kata sandbox. +// +// The coder contract crosses the trust boundary as files + env only (§5): +// INPUTS /workspace/SPEC.md, /workspace/repo/ (branch df/issue-), +// tmpfs bifrost-api-key + gh-token (mode 0400) +// ENV CODER_PROFILE, BIFROST_URL +// OUTPUTS git branch df/issue- + /workspace/artifacts/result.json +// +// P1 talks to the coder over the sandbox's in-VM control endpoint (the coder +// image runs a tiny agent listening on :8080 that accepts a run spec and +// streams stage events). The orchestrator NEVER hands cloud credentials in — +// it only writes the spec and reads back result.json. Secrets reach the +// sandbox via projected tmpfs wired on the SandboxTemplate, out of band. +const http = require("http"); + +const CODER_PORT = parseInt(process.env.CODER_PORT || "8080", 10); +const CODER_RUN_TIMEOUT_MS = parseInt( + process.env.CODER_RUN_TIMEOUT_MS || "1800000", // 30 min + 10, +); + +function branchName(issueId) { + return `df/issue-${issueId}`; +} + +// POST the run spec to the coder agent inside the sandbox and await result.json. +// `host` is the bound sandbox pod IP (from SandboxClaim.status.sandbox.podIPs). +function runCoder(host, spec) { + return new Promise((resolve, reject) => { + const payload = JSON.stringify(spec); + const req = http.request( + { + host, + port: CODER_PORT, + path: "/run", + method: "POST", + headers: { + "Content-Type": "application/json", + "Content-Length": Buffer.byteLength(payload), + }, + timeout: CODER_RUN_TIMEOUT_MS, + }, + (res) => { + let buf = ""; + res.on("data", (c) => (buf += c)); + res.on("end", () => { + if (res.statusCode !== 200) { + return reject(new Error(`coder /run → ${res.statusCode}: ${buf}`)); + } + try { + resolve(JSON.parse(buf)); // result.json + } catch (e) { + reject(new Error(`coder returned non-JSON result: ${buf.slice(0, 200)}`)); + } + }); + }, + ); + req.on("timeout", () => req.destroy(new Error("coder run timed out"))); + req.on("error", reject); + req.write(payload); + req.end(); + }); +} + +// Build the run spec the coder consumes. The issue body becomes SPEC.md; the +// target repo + branch tell the coder where to work. No secrets in here. +function buildRunSpec({ issueId, repo, issueTitle, issueBody, base }) { + return { + spec: `# ${issueTitle}\n\n${issueBody || ""}\n`, + repo, // e.g. "aws-samples/sample-open-agentic-platform" + baseBranch: base || "main", + branch: branchName(issueId), + profile: process.env.CODER_PROFILE || "claude-code", + // P1: implement → build → unit tests until green, then open nothing — + // the orchestrator opens the PR after verification stages. + tasks: ["implement", "build", "test"], + }; +} + +module.exports = { branchName, runCoder, buildRunSpec, CODER_PORT }; From 235136973ec817c9bcc941830c35d1b97b470d11 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:48 -0400 Subject: [PATCH 58/67] =?UTF-8?q?feat(dark-factory):=20P1=20orchestrator?= =?UTF-8?q?=20server=20=E2=80=94=20claim=E2=86=92code=E2=86=92PR+live=20st?= =?UTF-8?q?atus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ties the pipeline together: POST /run claims a warm sandbox, drives the coder, opens a PR (no auto-merge), and maintains the live sticky status; POST /teardown releases the sandbox. Trusted component, runs outside the Kata VM. --- examples/dark-factory/orchestrator/server.js | 192 +++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 examples/dark-factory/orchestrator/server.js diff --git a/examples/dark-factory/orchestrator/server.js b/examples/dark-factory/orchestrator/server.js new file mode 100644 index 0000000..3a31078 --- /dev/null +++ b/examples/dark-factory/orchestrator/server.js @@ -0,0 +1,192 @@ +// server.js — Dark Factory orchestrator (Flow B, phase P1). +// +// Trigger → claim warm sandbox → drive the coder → open PR with a live sticky +// status comment → manual teardown. Runs on spoke-dev only, OUTSIDE the Kata +// sandbox, and is the trusted component: it holds the GitHub token (passed +// per-run by the Action) and — in later phases — AWS IAM. The untrusted coder +// sandbox never receives cloud credentials. +// +// Endpoints: +// POST /run { issue, repo, title, body, base, ghToken } → start a run +// POST /teardown { issue, repo, ghToken } → release sandbox +// GET /healthz +// +// This is the Flow B adaptation of the openclaw session-router: keyed on the +// GitHub issue id instead of a Cognito sub, and it binds a warm sandbox from +// the Flow A SandboxWarmPool via a SandboxClaim rather than creating per-user +// resources. +const http = require("http"); +const k8s = require("./lib/k8s"); +const gh = require("./lib/github"); +const coder = require("./lib/coder"); + +const PORT = parseInt(process.env.PORT || "8080", 10); +const BIFROST_URL = + process.env.BIFROST_URL || "http://bifrost.bifrost.svc.cluster.local:8080"; + +function now() { + // Wall-clock HH:MM stamp for the sticky comment. Uses the process TZ. + return new Date().toISOString().slice(11, 16); +} + +async function readJson(req) { + return new Promise((resolve, reject) => { + let buf = ""; + req.on("data", (c) => (buf += c)); + req.on("end", () => { + try { + resolve(buf ? JSON.parse(buf) : {}); + } catch (e) { + reject(e); + } + }); + req.on("error", reject); + }); +} + +// Run the P1 pipeline for one issue. Updates the sticky comment at each stage +// so the human watches the factory work in real time. +async function runPipeline({ issue, repo, title, body, base, ghToken }) { + const states = {}; + const push = async (key, patch) => { + states[key] = { ...(states[key] || {}), ...patch }; + try { + await gh.upsertStatus(ghToken, repo, issue, states); + } catch (e) { + console.error(`[orch] status update failed: ${e.message}`); + } + }; + + // Seed the comment with all stages pending, first one in progress. + await push("claim", { state: "now" }); + + // 1) Claim a warm sandbox (instant if the pool has buffer). + await k8s.claimSandbox(issue, [ + { name: "BIFROST_URL", value: BIFROST_URL }, + { name: "CODER_PROFILE", value: process.env.CODER_PROFILE || "claude-code" }, + ]); + const bound = await k8s.waitForClaimBound(issue); + await push("claim", { state: "done", at: now(), note: bound.name }); + + if (!bound.podIPs.length) { + throw new Error(`bound sandbox ${bound.name} reported no pod IPs`); + } + const host = bound.podIPs[0]; + + // 2) Drive the coder: SPEC.md + branch + implement/build/test until green. + await push("branch", { state: "done", at: now(), note: coder.branchName(issue) }); + await push("implement", { state: "now" }); + + const runSpec = coder.buildRunSpec({ + issueId: issue, + repo, + issueTitle: title, + issueBody: body, + base, + }); + const result = await coder.runCoder(host, runSpec); + + await push("implement", { state: "done", at: now() }); + const testState = result.testsGreen ? "done" : "fail"; + await push("test", { + state: testState, + at: now(), + log: result.logUrl, + note: result.testSummary, + }); + if (!result.testsGreen) { + throw new Error(`coder could not get tests green: ${result.testSummary || "unknown"}`); + } + + // 3) Verification stages are P2/P3 — leave them pending in the surface. + + // 4) Open the PR with the evidence report. P1 = no auto-merge; the human + // approves. Branch protections + CI still apply. + await push("pr", { state: "now" }); + const pr = await gh.openPullRequest(ghToken, repo, { + head: coder.branchName(issue), + base: base || "main", + title: `Dark Factory: ${title} (#${issue})`, + body: prBody(issue, result), + }); + await push("pr", { state: "done", at: now(), note: `#${pr.number}` }); + + console.log(`[orch] issue #${issue} → PR #${pr.number} (${pr.html_url})`); + return { pr: pr.number, url: pr.html_url, sandbox: bound.name }; +} + +function prBody(issue, result) { + return [ + `Closes #${issue}.`, + "", + "## 🏭 Dark Factory report", + "", + "_Autonomously implemented in a hardware-isolated Kata micro-VM (spoke-dev)._", + "_Review the **evidence** below, not the diff line-by-line._", + "", + `- **Build + unit tests:** ${result.testsGreen ? "✅ green" : "❌ failing"}` + + (result.testSummary ? ` — ${result.testSummary}` : ""), + result.logUrl ? `- **Logs:** ${result.logUrl}` : "", + "- **Holdout gate:** _pending (P2)_", + "- **Security / DevOps agents:** _pending (P3)_", + "", + result.summary ? `### What changed\n\n${result.summary}` : "", + ] + .filter(Boolean) + .join("\n"); +} + +const server = http.createServer(async (req, res) => { + try { + if (req.method === "GET" && req.url === "/healthz") { + res.writeHead(200).end("ok"); + return; + } + + if (req.method === "POST" && req.url === "/run") { + const b = await readJson(req); + for (const f of ["issue", "repo", "ghToken"]) { + if (!b[f]) { + res.writeHead(400).end(`missing field: ${f}`); + return; + } + } + // Acknowledge immediately; run the pipeline in the background so the + // Action's HTTP call doesn't hold open for the whole build. + res.writeHead(202).end(JSON.stringify({ accepted: true, issue: b.issue })); + runPipeline(b).catch(async (e) => { + console.error(`[orch] pipeline failed for #${b.issue}: ${e.message}`); + try { + const states = { test: { state: "fail", note: e.message.slice(0, 120) } }; + await gh.upsertStatus(b.ghToken, b.repo, b.issue, states); + } catch (_) { + /* best-effort */ + } + }); + return; + } + + if (req.method === "POST" && req.url === "/teardown") { + const b = await readJson(req); + if (!b.issue) { + res.writeHead(400).end("missing field: issue"); + return; + } + await k8s.releaseSandbox(b.issue); + res.writeHead(200).end(JSON.stringify({ released: true, issue: b.issue })); + return; + } + + res.writeHead(404).end("not found"); + } catch (e) { + console.error(`[orch] request error: ${e.message}`); + res.writeHead(500).end(e.message); + } +}); + +server.listen(PORT, "0.0.0.0", () => { + console.log( + `[orch] Dark Factory orchestrator listening on :${PORT} ` + + `(ns=${k8s.NAMESPACE}, warmPool=${k8s.WARM_POOL})`, + ); +}); From 3cb38976b982bf57be784b30ac687d727db7287a Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:48 -0400 Subject: [PATCH 59/67] feat(dark-factory): P1 orchestrator package.json (@kubernetes/client-node) --- examples/dark-factory/orchestrator/package.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/dark-factory/orchestrator/package.json diff --git a/examples/dark-factory/orchestrator/package.json b/examples/dark-factory/orchestrator/package.json new file mode 100644 index 0000000..b20b2c7 --- /dev/null +++ b/examples/dark-factory/orchestrator/package.json @@ -0,0 +1,16 @@ +{ + "name": "dark-factory-orchestrator", + "version": "0.1.0", + "private": true, + "description": "Dark Factory (Flow B) orchestrator — claims a warm Kata sandbox per GitHub issue, drives the coder, opens a PR with a live sticky status comment.", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "engines": { + "node": ">=20" + }, + "dependencies": { + "@kubernetes/client-node": "^0.21.0" + } +} From e02c771da49406e0e2ce32e4b8db6c82c79c795d Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:00:48 -0400 Subject: [PATCH 60/67] =?UTF-8?q?feat(dark-factory):=20P1=20orchestrator?= =?UTF-8?q?=20Dockerfile=20=E2=80=94=20non-root=20node:20-alpine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/dark-factory/orchestrator/Dockerfile | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 examples/dark-factory/orchestrator/Dockerfile diff --git a/examples/dark-factory/orchestrator/Dockerfile b/examples/dark-factory/orchestrator/Dockerfile new file mode 100644 index 0000000..232e6b7 --- /dev/null +++ b/examples/dark-factory/orchestrator/Dockerfile @@ -0,0 +1,22 @@ +# Dark Factory orchestrator — small, non-root Node image. +# Purpose-built (not npm-install-at-start) so the trusted component is +# auditable and starts fast. The orchestrator holds credentials and talks to +# the Kubernetes API + GitHub, so it stays minimal. +FROM public.ecr.aws/docker/library/node:20-alpine + +WORKDIR /app + +# Install deps first for layer caching. Only @kubernetes/client-node. +COPY package.json ./ +RUN npm install --omit=dev --no-audit --no-fund + +COPY server.js ./ +COPY lib ./lib + +# Non-root: the orchestrator needs no privileges beyond its ServiceAccount RBAC. +USER 1000 + +ENV PORT=8080 +EXPOSE 8080 + +CMD ["node", "server.js"] From 5d6a499a507a7080122669bbcd34236fbf744efc Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 61/67] =?UTF-8?q?feat(dark-factory):=20P1=20orchestrator?= =?UTF-8?q?=20RBAC=20=E2=80=94=20SandboxClaims=20only,=20namespace-scoped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SA + Role + RoleBinding scoped to sandboxclaims (CRUD) + read sandboxes in agent-sandbox-system. No pod/exec, no secrets, no cluster scope — mirrors the session-router trust invariants. Validated server-side on spoke-dev. --- .../dark-factory/orchestrator/k8s/rbac.yaml | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 examples/dark-factory/orchestrator/k8s/rbac.yaml diff --git a/examples/dark-factory/orchestrator/k8s/rbac.yaml b/examples/dark-factory/orchestrator/k8s/rbac.yaml new file mode 100644 index 0000000..669c70a --- /dev/null +++ b/examples/dark-factory/orchestrator/k8s/rbac.yaml @@ -0,0 +1,50 @@ +# Narrowly-scoped RBAC for the Dark Factory orchestrator. +# +# The orchestrator is trusted but still least-privilege: it only manages +# SandboxClaims (claim/inspect/release the warm pool) in the agent-sandbox +# namespace. It does NOT get pod/exec, secrets, or cluster scope — the coder +# runs in a Kata VM the orchestrator never shells into, and all model access is +# via Bifrost. This mirrors the openclaw session-router's trust invariants. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dark-factory-orchestrator + namespace: agent-sandbox-system + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: dark-factory-orchestrator + namespace: agent-sandbox-system + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory +rules: + # Claim / inspect / release warm sandboxes. + - apiGroups: ["extensions.agents.x-k8s.io"] + resources: ["sandboxclaims"] + verbs: ["get", "list", "watch", "create", "delete"] + # Read the bound Sandbox + its pod IPs (status) — read-only. + - apiGroups: ["agents.x-k8s.io"] + resources: ["sandboxes"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: dark-factory-orchestrator + namespace: agent-sandbox-system + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory +subjects: + - kind: ServiceAccount + name: dark-factory-orchestrator + namespace: agent-sandbox-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: dark-factory-orchestrator From 13b813d16cc278b4ba322dd430ee8c58987bf9ae Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 62/67] feat(dark-factory): P1 orchestrator Deployment + Service (spoke-dev) Runs on general Auto Mode nodes (trusted, no micro-VM needed), non-root, readOnlyRootFilesystem, drop ALL caps, healthz probes. Validated server-side. --- .../orchestrator/k8s/deployment.yaml | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 examples/dark-factory/orchestrator/k8s/deployment.yaml diff --git a/examples/dark-factory/orchestrator/k8s/deployment.yaml b/examples/dark-factory/orchestrator/k8s/deployment.yaml new file mode 100644 index 0000000..ecd083e --- /dev/null +++ b/examples/dark-factory/orchestrator/k8s/deployment.yaml @@ -0,0 +1,94 @@ +# Dark Factory orchestrator — Deployment + Service. +# +# Runs on spoke-dev only (Flow B), on the general-purpose Auto Mode nodes (NOT +# the kata MNG — the orchestrator is trusted and holds no untrusted code, so it +# does not need micro-VM isolation). It reaches the coder sandbox over the +# pod network and the Kubernetes API via its ServiceAccount. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dark-factory-orchestrator + namespace: agent-sandbox-system + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory +spec: + replicas: 1 + selector: + matchLabels: + app: dark-factory-orchestrator + template: + metadata: + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory + spec: + serviceAccountName: dark-factory-orchestrator + securityContext: + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + containers: + - name: orchestrator + # Replace with the built image (ECR). Placeholder tag pinned by the + # GitOps values/kustomize overlay at deploy time. + image: public.ecr.aws/docker/library/node:20-alpine + command: ["node", "server.js"] + workingDir: /app + env: + - name: PORT + value: "8080" + - name: SANDBOX_NAMESPACE + value: agent-sandbox-system + - name: WARM_POOL_NAME + value: coder-warmpool + - name: BIFROST_URL + value: http://bifrost.bifrost.svc.cluster.local:8080 + - name: CODER_PROFILE + value: claude-code + ports: + - containerPort: 8080 + name: http + readinessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 3 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] + resources: + requests: { cpu: 50m, memory: 96Mi } + limits: { cpu: 500m, memory: 256Mi } + volumeMounts: + - name: tmp + mountPath: /tmp + volumes: + - name: tmp + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: dark-factory-orchestrator + namespace: agent-sandbox-system + labels: + app: dark-factory-orchestrator + app.kubernetes.io/part-of: dark-factory +spec: + selector: + app: dark-factory-orchestrator + ports: + - name: http + port: 8080 + targetPort: http From d54f3c2df7126c0123998357508f9fcfb57f802c Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 63/67] =?UTF-8?q?feat(dark-factory):=20P1=20trigger=20?= =?UTF-8?q?=E2=80=94=20GitHub=20Action=20on=20dark-factory=20label?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gates on the label, acknowledges on the issue, and POSTs the run request (issue/repo/title/body/base + short-TTL github.token) to the orchestrator. Net-new — OAP had no GitHub Actions. Least-privilege permissions block. --- .github/workflows/dark-factory.yml | 75 ++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 .github/workflows/dark-factory.yml diff --git a/.github/workflows/dark-factory.yml b/.github/workflows/dark-factory.yml new file mode 100644 index 0000000..8c9dddd --- /dev/null +++ b/.github/workflows/dark-factory.yml @@ -0,0 +1,75 @@ +# Dark Factory (Flow B) trigger — issue labeled `dark-factory` → orchestrator. +# +# This is the P1 entrypoint (§4 step 1). It gates on the label, mints a +# short-TTL token scoped to this repo, and POSTs the run request to the +# orchestrator running on spoke-dev. The orchestrator (not this Action) holds +# the long-lived credentials and drives the sandbox; the Action's only job is +# to authenticate the trigger and hand over a short-lived token. +# +# The token here is the workflow's GITHUB_TOKEN (auto-expires when the run +# ends). For cross-repo / org installs, swap in a GitHub App token minted via +# actions/create-github-app-token — the orchestrator treats it the same way. +name: dark-factory + +on: + issues: + types: [labeled] + +# Least-privilege: the orchestrator opens the PR + updates the sticky comment +# using the token we pass, so it needs write on contents + PRs + issues. +permissions: + contents: write + pull-requests: write + issues: write + +jobs: + dispatch: + # Only fire when the `dark-factory` label is the one that was added. + if: github.event.label.name == 'dark-factory' + runs-on: ubuntu-latest + steps: + - name: Acknowledge on the issue + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: '🏭 Dark Factory accepted this issue — claiming a sandbox on spoke-dev…', + }); + + - name: Dispatch to orchestrator + env: + # The orchestrator's ingress URL (private ALB / VPN-reachable). + # Configure as a repo/org variable; kept out of the workflow so the + # endpoint isn't hard-coded. + ORCHESTRATOR_URL: ${{ vars.DARK_FACTORY_ORCHESTRATOR_URL }} + # Shared secret so the orchestrator only accepts trusted triggers. + DISPATCH_TOKEN: ${{ secrets.DARK_FACTORY_DISPATCH_TOKEN }} + GH_TOKEN: ${{ github.token }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_TITLE: ${{ github.event.issue.title }} + ISSUE_BODY: ${{ github.event.issue.body }} + REPO: ${{ github.repository }} + BASE: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + if [ -z "${ORCHESTRATOR_URL:-}" ]; then + echo "::error::DARK_FACTORY_ORCHESTRATOR_URL is not set — cannot dispatch." + exit 1 + fi + # Build the JSON payload safely (jq handles escaping of title/body). + payload="$(jq -n \ + --arg issue "$ISSUE_NUMBER" \ + --arg repo "$REPO" \ + --arg title "$ISSUE_TITLE" \ + --arg body "$ISSUE_BODY" \ + --arg base "$BASE" \ + --arg ghToken "$GH_TOKEN" \ + '{issue: ($issue|tonumber), repo: $repo, title: $title, body: $body, base: $base, ghToken: $ghToken}')" + curl -fsS -X POST "$ORCHESTRATOR_URL/run" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${DISPATCH_TOKEN:-}" \ + -d "$payload" + echo "Dispatched issue #$ISSUE_NUMBER to the Dark Factory orchestrator." From 47cb0977e55d5b18c91e3c9094f33932e4bfe4e4 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 64/67] =?UTF-8?q?feat(dark-factory):=20P1=20in-VM=20coder?= =?UTF-8?q?=20agent=20=E2=80=94=20honors=20the=20files+env=20contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Untrusted side: reads Bifrost key + short-TTL gh-token from tmpfs (0400, never in env), writes SPEC.md, checks out df/issue-N, runs Claude Code headless via Bifrost, builds+tests until green (bounded, RETRY.md on failure), returns result.json. Kiro is a one-branch swap in runProfile(). --- examples/dark-factory/coder/agent.js | 159 +++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 examples/dark-factory/coder/agent.js diff --git a/examples/dark-factory/coder/agent.js b/examples/dark-factory/coder/agent.js new file mode 100644 index 0000000..56dd80c --- /dev/null +++ b/examples/dark-factory/coder/agent.js @@ -0,0 +1,159 @@ +// agent.js — the in-VM coder agent (runs INSIDE the Kata micro-VM sandbox). +// +// This is the untrusted side of the trust boundary. It holds NO cloud +// credentials — only a Bifrost API key + a short-TTL GitHub token, both read +// from projected tmpfs (mode 0400), used, and never placed in the environment. +// It listens on :8080 for a run spec from the orchestrator, then: +// 1. writes /workspace/SPEC.md from the issue +// 2. checks out the target repo on branch df/issue- +// 3. runs the pluggable coder (Claude Code headless by default) via Bifrost +// 4. builds + runs unit tests until green (bounded attempts) +// 5. pushes the branch and returns /workspace/artifacts/result.json +// +// The concrete coder invocation is profile-pluggable (§5). This reference +// wires the contract and the Claude Code headless call; swapping to Kiro is a +// single branch in runProfile(). +const http = require("http"); +const fs = require("fs"); +const { execFileSync } = require("child_process"); + +const PORT = parseInt(process.env.CODER_PORT || "8080", 10); +const WORKSPACE = process.env.WORKSPACE || "/workspace"; +const BIFROST_URL = process.env.BIFROST_URL || "http://bifrost.bifrost.svc.cluster.local:8080"; +const MAX_TEST_ATTEMPTS = parseInt(process.env.MAX_TEST_ATTEMPTS || "3", 10); + +// Secrets live on tmpfs, mode 0400 — read at point of use, never in env. +function readSecret(path) { + try { + return fs.readFileSync(path, "utf8").trim(); + } catch { + return null; + } +} +const BIFROST_KEY_PATH = process.env.BIFROST_KEY_PATH || "/etc/secrets/bifrost-api-key"; +const GH_TOKEN_PATH = process.env.GH_TOKEN_PATH || "/etc/secrets/gh-token"; + +function sh(cmd, args, opts = {}) { + return execFileSync(cmd, args, { + cwd: opts.cwd || WORKSPACE, + encoding: "utf8", + stdio: ["ignore", "pipe", "pipe"], + env: opts.env || process.env, + maxBuffer: 32 * 1024 * 1024, + }); +} + +function writeSpec(spec) { + fs.writeFileSync(`${WORKSPACE}/SPEC.md`, spec, { mode: 0o644 }); +} + +// Clone/checkout the target repo on the coder branch. The gh-token authorizes +// the clone + later push; it never enters the process env. +function checkoutRepo(repo, base, branch) { + const token = readSecret(GH_TOKEN_PATH); + if (!token) throw new Error("gh-token not present on tmpfs"); + const url = `https://x-access-token:${token}@github.com/${repo}.git`; + const dir = `${WORKSPACE}/repo`; + if (!fs.existsSync(dir)) { + sh("git", ["clone", "--depth", "1", "--branch", base, url, dir]); + } + sh("git", ["checkout", "-B", branch], { cwd: dir }); + return dir; +} + +// Run the pluggable coder. Claude Code headless routes to Bedrock via Bifrost +// (base-URL override); Kiro headless is the second profile. +function runProfile(profile, repoDir, spec) { + const key = readSecret(BIFROST_KEY_PATH); + if (!key) throw new Error("bifrost-api-key not present on tmpfs"); + const env = { + ...process.env, + ANTHROPIC_BASE_URL: BIFROST_URL, + ANTHROPIC_API_KEY: key, + CLAUDE_CODE_USE_BEDROCK: "1", + }; + if (profile === "kiro") { + // Kiro headless (spec-driven): spec → requirements → design → tasks. + return sh("kiro", ["run", "--headless", "--spec", `${WORKSPACE}/SPEC.md`], { cwd: repoDir, env }); + } + // Default: Claude Code headless, non-interactive, prompted with the spec. + return sh( + "claude", + ["-p", `Implement the change described in ${WORKSPACE}/SPEC.md. Build and run unit tests until green. Commit your work.`], + { cwd: repoDir, env }, + ); +} + +// Build + unit tests. Auto-detects the toolchain; returns { green, summary }. +function buildAndTest(repoDir) { + let summary = ""; + for (let attempt = 1; attempt <= MAX_TEST_ATTEMPTS; attempt++) { + try { + if (fs.existsSync(`${repoDir}/package.json`)) { + sh("npm", ["install", "--no-audit", "--no-fund"], { cwd: repoDir }); + sh("npm", ["test"], { cwd: repoDir }); + } else if (fs.existsSync(`${repoDir}/go.mod`)) { + sh("go", ["test", "./..."], { cwd: repoDir }); + } else if (fs.existsSync(`${repoDir}/pyproject.toml`) || fs.existsSync(`${repoDir}/setup.py`)) { + sh("python", ["-m", "pytest", "-q"], { cwd: repoDir }); + } else { + return { green: true, summary: "no recognized test suite — skipped" }; + } + return { green: true, summary: `tests passed (attempt ${attempt})` }; + } catch (e) { + summary = (e.stdout || e.stderr || e.message || "").toString().slice(-500); + // Give the coder the failure reason and let it try again. + fs.writeFileSync(`${WORKSPACE}/RETRY.md`, `Test failure (attempt ${attempt}):\n${summary}\n`); + } + } + return { green: false, summary: `tests still failing after ${MAX_TEST_ATTEMPTS} attempts: ${summary}` }; +} + +function pushBranch(repoDir, branch) { + sh("git", ["push", "-u", "origin", branch, "--force-with-lease"], { cwd: repoDir }); +} + +function runOnce(runSpec) { + fs.mkdirSync(`${WORKSPACE}/artifacts`, { recursive: true }); + writeSpec(runSpec.spec); + const repoDir = checkoutRepo(runSpec.repo, runSpec.baseBranch, runSpec.branch); + runProfile(runSpec.profile, repoDir, runSpec.spec); + const test = buildAndTest(repoDir); + if (test.green) pushBranch(repoDir, runSpec.branch); + const result = { + branch: runSpec.branch, + testsGreen: test.green, + testSummary: test.summary, + summary: `Implemented per SPEC.md on ${runSpec.branch}.`, + }; + fs.writeFileSync(`${WORKSPACE}/artifacts/result.json`, JSON.stringify(result, null, 2)); + return result; +} + +const server = http.createServer((req, res) => { + if (req.method === "GET" && req.url === "/healthz") { + res.writeHead(200).end("ok"); + return; + } + if (req.method === "POST" && req.url === "/run") { + let buf = ""; + req.on("data", (c) => (buf += c)); + req.on("end", () => { + try { + const result = runOnce(JSON.parse(buf)); + res.writeHead(200, { "Content-Type": "application/json" }).end(JSON.stringify(result)); + } catch (e) { + console.error(`[coder] run failed: ${e.message}`); + res + .writeHead(200, { "Content-Type": "application/json" }) + .end(JSON.stringify({ testsGreen: false, testSummary: e.message })); + } + }); + return; + } + res.writeHead(404).end("not found"); +}); + +server.listen(PORT, "0.0.0.0", () => { + console.log(`[coder] agent listening on :${PORT} (workspace=${WORKSPACE}, bifrost=${BIFROST_URL})`); +}); From 9904e712e220872b245036411f0440f5d46454e4 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 65/67] =?UTF-8?q?feat(dark-factory):=20P1=20coder=20Docker?= =?UTF-8?q?file=20=E2=80=94=20Kata-VM=20image,=20no=20baked=20creds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/dark-factory/coder/Dockerfile | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 examples/dark-factory/coder/Dockerfile diff --git a/examples/dark-factory/coder/Dockerfile b/examples/dark-factory/coder/Dockerfile new file mode 100644 index 0000000..1fcac88 --- /dev/null +++ b/examples/dark-factory/coder/Dockerfile @@ -0,0 +1,26 @@ +# Dark Factory coder image — runs INSIDE the Kata micro-VM sandbox. +# +# Bundles the in-VM agent + the toolchains a coder run needs (git, node, the +# Claude Code CLI). This is untrusted-code territory: the image carries no +# credentials — secrets are injected at runtime via projected tmpfs (0400) and +# model access is only through Bifrost. Keep it lean and pinned. +FROM public.ecr.aws/docker/library/node:20-alpine + +# Toolchains for build/test across common stacks + git for checkout/push. +# (Extend per the repos the factory targets; kept minimal for P1.) +RUN apk add --no-cache git bash python3 py3-pip go + +# Claude Code headless CLI (primary coder profile). Pinned via npm. +RUN npm install -g @anthropic-ai/claude-code + +WORKDIR /app +COPY agent.js ./ + +# Non-root, matches the SandboxTemplate securityContext (runAsUser 1000). +USER 1000 + +ENV CODER_PORT=8080 \ + WORKSPACE=/workspace +EXPOSE 8080 + +CMD ["node", "agent.js"] From bfad46ad1d3b81e7149090f34f1f7e45fab918a9 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:01 -0400 Subject: [PATCH 66/67] =?UTF-8?q?feat(dark-factory):=20P1=20ArgoCD=20app?= =?UTF-8?q?=20=E2=80=94=20orchestrator=20pinned=20to=20spoke-dev=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/dark-factory/gitops-app.yaml | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 examples/dark-factory/gitops-app.yaml diff --git a/examples/dark-factory/gitops-app.yaml b/examples/dark-factory/gitops-app.yaml new file mode 100644 index 0000000..66b9007 --- /dev/null +++ b/examples/dark-factory/gitops-app.yaml @@ -0,0 +1,38 @@ +# ArgoCD Application for the Dark Factory orchestrator (Flow B, P1). +# +# Deploys the orchestrator's k8s manifests onto spoke-dev ONLY. Flow B runs on +# spoke-dev exclusively (prod is never a test bed — see docs/dark-factory §10). +# The `destination.name: spoke-dev` pins it to the dev spoke; apply this on the +# hub ArgoCD (the same control plane that owns the agent-sandbox appsets). +# +# The coder image is not deployed here — it's referenced by the Flow A +# SandboxTemplate that the warm pool clones; the orchestrator only claims from +# that pool. Build + push both images (orchestrator, coder) to ECR and pin the +# tags before enabling. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: dark-factory-orchestrator + namespace: argocd + labels: + app.kubernetes.io/part-of: dark-factory + annotations: + # After the agent-sandbox capability (Flow A) is up. + argocd.argoproj.io/sync-wave: "3" +spec: + project: default + source: + repoURL: https://github.com/aws-samples/sample-open-agentic-platform.git + targetRevision: dark-factory-autonomous-agent-coding-pattern + path: examples/dark-factory/orchestrator/k8s + destination: + # spoke-dev only — Flow B does not run on hub or prod. + name: spoke-dev + namespace: agent-sandbox-system + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=false # agent-sandbox-system is owned by Flow A + - ServerSideApply=true From 14a41fae65fc68ca4b1275c17841f3f21048e0e2 Mon Sep 17 00:00:00 2001 From: elamaran shanmugam Date: Fri, 10 Jul 2026 19:01:02 -0400 Subject: [PATCH 67/67] =?UTF-8?q?docs(dark-factory):=20P1=20README=20?= =?UTF-8?q?=E2=80=94=20components,=20request=20flow,=20claim=20contract,?= =?UTF-8?q?=20trust=20boundary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/dark-factory/README.md | 110 ++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 examples/dark-factory/README.md diff --git a/examples/dark-factory/README.md b/examples/dark-factory/README.md new file mode 100644 index 0000000..7bd262a --- /dev/null +++ b/examples/dark-factory/README.md @@ -0,0 +1,110 @@ +# Dark Factory — Flow B, Phase P1 + +**Trigger → claim warm sandbox → drive the coder → open a PR with a live sticky status → manual +teardown.** The first independently-useful slice of the [Dark Factory pattern](../../docs/dark-factory/README.md) +and the first real consumer of **[Flow A](../../docs/dark-factory/diagrams/flow-a-sandbox-capability.md)**'s +Kata micro-VM warm pool. + +Runs on **spoke-dev only**. Autonomy is bounded here: P1 opens a PR and **stops** — a human still +reviews and merges. The verification gates (holdout, Security/DevOps agents) arrive in P2/P3. + +## Components + +| Path | Role | Trust | +|---|---|---| +| `.github/workflows/dark-factory.yml` | GitHub Action — gates on the `dark-factory` label, mints a short-TTL token, POSTs to the orchestrator | trigger | +| `orchestrator/server.js` | HTTP service: `/run` drives the pipeline, `/teardown` releases the sandbox | **trusted** (holds the GH token; in later phases, AWS IAM) | +| `orchestrator/lib/k8s.js` | Claims a warm sandbox via a `SandboxClaim(warmPoolRef)`, waits for bind+Ready, releases on teardown | trusted | +| `orchestrator/lib/github.js` | The **one** sticky PR status comment (edited in place) + PR creation | trusted | +| `orchestrator/lib/coder.js` | Drives the pluggable coder inside the sandbox over its `:8080` control endpoint | trusted → boundary | +| `coder/agent.js` | The in-VM coder agent: writes `SPEC.md`, checks out `df/issue-`, runs Claude Code headless via Bifrost, builds+tests, returns `result.json` | **untrusted** (Kata VM, no cloud creds) | +| `orchestrator/k8s/*` | Deployment + Service + narrowly-scoped RBAC (SandboxClaims only) | — | +| `gitops-app.yaml` | ArgoCD Application pinning the orchestrator to **spoke-dev** | — | + +## Request flow + +``` +GitHub issue (label: dark-factory) + → GitHub Action (gate on label, mint short-TTL token) + → orchestrator POST /run ← trusted; holds GH token, narrow RBAC + ├─ SandboxClaim(warmPoolRef=coder-warmpool) ← binds a warm Kata VM (Flow A) + ├─ wait for status.sandbox {name, podIPs} + Ready + ├─ POST run spec to coder agent in the VM (SPEC.md + branch df/issue-N) + │ coder: implement → build → unit tests until green → push branch + ├─ open PR + maintain ONE sticky status comment (⏳→✅) + └─ (P2/P3) holdout gate + Security/DevOps agents — pending + → human reviews evidence, approves, merges + → orchestrator POST /teardown → delete SandboxClaim (pool refills) +``` + +## The SandboxClaim contract (verified against the live v1beta1 CRD) + +The orchestrator claims from Flow A's `SandboxWarmPool` rather than creating sandboxes: + +```yaml +apiVersion: extensions.agents.x-k8s.io/v1beta1 +kind: SandboxClaim +metadata: { name: df-issue-42, namespace: agent-sandbox-system } +spec: + warmPoolRef: { name: coder-warmpool } # bind a pre-warmed idle sandbox + env: # per-container, NON-secret + - { containerName: coder, name: BIFROST_URL, value: http://bifrost.bifrost.svc.cluster.local:8080 } + lifecycle: { ttlSecondsAfterFinished: 10800 } # safety-net TTL +# status.sandbox.{name, podIPs[]} + status.conditions[Ready] → the bound VM +``` + +## Trust boundary (§10) + +- The **orchestrator** is trusted and runs on general Auto Mode nodes (not the kata MNG). It holds + the GitHub token (handed per-run by the Action) and — in later phases — AWS IAM. Its RBAC is + scoped to `sandboxclaims` (+ read `sandboxes`) in one namespace; no pod/exec, no secrets, no + cluster scope. +- The **coder** is untrusted: it runs in a **Kata micro-VM**, holds only a Bifrost API key + a + short-TTL GitHub token via **projected tmpfs (mode 0400)** — read at point of use, never in env — + and reaches models only through **Bifrost**. Flow A's NetworkPolicy locks egress to + Bifrost + DNS + GitHub. +- This breaks the **lethal trifecta** (untrusted issue text + credentials + egress): credentials are + never in the issue-ingesting sandbox context, and egress is denied by default. + +## Build & deploy (staged — not auto-deployed) + +```bash +# 1) Build + push both images to ECR, pin the tags. +docker build -t /dark-factory-orchestrator:0.1.0 examples/dark-factory/orchestrator +docker build -t /dark-factory-coder:0.1.0 examples/dark-factory/coder +# → set the coder image on the Flow A SandboxTemplate (coderTemplate.image) +# → set the orchestrator image in orchestrator/k8s/deployment.yaml + +# 2) Deploy the orchestrator onto spoke-dev. +kubectl --context hub apply -f examples/dark-factory/gitops-app.yaml # ArgoCD (recommended) +# or directly: +kubectl --context spoke-dev apply -f examples/dark-factory/orchestrator/k8s/ + +# 3) Wire the trigger. +# repo/org variable DARK_FACTORY_ORCHESTRATOR_URL = https:// +# repo/org secret DARK_FACTORY_DISPATCH_TOKEN = shared dispatch secret +# Label an issue `dark-factory` to fire a run. +``` + +## Configuration (orchestrator env) + +| Var | Default | Purpose | +|---|---|---| +| `SANDBOX_NAMESPACE` | `agent-sandbox-system` | Where the warm pool + claims live | +| `WARM_POOL_NAME` | `coder-warmpool` | Flow A `SandboxWarmPool` to claim from | +| `CLAIM_READY_TIMEOUT_MS` | `120000` | Max wait for a claim to bind + Ready | +| `CLAIM_TTL_SECONDS` | `10800` | Safety-net TTL on the claim (reaper backstop) | +| `BIFROST_URL` | `http://bifrost.bifrost.svc.cluster.local:8080` | LLM gateway the coder uses | +| `CODER_PROFILE` | `claude-code` | `claude-code` (primary) or `kiro` | + +## Not in P1 (by design) + +- **Holdout gate** (P2), **AWS Security/DevOps agents** (P3) — rendered as pending in the sticky + comment so the surface is stable. +- **Auto-teardown on merge** + reaper (P4) — P1 teardown is the manual `/teardown` call. +- **Iterative comment loop** — P1 opens the PR and stops; the human drives from there. + +## Status + +Code + manifests validated (JS syntax, server-side `kubectl --dry-run` against spoke-dev). Images +are **not** built/pushed and nothing is deployed yet — this is the staged P1 implementation.