The deployment wizard -- dfe-ops init
dfe-ops init walks you through the fields in deployment.example.yaml and writes a deployment.yaml dial. Defaults come from that file. Every non-trivial answer is checked by calling render_dial.py's or resolve_sizing.py's own functions, so there's no second copy of their rules to drift out of step.
python3 scripts/dfe-ops init # interactive
python3 scripts/dfe-ops init --answers answers.env # non-interactive (CI)
python3 scripts/dfe-ops init --dry-run # print the dial, write nothing
Every question shows its default in brackets, and Enter takes it. A refused answer re-prompts with the validator's own message.
The nine questions
- Target.
on-prem(an existing cluster) or a cloud.awsis the only cloud today, andgcp/azureare named but refused because neither has a tofu root yet. A cloud target also asks the AWS account, region and VPC CIDR. - Profile/tier, ingest, focus. The three Kubernetes tiers are labelled Small/Medium/Large for the prompt. The real dial value is
slim/single/scale(seescripts/profiles.py). Estimated ingest is in GB/day, and blank means "no estimate" (the tyre-kick floorresolve_sizing.pyreports rather than targets). Focus iseconomy(default, 40% headroom),balanced(60%) orperformance(100%, high-IOPS storage), straight fromsizing/sizing.yaml's ownfocus:table. - Kafka provider and quorum. One of
strimzi,redpanda,msk,confluent-cloud,redpanda-cloud, pre-selected by tier:mskon AWS Small/Medium,confluent-cloudat Large,strimzion-prem.mskasks the broker count. An in-cluster broker also askskafka.controller_pool.combined(the default, and the chart's own) keeps the KRaft metadata quorum on the brokers, andseparategives it a sized pool. Moving it on a live cluster re-forms the quorum, sosizing.yamllocks it ascontroller_mode. - ClickHouse storage model.
sizing.storage_modeldefaults toauto, where the chart derives it from whether an object-store endpoint exists.cached-objectforces the object store and refuses to render without one.localforces local storage even with one configured. Switching later is a data migration, not a values edit (storage.md). The wizard also offers the one other lever on ClickHouse sizing: an instance-type override. - Public UIs, OIDC, CIDR, DNS.
dfe-uiis public by default and every admin UI is opt-in, one at a time. The moment any UI is public, the wizard asks you to confirm OIDC will be wired up for it (gateway-oidc.md) and refuses to continue without that. There's no OIDC dial field, so this is a wizard-side gate, not a renderer validation. Then comes an optional CIDR allow-list, any CDN's ranges, and the public DNS zone name. The answers land in the dial'sedge:block:dfe-uiunderedge.product.publicand the admin UIs underedge.admin_uis.public.*. That one block replaced the old top-levelui:andingest:. - Telemetry sink. AWS only.
otelis the default (DFE's own policy).cloudwatchis opt-in and asks for a one-line reason, which lands as a comment beside the field. - Lifecycle and AZ count.
ephemeralorpersistent, andnetwork.az_count(2-6, default 3). - Toolbox. The in-cluster pod (any target) and, on AWS, the on-demand SSM-managed instance. Both are opt-in, and the instance asks for the operator IAM role ARN once enabled. See toolbox.md.
- Sizing overrides. "Override any sizing?" Only if you say yes does it walk the documented workload names and their fields (cpu, memory, disk_gb, replicas, instance_type, iops, throughput_mibs), checked by the exact function a hand-edited dial is checked against.
What it writes, and what it leaves blank
The template ships some estate-specific fields blank on purpose: k8s.repo_url, state.bucket, state.region, tags.owner, tags.cost-center. They stay blank. The operator's own tooling injects them from the deployment's secrets backend at deploy time, or an operator fills them by hand. dfe-ops init names them in its final output on an AWS target.
Sizing
Pass --fixtures <dir> (captured API answers, scripts/resolve_sizing.py capture) or --live and, once the dial is written, dfe-ops init runs scripts/resolve_sizing.py resolve against it. It prints the report path plus the monthly compute line. That only happens for the scale tier, because resolve_sizing.py sizes the scale tier only. Every other profile is skipped with a one-line note rather than a crash.
Non-interactive mode
--answers PATH reads a flat key=value file (envfile.py, the same reader bootstrap/.env uses, so no YAML lists) and drives the identical flow with no prompts. An answer that fails validation refuses immediately, since there's nobody to re-ask. CI and scripts/tests/test_dfe_ops_init.py use it to exercise the wizard without a terminal. --dry-run prints the resulting dial and writes nothing, so you can preview an answers file before it lands.
Related
- ../../deployment.example.yaml -- the schema this wizard walks, where every field and default traces back
- ../../scripts/render_dial.py -- the validators the wizard calls, and what actually reads the written dial
- README.md -- the three layers and the values cascade
- toolbox.md -- the two troubleshooting surfaces question 8 asks about
- gateway-oidc.md -- what question 5's OIDC gate is asking you to configure