mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-08-16 04:39:15 +00:00
fix: stale cloud-init secret name reused after VM name change (#1012)
* fix: regenerate stale cloud-init secret name after VM name change When creating a VM, the cloud-init/sysprep secret name was generated once and cached for the component's lifetime (needNewSecret is always false during create). If a first create attempt was rejected by the API (e.g. duplicate name) and the user corrected the name and retried, the VM was created successfully but reused the secret name derived from the rejected attempt, and any subsequent secret-creation failure surfaced as a stale error after the VM already existed. Now the secret name (and Windows sysprep secret name) is regenerated whenever the VM name prefix used to generate it no longer matches the current name, and is proactively reset on a failed create attempt so retries always start fresh. Fixes harvester/harvester#11174 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: copilot review Signed-off-by: Andy Lee <andy.lee@suse.com> * refactor: remove console Signed-off-by: Andy Lee <andy.lee@suse.com> --------- Signed-off-by: Andy Lee <andy.lee@suse.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
dc166d8fc9
commit
429d9e18ad
@ -484,6 +484,20 @@ export default {
|
|||||||
await value.save();
|
await value.save();
|
||||||
await this.applyHooks(AFTER_SAVE_HOOKS);
|
await this.applyHooks(AFTER_SAVE_HOOKS);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Reset the generated secret name(s) so a retried create (e.g. after correcting an
|
||||||
|
// invalid/duplicate VM name) always regenerates them from the current name instead of
|
||||||
|
// reusing names derived from this failed attempt. Only do this for create: in edit mode
|
||||||
|
// secretName/sysprep.secretName may reference an existing secret loaded from the VM,
|
||||||
|
// which must not be discarded. See harvester/harvester#11174.
|
||||||
|
if (this.isCreate) {
|
||||||
|
this.secretName = '';
|
||||||
|
this.secretNamePrefixUsed = '';
|
||||||
|
if (this.sysprepSecretNamePrefixUsed !== '') {
|
||||||
|
this.sysprep.secretName = '';
|
||||||
|
this.sysprepSecretNamePrefixUsed = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.errors.push(...exceptionToErrorsArray(e));
|
this.errors.push(...exceptionToErrorsArray(e));
|
||||||
buttonCb(false);
|
buttonCb(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -162,6 +162,12 @@ export default {
|
|||||||
machineType: '',
|
machineType: '',
|
||||||
machineTypes: [],
|
machineTypes: [],
|
||||||
secretName: '',
|
secretName: '',
|
||||||
|
// Tracks the name prefix that `secretName` was generated from, so it can be
|
||||||
|
// regenerated if the VM name changes (e.g. after a failed create attempt is retried
|
||||||
|
// with a different name). See harvester/harvester#11174.
|
||||||
|
secretNamePrefixUsed: '',
|
||||||
|
// Same purpose as secretNamePrefixUsed, but for the Windows sysprep secret name.
|
||||||
|
sysprepSecretNamePrefixUsed: '',
|
||||||
secretRef: null,
|
secretRef: null,
|
||||||
showAdvanced: false,
|
showAdvanced: false,
|
||||||
deleteAgent: true,
|
deleteAgent: true,
|
||||||
@ -866,18 +872,30 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.needNewSecret || !this.secretName) {
|
// Regenerate the cloud-init secret name whenever it hasn't been generated yet, or the VM
|
||||||
|
// name has changed since it was last generated (e.g. a previous create attempt failed with
|
||||||
|
// an invalid/duplicate name and the user corrected it). Without this, a stale secret name
|
||||||
|
// derived from a rejected attempt gets reused for the VM that's actually created.
|
||||||
|
// See harvester/harvester#11174.
|
||||||
|
if (this.needNewSecret || !this.secretName || (this.isCreate && this.secretNamePrefixUsed !== this.secretNamePrefix)) {
|
||||||
this.secretName = this.generateSecretName(this.secretNamePrefix);
|
this.secretName = this.generateSecretName(this.secretNamePrefix);
|
||||||
|
this.secretNamePrefixUsed = this.secretNamePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!disks.find((D) => D.name === 'sysprep') && this.isWindows) {
|
if (!disks.find((D) => D.name === 'sysprep') && this.isWindows) {
|
||||||
const hasSysprepContent = !!this.sysprep.xmlContent?.trim?.();
|
const hasSysprepContent = !!this.sysprep.xmlContent?.trim?.();
|
||||||
|
|
||||||
// If we have content but no secret name, it's a new secret that needs a name.
|
// If we have content but no secret name, it's a new secret that needs a name. Also
|
||||||
if (hasSysprepContent && !this.sysprep.secretName?.trim?.()) {
|
// regenerate when creating a VM if the name prefix has changed since it was last
|
||||||
|
// generated.
|
||||||
|
const sysprepNeedsNewSecretName = !this.sysprep.secretName?.trim?.() ||
|
||||||
|
(this.isCreate && this.sysprepSecretNamePrefixUsed !== '' && this.sysprepSecretNamePrefixUsed !== this.secretNamePrefix);
|
||||||
|
|
||||||
|
if (hasSysprepContent && sysprepNeedsNewSecretName) {
|
||||||
const prefix = this.secretNamePrefix ? `${ this.secretNamePrefix }-windows-sysprep` : 'windows-sysprep';
|
const prefix = this.secretNamePrefix ? `${ this.secretNamePrefix }-windows-sysprep` : 'windows-sysprep';
|
||||||
|
|
||||||
this.sysprep.secretName = `${ this.value.metadata.namespace }/${ this.generateSecretName(prefix) }`;
|
this.sysprep.secretName = `${ this.value.metadata.namespace }/${ this.generateSecretName(prefix) }`;
|
||||||
|
this.sysprepSecretNamePrefixUsed = this.secretNamePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preserve/attach sysprep whenever a secret is selected/known.
|
// Preserve/attach sysprep whenever a secret is selected/known.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user