You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* fix: template wizard uses instance-types API, not availability
Templates are saved configs — filtering by real-time availability
doesn't make sense. Instance type and location steps now use the
instance-types and locations APIs in template mode, showing all
options. Location is optional in templates (skip = decide at deploy
time). Deploy mode is unchanged.
Also improves UX when deploying from a location-less template: the
wizard now prompts for location instead of silently defaulting to
FIN-01, and shows a clear error when no locations are available.
internal/skills/ # Embedded AI skill files (go:embed)
26
28
```
27
29
30
+
### Per-Command Documentation
31
+
32
+
Each command directory has its own `CLAUDE.md` (domain knowledge) and `README.md` (usage/architecture). These are the source of truth for command-specific behavior.
33
+
34
+
| Directory | Docs | Description |
35
+
|-----------|------|-------------|
36
+
|`cmd/vm/`| CLAUDE.md, README.md | VM create/list/describe/action, wizard, templates |
|`kind`| string |`"GPU"` or `"CPU"` (lowercase in template, case-insensitive in matching) |
26
26
|`instance_type`| string | e.g. `"1V100.6V"`|
27
-
|`location`| string | e.g. `"FIN-01"`|
28
-
|`image`| string | OS image slug or ID|
27
+
|`location`| string |Optional. e.g. `"FIN-01"`. If omitted, wizard prompts at deploy time|
28
+
|`image`| string | OS image **name** (resolved to ID at deploy time)|
29
29
|`os_volume_size`| int | GiB |
30
30
|`storage`|[]StorageSpec | Each has `type` and `size`|
31
31
|`storage_skip`| bool | Skip storage step in wizard |
@@ -79,8 +79,8 @@ The `template edit` command uses a field menu approach (not the full wizard):
79
79
### Edit field editors
80
80
-**Billing Type**: static select (on-demand / spot). Clears contract when switching to spot.
81
81
-**Kind**: static select (gpu / cpu)
82
-
-**Instance Type**: API call to `InstanceTypes.Get`, filtered by current kind, shows price
83
-
-**Location**: API call to `Locations.Get`
82
+
-**Instance Type**: API call to `InstanceTypes.Get` (not availability), filtered by current kind, shows price
83
+
-**Location**: API call to `Locations.Get`, includes "None (decide at deploy time)" to clear location
84
84
-**Image**: API call to `Images.Get`, excludes cluster images
85
85
-**OS Volume Size**: text input with current value as default
86
86
-**SSH Keys**: API call to `SSHKeys.GetAllSSHKeys`, multi-select with current keys pre-selected
@@ -108,6 +108,9 @@ Displays all template fields, including those previously hidden:
108
108
109
109
-**Import cycle**: `cmd/template/` cannot import `cmd/vm/` for the Template type (circular dependency). Shared types live in `internal/verda-cli/template/`, re-exported by `cmd/template/types.go` via type aliases and `var` bindings.
110
110
-**`billingTypeSet` / `locationSet` flags**: Needed because `IsSet` in the wizard can't distinguish `"on-demand"` (falsy `IsSpot=false`) from "unset". When a template sets billing type or location, these booleans are set to `true` so the wizard skips those steps.
111
+
-**Template without location triggers wizard**: When `--from` is used and the template has no location (`!opts.locationSet`), `resolveCreateInputs` triggers the wizard so the user is prompted for location instead of silently defaulting to FIN-01.
112
+
-**Template instance type/location use different APIs**: Template wizard (create) uses instance-types API and locations API directly. Deploy wizard uses availability API to filter. Template edit also uses instance-types and locations APIs directly.
113
+
-**Template error message**: `Resolve()` now shows `template name is required — template "X" not found` with guidance to run `verda template list` or use `--from` interactively.
111
114
-**`NoOptDefVal` on `--from` flag**: Set to `" "` (space) so `--from` without a value is recognized as "flag changed but empty". When the user writes `verda vm create --from gpu-training`, cobra parses `gpu-training` as a positional arg; `RunE` recombines it into `opts.From`.
112
115
-**Startup script "None (skip)" label**: The wizard presents "None (skip)" as a selectable option. Previously, this label text was captured as the script name. Fixed by checking `Value != ""` before storing the name.
113
116
-**`ensurePricingCache`**: The confirm-deploy step calls this (with parent context, not `context.Background()`) to fetch pricing when the cache is empty from template pre-fill.
Copy file name to clipboardExpand all lines: internal/verda-cli/cmd/template/README.md
+11-5Lines changed: 11 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ verda template create
28
28
verda template create gpu-training
29
29
```
30
30
31
-
The create command runs the VM wizard in **template mode** -- the same 10 configuration steps (billing type through startup script) but without hostname, description, or confirm-deploy. The resulting settings are saved to disk.
31
+
The create command runs the VM wizard in **template mode** -- the same 10 configuration steps (billing type through startup script) but without hostname, description, or confirm-deploy. In template mode, instance types come from the instance-types API (not filtered by availability) and location is optional ("None — decide at deploy time"). The resulting settings are saved to disk.
32
32
33
33
### Edit
34
34
@@ -40,7 +40,7 @@ verda template edit
40
40
verda template edit vm/gpu-training
41
41
```
42
42
43
-
Shows a menu of all template fields with their current values. Pick a field to change, edit it with the appropriate prompt (static choices for simple fields, API-backed selection for instance type/location/image/SSH keys/startup script). Repeat until "Save & exit".
43
+
Shows a menu of all template fields with their current values. Pick a field to change, edit it with the appropriate prompt (static choices for simple fields, API-backed selection for instance type/location/image/SSH keys/startup script). Location includes a "None (decide at deploy time)" option to clear the value. Repeat until "Save & exit".
44
44
45
45
### List
46
46
@@ -101,8 +101,8 @@ billing_type: on-demand # on-demand or spot
101
101
contract: PAY_AS_YOU_GO
102
102
kind: GPU # GPU or CPU
103
103
instance_type: 1V100.6V
104
-
location: FIN-01
105
-
image: ubuntu-24.04-cuda-12.8
104
+
location: FIN-01# optional — omit to prompt at deploy time
105
+
image: ubuntu-24.04-cuda-12.8# stored by name, resolved to ID at deploy time
106
106
os_volume_size: 200# GiB
107
107
storage:
108
108
- type: NVMe
@@ -124,11 +124,17 @@ verda vm create --from gpu-training # load by name
124
124
verda vm create --from ./my-template.yaml # load from file path
125
125
verda vm create --from # pick from list (interactive)
126
126
verda vm create --from gpu-training --hostname my-vm --description "test"
127
+
128
+
# Override template values with flags
129
+
verda vm create --from gpu-training --location FIN-03
130
+
verda vm create --from gpu-training --hostname my-vm --os-volume-size 200
127
131
```
128
132
133
+
Flags passed alongside `--from` override the template values.
134
+
129
135
### Flow
130
136
131
-
1. Template values pre-fill the wizard's `createOptions`
137
+
1. Template values pre-fill the wizard's `createOptions` (CLI flags take precedence — they are parsed first)
132
138
2. A summary of template values is printed to stderr
133
139
3. SSH keys and startup scripts are resolved by name to ID via the API; unresolved names produce warnings (no longer silently swallowed)
134
140
4. Only unfilled steps are prompted (hostname, description, confirm-deploy are always prompted; other steps only if the template didn't fill them)
- Steps with `DependsOn` re-run their Loader when dependencies change
85
85
-`contract` step: `ShouldSkip` returns true for spot billing
86
+
-`instance-type` step: accepts `WizardMode`. Deploy mode filters by real-time availability; template mode shows all instance types from the instance-types API (no availability filtering)
87
+
-`location` step: accepts `WizardMode`. Deploy mode shows only locations where the instance type is available; template mode shows all locations with a "None (decide at deploy time)" skip option. Deploy mode returns a clear error when no locations are available for the instance type
-`location` step: `Required` is dynamic — true in deploy mode, false in template mode
87
90
-`storage`, `ssh-keys`, `startup-script` steps: manage values directly in Loader (Setter/Resetter are no-ops), include inline sub-flows for creating new resources via API
88
91
-`confirm-deploy` step: renders deployment summary with full cost breakdown via `renderDeploymentSummary(w, opts, cache)`
89
92
- Steps have `Default` functions that return current `opts` values for pre-selection (used when `--from` pre-fills values)
-**Wizard triggers when ANY of instance-type, os, or hostname is missing** -- not all three. Providing two of three still launches the wizard.
104
+
-**Wizard triggers when ANY of instance-type, os, or hostname is missing** -- not all three. Providing two of three still launches the wizard. Also triggers when `--from` was used but the template had no location (`templateWithoutLocation` check in `resolveCreateInputs`).
102
105
-**Location default quirk**: `LocationCode` defaults to `FIN-01` in createOptions, but the wizard's `IsSet` returns false for `FIN-01` specifically, so the wizard always prompts for location even when the default is in effect.
106
+
-**Flags override template values**: When `--from` is used alongside other flags (e.g. `--hostname`, `--location`), flags are parsed first, then `applyTemplate` only overwrites empty fields. CLI flags take precedence.
103
107
-**apiCache invalidation**: Cache is invalidated when `isSpot` changes (user switches billing type), because availability differs between spot and on-demand.
104
108
-**Lazy client resolution**: `clientFunc` defers credential resolution until the first API-dependent wizard step fires. Early steps (billing-type, kind, text inputs) run without credentials.
105
109
-**Hidden flag aliases**: `--type`, `--image`, `--ssh-key-id`, `--startup-script-id`, `--spot` are hidden aliases for their primary flags.
0 commit comments