@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.
Files changed (294) hide show
  1. package/assets/translations/en-us.yaml +33 -769
  2. package/assets/translations/zh-hans.yaml +153 -781
  3. package/components/ActionMenu.vue +3 -3
  4. package/components/CodeMirror.vue +6 -8
  5. package/components/CommunityLinks.vue +1 -1
  6. package/components/ContainerResourceLimit.vue +14 -0
  7. package/components/ExplorerMembers.vue +123 -0
  8. package/components/ExplorerProjectsNamespaces.vue +405 -0
  9. package/components/GrafanaDashboard.vue +17 -2
  10. package/components/LocaleSelector.vue +81 -0
  11. package/components/PromptModal.vue +2 -3
  12. package/components/ResourceList/index.vue +1 -1
  13. package/components/ResourceTable.vue +3 -6
  14. package/components/SingleClusterInfo.vue +1 -1
  15. package/components/SortableTable/index.vue +23 -20
  16. package/components/SortableTable/selection.js +1 -0
  17. package/components/auth/AzureWarning.vue +5 -1
  18. package/components/auth/Principal.vue +1 -1
  19. package/components/auth/RoleDetailEdit.vue +32 -12
  20. package/components/fleet/FleetRepos.vue +0 -2
  21. package/components/form/NameNsDescription.vue +4 -6
  22. package/components/form/NodeScheduling.vue +1 -1
  23. package/components/form/ResourceTabs/index.vue +27 -18
  24. package/components/form/WorkloadPorts.vue +1 -1
  25. package/components/formatter/ClusterLink.vue +13 -0
  26. package/components/formatter/PodImages.vue +11 -1
  27. package/components/formatter/RKETemplateName.vue +37 -0
  28. package/components/formatter/WorkloadHealthScale.vue +1 -1
  29. package/components/nav/Header.vue +9 -9
  30. package/components/nav/NamespaceFilter.vue +7 -4
  31. package/components/nav/TopLevelMenu.vue +6 -43
  32. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  33. package/config/product/harvester-manager.js +64 -2
  34. package/config/product/manager.js +9 -0
  35. package/config/settings.js +17 -71
  36. package/config/table-headers.js +0 -1
  37. package/config/types.js +8 -26
  38. package/core/plugin-routes.ts +34 -22
  39. package/core/plugin.ts +15 -3
  40. package/core/plugins-loader.js +2 -0
  41. package/core/plugins.js +79 -36
  42. package/core/types.ts +7 -1
  43. package/creators/app/tsconfig.json +6 -1
  44. package/creators/pkg/init +3 -0
  45. package/creators/pkg/tsconfig.json +7 -2
  46. package/detail/provisioning.cattle.io.cluster.vue +23 -0
  47. package/detail/workload/index.vue +11 -5
  48. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  49. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  50. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  51. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  52. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  53. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  54. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  55. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  56. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +0 -0
  57. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  58. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  59. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  60. package/edit/auth/azuread.vue +20 -1
  61. package/edit/cloudcredential.vue +7 -1
  62. package/edit/management.cattle.io.project.vue +2 -2
  63. package/edit/namespace.vue +17 -10
  64. package/edit/networking.k8s.io.ingress/index.vue +2 -1
  65. package/edit/persistentvolumeclaim.vue +33 -2
  66. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  67. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +34 -6
  68. package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
  69. package/edit/provisioning.cattle.io.cluster/rke2.vue +21 -6
  70. package/edit/service.vue +1 -1
  71. package/edit/workload/index.vue +363 -15
  72. package/edit/workload/mixins/workload.js +62 -7
  73. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  74. package/layouts/default.vue +52 -27
  75. package/layouts/error.vue +5 -1
  76. package/layouts/home.vue +6 -2
  77. package/list/harvesterhci.io.management.cluster.vue +74 -33
  78. package/list/namespace.vue +3 -5
  79. package/list/provisioning.cattle.io.cluster.vue +6 -0
  80. package/machine-config/amazonec2.vue +2 -0
  81. package/machine-config/harvester.vue +96 -49
  82. package/middleware/authenticated.js +56 -52
  83. package/mixins/brand.js +3 -4
  84. package/mixins/create-edit-view/impl.js +0 -8
  85. package/mixins/form-validation.js +1 -1
  86. package/mixins/resource-fetch.js +3 -1
  87. package/models/chart.js +1 -1
  88. package/models/cluster/node.js +12 -1
  89. package/models/fleet.cattle.io.bundle.js +26 -19
  90. package/models/harvesterhci.io.management.cluster.js +194 -5
  91. package/models/management.cattle.io.cluster.js +1 -1
  92. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  93. package/models/management.cattle.io.globalrole.js +0 -19
  94. package/models/management.cattle.io.project.js +23 -2
  95. package/models/management.cattle.io.roletemplate.js +2 -21
  96. package/models/namespace.js +19 -3
  97. package/models/pod.js +19 -2
  98. package/models/provisioning.cattle.io.cluster.js +71 -0
  99. package/models/service.js +5 -1
  100. package/models/workload.js +4 -243
  101. package/models/workload.service.js +314 -0
  102. package/nuxt.config.js +14 -12
  103. package/package.json +3 -3
  104. package/pages/auth/login.vue +11 -2
  105. package/pages/auth/setup.vue +1 -1
  106. package/pages/c/_cluster/_product/members/index.vue +3 -93
  107. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  108. package/pages/c/_cluster/apps/charts/install.vue +0 -6
  109. package/pages/c/_cluster/settings/performance.vue +19 -16
  110. package/pages/fail-whale.vue +1 -10
  111. package/pages/index.vue +18 -4
  112. package/pages/plugins.vue +2 -2
  113. package/pages/prefs.vue +8 -6
  114. package/pkg/auto-import.js +44 -7
  115. package/pkg/dynamic-plugin-loader.js +28 -0
  116. package/pkg/import.js +2 -2
  117. package/pkg/model-loader-require.lib.js +3 -0
  118. package/pkg/vue.config.js +9 -6
  119. package/plugins/console.js +10 -5
  120. package/plugins/dashboard-store/actions.js +8 -3
  121. package/plugins/dashboard-store/getters.js +7 -2
  122. package/plugins/dashboard-store/model-loader-require.js +12 -0
  123. package/plugins/dashboard-store/model-loader.js +4 -1
  124. package/plugins/dashboard-store/resource-class.js +10 -3
  125. package/plugins/steve/actions.js +1 -1
  126. package/plugins/steve/index.js +6 -4
  127. package/plugins/steve/steve-description-class.js +32 -0
  128. package/plugins/steve/subscribe.js +34 -23
  129. package/rancher-components/Banner/Banner.vue +2 -2
  130. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  131. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  132. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +0 -2
  133. package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
  134. package/rancher-components/Form/Radio/RadioButton.vue +14 -1
  135. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  136. package/{components/form → rancher-components/Form/ToggleSwitch}/ToggleSwitch.vue +18 -8
  137. package/rancher-components/Form/ToggleSwitch/index.ts +1 -0
  138. package/rancher-components/Form/index.ts +1 -0
  139. package/scripts/build-pkg.sh +48 -2
  140. package/scripts/drone-build-pkg.sh +31 -0
  141. package/scripts/publish-shell.sh +10 -11
  142. package/scripts/serve-pkgs +17 -10
  143. package/scripts/test-plugins-build.sh +18 -1
  144. package/store/catalog.js +3 -1
  145. package/store/i18n.js +16 -11
  146. package/store/index.js +4 -181
  147. package/store/prefs.js +30 -2
  148. package/store/type-map.js +16 -29
  149. package/types/{index.d.ts → rancher/index.d.ts} +0 -0
  150. package/utils/cluster.js +1 -1
  151. package/utils/custom-validators.js +1 -12
  152. package/utils/dynamic-importer.js +1 -1
  153. package/utils/validators/setting.js +0 -35
  154. package/components/FilterLabel.vue +0 -254
  155. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  156. package/components/VMConsoleBar.vue +0 -87
  157. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  158. package/components/dialog/harvester/BackupModal.vue +0 -117
  159. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  160. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  161. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  162. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  163. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  164. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  165. package/components/dialog/harvester/SupportBundle.vue +0 -217
  166. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  167. package/components/form/SerialConsole/index.vue +0 -267
  168. package/components/formatter/AttachVMWithName.vue +0 -46
  169. package/components/formatter/CloudInitType.vue +0 -27
  170. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  171. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  172. package/components/formatter/HarvesterDiskState.vue +0 -66
  173. package/components/formatter/HarvesterHostName.vue +0 -66
  174. package/components/formatter/HarvesterIpAddress.vue +0 -90
  175. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  176. package/components/formatter/HarvesterMigrationState.vue +0 -85
  177. package/components/formatter/HarvesterNodeName.vue +0 -49
  178. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  179. package/components/formatter/HarvesterVmState.vue +0 -123
  180. package/components/nav/HarvesterUpgrade.vue +0 -232
  181. package/components/novnc/NovncConsole.vue +0 -93
  182. package/components/novnc/NovncConsoleItem.vue +0 -89
  183. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  184. package/config/harvester-map.js +0 -44
  185. package/config/harvester-table-headers.js +0 -27
  186. package/config/product/harvester.js +0 -305
  187. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  188. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  189. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  190. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  191. package/detail/harvesterhci.io.host/index.vue +0 -243
  192. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  193. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  194. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  195. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  196. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  197. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  198. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  199. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  200. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  201. package/edit/harvesterhci.io.host/index.vue +0 -533
  202. package/edit/harvesterhci.io.keypair.vue +0 -112
  203. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  204. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  205. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  206. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  207. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  208. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  209. package/edit/harvesterhci.io.setting/index.vue +0 -201
  210. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  211. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  212. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  213. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  214. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  215. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  216. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  217. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  218. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  219. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  220. package/edit/harvesterhci.io.volume.vue +0 -195
  221. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  222. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  223. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  224. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  225. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  226. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  227. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  228. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  229. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  230. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  231. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  232. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  233. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  234. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  235. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  236. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  237. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  238. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  239. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  240. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  241. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  242. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  243. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  244. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  245. package/edit/workload/types/Deployment.vue +0 -377
  246. package/edit/workload/types/Generic.vue +0 -295
  247. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  248. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  249. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  250. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  251. package/list/harvesterhci.io.host/index.vue +0 -186
  252. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  253. package/list/harvesterhci.io.setting.vue +0 -241
  254. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  255. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  256. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  257. package/list/harvesterhci.io.volume.vue +0 -122
  258. package/list/kubevirt.io.virtualmachine.vue +0 -193
  259. package/mixins/harvester-vm/impl.js +0 -267
  260. package/mixins/harvester-vm/index.js +0 -1357
  261. package/models/harvester/configmap.js +0 -32
  262. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  263. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  264. package/models/harvester/harvesterhci.io.setting.js +0 -127
  265. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  266. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  267. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  268. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  269. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  270. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  271. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  272. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  273. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  274. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  275. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  276. package/models/harvester/management.cattle.io.setting.js +0 -40
  277. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  278. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  279. package/models/harvester/node.js +0 -255
  280. package/models/harvester/persistentvolumeclaim.js +0 -166
  281. package/models/harvester/pod.js +0 -185
  282. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  283. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  284. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  285. package/pages/c/_cluster/harvester/index.vue +0 -24
  286. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  287. package/pkg/model-loader.lib.js +0 -3
  288. package/plugins/lookup.js +0 -50
  289. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  290. package/store/harvester-common.js +0 -126
  291. package/utils/validators/vm-datavolumes.js +0 -38
  292. package/utils/validators/vm-image.js +0 -32
  293. package/utils/validators/vm.js +0 -221
  294. 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 '~shell/utils/array';
5
- import { FLEET } from '~shell/config/types';
6
- import { convertSelectorObj, matching } from '~shell/utils/selector';
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'](FLEET.WORKSPACE, this.metadata.namespace);
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 ( workspace.id === 'fleet-local' ) {
45
+ if (workspace.id === 'fleet-local') {
43
46
  const local = findBy(groups, 'id', 'fleet-local/default');
44
47
 
45
- if ( local ) {
48
+ if (local) {
46
49
  return local.targetClusters;
47
50
  }
48
51
 
49
52
  return [];
50
53
  }
51
54
 
52
- for ( const tgt of this.spec.targets ) {
53
- if ( tgt.clusterName ) {
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 ( cluster ) {
59
+ if (cluster) {
57
60
  addObject(out, cluster);
58
61
  }
59
- } else if ( tgt.clusterGroup ) {
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 ( group ) {
68
+ if (group) {
66
69
  addObjects(out, group.targetClusters);
67
70
  }
68
- } else if ( tgt.clusterGroupSelector ) {
71
+ } else if (tgt.clusterGroupSelector) {
69
72
  const expressions = convertSelectorObj(tgt.clusterGroupSelector);
70
73
  const matchingGroups = matching(groups, expressions);
71
74
 
72
- for ( const group of matchingGroups ) {
75
+ for (const group of matchingGroups) {
73
76
  addObjects(out, group.targetClusters);
74
77
  }
75
- } else if ( tgt.clusterSelector ) {
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 = message?.toLowerCase().includes('errapplied') || message?.toLowerCase().includes('error');
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 ( name ) {
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']('resourceTable.groupLabel.notInAWorkspace');
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
- export default class HciCluster extends ProvCluster {
5
- get availableActions() {
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 { NAME as HARVESTER } from '@shell/config/product/harvester';
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 SteveModel from '@shell/plugins/steve/steve-class';
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 SteveModel {
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
  }
@@ -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
- if (this.$rootGetters['isSingleProduct']) {
176
- return { name: 'c-cluster-product-resource' };
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 { name: this.$rootGetters['isRancher'] ? 'c-cluster-product-projectsnamespaces' : 'c-cluster-product-namespaces' };
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 SteveModel {
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', { type: POD, selector: podRelationship.selector }, { root: true });
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;