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
The image slice of the credential-locality work: CreateImage and
resolveImage now go through the cluster-access seam, so image creation
and lookup work in a remote (agent-only) zone.
- vmImageCapability gains VerbCreate (RouteVerbs) and Create/Apply
(AgentVerbs); the agent RBAC is regenerated to grant create + patch
on virtualmachineimages (patch because the agent create is
server-side apply).
- resolveImage lists via c.access.List (was a direct c.dynamic list),
so image resolution routes to the zone's agent.
- CreateImage routes via c.access.Create. Because the agent create is
SSA and SSA requires a name, the image now gets a client-assigned
"image-<random>" name instead of the apiserver's generateName; the
local path still POSTs it and Harvester imports it the same way.
resolveImage matches by display name / ID, so the assigned name is
not user-visible.
Both modules build; unit tests (new create/resolve seam tests and the
RBAC drift check) pass. CreateImage builds a VirtualMachineImage CR,
so a live structural diff of the generated object against a real
Harvester image is the remaining pre-merge check (no cluster here).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RC3BDHCFmJBdxvGVW69FAr
// ListVMs/ListImages/ListNetworks (list slice — M-D), and the image slice —
104
+
// CreateImage's create and resolveImage's create-time storageClass lookup. The
105
+
// cloud-provider SA bootstrap and the VMI read inside GetVM still call
106
+
// c.dynamic directly. The seam never leaks an agent concept past the
107
+
// ComputeProvider interface.
105
108
access clusteraccess.Accessor
106
109
107
110
// remoteRegion/remoteZone are non-empty ONLY for a credential-free REMOTE
108
111
// client built by NewRemoteClient (multi-zone routing). For such a client
109
-
// c.dynamic is nil: the seam ops (CreateVM/GetVM/DeleteVM via c.access, and
110
-
// the list reads via c.access.List) route to that zone's agent. The two
112
+
// c.dynamic is nil: the seam ops (CreateVM/GetVM/DeleteVM via c.access, the
113
+
// list reads via c.access.List, and the image slice — CreateImage's create and
114
+
// resolveImage's lookup — via c.access) route to that zone's agent. The two
111
115
// remaining direct paths behave differently on a remote client:
112
116
// - GetVM's VMI IP enrichment read DEGRADES GRACEFULLY: it is SKIPPED (the
113
117
// `c.dynamic == nil` guard returns the agent-supplied VM status WITHOUT IP
114
118
// enrichment — no error), so a remote VM's status is still reported.
115
-
// - the genuinely local-only ops — image RESOLUTION/import, the cloud-provider
116
-
// SA bootstrap, and VM create's local storageClass resolution — have no
117
-
// direct path and return a clear local-only error (localOnlyErr) naming the
118
-
// zone instead of panicking on a nil dynamic client.
119
+
// - the genuinely local-only ops — the cloud-provider SA bootstrap and VM
120
+
// create's local storageClass resolution — have no direct path and return a
121
+
// clear local-only error (localOnlyErr) naming the zone instead of panicking
122
+
// on a nil dynamic client.
119
123
// Empty for the LOCAL client → today's behaviour.
120
124
remoteRegion, remoteZonestring
121
125
}
122
126
123
-
// localOnlyErr is returned by a REMOTE client's direct-only methods (image
124
-
// resolution/import, the cloud-provider SA bootstrap, VM create which needs the
125
-
// image storageClass resolved locally). These touch c.dynamic, which a remote
126
-
// client does not have. Failing here — BEFORE a PENDING row or a provisioner
127
-
// call — is the documented local-only constraint for the remote-zone build:
128
-
// routing the VM-object CRUD lifecycle and the collection reads is in scope;
129
-
// routing image resolution/import and the SA bootstrap is future work behind this
130
-
// explicit error.
127
+
// localOnlyErr is returned by a REMOTE client's direct-only methods: VM create
128
+
// (which resolves the image storageClass — see CreateVM's note) and the
129
+
// cloud-provider SA bootstrap. These touch c.dynamic, which a remote client does
130
+
// not have. Failing here — BEFORE a PENDING row or a provisioner call — is the
131
+
// documented local-only constraint for the remote-zone build. NOTE: image
132
+
// resolution/import (resolveImage, CreateImage) and the collection reads are NO
133
+
// LONGER local-only — they route through the cluster-access seam (c.access), so a
134
+
// remote client serves them via the agent; only VM create's storageClass lookup
135
+
// and the SA bootstrap remain behind this explicit error.
131
136
func (c*Client) localOnlyErr(opstring) error {
132
137
returnfmt.Errorf(
133
-
"%s is not supported for remote zone %s/%s yet: dc-api holds no direct Harvester credentials there (image resolution/import and the cloud-provider SA bootstrap are local-only for now)",
138
+
"%s is not supported for remote zone %s/%s yet: dc-api holds no direct Harvester credentials there (VM create's storageClass resolution and the cloud-provider SA bootstrap are local-only for now)",
0 commit comments