diff --git a/pkg/harvester/formatters/HarvesterIpAddress.vue b/pkg/harvester/formatters/HarvesterIpAddress.vue
index 04eff11d..468de23d 100644
--- a/pkg/harvester/formatters/HarvesterIpAddress.vue
+++ b/pkg/harvester/formatters/HarvesterIpAddress.vue
@@ -132,16 +132,28 @@ export default {
-
+
+
diff --git a/pkg/harvester/mixins/harvester-vm/index.js b/pkg/harvester/mixins/harvester-vm/index.js
index 5c227a1e..1243fd2f 100644
--- a/pkg/harvester/mixins/harvester-vm/index.js
+++ b/pkg/harvester/mixins/harvester-vm/index.js
@@ -791,18 +791,41 @@ export default {
}
const staticIpPrefix = `${ HCI_ANNOTATIONS.STATIC_IP }/`;
+ const annotations = vm.metadata.annotations;
- Object.keys(vm.metadata.annotations).forEach((key) => {
- if (key.startsWith(staticIpPrefix)) {
- delete vm.metadata.annotations[key];
- }
- });
+ const desired = {};
this.networkRows.forEach((row) => {
if (row.name && row.staticIp) {
- vm.metadata.annotations[`${ staticIpPrefix }${ row.name }`] = row.staticIp;
+ desired[`${ staticIpPrefix }${ row.name }`] = row.staticIp;
}
});
+
+ const current = {};
+
+ Object.keys(annotations).forEach((key) => {
+ if (key.startsWith(staticIpPrefix)) {
+ current[key] = annotations[key];
+ }
+ });
+
+ // Skip mutation when already in sync to avoid triggering a reactive update loop.
+ const desiredKeys = Object.keys(desired);
+ const currentKeys = Object.keys(current);
+ const isSame = desiredKeys.length === currentKeys.length &&
+ desiredKeys.every((key) => current[key] === desired[key]);
+
+ if (isSame) {
+ return;
+ }
+
+ currentKeys.forEach((key) => {
+ delete annotations[key];
+ });
+
+ Object.entries(desired).forEach(([key, value]) => {
+ annotations[key] = value;
+ });
},
setCPUAndMemory() {