@rancher/shell 0.1.2 → 0.1.4

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 (347) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/rancher-logo.svg +1 -130
  3. package/assets/images/featured/img1.jpg +0 -0
  4. package/assets/images/featured.jpg +0 -0
  5. package/assets/images/generic-plugin.svg +7 -0
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/translations/en-us.yaml +209 -813
  10. package/assets/translations/zh-hans.yaml +28 -792
  11. package/components/ActionMenu.vue +3 -3
  12. package/components/AsyncButton.vue +17 -2
  13. package/components/ButtonDropdown.vue +4 -0
  14. package/components/Carousel.vue +291 -0
  15. package/components/CodeMirror.vue +6 -8
  16. package/components/CommunityLinks.vue +70 -19
  17. package/components/ContainerResourceLimit.vue +14 -0
  18. package/components/CruResource.vue +11 -3
  19. package/components/Dialog.vue +102 -0
  20. package/components/ExplorerMembers.vue +121 -0
  21. package/components/ExplorerProjectsNamespaces.vue +404 -0
  22. package/components/GrafanaDashboard.vue +17 -2
  23. package/components/IconMessage.vue +9 -1
  24. package/components/LocaleSelector.vue +114 -0
  25. package/components/PromptModal.vue +2 -3
  26. package/components/ResourceList/index.vue +1 -1
  27. package/components/ResourceTable.vue +9 -7
  28. package/components/SimpleBox.vue +6 -4
  29. package/components/SingleClusterInfo.vue +1 -1
  30. package/components/SortableTable/index.vue +18 -25
  31. package/components/SortableTable/selection.js +1 -0
  32. package/components/Tabbed/Tab.vue +5 -0
  33. package/components/Tabbed/index.vue +29 -2
  34. package/components/auth/AzureWarning.vue +5 -1
  35. package/components/auth/Principal.vue +2 -1
  36. package/components/auth/RoleDetailEdit.vue +18 -11
  37. package/components/fleet/FleetBundles.vue +8 -3
  38. package/components/fleet/FleetRepos.vue +0 -2
  39. package/components/fleet/FleetSummary.vue +6 -0
  40. package/components/form/KeyValue.vue +80 -58
  41. package/components/form/NameNsDescription.vue +12 -8
  42. package/components/form/NodeScheduling.vue +1 -1
  43. package/components/form/ResourceTabs/index.vue +5 -1
  44. package/components/form/WorkloadPorts.vue +1 -1
  45. package/components/formatter/ClusterLink.vue +3 -7
  46. package/components/formatter/WorkloadHealthScale.vue +1 -1
  47. package/components/nav/Header.vue +9 -9
  48. package/components/nav/NamespaceFilter.vue +10 -7
  49. package/components/nav/TopLevelMenu.vue +10 -65
  50. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  51. package/config/footer.js +13 -14
  52. package/config/labels-annotations.js +2 -1
  53. package/config/product/explorer.js +5 -4
  54. package/config/product/harvester-manager.js +64 -2
  55. package/config/product/legacy.js +0 -47
  56. package/config/product/manager.js +9 -0
  57. package/config/product/multi-cluster-apps.js +0 -12
  58. package/config/product/settings.js +12 -1
  59. package/config/product/uiplugins.js +17 -0
  60. package/config/settings.js +37 -72
  61. package/config/table-headers.js +0 -1
  62. package/config/types.js +9 -25
  63. package/config/uiplugins.js +60 -0
  64. package/content/docs/en-us/getting-started.md +1 -26
  65. package/core/plugin-routes.ts +34 -22
  66. package/core/plugin.ts +15 -3
  67. package/core/plugins-loader.js +2 -0
  68. package/core/plugins.js +91 -36
  69. package/core/types.ts +7 -1
  70. package/detail/provisioning.cattle.io.cluster.vue +15 -2
  71. package/detail/workload/index.vue +11 -5
  72. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  73. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  74. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  75. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  76. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  77. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  78. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  79. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  80. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  81. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +9 -3
  82. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  83. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  84. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  85. package/edit/auth/azuread.vue +44 -6
  86. package/edit/management.cattle.io.project.vue +2 -2
  87. package/edit/namespace.vue +17 -10
  88. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  89. package/edit/persistentvolume/index.vue +3 -0
  90. package/edit/persistentvolumeclaim.vue +1 -0
  91. package/edit/pod.vue +27 -0
  92. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  93. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +33 -5
  94. package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
  95. package/edit/service.vue +8 -6
  96. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  97. package/edit/workload/index.vue +375 -15
  98. package/edit/workload/mixins/workload.js +62 -7
  99. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  100. package/edit/workload/storage/Mount.vue +1 -0
  101. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  102. package/edit/workload/storage/azureDisk.vue +22 -2
  103. package/edit/workload/storage/azureFile.vue +20 -2
  104. package/edit/workload/storage/csi/index.vue +23 -1
  105. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  106. package/edit/workload/storage/index.vue +23 -49
  107. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  108. package/edit/workload/storage/vsphereVolume.vue +11 -1
  109. package/layouts/default.vue +63 -32
  110. package/layouts/error.vue +5 -1
  111. package/layouts/home.vue +14 -5
  112. package/layouts/plain.vue +10 -5
  113. package/list/harvesterhci.io.management.cluster.vue +74 -33
  114. package/list/management.cattle.io.setting.vue +3 -3
  115. package/list/namespace.vue +3 -5
  116. package/list/provisioning.cattle.io.cluster.vue +1 -1
  117. package/machine-config/amazonec2.vue +2 -0
  118. package/machine-config/harvester.vue +100 -51
  119. package/middleware/authenticated.js +56 -52
  120. package/mixins/form-validation.js +1 -1
  121. package/mixins/resource-fetch.js +3 -1
  122. package/models/catalog.cattle.io.uiplugin.js +34 -0
  123. package/models/cluster/node.js +25 -2
  124. package/models/fleet.cattle.io.bundle.js +27 -20
  125. package/models/harvesterhci.io.management.cluster.js +200 -5
  126. package/models/management.cattle.io.cluster.js +1 -1
  127. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  128. package/models/management.cattle.io.project.js +23 -2
  129. package/models/namespace.js +19 -3
  130. package/models/pod.js +19 -2
  131. package/models/provisioning.cattle.io.cluster.js +16 -6
  132. package/models/workload.js +9 -246
  133. package/models/workload.service.js +314 -0
  134. package/nuxt.config.js +80 -34
  135. package/package.json +107 -108
  136. package/pages/auth/login.vue +11 -2
  137. package/pages/auth/setup.vue +1 -1
  138. package/pages/c/_cluster/_product/members/index.vue +3 -93
  139. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  140. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  141. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  142. package/pages/c/_cluster/explorer/index.vue +72 -9
  143. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  144. package/pages/c/_cluster/mcapps/index.vue +1 -1
  145. package/pages/c/_cluster/settings/brand.vue +0 -40
  146. package/pages/c/_cluster/settings/links.vue +200 -0
  147. package/pages/c/_cluster/settings/performance.vue +19 -16
  148. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  149. package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
  150. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
  151. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
  152. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
  153. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
  154. package/pages/c/_cluster/uiplugins/index.vue +694 -0
  155. package/pages/diagnostic.vue +185 -101
  156. package/pages/docs/_doc.vue +3 -1
  157. package/pages/fail-whale.vue +1 -10
  158. package/pages/home.vue +21 -56
  159. package/pages/index.vue +18 -4
  160. package/pages/prefs.vue +108 -86
  161. package/pages/safeMode.vue +17 -0
  162. package/pages/support/index.vue +23 -15
  163. package/pkg/auto-import.js +44 -7
  164. package/pkg/dynamic-importer.lib.js +4 -0
  165. package/pkg/dynamic-plugin-loader.js +28 -0
  166. package/pkg/import.js +2 -2
  167. package/pkg/model-loader-require.lib.js +3 -0
  168. package/pkg/vue.config.js +9 -6
  169. package/plugins/dashboard-store/model-loader-require.js +12 -0
  170. package/plugins/dashboard-store/model-loader.js +4 -1
  171. package/plugins/dashboard-store/resource-class.js +12 -5
  172. package/plugins/formatters.js +15 -0
  173. package/plugins/plugin.js +56 -4
  174. package/plugins/steve/actions.js +1 -1
  175. package/plugins/steve/index.js +6 -4
  176. package/plugins/steve/mutations.js +1 -1
  177. package/plugins/steve/subscribe.js +89 -56
  178. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  179. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  180. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  181. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  182. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  183. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  184. package/scripts/build-pkg.sh +48 -2
  185. package/scripts/drone-build-pkg.sh +31 -0
  186. package/scripts/publish-shell.sh +11 -12
  187. package/scripts/serve-pkgs +17 -10
  188. package/scripts/sync-shell-deps +37 -0
  189. package/store/catalog.js +12 -9
  190. package/store/i18n.js +26 -12
  191. package/store/index.js +4 -181
  192. package/store/prefs.js +46 -2
  193. package/store/type-map.js +47 -33
  194. package/store/uiplugins.ts +15 -61
  195. package/utils/__tests__/object.test.ts +0 -24
  196. package/utils/__tests__/selector.test.ts +1 -1
  197. package/utils/cluster.js +1 -1
  198. package/utils/custom-validators.js +1 -12
  199. package/utils/dynamic-importer.js +5 -1
  200. package/utils/grafana.js +2 -6
  201. package/utils/socket.js +41 -20
  202. package/utils/string.js +1 -7
  203. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  204. package/utils/validators/formRules/index.ts +9 -1
  205. package/utils/validators/setting.js +0 -35
  206. package/yarn-error.log +195 -0
  207. package/components/FilterLabel.vue +0 -254
  208. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  209. package/components/VMConsoleBar.vue +0 -87
  210. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  211. package/components/dialog/harvester/BackupModal.vue +0 -117
  212. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  213. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  214. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  215. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  216. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  217. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  218. package/components/dialog/harvester/SupportBundle.vue +0 -217
  219. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  220. package/components/form/SerialConsole/index.vue +0 -267
  221. package/components/formatter/AttachVMWithName.vue +0 -46
  222. package/components/formatter/CloudInitType.vue +0 -27
  223. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  224. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  225. package/components/formatter/HarvesterDiskState.vue +0 -66
  226. package/components/formatter/HarvesterHostName.vue +0 -66
  227. package/components/formatter/HarvesterIpAddress.vue +0 -90
  228. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  229. package/components/formatter/HarvesterMigrationState.vue +0 -85
  230. package/components/formatter/HarvesterNodeName.vue +0 -49
  231. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  232. package/components/formatter/HarvesterVmState.vue +0 -123
  233. package/components/nav/HarvesterUpgrade.vue +0 -232
  234. package/components/novnc/NovncConsole.vue +0 -93
  235. package/components/novnc/NovncConsoleItem.vue +0 -89
  236. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  237. package/config/harvester-map.js +0 -44
  238. package/config/harvester-table-headers.js +0 -27
  239. package/config/product/harvester.js +0 -305
  240. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  241. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  242. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  243. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  244. package/detail/harvesterhci.io.host/index.vue +0 -243
  245. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  246. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  247. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  248. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  249. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  250. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  251. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  252. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  253. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  254. package/edit/harvesterhci.io.host/index.vue +0 -533
  255. package/edit/harvesterhci.io.keypair.vue +0 -112
  256. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  257. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  258. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  259. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  260. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  261. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  262. package/edit/harvesterhci.io.setting/index.vue +0 -201
  263. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  264. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  265. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  266. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  267. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  268. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  269. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  270. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  271. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  272. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  273. package/edit/harvesterhci.io.volume.vue +0 -195
  274. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  275. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  276. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  277. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  278. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  279. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  280. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  281. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  282. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  283. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  284. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  285. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  286. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  287. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  288. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  289. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  290. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  291. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  292. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  293. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  294. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  295. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  296. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  297. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  298. package/edit/workload/types/Deployment.vue +0 -377
  299. package/edit/workload/types/Generic.vue +0 -295
  300. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  301. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  302. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  303. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  304. package/list/harvesterhci.io.host/index.vue +0 -186
  305. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  306. package/list/harvesterhci.io.setting.vue +0 -241
  307. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  308. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  309. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  310. package/list/harvesterhci.io.volume.vue +0 -122
  311. package/list/kubevirt.io.virtualmachine.vue +0 -193
  312. package/mixins/harvester-vm/impl.js +0 -267
  313. package/mixins/harvester-vm/index.js +0 -1357
  314. package/models/harvester/configmap.js +0 -32
  315. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  316. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  317. package/models/harvester/harvesterhci.io.setting.js +0 -127
  318. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  319. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  320. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  321. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  322. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  323. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  324. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  325. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  326. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  327. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  328. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  329. package/models/harvester/management.cattle.io.setting.js +0 -40
  330. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  331. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  332. package/models/harvester/node.js +0 -255
  333. package/models/harvester/persistentvolumeclaim.js +0 -166
  334. package/models/harvester/pod.js +0 -185
  335. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  336. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  337. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  338. package/pages/c/_cluster/harvester/index.vue +0 -24
  339. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  340. package/pages/plugins.vue +0 -387
  341. package/pkg/model-loader.lib.js +0 -3
  342. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  343. package/server/verdaccio-middleware.js +0 -56
  344. package/store/harvester-common.js +0 -126
  345. package/utils/validators/vm-datavolumes.js +0 -38
  346. package/utils/validators/vm-image.js +0 -32
  347. package/utils/validators/vm.js +0 -221
package/plugins/plugin.js CHANGED
@@ -1,10 +1,11 @@
1
- // This plugin loads any extensions at app load time
2
-
3
- import { allHash } from '@shell/utils/promise';
1
+ // This plugin loads any UI Plugins at app load time
2
+ import { allHashSettled } from '@shell/utils/promise';
3
+ import { shouldLoadPlugin, UI_PLUGIN_BASE_URL } from '@shell/config/uiplugins';
4
4
 
5
5
  const META_NAME_PREFIX = 'app-autoload-';
6
6
 
7
7
  export default async(context) => {
8
+ // UI Plugins declared in the HTML head
8
9
  const meta = context.app?.head?.meta || [];
9
10
  const hash = {};
10
11
 
@@ -18,5 +19,56 @@ export default async(context) => {
18
19
  }
19
20
  });
20
21
 
21
- await allHash(hash);
22
+ // Provide a mechanism to load the UI without the plugins loaded - in case there is a problem
23
+ let loadPlugins = true;
24
+
25
+ if (context.route?.path.endsWith('/safeMode')) {
26
+ loadPlugins = false;
27
+ console.warn('Safe Mode - plugins will not be loaded'); // eslint-disable-line no-console
28
+ }
29
+
30
+ if (loadPlugins) {
31
+ const { store, $plugin } = context;
32
+
33
+ // Fetch list of installed plugins from endpoint
34
+ try {
35
+ const res = await store.dispatch('management/request', {
36
+ url: `${ UI_PLUGIN_BASE_URL }/index.json`,
37
+ headers: { accept: 'application/json' }
38
+ });
39
+
40
+ if (res) {
41
+ const entries = res.entries || res.Entries || {};
42
+
43
+ Object.values(entries).forEach((plugin) => {
44
+ if (shouldLoadPlugin(plugin)) {
45
+ let url;
46
+
47
+ if (plugin?.metadata?.['direct'] === 'true') {
48
+ url = plugin.endpoint;
49
+ }
50
+
51
+ hash[plugin.name] = $plugin.loadAsyncByNameAndVersion(plugin.name, plugin.version, url);
52
+ }
53
+ });
54
+ }
55
+ } catch (e) {
56
+ console.error('Could not load UI Plugin list', e); // eslint-disable-line no-console
57
+ }
58
+
59
+ // Load all of the plugins
60
+ const pluginLoads = await allHashSettled(hash);
61
+
62
+ // Some pluigns may have failed to load - store this
63
+ Object.keys(pluginLoads).forEach((name) => {
64
+ const res = pluginLoads[name];
65
+
66
+ if (res?.status === 'rejected') {
67
+ console.error(`Failed to load plugin: ${ name }`); // eslint-disable-line no-console
68
+
69
+ // Record error in the uiplugins store, so that we can show this to the user
70
+ context.store.dispatch('uiplugins/setError', { name, error: true });
71
+ }
72
+ });
73
+ }
22
74
  };
@@ -178,7 +178,7 @@ export default {
178
178
  const res = err.response;
179
179
 
180
180
  // Go to the logout page for 401s, unless redirectUnauthorized specifically disables (for the login page)
181
- if ( opt.redirectUnauthorized !== false && process.client && res.status === 401 ) {
181
+ if ( opt.redirectUnauthorized !== false && res.status === 401 ) {
182
182
  dispatch('auth/logout', opt.logoutOnError, { root: true });
183
183
  }
184
184
 
@@ -10,7 +10,7 @@ import getters, { STEVE_MODEL_TYPES } from './getters';
10
10
  import mutations from './mutations';
11
11
  import actions from './actions';
12
12
 
13
- function SteveFactory(namespace, baseUrl) {
13
+ export function SteveFactory(namespace, baseUrl) {
14
14
  return {
15
15
  ...coreStoreModule,
16
16
 
@@ -50,6 +50,10 @@ function SteveFactory(namespace, baseUrl) {
50
50
  };
51
51
  }
52
52
 
53
+ export const steveStoreInit = (store, ctx) => {
54
+ createWorker(store, ctx);
55
+ };
56
+
53
57
  export default (config) => {
54
58
  config.namespace = config.namespace || '';
55
59
 
@@ -67,8 +71,6 @@ export default (config) => {
67
71
  return coreStore(
68
72
  SteveFactory(config.namespace, config.baseUrl),
69
73
  config,
70
- (store, ctx) => {
71
- createWorker(store, ctx);
72
- }
74
+ steveStoreInit
73
75
  );
74
76
  };
@@ -64,7 +64,7 @@ export default {
64
64
 
65
65
  if (worker) {
66
66
  // Store raw json objects, not the proxies
67
- worker.loadSchema(data);
67
+ worker.postMessage({ loadSchemas: data });
68
68
  }
69
69
  }
70
70
  },
@@ -1,6 +1,7 @@
1
1
  import { addObject, clear, removeObject } from '@shell/utils/array';
2
2
  import { get } from '@shell/utils/object';
3
3
  import { COUNT, SCHEMA } from '@shell/config/types';
4
+ import { getPerformanceSetting } from '@shell/config/settings';
4
5
  import Socket, {
5
6
  EVENT_CONNECTED,
6
7
  EVENT_DISCONNECTED,
@@ -15,8 +16,7 @@ import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
15
16
  import { escapeHtml } from '@shell/utils/string';
16
17
 
17
18
  // eslint-disable-next-line
18
- import Worker from './web-worker.steve-sub-worker.js'
19
- import * as Comlink from 'comlink';
19
+ import webworker from './web-worker.steve-sub-worker.js';
20
20
 
21
21
  export const NO_WATCH = 'NO_WATCH';
22
22
  export const NO_SCHEMA = 'NO_SCHEMA';
@@ -24,9 +24,6 @@ export const NO_SCHEMA = 'NO_SCHEMA';
24
24
  // minimum length of time a disconnect notification is shown
25
25
  const MINIMUM_TIME_NOTIFIED = 3000;
26
26
 
27
- // minimum time a socket must be disconnected for before sending a growl
28
- const MINIMUM_TIME_DISCONNECTED = 10000;
29
-
30
27
  // We only create a worker for the cluster store
31
28
  export function createWorker(store, ctx) {
32
29
  const { getters } = ctx;
@@ -38,16 +35,33 @@ export function createWorker(store, ctx) {
38
35
  return;
39
36
  }
40
37
 
41
- function callback(resource) {
42
- queueChange(ctx, resource, true, 'Change');
43
- }
38
+ const workerActions = {
39
+ load: (resource) => {
40
+ queueChange(ctx, resource, true, 'Change');
41
+ },
42
+ destroyWorker: () => {
43
+ if (store.$workers) {
44
+ delete store.$workers[storeName];
45
+ }
46
+ }
47
+ };
44
48
 
45
49
  if (!store.$workers[storeName]) {
46
- const worker = Comlink.wrap(new Worker());
50
+ const worker = new webworker();
47
51
 
48
52
  store.$workers[storeName] = worker;
49
53
 
50
- worker.initWorker(storeName, Comlink.proxy(callback));
54
+ worker.postMessage({ initWorker: { storeName } });
55
+
56
+ store.$workers[storeName].onmessage = (e) => {
57
+ /* on the off chance there's more than key in the message, we handle them in the order that they "keys" method provides which is
58
+ // good enough for now considering that we never send more than one message action at a time right now */
59
+ const messageActions = Object.keys(e?.data);
60
+
61
+ messageActions.forEach((action) => {
62
+ workerActions[action](e?.data[action]);
63
+ });
64
+ };
51
65
  }
52
66
  }
53
67
 
@@ -118,6 +132,10 @@ function queueChange({ getters, state }, { data, revision }, load, label) {
118
132
  }
119
133
  }
120
134
 
135
+ function growlsDisabled(rootGetters) {
136
+ return getPerformanceSetting(rootGetters)?.disableWebsocketNotification;
137
+ }
138
+
121
139
  export const actions = {
122
140
  subscribe(ctx, opt) {
123
141
  const {
@@ -144,7 +162,9 @@ export const actions = {
144
162
  socket.setAutoReconnect(true);
145
163
  socket.setUrl(url);
146
164
  } else {
147
- socket = new Socket(`${ state.config.baseUrl }/subscribe`);
165
+ const maxTries = growlsDisabled(rootGetters) ? null : 3;
166
+
167
+ socket = new Socket(`${ state.config.baseUrl }/subscribe`, true, null, null, maxTries);
148
168
 
149
169
  commit('setSocket', socket);
150
170
  socket.addEventListener(EVENT_CONNECTED, (e) => {
@@ -176,24 +196,17 @@ export const actions = {
176
196
  });
177
197
  }
178
198
 
179
- socket.connect(get(opt, 'metadata'));
199
+ socket.connect(get(opt, 'metadata') );
180
200
  },
181
201
 
182
- unsubscribe({ state, commit, getters }) {
202
+ unsubscribe({ commit, getters, state }) {
183
203
  const socket = state.socket;
184
204
  const worker = (this.$workers || {})[getters.storeName];
185
205
 
186
206
  commit('setWantSocket', false);
187
207
 
188
208
  if (worker) {
189
- try {
190
- worker.destroyWorker();
191
- worker[Comlink.releaseProxy]();
192
- } catch (e) {
193
- console.error(e); // eslint-disable-line no-console
194
- }
195
-
196
- delete this.$workers[getters.storeName];
209
+ worker.postMessage({ destroyWorker: true }); // we're only passing the boolean here because the key needs to be something truthy to ensure it's passed on the object.
197
210
  }
198
211
 
199
212
  if ( socket ) {
@@ -395,8 +408,10 @@ export const actions = {
395
408
  commit, dispatch, state, getters, rootGetters
396
409
  }, event) {
397
410
  state.debugSocket && console.info(`WebSocket Opened [${ getters.storeName }]`); // eslint-disable-line no-console
398
-
399
411
  const socket = event.currentTarget;
412
+ const tries = event?.detail?.tries; // have to pull it off of the event because the socket's tries is already reset to 0
413
+ const t = rootGetters['i18n/t'];
414
+ const disableGrowl = growlsDisabled(rootGetters);
400
415
 
401
416
  this.$socket = socket;
402
417
 
@@ -419,19 +434,16 @@ export const actions = {
419
434
  if ( socket.hasReconnected ) {
420
435
  await dispatch('reconnectWatches');
421
436
  // Check for disconnect notifications and clear them
422
- const growlErr = rootGetters['growl/find']({ key: 'url', val: this.$socket.url });
437
+ const growlErr = rootGetters['growl/find']({ key: 'url', val: socket.url });
423
438
 
424
439
  if (growlErr) {
425
- const now = Date.now();
426
-
427
- // even if the socket reconnected, keep the error growl for at least a few seconds to ensure its readable
428
- if (now >= growlErr.earliestClose) {
429
- dispatch('growl/remove', growlErr.id, { root: true });
430
- } else {
431
- setTimeout(() => {
432
- dispatch('growl/remove', growlErr.id, { root: true });
433
- }, growlErr.earliestClose - now);
434
- }
440
+ dispatch('growl/remove', growlErr.id, { root: true });
441
+ }
442
+ if (tries > 1 && !disableGrowl) {
443
+ dispatch('growl/success', {
444
+ title: t('growl.reconnected.title'),
445
+ message: t('growl.reconnected.message', { url: this.$socket.url, tries }),
446
+ }, { root: true });
435
447
  }
436
448
  }
437
449
 
@@ -455,32 +467,53 @@ export const actions = {
455
467
  }, e) {
456
468
  clearTimeout(state.queueTimer);
457
469
  state.queueTimer = null;
458
- if (e.type === EVENT_DISCONNECT_ERROR) {
459
- // do not send a growl notification unless the socket stays disconnected for more than MINIMUM_TIME_DISCONNECTED
460
- setTimeout(() => {
461
- if (state.socket.isConnected()) {
462
- return;
463
- }
464
- const dateFormat = escapeHtml( rootGetters['prefs/get'](DATE_FORMAT));
465
- const timeFormat = escapeHtml( rootGetters['prefs/get'](TIME_FORMAT));
466
- const time = e?.srcElement?.disconnectedAt || Date.now();
467
470
 
468
- const timeFormatted = `${ day(time).format(`${ dateFormat } ${ timeFormat }`) }`;
469
- const url = e?.srcElement?.url;
471
+ // determine if websocket notifications are disabled
472
+ const disableGrowl = growlsDisabled(rootGetters);
473
+
474
+ if (!disableGrowl) {
475
+ const dateFormat = escapeHtml( rootGetters['prefs/get'](DATE_FORMAT));
476
+ const timeFormat = escapeHtml( rootGetters['prefs/get'](TIME_FORMAT));
477
+ const time = e?.srcElement?.disconnectedAt || Date.now();
478
+
479
+ const timeFormatted = `${ day(time).format(`${ dateFormat } ${ timeFormat }`) }`;
480
+ const url = e?.srcElement?.url;
481
+ const tries = state?.socket?.tries;
470
482
 
471
- const t = rootGetters['i18n/t'];
483
+ const t = rootGetters['i18n/t'];
472
484
 
485
+ const growlErr = rootGetters['growl/find']({ key: 'url', val: url });
486
+
487
+ if (e.type === EVENT_CONNECT_ERROR) { // if this occurs, then we're at least retrying to connect
488
+ if (growlErr) {
489
+ dispatch('growl/remove', growlErr.id, { root: true });
490
+ }
473
491
  dispatch('growl/error', {
474
- title: t('growl.disconnected.title'),
475
- message: t('growl.disconnected.message', { url, time: timeFormatted }, { raw: true }),
492
+ title: t('growl.connectError.title'),
493
+ message: t('growl.connectError.message', {
494
+ url, time: timeFormatted, tries
495
+ }, { raw: true }),
476
496
  icon: 'error',
477
- earliestClose: time + MINIMUM_TIME_NOTIFIED + MINIMUM_TIME_DISCONNECTED,
497
+ earliestClose: time + MINIMUM_TIME_NOTIFIED,
478
498
  url
479
499
  }, { root: true });
480
- }, MINIMUM_TIME_DISCONNECTED);
481
- } else {
482
- // if the error is not a disconnect error, the socket never worked: log whether the current browser is safari
483
- console.error(`WebSocket Connection Error [${ getters.storeName }]`, e.detail); // eslint-disable-line no-console
500
+ } else if (e.type === EVENT_DISCONNECT_ERROR) { // if this occurs, we've given up on trying to reconnect
501
+ if (growlErr) {
502
+ dispatch('growl/remove', growlErr.id, { root: true });
503
+ }
504
+ dispatch('growl/error', {
505
+ title: t('growl.disconnectError.title'),
506
+ message: t('growl.disconnectError.message', {
507
+ url, time: timeFormatted, tries
508
+ }, { raw: true }),
509
+ icon: 'error',
510
+ earliestClose: time + MINIMUM_TIME_NOTIFIED,
511
+ url
512
+ }, { root: true });
513
+ } else {
514
+ // if the error is not a connect error or disconnect error, the socket never worked: log whether the current browser is safari
515
+ console.error(`WebSocket Connection Error [${ getters.storeName }]`, e.detail); // eslint-disable-line no-console
516
+ }
484
517
  }
485
518
  },
486
519
 
@@ -572,7 +605,7 @@ export const actions = {
572
605
  const worker = (this.$workers || {})[ctx.getters.storeName];
573
606
 
574
607
  if (worker) {
575
- worker.countsUpdate(msg);
608
+ worker.postMessage({ countsUpdate: msg });
576
609
 
577
610
  // No further processing - let the web worker debounce the counts
578
611
  return;
@@ -585,7 +618,7 @@ export const actions = {
585
618
  const worker = (this.$workers || {})[ctx.getters.storeName];
586
619
 
587
620
  if (worker) {
588
- worker.updateSchema(data);
621
+ worker.postMessage({ updateSchema: data });
589
622
 
590
623
  // No further processing - let the web worker check the schema updates
591
624
  return;
@@ -620,7 +653,7 @@ export const actions = {
620
653
  const worker = (this.$workers || {})[ctx.getters.storeName];
621
654
 
622
655
  if (worker) {
623
- worker.removeSchema(data.id);
656
+ worker.postMessage({ removeSchema: data.id });
624
657
  }
625
658
  }
626
659
 
@@ -701,7 +734,7 @@ export const mutations = {
701
734
  clear(state.started);
702
735
  clear(state.pendingFrames);
703
736
  clear(state.queue);
704
- clearInterval(state.queueTimer);
737
+ clearTimeout(state.queueTimer);
705
738
  state.deferredRequests = {};
706
739
  state.queueTimer = null;
707
740
  }
@@ -1,4 +1,3 @@
1
- import * as Comlink from 'comlink';
2
1
  import { SCHEMA } from '@shell/config/types';
3
2
 
4
3
  const COUNTS_FLUSH_TIMEOUT = 5000;
@@ -6,7 +5,6 @@ const SCHEMA_FLUSH_TIMEOUT = 2500;
6
5
 
7
6
  const state = {
8
7
  store: '', // Store name
9
- load: undefined, // Load callback to load a resource into the store
10
8
  counts: [], // Buffer of count resources recieved in a given window
11
9
  countTimer: undefined, // Tiemr to flush the count buffer
12
10
  flushTimer: undefined, // Timer to flush the schema chaneg queue
@@ -61,22 +59,33 @@ state.flushTimer = setTimeout(flush, SCHEMA_FLUSH_TIMEOUT);
61
59
 
62
60
  // Callback to the store's load function (in the main thread) to process a load
63
61
  function load(data) {
64
- if (state.load) {
65
- state.load(data);
66
- }
62
+ self.postMessage({ load: data });
67
63
  }
68
64
 
69
- // Web Worker API
70
- const fns = {
71
- initWorker(storeName, loadFn) {
65
+ const workerActions = {
66
+ onmessage: (e) => {
67
+ /* on the off chance there's more than key in the message, we handle them in the order that they "keys" method provides which is
68
+ // good enough for now considering that we never send more than one message action at a time right now */
69
+ const messageActions = Object.keys(e?.data);
70
+
71
+ messageActions.forEach((action) => {
72
+ if (workerActions[action]) {
73
+ workerActions[action](e?.data[action]);
74
+ } else {
75
+ console.warn('no associated action for:', action); // eslint-disable-line no-console
76
+ }
77
+ });
78
+ },
79
+ initWorker: ({ storeName }) => {
72
80
  state.store = storeName;
73
- state.load = loadFn;
74
81
  },
75
82
 
76
- destroyWorker() {
83
+ destroyWorker: () => {
77
84
  clearTimeout(state.countTimer);
78
85
  clearTimeout(state.flushTimer);
79
86
 
87
+ self.postMessage({ destroyWorker: true }); // we're only passing the boolean here because the key needs to be something truthy to ensure it's passed on the object.
88
+
80
89
  // Web worker global function to terminate the web worker
81
90
  close();
82
91
  },
@@ -98,7 +107,7 @@ const fns = {
98
107
  },
99
108
 
100
109
  // Called to load schema
101
- loadSchema(schemas) {
110
+ loadSchemas: (schemas) => {
102
111
  schemas.forEach((schema) => {
103
112
  // These properties are added to the object, but aren't on the raw object, so remove them
104
113
  // otherwise our comparison will show changes when there aren't any
@@ -107,16 +116,17 @@ const fns = {
107
116
 
108
117
  state.schemas[schema.id] = hashObj(schema);
109
118
  });
119
+ // console.log(JSON.parse(JSON.stringify(state.resources.schemas)));
110
120
  },
111
121
 
112
122
  // Called when schema is updated
113
- updateSchema(schema) {
123
+ updateSchema: (schema) => {
114
124
  // Add the schema to the queue to be checked to see if the schema really changed
115
125
  state.queue.push(schema);
116
126
  },
117
127
 
118
128
  // Remove the cached schema
119
- removeSchema(id) {
129
+ removeSchema: (id) => {
120
130
  // Remove anything in the queue related to the schema - we don't want to send any pending updates later for a schema that has been removed
121
131
  state.queue = state.queue.filter(schema => schema.id !== id);
122
132
 
@@ -125,5 +135,4 @@ const fns = {
125
135
  }
126
136
  };
127
137
 
128
- // Expose the Web Worker API - see: https://github.com/GoogleChromeLabs/comlink
129
- Comlink.expose(fns);
138
+ onmessage = workerActions.onmessage; // bind everything to the worker's onmessage handler via the workerAction
@@ -0,0 +1,47 @@
1
+ <script>
2
+ import RoleDeletionCheck from '@shell/promptRemove/mixin/roleDeletionCheck';
3
+ export default {
4
+ name: 'GlobalRolePromptRemove',
5
+ mixins: [RoleDeletionCheck],
6
+ props: {
7
+ value: {
8
+ type: Array,
9
+ default: () => {
10
+ return [];
11
+ }
12
+ },
13
+
14
+ type: {
15
+ type: String,
16
+ required: true
17
+ }
18
+ },
19
+ };
20
+ </script>
21
+
22
+ <template>
23
+ <div>
24
+ <template>
25
+ {{ t('promptRemove.attemptingToRemove', { type }) }} <span
26
+ v-html="resourceNames(names, plusMore, t)"
27
+ ></span>
28
+ </template>
29
+ <div v-if="info" class="text info mb-10 mt-20">
30
+ <span v-html="info" />
31
+ </div>
32
+ <div v-if="warning" class="text-warning mb-10 mt-20">
33
+ {{ warning }}
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <style lang="scss" scoped>
39
+ .text.info {
40
+ display: flex;
41
+ align-items: center;
42
+
43
+ > span {
44
+ margin-right: 5px;
45
+ }
46
+ }
47
+ </style>
@@ -0,0 +1,47 @@
1
+ <script>
2
+ import RoleDeletionCheck from '@shell/promptRemove/mixin/roleDeletionCheck';
3
+ export default {
4
+ name: 'RoleTemplatePromptRemove',
5
+ mixins: [RoleDeletionCheck],
6
+ props: {
7
+ value: {
8
+ type: Array,
9
+ default: () => {
10
+ return [];
11
+ }
12
+ },
13
+
14
+ type: {
15
+ type: String,
16
+ required: true
17
+ }
18
+ },
19
+ };
20
+ </script>
21
+
22
+ <template>
23
+ <div>
24
+ <template>
25
+ {{ t('promptRemove.attemptingToRemove', { type }) }} <span
26
+ v-html="resourceNames(names, plusMore, t)"
27
+ ></span>
28
+ </template>
29
+ <div v-if="info" class="text info mb-10 mt-20">
30
+ <span v-html="info" />
31
+ </div>
32
+ <div v-if="warning" class="text-warning mb-10 mt-20">
33
+ {{ warning }}
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <style lang="scss" scoped>
39
+ .text.info {
40
+ display: flex;
41
+ align-items: center;
42
+
43
+ > span {
44
+ margin-right: 5px;
45
+ }
46
+ }
47
+ </style>
@@ -0,0 +1,97 @@
1
+ import { mapState, mapGetters } from 'vuex';
2
+ import { resourceNames } from '@shell/utils/string';
3
+ import { MANAGEMENT } from '@shell/config/types';
4
+ import { SUBTYPE_MAPPING } from '@shell/models/management.cattle.io.roletemplate';
5
+ const CLUSTER = SUBTYPE_MAPPING.CLUSTER.key;
6
+
7
+ export default {
8
+ data() {
9
+ return {
10
+ warning: '',
11
+ info: '',
12
+ };
13
+ },
14
+
15
+ computed: {
16
+ ...mapState('action-menu', ['toRemove']),
17
+ ...mapGetters({ t: 'i18n/t' }),
18
+
19
+ names() {
20
+ return this.toRemove.map(obj => obj.nameDisplay).slice(0, 5);
21
+ },
22
+
23
+ plusMore() {
24
+ const remaining = this.toRemove.length - this.names.length;
25
+
26
+ return this.t('promptRemove.andOthers', { count: remaining });
27
+ },
28
+ },
29
+ watch: {
30
+ value: {
31
+ handler(neu) {
32
+ this.handleRoleDeletionCheck(neu, neu[0].type, this.$route.hash);
33
+ },
34
+ immediate: true
35
+ }
36
+ },
37
+ methods: {
38
+ resourceNames,
39
+ async handleRoleDeletionCheck(rolesToRemove, resourceType, queryHash) {
40
+ this.warning = '';
41
+ let resourceToCheck;
42
+ let propToMatch;
43
+ let numberOfRolesWithBinds = 0;
44
+ const uniqueUsersWithBinds = new Set();
45
+
46
+ this.info = this.t('rbac.globalRoles.waiting', { count: rolesToRemove.length });
47
+
48
+ switch (resourceType) {
49
+ case MANAGEMENT.GLOBAL_ROLE:
50
+ resourceToCheck = MANAGEMENT.GLOBAL_ROLE_BINDING;
51
+ propToMatch = 'globalRoleName';
52
+ break;
53
+ default:
54
+ if (queryHash.includes(CLUSTER)) {
55
+ resourceToCheck = MANAGEMENT.CLUSTER_ROLE_TEMPLATE_BINDING;
56
+ } else {
57
+ resourceToCheck = MANAGEMENT.PROJECT_ROLE_TEMPLATE_BINDING;
58
+ }
59
+ propToMatch = 'roleTemplateName';
60
+ break;
61
+ }
62
+
63
+ try {
64
+ const request = await this.$store.dispatch('management/request', {
65
+ url: `/v1/${ resourceToCheck }`,
66
+ method: 'get',
67
+ }, { root: true });
68
+
69
+ if (request.data && request.data.length) {
70
+ rolesToRemove.forEach((toRemove) => {
71
+ const usedRoles = request.data.filter(item => item[propToMatch] === toRemove.id);
72
+
73
+ if (usedRoles.length) {
74
+ const uniqueUsers = [...new Set(usedRoles.map(item => item.userName))];
75
+
76
+ if (uniqueUsers.length) {
77
+ numberOfRolesWithBinds++;
78
+ uniqueUsers.forEach(user => uniqueUsersWithBinds.add(user));
79
+ }
80
+ }
81
+ });
82
+
83
+ if (numberOfRolesWithBinds && uniqueUsersWithBinds.size) {
84
+ this.info = '';
85
+ this.warning = this.t('rbac.globalRoles.usersBound', { count: uniqueUsersWithBinds.size });
86
+ } else {
87
+ this.info = this.t('rbac.globalRoles.notBound', null, true);
88
+ }
89
+ } else {
90
+ this.info = this.t('rbac.globalRoles.notBound', null, true);
91
+ }
92
+ } catch (e) {
93
+ this.info = this.t('rbac.globalRoles.unableToCheck');
94
+ }
95
+ },
96
+ },
97
+ };