mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-01 03:36:04 +08:00
Compare commits
61
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3be7ce8783 | ||
|
|
311de06483 | ||
|
|
37ddf83f42 | ||
|
|
76bd9195f9 | ||
|
|
50d66a521d | ||
|
|
c81d2a87fd | ||
|
|
2e996d95da | ||
|
|
bdfa44186d | ||
|
|
ab2aa79037 | ||
|
|
cd86909b73 | ||
|
|
c73aca870f | ||
|
|
447be1f75d | ||
|
|
d958f443bf | ||
|
|
c43c3915b7 | ||
|
|
2e3547d0a2 | ||
|
|
1cbb6a6d54 | ||
|
|
3a3f8f60dc | ||
|
|
f7d2f1c586 | ||
|
|
4d4e3699a8 | ||
|
|
9423cf4c11 | ||
|
|
73b6193bf7 | ||
|
|
21ff6b0307 | ||
|
|
b887e5ee01 | ||
|
|
bf9b5866a7 | ||
|
|
b97017e076 | ||
|
|
3740c9c424 | ||
|
|
af8e8b2eeb | ||
|
|
7906033287 | ||
|
|
5584c86789 | ||
|
|
1dcb528717 | ||
|
|
36fc21ccbc | ||
|
|
8803b79524 | ||
|
|
3f80a71303 | ||
|
|
13e4154335 | ||
|
|
a80b87ce4f | ||
|
|
809b9925fa | ||
|
|
7788161d94 | ||
|
|
90b8a821a1 | ||
|
|
87ff014bd8 | ||
|
|
20328b06e6 | ||
|
|
bbc415a2b4 | ||
|
|
c12d4b5fba | ||
|
|
dc91be11f9 | ||
|
|
e5b72499b5 | ||
|
|
e66037b007 | ||
|
|
c676cad057 | ||
|
|
254abd4648 | ||
|
|
1df1d3534a | ||
|
|
ff1e6e6e7f | ||
|
|
622242e4a5 | ||
|
|
d8ea9be174 | ||
|
|
f8a479cfcf | ||
|
|
6d5e584113 | ||
|
|
a9eb04195e | ||
|
|
0441c1f6e3 | ||
|
|
dde58269d5 | ||
|
|
b8111f0ad7 | ||
|
|
6d627f82e9 | ||
|
|
cfc7a76fe7 | ||
|
|
71d3067354 | ||
|
|
9ecc372009 |
+4
-13
@@ -39,20 +39,11 @@
|
||||
"reviewers": ["a110605", "houhoucoop"]
|
||||
},
|
||||
{
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"automerge": false,
|
||||
"matchUpdateTypes": ["patch", "digest"],
|
||||
"automerge": true,
|
||||
"minimumReleaseAge": "7 days",
|
||||
"groupName": "patch dependencies",
|
||||
"labels": ["patch-update"],
|
||||
"reviewers": ["a110605", "houhoucoop"]
|
||||
},
|
||||
{
|
||||
"matchUpdateTypes": ["digest", "pinDigest"],
|
||||
"automerge": false,
|
||||
"groupName": "digest dependencies",
|
||||
"labels": ["digest-update"],
|
||||
"schedule": ["on the first day of the month"],
|
||||
"reviewers": ["a110605", "houhoucoop"]
|
||||
"groupName": "patch digest dependencies",
|
||||
"labels": ["patch-update", "automerge"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -43,12 +43,10 @@ jobs:
|
||||
needs:
|
||||
- setup-release-tag
|
||||
- check-version
|
||||
uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@3b26a36bad555e5e2b8634b24823be29732f287c # master
|
||||
uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@9bf23dff6650116673346447bcf0b088e0edb27f # creators-pkg-v3.0.12
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
deployments: write
|
||||
pages: write
|
||||
pull-requests: write
|
||||
with:
|
||||
target_branch: gh-pages
|
||||
tagged_release: '${{ needs.setup-release-tag.outputs.release_tag }}'
|
||||
|
||||
+7
-7
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "harvester-ui-extension",
|
||||
"version": "1.9.0-dev",
|
||||
"version": "1.8.2",
|
||||
"private": false,
|
||||
"engines": {
|
||||
"node": ">=24.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-class-static-block": "7.28.6",
|
||||
"@babel/plugin-transform-class-static-block": "7.29.7",
|
||||
"@rancher/shell": "3.0.12-rc.1",
|
||||
"@vue-flow/background": "^1.3.0",
|
||||
"@vue-flow/controls": "^1.1.1",
|
||||
@@ -21,7 +21,7 @@
|
||||
"yaml": "^2.5.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "25.6.2",
|
||||
"@types/node": "25.9.5",
|
||||
"cronstrue": "2.59.0",
|
||||
"d3-color": "3.1.0",
|
||||
"ejs": "3.1.10",
|
||||
@@ -29,13 +29,13 @@
|
||||
"glob": "7.2.3",
|
||||
"glob-parent": "6.0.2",
|
||||
"json5": "2.2.3",
|
||||
"@types/lodash": "4.17.24",
|
||||
"@types/lodash": "4.17.25",
|
||||
"merge": "2.1.1",
|
||||
"node-forge": "1.4.0",
|
||||
"nth-check": "2.1.1",
|
||||
"qs": "6.15.1",
|
||||
"roarr": "7.21.4",
|
||||
"semver": "7.8.0",
|
||||
"qs": "6.15.3",
|
||||
"roarr": "7.21.7",
|
||||
"semver": "7.8.5",
|
||||
"@vue/cli-service/html-webpack-plugin": "^5.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -122,7 +122,7 @@ export default {
|
||||
return this.$store.getters['currentCluster'].isLocal;
|
||||
},
|
||||
canEditClusterMembers() {
|
||||
return this.schema?.collectionMethods.find((x) => x.toLowerCase() === 'post');
|
||||
return this.normanClusterRTBSchema?.collectionMethods.find((x) => x.toLowerCase() === 'post');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
<script>
|
||||
import { RadioGroup } from '@components/Form/Radio';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { NAMESPACE } from '@shell/config/types';
|
||||
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterClusterPodSecurityStandard',
|
||||
|
||||
components: {
|
||||
RadioGroup,
|
||||
LabeledSelect,
|
||||
},
|
||||
|
||||
mixins: [CreateEditView],
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
|
||||
async fetch() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
await this.$store.dispatch(`${ inStore }/findAll`, { type: NAMESPACE });
|
||||
},
|
||||
|
||||
data() {
|
||||
let enabled = false;
|
||||
let whitelistedNamespaces = [];
|
||||
let privilegedNamespaces = [];
|
||||
let restrictedNamespaces = [];
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(this.value.value || this.value.default || '{}');
|
||||
|
||||
enabled = !!parsed.enabled;
|
||||
whitelistedNamespaces = parsed.whitelistedNamespacesList ? parsed.whitelistedNamespacesList.split(',') : [];
|
||||
privilegedNamespaces = parsed.privilegedNamespacesList ? parsed.privilegedNamespacesList.split(',') : [];
|
||||
restrictedNamespaces = parsed.restrictedNamespacesList ? parsed.restrictedNamespacesList.split(',') : [];
|
||||
} catch (e) {
|
||||
enabled = false;
|
||||
whitelistedNamespaces = [];
|
||||
privilegedNamespaces = [];
|
||||
restrictedNamespaces = [];
|
||||
}
|
||||
|
||||
return {
|
||||
enabled,
|
||||
whitelistedNamespaces,
|
||||
privilegedNamespaces,
|
||||
restrictedNamespaces,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
enabledOptions() {
|
||||
return [
|
||||
{ label: this.t('generic.enabled'), value: true },
|
||||
{ label: this.t('generic.disabled'), value: false },
|
||||
];
|
||||
},
|
||||
|
||||
allNamespaces() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
|
||||
return this.$store.getters[`${ inStore }/all`](NAMESPACE).filter((ns) => !ns.isSystem).map((ns) => ns.id);
|
||||
},
|
||||
|
||||
whitelistedOptions() {
|
||||
const excluded = new Set([...this.privilegedNamespaces, ...this.restrictedNamespaces]);
|
||||
|
||||
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||
},
|
||||
|
||||
privilegedOptions() {
|
||||
const excluded = new Set([...this.whitelistedNamespaces, ...this.restrictedNamespaces]);
|
||||
|
||||
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||
},
|
||||
|
||||
restrictedOptions() {
|
||||
const excluded = new Set([...this.whitelistedNamespaces, ...this.privilegedNamespaces]);
|
||||
|
||||
return this.allNamespaces.filter((ns) => !excluded.has(ns));
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
useDefault() {
|
||||
try {
|
||||
const parsed = JSON.parse(this.value.default || '{}');
|
||||
|
||||
this.enabled = !!parsed.enabled;
|
||||
this.whitelistedNamespaces = parsed.whitelistedNamespacesList ? parsed.whitelistedNamespacesList.split(',') : [];
|
||||
this.privilegedNamespaces = parsed.privilegedNamespacesList ? parsed.privilegedNamespacesList.split(',') : [];
|
||||
this.restrictedNamespaces = parsed.restrictedNamespacesList ? parsed.restrictedNamespacesList.split(',') : [];
|
||||
} catch (e) {
|
||||
this.enabled = false;
|
||||
this.whitelistedNamespaces = [];
|
||||
this.privilegedNamespaces = [];
|
||||
this.restrictedNamespaces = [];
|
||||
}
|
||||
this.save();
|
||||
},
|
||||
|
||||
onUpdateEnabled() {
|
||||
if (!this.enabled) {
|
||||
this.whitelistedNamespaces = [];
|
||||
this.privilegedNamespaces = [];
|
||||
this.restrictedNamespaces = [];
|
||||
}
|
||||
this.save();
|
||||
},
|
||||
|
||||
updateWhitelisted(selected) {
|
||||
this.whitelistedNamespaces = selected;
|
||||
this.save();
|
||||
},
|
||||
|
||||
updatePrivileged(selected) {
|
||||
this.privilegedNamespaces = selected;
|
||||
this.save();
|
||||
},
|
||||
|
||||
updateRestricted(selected) {
|
||||
this.restrictedNamespaces = selected;
|
||||
this.save();
|
||||
},
|
||||
|
||||
save() {
|
||||
this.value.value = JSON.stringify({
|
||||
enabled: this.enabled,
|
||||
whitelistedNamespacesList: this.whitelistedNamespaces.join(','),
|
||||
privilegedNamespacesList: this.privilegedNamespaces.join(','),
|
||||
restrictedNamespacesList: this.restrictedNamespaces.join(','),
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="row mb-20">
|
||||
<div class="col span-6">
|
||||
<RadioGroup
|
||||
v-model:value="enabled"
|
||||
name="enabled"
|
||||
:options="enabledOptions"
|
||||
@update:value="onUpdateEnabled"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<template v-if="enabled">
|
||||
<div class="row mb-20">
|
||||
<div class="col span-12">
|
||||
<LabeledSelect
|
||||
v-model:value="whitelistedNamespaces"
|
||||
:label="t('harvester.setting.clusterPodSecurityStandard.whitelistedNamespaces.label')"
|
||||
:options="whitelistedOptions"
|
||||
:multiple="true"
|
||||
:mode="mode"
|
||||
@update:value="updateWhitelisted"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
<div class="col span-12">
|
||||
<LabeledSelect
|
||||
v-model:value="privilegedNamespaces"
|
||||
:label="t('harvester.setting.clusterPodSecurityStandard.privilegedNamespaces.label')"
|
||||
:options="privilegedOptions"
|
||||
:multiple="true"
|
||||
:mode="mode"
|
||||
@update:value="updatePrivileged"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
<div class="col span-12">
|
||||
<LabeledSelect
|
||||
v-model:value="restrictedNamespaces"
|
||||
:label="t('harvester.setting.clusterPodSecurityStandard.restrictedNamespaces.label')"
|
||||
:options="restrictedOptions"
|
||||
:multiple="true"
|
||||
:mode="mode"
|
||||
@update:value="updateRestricted"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,11 +65,8 @@ const FEATURE_FLAGS = {
|
||||
'vGPUAsPCIDevice',
|
||||
'instanceManagerResourcesSetting',
|
||||
'rwxNetworkSetting',
|
||||
'createPVCWithDataVolume',
|
||||
'clusterPodSecurityStandardSetting'
|
||||
'createPVCWithDataVolume'
|
||||
],
|
||||
'v1.8.1': [],
|
||||
'v1.9.0': [],
|
||||
};
|
||||
|
||||
const generateFeatureFlags = () => {
|
||||
|
||||
@@ -237,7 +237,6 @@ export function init($plugin, store) {
|
||||
labelKey: 'harvester.addons.vmImport.labels.vmimport',
|
||||
group: 'vmimport',
|
||||
namespaced: true,
|
||||
ifHaveType: HCI.VMIMPORT,
|
||||
route: {
|
||||
name: `${ PRODUCT_NAME }-c-cluster-resource`,
|
||||
params: { resource: HCI.VMIMPORT }
|
||||
@@ -267,7 +266,6 @@ export function init($plugin, store) {
|
||||
labelKey: 'harvester.addons.vmImport.labels.vmimportSourceVMWare',
|
||||
group: 'vmimport',
|
||||
namespaced: true,
|
||||
ifHaveType: HCI.VMIMPORT_SOURCE_V,
|
||||
route: {
|
||||
name: `${ PRODUCT_NAME }-c-cluster-resource`,
|
||||
params: { resource: HCI.VMIMPORT_SOURCE_V }
|
||||
@@ -297,7 +295,6 @@ export function init($plugin, store) {
|
||||
labelKey: 'harvester.addons.vmImport.labels.vmimportSourceOpenStack',
|
||||
group: 'vmimport',
|
||||
namespaced: true,
|
||||
ifHaveType: HCI.VMIMPORT_SOURCE_O,
|
||||
route: {
|
||||
name: `${ PRODUCT_NAME }-c-cluster-resource`,
|
||||
params: { resource: HCI.VMIMPORT_SOURCE_O }
|
||||
@@ -326,7 +323,6 @@ export function init($plugin, store) {
|
||||
labelKey: 'harvester.addons.vmImport.labels.vmimportSourceOVA',
|
||||
group: 'vmimport',
|
||||
namespaced: true,
|
||||
ifHaveType: HCI.VMIMPORT_SOURCE_OVA,
|
||||
route: {
|
||||
name: `${ PRODUCT_NAME }-c-cluster-resource`,
|
||||
params: { resource: HCI.VMIMPORT_SOURCE_OVA }
|
||||
@@ -488,7 +484,6 @@ export function init($plugin, store) {
|
||||
});
|
||||
|
||||
virtualType({
|
||||
ifHaveType: LOGGING.CLUSTER_FLOW,
|
||||
labelKey: 'harvester.logging.clusterFlow.label',
|
||||
name: HCI.CLUSTER_FLOW,
|
||||
namespaced: true,
|
||||
@@ -512,7 +507,6 @@ export function init($plugin, store) {
|
||||
});
|
||||
|
||||
virtualType({
|
||||
ifHaveType: LOGGING.CLUSTER_OUTPUT,
|
||||
labelKey: 'harvester.logging.clusterOutput.label',
|
||||
name: HCI.CLUSTER_OUTPUT,
|
||||
namespaced: true,
|
||||
@@ -536,7 +530,6 @@ export function init($plugin, store) {
|
||||
});
|
||||
|
||||
virtualType({
|
||||
ifHaveType: LOGGING.FLOW,
|
||||
labelKey: 'harvester.logging.flow.label',
|
||||
name: HCI.FLOW,
|
||||
namespaced: true,
|
||||
@@ -560,7 +553,6 @@ export function init($plugin, store) {
|
||||
});
|
||||
|
||||
virtualType({
|
||||
ifHaveType: LOGGING.OUTPUT,
|
||||
labelKey: 'harvester.logging.output.label',
|
||||
name: HCI.OUTPUT,
|
||||
namespaced: true,
|
||||
@@ -694,7 +686,7 @@ export function init($plugin, store) {
|
||||
},
|
||||
resource: NETWORK_ATTACHMENT,
|
||||
resourceDetail: HCI.NETWORK_ATTACHMENT,
|
||||
resourceEdit: HCI.NETWORK_ATTACHMENT,
|
||||
resourceEdit: HCI.NETWORK_ATTACHMENT
|
||||
});
|
||||
|
||||
virtualType({
|
||||
|
||||
@@ -41,8 +41,7 @@ export const HCI_SETTING = {
|
||||
RANCHER_CLUSTER: 'rancher-cluster',
|
||||
MAX_HOTPLUG_RATIO: 'max-hotplug-ratio',
|
||||
KUBEVIRT_MIGRATION: 'kubevirt-migration',
|
||||
INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources',
|
||||
CLUSTER_POD_SECURITY_STANDARD: 'cluster-pod-security-standard'
|
||||
INSTANCE_MANAGER_RESOURCES: 'instance-manager-resources'
|
||||
};
|
||||
|
||||
export const HCI_ALLOWED_SETTINGS = {
|
||||
@@ -131,9 +130,6 @@ export const HCI_ALLOWED_SETTINGS = {
|
||||
},
|
||||
[HCI_SETTING.INSTANCE_MANAGER_RESOURCES]: {
|
||||
kind: 'json', from: 'import', featureFlag: 'instanceManagerResourcesSetting'
|
||||
},
|
||||
[HCI_SETTING.CLUSTER_POD_SECURITY_STANDARD]: {
|
||||
kind: 'json', from: 'import', canReset: true, featureFlag: 'clusterPodSecurityStandardSetting'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,11 +27,15 @@ export default {
|
||||
await allHash({
|
||||
vms: this.$store.dispatch('harvester/findAll', { type: HCI.VM }),
|
||||
vmis: this.$store.dispatch('harvester/findAll', { type: HCI.VMI }),
|
||||
vmims: this.$store.dispatch('harvester/findAll', { type: HCI.VMIM }),
|
||||
allClusterNetwork: this.$store.dispatch('harvester/findAll', { type: HCI.CLUSTER_NETWORK }),
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
allClusterNetwork() {
|
||||
return this.$store.getters['harvester/all'](HCI.CLUSTER_NETWORK);
|
||||
},
|
||||
|
||||
rows() {
|
||||
const vms = this.$store.getters['harvester/all'](HCI.VM);
|
||||
|
||||
@@ -104,6 +108,7 @@ export default {
|
||||
<HarvesterVmState
|
||||
class="vmstate"
|
||||
:row="scope.row"
|
||||
:all-cluster-network="allClusterNetwork"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
<script>
|
||||
import merge from 'lodash/merge';
|
||||
import jsyaml from 'js-yaml';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { Card } from '@components/Card';
|
||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||
import AsyncButton from '@shell/components/AsyncButton';
|
||||
import { escapeHtml } from '@shell/utils/string';
|
||||
|
||||
const DEFAULT_VALUE = { image: { repository: 'rancher/harvester-nvidia-driver-toolkit' } };
|
||||
|
||||
export default {
|
||||
name: 'HarvesterEnableNvidiaDriverToolkit',
|
||||
|
||||
emits: ['close'],
|
||||
|
||||
components: {
|
||||
AsyncButton,
|
||||
Card,
|
||||
LabeledInput,
|
||||
},
|
||||
|
||||
props: {
|
||||
resources: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
const addon = this.resources[0];
|
||||
let valuesContentJson;
|
||||
|
||||
try {
|
||||
valuesContentJson = merge({}, DEFAULT_VALUE, jsyaml.load(addon.spec.valuesContent));
|
||||
} catch (e) {
|
||||
valuesContentJson = { ...DEFAULT_VALUE };
|
||||
}
|
||||
|
||||
return { valuesContentJson };
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters({ t: 'i18n/t' }),
|
||||
|
||||
buttonDisabled() {
|
||||
const { image, driverLocation } = this.valuesContentJson;
|
||||
|
||||
return !(image?.repository || '').trim() || !(image?.tag || '').trim() || !(driverLocation || '').trim();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('close');
|
||||
},
|
||||
|
||||
async enable(buttonCb) {
|
||||
const addon = this.resources[0];
|
||||
|
||||
try {
|
||||
addon.spec.valuesContent = jsyaml.dump(this.valuesContentJson);
|
||||
addon.spec.enabled = true;
|
||||
await addon.save();
|
||||
buttonCb(true);
|
||||
this.close();
|
||||
} catch (err) {
|
||||
addon.spec.enabled = false;
|
||||
this.$store.dispatch('growl/fromError', {
|
||||
title: this.t('generic.notification.title.error', { name: escapeHtml(addon.metadata.name) }),
|
||||
err,
|
||||
}, { root: true });
|
||||
buttonCb(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card :show-highlight-border="false">
|
||||
<template #title>
|
||||
<h4
|
||||
v-clean-html="t('harvester.addons.nvidiaDriverToolkit.enable.title')"
|
||||
class="text-default-text"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<div class="body">
|
||||
<div class="row mb-15">
|
||||
<div class="col span-6">
|
||||
<LabeledInput
|
||||
v-model:value="valuesContentJson.image.repository"
|
||||
:required="true"
|
||||
:label="t('harvester.addons.nvidiaDriverToolkit.image.repository')"
|
||||
/>
|
||||
</div>
|
||||
<div class="col span-6">
|
||||
<LabeledInput
|
||||
v-model:value="valuesContentJson.image.tag"
|
||||
:required="true"
|
||||
:label="t('harvester.addons.nvidiaDriverToolkit.image.tag')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-15">
|
||||
<div class="col span-12">
|
||||
<LabeledInput
|
||||
v-model:value="valuesContentJson.driverLocation"
|
||||
:required="true"
|
||||
:label="t('harvester.addons.nvidiaDriverToolkit.driver.location')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<div class="buttons actions">
|
||||
<button
|
||||
class="btn role-secondary mr-10"
|
||||
@click="close"
|
||||
>
|
||||
{{ t('generic.cancel') }}
|
||||
</button>
|
||||
|
||||
<AsyncButton
|
||||
mode="enable"
|
||||
:disabled="buttonDisabled"
|
||||
@click="enable"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,15 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import { NODE } from '@shell/config/types';
|
||||
import { exceptionToErrorsArray } from '@shell/utils/error';
|
||||
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
||||
|
||||
import { Card } from '@components/Card';
|
||||
import { Banner } from '@components/Banner';
|
||||
import AsyncButton from '@shell/components/AsyncButton';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import { HCI } from '../types';
|
||||
|
||||
export default {
|
||||
emits: ['close'],
|
||||
@@ -59,46 +62,28 @@ export default {
|
||||
return this.resources[0];
|
||||
},
|
||||
|
||||
anyCpuPinning() {
|
||||
return this.resources.some((r) => r.isCpuPinning);
|
||||
},
|
||||
vmi() {
|
||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||
const vmiResources = this.$store.getters[`${ inStore }/all`](HCI.VMI);
|
||||
const resource = vmiResources.find((VMI) => VMI.id === this.actionResource?.id) || null;
|
||||
|
||||
vmsByNode() {
|
||||
const groups = {};
|
||||
|
||||
for (const r of this.resources) {
|
||||
const node = r.nodeName || '';
|
||||
const name = r.nameDisplay || r.name || r.id;
|
||||
|
||||
if (!groups[node]) {
|
||||
groups[node] = [];
|
||||
}
|
||||
groups[node].push(name);
|
||||
}
|
||||
|
||||
return Object.entries(groups).map(([node, vms]) => ({ node, vms })).sort((a, b) => a.node.localeCompare(b.node));
|
||||
return resource;
|
||||
},
|
||||
|
||||
cpuPinningAlertMessage() {
|
||||
return this.t('harvester.virtualMachine.cpuPinning.migrationMessage');
|
||||
},
|
||||
|
||||
allVmsOnTargetNode() {
|
||||
if (!this.nodeName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.resources.every((r) => r.nodeName === this.nodeName);
|
||||
},
|
||||
|
||||
nodeNameList() {
|
||||
const nodes = this.$store.getters['harvester/all'](NODE);
|
||||
|
||||
return nodes.filter((n) => {
|
||||
const isNotSelfNode = !!this.availableNodes.includes(n.id);
|
||||
const isNotWitnessNode = n.isEtcd !== 'true'; // do not allow to migrate to self node and witness node
|
||||
const matchingCpuManagerConfig = !this.anyCpuPinning || n.isCPUManagerEnabled; // If cpu-pinning is enabled, filter-out non-enabled CPU manager nodes.
|
||||
const isCpuPinning = this.actionResource?.isCpuPinning;
|
||||
const matchingCpuManagerConfig = !isCpuPinning || n.isCPUManagerEnabled; // If cpu-pinning is enabled, filter-out non-enabled CPU manager nodes.
|
||||
|
||||
return isNotWitnessNode && matchingCpuManagerConfig;
|
||||
return isNotSelfNode && isNotWitnessNode && matchingCpuManagerConfig;
|
||||
}).map((n) => {
|
||||
let label = n?.metadata?.name;
|
||||
const value = n?.metadata?.name;
|
||||
@@ -141,29 +126,7 @@ export default {
|
||||
}
|
||||
|
||||
try {
|
||||
// Filter out VMs already running on the selected node
|
||||
const toMigrate = this.resources.filter((r) => r.nodeName !== this.nodeName);
|
||||
|
||||
// await Promise.allSettled(toMigrate.map((r) => r.doAction('migrate', { nodeName: this.nodeName }, {}, false)));
|
||||
// We want to show all migration errors if there are multiple VMs, so we use allSettled here and handle the results accordingly.
|
||||
const results = await Promise.allSettled(toMigrate.map((r) => r.doAction('migrate', { nodeName: this.nodeName }, {}, false)));
|
||||
|
||||
const failedMigrations = results
|
||||
.map((result, index) => ({ resource: toMigrate[index], result }))
|
||||
.filter(({ result }) => result.status === 'rejected');
|
||||
|
||||
if (failedMigrations.length) {
|
||||
this['errors'] = failedMigrations.flatMap(({ resource, result }) => {
|
||||
const vmName = resource?.nameDisplay || resource?.name || resource?.metadata?.name || this.$store.getters['i18n/t']('generic.unknown');
|
||||
const error = result.reason?.data || result.reason;
|
||||
const messages = exceptionToErrorsArray(error);
|
||||
|
||||
return messages.map((message) => `${ vmName }: ${ message }`);
|
||||
});
|
||||
buttonDone(false);
|
||||
|
||||
return;
|
||||
}
|
||||
await this.actionResource.doAction('migrate', { nodeName: this.nodeName }, {}, false);
|
||||
|
||||
buttonDone(true);
|
||||
this.close();
|
||||
@@ -183,35 +146,17 @@ export default {
|
||||
<template>
|
||||
<Card :show-highlight-border="false">
|
||||
<template #title>
|
||||
{{ t('harvester.modal.migration.vmMigrationTitle', { count: resources.length }) }}
|
||||
{{ t('harvester.modal.migration.title') }}
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<Banner
|
||||
v-if="anyCpuPinning"
|
||||
v-if="actionResource?.isCpuPinning"
|
||||
color="warning"
|
||||
:label="cpuPinningAlertMessage"
|
||||
/>
|
||||
<p>
|
||||
{{ t('harvester.modal.migration.selectedVMs') }}
|
||||
</p>
|
||||
<ul class="vm-list">
|
||||
<li
|
||||
v-for="group in vmsByNode"
|
||||
:key="group.node"
|
||||
>
|
||||
{{ group.node || t('harvester.modal.migration.unknownNode') }}: {{ group.vms.join(', ') }}
|
||||
<span
|
||||
v-if="nodeName && group.node === nodeName"
|
||||
class="already-on-target"
|
||||
>
|
||||
({{ t('harvester.modal.migration.alreadyOnTarget') }})
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<LabeledSelect
|
||||
v-model:value="nodeName"
|
||||
class="mt-15"
|
||||
:label="t('harvester.modal.migration.fields.nodeName.label')"
|
||||
:placeholder="t('harvester.modal.migration.fields.nodeName.placeholder')"
|
||||
:options="nodeNameList"
|
||||
@@ -238,7 +183,7 @@ export default {
|
||||
|
||||
<AsyncButton
|
||||
mode="apply"
|
||||
:disabled="!nodeName || allVmsOnTargetNode"
|
||||
:disabled="!nodeName"
|
||||
@click="apply"
|
||||
/>
|
||||
</div>
|
||||
@@ -256,16 +201,4 @@ export default {
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.already-on-target {
|
||||
color: var(--warning);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.vm-list {
|
||||
list-style: disc;
|
||||
padding-left: 1.5em;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,7 +8,6 @@ import FileSelector, { createOnSelected } from '@shell/components/form/FileSelec
|
||||
|
||||
import { randomStr } from '@shell/utils/string';
|
||||
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||
import { getLoginAwareErrors } from '../utils/error';
|
||||
|
||||
export default {
|
||||
name: 'HarvesterEditKeypair',
|
||||
@@ -64,14 +63,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
normalizedErrors() {
|
||||
const message = this.t('harvester.virtualMachine.genericLoginError');
|
||||
|
||||
return getLoginAwareErrors(this.errors, message);
|
||||
}
|
||||
},
|
||||
|
||||
methods: { onKeySelected: createOnSelected('publicKey') },
|
||||
};
|
||||
</script>
|
||||
@@ -81,9 +72,10 @@ export default {
|
||||
:done-route="doneRoute"
|
||||
:resource="value"
|
||||
:mode="mode"
|
||||
:errors="normalizedErrors"
|
||||
:errors="errors"
|
||||
:apply-hooks="applyHooks"
|
||||
@finish="save"
|
||||
@error="e=>errors=e"
|
||||
>
|
||||
<div class="header mb-20">
|
||||
<FileSelector
|
||||
|
||||
@@ -254,24 +254,15 @@ export default {
|
||||
v-if="restoreNewVm"
|
||||
v-model:value="restoreResource.spec.keepMacAddress"
|
||||
type="checkbox"
|
||||
class="check mb-20"
|
||||
:label="t('harvester.backup.restore.keepMacAddress')"
|
||||
/>
|
||||
|
||||
<LabeledSelect
|
||||
v-if="!restoreNewVm"
|
||||
v-model:value="deletionPolicy"
|
||||
class="mb-20"
|
||||
:label="t('harvester.backup.restore.deletePreviousVolumes')"
|
||||
:options="deletionPolicyOption"
|
||||
/>
|
||||
|
||||
<Checkbox
|
||||
v-model:value="restoreResource.spec.haltAfterRestore"
|
||||
type="checkbox"
|
||||
class="check mb-20"
|
||||
:label="t('harvester.backup.restore.haltAfterRestore')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Footer
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import Footer from '@shell/components/form/Footer';
|
||||
import { RadioGroup } from '@components/Form/Radio';
|
||||
import { LabeledInput } from '@components/Form/LabeledInput';
|
||||
import Checkbox from '@components/Form/Checkbox/Checkbox';
|
||||
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import CreateEditView from '@shell/mixins/create-edit-view';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
@@ -33,7 +32,6 @@ const createObject = {
|
||||
export default {
|
||||
name: 'CreateRestore',
|
||||
components: {
|
||||
Checkbox,
|
||||
Footer,
|
||||
RadioGroup,
|
||||
LabeledInput,
|
||||
@@ -251,17 +249,9 @@ export default {
|
||||
<LabeledSelect
|
||||
v-if="!restoreNewVm"
|
||||
v-model:value="deletionPolicy"
|
||||
class="mb-20"
|
||||
:label="t('harvester.backup.restore.deletePreviousVolumes')"
|
||||
:options="deletionPolicyOption"
|
||||
/>
|
||||
|
||||
<Checkbox
|
||||
v-model:value="restoreResource.spec.haltAfterRestore"
|
||||
type="checkbox"
|
||||
class="check mb-20"
|
||||
:label="t('harvester.backup.restore.haltAfterRestore')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Footer
|
||||
|
||||
+38
-24
@@ -152,10 +152,6 @@ export default {
|
||||
return !rows.find((device) => !device.passthroughClaim);
|
||||
},
|
||||
|
||||
canManageGroup(rows = []) {
|
||||
return rows.length > 0 && rows.every((row) => row.canUpdate === true);
|
||||
},
|
||||
|
||||
changeRows(filterRows, parentSriov) {
|
||||
this['filterRows'] = filterRows;
|
||||
this['parentSriov'] = parentSriov;
|
||||
@@ -189,27 +185,22 @@ export default {
|
||||
v-trim-whitespace
|
||||
class="group-tab"
|
||||
>
|
||||
<div
|
||||
v-if="canManageGroup(group.rows)"
|
||||
class="group-actions"
|
||||
<button
|
||||
v-if="groupIsAllEnabled(group.rows)"
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{disableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
<button
|
||||
v-if="groupIsAllEnabled(group.rows)"
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{disableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.pci.disableGroup') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{enableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.pci.enableGroup') }}
|
||||
</button>
|
||||
</div>
|
||||
{{ t('harvester.pci.disableGroup') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{enableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.pci.enableGroup') }}
|
||||
</button>
|
||||
<span v-clean-html="group.key" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -246,4 +237,27 @@ export default {
|
||||
.group-actions {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
// Match the enable/disable passthrough bulk-action buttons height to the .btn (40px) on the right.
|
||||
:deep(.bulk .rc-button.btn-medium.bulk-action:not(.btn-sm)) {
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
// Make the collapsed "Actions" dropdown button 40px too.
|
||||
:deep(.bulk .rc-button.btn-medium.bulk-actions-dropdown:not(.btn-sm)) {
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
// Lay the bulk row out with flex so the "N selected" label can wrap below the buttons.
|
||||
:deep(.bulk) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.bulk .action-availability) {
|
||||
flex-basis: 100%;
|
||||
margin-left: 0;
|
||||
margin-top: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,6 +5,7 @@ import LabeledSelect from '@shell/components/form/LabeledSelect';
|
||||
import Banner from '@components/Banner/Banner.vue';
|
||||
import remove from 'lodash/remove';
|
||||
import { set } from '@shell/utils/object';
|
||||
import { uniq } from '@shell/utils/array';
|
||||
import { HCI } from '../../../types';
|
||||
import DeviceList from './DeviceList';
|
||||
import CompatibilityMatrix from '../CompatibilityMatrix';
|
||||
@@ -52,31 +53,29 @@ export default {
|
||||
}
|
||||
|
||||
const selectedDevices = [];
|
||||
const oldFormatDevices = [];
|
||||
|
||||
const vmDevices = this.value?.domain?.devices?.hostDevices || [];
|
||||
const otherDevices = this.otherDevices(vmDevices).map(({ name }) => name);
|
||||
const vmDeviceNames = vmDevices.map(({ name }) => name);
|
||||
|
||||
this.pciDevices.forEach((row) => {
|
||||
row.allowDisable = !vmDeviceNames.includes(row.metadata.name);
|
||||
});
|
||||
|
||||
vmDevices.forEach(({ name, deviceName }) => {
|
||||
const checkName = (deviceName || '').split('/')?.[1];
|
||||
// When off, read from spec; otherwise the spec name is a placeholder ('provisioned'),
|
||||
// so read the real allocated device names from the deviceAllocationDetails annotation.
|
||||
const hostDeviceNames = this.vm.isOff ? [
|
||||
...vmDevices.map(({ name }) => name),
|
||||
] : [
|
||||
...Object.values(this.vm?.provisionedHostDevices || {}).reduce((acc, devices) => [...acc, ...devices], []),
|
||||
];
|
||||
|
||||
if (checkName && name.includes(checkName) && !otherDevices.includes(name)) {
|
||||
oldFormatDevices.push(name);
|
||||
} else if (this.enabledDevices.find((device) => device?.metadata?.name === name)) {
|
||||
uniq(hostDeviceNames).forEach((name) => {
|
||||
if (this.enabledDevices.find((device) => device?.metadata?.name === name)) {
|
||||
selectedDevices.push(name);
|
||||
}
|
||||
});
|
||||
|
||||
if (oldFormatDevices.length > 0) {
|
||||
this.oldFormatDevices = oldFormatDevices;
|
||||
} else {
|
||||
this.selectedDevices = selectedDevices;
|
||||
}
|
||||
this.selectedDevices = selectedDevices;
|
||||
},
|
||||
|
||||
data() {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { _VIEW } from '@shell/config/query-params';
|
||||
|
||||
import { NAMESPACE } from '@shell/config/types';
|
||||
import { HCI } from '../../types';
|
||||
import { getLoginAwareErrors } from '../../utils/error';
|
||||
|
||||
const _NEW = '_NEW';
|
||||
|
||||
@@ -215,9 +214,7 @@ export default {
|
||||
buttonCb(true);
|
||||
this.cancel();
|
||||
} catch (err) {
|
||||
const message = this.t('harvester.virtualMachine.genericLoginError');
|
||||
|
||||
this.errors = getLoginAwareErrors(err, message);
|
||||
this.errors = [err.message];
|
||||
buttonCb(false);
|
||||
}
|
||||
},
|
||||
|
||||
+15
-37
@@ -64,12 +64,6 @@ export default {
|
||||
value: 'status.productID',
|
||||
sort: ['status.productID', 'status.vendorID']
|
||||
},
|
||||
{
|
||||
name: 'classType',
|
||||
labelKey: 'harvester.usb.classType',
|
||||
value: 'status.classType',
|
||||
sort: ['status.classType']
|
||||
},
|
||||
];
|
||||
|
||||
if (!isSingleProduct) {
|
||||
@@ -113,11 +107,6 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
canManageGroup(rows = []) {
|
||||
return rows.every((row) => row.canUpdate === true);
|
||||
},
|
||||
|
||||
groupIsAllEnabled(rows = []) {
|
||||
return !rows.find((device) => !device.passthroughClaim);
|
||||
},
|
||||
@@ -158,27 +147,22 @@ export default {
|
||||
v-trim-whitespace
|
||||
class="group-tab"
|
||||
>
|
||||
<div
|
||||
v-if="canManageGroup(group.rows)"
|
||||
class="group-actions"
|
||||
<button
|
||||
v-if="groupIsAllEnabled(group.rows)"
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{disableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
<button
|
||||
v-if="groupIsAllEnabled(group.rows)"
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{disableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.usb.disableGroup') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{enableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.usb.enableGroup') }}
|
||||
</button>
|
||||
</div>
|
||||
{{ t('harvester.usb.disableGroup') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-sm role-secondary mr-5"
|
||||
@click="e=>{enableGroup(group.rows); e.target.blur()}"
|
||||
>
|
||||
{{ t('harvester.usb.enableGroup') }}
|
||||
</button>
|
||||
<span v-clean-html="group.key" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -191,9 +175,3 @@ export default {
|
||||
</template>
|
||||
</ResourceTable>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.group-actions {
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -475,6 +475,7 @@ export default {
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm bg-primary mr-15 mb-10"
|
||||
:disabled="rows.length === 0"
|
||||
@click="addVolume(SOURCE_TYPE.NEW)"
|
||||
>
|
||||
{{ t('harvester.virtualMachine.volume.addVolume') }}
|
||||
|
||||
@@ -20,7 +20,12 @@ export default {
|
||||
|
||||
computed: {
|
||||
vmiResource() {
|
||||
return this.$store.getters['harvester/byId'](HCI.VMI, this.vmResource?.id) || null;
|
||||
const vmiList = this.$store.getters['harvester/all'](HCI.VMI) || [];
|
||||
const vmi = vmiList.find( (VMI) => {
|
||||
return VMI?.metadata?.ownerReferences?.[0]?.uid === this.vmResource?.metadata?.uid;
|
||||
});
|
||||
|
||||
return vmi;
|
||||
},
|
||||
migrationState() {
|
||||
return this.vmiResource?.migrationState?.status || '';
|
||||
|
||||
@@ -14,6 +14,20 @@ export default {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
|
||||
allNodeNetwork: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
allClusterNetwork: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
|
||||
@@ -144,10 +144,6 @@ harvester:
|
||||
migration:
|
||||
failedMessage: Latest migration failed!
|
||||
title: Migration
|
||||
vmMigrationTitle: '{count, plural, one {Migrating # VM} other {Migrating # VMs}}'
|
||||
selectedVMs: "The following virtual machine(s) will be migrated to the target node"
|
||||
unknownNode: (unknown node)
|
||||
alreadyOnTarget: Already on Target
|
||||
fields:
|
||||
nodeName:
|
||||
label: Target Node
|
||||
@@ -252,7 +248,6 @@ harvester:
|
||||
suspendSchedule: Suspend
|
||||
restoreExistingVM: Replace Existing
|
||||
migrate: Migrate
|
||||
vmMigrate: Virtual Machine Migration
|
||||
cpuAndMemoryHotplug: Edit CPU and Memory
|
||||
abortMigration: Abort Migration
|
||||
storageMigration: Storage Migration
|
||||
@@ -303,7 +298,6 @@ harvester:
|
||||
phase: Phase
|
||||
attachedVM: Attached Virtual Machine
|
||||
cpuManager: CPU Manager
|
||||
routeConnectivityTooltip: Connectivity between the VM network and the management network, which the Harvester nodes are connected to.
|
||||
fingerprint: Fingerprint
|
||||
value: Value
|
||||
actions: Actions
|
||||
@@ -732,7 +726,6 @@ harvester:
|
||||
other {Start}
|
||||
} Now
|
||||
createSSHKey: Create a New...
|
||||
genericLoginError: Authentication failed. Please re-log in and try again.
|
||||
installAgent: Install guest agent
|
||||
enableUsb: Enable USB Tablet
|
||||
advancedOptions:
|
||||
@@ -1118,7 +1111,6 @@ harvester:
|
||||
replaceExisting: Replace existing
|
||||
virtualMachineName: Virtual Machine Name
|
||||
keepMacAddress: Keep MAC Address
|
||||
haltAfterRestore: Keep powered off after restore
|
||||
matchTarget: The current backup target does not match the existing one.
|
||||
progress:
|
||||
details: Volume details
|
||||
@@ -1293,13 +1285,6 @@ harvester:
|
||||
rancherCluster:
|
||||
kubeConfig: Rancher KubeConfig
|
||||
removeUpstreamClusterWhenNamespaceIsDeleted: Remove Upstream Cluster When Namespace Is Deleted
|
||||
clusterPodSecurityStandard:
|
||||
whitelistedNamespaces:
|
||||
label: 'Whitelisted Namespaces'
|
||||
privilegedNamespaces:
|
||||
label: 'Privileged Namespaces'
|
||||
restrictedNamespaces:
|
||||
label: 'Restricted Namespaces'
|
||||
storageNetwork:
|
||||
range:
|
||||
placeholder: e.g. 172.16.0.0/24
|
||||
@@ -1523,7 +1508,6 @@ harvester:
|
||||
vmSnapshot:
|
||||
label: Virtual Machine Snapshots
|
||||
createText: Restore Snapshot
|
||||
title: Restore Virtual Machine
|
||||
snapshot: Snapshot
|
||||
|
||||
storage:
|
||||
@@ -1780,8 +1764,6 @@ harvester:
|
||||
repository: Image Repository
|
||||
driver:
|
||||
location: Driver Location
|
||||
enable:
|
||||
title: Enable NVIDIA Driver Toolkit
|
||||
parsingSpecError:
|
||||
The field 'spec.valuesContent' has invalid format.
|
||||
usbController:
|
||||
@@ -1973,7 +1955,6 @@ harvester:
|
||||
title: Cannot Disable Passthrough
|
||||
message: Please detach the device from the VM and save it first before disabling passthrough.
|
||||
enablePassthroughWarning: 'Please re-enable the USB device if the device path changes in the following situations:<br/> 1) Re-plugging the USB device.<br/> 2) Rebooting the node.<br/><br/>An incorrect device path may cause passthrough to fail.'
|
||||
classType: Class Type
|
||||
|
||||
harvesterVlanConfigMigrateDialog:
|
||||
targetClusterNetwork:
|
||||
@@ -2058,7 +2039,6 @@ advancedSettings:
|
||||
'harv-max-hotplug-ratio': 'The ratio for kubevirt to limit the maximum CPU and memory that can be hotplugged to a VM. The value could be an integer between 1 and 20, default to 4.'
|
||||
'harv-kubevirt-migration': 'Configure cluster-wide KubeVirt live migration parameters.'
|
||||
'harv-instance-manager-resources': 'Configure resource percentage reservations for Longhorn instance manager V1 and V2. Valid instance manager CPU range between 0 - 40.'
|
||||
'harv-cluster-pod-security-standard': 'Enforce Kubernetes Pod Security Standards (PSS) at the cluster level.'
|
||||
|
||||
typeLabel:
|
||||
kubevirt.io.virtualmachine: |-
|
||||
@@ -2181,7 +2161,11 @@ typeLabel:
|
||||
one { PCI Device }
|
||||
other { PCI Devices }
|
||||
}
|
||||
|
||||
persistentvolumeclaim: |-
|
||||
{count, plural,
|
||||
one { Volume }
|
||||
other { Volumes }
|
||||
}
|
||||
network.harvesterhci.io.clusternetwork: |-
|
||||
{count, plural,
|
||||
one { Cluster Network }
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Banner } from '@components/Banner';
|
||||
import Loading from '@shell/components/Loading';
|
||||
import ResourceTable from '@shell/components/ResourceTable';
|
||||
import BadgeState from '@shell/components/formatter/BadgeStateFormatter';
|
||||
|
||||
import { NAME, AGE, NAMESPACE, STATE } from '@shell/config/table-headers';
|
||||
import { NETWORK_ATTACHMENT, SCHEMA } from '@shell/config/types';
|
||||
import { allHash } from '@shell/utils/promise';
|
||||
@@ -112,7 +113,6 @@ export default {
|
||||
value: 'connectivity',
|
||||
labelKey: 'tableHeaders.routeConnectivity',
|
||||
formatter: 'NetworkRouteConnectivity',
|
||||
tooltip: 'harvester.tableHeaders.routeConnectivityTooltip',
|
||||
formatterOpts: { arbitrary: true },
|
||||
width: 130,
|
||||
},
|
||||
|
||||
@@ -12,11 +12,6 @@ import { HCI } from '../types';
|
||||
import HarvesterVmState from '../formatters/HarvesterVmState';
|
||||
import ConsoleBar from '../components/VMConsoleBar';
|
||||
|
||||
const ENCRYPTED_VOLUME_TOOLTIP_KEYS = {
|
||||
all: 'harvester.virtualMachine.volume.lockTooltip.all',
|
||||
partial: 'harvester.virtualMachine.volume.lockTooltip.partial',
|
||||
};
|
||||
|
||||
export const VM_HEADERS = [
|
||||
STATE,
|
||||
{
|
||||
@@ -98,9 +93,19 @@ export default {
|
||||
this.hasNode = true;
|
||||
}
|
||||
|
||||
if (this.$store.getters[`${ inStore }/schemaFor`](HCI.NODE_NETWORK)) {
|
||||
_hash.nodeNetworks = this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.NODE_NETWORK });
|
||||
}
|
||||
|
||||
if (this.$store.getters[`${ inStore }/schemaFor`](HCI.CLUSTER_NETWORK)) {
|
||||
_hash.clusterNetworks = this.$store.dispatch(`${ inStore }/findAll`, { type: HCI.CLUSTER_NETWORK });
|
||||
}
|
||||
|
||||
const hash = await allHash(_hash);
|
||||
|
||||
this.allVMs = hash.vms;
|
||||
this.allNodeNetworks = hash.nodeNetworks || [];
|
||||
this.allClusterNetworks = hash.clusterNetworks || [];
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -108,6 +113,8 @@ export default {
|
||||
hasNode: false,
|
||||
allVMs: [],
|
||||
allVMIs: [],
|
||||
allNodeNetworks: [],
|
||||
allClusterNetworks: [],
|
||||
restartNotificationDisplayed: false,
|
||||
HCI
|
||||
};
|
||||
@@ -156,12 +163,6 @@ export default {
|
||||
*/
|
||||
hasBackUpRestoreInProgress() {
|
||||
return !!this.rows.find((r) => r.restoreResource && !r.restoreResource.fromSnapshot && !r.restoreResource.isComplete);
|
||||
},
|
||||
|
||||
vmRestartRequiredNames() {
|
||||
return this.allVMs
|
||||
.filter((vm) => vm.isRestartRequired)
|
||||
.map((vm) => vm.metadata.name);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -180,35 +181,53 @@ export default {
|
||||
},
|
||||
|
||||
watch: {
|
||||
vmRestartRequiredNames(vmNames) {
|
||||
const count = vmNames.length;
|
||||
allVMs: {
|
||||
handler(neu) {
|
||||
const vmNames = [];
|
||||
|
||||
if (count === 0 && this.restartNotificationDisplayed) {
|
||||
this.restartNotificationDisplayed = false;
|
||||
neu.forEach((vm) => {
|
||||
if (vm.isRestartRequired) {
|
||||
vmNames.push(vm.metadata.name);
|
||||
}
|
||||
});
|
||||
const count = vmNames.length;
|
||||
|
||||
return;
|
||||
}
|
||||
if ( count === 0 && this.restartNotificationDisplayed) {
|
||||
this.restartNotificationDisplayed = false;
|
||||
|
||||
if (count > 0) {
|
||||
// clear old notification before showing new one
|
||||
if (this.restartNotificationDisplayed) {
|
||||
this.$store.dispatch('growl/clear');
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('growl/warning', {
|
||||
title: this.t('harvester.notification.restartRequired.title', { count }),
|
||||
message: this.t('harvester.notification.restartRequired.message', { vmNames: vmNames.join(', ') }),
|
||||
timeout: 10000,
|
||||
}, { root: true });
|
||||
this.restartNotificationDisplayed = true;
|
||||
}
|
||||
if (count > 0) {
|
||||
// clear old notification before showing new one
|
||||
if (this.restartNotificationDisplayed) {
|
||||
this.$store.dispatch('growl/clear');
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0 && vmNames.length > 0) {
|
||||
this.$store.dispatch('growl/warning', {
|
||||
title: this.t('harvester.notification.restartRequired.title', { count }),
|
||||
message: this.t('harvester.notification.restartRequired.message', { vmNames: vmNames.join(', ') }),
|
||||
timeout: 10000,
|
||||
}, { root: true });
|
||||
this.restartNotificationDisplayed = true;
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
lockIconTooltipMessage(row) {
|
||||
const key = ENCRYPTED_VOLUME_TOOLTIP_KEYS[row.encryptedVolumeType];
|
||||
const message = '';
|
||||
|
||||
return key ? this.t(key) : '';
|
||||
if (row.encryptedVolumeType === 'all') {
|
||||
return this.t('harvester.virtualMachine.volume.lockTooltip.all');
|
||||
} else if (row.encryptedVolumeType === 'partial') {
|
||||
return this.t('harvester.virtualMachine.volume.lockTooltip.partial');
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -234,6 +253,8 @@ export default {
|
||||
<HarvesterVmState
|
||||
class="vmstate"
|
||||
:row="scope.row"
|
||||
:all-node-network="allNodeNetworks"
|
||||
:all-cluster-network="allClusterNetworks"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -246,7 +267,7 @@ export default {
|
||||
>
|
||||
{{ scope.row.metadata.name }}
|
||||
<i
|
||||
v-if="scope.row.encryptedVolumeType !== 'none'"
|
||||
v-if="lockIconTooltipMessage(scope.row)"
|
||||
v-tooltip="lockIconTooltipMessage(scope.row)"
|
||||
class="icon icon-lock"
|
||||
:class="{'green-icon': scope.row.encryptedVolumeType === 'all', 'yellow-icon': scope.row.encryptedVolumeType === 'partial'}"
|
||||
|
||||
@@ -9,7 +9,6 @@ import HarvesterResource from './harvester';
|
||||
export default class MIGCONFIGURATION extends HarvesterResource {
|
||||
get _availableActions() {
|
||||
let out = super._availableActions;
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
out = out.map((action) => {
|
||||
if (action.action === 'showConfiguration') {
|
||||
@@ -27,13 +26,13 @@ export default class MIGCONFIGURATION extends HarvesterResource {
|
||||
out.push(
|
||||
{
|
||||
action: 'enableConfig',
|
||||
enabled: !this.isEnabled && canUpdate,
|
||||
enabled: !this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable',
|
||||
},
|
||||
{
|
||||
action: 'disableConfig',
|
||||
enabled: this.isEnabled && canUpdate,
|
||||
enabled: this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable',
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@ export default class PCIDevice extends SteveModel {
|
||||
out.push(
|
||||
{
|
||||
action: 'enablePassthroughBulk',
|
||||
enabled: !this.isEnabling && !this.isvGPUDevice && this.canUpdate,
|
||||
enabled: !this.isEnabling && !this.isvGPUDevice,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -43,7 +43,7 @@ export default class PCIDevice extends SteveModel {
|
||||
},
|
||||
{
|
||||
action: 'disablePassthrough',
|
||||
enabled: this.isEnabling && this.claimedByMe && !this.isvGPUDevice && this.canUpdate,
|
||||
enabled: this.isEnabling && this.claimedByMe && !this.isvGPUDevice,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -54,10 +54,6 @@ export default class PCIDevice extends SteveModel {
|
||||
return out;
|
||||
}
|
||||
|
||||
get canUpdate() {
|
||||
return !!this.linkFor('update');
|
||||
}
|
||||
|
||||
get isvGPUDevice() {
|
||||
if (!this.vGPUAsPCIDeviceFeatureEnabled) {
|
||||
return false;
|
||||
|
||||
@@ -16,13 +16,13 @@ export default class SRIOVDevice extends SteveModel {
|
||||
out.push(
|
||||
{
|
||||
action: 'enableDevice',
|
||||
enabled: !this.isEnabled && this.canUpdate,
|
||||
enabled: !this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable',
|
||||
},
|
||||
{
|
||||
action: 'disableDevice',
|
||||
enabled: this.isEnabled && this.canUpdate,
|
||||
enabled: this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable',
|
||||
},
|
||||
@@ -31,10 +31,6 @@ export default class SRIOVDevice extends SteveModel {
|
||||
return out;
|
||||
}
|
||||
|
||||
get canUpdate() {
|
||||
return !!this.linkFor('update');
|
||||
}
|
||||
|
||||
get canYaml() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export default class USBDevice extends SteveModel {
|
||||
out.push(
|
||||
{
|
||||
action: 'enablePassthroughBulk',
|
||||
enabled: !this.passthroughClaim && !this.status.enabled && this.canUpdate,
|
||||
enabled: !this.passthroughClaim && !this.status.enabled,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -42,7 +42,7 @@ export default class USBDevice extends SteveModel {
|
||||
},
|
||||
{
|
||||
action: 'disablePassthrough',
|
||||
enabled: this.status.enabled && this.canUpdate,
|
||||
enabled: this.status.enabled,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable Passthrough',
|
||||
bulkable: true,
|
||||
@@ -53,10 +53,6 @@ export default class USBDevice extends SteveModel {
|
||||
return out;
|
||||
}
|
||||
|
||||
get canUpdate() {
|
||||
return !!this.linkFor('update');
|
||||
}
|
||||
|
||||
get canYaml() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,18 +27,17 @@ const STATUS_DISPLAY = {
|
||||
export default class VGpuDevice extends SteveModel {
|
||||
get _availableActions() {
|
||||
const out = super._availableActions;
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
out.push(
|
||||
{
|
||||
action: 'enableVGpu',
|
||||
enabled: !this.isEnabled && canUpdate,
|
||||
enabled: !this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot',
|
||||
label: 'Enable',
|
||||
},
|
||||
{
|
||||
action: 'disableVGpu',
|
||||
enabled: this.isEnabled && canUpdate,
|
||||
enabled: this.isEnabled,
|
||||
icon: 'icon icon-fw icon-dot-open',
|
||||
label: 'Disable',
|
||||
bulkable: true,
|
||||
|
||||
@@ -24,7 +24,7 @@ const OBSCURE_NAMESPACE_PREFIX = [
|
||||
|
||||
export default class HciNamespace extends namespace {
|
||||
get _availableActions() {
|
||||
let out = super._availableActions;
|
||||
const out = super._availableActions;
|
||||
const remove = out.findIndex((a) => a.action === 'promptRemove');
|
||||
|
||||
const promptRemove = {
|
||||
@@ -53,16 +53,6 @@ export default class HciNamespace extends namespace {
|
||||
insertAt(out, out.length - 1, promptRemove);
|
||||
insertAt(out, out.length - 5, editQuotaAction);
|
||||
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
out = out.map((action) => {
|
||||
if (['move'].includes(action.action)) {
|
||||
return { ...action, enabled: action.enabled && canUpdate };
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,6 @@ import Secret from '@shell/models/secret';
|
||||
import { NAMESPACE } from '@shell/config/types';
|
||||
|
||||
export default class HciSecret extends Secret {
|
||||
get _availableActions() {
|
||||
let out = super._availableActions;
|
||||
|
||||
out = out.map((action) => {
|
||||
if (['download'].includes(action.action)) {
|
||||
return { ...action, enabled: !!this.linkFor('update') };
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// prevent harvester secret detail page be overridden.
|
||||
// See isFullPageOverride in https://github.com/rancher/dashboard/blob/master/shell/components/ResourceDetail/index.vue
|
||||
get fullDetailPageOverride() {
|
||||
|
||||
@@ -106,15 +106,6 @@ export default class HciStorageClass extends StorageClass {
|
||||
|
||||
get availableActions() {
|
||||
let out = super.availableActions || [];
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
out = out.map((action) => {
|
||||
if (['setDefault', 'setAsDefault', 'resetDefault'].includes(action.action)) {
|
||||
return { ...action, enabled: canUpdate };
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
if (this.isInternalStorageClass()) {
|
||||
out = out.filter((action) => {
|
||||
|
||||
@@ -4,8 +4,6 @@ import { HCI as HCI_ANNOTATIONS } from '../config/labels-annotations';
|
||||
import HarvesterResource from './harvester';
|
||||
import { HCI } from '../types';
|
||||
|
||||
const HARVESTER_NVIDIA_DRIVER_TOOLKIT = 'harvester-system/nvidia-driver-toolkit';
|
||||
|
||||
export default class HciAddonConfig extends HarvesterResource {
|
||||
get availableActions() {
|
||||
const out = super._availableActions;
|
||||
@@ -21,10 +19,9 @@ export default class HciAddonConfig extends HarvesterResource {
|
||||
out.push(rancherDashboard);
|
||||
}
|
||||
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
const toggleAddon = {
|
||||
action: 'toggleAddon',
|
||||
enabled: canUpdate,
|
||||
enabled: true,
|
||||
icon: this.spec.enabled ? 'icon icon-pause' : 'icon icon-play',
|
||||
label: this.spec.enabled ? this.t('generic.disable') : this.t('generic.enable'),
|
||||
};
|
||||
@@ -48,15 +45,6 @@ export default class HciAddonConfig extends HarvesterResource {
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.spec.enabled && this.id === HARVESTER_NVIDIA_DRIVER_TOOLKIT) {
|
||||
this.$dispatch('promptModal', {
|
||||
resources: [this],
|
||||
component: 'HarvesterEnableNvidiaDriverToolkit',
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.spec.enabled = !this.spec.enabled;
|
||||
await this.save();
|
||||
} catch (err) {
|
||||
|
||||
@@ -3,20 +3,6 @@ import { findBy } from '@shell/utils/array';
|
||||
import HarvesterResource from './harvester';
|
||||
|
||||
export default class HciKeypair extends HarvesterResource {
|
||||
get _availableActions() {
|
||||
let out = super._availableActions;
|
||||
|
||||
out = out.map((action) => {
|
||||
if (['download'].includes(action.action)) {
|
||||
return { ...action, enabled: !!this.linkFor('update') };
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
get stateDisplay() {
|
||||
const conditions = get(this, 'status.conditions');
|
||||
const status = (findBy(conditions, 'type', 'validated') || {}).status ;
|
||||
|
||||
@@ -19,18 +19,16 @@ export default class ScheduleVmBackup extends HarvesterResource {
|
||||
}
|
||||
});
|
||||
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
return [
|
||||
{
|
||||
action: 'resumeSchedule',
|
||||
enabled: canUpdate && ucFirst(this.state) === STATES.suspended.label,
|
||||
enabled: ucFirst(this.state) === STATES.suspended.label,
|
||||
icon: 'icons icon-play',
|
||||
label: this.t('harvester.action.resumeSchedule'),
|
||||
},
|
||||
{
|
||||
action: 'suspendSchedule',
|
||||
enabled: canUpdate && ucFirst(this.state) === STATES.active.label,
|
||||
enabled: ucFirst(this.state) === STATES.active.label,
|
||||
icon: 'icons icon-pause',
|
||||
label: this.t('harvester.action.suspendSchedule'),
|
||||
},
|
||||
|
||||
@@ -39,6 +39,9 @@ function isReady() {
|
||||
export default class HciVmImage extends HarvesterResource {
|
||||
get availableActions() {
|
||||
let out = super._availableActions;
|
||||
const toFilter = ['goToEditYaml'];
|
||||
|
||||
out = out.filter( (A) => !toFilter.includes(A.action));
|
||||
|
||||
// show `Clone` only when imageSource is `download`
|
||||
if (this.imageSource !== 'download') {
|
||||
@@ -52,7 +55,6 @@ export default class HciVmImage extends HarvesterResource {
|
||||
canCreateVM = false;
|
||||
}
|
||||
|
||||
const canCreateImage = !!this.$getters?.['schemaFor']?.(HCI.IMAGE)?.collectionMethods?.some((method) => method.toLowerCase() === 'post');
|
||||
const customActions = this.isReady ? [
|
||||
{
|
||||
action: 'createFromImage',
|
||||
@@ -62,13 +64,13 @@ export default class HciVmImage extends HarvesterResource {
|
||||
},
|
||||
{
|
||||
action: 'encryptImage',
|
||||
enabled: this.volumeEncryptionFeatureEnabled && !this.isEncrypted && canCreateImage,
|
||||
enabled: this.volumeEncryptionFeatureEnabled && !this.isEncrypted,
|
||||
icon: 'icon icon-lock',
|
||||
label: this.t('harvester.action.encryptImage'),
|
||||
},
|
||||
{
|
||||
action: 'decryptImage',
|
||||
enabled: this.volumeEncryptionFeatureEnabled && this.isEncrypted && canCreateImage,
|
||||
enabled: this.volumeEncryptionFeatureEnabled && this.isEncrypted,
|
||||
icon: 'icon icon-unlock',
|
||||
label: this.t('harvester.action.decryptImage'),
|
||||
},
|
||||
|
||||
@@ -23,17 +23,17 @@ export default class HciVmTemplateVersion extends HarvesterResource {
|
||||
});
|
||||
|
||||
const schema = this.$getters['schemaFor'](HCI.VM);
|
||||
let canCreateVM = false;
|
||||
let canCreateVM = true;
|
||||
|
||||
if (schema?.collectionMethods.find((x) => ['post'].includes(x.toLowerCase())) ) {
|
||||
canCreateVM = true;
|
||||
if ( schema && !schema?.collectionMethods.find((x) => ['post'].includes(x.toLowerCase())) ) {
|
||||
canCreateVM = false;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
action: 'launchFromTemplate',
|
||||
icon: 'icon icon-spinner',
|
||||
enabled: canCreateVM && this.isReady,
|
||||
disabled: !canCreateVM || !this.isReady,
|
||||
label: this.t('harvester.action.launchFormTemplate'),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -83,42 +83,6 @@ const VMIPhase = {
|
||||
|
||||
let productInStore;
|
||||
|
||||
let _podOwnerMap = null;
|
||||
let _podOwnerMapSource = null;
|
||||
|
||||
function getPodByOwnerName(rootGetters, inStore, ownerName) {
|
||||
const podList = rootGetters[`${ inStore }/all`](POD);
|
||||
|
||||
if (!Array.isArray(podList)) {
|
||||
return undefined;
|
||||
}
|
||||
// if not equals (usually means the pod list has been updated), we need to rebuild the map, otherwise we can reuse the map for better performance
|
||||
if (_podOwnerMapSource !== podList) {
|
||||
_podOwnerMap = new Map(); // use Map to store ownerReference name and pod mapping
|
||||
for (const pod of podList) {
|
||||
const refName = pod.metadata?.ownerReferences?.[0]?.name;
|
||||
|
||||
if (refName) {
|
||||
_podOwnerMap.set(refName, pod);
|
||||
}
|
||||
}
|
||||
_podOwnerMapSource = podList;
|
||||
}
|
||||
|
||||
return _podOwnerMap.get(ownerName);
|
||||
}
|
||||
|
||||
function getPvcsByNames(rootGetters, inStore, names) {
|
||||
const pvcList = rootGetters[`${ inStore }/all`](PVC);
|
||||
|
||||
if (!Array.isArray(pvcList)) {
|
||||
return [];
|
||||
}
|
||||
const uniqueNames = new Set(names);
|
||||
|
||||
return pvcList.filter((pvc) => uniqueNames.has(pvc.metadata?.name));
|
||||
}
|
||||
|
||||
const IgnoreMessages = ['pod has unbound immediate PersistentVolumeClaims'];
|
||||
|
||||
export default class VirtVm extends HarvesterResource {
|
||||
@@ -130,8 +94,6 @@ export default class VirtVm extends HarvesterResource {
|
||||
clone.action = 'goToCloneVM';
|
||||
}
|
||||
|
||||
const canCreateVMSSchedule = !!this.$getters?.['schemaFor']?.(HCI.SCHEDULE_VM_BACKUP)?.collectionMethods?.find((x) => ['post'].includes(x.toLowerCase()));
|
||||
|
||||
return [
|
||||
{
|
||||
action: 'stopVM',
|
||||
@@ -164,7 +126,6 @@ export default class VirtVm extends HarvesterResource {
|
||||
},
|
||||
{
|
||||
action: 'restartVM',
|
||||
altAction: 'altRestartVM',
|
||||
enabled: !!this.actions?.restart,
|
||||
icon: 'icon icon-refresh',
|
||||
label: this.t('harvester.action.restart'),
|
||||
@@ -172,11 +133,10 @@ export default class VirtVm extends HarvesterResource {
|
||||
bulkAction: 'restartVM'
|
||||
},
|
||||
{
|
||||
action: 'softrebootVM',
|
||||
altAction: 'doSoftReboot',
|
||||
enabled: !!this.actions?.softreboot,
|
||||
icon: 'icon icon-pipeline',
|
||||
label: this.t('harvester.action.softreboot')
|
||||
action: 'softrebootVM',
|
||||
enabled: !!this.actions?.softreboot,
|
||||
icon: 'icon icon-pipeline',
|
||||
label: this.t('harvester.action.softreboot')
|
||||
},
|
||||
{
|
||||
action: 'startVM',
|
||||
@@ -211,7 +171,7 @@ export default class VirtVm extends HarvesterResource {
|
||||
},
|
||||
{
|
||||
action: 'createSchedule',
|
||||
enabled: canCreateVMSSchedule && this.schedulingVMBackupFeatureEnabled,
|
||||
enabled: this.schedulingVMBackupFeatureEnabled,
|
||||
icon: 'icon icon-history',
|
||||
label: this.t('harvester.action.createSchedule')
|
||||
},
|
||||
@@ -228,12 +188,10 @@ export default class VirtVm extends HarvesterResource {
|
||||
label: this.t('harvester.action.ejectCDROM')
|
||||
},
|
||||
{
|
||||
action: 'migrateVM',
|
||||
enabled: !!this.actions?.migrate,
|
||||
icon: 'icon icon-copy',
|
||||
label: this.t('harvester.action.vmMigrate'),
|
||||
bulkable: true,
|
||||
bulkAction: 'migrateVM'
|
||||
action: 'migrateVM',
|
||||
enabled: !!this.actions?.migrate,
|
||||
icon: 'icon icon-copy',
|
||||
label: this.t('harvester.action.migrate')
|
||||
},
|
||||
{
|
||||
action: 'abortMigrationVM',
|
||||
@@ -373,10 +331,6 @@ export default class VirtVm extends HarvesterResource {
|
||||
this.metadata.annotations[HCI_ANNOTATIONS.VOLUME_CLAIM_TEMPLATE] = JSON.stringify(deleteDataSource);
|
||||
}
|
||||
|
||||
altRestartVM() {
|
||||
this.doActionGrowl('restart', {});
|
||||
}
|
||||
|
||||
restartVM(resources = this) {
|
||||
this.$dispatch('promptModal', {
|
||||
resources,
|
||||
@@ -706,13 +660,16 @@ export default class VirtVm extends HarvesterResource {
|
||||
|
||||
get podResource() {
|
||||
const inStore = this.productInStore;
|
||||
|
||||
const vmiResource = this.$rootGetters[`${ inStore }/byId`](HCI.VMI, this.id);
|
||||
const podList = this.$rootGetters[`${ inStore }/all`](POD);
|
||||
|
||||
if (!vmiResource?.metadata?.name) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getPodByOwnerName(this.$rootGetters, inStore, vmiResource.metadata.name);
|
||||
return podList.find((P) => {
|
||||
return (
|
||||
vmiResource?.metadata?.name &&
|
||||
vmiResource?.metadata?.name === P.metadata?.ownerReferences?.[0].name
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
get isPaused() {
|
||||
@@ -753,13 +710,17 @@ export default class VirtVm extends HarvesterResource {
|
||||
get vmi() {
|
||||
const inStore = this.productInStore;
|
||||
|
||||
return this.$rootGetters[`${ inStore }/byId`](HCI.VMI, this.id);
|
||||
const vmis = this.$rootGetters[`${ inStore }/all`](HCI.VMI);
|
||||
|
||||
return vmis.find((VMI) => VMI.id === this.id);
|
||||
}
|
||||
|
||||
get volumes() {
|
||||
const pvcs = this.$rootGetters[`${ this.productInStore }/all`](PVC);
|
||||
|
||||
const volumeClaimNames = this.spec.template.spec.volumes?.map((v) => v.persistentVolumeClaim?.claimName).filter((v) => !!v) || [];
|
||||
|
||||
return getPvcsByNames(this.$rootGetters, this.productInStore, volumeClaimNames);
|
||||
return pvcs.filter((pvc) => volumeClaimNames.includes(pvc.metadata.name));
|
||||
}
|
||||
|
||||
get lvmVolumes() {
|
||||
@@ -792,6 +753,17 @@ export default class VirtVm extends HarvesterResource {
|
||||
return { status: 'VMI error', detailedMessage: vmiFailureCond.message };
|
||||
}
|
||||
|
||||
if ((this.vmi || this.isVMCreated) && this.podResource) {
|
||||
// const podStatus = this.podResource.getPodStatus;
|
||||
// if (POD_STATUS_ALL_ERROR.includes(podStatus?.status)) {
|
||||
// return {
|
||||
// ...podStatus,
|
||||
// status: 'LAUNCHER_POD_ERROR',
|
||||
// pod: this.podResource,
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
||||
return this?.vmi?.status?.phase;
|
||||
}
|
||||
|
||||
@@ -929,7 +901,9 @@ export default class VirtVm extends HarvesterResource {
|
||||
|
||||
const inStore = this.productInStore;
|
||||
|
||||
const res = this.$rootGetters[`${ inStore }/byId`](HCI.RESTORE, id);
|
||||
const allRestore = this.$rootGetters[`${ inStore }/all`](HCI.RESTORE);
|
||||
|
||||
const res = allRestore.find((O) => O.id === id);
|
||||
|
||||
if (res) {
|
||||
const allBackups = this.$rootGetters[`${ inStore }/all`](HCI.BACKUP);
|
||||
@@ -1099,6 +1073,42 @@ export default class VirtVm extends HarvesterResource {
|
||||
return out;
|
||||
}
|
||||
|
||||
get warningCount() {
|
||||
return this.resourcesStatus.warningCount;
|
||||
}
|
||||
|
||||
get errorCount() {
|
||||
return this.resourcesStatus.errorCount;
|
||||
}
|
||||
|
||||
get resourcesStatus() {
|
||||
const inStore = this.productInStore;
|
||||
const vmList = this.$rootGetters[`${ inStore }/all`](HCI.VM);
|
||||
let warningCount = 0;
|
||||
let errorCount = 0;
|
||||
|
||||
vmList.forEach((vm) => {
|
||||
const status = vm.actualState;
|
||||
|
||||
if (status === VM_ERROR) {
|
||||
errorCount += 1;
|
||||
} else if (
|
||||
status === 'Stopping' ||
|
||||
status === 'Waiting' ||
|
||||
status === 'Pending' ||
|
||||
status === 'Starting' ||
|
||||
status === 'Terminating'
|
||||
) {
|
||||
warningCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
warningCount,
|
||||
errorCount
|
||||
};
|
||||
}
|
||||
|
||||
get volumeClaimTemplates() {
|
||||
return parseVolumeClaimTemplates(this);
|
||||
}
|
||||
@@ -1116,6 +1126,7 @@ export default class VirtVm extends HarvesterResource {
|
||||
get rootImageId() {
|
||||
let imageId = '';
|
||||
const inStore = this.productInStore;
|
||||
const pvcs = this.$rootGetters[`${ inStore }/all`](PVC) || [];
|
||||
|
||||
const volumes = this.spec.template.spec.volumes || [];
|
||||
|
||||
@@ -1125,7 +1136,9 @@ export default class VirtVm extends HarvesterResource {
|
||||
});
|
||||
|
||||
if (!isNoExistingVolume) {
|
||||
const existingVolume = this.$rootGetters[`${ inStore }/byId`](PVC, `${ this.metadata.namespace }/${ firstVolumeName }`);
|
||||
const existingVolume = pvcs.find(
|
||||
(P) => P.id === `${ this.metadata.namespace }/${ firstVolumeName }`
|
||||
);
|
||||
|
||||
if (existingVolume) {
|
||||
return existingVolume?.metadata?.annotations?.[
|
||||
@@ -1270,6 +1283,18 @@ export default class VirtVm extends HarvesterResource {
|
||||
}
|
||||
}
|
||||
|
||||
get provisionedHostDevices() {
|
||||
// Rancher-provisioned VMs store hostDevices.name as a placeholder ('provisioned'); the
|
||||
// real allocated PCI device names live in this annotation, keyed by resourceName.
|
||||
try {
|
||||
const deviceAllocationDetails = JSON.parse(this.metadata?.annotations[HCI_ANNOTATIONS.VM_DEVICE_ALLOCATION_DETAILS] || '{}');
|
||||
|
||||
return deviceAllocationDetails?.hostdevices || {};
|
||||
} catch (error) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
get schedulingVMBackupFeatureEnabled() {
|
||||
return this.$rootGetters['harvester-common/getFeatureEnabled']('schedulingVMBackup');
|
||||
}
|
||||
@@ -1303,7 +1328,8 @@ export default class VirtVm extends HarvesterResource {
|
||||
}
|
||||
|
||||
get isBackupTargetUnavailable() {
|
||||
const backupTargetSetting = this.$rootGetters['harvester/byId'](HCI.SETTING, 'backup-target');
|
||||
const allSettings = this.$rootGetters['harvester/all'](HCI.SETTING) || [];
|
||||
const backupTargetSetting = allSettings.find( (O) => O.id === 'backup-target');
|
||||
|
||||
return isBackupTargetSettingUnavailable(backupTargetSetting);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
import shellProject from '@shell/models/management.cattle.io.project';
|
||||
|
||||
// This model controls `Project / Namespace` page in rancher integration mode
|
||||
// Extend management.cattle.io.project model from shell
|
||||
export default class Project extends shellProject {
|
||||
get _availableActions() {
|
||||
const canUpdate = !!this.linkFor('update');
|
||||
|
||||
// disable `Edit Config` action if user does not have update permission.
|
||||
return super._availableActions.map((action) => {
|
||||
if (action.action === 'goToEdit') {
|
||||
return { ...action, enabled: canUpdate };
|
||||
}
|
||||
|
||||
return action;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -57,11 +57,7 @@ export default class HciVlanConfig extends HarvesterResource {
|
||||
get _availableActions() {
|
||||
const out = super._availableActions;
|
||||
|
||||
const canMigrate = !!this.$getters?.['schemaFor']?.(HCI.VLAN_CONFIG)?.collectionMethods?.find((x) => ['post'].includes(x.toLowerCase()));
|
||||
|
||||
if (canMigrate) {
|
||||
insertAt(out, 0, this.migrateAction);
|
||||
}
|
||||
insertAt(out, 0, this.migrateAction);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "harvester",
|
||||
"description": "Rancher UI Extension for Harvester",
|
||||
"version": "1.9.0-dev",
|
||||
"version": "1.8.2",
|
||||
"private": false,
|
||||
"rancher": {
|
||||
"annotations": {
|
||||
|
||||
@@ -123,26 +123,5 @@ export default {
|
||||
const clusterId = currentCluster.id;
|
||||
|
||||
return projectsInAllClusters.filter((project: any) => project.spec.clusterName === clusterId && project.nameDisplay !== 'System');
|
||||
},
|
||||
|
||||
// Few harvester resources name and REAL resource are different. E.g. HCI.NETWORK_ATTACHMENT page resource is NETWORK_ATTACHMENT.
|
||||
// Check in config/harvester-cluster.js for more details.
|
||||
// We need to look up the schema by resource name, and fallback to find using real resource name
|
||||
schemaFor: (state, getters, rootState, rootGetters) => (type, _fuzzy = false, _allowThrow = true) => {
|
||||
// follow the same logic as type-map/schemaFor in /dashboard/shell/plugins/dashboard-store/getters.js
|
||||
const normalizedType = getters.normalizeType(type);
|
||||
const schemas = state.types['schema'];
|
||||
const out = schemas?.map?.get(normalizedType);
|
||||
|
||||
if (out) return out;
|
||||
|
||||
// if not found, use the resource mapping in configureType for a second try
|
||||
const resourceType = rootGetters['type-map/optionsFor'](type)?.resource;
|
||||
if (resourceType && resourceType !== type) {
|
||||
const normalizedResource = getters.normalizeType(resourceType);
|
||||
return schemas?.map?.get(normalizedResource) || null;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,42 +31,22 @@ export function registerAddonSideNav(store, productName, {
|
||||
}, 600);
|
||||
};
|
||||
|
||||
const hasAccessibleSchema = (t) => {
|
||||
try {
|
||||
return !!store.getters[`${ productName }/schemaFor`]?.(t);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const showTypes = (visibleTypes) => {
|
||||
store.commit('type-map/basicType', {
|
||||
product: productName,
|
||||
group: navGroup,
|
||||
types: visibleTypes
|
||||
});
|
||||
};
|
||||
|
||||
const hideTypes = () => {
|
||||
const basicTypes = store.state['type-map'].basicTypes[productName];
|
||||
|
||||
if (basicTypes) {
|
||||
types.forEach((t) => delete basicTypes[t]);
|
||||
}
|
||||
};
|
||||
|
||||
// Adds or removes the resource IDs from the product visibility whitelist.
|
||||
const setMenuVisibility = (visible) => {
|
||||
const accessibleTypes = visible ? types.filter(hasAccessibleSchema) : [];
|
||||
if (visible) {
|
||||
store.commit('type-map/basicType', {
|
||||
product: productName,
|
||||
group: navGroup,
|
||||
types
|
||||
});
|
||||
} else {
|
||||
// Manually delete the keys from the state object to hide them.
|
||||
const basicTypes = store.state['type-map'].basicTypes[productName];
|
||||
|
||||
// Always clear first to remove any previously-registered types that are
|
||||
// no longer accessible (e.g. partial permission changes like types=[A,B] where B is dropped).
|
||||
hideTypes();
|
||||
|
||||
if (accessibleTypes.length > 0) {
|
||||
showTypes(accessibleTypes);
|
||||
if (basicTypes) {
|
||||
types.forEach((t) => delete basicTypes[t]);
|
||||
}
|
||||
}
|
||||
|
||||
kickSideNav();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
const AUTH_ERROR_CODES = [401, 403, 404];
|
||||
|
||||
export function getLoginAwareErrors(err, message = '') {
|
||||
const errors = Array.isArray(err) ? err : (err ? [err] : []);
|
||||
|
||||
if (!errors.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const generic = message;
|
||||
|
||||
if (errors.some((e) => AUTH_ERROR_CODES.includes(e?._status || e?.response?.status))) {
|
||||
return [generic];
|
||||
}
|
||||
|
||||
const msgs = errors
|
||||
.map((e) => (typeof e === 'string' ? e : (e?.message || e?._statusText || '')))
|
||||
.filter(Boolean);
|
||||
|
||||
return msgs.length ? msgs : [generic];
|
||||
}
|
||||
@@ -27,6 +27,23 @@ OUTPUT_DIR=dist/${DIR}-embedded
|
||||
echo "Building..."
|
||||
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=$OUTPUT_DIR ROUTER_BASE='/dashboard/' RESOURCE_BASE='/dashboard/' RANCHER_ENV=harvester yarn run build
|
||||
|
||||
if [ -v EMBED_PKG ]; then
|
||||
echo "Build and embed plugin from: $EMBED_PKG"
|
||||
PKG_FILE_NAME=${EMBED_PKG##*/}
|
||||
echo PKG_FILE_NAME: $PKG_FILE_NAME
|
||||
|
||||
PKG_NAME="${PKG_FILE_NAME/.tar.gz/""}"
|
||||
echo "Plugin name: '$PKG_NAME'"
|
||||
|
||||
# Fetch file, unpack and move to dist
|
||||
curl $EMBED_PKG --output $PKG_FILE_NAME
|
||||
OUTPUT_DIR_PKG=$OUTPUT_DIR/$PKG_NAME
|
||||
mkdir -p $OUTPUT_DIR_PKG
|
||||
tar xvfz $PKG_FILE_NAME -C $OUTPUT_DIR/$PKG_NAME
|
||||
echo "Plugin contents that will be served from $PKG_NAME"
|
||||
ls -alR $OUTPUT_DIR/$PKG_NAME
|
||||
fi
|
||||
|
||||
echo "Destroying..."
|
||||
find $OUTPUT_DIR -name "index.html" -mindepth 2 -exec rm {} \;
|
||||
find $OUTPUT_DIR -type d -empty -depth -exec rmdir {} \;
|
||||
|
||||
@@ -919,12 +919,12 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.10.4"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0", "@babel/code-frame@^7.8.3":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c"
|
||||
integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.29.0", "@babel/code-frame@^7.29.7", "@babel/code-frame@^7.8.3":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.7.tgz#f2fbbfea87c44a21590ec515b778b2c26d8866e7"
|
||||
integrity sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
"@babel/helper-validator-identifier" "^7.29.7"
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
@@ -954,23 +954,23 @@
|
||||
json5 "^2.2.3"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/generator@^7.29.0", "@babel/generator@^7.7.2":
|
||||
version "7.29.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.1.tgz#d09876290111abbb00ef962a7b83a5307fba0d50"
|
||||
integrity sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==
|
||||
"@babel/generator@^7.29.0", "@babel/generator@^7.29.7", "@babel/generator@^7.7.2":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.7.tgz#cca0b8827e6bcf3ba176788e7f3b180ad6db2fa3"
|
||||
integrity sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.29.0"
|
||||
"@babel/types" "^7.29.0"
|
||||
"@babel/parser" "^7.29.7"
|
||||
"@babel/types" "^7.29.7"
|
||||
"@jridgewell/gen-mapping" "^0.3.12"
|
||||
"@jridgewell/trace-mapping" "^0.3.28"
|
||||
jsesc "^3.0.2"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3":
|
||||
version "7.27.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5"
|
||||
integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==
|
||||
"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3", "@babel/helper-annotate-as-pure@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz#c70fe3c6ecbdc3fd2dd1b0f498428b88b82ce47f"
|
||||
integrity sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==
|
||||
dependencies:
|
||||
"@babel/types" "^7.27.3"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.12.16", "@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.28.6":
|
||||
version "7.28.6"
|
||||
@@ -983,17 +983,17 @@
|
||||
lru-cache "^5.1.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz#611ff5482da9ef0db6291bcd24303400bca170fb"
|
||||
integrity sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==
|
||||
"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.28.6", "@babel/helper-create-class-features-plugin@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz#6eddf286f2ec418f740c91d60a83347c55838ddd"
|
||||
integrity sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.27.3"
|
||||
"@babel/helper-member-expression-to-functions" "^7.28.5"
|
||||
"@babel/helper-optimise-call-expression" "^7.27.1"
|
||||
"@babel/helper-replace-supers" "^7.28.6"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.27.1"
|
||||
"@babel/traverse" "^7.28.6"
|
||||
"@babel/helper-annotate-as-pure" "^7.29.7"
|
||||
"@babel/helper-member-expression-to-functions" "^7.29.7"
|
||||
"@babel/helper-optimise-call-expression" "^7.29.7"
|
||||
"@babel/helper-replace-supers" "^7.29.7"
|
||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.29.7"
|
||||
"@babel/traverse" "^7.29.7"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1", "@babel/helper-create-regexp-features-plugin@^7.28.5":
|
||||
@@ -1016,18 +1016,18 @@
|
||||
lodash.debounce "^4.0.8"
|
||||
resolve "^1.22.11"
|
||||
|
||||
"@babel/helper-globals@^7.28.0":
|
||||
version "7.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674"
|
||||
integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==
|
||||
"@babel/helper-globals@^7.28.0", "@babel/helper-globals@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz#f04a96fbd8473241b1079243f5b3f03a3010ab7b"
|
||||
integrity sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==
|
||||
|
||||
"@babel/helper-member-expression-to-functions@^7.28.5":
|
||||
version "7.28.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz#f3e07a10be37ed7a63461c63e6929575945a6150"
|
||||
integrity sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==
|
||||
"@babel/helper-member-expression-to-functions@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz#8dbdb3ce0b5c487e1aec10e13c9a43a500814df8"
|
||||
integrity sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.28.5"
|
||||
"@babel/types" "^7.28.5"
|
||||
"@babel/traverse" "^7.29.7"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.27.1", "@babel/helper-module-imports@^7.28.6":
|
||||
version "7.28.6"
|
||||
@@ -1046,17 +1046,17 @@
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
"@babel/traverse" "^7.28.6"
|
||||
|
||||
"@babel/helper-optimise-call-expression@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200"
|
||||
integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==
|
||||
"@babel/helper-optimise-call-expression@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz#77b0b5b94f1997fa9d6e3125f445227b1faf9d85"
|
||||
integrity sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==
|
||||
dependencies:
|
||||
"@babel/types" "^7.27.1"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.8.0":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz#6f13ea251b68c8532e985fd532f28741a8af9ac8"
|
||||
integrity sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==
|
||||
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.28.6", "@babel/helper-plugin-utils@^7.29.7", "@babel/helper-plugin-utils@^7.8.0":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz#c0a0766f1a13617d8a17407d7ab8f9d486225ea4"
|
||||
integrity sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==
|
||||
|
||||
"@babel/helper-remap-async-to-generator@^7.27.1":
|
||||
version "7.27.1"
|
||||
@@ -1067,32 +1067,32 @@
|
||||
"@babel/helper-wrap-function" "^7.27.1"
|
||||
"@babel/traverse" "^7.27.1"
|
||||
|
||||
"@babel/helper-replace-supers@^7.27.1", "@babel/helper-replace-supers@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz#94aa9a1d7423a00aead3f204f78834ce7d53fe44"
|
||||
integrity sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==
|
||||
"@babel/helper-replace-supers@^7.27.1", "@babel/helper-replace-supers@^7.28.6", "@babel/helper-replace-supers@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz#bc3c3964329043c79112e513c1b198f16589ac21"
|
||||
integrity sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==
|
||||
dependencies:
|
||||
"@babel/helper-member-expression-to-functions" "^7.28.5"
|
||||
"@babel/helper-optimise-call-expression" "^7.27.1"
|
||||
"@babel/traverse" "^7.28.6"
|
||||
"@babel/helper-member-expression-to-functions" "^7.29.7"
|
||||
"@babel/helper-optimise-call-expression" "^7.29.7"
|
||||
"@babel/traverse" "^7.29.7"
|
||||
|
||||
"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56"
|
||||
integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==
|
||||
"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.27.1", "@babel/helper-skip-transparent-expression-wrappers@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz#50c95c7e4c4f54936cfa0116428edc559862d551"
|
||||
integrity sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.27.1"
|
||||
"@babel/types" "^7.27.1"
|
||||
"@babel/traverse" "^7.29.7"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/helper-string-parser@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
|
||||
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
|
||||
"@babel/helper-string-parser@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f"
|
||||
integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.25.9", "@babel/helper-validator-identifier@^7.28.5":
|
||||
version "7.28.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4"
|
||||
integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==
|
||||
"@babel/helper-validator-identifier@^7.25.9", "@babel/helper-validator-identifier@^7.28.5", "@babel/helper-validator-identifier@^7.29.7":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2"
|
||||
integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==
|
||||
|
||||
"@babel/helper-validator-option@^7.16.7", "@babel/helper-validator-option@^7.27.1":
|
||||
version "7.27.1"
|
||||
@@ -1126,12 +1126,12 @@
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.0", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0", "@babel/parser@^7.7.0":
|
||||
version "7.29.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.2.tgz#58bd50b9a7951d134988a1ae177a35ef9a703ba1"
|
||||
integrity sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==
|
||||
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.28.0", "@babel/parser@^7.29.0", "@babel/parser@^7.29.7", "@babel/parser@^7.7.0":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.7.tgz#837b87387cbf5ec5530cb634b3c622f68edb9334"
|
||||
integrity sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.29.0"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.28.5":
|
||||
version "7.28.5"
|
||||
@@ -1416,13 +1416,13 @@
|
||||
"@babel/helper-create-class-features-plugin" "^7.28.6"
|
||||
"@babel/helper-plugin-utils" "^7.28.6"
|
||||
|
||||
"@babel/plugin-transform-class-static-block@7.28.6", "@babel/plugin-transform-class-static-block@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz#1257491e8259c6d125ac4d9a6f39f9d2bf3dba70"
|
||||
integrity sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==
|
||||
"@babel/plugin-transform-class-static-block@7.29.7", "@babel/plugin-transform-class-static-block@^7.28.6":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz#fed8efd19f3dd3e1114ee390707c70912778fd7c"
|
||||
integrity sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==
|
||||
dependencies:
|
||||
"@babel/helper-create-class-features-plugin" "^7.28.6"
|
||||
"@babel/helper-plugin-utils" "^7.28.6"
|
||||
"@babel/helper-create-class-features-plugin" "^7.29.7"
|
||||
"@babel/helper-plugin-utils" "^7.29.7"
|
||||
|
||||
"@babel/plugin-transform-classes@^7.28.6":
|
||||
version "7.28.6"
|
||||
@@ -1888,35 +1888,35 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.2.tgz#9a6e2d05f4b6692e1801cd4fb176ad823930ed5e"
|
||||
integrity sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==
|
||||
|
||||
"@babel/template@^7.27.2", "@babel/template@^7.28.6", "@babel/template@^7.3.3":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57"
|
||||
integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==
|
||||
"@babel/template@^7.27.2", "@babel/template@^7.28.6", "@babel/template@^7.29.7", "@babel/template@^7.3.3":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.29.7.tgz#4d9d4004f645cdd304de958c725162784ecac700"
|
||||
integrity sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.28.6"
|
||||
"@babel/parser" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
"@babel/code-frame" "^7.29.7"
|
||||
"@babel/parser" "^7.29.7"
|
||||
"@babel/types" "^7.29.7"
|
||||
|
||||
"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6", "@babel/traverse@^7.29.0", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.0.tgz#f323d05001440253eead3c9c858adbe00b90310a"
|
||||
integrity sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==
|
||||
"@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6", "@babel/traverse@^7.29.0", "@babel/traverse@^7.29.7", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.29.7.tgz#c47b07a41b95da0907d026b5dd894d98de7d2f2d"
|
||||
integrity sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.29.0"
|
||||
"@babel/generator" "^7.29.0"
|
||||
"@babel/helper-globals" "^7.28.0"
|
||||
"@babel/parser" "^7.29.0"
|
||||
"@babel/template" "^7.28.6"
|
||||
"@babel/types" "^7.29.0"
|
||||
"@babel/code-frame" "^7.29.7"
|
||||
"@babel/generator" "^7.29.7"
|
||||
"@babel/helper-globals" "^7.29.7"
|
||||
"@babel/parser" "^7.29.7"
|
||||
"@babel/template" "^7.29.7"
|
||||
"@babel/types" "^7.29.7"
|
||||
debug "^4.3.1"
|
||||
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.5", "@babel/types@^7.28.6", "@babel/types@^7.29.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7"
|
||||
integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==
|
||||
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.28.6", "@babel/types@^7.29.0", "@babel/types@^7.29.7", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
|
||||
version "7.29.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.7.tgz#8005e31d82712ee7adaef6e23c63b71a62770a92"
|
||||
integrity sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.27.1"
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
"@babel/helper-string-parser" "^7.29.7"
|
||||
"@babel/helper-validator-identifier" "^7.29.7"
|
||||
|
||||
"@bcoe/v8-coverage@^0.2.3":
|
||||
version "0.2.3"
|
||||
@@ -3386,10 +3386,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/lodash@4.17.24":
|
||||
version "4.17.24"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.24.tgz#4ae334fc62c0e915ca8ed8e35dcc6d4eeb29215f"
|
||||
integrity sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==
|
||||
"@types/lodash@4.17.25":
|
||||
version "4.17.25"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.25.tgz#69765ac7bcddb0eb072961cf292524a8f5b3c2c0"
|
||||
integrity sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==
|
||||
|
||||
"@types/mime@^1":
|
||||
version "1.3.5"
|
||||
@@ -3408,12 +3408,12 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@25.3.3", "@types/node@25.6.2", "@types/node@^14.14.31":
|
||||
version "25.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.6.2.tgz#8c491201373690e4ef2a2ffed0dfb510a5830b92"
|
||||
integrity sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==
|
||||
"@types/node@*", "@types/node@25.3.3", "@types/node@25.9.5", "@types/node@^14.14.31":
|
||||
version "25.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.9.5.tgz#0fefc09e6e82e94cde291bacf43522e989eb01a4"
|
||||
integrity sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==
|
||||
dependencies:
|
||||
undici-types "~7.19.0"
|
||||
undici-types ">=7.24.0 <7.24.7"
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.4"
|
||||
@@ -8294,9 +8294,9 @@ html-tags@^2.0.0:
|
||||
integrity sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==
|
||||
|
||||
html-webpack-plugin@^5.0.0, html-webpack-plugin@^5.1.0:
|
||||
version "5.6.7"
|
||||
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz#429bab4e12abf3c07e1c608886608e2df2c06b11"
|
||||
integrity sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==
|
||||
version "5.6.8"
|
||||
resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.8.tgz#5425dbc63eb533ffa59e92342be94894a125fc23"
|
||||
integrity sha512-MZmKQcTnhEh1SPSyMiEytIeDZDUoBZVorNHivQGXMASHf/BSGGOrKa2xQ5bGx3TCe1n109ecCt+cpww7wwWhKA==
|
||||
dependencies:
|
||||
"@types/html-minifier-terser" "^6.0.0"
|
||||
html-minifier-terser "^6.0.2"
|
||||
@@ -11477,12 +11477,13 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0, punycode@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
qs@6.15.1, qs@6.7.0, qs@^6.12.3, qs@~6.10.3, qs@~6.14.0:
|
||||
version "6.15.1"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.1.tgz#bdb55aed06bfac257a90c44a446a73fba5575c8f"
|
||||
integrity sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==
|
||||
qs@6.15.3, qs@6.7.0, qs@^6.12.3, qs@~6.10.3, qs@~6.14.0:
|
||||
version "6.15.3"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.3.tgz#76852132a58ed5c7c0ef67e4441b9bb5d6061b3b"
|
||||
integrity sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==
|
||||
dependencies:
|
||||
side-channel "^1.1.0"
|
||||
es-define-property "^1.0.1"
|
||||
side-channel "^1.1.1"
|
||||
|
||||
querystring-es3@^0.2.1:
|
||||
version "0.2.1"
|
||||
@@ -11808,10 +11809,10 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.3:
|
||||
hash-base "^3.1.2"
|
||||
inherits "^2.0.4"
|
||||
|
||||
roarr@7.21.4:
|
||||
version "7.21.4"
|
||||
resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.21.4.tgz#c202c84d0b201ac821591f4bb46a3b28b8affe6b"
|
||||
integrity sha512-qvfUKCrpPzhWmQ4NxRYnuwhkI5lwmObhBU06BCK/lpj6PID9nL4Hk6XDwek2foKI+TMaV+Yw//XZshGF2Lox/Q==
|
||||
roarr@7.21.7:
|
||||
version "7.21.7"
|
||||
resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.21.7.tgz#b77c762660378234e1370c3e333596a744c0f6b1"
|
||||
integrity sha512-6X9ID9jb83kPkDxm5xLb9rZdGm6ksdDjpeL0iW5weKelJFi+NVBSowRpEuH8CdpX2x+7RW0TZaezibE7yQB7pg==
|
||||
dependencies:
|
||||
fast-printf "^1.6.9"
|
||||
safe-stable-stringify "^2.4.3"
|
||||
@@ -11966,10 +11967,10 @@ semver-compare@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@7.8.0, semver@^5.5.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~7.0.0:
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.0.tgz#ed0661039fcbcda2ce71f01fa6adbefaa77040df"
|
||||
integrity sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==
|
||||
"semver@2 || 3 || 4 || 5", semver@7.8.5, semver@^5.5.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~7.0.0:
|
||||
version "7.8.5"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69"
|
||||
integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==
|
||||
|
||||
send@0.17.1:
|
||||
version "0.17.1"
|
||||
@@ -12155,7 +12156,7 @@ shell-quote@^1.8.3:
|
||||
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b"
|
||||
integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==
|
||||
|
||||
side-channel-list@^1.0.0:
|
||||
side-channel-list@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127"
|
||||
integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==
|
||||
@@ -12184,14 +12185,14 @@ side-channel-weakmap@^1.0.2:
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-map "^1.0.1"
|
||||
|
||||
side-channel@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
|
||||
integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
|
||||
side-channel@^1.1.0, side-channel@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab"
|
||||
integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
object-inspect "^1.13.3"
|
||||
side-channel-list "^1.0.0"
|
||||
object-inspect "^1.13.4"
|
||||
side-channel-list "^1.0.1"
|
||||
side-channel-map "^1.0.1"
|
||||
side-channel-weakmap "^1.0.2"
|
||||
|
||||
@@ -13084,10 +13085,10 @@ undefsafe@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
|
||||
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
|
||||
|
||||
undici-types@~7.19.0:
|
||||
version "7.19.2"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.19.2.tgz#1b67fc26d0f157a0cba3a58a5b5c1e2276b8ba2a"
|
||||
integrity sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==
|
||||
"undici-types@>=7.24.0 <7.24.7":
|
||||
version "7.24.6"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.24.6.tgz#61275b485d7fd4e9d269c7cf04ec2873c9cc0f91"
|
||||
integrity sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==
|
||||
|
||||
unfetch@4.2.0:
|
||||
version "4.2.0"
|
||||
@@ -13838,9 +13839,9 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
|
||||
integrity sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==
|
||||
|
||||
yaml@^2.5.1:
|
||||
version "2.8.4"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.4.tgz#4b5f411dd25f9544914d8673d4da7f29248e5e2e"
|
||||
integrity sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.9.0.tgz#78274afd93598a1dfdd6130df6a566defcbf9aa4"
|
||||
integrity sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==
|
||||
|
||||
yargs-parser@^18.1.2:
|
||||
version "18.1.3"
|
||||
|
||||
Reference in New Issue
Block a user