Compare commits

..
7 Commits
Author SHA1 Message Date
mergify[bot]andAndy Lee 19b6842b21 chore: bump version to v1.6.0 (#480) (#481)
(cherry picked from commit d175e3b11a)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-26 11:22:02 +08:00
mergify[bot]andAndy Lee fa78229d3a fix: resource page detail title link (#459) (#464)
* fix: resource page detail title link



* refactor: extract harvester type in a map



* refactor: put in config/harvester-map.js



---------


(cherry picked from commit 795e5d178f)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-15 16:54:00 +08:00
mergify[bot]andAndy Lee c3bfaf00ea fix: spec.domain.memory.guest is lost issue (#462) (#463)
(cherry picked from commit 2e03ac3cf7)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-15 12:02:18 +08:00
mergify[bot]andAndy Lee 1a176960bc refactor: remove unneeded divider in storage class action menu (#460) (#461)
(cherry picked from commit 76605fdc07)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-15 10:53:56 +08:00
mergify[bot]andAndy Lee e82ba9d9f5 chore: bump version to v1.6.0-rc6 (#456) (#457)
(cherry picked from commit c289b001db)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-13 15:16:55 +08:00
mergify[bot]andYiya Chen f7fc001abd fix: fallback default value (#454) (#455)
(cherry picked from commit e8d63da1eb)

Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
Co-authored-by: Yiya Chen <yiya.chen@suse.com>
2025-08-12 13:55:37 +08:00
mergify[bot]andAndy Lee d1c676ee2c chore: update reviewer (#452) (#453)
(cherry picked from commit 4a456ac07d)

Signed-off-by: Andy Lee <andy.lee@suse.com>
Co-authored-by: Andy Lee <andy.lee@suse.com>
2025-08-05 12:41:13 +08:00
19 changed files with 137 additions and 27 deletions
-1
View File
@@ -4,4 +4,3 @@ numberOfReviewers: 0
reviewers: reviewers:
- a110605 - a110605
- houhoucoop - houhoucoop
- NickChungSUSE
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "harvester-ui-extension", "name": "harvester-ui-extension",
"version": "1.6.0-rc5", "version": "1.6.0",
"private": false, "private": false,
"engines": { "engines": {
"node": ">=20.0.0" "node": ">=20.0.0"
+13
View File
@@ -1,3 +1,5 @@
import { HCI } from '../types';
// TODO: delete this not used variable // TODO: delete this not used variable
export const MemoryUnit = [{ export const MemoryUnit = [{
label: 'Mi', label: 'Mi',
@@ -81,3 +83,14 @@ export const CSI_SECRETS = {
CSI_NODE_STAGE_SECRET_NAME: 'csi.storage.k8s.io/node-stage-secret-name', CSI_NODE_STAGE_SECRET_NAME: 'csi.storage.k8s.io/node-stage-secret-name',
CSI_NODE_STAGE_SECRET_NAMESPACE: 'csi.storage.k8s.io/node-stage-secret-namespace', CSI_NODE_STAGE_SECRET_NAMESPACE: 'csi.storage.k8s.io/node-stage-secret-namespace',
}; };
// Some harvester CRD type is not equal to model file name, define the mapping here
export const HARVESTER_CRD_MAP = {
node: HCI.HOST,
configmap: HCI.CLOUD_TEMPLATE,
persistentvolumeclaim: HCI.VOLUME,
'snapshot.storage.k8s.io.volumesnapshot': HCI.SNAPSHOT,
// specific groupable table detail page
'network.harvesterhci.io.vlanconfig': HCI.CLUSTER_NETWORK,
'kubeovn.io.subnet': HCI.VPC
};
@@ -44,6 +44,12 @@ export default {
}; };
await allHash(hash); await allHash(hash);
if (this.mode === _CREATE ) {
this.setDefaultVolumeSnapshotClass();
} else {
this.initCDISettingsFromAnnotations();
}
}, },
data() { data() {
@@ -59,14 +65,6 @@ export default {
}; };
}, },
created() {
if (this.mode === _CREATE ) {
this.setDefaultVolumeSnapshotClass();
} else {
this.initCDISettingsFromAnnotations();
}
},
computed: { computed: {
inStore() { inStore() {
return this.$store.getters['currentProduct'].inStore; return this.$store.getters['currentProduct'].inStore;
@@ -148,7 +146,7 @@ export default {
setDefaultVolumeSnapshotClass() { setDefaultVolumeSnapshotClass() {
try { try {
const setting = this.$store.getters[`${ this.inStore }/byId`](HCI.SETTING, HCI_SETTING.CSI_DRIVER_CONFIG); const setting = this.$store.getters[`${ this.inStore }/byId`](HCI.SETTING, HCI_SETTING.CSI_DRIVER_CONFIG);
const config = JSON.parse(setting?.value || '{}'); const config = JSON.parse(setting?.value || setting?.default || '{}');
const defaultClass = config?.[this.provisioner]?.volumeSnapshotClassName || null; const defaultClass = config?.[this.provisioner]?.volumeSnapshotClassName || null;
const allClasses = this.$store.getters[`${ this.inStore }/all`](VOLUME_SNAPSHOT_CLASS) || []; const allClasses = this.$store.getters[`${ this.inStore }/all`](VOLUME_SNAPSHOT_CLASS) || [];
@@ -257,6 +257,7 @@ export default {
:label="t('harvester.vmTemplate.tabs.basics')" :label="t('harvester.vmTemplate.tabs.basics')"
> >
<CpuMemory <CpuMemory
class="mb-20"
:cpu="cpu" :cpu="cpu"
:memory="memory" :memory="memory"
:max-cpu="maxCpu" :max-cpu="maxCpu"
@@ -240,7 +240,7 @@ export default {
</script> </script>
<template> <template>
<div class="mt-20"> <div>
<LabeledSelect <LabeledSelect
v-model:value="checkedSsh" v-model:value="checkedSsh"
:label="t('harvester.virtualMachine.input.sshKey')" :label="t('harvester.virtualMachine.input.sshKey')"
@@ -605,6 +605,7 @@ export default {
:label="t('harvester.virtualMachine.detail.tabs.basics')" :label="t('harvester.virtualMachine.detail.tabs.basics')"
> >
<CpuMemory <CpuMemory
class="mb-20"
:cpu="cpu" :cpu="cpu"
:max-cpu="maxCpu" :max-cpu="maxCpu"
:memory="memory" :memory="memory"
+6 -3
View File
@@ -691,11 +691,14 @@ export default {
this.spec.template.spec.domain.cpu.cores = this.cpu; this.spec.template.spec.domain.cpu.cores = this.cpu;
this.spec.template.spec.domain.resources.limits.cpu = this.cpu?.toString(); this.spec.template.spec.domain.resources.limits.cpu = this.cpu?.toString();
this.spec.template.spec.domain.resources.limits.memory = this.memory; this.spec.template.spec.domain.resources.limits.memory = this.memory;
// clean // clean below fields as we don't need them if not enable CPU and memory hotplug
delete this.spec.template.spec.resources; if (this.spec?.template?.spec?.domain?.cpu?.maxSockets) {
delete this.spec.template.spec.domain.memory;
delete this.spec.template.spec.domain.cpu.maxSockets; delete this.spec.template.spec.domain.cpu.maxSockets;
} }
if (this.spec?.template?.spec?.domain?.memory?.maxGuest) {
delete this.spec.template.spec.domain.memory.maxGuest;
}
}
}, },
parseDiskRows(disk) { parseDiskRows(disk) {
+3 -1
View File
@@ -1,17 +1,19 @@
import SteveModel from '@shell/plugins/steve/steve-class'; import SteveModel from '@shell/plugins/steve/steve-class';
import { VIEW_IN_API, DEV } from '@shell/store/prefs'; import { VIEW_IN_API, DEV } from '@shell/store/prefs';
import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../config/harvester'; import { PRODUCT_NAME as HARVESTER_PRODUCT } from '../config/harvester';
import { HARVESTER_CRD_MAP } from '../config/harvester-map';
export default class HarvesterResource extends SteveModel { export default class HarvesterResource extends SteveModel {
get listLocation() { get listLocation() {
const name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`; const name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
const resource = HARVESTER_CRD_MAP[this.type] || this.type;
return this.$rootGetters['type-map/optionsFor'](this.type).customRoute || { return this.$rootGetters['type-map/optionsFor'](this.type).customRoute || {
name, name,
params: { params: {
product: this.$rootGetters['productId'], product: this.$rootGetters['productId'],
cluster: this.$rootGetters['clusterId'], cluster: this.$rootGetters['clusterId'],
resource: this.type, resource
}, },
}; };
} }
@@ -1,3 +1,4 @@
// This file is Cloud Configuration Templates page model
import { clone } from '@shell/utils/object'; import { clone } from '@shell/utils/object';
import { HCI } from '../../types'; import { HCI } from '../../types';
import HarvesterResource from '../harvester'; import HarvesterResource from '../harvester';
@@ -12,7 +12,7 @@ export default class HarvesterNetworkAttachmentDef extends NetworkAttachmentDef
params: { params: {
product: HARVESTER_PRODUCT, product: HARVESTER_PRODUCT,
cluster: this.$rootGetters['clusterId'], cluster: this.$rootGetters['clusterId'],
resource: this.type, resource: HCI.NETWORK_ATTACHMENT,
}, },
}; };
} }
@@ -9,6 +9,19 @@ export default class HciClusterflow extends HarvesterFlow {
return this.$rootGetters['harvester/all'](LOGGING.CLUSTER_OUTPUT) || []; return this.$rootGetters['harvester/all'](LOGGING.CLUSTER_OUTPUT) || [];
} }
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.CLUSTER_FLOW;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get _detailLocation() { get _detailLocation() {
const schema = this.$getters['schemaFor'](this.type); const schema = this.$getters['schemaFor'](this.type);
@@ -21,6 +21,19 @@ export default class HciClusteroutput extends LogOutput {
}; };
} }
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.CLUSTER_OUTPUT;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get detailLocation() { get detailLocation() {
const detailLocation = clone(this._detailLocation); const detailLocation = clone(this._detailLocation);
@@ -14,6 +14,19 @@ export default class HarvesterLogFlow extends Flow {
return this.$rootGetters['harvester/all'](LOGGING.CLUSTER_OUTPUT) || []; return this.$rootGetters['harvester/all'](LOGGING.CLUSTER_OUTPUT) || [];
} }
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.FLOW;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get _detailLocation() { get _detailLocation() {
const schema = this.$getters['schemaFor'](this.type); const schema = this.$getters['schemaFor'](this.type);
@@ -22,6 +22,19 @@ export default class HarvesterLogOutput extends LogOutput {
}; };
} }
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.OUTPUT;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get detailLocation() { get detailLocation() {
const detailLocation = clone(this._detailLocation); const detailLocation = clone(this._detailLocation);
@@ -19,6 +19,19 @@ export default class HciAlertmanagerConfig extends SteveModel {
}; };
} }
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.ALERTMANAGERCONFIG;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get doneOverride() { get doneOverride() {
const detailLocation = clone(this._detailLocation); const detailLocation = clone(this._detailLocation);
+13
View File
@@ -5,6 +5,19 @@ import Secret from '@shell/models/secret';
import { NAMESPACE } from '@shell/config/types'; import { NAMESPACE } from '@shell/config/types';
export default class HciSecret extends Secret { export default class HciSecret extends Secret {
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.SECRET;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get _detailLocation() { get _detailLocation() {
const schema = this.$getters['schemaFor'](this.type); const schema = this.$getters['schemaFor'](this.type);
@@ -9,6 +9,19 @@ import { isInternalStorageClass } from '../../utils/storage-class';
export const LVM_DRIVER = 'lvm.driver.harvesterhci.io'; export const LVM_DRIVER = 'lvm.driver.harvesterhci.io';
export default class HciStorageClass extends StorageClass { export default class HciStorageClass extends StorageClass {
get listLocation() {
const listLocation = clone(super.listLocation);
listLocation.name = this.harvesterResourcesInExplorer ? 'c-cluster-product-resource' : `${ HARVESTER_PRODUCT }-c-cluster-resource`;
listLocation.params.resource = HCI.STORAGE;
return listLocation;
}
get harvesterResourcesInExplorer() {
return this.$rootGetters['productId'] !== HARVESTER_PRODUCT;
}
get detailLocation() { get detailLocation() {
const detailLocation = clone(this._detailLocation); const detailLocation = clone(this._detailLocation);
@@ -94,13 +107,14 @@ export default class HciStorageClass extends StorageClass {
get availableActions() { get availableActions() {
let out = super.availableActions || []; let out = super.availableActions || [];
out = out.map((action) => { if (this.isInternalStorageClass()) {
if ((action.action === 'setDefault' || action.action === 'setAsDefault' || action.action === 'promptRemove') && this.isInternalStorageClass()) { out = out.filter((action) => {
return { ...action, enabled: false }; return !['setDefault', 'setAsDefault', 'promptRemove'].includes(action.action);
}
return action;
}); });
}
if (out[0] && out[0].divider === true) {
out = out.slice(1);
}
return out; return out;
} }
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "harvester", "name": "harvester",
"description": "Rancher UI Extension for Harvester", "description": "Rancher UI Extension for Harvester",
"version": "1.6.0-rc5", "version": "1.6.0",
"private": false, "private": false,
"rancher": { "rancher": {
"annotations": { "annotations": {