@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
@@ -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,12 +13,12 @@ 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
 
20
20
  get lastUpdateTime() {
21
- return this.status.conditions[0].lastUpdateTime;
21
+ return this.status?.conditions?.[0].lastUpdateTime;
22
22
  }
23
23
 
24
24
  get bundleType() {
@@ -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,200 @@ 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 embedded plugin that was in the last rancher release)
83
+ const embeddedPath = `${ pkgName }/${ pkgName }.umd.min.js`;
84
+
85
+ return {
86
+ pkgUrl: process.env.dev ? `${ process.env.api }/dashboard/${ 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
+ let 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
+
124
+ // When using an external address, the pkgName should also be get from the url
125
+ const names = pkgUrl.split('/');
126
+ const jsName = names[names.length - 1];
127
+
128
+ pkgName = jsName?.split('.umd.min.js')[0];
129
+ } else {
130
+ throw new Error('Harvester cluster requested the plugin at `ui-plugin-index` is used, however did not provide a value for it');
131
+ }
132
+ }
133
+
134
+ return {
135
+ pkgUrl,
136
+ pkgName
137
+ };
138
+ }
139
+
140
+ _overridePkgDetails() {
141
+ // Support loading the pkg from a locally, or other, address
142
+ // This helps testing of the harvester plugin when packaged up, instead of directly imported
143
+ const harvesterPkgUrl = process.env.harvesterPkgUrl;
144
+
145
+ if (!harvesterPkgUrl) {
146
+ return;
147
+ }
148
+ const parts = harvesterPkgUrl.replace('.umd.min.js', '').split('/');
149
+ const pkgNameFromUrl = parts.length > 1 ? parts[parts.length - 1] : null;
150
+
151
+ if (pkgNameFromUrl) {
152
+ return {
153
+ pkgUrl: harvesterPkgUrl,
154
+ pkgName: pkgNameFromUrl
155
+ };
156
+ }
157
+ }
158
+
159
+ async _pkgDetails() {
160
+ const overridePkgDetails = this._overridePkgDetails();
161
+
162
+ if (overridePkgDetails) {
163
+ return overridePkgDetails;
164
+ }
165
+
166
+ const clusterId = this.mgmt.id;
167
+ const uiInfo = await this._getUiInfo(clusterId);
168
+
169
+ return uiInfo ? this._supportedClusterPkgDetails(uiInfo, clusterId) : this._legacyClusterPkgDetails();
170
+ }
171
+
172
+ async loadClusterPlugin() {
173
+ // Skip loading if it's built in
174
+ const plugins = this.$rootState.$plugin.getPlugins();
175
+ const loadedPkgs = Object.keys(plugins);
176
+
177
+ if (loadedPkgs.find(pkg => pkg === HARVESTER_NAME)) {
178
+ console.info('Harvester plugin built is built in, skipping load from external sources'); // eslint-disable-line no-console
179
+
180
+ return;
181
+ }
182
+
183
+ // Determine the plugin name and the url it can be fetched from
184
+ const { pkgUrl, pkgName } = await this._pkgDetails();
185
+
186
+ console.info('Harvester plugin details: ', pkgName, pkgUrl); // eslint-disable-line no-console
187
+
188
+ // Skip loading if we've previously loaded the correct one
189
+ if (!!plugins[pkgName]) {
190
+ console.info('Harvester plugin already loaded, no need to load', pkgName); // eslint-disable-line no-console
191
+
192
+ return;
193
+ }
194
+
195
+ console.info('Attempting to load Harvester plugin', pkgName); // eslint-disable-line no-console
196
+
197
+ const res = await this.$rootState.$plugin.loadAsync(pkgName, pkgUrl);
198
+
199
+ console.info('Loaded Harvester plugin', pkgName); // eslint-disable-line no-console
200
+
201
+ return res;
202
+ }
203
+
204
+ goToCluster() {
205
+ this.loadClusterPlugin()
206
+ .then(() => {
207
+ this.currentRouter().push({
208
+ name: `${ VIRTUAL }-c-cluster-resource`,
209
+ params: {
210
+ cluster: this.status.clusterName,
211
+ product: VIRTUAL,
212
+ resource: HCI.DASHBOARD // Go directly to dashboard to avoid blip of components on screen
213
+ }
214
+ });
215
+ })
216
+ .catch((err) => {
217
+ const message = typeof error === 'object' ? JSON.stringify(err) : err;
218
+
219
+ console.error('Failed to load harvester package: ', message); // eslint-disable-line no-console
220
+
221
+ this.$dispatch('growl/error', {
222
+ title: this.t('harvesterManager.plugins.loadError'),
223
+ message,
224
+ timeout: 5000
225
+ }, { root: true });
226
+ });
227
+ }
33
228
  }
@@ -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
 
@@ -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 {
@@ -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
  }
@@ -197,12 +197,10 @@ export default class ProvCluster extends SteveModel {
197
197
  return super.canEditYaml;
198
198
  }
199
199
 
200
- get isAKS() {
201
- return this.provisioner === 'AKS';
202
- }
200
+ get isHostedKubernetesProvider() {
201
+ const providers = ['AKS', 'EKS', 'GKE'];
203
202
 
204
- get isEKS() {
205
- return this.provisioner === 'EKS';
203
+ return providers.includes(this.provisioner);
206
204
  }
207
205
 
208
206
  get isImported() {
@@ -230,13 +228,17 @@ export default class ProvCluster extends SteveModel {
230
228
  get isImportedK3s() {
231
229
  // As of Rancher v2.6.7, this returns false for imported K3s clusters,
232
230
  // in which this.provisioner is `k3s`.
233
- return this.isImported && this.mgmt?.status?.provider === 'k3s';
231
+ return this.isImported && this.isK3s;
234
232
  }
235
233
 
236
234
  get isImportedRke2() {
237
235
  return this.isImported && this.mgmt?.status?.provider?.startsWith('rke2');
238
236
  }
239
237
 
238
+ get isK3s() {
239
+ return this.mgmt?.status?.provider === 'k3s';
240
+ }
241
+
240
242
  get isRke2() {
241
243
  return !!this.spec?.rkeConfig;
242
244
  }
@@ -269,6 +271,10 @@ export default class ProvCluster extends SteveModel {
269
271
  return !!this.mgmt?.isReady;
270
272
  }
271
273
 
274
+ get eksNodeGroups() {
275
+ return this.mgmt?.spec?.eksConfig?.nodeGroups;
276
+ }
277
+
272
278
  waitForProvisioner(timeout, interval) {
273
279
  return this.waitForTestFn(() => {
274
280
  return !!this.provisioner;
@@ -760,4 +766,8 @@ export default class ProvCluster extends SteveModel {
760
766
  await this.$dispatch('ws.resource.remove', { data: this });
761
767
  }
762
768
  }
769
+
770
+ get hasError() {
771
+ return this.status?.conditions?.some(condition => condition.error === true);
772
+ }
763
773
  }