@rancher/shell 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/translations/en-us.yaml +33 -769
- package/assets/translations/zh-hans.yaml +153 -781
- package/components/ActionMenu.vue +3 -3
- package/components/CodeMirror.vue +6 -8
- package/components/CommunityLinks.vue +1 -1
- package/components/ContainerResourceLimit.vue +14 -0
- package/components/ExplorerMembers.vue +123 -0
- package/components/ExplorerProjectsNamespaces.vue +405 -0
- package/components/GrafanaDashboard.vue +17 -2
- package/components/LocaleSelector.vue +81 -0
- package/components/PromptModal.vue +2 -3
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +3 -6
- package/components/SingleClusterInfo.vue +1 -1
- package/components/SortableTable/index.vue +23 -20
- package/components/SortableTable/selection.js +1 -0
- package/components/auth/AzureWarning.vue +5 -1
- package/components/auth/Principal.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +32 -12
- package/components/fleet/FleetRepos.vue +0 -2
- package/components/form/NameNsDescription.vue +4 -6
- package/components/form/NodeScheduling.vue +1 -1
- package/components/form/ResourceTabs/index.vue +27 -18
- package/components/form/WorkloadPorts.vue +1 -1
- package/components/formatter/ClusterLink.vue +13 -0
- package/components/formatter/PodImages.vue +11 -1
- package/components/formatter/RKETemplateName.vue +37 -0
- package/components/formatter/WorkloadHealthScale.vue +1 -1
- package/components/nav/Header.vue +9 -9
- package/components/nav/NamespaceFilter.vue +7 -4
- package/components/nav/TopLevelMenu.vue +6 -43
- package/components/nav/WindowManager/ContainerLogs.vue +1 -1
- package/config/product/harvester-manager.js +64 -2
- package/config/product/manager.js +9 -0
- package/config/settings.js +17 -71
- package/config/table-headers.js +0 -1
- package/config/types.js +8 -26
- package/core/plugin-routes.ts +34 -22
- package/core/plugin.ts +15 -3
- package/core/plugins-loader.js +2 -0
- package/core/plugins.js +79 -36
- package/core/types.ts +7 -1
- package/creators/app/tsconfig.json +6 -1
- package/creators/pkg/init +3 -0
- package/creators/pkg/tsconfig.json +7 -2
- package/detail/provisioning.cattle.io.cluster.vue +23 -0
- package/detail/workload/index.vue +11 -5
- package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
- package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
- package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
- package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
- package/{components/dialog → dialog}/DrainNode.vue +0 -0
- package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
- package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
- package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
- package/{components/dialog → dialog}/RotateCertificatesDialog.vue +0 -0
- package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
- package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
- package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
- package/edit/auth/azuread.vue +20 -1
- package/edit/cloudcredential.vue +7 -1
- package/edit/management.cattle.io.project.vue +2 -2
- package/edit/namespace.vue +17 -10
- package/edit/networking.k8s.io.ingress/index.vue +2 -1
- package/edit/persistentvolumeclaim.vue +33 -2
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +34 -6
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +21 -6
- package/edit/service.vue +1 -1
- package/edit/workload/index.vue +363 -15
- package/edit/workload/mixins/workload.js +62 -7
- package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
- package/layouts/default.vue +52 -27
- package/layouts/error.vue +5 -1
- package/layouts/home.vue +6 -2
- package/list/harvesterhci.io.management.cluster.vue +74 -33
- package/list/namespace.vue +3 -5
- package/list/provisioning.cattle.io.cluster.vue +6 -0
- package/machine-config/amazonec2.vue +2 -0
- package/machine-config/harvester.vue +96 -49
- package/middleware/authenticated.js +56 -52
- package/mixins/brand.js +3 -4
- package/mixins/create-edit-view/impl.js +0 -8
- package/mixins/form-validation.js +1 -1
- package/mixins/resource-fetch.js +3 -1
- package/models/chart.js +1 -1
- package/models/cluster/node.js +12 -1
- package/models/fleet.cattle.io.bundle.js +26 -19
- package/models/harvesterhci.io.management.cluster.js +194 -5
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
- package/models/management.cattle.io.globalrole.js +0 -19
- package/models/management.cattle.io.project.js +23 -2
- package/models/management.cattle.io.roletemplate.js +2 -21
- package/models/namespace.js +19 -3
- package/models/pod.js +19 -2
- package/models/provisioning.cattle.io.cluster.js +71 -0
- package/models/service.js +5 -1
- package/models/workload.js +4 -243
- package/models/workload.service.js +314 -0
- package/nuxt.config.js +14 -12
- package/package.json +3 -3
- package/pages/auth/login.vue +11 -2
- package/pages/auth/setup.vue +1 -1
- package/pages/c/_cluster/_product/members/index.vue +3 -93
- package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
- package/pages/c/_cluster/apps/charts/install.vue +0 -6
- package/pages/c/_cluster/settings/performance.vue +19 -16
- package/pages/fail-whale.vue +1 -10
- package/pages/index.vue +18 -4
- package/pages/plugins.vue +2 -2
- package/pages/prefs.vue +8 -6
- package/pkg/auto-import.js +44 -7
- package/pkg/dynamic-plugin-loader.js +28 -0
- package/pkg/import.js +2 -2
- package/pkg/model-loader-require.lib.js +3 -0
- package/pkg/vue.config.js +9 -6
- package/plugins/console.js +10 -5
- package/plugins/dashboard-store/actions.js +8 -3
- package/plugins/dashboard-store/getters.js +7 -2
- package/plugins/dashboard-store/model-loader-require.js +12 -0
- package/plugins/dashboard-store/model-loader.js +4 -1
- package/plugins/dashboard-store/resource-class.js +10 -3
- package/plugins/steve/actions.js +1 -1
- package/plugins/steve/index.js +6 -4
- package/plugins/steve/steve-description-class.js +32 -0
- package/plugins/steve/subscribe.js +34 -23
- package/rancher-components/Banner/Banner.vue +2 -2
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +0 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
- package/rancher-components/Form/Radio/RadioButton.vue +14 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
- package/{components/form → rancher-components/Form/ToggleSwitch}/ToggleSwitch.vue +18 -8
- package/rancher-components/Form/ToggleSwitch/index.ts +1 -0
- package/rancher-components/Form/index.ts +1 -0
- package/scripts/build-pkg.sh +48 -2
- package/scripts/drone-build-pkg.sh +31 -0
- package/scripts/publish-shell.sh +10 -11
- package/scripts/serve-pkgs +17 -10
- package/scripts/test-plugins-build.sh +18 -1
- package/store/catalog.js +3 -1
- package/store/i18n.js +16 -11
- package/store/index.js +4 -181
- package/store/prefs.js +30 -2
- package/store/type-map.js +16 -29
- package/types/{index.d.ts → rancher/index.d.ts} +0 -0
- package/utils/cluster.js +1 -1
- package/utils/custom-validators.js +1 -12
- package/utils/dynamic-importer.js +1 -1
- package/utils/validators/setting.js +0 -35
- package/components/FilterLabel.vue +0 -254
- package/components/HarvesterUpgradeProgressBarList.vue +0 -109
- package/components/VMConsoleBar.vue +0 -87
- package/components/dialog/harvester/AddHotplugModal.vue +0 -159
- package/components/dialog/harvester/BackupModal.vue +0 -117
- package/components/dialog/harvester/CloneTemplate.vue +0 -125
- package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
- package/components/dialog/harvester/ExportImageDialog.vue +0 -152
- package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
- package/components/dialog/harvester/MigrationDialog.vue +0 -154
- package/components/dialog/harvester/RestoreDialog.vue +0 -153
- package/components/dialog/harvester/SupportBundle.vue +0 -217
- package/components/dialog/harvester/UnplugVolume.vue +0 -108
- package/components/form/SerialConsole/index.vue +0 -267
- package/components/formatter/AttachVMWithName.vue +0 -46
- package/components/formatter/CloudInitType.vue +0 -27
- package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
- package/components/formatter/HarvesterCPUUsed.vue +0 -122
- package/components/formatter/HarvesterDiskState.vue +0 -66
- package/components/formatter/HarvesterHostName.vue +0 -66
- package/components/formatter/HarvesterIpAddress.vue +0 -90
- package/components/formatter/HarvesterMemoryUsed.vue +0 -140
- package/components/formatter/HarvesterMigrationState.vue +0 -85
- package/components/formatter/HarvesterNodeName.vue +0 -49
- package/components/formatter/HarvesterStorageUsed.vue +0 -194
- package/components/formatter/HarvesterVmState.vue +0 -123
- package/components/nav/HarvesterUpgrade.vue +0 -232
- package/components/novnc/NovncConsole.vue +0 -93
- package/components/novnc/NovncConsoleItem.vue +0 -89
- package/components/novnc/NovncConsoleWrapper.vue +0 -243
- package/config/harvester-map.js +0 -44
- package/config/harvester-table-headers.js +0 -27
- package/config/product/harvester.js +0 -305
- package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
- package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
- package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
- package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
- package/detail/harvesterhci.io.host/index.vue +0 -243
- package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
- package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
- package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
- package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
- package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
- package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
- package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
- package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
- package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
- package/edit/harvesterhci.io.host/index.vue +0 -533
- package/edit/harvesterhci.io.keypair.vue +0 -112
- package/edit/harvesterhci.io.managedchart/index.vue +0 -25
- package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
- package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
- package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
- package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
- package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
- package/edit/harvesterhci.io.setting/index.vue +0 -201
- package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
- package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
- package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
- package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
- package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
- package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
- package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
- package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
- package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
- package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
- package/edit/harvesterhci.io.volume.vue +0 -195
- package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
- package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
- package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
- package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
- package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
- package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
- package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
- package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
- package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
- package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
- package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
- package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
- package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
- package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
- package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
- package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
- package/edit/workload/types/Deployment.vue +0 -377
- package/edit/workload/types/Generic.vue +0 -295
- package/list/harvesterhci.io.cloudtemplate.vue +0 -78
- package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
- package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
- package/list/harvesterhci.io.dashboard/index.vue +0 -752
- package/list/harvesterhci.io.host/index.vue +0 -186
- package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
- package/list/harvesterhci.io.setting.vue +0 -241
- package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
- package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
- package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
- package/list/harvesterhci.io.volume.vue +0 -122
- package/list/kubevirt.io.virtualmachine.vue +0 -193
- package/mixins/harvester-vm/impl.js +0 -267
- package/mixins/harvester-vm/index.js +0 -1357
- package/models/harvester/configmap.js +0 -32
- package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
- package/models/harvester/harvesterhci.io.keypair.js +0 -12
- package/models/harvester/harvesterhci.io.setting.js +0 -127
- package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
- package/models/harvester/harvesterhci.io.upgrade.js +0 -226
- package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
- package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
- package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
- package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
- package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
- package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
- package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
- package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
- package/models/harvester/management.cattle.io.managedchart.js +0 -191
- package/models/harvester/management.cattle.io.setting.js +0 -40
- package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
- package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
- package/models/harvester/node.js +0 -255
- package/models/harvester/persistentvolumeclaim.js +0 -166
- package/models/harvester/pod.js +0 -185
- package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
- package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
- package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
- package/pages/c/_cluster/harvester/index.vue +0 -24
- package/pages/c/_cluster/harvester/support/index.vue +0 -154
- package/pkg/model-loader.lib.js +0 -3
- package/plugins/lookup.js +0 -50
- package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
- package/store/harvester-common.js +0 -126
- package/utils/validators/vm-datavolumes.js +0 -38
- package/utils/validators/vm-image.js +0 -32
- package/utils/validators/vm.js +0 -221
- package/yarn-error.log +0 -196
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { escapeHtml, ucFirst } from '@shell/utils/string';
|
|
2
2
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
3
3
|
import typeHelper from '@shell/utils/type-helpers';
|
|
4
|
-
import { addObject, addObjects, findBy } from '
|
|
5
|
-
import { FLEET } from '
|
|
6
|
-
import { convertSelectorObj, matching } from '
|
|
4
|
+
import { addObject, addObjects, findBy } from '@shell/utils/array';
|
|
5
|
+
import { FLEET } from '@shell/config/types';
|
|
6
|
+
import { convertSelectorObj, matching } from '@shell/utils/selector';
|
|
7
7
|
|
|
8
8
|
export default class FleetBundle extends SteveModel {
|
|
9
9
|
get deploymentInfo() {
|
|
@@ -13,7 +13,7 @@ export default class FleetBundle extends SteveModel {
|
|
|
13
13
|
return {
|
|
14
14
|
ready,
|
|
15
15
|
unready: total - ready,
|
|
16
|
-
total
|
|
16
|
+
total
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -34,45 +34,48 @@ export default class FleetBundle extends SteveModel {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
get targetClusters() {
|
|
37
|
-
const workspace = this.$getters['byId'](
|
|
37
|
+
const workspace = this.$getters['byId'](
|
|
38
|
+
FLEET.WORKSPACE,
|
|
39
|
+
this.metadata.namespace
|
|
40
|
+
);
|
|
38
41
|
const clusters = workspace?.clusters || [];
|
|
39
42
|
const groups = workspace?.clusterGroups || [];
|
|
40
43
|
const out = [];
|
|
41
44
|
|
|
42
|
-
if (
|
|
45
|
+
if (workspace.id === 'fleet-local') {
|
|
43
46
|
const local = findBy(groups, 'id', 'fleet-local/default');
|
|
44
47
|
|
|
45
|
-
if (
|
|
48
|
+
if (local) {
|
|
46
49
|
return local.targetClusters;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
return [];
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
for (
|
|
53
|
-
if (
|
|
55
|
+
for (const tgt of this.spec.targets) {
|
|
56
|
+
if (tgt.clusterName) {
|
|
54
57
|
const cluster = findBy(clusters, 'metadata.name', tgt.clusterName);
|
|
55
58
|
|
|
56
|
-
if (
|
|
59
|
+
if (cluster) {
|
|
57
60
|
addObject(out, cluster);
|
|
58
61
|
}
|
|
59
|
-
} else if (
|
|
62
|
+
} else if (tgt.clusterGroup) {
|
|
60
63
|
const group = findBy(groups, {
|
|
61
64
|
'metadata.namespace': this.metadata.namespace,
|
|
62
|
-
'metadata.name': tgt.clusterGroup
|
|
65
|
+
'metadata.name': tgt.clusterGroup
|
|
63
66
|
});
|
|
64
67
|
|
|
65
|
-
if (
|
|
68
|
+
if (group) {
|
|
66
69
|
addObjects(out, group.targetClusters);
|
|
67
70
|
}
|
|
68
|
-
} else if (
|
|
71
|
+
} else if (tgt.clusterGroupSelector) {
|
|
69
72
|
const expressions = convertSelectorObj(tgt.clusterGroupSelector);
|
|
70
73
|
const matchingGroups = matching(groups, expressions);
|
|
71
74
|
|
|
72
|
-
for (
|
|
75
|
+
for (const group of matchingGroups) {
|
|
73
76
|
addObjects(out, group.targetClusters);
|
|
74
77
|
}
|
|
75
|
-
} else if (
|
|
78
|
+
} else if (tgt.clusterSelector) {
|
|
76
79
|
const expressions = convertSelectorObj(tgt.clusterSelector);
|
|
77
80
|
const matchingClusters = matching(clusters, expressions);
|
|
78
81
|
|
|
@@ -106,7 +109,9 @@ export default class FleetBundle extends SteveModel {
|
|
|
106
109
|
* "type": "Ready"
|
|
107
110
|
* },
|
|
108
111
|
*/
|
|
109
|
-
const hasErrorMessage =
|
|
112
|
+
const hasErrorMessage =
|
|
113
|
+
message?.toLowerCase().includes('errapplied') ||
|
|
114
|
+
message?.toLowerCase().includes('error');
|
|
110
115
|
|
|
111
116
|
return errState && hasErrorMessage;
|
|
112
117
|
});
|
|
@@ -123,10 +128,12 @@ export default class FleetBundle extends SteveModel {
|
|
|
123
128
|
get groupByLabel() {
|
|
124
129
|
const name = this.metadata.namespace;
|
|
125
130
|
|
|
126
|
-
if (
|
|
131
|
+
if (name) {
|
|
127
132
|
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.workspace', { name: escapeHtml(name) });
|
|
128
133
|
} else {
|
|
129
|
-
return this.$rootGetters['i18n/t'](
|
|
134
|
+
return this.$rootGetters['i18n/t'](
|
|
135
|
+
'resourceTable.groupLabel.notInAWorkspace'
|
|
136
|
+
);
|
|
130
137
|
}
|
|
131
138
|
}
|
|
132
139
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
2
|
import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
|
|
3
|
-
import { DEFAULT_WORKSPACE } from '@shell/config/types';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return this._availableActions;
|
|
7
|
-
}
|
|
3
|
+
import { DEFAULT_WORKSPACE, HCI, MANAGEMENT } from '@shell/config/types';
|
|
4
|
+
import { HARVESTER_NAME, HARVESTER_NAME as VIRTUAL } from '@shell/config/product/harvester-manager';
|
|
5
|
+
import { SETTING } from '@shell/config/settings';
|
|
8
6
|
|
|
7
|
+
export default class HciCluster extends ProvCluster {
|
|
9
8
|
get stateObj() {
|
|
10
9
|
return this._stateObj;
|
|
11
10
|
}
|
|
@@ -30,4 +29,194 @@ export default class HciCluster extends ProvCluster {
|
|
|
30
29
|
get canEdit() {
|
|
31
30
|
return false;
|
|
32
31
|
}
|
|
32
|
+
|
|
33
|
+
cachedHarvesterClusterVersion = '';
|
|
34
|
+
|
|
35
|
+
_uiInfo = undefined;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fetch and cache the response for /ui-info
|
|
39
|
+
*
|
|
40
|
+
* Storing this in a cache means any changes to `ui-info` require a dashboard refresh... but it cuts out a http request every time we
|
|
41
|
+
* go to a cluster
|
|
42
|
+
*
|
|
43
|
+
* @param {string} clusterId
|
|
44
|
+
*/
|
|
45
|
+
async _getUiInfo(clusterId) {
|
|
46
|
+
if (!this._uiInfo) {
|
|
47
|
+
try {
|
|
48
|
+
const infoUrl = `/k8s/clusters/${ clusterId }/v1/harvester/ui-info`;
|
|
49
|
+
|
|
50
|
+
this._uiInfo = await this.$dispatch('request', { url: infoUrl });
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.info(`Failed to fetch harvester ui-info from ${ this.nameDisplay }, this may be an older cluster that cannot provide one`); // eslint-disable-line no-console
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this._uiInfo;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Determine the harvester plugin's package name and url for legacy clusters that don't provide the package (i.e. it's coming from
|
|
61
|
+
* outside the cluster)
|
|
62
|
+
*/
|
|
63
|
+
_legacyClusterPkgDetails() {
|
|
64
|
+
let uiOfflinePreferred = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_OFFLINE_PREFERRED)?.value;
|
|
65
|
+
// options: ['dynamic', 'true', 'false']
|
|
66
|
+
|
|
67
|
+
if (uiOfflinePreferred === 'dynamic') {
|
|
68
|
+
// We shouldn't need to worry about the version of the dashboard when embedded in harvester (aka in isSingleProduct)
|
|
69
|
+
const version = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, 'server-version')?.value;
|
|
70
|
+
|
|
71
|
+
if (version.endsWith('-head')) {
|
|
72
|
+
uiOfflinePreferred = 'false';
|
|
73
|
+
} else {
|
|
74
|
+
uiOfflinePreferred = 'true';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// This is the version that's embedded in the dashboard
|
|
79
|
+
const pkgName = `${ HARVESTER_NAME }-1.0.3`;
|
|
80
|
+
|
|
81
|
+
if (uiOfflinePreferred === 'true') {
|
|
82
|
+
// Embedded (aka give me the version of the embedded plugin that was in the last release)
|
|
83
|
+
const embeddedPath = `dashboard/${ pkgName }/${ pkgName }.umd.min.js`;
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
pkgUrl: process.env.dev ? `${ process.env.api }/${ embeddedPath }` : embeddedPath,
|
|
87
|
+
pkgName
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (uiOfflinePreferred === 'false') {
|
|
92
|
+
// Remote (aka give me the latest version of the embedded plugin that might not have been released yet)
|
|
93
|
+
const uiDashboardHarvesterRemotePlugin = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_DASHBOARD_HARVESTER_LEGACY_PLUGIN)?.value;
|
|
94
|
+
const parts = uiDashboardHarvesterRemotePlugin?.replace('.umd.min.js', '').split('/');
|
|
95
|
+
const pkgNameFromUrl = parts?.length > 1 ? parts[parts.length - 1] : null;
|
|
96
|
+
|
|
97
|
+
if (!pkgNameFromUrl) {
|
|
98
|
+
throw new Error(`Unable to determine harvester plugin name from '${ uiDashboardHarvesterRemotePlugin }'`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
pkgUrl: uiDashboardHarvesterRemotePlugin,
|
|
103
|
+
pkgName: pkgNameFromUrl
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(`Unsupported value for ${ SETTING.UI_OFFLINE_PREFERRED }: 'uiOfflinePreferred'`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Determine the harvester plugin's package name and url for clusters that provide the plugin
|
|
112
|
+
*/
|
|
113
|
+
_supportedClusterPkgDetails(uiInfo, clusterId) {
|
|
114
|
+
const pkgName = `${ HARVESTER_NAME }-${ uiInfo['ui-plugin-bundled-version'] }`;
|
|
115
|
+
const fileName = `${ pkgName }.umd.min.js`;
|
|
116
|
+
let pkgUrl;
|
|
117
|
+
|
|
118
|
+
if (uiInfo['ui-source'] === 'bundled' ) { // offline bundled
|
|
119
|
+
pkgUrl = `k8s/clusters/${ clusterId }/v1/harvester/plugin-assets/${ fileName }`;
|
|
120
|
+
} else if (uiInfo['ui-source'] === 'external') {
|
|
121
|
+
if (uiInfo['ui-plugin-index']) {
|
|
122
|
+
pkgUrl = uiInfo['ui-plugin-index'];
|
|
123
|
+
} else {
|
|
124
|
+
throw new Error('Harvester cluster requested the plugin at `ui-plugin-index` is used, however did not provide a value for it');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
pkgUrl,
|
|
130
|
+
pkgName
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_overridePkgDetails() {
|
|
135
|
+
// Support loading the pkg from a locally, or other, address
|
|
136
|
+
// This helps testing of the harvester plugin when packaged up, instead of directly imported
|
|
137
|
+
const harvesterPkgUrl = process.env.harvesterPkgUrl;
|
|
138
|
+
|
|
139
|
+
if (!harvesterPkgUrl) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const parts = harvesterPkgUrl.replace('.umd.min.js', '').split('/');
|
|
143
|
+
const pkgNameFromUrl = parts.length > 1 ? parts[parts.length - 1] : null;
|
|
144
|
+
|
|
145
|
+
if (pkgNameFromUrl) {
|
|
146
|
+
return {
|
|
147
|
+
pkgUrl: harvesterPkgUrl,
|
|
148
|
+
pkgName: pkgNameFromUrl
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async _pkgDetails() {
|
|
154
|
+
const overridePkgDetails = this._overridePkgDetails();
|
|
155
|
+
|
|
156
|
+
if (overridePkgDetails) {
|
|
157
|
+
return overridePkgDetails;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const clusterId = this.mgmt.id;
|
|
161
|
+
const uiInfo = await this._getUiInfo(clusterId);
|
|
162
|
+
|
|
163
|
+
return uiInfo ? this._supportedClusterPkgDetails(uiInfo, clusterId) : this._legacyClusterPkgDetails();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async loadClusterPlugin() {
|
|
167
|
+
// Skip loading if it's built in
|
|
168
|
+
const plugins = this.$rootState.$plugin.getPlugins();
|
|
169
|
+
const loadedPkgs = Object.keys(plugins);
|
|
170
|
+
|
|
171
|
+
if (loadedPkgs.find(pkg => pkg === HARVESTER_NAME)) {
|
|
172
|
+
console.info('Harvester plugin built is built in, skipping load from external sources'); // eslint-disable-line no-console
|
|
173
|
+
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Determine the plugin name and the url it can be fetched from
|
|
178
|
+
const { pkgUrl, pkgName } = await this._pkgDetails();
|
|
179
|
+
|
|
180
|
+
console.info('Harvester plugin details: ', pkgName, pkgUrl); // eslint-disable-line no-console
|
|
181
|
+
|
|
182
|
+
// Skip loading if we've previously loaded the correct one
|
|
183
|
+
if (!!plugins[pkgName]) {
|
|
184
|
+
console.info('Harvester plugin already loaded, no need to load', pkgName); // eslint-disable-line no-console
|
|
185
|
+
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.info('Attempting to load Harvester plugin', pkgName); // eslint-disable-line no-console
|
|
190
|
+
|
|
191
|
+
const res = await this.$rootState.$plugin.loadAsync(pkgName, pkgUrl);
|
|
192
|
+
|
|
193
|
+
console.info('Loaded Harvester plugin', pkgName); // eslint-disable-line no-console
|
|
194
|
+
|
|
195
|
+
return res;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
goToCluster() {
|
|
199
|
+
this.loadClusterPlugin()
|
|
200
|
+
.then(() => {
|
|
201
|
+
this.currentRouter().push({
|
|
202
|
+
name: `${ VIRTUAL }-c-cluster-resource`,
|
|
203
|
+
params: {
|
|
204
|
+
cluster: this.status.clusterName,
|
|
205
|
+
product: VIRTUAL,
|
|
206
|
+
resource: HCI.DASHBOARD // Go directly to dashboard to avoid blip of components on screen
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
})
|
|
210
|
+
.catch((err) => {
|
|
211
|
+
const message = typeof error === 'object' ? JSON.stringify(err) : err;
|
|
212
|
+
|
|
213
|
+
console.error('Failed to load harvester package: ', message); // eslint-disable-line no-console
|
|
214
|
+
|
|
215
|
+
this.$dispatch('growl/error', {
|
|
216
|
+
title: this.t('harvesterManager.plugins.loadError'),
|
|
217
|
+
message,
|
|
218
|
+
timeout: 5000
|
|
219
|
+
}, { root: true });
|
|
220
|
+
});
|
|
221
|
+
}
|
|
33
222
|
}
|
|
@@ -9,7 +9,7 @@ import jsyaml from 'js-yaml';
|
|
|
9
9
|
import { eachLimit } from '@shell/utils/promise';
|
|
10
10
|
import { addParams } from '@shell/utils/url';
|
|
11
11
|
import { isEmpty } from '@shell/utils/object';
|
|
12
|
-
import {
|
|
12
|
+
import { HARVESTER_NAME as HARVESTER } from '@shell/config/product/harvester-manager';
|
|
13
13
|
import { isHarvesterCluster } from '@shell/utils/cluster';
|
|
14
14
|
import HybridModel from '@shell/plugins/steve/hybrid-class';
|
|
15
15
|
import { LINUX, WINDOWS } from '@shell/store/catalog';
|
|
@@ -2,6 +2,7 @@ import { CREATOR_ID } from '@shell/config/labels-annotations';
|
|
|
2
2
|
import { _CREATE } from '@shell/config/query-params';
|
|
3
3
|
import { MANAGEMENT, NORMAN } from '@shell/config/types';
|
|
4
4
|
import HybridModel from '@shell/plugins/steve/hybrid-class';
|
|
5
|
+
import { HARVESTER_NAME } from '@shell/config/product/harvester-manager';
|
|
5
6
|
|
|
6
7
|
export default class CRTB extends HybridModel {
|
|
7
8
|
detailPageHeaderActionOverride(realMode) {
|
|
@@ -65,6 +66,9 @@ export default class CRTB extends HybridModel {
|
|
|
65
66
|
return this.cluster ? this.cluster.nameDisplay : this.clusterName;
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* This is used in a table formatter on the management.cattle.io.user detail view which exists outside harvester so no override on this route as there is with listLocation
|
|
71
|
+
*/
|
|
68
72
|
get clusterDetailLocation() {
|
|
69
73
|
if (this.cluster) {
|
|
70
74
|
return this.cluster.detailLocation;
|
|
@@ -82,6 +86,11 @@ export default class CRTB extends HybridModel {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
get listLocation() {
|
|
89
|
+
// Harvester uses these resource directly... but has different routes
|
|
90
|
+
if (this.$rootGetters['currentProduct'].inStore === HARVESTER_NAME) {
|
|
91
|
+
return { name: `${ HARVESTER_NAME }-c-cluster-members` };
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
return { name: 'c-cluster-product-members' };
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -14,25 +14,6 @@ const SPECIAL = [BASE, ADMIN, USER];
|
|
|
14
14
|
const GLOBAL = SUBTYPE_MAPPING.GLOBAL.key;
|
|
15
15
|
|
|
16
16
|
export default class GlobalRole extends SteveModel {
|
|
17
|
-
get availableActions() {
|
|
18
|
-
const out = super._availableActions;
|
|
19
|
-
|
|
20
|
-
const toFilter = ['goToEdit', 'promptRemove'];
|
|
21
|
-
const editActions = out.filter((a) => {
|
|
22
|
-
if ( toFilter.includes(a.action) ) {
|
|
23
|
-
return a;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if ( editActions.length > 0 ) {
|
|
28
|
-
editActions.forEach((a) => {
|
|
29
|
-
a.enabled = !this.builtin;
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
17
|
get customValidationRules() {
|
|
37
18
|
return Role.customValidationRules();
|
|
38
19
|
}
|
|
@@ -2,6 +2,7 @@ import { DEFAULT_PROJECT, SYSTEM_PROJECT } from '@shell/config/labels-annotation
|
|
|
2
2
|
import { MANAGEMENT, NAMESPACE, NORMAN } from '@shell/config/types';
|
|
3
3
|
import HybridModel from '@shell/plugins/steve/hybrid-class';
|
|
4
4
|
import isEmpty from 'lodash/isEmpty';
|
|
5
|
+
import { HARVESTER_NAME as HARVESTER } from '@shell/config/product/harvester-manager';
|
|
5
6
|
|
|
6
7
|
function clearUnusedResourceQuotas(spec, types) {
|
|
7
8
|
types.forEach((type) => {
|
|
@@ -61,10 +62,30 @@ export default class Project extends HybridModel {
|
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
get doneOverride() {
|
|
66
|
+
return this.listLocation;
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
get listLocation() {
|
|
70
|
+
// Harvester uses these resource directly... but has different routes. listLocation covers routes leading back to route
|
|
71
|
+
if (this.$rootGetters['currentProduct'].inStore === HARVESTER) {
|
|
72
|
+
return { name: `${ HARVESTER }-c-cluster-projectsnamespaces` };
|
|
73
|
+
}
|
|
74
|
+
|
|
65
75
|
return { name: 'c-cluster-product-projectsnamespaces' };
|
|
66
76
|
}
|
|
67
77
|
|
|
78
|
+
get _detailLocation() {
|
|
79
|
+
// Harvester uses these resource directly... but has different routes. detailLocation covers routes leading to resource (like edit)
|
|
80
|
+
const _detailLocation = super._detailLocation;
|
|
81
|
+
|
|
82
|
+
if (this.$rootGetters['currentProduct'].inStore === HARVESTER) {
|
|
83
|
+
_detailLocation.name = `${ HARVESTER }-${ _detailLocation.name }`.replace('-product', '');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return _detailLocation;
|
|
87
|
+
}
|
|
88
|
+
|
|
68
89
|
get parentLocationOverride() {
|
|
69
90
|
return this.listLocation;
|
|
70
91
|
}
|
|
@@ -81,9 +102,9 @@ export default class Project extends HybridModel {
|
|
|
81
102
|
try {
|
|
82
103
|
await newValue.doAction('setpodsecuritypolicytemplate', { podSecurityPolicyTemplateId: this.spec.podSecurityPolicyTemplateId || null });
|
|
83
104
|
} catch (err) {
|
|
84
|
-
if (err.status === 409) {
|
|
105
|
+
if ( err.status === 409 || err.status === 403 ) {
|
|
85
106
|
// The backend updates each new project soon after it is created,
|
|
86
|
-
// so there is a chance of a resource conflict error. If that happens,
|
|
107
|
+
// so there is a chance of a resource conflict or forbidden error. If that happens,
|
|
87
108
|
// retry the action.
|
|
88
109
|
await newValue.doAction('setpodsecuritypolicytemplate', { podSecurityPolicyTemplateId: this.spec.podSecurityPolicyTemplateId || null });
|
|
89
110
|
} else {
|
|
@@ -2,7 +2,7 @@ import Vue from 'vue';
|
|
|
2
2
|
import { get } from '@shell/utils/object';
|
|
3
3
|
import { DESCRIPTION } from '@shell/config/labels-annotations';
|
|
4
4
|
import { NORMAN } from '@shell/config/types';
|
|
5
|
-
import
|
|
5
|
+
import SteveDescriptionModel from '@shell/plugins/steve/steve-description-class';
|
|
6
6
|
import Role from './rbac.authorization.k8s.io.role';
|
|
7
7
|
|
|
8
8
|
export const CATTLE_API_GROUP = '.cattle.io';
|
|
@@ -55,26 +55,7 @@ export const VERBS = [
|
|
|
55
55
|
'watch',
|
|
56
56
|
];
|
|
57
57
|
|
|
58
|
-
export default class RoleTemplate extends
|
|
59
|
-
get availableActions() {
|
|
60
|
-
const out = super._availableActions;
|
|
61
|
-
|
|
62
|
-
const toFilter = ['goToEdit', 'promptRemove'];
|
|
63
|
-
const editActions = out.filter((a) => {
|
|
64
|
-
if ( toFilter.includes(a.action) ) {
|
|
65
|
-
return a;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if ( editActions.length > 0 ) {
|
|
70
|
-
editActions.forEach((a) => {
|
|
71
|
-
a.enabled = !this.builtin;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return out;
|
|
76
|
-
}
|
|
77
|
-
|
|
58
|
+
export default class RoleTemplate extends SteveDescriptionModel {
|
|
78
59
|
get customValidationRules() {
|
|
79
60
|
return Role.customValidationRules();
|
|
80
61
|
}
|
package/models/namespace.js
CHANGED
|
@@ -9,6 +9,7 @@ import { escapeHtml } from '@shell/utils/string';
|
|
|
9
9
|
import { insertAt, isArray } from '@shell/utils/array';
|
|
10
10
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
11
11
|
import Vue from 'vue';
|
|
12
|
+
import { HARVESTER_NAME as HARVESTER } from '@shell/config/product/harvester-manager';
|
|
12
13
|
|
|
13
14
|
const OBSCURE_NAMESPACE_PREFIX = [
|
|
14
15
|
'c-', // cluster namespace
|
|
@@ -172,11 +173,26 @@ export default class Namespace extends SteveModel {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
get listLocation() {
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
const listLocation = { name: this.$rootGetters['isRancher'] ? 'c-cluster-product-projectsnamespaces' : 'c-cluster-product-resource' };
|
|
177
|
+
|
|
178
|
+
// Harvester uses these resource directly... but has different routes. listLocation covers routes leading back to route
|
|
179
|
+
if (this.$rootGetters['currentProduct'].inStore === HARVESTER) {
|
|
180
|
+
listLocation.name = `${ HARVESTER }-${ listLocation.name }`.replace('-product', '');
|
|
181
|
+
listLocation.params = { resource: 'namespace' };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return listLocation;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
get _detailLocation() {
|
|
188
|
+
const _detailLocation = super._detailLocation;
|
|
189
|
+
|
|
190
|
+
// Harvester uses these resource directly... but has different routes. detailLocation covers routes leading to resource (like edit)
|
|
191
|
+
if (this.$rootGetters['currentProduct'].inStore === HARVESTER) {
|
|
192
|
+
_detailLocation.name = `${ HARVESTER }-${ _detailLocation.name }`.replace('-product', '');
|
|
177
193
|
}
|
|
178
194
|
|
|
179
|
-
return
|
|
195
|
+
return _detailLocation;
|
|
180
196
|
}
|
|
181
197
|
|
|
182
198
|
get parentLocationOverride() {
|
package/models/pod.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { insertAt } from '@shell/utils/array';
|
|
2
2
|
import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
3
3
|
import { NODE, WORKLOAD_TYPES } from '@shell/config/types';
|
|
4
|
-
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
5
4
|
import { escapeHtml, shortenedImage } from '@shell/utils/string';
|
|
5
|
+
import WorkloadService from '@shell/models/workload.service';
|
|
6
6
|
|
|
7
7
|
export const WORKLOAD_PRIORITY = {
|
|
8
8
|
[WORKLOAD_TYPES.DEPLOYMENT]: 1,
|
|
@@ -14,7 +14,7 @@ export const WORKLOAD_PRIORITY = {
|
|
|
14
14
|
[WORKLOAD_TYPES.REPLICATION_CONTROLLER]: 7,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export default class Pod extends
|
|
17
|
+
export default class Pod extends WorkloadService {
|
|
18
18
|
get _availableActions() {
|
|
19
19
|
const out = super._availableActions;
|
|
20
20
|
|
|
@@ -180,4 +180,21 @@ export default class Pod extends SteveModel {
|
|
|
180
180
|
|
|
181
181
|
return 0;
|
|
182
182
|
}
|
|
183
|
+
|
|
184
|
+
save() {
|
|
185
|
+
const { metadata, spec } = this.spec.template;
|
|
186
|
+
|
|
187
|
+
this.spec = {
|
|
188
|
+
...this.spec,
|
|
189
|
+
metadata: {
|
|
190
|
+
...this.metadata,
|
|
191
|
+
...metadata
|
|
192
|
+
},
|
|
193
|
+
...spec
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
delete this.spec.template;
|
|
197
|
+
|
|
198
|
+
return this._save(...arguments);
|
|
199
|
+
}
|
|
183
200
|
}
|
|
@@ -36,6 +36,17 @@ export default class ProvCluster extends SteveModel {
|
|
|
36
36
|
},
|
|
37
37
|
].filter(x => !!x.content);
|
|
38
38
|
|
|
39
|
+
// RKE Template details
|
|
40
|
+
const rkeTemplate = this.rkeTemplate;
|
|
41
|
+
|
|
42
|
+
if (rkeTemplate) {
|
|
43
|
+
out.push({
|
|
44
|
+
label: this.t('cluster.detail.rkeTemplate'),
|
|
45
|
+
formatter: 'RKETemplateName',
|
|
46
|
+
content: rkeTemplate,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
if (!this.machineProvider) {
|
|
40
51
|
out.splice(1, 1);
|
|
41
52
|
|
|
@@ -258,6 +269,10 @@ export default class ProvCluster extends SteveModel {
|
|
|
258
269
|
return !!this.mgmt?.isReady;
|
|
259
270
|
}
|
|
260
271
|
|
|
272
|
+
get eksNodeGroups() {
|
|
273
|
+
return this.mgmt?.spec?.eksConfig?.nodeGroups;
|
|
274
|
+
}
|
|
275
|
+
|
|
261
276
|
waitForProvisioner(timeout, interval) {
|
|
262
277
|
return this.waitForTestFn(() => {
|
|
263
278
|
return !!this.provisioner;
|
|
@@ -597,6 +612,62 @@ export default class ProvCluster extends SteveModel {
|
|
|
597
612
|
return this._stateObj;
|
|
598
613
|
}
|
|
599
614
|
|
|
615
|
+
get rkeTemplate() {
|
|
616
|
+
if (!this.isRke1 || !this.mgmt) {
|
|
617
|
+
// Not an RKE! cluster or no management cluster available
|
|
618
|
+
return false;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (!this.mgmt.spec?.clusterTemplateRevisionName) {
|
|
622
|
+
// Cluster does not use an RKE template
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const clusterTemplateName = this.mgmt.spec.clusterTemplateName.replace(':', '/');
|
|
627
|
+
const clusterTemplateRevisionName = this.mgmt.spec.clusterTemplateRevisionName.replace(':', '/');
|
|
628
|
+
const template = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE).find(t => t.id === clusterTemplateName);
|
|
629
|
+
const revision = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE_REVISION).find(t => t.spec.enabled && t.id === clusterTemplateRevisionName);
|
|
630
|
+
|
|
631
|
+
if (!template || !revision) {
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
return {
|
|
636
|
+
displayName: `${ template.spec?.displayName }/${ revision.spec?.displayName }`,
|
|
637
|
+
upgrade: this.rkeTemplateUpgrade,
|
|
638
|
+
template,
|
|
639
|
+
revision,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
get rkeTemplateUpgrade() {
|
|
644
|
+
if (!this.isRke1 || !this.mgmt) {
|
|
645
|
+
// Not an RKE! cluster or no management cluster available
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if (!this.mgmt.spec?.clusterTemplateRevisionName) {
|
|
650
|
+
// Cluster does not use an RKE template
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const clusterTemplateRevisionName = this.mgmt.spec.clusterTemplateRevisionName.replace(':', '/');
|
|
655
|
+
|
|
656
|
+
// Get all of the template revisions for this template
|
|
657
|
+
const revisions = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE_REVISION).filter(t => t.spec.enabled && t.spec.clusterTemplateName === this.mgmt.spec.clusterTemplateName);
|
|
658
|
+
|
|
659
|
+
if (revisions.length <= 1) {
|
|
660
|
+
// Only one template revision
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
revisions.sort((a, b) => {
|
|
665
|
+
return parseInt(a.metadata.resourceVersion, 10) - parseInt(b.metadata.resourceVersion, 10);
|
|
666
|
+
}).reverse();
|
|
667
|
+
|
|
668
|
+
return revisions[0].id !== clusterTemplateRevisionName ? revisions[0].spec?.displayName : false;
|
|
669
|
+
}
|
|
670
|
+
|
|
600
671
|
get _stateObj() {
|
|
601
672
|
if (!this.isRke2) {
|
|
602
673
|
return this.mgmt?.stateObj || this.metadata?.state;
|
package/models/service.js
CHANGED
|
@@ -136,7 +136,11 @@ export default class extends SteveModel {
|
|
|
136
136
|
let pods = [];
|
|
137
137
|
|
|
138
138
|
if (podRelationship) {
|
|
139
|
-
pods = await this.$dispatch('cluster/findMatching', {
|
|
139
|
+
pods = await this.$dispatch('cluster/findMatching', {
|
|
140
|
+
type: POD,
|
|
141
|
+
selector: podRelationship.selector,
|
|
142
|
+
namespace: this.namespace
|
|
143
|
+
}, { root: true });
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
return pods;
|