@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
@@ -16,6 +16,7 @@ type RouteInstallHistory = {
16
16
 
17
17
  export class PluginRoutes {
18
18
  router: Router;
19
+ pluginRoutes: RouteConfig[] = [];
19
20
 
20
21
  replacedRoutes: RouteInstallHistory = {};
21
22
 
@@ -53,7 +54,7 @@ export class PluginRoutes {
53
54
 
54
55
  break;
55
56
  } else {
56
- // Need to updare the previous item so that when it is removed, it restores the correct route
57
+ // Need to update the previous item so that when it is removed, it restores the correct route
57
58
  const previous = info[index - 1];
58
59
 
59
60
  previous.route = savedRoute.route;
@@ -65,14 +66,24 @@ export class PluginRoutes {
65
66
  }
66
67
  });
67
68
 
69
+ // Remove routes from pluginRoutes, update matcher (to avoid dupes when re-adding plugin routes)
70
+ this.pluginRoutes = this.pluginRoutes.filter(pR => !plugin.routes.find((r: any) => pR === r.route));
71
+ this.updateMatcher([], [
72
+ ...this.pluginRoutes,
73
+ ...(this.router.options.routes || [])
74
+ ]);
75
+
76
+ // Restore appropriate routes
68
77
  if (restore.length > 0) {
69
78
  this.addRoutes(null, restore);
70
79
  }
71
80
  }
72
81
 
73
82
  public addRoutes(plugin: any, routes: RouteInfo[]) {
74
- const appRoutes = this.router.options.routes || [];
75
- let replaced = 0;
83
+ const allRoutes = [
84
+ ...this.pluginRoutes,
85
+ ...(this.router.options.routes || [])
86
+ ];
76
87
 
77
88
  // Need to take into account if routes are being replaced
78
89
  // Despite what the docs say, routes are not replaced, so we use a workaround
@@ -82,18 +93,18 @@ export class PluginRoutes {
82
93
  let existing: any;
83
94
 
84
95
  if (r.parent) {
85
- const pExisting = appRoutes.findIndex((route: any) => route.name === r.parent) as any;
96
+ const pExisting = allRoutes.findIndex((route: any) => route.name === r.parent) as any;
86
97
  const path = `${ pExisting.path }${ r.route.path }`;
87
98
 
88
99
  // TODO: Validate
89
- existing = appRoutes.findIndex((route: any) => route.path === path);
100
+ existing = allRoutes.findIndex((route: any) => route.path === path);
90
101
  } else {
91
102
  // no parent route
92
- existing = appRoutes.findIndex((route: any) => route.name === r.route.name);
103
+ existing = allRoutes.findIndex((route: any) => route.name === r.route.name);
93
104
  }
94
105
 
95
106
  if (existing >= 0) {
96
- const existingRoute = appRoutes[existing];
107
+ const existingRoute = allRoutes[existing];
97
108
 
98
109
  // Store the route so we can restore it on uninstall
99
110
  if (plugin && existingRoute?.name) {
@@ -107,32 +118,33 @@ export class PluginRoutes {
107
118
  });
108
119
  }
109
120
 
110
- appRoutes.splice(existing, 1);
111
- replaced++;
121
+ allRoutes.splice(existing, 1);
112
122
  }
113
123
  });
114
124
 
115
- const newRouter: Router = replaced > 0 ? new Router({
125
+ this.updateMatcher(routes, allRoutes);
126
+ }
127
+
128
+ private updateMatcher(newRoutes: RouteInfo[], allRoutes: RouteConfig[]) {
129
+ // Note - Always use a new router and replace the existing router's matching
130
+ // Using the existing router and adding routes to it will force nuxt middleware (specifically authenticated on default layout) to
131
+ // execute many times (nuxt middleware boils down to router.beforeEach). This issue was seen refreshing in a harvester cluster with a
132
+ // dynamically loaded cluster
133
+ const newRouter: Router = new Router({
116
134
  mode: 'history',
117
- routes: appRoutes
118
- }) : this.router;
135
+ routes: allRoutes
136
+ });
119
137
 
120
- routes.forEach((r: any) => {
138
+ newRoutes.forEach((r: any) => {
121
139
  if (r.parent) {
122
140
  newRouter.addRoute(r.parent, r.route);
123
141
  } else {
124
142
  newRouter.addRoute(r.route);
125
143
  }
144
+ this.pluginRoutes.push(r.route);
126
145
  });
127
146
 
128
- if (replaced > 0) {
129
- // Typing is incorrect
130
- (this.router as any).matcher = (newRouter as any).matcher;
131
- }
132
-
133
- // If we replaced any routes, then we should reload on uninstall
134
- if (plugin) {
135
- plugin.reloadOnUninstall = replaced > 0;
136
- }
147
+ // Typing is incorrect
148
+ (this.router as any).matcher = (newRouter as any).matcher;
137
149
  }
138
150
  }
package/core/plugin.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { RouteConfig } from 'vue-router';
2
2
  import { DSL as STORE_DSL } from '@shell/store/type-map';
3
- import { IPlugin } from './types';
3
+ import { CoreStoreInit, IPlugin } from './types';
4
4
  import coreStore, { coreStoreModule, coreStoreState } from '@shell/plugins/dashboard-store';
5
5
  import {
6
6
  PluginRouteConfig, RegisterStore, UnregisterStore, CoreStoreSpecifics, CoreStoreConfig, OnNavToPackage, OnNavAwayFromPackage, OnLogOut
@@ -23,6 +23,8 @@ export class Plugin implements IPlugin {
23
23
  // Plugin metadata (plugin package.json)
24
24
  public _metadata: any = {};
25
25
 
26
+ public _validators: {[key:string]: Function } = {}
27
+
26
28
  // Is this a built-in plugin (bundled with the application)
27
29
  public builtin = false;
28
30
 
@@ -43,6 +45,14 @@ export class Plugin implements IPlugin {
43
45
  this.name = this._metadata.name || this.id;
44
46
  }
45
47
 
48
+ get validators() {
49
+ return this._validators;
50
+ }
51
+
52
+ set validators(vals: {[key:string]: Function }) {
53
+ this._validators = vals;
54
+ }
55
+
46
56
  // Track which products the plugin creates
47
57
  DSL(store: any, productName: string) {
48
58
  const storeDSL = STORE_DSL(store, productName);
@@ -104,13 +114,14 @@ export class Plugin implements IPlugin {
104
114
  });
105
115
  }
106
116
 
107
- addDashboardStore(storeName: string, storeSpecifics: CoreStoreSpecifics, config: CoreStoreConfig) {
117
+ addDashboardStore(storeName: string, storeSpecifics: CoreStoreSpecifics, config: CoreStoreConfig, init?: CoreStoreInit) {
108
118
  this.stores.push({
109
119
  storeName,
110
120
  register: () => {
111
121
  return coreStore(
112
122
  this.storeFactory(storeSpecifics, config),
113
123
  config,
124
+ init,
114
125
  );
115
126
  },
116
127
  unregister: (store: any) => {
@@ -167,7 +178,8 @@ export class Plugin implements IPlugin {
167
178
  const nparts = name.split('/');
168
179
 
169
180
  // Support components in a sub-folder - component_name/index.vue (and ignore other componnets in that folder)
170
- if (nparts.length === 2) {
181
+ // Allow store-scoped models via sub-folder - pkgname/models/storename/type will be registered as storename/type to avoid overwriting shell/models/type
182
+ if (nparts.length === 2 && type !== 'models') {
171
183
  if (nparts[1] !== 'index') {
172
184
  return;
173
185
  }
@@ -1,4 +1,5 @@
1
1
  import Vue from 'vue';
2
+ import $ from 'jquery';
2
3
  import JSZip from 'jszip';
3
4
  import jsyaml from 'js-yaml';
4
5
 
@@ -25,6 +26,7 @@ export default function({
25
26
  window.Vue = Vue;
26
27
 
27
28
  // Global libraries - allows us to externalise these to reduce package bundle size
29
+ window.$ = $;
28
30
  window.__jszip = JSZip;
29
31
  window.__jsyaml = jsyaml;
30
32
  }
package/core/plugins.js CHANGED
@@ -12,10 +12,12 @@ export default function({
12
12
  redirect
13
13
  }, inject) {
14
14
  const dynamic = {};
15
+ const validators = {};
15
16
  let _lastLoaded = 0;
16
17
 
17
18
  // Track which plugin loaded what, so we can unload stuff
18
19
  const plugins = {};
20
+
19
21
  const pluginRoutes = new PluginRoutes(app.router);
20
22
 
21
23
  inject('plugin', {
@@ -43,44 +45,69 @@ export default function({
43
45
  element.type = 'text/javascript';
44
46
  element.async = true;
45
47
 
46
- element.onload = () => {
47
- element.parentElement.removeChild(element);
48
+ // id is `<product>-<version>`.
49
+ const oldPlugin = Object.values(plugins).find(p => id.startsWith(p.name));
48
50
 
49
- if (!window[id]) {
50
- return reject(new Error('Could not load plugin code'));
51
- }
51
+ let removed = Promise.resolve();
52
+
53
+ if (oldPlugin) {
54
+ // Uninstall existing plugin if there is one. This ensures that last loaded plugin is not always used
55
+ // (nav harv1-->harv2-->harv1 and harv2 would be shown)
56
+ removed = this.removePlugin(oldPlugin.name).then(() => {
57
+ delete window[oldPlugin.id];
58
+
59
+ delete plugins[oldPlugin.id];
60
+ });
61
+ }
62
+
63
+ removed.then(() => {
64
+ element.onload = () => {
65
+ element.parentElement.removeChild(element);
66
+
67
+ if (!window[id]) {
68
+ return reject(new Error('Could not load plugin code'));
69
+ }
70
+
71
+ // Update the timestamp that new plugins were loaded - may be needed
72
+ // to update caches when new plugins are loaded
73
+ _lastLoaded = new Date().getTime();
74
+
75
+ // name is the name of the plugin, including the version number
76
+ const plugin = new Plugin(id);
52
77
 
53
- // Update the timestamp that new plugins were loaded - may be needed
54
- // to update caches when new plugins are loaded
55
- _lastLoaded = new Date().getTime();
78
+ plugins[id] = plugin;
56
79
 
57
- // TODO: Error if we are loading a plugin already loaded?
58
- // name is the name of the plugin, including the version number
59
- const plugin = new Plugin(id);
80
+ // Initialize the plugin
81
+ window[id].default(plugin, this.internal());
60
82
 
61
- plugins[id] = plugin;
83
+ // Uninstall existing plugin if there is one
84
+ this.removePlugin(plugin.name); // Removing this causes the plugin to not load on refresh
62
85
 
63
- // Initialize the plugin
64
- window[id].default(plugin, this.internal());
86
+ // Load all of the types etc from the plugin
87
+ this.applyPlugin(plugin);
65
88
 
66
- // Uninstall existing plugin if there is one
67
- this.removePlugin(plugin.name);
89
+ // Add the plugin to the store
90
+ store.dispatch('uiplugins/addPlugin', plugin);
68
91
 
69
- // Load all of the types etc from the plugin
70
- this.applyPlugin(plugin);
92
+ resolve();
93
+ };
71
94
 
72
- // Add the plugin to the store
73
- store.dispatch('uiplugins/addPlugin', plugin);
95
+ element.onerror = (e) => {
96
+ element.parentElement.removeChild(element);
97
+ // Massage the error into something useful
98
+ const errorMessage = `Failed to load script from '${ e.target.src }'`;
74
99
 
75
- resolve();
76
- };
100
+ console.error(errorMessage, e); // eslint-disable-line no-console
101
+ reject(new Error(errorMessage)); // This is more useful where it's used
102
+ };
77
103
 
78
- element.onerror = (e) => {
79
- element.parentElement.removeChild(element);
80
- reject(e);
81
- };
104
+ document.head.appendChild(element);
105
+ }).catch((e) => {
106
+ const errorMessage = `Failed to unload old plugin${ oldPlugin?.id }`;
82
107
 
83
- document.head.appendChild(element);
108
+ console.error(errorMessage, e); // eslint-disable-line no-console
109
+ reject(new Error(errorMessage)); // This is more useful where it's used
110
+ });
84
111
  });
85
112
  },
86
113
 
@@ -114,15 +141,17 @@ export default function({
114
141
  },
115
142
 
116
143
  // Remove the plugin
117
- removePlugin(name) {
144
+ async removePlugin(name) {
118
145
  const plugin = Object.values(plugins).find(p => p.name === name);
119
146
 
120
147
  if (!plugin) {
121
148
  return;
122
149
  }
123
150
 
151
+ const promises = [];
152
+
124
153
  plugin.productNames.forEach((product) => {
125
- store.dispatch('type-map/removeProduct', { product, plugin });
154
+ promises.push(store.dispatch('type-map/removeProduct', { product, plugin }));
126
155
  });
127
156
 
128
157
  // Remove all of the types
@@ -138,13 +167,13 @@ export default function({
138
167
 
139
168
  // Remove locales
140
169
  plugin.locales.forEach((localeObj) => {
141
- store.dispatch('i18n/removeLocale', localeObj);
170
+ promises.push(store.dispatch('i18n/removeLocale', localeObj));
142
171
  });
143
172
 
144
173
  if (plugin.types.models) {
145
174
  // Ask the Steve stores to forget any data it has for models that we are removing
146
- this.removeTypeFromStore(store, 'rancher', Object.keys(plugin.types.models));
147
- this.removeTypeFromStore(store, 'management', Object.keys(plugin.types.models));
175
+ promises.push(...this.removeTypeFromStore(store, 'rancher', Object.keys(plugin.types.models)));
176
+ promises.push(...this.removeTypeFromStore(store, 'management', Object.keys(plugin.types.models)));
148
177
  }
149
178
 
150
179
  // Uninstall routes
@@ -154,19 +183,24 @@ export default function({
154
183
  plugin.uninstallHooks.forEach(fn => fn(plugin, this.internal()));
155
184
 
156
185
  // Remove the plugin itself
157
- store.dispatch('uiplugins/removePlugin', name);
186
+ promises.push( store.dispatch('uiplugins/removePlugin', name));
158
187
 
159
188
  // Unregister vuex stores
160
189
  plugin.stores.forEach(pStore => pStore.unregister(store));
161
190
 
191
+ // Remove validators
192
+ Object.keys(plugin.validators).forEach((key) => {
193
+ delete validators[key];
194
+ });
195
+
196
+ await Promise.all(promises);
197
+
162
198
  // Update last load since we removed a plugin
163
199
  _lastLoaded = new Date().getTime();
164
200
  },
165
201
 
166
202
  removeTypeFromStore(store, storeName, types) {
167
- (types || []).forEach((type) => {
168
- store.commit(`${ storeName }/forgetType`, type);
169
- });
203
+ return (types || []).map(type => store.commit(`${ storeName }/forgetType`, type));
170
204
  },
171
205
 
172
206
  // Apply the plugin based on its metadata
@@ -200,6 +234,11 @@ export default function({
200
234
 
201
235
  // Routes
202
236
  pluginRoutes.addRoutes(plugin, plugin.routes);
237
+
238
+ // Validators
239
+ Object.keys(plugin.validators).forEach((key) => {
240
+ validators[key] = plugin.validators[key];
241
+ });
203
242
  },
204
243
 
205
244
  /**
@@ -252,6 +291,10 @@ export default function({
252
291
  return dynamic[typeName]?.[name];
253
292
  },
254
293
 
294
+ getValidator(name) {
295
+ return validators[name];
296
+ },
297
+
255
298
  // Timestamp that a UI package was last loaded
256
299
  // Typically used to invalidate caches (e.g. i18n) when new plugins are loaded
257
300
  get lastLoad() {
package/core/types.ts CHANGED
@@ -18,6 +18,7 @@ export interface PackageMetadata {
18
18
  export type VuexStoreObject = { [key: string]: any }
19
19
  export type CoreStoreSpecifics = { state: () => VuexStoreObject, getters: VuexStoreObject, mutations: VuexStoreObject, actions: VuexStoreObject }
20
20
  export type CoreStoreConfig = { namespace: string, baseUrl?: string, modelBaseClass?: string, supportsStream?: boolean, isClusterStore?: boolean }
21
+ export type CoreStoreInit = (store: any, ctx: any) => void;
21
22
  export type RegisterStore = () => (store: any) => void
22
23
  export type UnregisterStore = (store: any) => void
23
24
 
@@ -56,6 +57,11 @@ export interface IPlugin {
56
57
  */
57
58
  metadata: PackageMetadata;
58
59
 
60
+ /**
61
+ * Validators used in the same manner as shell/utils/custom-validators
62
+ */
63
+ validators: {[key: string]: Function};
64
+
59
65
  /**
60
66
  * Add a module contains localisations for a specific locale
61
67
  */
@@ -91,7 +97,7 @@ export interface IPlugin {
91
97
  * actions, will eventually call a `request` action which will make the raw http request. This is a pkg specific feature so needs the
92
98
  * `request` action needs to be supplied in the `storeSpecifics`
93
99
  */
94
- addDashboardStore(storeName: string, storeSpecifics: CoreStoreSpecifics, config: CoreStoreConfig): void;
100
+ addDashboardStore(storeName: string, storeSpecifics: CoreStoreSpecifics, config: CoreStoreConfig, init?: CoreStoreInit): void;
95
101
 
96
102
  /**
97
103
  * Add hooks that will execute when a user navigates
@@ -25,10 +25,15 @@
25
25
  "./node_modules/@rancher/shell/*"
26
26
  ]
27
27
  },
28
+ "typeRoots": [
29
+ "./node_modules",
30
+ "./node_modules/@rancher/shell/types"
31
+ ],
28
32
  "types": [
29
33
  "@types/node",
30
34
  "@nuxt/types",
31
- "cypress"
35
+ "cypress",
36
+ "rancher"
32
37
  ]
33
38
  },
34
39
  "exclude": [
package/creators/pkg/init CHANGED
@@ -137,6 +137,9 @@ if (!isNodeModulesShell) {
137
137
  tsconfig.compilerOptions.paths[p] = updateArray(tsconfig.compilerOptions.paths[p]);
138
138
  });
139
139
 
140
+ // Update typeRoots
141
+ tsconfig.compilerOptions.typeRoots = updateArray(tsconfig.compilerOptions.typeRoots);
142
+
140
143
  fs.writeFileSync(path.join(pkgFolder, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));
141
144
  console.log(' Updated tsconfig.json for shell folder location');
142
145
  }
@@ -13,9 +13,15 @@
13
13
  "sourceMap": true,
14
14
  "baseUrl": ".",
15
15
  "preserveSymlinks": true,
16
+ "typeRoots": [
17
+ "../../node_modules",
18
+ "../../node_modules/@rancher/shell/types"
19
+ ],
16
20
  "types": [
17
21
  "node",
18
- "webpack-env"
22
+ "webpack-env",
23
+ "@nuxt/types",
24
+ "rancher"
19
25
  ],
20
26
  "lib": [
21
27
  "esnext",
@@ -39,7 +45,6 @@
39
45
  "**/*.ts",
40
46
  "**/*.tsx",
41
47
  "**/*.vue",
42
- "../../node_modules/@rancher/shell/types/*.d.ts",
43
48
  "../../node_modules/@rancher/shell/core/types.ts"
44
49
  ],
45
50
  "exclude": [
@@ -146,6 +146,16 @@ export default {
146
146
  this.allNodePools = fetchTwoRes.allNodePools || [];
147
147
  this.haveNodePools = !!fetchTwoRes.allNodePools;
148
148
  this.machineTemplates = fetchTwoRes.mdtt || [];
149
+
150
+ // Fetch RKE template revisions so we can show when an updated template is available
151
+ // This request does not need to be blocking
152
+ if ( this.$store.getters['management/canList'](MANAGEMENT.RKE_TEMPLATE) ) {
153
+ this.$store.dispatch('management/findAll', { type: MANAGEMENT.RKE_TEMPLATE });
154
+ }
155
+
156
+ if ( this.$store.getters['management/canList'](MANAGEMENT.RKE_TEMPLATE_REVISION) ) {
157
+ this.$store.dispatch('management/findAll', { type: MANAGEMENT.RKE_TEMPLATE_REVISION });
158
+ }
149
159
  },
150
160
 
151
161
  created() {
@@ -311,6 +321,18 @@ export default {
311
321
  return false;
312
322
  },
313
323
 
324
+ showEksNodeGroupWarning() {
325
+ if ( this.value.isEKS ) {
326
+ const desiredTotal = this.value.eksNodeGroups.filter(g => g.desiredSize === 0);
327
+
328
+ if ( desiredTotal.length === this.value.eksNodeGroups.length ) {
329
+ return true;
330
+ }
331
+ }
332
+
333
+ return false;
334
+ },
335
+
314
336
  machineHeaders() {
315
337
  return [
316
338
  STATE,
@@ -575,6 +597,7 @@ export default {
575
597
  <Loading v-if="$fetchState.pending" />
576
598
  <div v-else>
577
599
  <Banner v-if="showWindowsWarning" color="error" :label="t('cluster.banner.os', { newOS: 'Windows', existingOS: 'Linux' })" />
600
+ <Banner v-if="showEksNodeGroupWarning" color="error" :label="t('cluster.banner.desiredNodeGroupWarning')" />
578
601
 
579
602
  <Banner v-if="$fetchState.error" color="error" :label="$fetchState.error" />
580
603
  <ResourceTabs v-model="value" :default-tab="defaultTab">
@@ -120,6 +120,10 @@ export default {
120
120
  return this.value.type === WORKLOAD_TYPES.CRON_JOB;
121
121
  },
122
122
 
123
+ isPod() {
124
+ return this.value.type === WORKLOAD_TYPES.POD;
125
+ },
126
+
123
127
  podSchema() {
124
128
  return this.$store.getters['cluster/schemaFor'](POD);
125
129
  },
@@ -133,13 +137,15 @@ export default {
133
137
  },
134
138
 
135
139
  podTemplateSpec() {
136
- const isCronJob = this.value.type === WORKLOAD_TYPES.CRON_JOB;
137
-
138
- if ( isCronJob ) {
140
+ if ( this.value.type === WORKLOAD_TYPES.CRON_JOB ) {
139
141
  return this.value.spec.jobTemplate.spec.template.spec;
140
- } else {
141
- return this.value.spec?.template?.spec;
142
142
  }
143
+
144
+ if ( this.value.type === WORKLOAD_TYPES.POD ) {
145
+ return this.value;
146
+ }
147
+
148
+ return this.value.spec?.template?.spec;
143
149
  },
144
150
 
145
151
  container() {
File without changes
File without changes
@@ -67,6 +67,10 @@ export default {
67
67
 
68
68
  async fetch() {
69
69
  await this.reloadModel();
70
+
71
+ if ( this.value?.graphEndpoint ) {
72
+ this.setInitialEndpoint(this.value.graphEndpoint);
73
+ }
70
74
  },
71
75
 
72
76
  data() {
@@ -171,6 +175,16 @@ export default {
171
175
  }
172
176
  },
173
177
 
178
+ setInitialEndpoint(endpoint) {
179
+ const endpointKey = Object.keys(ENDPOINT_MAPPING).find(key => ENDPOINT_MAPPING[key].graphEndpoint === endpoint);
180
+
181
+ if ( endpointKey ) {
182
+ this.endpoint = endpointKey;
183
+ } else {
184
+ this.endpoint = 'custom';
185
+ }
186
+ },
187
+
174
188
  getNewApplicationSecret() {
175
189
  const applicationSecretOrId =
176
190
  this.model.applicationSecret || this.applicationSecret;
@@ -291,7 +305,7 @@ export default {
291
305
  <InfoBox v-if="!model.enabled" id="reply-info" class="mt-20 mb-20 p-10">
292
306
  {{ t('authConfig.azuread.reply.info') }}
293
307
  <br />
294
- <label>{{ t('authConfig.azuread.reply.label') }} </label>
308
+ <label class="reply-url">{{ t('authConfig.azuread.reply.label') }} </label>
295
309
  <CopyToClipboardText :plain="true" :text="replyUrl" />
296
310
  </InfoBox>
297
311
 
@@ -387,4 +401,9 @@ export default {
387
401
  #reply-info {
388
402
  flex-grow: 0;
389
403
  }
404
+
405
+ .reply-url {
406
+ color: inherit;
407
+ font-weight: 700;
408
+ }
390
409
  </style>
@@ -260,7 +260,13 @@ export default {
260
260
  @select-type="selectType"
261
261
  @error="e=>errors = e"
262
262
  >
263
- <NameNsDescription v-model="value" name-key="_name" :mode="mode" :namespaced="false" />
263
+ <NameNsDescription
264
+ v-model="value"
265
+ name-key="_name"
266
+ description-key="description"
267
+ :mode="mode"
268
+ :namespaced="false"
269
+ />
264
270
  <keep-alive>
265
271
  <component
266
272
  :is="cloudComponent"
@@ -16,7 +16,7 @@ import { NAME } from '@shell/config/product/explorer';
16
16
  import { PROJECT_ID, _VIEW, _CREATE, _EDIT } from '@shell/config/query-params';
17
17
  import ProjectMembershipEditor from '@shell/components/form/Members/ProjectMembershipEditor';
18
18
  import { canViewProjectMembershipEditor } from '@shell/components/form/Members/ProjectMembershipEditor.vue';
19
- import { NAME as HARVESTER } from '@shell/config/product/harvester';
19
+ import { HARVESTER_NAME as HARVESTER } from '@shell/config/product/harvester-manager';
20
20
  import { Banner } from '@components/Banner';
21
21
 
22
22
  export default {
@@ -188,7 +188,7 @@ export default {
188
188
  <template>
189
189
  <CruResource
190
190
  class="project"
191
- :done-route="'c-cluster-product-projectsnamespaces'"
191
+ :done-route="value.listLocation"
192
192
  :errors="fvUnreportedValidationErrors"
193
193
  :mode="mode"
194
194
  :resource="value"