Merge the qemu-guest-agent bootstrap into each Proxy's cloud-config instead of vendor-data
In the kind cluster two KVM Proxies with real cloud-configs booted fine but never left Provisioning: the guest agent was not installed, so the provider could not learn the IP. cloud-init merges vendor-data under user-data with its default mergers, which keep the user-data's value for any key both define and never append lists, so a cloud-config with its own `packages:` silently dropped the vendor-data's packages and runcmd. The integration test passed only because its user-data was empty. withGuestAgent now appends qemu-guest-agent to `packages` and the enable command to `runcmd` of the Proxy's own cloud-config (skipping entries already present) and re-renders it. Vendor-data is no longer defaulted; `vendorData` is plain extra data. User-data that is not a cloud-config document (script, #include, MIME) still gets the bootstrap as vendor-data. A cloud-config that is not a YAML mapping, or whose packages/runcmd is not a list, fails the Proxy as ErrPermanent. Validated in-cluster: both Proxies Ready and healthy in two minutes, 204 through squid from the LAN. Docs, sample comment, CHANGELOG and the plan execution log (Run 7) updated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -30,8 +30,8 @@ func TestWithDefaults(t *testing.T) {
|
||||
if cfg.DiskSizeGB != defaultDiskSizeGB {
|
||||
t.Errorf("diskSizeGb = %d, want %d", cfg.DiskSizeGB, defaultDiskSizeGB)
|
||||
}
|
||||
if cfg.VendorData != defaultVendorData {
|
||||
t.Errorf("vendorData = %q, want the default", cfg.VendorData)
|
||||
if cfg.VendorData != "" {
|
||||
t.Errorf("vendorData = %q, want none: the guest-agent bootstrap is merged into the user-data, not defaulted here", cfg.VendorData)
|
||||
}
|
||||
if cfg.Images["debian"].Format != "qcow2" || cfg.Images["raw"].Format != "raw" {
|
||||
t.Errorf("image formats = %q/%q, want qcow2 default and raw kept", cfg.Images["debian"].Format, cfg.Images["raw"].Format)
|
||||
@@ -187,6 +187,10 @@ func assertCreated(t *testing.T, api *fakeAPI) {
|
||||
if seed.format != formatRaw || len(seed.data) == 0 || int64(len(seed.data)) != seed.capacity {
|
||||
t.Errorf("seed = format %s, %d bytes, capacity %d; want raw with capacity == uploaded size", seed.format, len(seed.data), seed.capacity)
|
||||
}
|
||||
_, files := readSeed(t, seed.data)
|
||||
if ud := files["user-data"]; !strings.Contains(ud, "squid") || !strings.Contains(ud, guestAgentPackage) {
|
||||
t.Errorf("seed user-data = %q, want the Proxy's cloud-config with the guest agent merged in", ud)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate_freshHost(t *testing.T) {
|
||||
@@ -956,7 +960,7 @@ func TestLogging_verbosityTiers(t *testing.T) {
|
||||
ctx, snapshot := captureContext(tc.verbosity)
|
||||
req := testRequest()
|
||||
const sentinel = "SENTINEL-cloud-init-must-never-be-logged"
|
||||
req.CloudInit = "#cloud-config\n" + sentinel + "\n"
|
||||
req.CloudInit = "#cloud-config\nhostname: " + sentinel + "\n"
|
||||
|
||||
runAllOps(t, ctx, req)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user