@rancher/shell 0.5.3 → 2.0.0

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 (581) hide show
  1. package/assets/data/aws-regions.json +9 -0
  2. package/assets/images/vendor/openid.svg +18 -0
  3. package/assets/styles/app.scss +1 -2
  4. package/assets/styles/fonts/_icons.scss +3 -3
  5. package/assets/styles/global/_columns.scss +1 -1
  6. package/assets/styles/global/_labeled-input.scss +2 -0
  7. package/assets/styles/themes/_csp.scss +2 -2
  8. package/assets/styles/themes/_dark.scss +8 -2
  9. package/assets/styles/themes/_light.scss +2 -1
  10. package/assets/styles/themes/_suse.scss +1 -1
  11. package/assets/styles/vendor/vue-select.scss +5 -0
  12. package/assets/translations/en-us.yaml +296 -58
  13. package/assets/translations/zh-hans.yaml +5 -27
  14. package/babel.config.js +1 -1
  15. package/chart/__tests__/S3.test.ts +9 -2
  16. package/chart/monitoring/grafana/index.vue +6 -2
  17. package/chart/monitoring/prometheus/index.vue +2 -2
  18. package/chart/rancher-backup/S3.vue +11 -9
  19. package/chart/rancher-backup/index.vue +15 -5
  20. package/cloud-credential/__tests__/harvester.test.ts +18 -0
  21. package/cloud-credential/generic.vue +18 -9
  22. package/cloud-credential/harvester.vue +11 -3
  23. package/components/AppModal.vue +167 -0
  24. package/components/AssignTo.vue +7 -4
  25. package/components/AsyncButton.vue +18 -5
  26. package/components/BackLink.vue +4 -4
  27. package/components/BannerGraphic.vue +1 -0
  28. package/components/BrandImage.vue +47 -1
  29. package/components/Carousel.vue +14 -8
  30. package/components/Certificates.vue +8 -11
  31. package/components/ClusterBadge.vue +12 -3
  32. package/components/ClusterIconMenu.vue +44 -16
  33. package/components/ClusterProviderIcon.vue +14 -3
  34. package/components/CodeMirror.vue +73 -38
  35. package/components/CommunityLinks.vue +12 -8
  36. package/components/CreateDriver.vue +81 -0
  37. package/components/CruResource.vue +51 -27
  38. package/components/DetailTop.vue +2 -2
  39. package/components/Dialog.vue +6 -5
  40. package/components/DisableAuthProviderModal.vue +14 -8
  41. package/components/DraggableZone.vue +2 -2
  42. package/components/ExplorerMembers.vue +3 -3
  43. package/components/ExplorerProjectsNamespaces.vue +6 -6
  44. package/components/FixedBanner.vue +47 -36
  45. package/components/GlobalRoleBindings.vue +26 -0
  46. package/components/Import.vue +10 -6
  47. package/components/Inactivity.vue +1 -5
  48. package/components/KeyValueView.vue +14 -10
  49. package/components/MessageLink.vue +2 -2
  50. package/components/ModalWithCard.vue +5 -8
  51. package/components/MoveModal.vue +35 -33
  52. package/components/PodSecurityAdmission.vue +3 -3
  53. package/components/PromptChangePassword.vue +33 -33
  54. package/components/PromptModal.vue +11 -21
  55. package/components/PromptRemove.vue +11 -17
  56. package/components/PromptRestore.vue +18 -16
  57. package/components/Questions/__tests__/Boolean.test.ts +9 -19
  58. package/components/Questions/__tests__/Float.test.ts +9 -19
  59. package/components/Questions/__tests__/Int.test.ts +9 -19
  60. package/components/Questions/__tests__/String.test.ts +9 -19
  61. package/components/Questions/__tests__/Yaml.test.ts +9 -20
  62. package/components/Questions/__tests__/utils/questions-defaults.ts +20 -0
  63. package/components/Questions/index.vue +18 -2
  64. package/components/ResourceCancelModal.vue +34 -29
  65. package/components/ResourceDetail/Masthead.vue +23 -7
  66. package/components/ResourceDetail/index.vue +5 -0
  67. package/components/ResourceList/Masthead.vue +28 -10
  68. package/components/ResourceList/index.vue +65 -14
  69. package/components/ResourceTable.vue +73 -19
  70. package/components/ResourceYaml.vue +1 -0
  71. package/components/SelectIconGrid.vue +3 -3
  72. package/components/SideNav.vue +15 -37
  73. package/components/SingleClusterInfo.vue +4 -4
  74. package/components/SortableTable/THead.vue +26 -12
  75. package/components/SortableTable/filtering.js +9 -1
  76. package/components/SortableTable/grouping.js +8 -1
  77. package/components/SortableTable/index.vue +142 -42
  78. package/components/SortableTable/paging.js +36 -7
  79. package/components/SortableTable/selection.js +2 -1
  80. package/components/SortableTable/sorting.js +24 -7
  81. package/components/TabTitle.vue +84 -0
  82. package/components/Tabbed/index.vue +6 -1
  83. package/components/TableDataUserIcon.vue +47 -0
  84. package/components/TypeDescription.vue +1 -0
  85. package/components/Wizard.vue +1 -0
  86. package/components/__tests__/AppModal.test.ts +98 -0
  87. package/components/__tests__/AsyncButton.test.ts +1 -3
  88. package/components/__tests__/BackLink.test.ts +1 -1
  89. package/components/__tests__/ButtonGroup.test.ts +3 -6
  90. package/components/__tests__/Carousel.test.ts +43 -0
  91. package/components/__tests__/Certificates.test.ts +29 -0
  92. package/components/__tests__/{CodeMirror.spec.ts → CodeMirror.test.ts} +5 -17
  93. package/components/__tests__/CruResource.test.ts +10 -9
  94. package/components/__tests__/EtcdInfoBanner.test.ts +37 -0
  95. package/components/__tests__/FixedBanner.test.ts +5 -20
  96. package/components/__tests__/NamespaceFilter.test.ts +9 -18
  97. package/components/__tests__/TabTitle.test.ts +129 -0
  98. package/components/auth/AzureWarning.vue +2 -2
  99. package/components/auth/RoleDetailEdit.vue +10 -0
  100. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  101. package/components/auth/login/oidc.vue +7 -1
  102. package/components/fleet/FleetClusters.vue +9 -9
  103. package/components/fleet/FleetIntro.vue +11 -17
  104. package/components/fleet/FleetNoWorkspaces.vue +2 -2
  105. package/components/fleet/FleetRepos.vue +1 -0
  106. package/components/fleet/ForceDirectedTreeChart/index.vue +9 -3
  107. package/components/form/ArrayList.vue +30 -19
  108. package/components/form/ArrayListSelect.vue +9 -4
  109. package/components/form/ClusterAppearance.vue +132 -0
  110. package/components/form/ColorInput.vue +1 -0
  111. package/components/form/Error.vue +3 -3
  112. package/components/form/Footer.vue +2 -2
  113. package/components/form/GitPicker.vue +83 -38
  114. package/components/form/KeyValue.vue +67 -48
  115. package/components/form/LabeledSelect.vue +143 -43
  116. package/components/form/Labels.vue +3 -1
  117. package/components/form/NameNsDescription.vue +26 -9
  118. package/components/form/ResourceLabeledSelect.vue +187 -0
  119. package/components/form/ResourceTabs/index.vue +31 -15
  120. package/components/form/SecretSelector.vue +93 -18
  121. package/components/form/Select.vue +1 -1
  122. package/components/form/SelectOrCreateAuthSecret.vue +135 -62
  123. package/components/form/SimpleSecretSelector.vue +88 -28
  124. package/components/form/__tests__/BannerSettings.test.ts +53 -0
  125. package/components/form/__tests__/KeyValue.test.ts +121 -12
  126. package/components/form/__tests__/LabeledSelect.test.ts +0 -18
  127. package/components/form/__tests__/NameNsDescription.test.ts +25 -15
  128. package/components/form/labeled-select-utils/labeled-select-pagination.ts +151 -0
  129. package/components/form/labeled-select-utils/labeled-select.utils.ts +122 -0
  130. package/components/formatter/AppSummaryGraph.vue +2 -2
  131. package/components/formatter/CloudCredPublicData.vue +30 -0
  132. package/components/formatter/ClusterLink.vue +2 -2
  133. package/components/formatter/FleetSummaryGraph.vue +2 -1
  134. package/components/formatter/ImagePercentageBar.vue +0 -4
  135. package/components/formatter/IngressTarget.vue +18 -7
  136. package/components/formatter/Link.vue +2 -2
  137. package/components/formatter/LinkDetail.vue +2 -2
  138. package/components/formatter/LinkDetailImage.vue +2 -2
  139. package/components/formatter/LinkName.vue +2 -2
  140. package/components/formatter/LiveDate.vue +16 -0
  141. package/components/formatter/PrincipalGroupBindings.vue +2 -2
  142. package/components/formatter/SecretType.vue +2 -2
  143. package/components/formatter/VirtualServiceGateways.vue +2 -2
  144. package/components/formatter/__tests__/LinkDetail.test.ts +5 -5
  145. package/components/nav/Group.vue +7 -5
  146. package/components/nav/Header.vue +82 -43
  147. package/components/nav/NamespaceFilter.vue +8 -1
  148. package/components/nav/TopLevelMenu.vue +336 -125
  149. package/components/nav/Type.vue +58 -102
  150. package/components/nav/__tests__/TopLevelMenu.test.ts +370 -9
  151. package/components/nav/__tests__/Type.test.ts +321 -126
  152. package/components/nuxt/nuxt-child.js +0 -5
  153. package/components/nuxt/nuxt-error.vue +1 -1
  154. package/components/nuxt/nuxt-link.client.js +13 -95
  155. package/components/templates/default.vue +3 -3
  156. package/components/templates/error.vue +6 -10
  157. package/components/templates/standalone.vue +0 -4
  158. package/components/templates/unauthenticated.vue +1 -2
  159. package/components/user.retention/user-retention-header.vue +34 -0
  160. package/composables/useCompactInput.test.ts +36 -0
  161. package/composables/useCompactInput.ts +2 -2
  162. package/composables/useI18n.ts +26 -0
  163. package/composables/useLabeledFormElement.test.ts +135 -0
  164. package/composables/useStore.ts +16 -0
  165. package/config/home-links.js +32 -1
  166. package/config/labels-annotations.js +2 -1
  167. package/config/middleware.js +0 -6
  168. package/config/pagination-table-headers.js +57 -0
  169. package/config/pod-security-admission.ts +1 -1
  170. package/config/private-label.js +1 -3
  171. package/config/product/auth.js +1 -0
  172. package/config/product/explorer.js +167 -46
  173. package/config/product/legacy.js +3 -95
  174. package/config/product/manager.js +44 -11
  175. package/config/query-params.js +1 -0
  176. package/config/roles.ts +23 -0
  177. package/config/router/index.js +23 -0
  178. package/config/router/navigation-guards/attempt-first-login.js +73 -0
  179. package/config/router/navigation-guards/authentication.js +63 -0
  180. package/config/router/navigation-guards/index.js +15 -0
  181. package/config/router/navigation-guards/load-initial-settings.js +15 -0
  182. package/config/router/routes.js +487 -0
  183. package/config/settings.ts +38 -2
  184. package/config/store.js +7 -3
  185. package/config/table-headers.js +46 -1
  186. package/config/types.js +36 -16
  187. package/config/uiplugins.js +10 -5
  188. package/core/plugin-helpers.js +1 -1
  189. package/core/plugin.ts +2 -1
  190. package/core/plugins.js +289 -282
  191. package/creators/app/files/.eslintignore +0 -2
  192. package/creators/app/files/.vscode/settings.json +0 -1
  193. package/creators/pkg/files/.github/workflows/build-extension-catalog.yml +2 -6
  194. package/creators/pkg/files/.github/workflows/build-extension-charts.yml +2 -6
  195. package/creators/pkg/init +32 -0
  196. package/detail/__tests__/service.test.ts +62 -0
  197. package/detail/catalog.cattle.io.app.vue +1 -1
  198. package/detail/cis.cattle.io.clusterscan.vue +14 -3
  199. package/detail/fleet.cattle.io.gitrepo.vue +15 -9
  200. package/detail/namespace.vue +2 -2
  201. package/detail/networking.k8s.io.ingress.vue +52 -19
  202. package/detail/node.vue +20 -43
  203. package/detail/pod.vue +1 -68
  204. package/detail/provisioning.cattle.io.cluster.vue +2 -1
  205. package/detail/service.vue +1 -1
  206. package/detail/workload/index.vue +2 -15
  207. package/dialog/AddCustomBadgeDialog.vue +318 -161
  208. package/dialog/DeactivateDriverDialog.vue +118 -0
  209. package/dialog/RollbackWorkloadDialog.vue +2 -2
  210. package/dialog/RotateCertificatesDialog.vue +0 -21
  211. package/directives/clean-html.js +15 -0
  212. package/directives/clean-tooltip.js +32 -0
  213. package/directives/focus.js +41 -0
  214. package/directives/int-number.js +21 -0
  215. package/directives/positive-int-number.js +19 -0
  216. package/directives/trim-whitespace.js +19 -0
  217. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +3 -2
  218. package/edit/__tests__/kontainerDriver.test.ts +107 -0
  219. package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +12 -1
  220. package/edit/__tests__/management.cattle.io.setting.test.ts +2 -1
  221. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +2 -3
  222. package/edit/__tests__/nodeDriver.test.ts +107 -0
  223. package/edit/__tests__/service.test.ts +1 -5
  224. package/edit/__tests__/ui.cattle.io.navlink.test.ts +3 -1
  225. package/edit/auth/AuthProviderWarningBanners.vue +34 -0
  226. package/edit/auth/__tests__/AuthProviderWarningBanners.test.ts +19 -0
  227. package/edit/auth/__tests__/azuread.test.ts +241 -0
  228. package/edit/auth/__tests__/oidc.test.ts +137 -0
  229. package/edit/auth/azuread.vue +133 -31
  230. package/edit/auth/github.vue +5 -17
  231. package/edit/auth/googleoauth.vue +5 -18
  232. package/edit/auth/ldap/index.vue +5 -17
  233. package/edit/auth/oidc.vue +143 -42
  234. package/edit/auth/saml.vue +5 -14
  235. package/edit/catalog.cattle.io.clusterrepo.vue +175 -20
  236. package/edit/cis.cattle.io.clusterscan.vue +5 -2
  237. package/edit/cis.cattle.io.clusterscanbenchmark.vue +41 -9
  238. package/edit/cloudcredential.vue +26 -4
  239. package/edit/configmap.vue +10 -4
  240. package/edit/fleet.cattle.io.gitrepo.vue +7 -4
  241. package/edit/helm.cattle.io.projecthelmchart.vue +29 -19
  242. package/edit/kontainerDriver.vue +65 -0
  243. package/edit/logging-flow/Match.vue +10 -9
  244. package/edit/logging-flow/index.vue +4 -19
  245. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +232 -2
  246. package/edit/logging.banzaicloud.io.output/index.vue +43 -26
  247. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +3 -3
  248. package/edit/management.cattle.io.project.vue +2 -1
  249. package/edit/management.cattle.io.setting.vue +20 -0
  250. package/edit/management.cattle.io.user.vue +2 -1
  251. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +10 -7
  252. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +21 -16
  253. package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +1 -0
  254. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +3 -0
  255. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +2 -0
  256. package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +2 -0
  257. package/edit/monitoring.coreos.com.prometheusrule/index.vue +2 -0
  258. package/edit/networking.k8s.io.ingress/Rules.vue +8 -3
  259. package/edit/networking.k8s.io.ingress/index.vue +64 -8
  260. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +1 -0
  261. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +6 -2
  262. package/edit/networking.k8s.io.networkpolicy/__tests__/{PolicyRuleTarget.spec.ts → PolicyRuleTarget.test.ts} +45 -6
  263. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/selectors.test.ts +1 -1
  264. package/edit/networking.k8s.io.networkpolicy/index.vue +2 -0
  265. package/edit/nodeDriver.vue +65 -0
  266. package/edit/persistentvolume/index.vue +2 -2
  267. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +18 -9
  268. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +165 -1
  269. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +1 -1
  270. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +0 -3
  271. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +228 -0
  272. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +70 -12
  273. package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +5 -0
  274. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  275. package/edit/provisioning.cattle.io.cluster/index.vue +21 -15
  276. package/edit/provisioning.cattle.io.cluster/rke2.vue +185 -114
  277. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +67 -7
  278. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +19 -6
  279. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +132 -0
  280. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +7 -0
  281. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
  282. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +1 -0
  283. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +3 -0
  284. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -0
  285. package/edit/resources.cattle.io.backup.vue +139 -124
  286. package/edit/resources.cattle.io.restore.vue +146 -126
  287. package/edit/service.vue +1 -0
  288. package/edit/serviceaccount.vue +46 -4
  289. package/edit/workload/__tests__/Job.test.ts +1 -3
  290. package/edit/workload/__tests__/Upgrading.test.ts +2 -2
  291. package/edit/workload/mixins/workload.js +34 -1
  292. package/edit/workload/storage/emptyDir.vue +2 -2
  293. package/initialize/App.vue +75 -0
  294. package/initialize/app-extended.js +128 -0
  295. package/initialize/entry-helpers.js +549 -0
  296. package/initialize/entry.js +32 -0
  297. package/initialize/install-components.js +23 -0
  298. package/initialize/install-directives.js +59 -0
  299. package/initialize/install-plugins.js +123 -0
  300. package/list/__tests__/workload.test.ts +1 -1
  301. package/list/cis.cattle.io.clusterscan.vue +16 -10
  302. package/list/group.principal.vue +2 -2
  303. package/list/management.cattle.io.feature.vue +11 -7
  304. package/list/management.cattle.io.user.vue +36 -3
  305. package/list/networking.k8s.io.ingress.vue +36 -0
  306. package/list/node.vue +211 -73
  307. package/list/provisioning.cattle.io.cluster.vue +17 -4
  308. package/list/ui.cattle.io.navlink.vue +2 -2
  309. package/list/workload.vue +22 -0
  310. package/machine-config/__tests__/vmwarevsphere-pool-config-merge.test.ts +30 -0
  311. package/machine-config/__tests__/vmwarevsphere.test.ts +162 -59
  312. package/machine-config/amazonec2.vue +1 -1
  313. package/machine-config/azure.vue +38 -21
  314. package/machine-config/generic.vue +11 -15
  315. package/machine-config/vmwarevsphere-pool-config-merge.ts +25 -0
  316. package/machine-config/vmwarevsphere.vue +20 -11
  317. package/middleware/authenticated.js +9 -361
  318. package/mixins/__tests__/chart.test.ts +48 -6
  319. package/mixins/__tests__/create-edit-view.test.ts +2 -3
  320. package/mixins/auth-config.js +3 -2
  321. package/mixins/brand.js +75 -57
  322. package/mixins/chart.js +27 -13
  323. package/mixins/create-edit-view/index.js +2 -2
  324. package/mixins/fetch.client.js +42 -48
  325. package/mixins/labeled-form-element.ts +21 -1
  326. package/mixins/page-actions.js +7 -5
  327. package/mixins/resource-fetch-api-pagination.js +304 -0
  328. package/mixins/resource-fetch-namespaced.js +1 -1
  329. package/mixins/resource-fetch.js +46 -5
  330. package/models/__tests__/cluster.test.ts +44 -0
  331. package/models/__tests__/fleet.cattle.io.cluster.test.ts +36 -0
  332. package/models/__tests__/schema.tests.ts +24 -0
  333. package/models/__tests__/steve-schema.test.ts +73 -0
  334. package/models/__tests__/workload.test.ts +1 -1
  335. package/models/catalog.cattle.io.app.js +8 -0
  336. package/models/catalog.cattle.io.clusterrepo.js +9 -1
  337. package/models/catalog.cattle.io.uiplugin.js +7 -8
  338. package/models/cis.cattle.io.clusterscan.js +29 -8
  339. package/models/cloudcredential.js +9 -1
  340. package/models/cluster/node.js +4 -0
  341. package/models/cluster/schema.js +6 -0
  342. package/models/cluster.js +33 -0
  343. package/models/driver.js +62 -0
  344. package/models/fleet.cattle.io.cluster.js +23 -11
  345. package/models/fleet.cattle.io.gitrepo.js +10 -0
  346. package/models/helm.cattle.io.projecthelmchart.js +1 -1
  347. package/models/kontainerdriver.js +68 -0
  348. package/models/management/schema.js +6 -0
  349. package/models/management.cattle.io.authconfig.js +3 -2
  350. package/models/management.cattle.io.cluster.js +5 -4
  351. package/models/management.cattle.io.globalrole.js +2 -0
  352. package/models/management.cattle.io.user.js +67 -2
  353. package/models/monitoring.coreos.com.receiver.js +3 -1
  354. package/models/monitoring.coreos.com.route.js +1 -1
  355. package/models/networking.k8s.io.ingress.js +2 -1
  356. package/models/nodedriver.js +68 -0
  357. package/models/provisioning.cattle.io.cluster.js +34 -1
  358. package/models/schema.js +28 -7
  359. package/models/service.js +2 -0
  360. package/models/steve-schema.ts +254 -0
  361. package/models/workload.js +1 -0
  362. package/package.json +6 -5
  363. package/pages/about.vue +12 -5
  364. package/pages/account/index.vue +7 -2
  365. package/pages/auth/login.vue +106 -102
  366. package/pages/auth/logout.vue +2 -2
  367. package/pages/auth/setup.vue +57 -64
  368. package/pages/auth/verify.vue +17 -17
  369. package/pages/c/_cluster/apps/charts/chart.vue +54 -9
  370. package/pages/c/_cluster/apps/charts/index.vue +37 -13
  371. package/pages/c/_cluster/apps/charts/install.vue +4 -4
  372. package/pages/c/_cluster/auth/config/_id.vue +0 -6
  373. package/pages/c/_cluster/auth/config/index.vue +15 -9
  374. package/pages/c/_cluster/auth/roles/index.vue +8 -10
  375. package/pages/c/_cluster/auth/user.retention/index.vue +384 -0
  376. package/pages/c/_cluster/explorer/ConfigBadge.vue +13 -8
  377. package/pages/c/_cluster/explorer/EventsTable.vue +18 -0
  378. package/pages/c/_cluster/explorer/__tests__/index.test.ts +181 -0
  379. package/pages/c/_cluster/explorer/index.vue +231 -72
  380. package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +69 -0
  381. package/pages/c/_cluster/explorer/tools/index.vue +12 -176
  382. package/pages/c/_cluster/fleet/index.vue +88 -93
  383. package/pages/c/_cluster/longhorn/__tests__/longhorn.index.test.ts +89 -0
  384. package/pages/c/_cluster/longhorn/index.vue +52 -17
  385. package/pages/c/_cluster/manager/cloudCredential/index.vue +18 -25
  386. package/pages/c/_cluster/manager/drivers/kontainerDriver/_id.vue +12 -0
  387. package/pages/c/_cluster/manager/drivers/kontainerDriver/create.vue +15 -0
  388. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +94 -0
  389. package/pages/c/_cluster/manager/drivers/nodeDriver/_id.vue +12 -0
  390. package/pages/c/_cluster/manager/drivers/nodeDriver/create.vue +15 -0
  391. package/pages/c/_cluster/manager/drivers/nodeDriver/index.vue +63 -0
  392. package/pages/c/_cluster/manager/jwt.authentication/index.vue +235 -0
  393. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +4 -0
  394. package/pages/c/_cluster/monitoring/index.vue +1 -17
  395. package/pages/c/_cluster/monitoring/route-receiver/index.vue +2 -2
  396. package/pages/c/_cluster/neuvector/index.vue +1 -0
  397. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -0
  398. package/pages/c/_cluster/settings/banners.vue +86 -8
  399. package/pages/c/_cluster/settings/brand.vue +258 -36
  400. package/pages/c/_cluster/settings/index.vue +4 -4
  401. package/pages/c/_cluster/settings/links.vue +5 -3
  402. package/pages/c/_cluster/settings/performance.vue +71 -2
  403. package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +5 -2
  404. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +10 -7
  405. package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +9 -6
  406. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +11 -5
  407. package/pages/c/_cluster/uiplugins/InstallDialog.vue +53 -18
  408. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +36 -301
  409. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +14 -6
  410. package/pages/c/_cluster/uiplugins/__tests__/SetupUIPlugins.test.ts +52 -106
  411. package/pages/c/_cluster/uiplugins/index.vue +38 -52
  412. package/pages/diagnostic.vue +1 -0
  413. package/pages/fail-whale.vue +103 -41
  414. package/pages/home.vue +81 -24
  415. package/pages/prefs.vue +8 -3
  416. package/pages/support/index.vue +12 -2
  417. package/plugins/clean-html-directive.js +5 -12
  418. package/plugins/clean-tooltip-directive.js +6 -31
  419. package/plugins/codemirror.js +0 -9
  420. package/plugins/dashboard-store/__tests__/mutations.test.ts +296 -313
  421. package/plugins/dashboard-store/actions.js +140 -32
  422. package/plugins/dashboard-store/getters.js +86 -39
  423. package/plugins/dashboard-store/index.js +0 -99
  424. package/plugins/dashboard-store/mutations.js +150 -48
  425. package/plugins/dashboard-store/resource-class.js +14 -109
  426. package/plugins/directives.js +6 -39
  427. package/plugins/ember-cookie.js +13 -0
  428. package/plugins/global-formatters.js +26 -5
  429. package/plugins/i18n.js +90 -56
  430. package/plugins/int-number.js +6 -20
  431. package/plugins/plugin.js +3 -3
  432. package/plugins/positive-int-number.js +6 -17
  433. package/plugins/steve/__tests__/{getters.spec.ts → getters.test.ts} +124 -31
  434. package/plugins/steve/__tests__/mutations.test.ts +49 -0
  435. package/plugins/steve/__tests__/subscribe.spec.ts +109 -0
  436. package/plugins/steve/__tests__/utils/mutation.test.helpers.ts +105 -0
  437. package/plugins/steve/accept-or-reject-socket-message.ts +103 -0
  438. package/plugins/steve/actions.js +0 -1
  439. package/plugins/steve/getters.js +183 -63
  440. package/plugins/steve/hybrid-class.js +5 -1
  441. package/plugins/steve/mutations.js +29 -5
  442. package/plugins/steve/norman-class.js +123 -2
  443. package/{utils → plugins/steve}/projectAndNamespaceFiltering.utils.ts +28 -10
  444. package/plugins/steve/schema.d.ts +22 -0
  445. package/plugins/steve/steve-pagination-utils.ts +368 -0
  446. package/plugins/steve/subscribe.js +37 -75
  447. package/plugins/trim-whitespace.js +6 -34
  448. package/plugins/vue-js-modal.js +1 -1
  449. package/public/index.html +1 -0
  450. package/rancher-components/Accordion/Accordion.vue +3 -2
  451. package/rancher-components/BadgeState/BadgeState.vue +3 -3
  452. package/rancher-components/Banner/Banner.test.ts +1 -5
  453. package/rancher-components/Banner/Banner.vue +2 -2
  454. package/rancher-components/Card/Card.vue +4 -4
  455. package/rancher-components/Form/Checkbox/Checkbox.vue +4 -3
  456. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +1 -1
  457. package/rancher-components/Form/LabeledInput/LabeledInput.vue +66 -30
  458. package/rancher-components/Form/Radio/RadioButton.test.ts +1 -3
  459. package/rancher-components/Form/Radio/RadioButton.vue +13 -7
  460. package/rancher-components/Form/Radio/RadioGroup.vue +4 -3
  461. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
  462. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  463. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
  464. package/rancher-components/StringList/StringList.vue +8 -8
  465. package/rancher-components/components/Accordion/Accordion.vue +3 -2
  466. package/rancher-components/components/BadgeState/BadgeState.vue +3 -3
  467. package/rancher-components/components/Banner/Banner.test.ts +1 -5
  468. package/rancher-components/components/Banner/Banner.vue +2 -2
  469. package/rancher-components/components/Card/Card.vue +4 -4
  470. package/rancher-components/components/Form/Checkbox/Checkbox.vue +4 -3
  471. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +1 -1
  472. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +66 -30
  473. package/rancher-components/components/Form/Radio/RadioButton.test.ts +1 -3
  474. package/rancher-components/components/Form/Radio/RadioButton.vue +13 -7
  475. package/rancher-components/components/Form/Radio/RadioGroup.vue +4 -3
  476. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
  477. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  478. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +9 -4
  479. package/rancher-components/components/StringList/StringList.vue +8 -8
  480. package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +27 -8
  481. package/scripts/clean +1 -1
  482. package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +11 -0
  483. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -0
  484. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  485. package/scripts/extension/helm/package/Dockerfile +1 -1
  486. package/scripts/extension/helm/scripts/patch +27 -0
  487. package/scripts/extension/publish +6 -6
  488. package/scripts/serve-pkgs +0 -2
  489. package/scripts/test-plugins-build.sh +6 -6
  490. package/scripts/vue-migrate.js +683 -0
  491. package/store/__tests__/catalog.test.ts +224 -0
  492. package/store/auth.js +23 -4
  493. package/store/aws.js +53 -6
  494. package/store/catalog.js +21 -5
  495. package/store/cru-resource.ts +26 -0
  496. package/store/customisation.js +35 -0
  497. package/store/features.js +6 -4
  498. package/store/index.js +132 -39
  499. package/store/plugins.js +8 -4
  500. package/store/type-map.js +143 -143
  501. package/store/type-map.utils.ts +226 -0
  502. package/tsconfig.json +0 -1
  503. package/tsconfig.paths.json +4 -1
  504. package/types/components/labeledSelect.ts +50 -0
  505. package/types/resources/settings.d.ts +32 -0
  506. package/types/{userPreferences.d.ts → resources/userPreferences.d.ts} +0 -1
  507. package/types/shell/index.d.ts +996 -782
  508. package/types/store/dashboard-store.types.ts +42 -0
  509. package/types/store/pagination.types.ts +457 -0
  510. package/types/store/type-map.ts +30 -0
  511. package/types/store/vuex.d.ts +9 -0
  512. package/types/vue-shim.d.ts +51 -0
  513. package/utils/__tests__/cluster.test.ts +20 -18
  514. package/utils/__tests__/create-yaml.test.ts +359 -2
  515. package/utils/__tests__/kontainer.test.ts +92 -0
  516. package/utils/__tests__/pod-security-admission.test.ts +1 -1
  517. package/utils/alertmanagerconfig.js +19 -0
  518. package/utils/array.ts +40 -1
  519. package/utils/async.ts +2 -0
  520. package/utils/auth.js +152 -4
  521. package/utils/axios.js +2 -2
  522. package/utils/banners.js +103 -0
  523. package/utils/cluster.js +1 -1
  524. package/utils/config.js +4 -0
  525. package/utils/create-yaml.js +54 -27
  526. package/utils/error.js +25 -0
  527. package/utils/formatter.js +5 -3
  528. package/utils/git.ts +1 -1
  529. package/utils/install-redirect.js +1 -1
  530. package/utils/kontainer.ts +186 -0
  531. package/utils/monitoring.js +2 -37
  532. package/utils/pagination-utils.ts +154 -0
  533. package/utils/pod-security-admission.ts +1 -1
  534. package/utils/router.js +86 -0
  535. package/utils/settings.ts +46 -0
  536. package/utils/socket.js +1 -0
  537. package/utils/time.js +1 -0
  538. package/utils/title.ts +3 -0
  539. package/utils/unit-tests/ChildRenderingRouterLinkStub.ts +36 -0
  540. package/utils/validators/formRules/__tests__/index.test.ts +21 -0
  541. package/utils/validators/formRules/index.ts +3 -0
  542. package/utils/validators/index.js +1 -0
  543. package/vue.config.js +376 -421
  544. package/assets/styles/vendor/vue-js-modal.scss +0 -16
  545. package/chart/monitoring/steps/uninstall-v1.vue +0 -135
  546. package/components/EventsTable.vue +0 -67
  547. package/components/TabbedLinks/index.vue +0 -94
  548. package/components/nuxt/nuxt-link.server.js +0 -16
  549. package/components/nuxt/nuxt.js +0 -101
  550. package/config/router.js +0 -425
  551. package/initialize/App.js +0 -152
  552. package/initialize/client.js +0 -734
  553. package/initialize/index.js +0 -287
  554. package/middleware/i18n.js +0 -10
  555. package/middleware/unauthenticated.js +0 -22
  556. package/mixins/v1-workload-metrics.js +0 -43
  557. package/pages/c/_cluster/apps/index.vue +0 -15
  558. package/pages/c/_cluster/auth/index.vue +0 -17
  559. package/pages/c/_cluster/index.vue +0 -15
  560. package/pages/c/_cluster/legacy/index.vue +0 -22
  561. package/pages/c/_cluster/manager/index.vue +0 -22
  562. package/pages/c/_cluster/mcapps/index.vue +0 -21
  563. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +0 -232
  564. package/plugins/dashboard-store/rehydrate-all.js +0 -44
  565. package/plugins/index.js +0 -11
  566. package/plugins/portal-vue.js +0 -4
  567. package/plugins/portal.js +0 -4
  568. package/plugins/resize.js +0 -5
  569. package/plugins/shortkey.js +0 -4
  570. package/plugins/tooltip.js +0 -4
  571. package/plugins/v-select.js +0 -4
  572. package/utils/group.js +0 -70
  573. package/utils/nuxt.js +0 -638
  574. package/utils/router.scrollBehavior.js +0 -78
  575. /package/components/__tests__/{Collapse.spec.ts → Collapse.test.ts} +0 -0
  576. /package/models/__tests__/{node.ts → node.test.ts} +0 -0
  577. /package/plugins/steve/__tests__/{header-warnings.spec.ts → header-warnings.test.ts} +0 -0
  578. /package/plugins/steve/__tests__/{steve-class.spec.ts → steve-class.test.ts} +0 -0
  579. /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
  580. /package/rancher-components/components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
  581. /package/types/{pod-security-admission.ts → resources/pod-security-admission.ts} +0 -0
@@ -1,9 +1,34 @@
1
1
  import { ANNOTATIONS_TO_IGNORE_REGEX, LABELS_TO_IGNORE_REGEX } from '@shell/config/labels-annotations';
2
2
  import pickBy from 'lodash/pickBy';
3
3
  import Vue from 'vue';
4
- import { matchesSomeRegex } from '@shell/utils/string';
5
- import Resource from '@shell/plugins/dashboard-store/resource-class';
6
4
  import { findBy } from '@shell/utils/array';
5
+ import { matchesSomeRegex, coerceStringTypeToScalarType } from '@shell/utils/string';
6
+ import Resource, { DNS_LIKE_TYPES } from '@shell/plugins/dashboard-store/resource-class';
7
+ import { get } from '@shell/utils/object';
8
+ import {
9
+ displayKeyFor,
10
+ validateBoolean,
11
+ validateChars,
12
+ validateDnsLikeTypes,
13
+ validateLength,
14
+ } from '@shell/utils/validators';
15
+ import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
16
+ import isString from 'lodash/isString';
17
+ import uniq from 'lodash/uniq';
18
+
19
+ import isEmpty from 'lodash/isEmpty';
20
+
21
+ const STRING_LIKE_TYPES = [
22
+ 'string',
23
+ 'date',
24
+ 'blob',
25
+ 'enum',
26
+ 'multiline',
27
+ 'masked',
28
+ 'password',
29
+ 'dnsLabel',
30
+ 'hostname',
31
+ ];
7
32
 
8
33
  export default class NormanModel extends Resource {
9
34
  setLabels(val) {
@@ -75,4 +100,100 @@ export default class NormanModel extends Resource {
75
100
 
76
101
  return (entry.status || '').toLowerCase() === `${ withStatus }`.toLowerCase();
77
102
  }
103
+
104
+ /**
105
+ * Check this instance is valid against
106
+ * - the schema's resource fields
107
+ * - also calls super.validationErrors
108
+ */
109
+ validationErrors(data = this, opt = { ignoreFields: undefined }) {
110
+ const errors = [];
111
+ const {
112
+ type: originalType,
113
+ schema
114
+ } = data;
115
+ const type = normalizeType(originalType);
116
+
117
+ if ( !originalType ) {
118
+ // eslint-disable-next-line
119
+ console.warn(this.t('validation.noType'), data);
120
+
121
+ return errors;
122
+ }
123
+
124
+ if ( !schema ) {
125
+ // eslint-disable-next-line
126
+ // console.warn(this.t('validation.noSchema'), originalType, data);
127
+
128
+ return errors;
129
+ }
130
+
131
+ const fields = schema.resourceFields || {};
132
+ const keys = Object.keys(fields);
133
+ let field, key, val, displayKey;
134
+
135
+ for ( let i = 0 ; i < keys.length ; i++ ) {
136
+ const fieldErrors = [];
137
+
138
+ key = keys[i];
139
+ field = fields[key];
140
+ val = get(data, key);
141
+ displayKey = displayKeyFor(type, key, this.$rootGetters);
142
+
143
+ const fieldType = field?.type ? normalizeType(field.type) : null;
144
+ const valIsString = isString(val);
145
+
146
+ if ( opt.ignoreFields && opt.ignoreFields.includes(key) ) {
147
+ continue;
148
+ }
149
+
150
+ if ( val === undefined ) {
151
+ val = null;
152
+ }
153
+
154
+ if (valIsString) {
155
+ if (fieldType) {
156
+ Vue.set(data, key, coerceStringTypeToScalarType(val, fieldType));
157
+ }
158
+
159
+ // Empty strings on nullable string fields -> null
160
+ if ( field.nullable && val.length === 0 && STRING_LIKE_TYPES.includes(fieldType)) {
161
+ val = null;
162
+
163
+ Vue.set(data, key, val);
164
+ }
165
+ }
166
+ if (fieldType === 'boolean') {
167
+ validateBoolean(val, field, displayKey, this.$rootGetters, fieldErrors);
168
+ } else {
169
+ validateLength(val, field, displayKey, this.$rootGetters, fieldErrors);
170
+ validateChars(val, field, displayKey, this.$rootGetters, fieldErrors);
171
+ }
172
+
173
+ if (fieldErrors.length > 0) {
174
+ fieldErrors.push(this.t('validation.required', { key: displayKey }));
175
+ errors.push(...fieldErrors);
176
+ continue;
177
+ }
178
+
179
+ // IDs claim to be these but are lies...
180
+ if ( key !== 'id' && !isEmpty(val) && DNS_LIKE_TYPES.includes(fieldType) ) {
181
+ // DNS types should be lowercase
182
+ const tolower = (val || '').toLowerCase();
183
+
184
+ if ( tolower !== val ) {
185
+ val = tolower;
186
+
187
+ Vue.set(data, key, val);
188
+ }
189
+
190
+ fieldErrors.push(...validateDnsLikeTypes(val, fieldType, displayKey, this.$rootGetters, fieldErrors));
191
+ }
192
+ errors.push(...fieldErrors);
193
+ }
194
+
195
+ const rootErrors = super.validationErrors(this, opt);
196
+
197
+ return uniq([...errors, ...rootErrors]);
198
+ }
78
199
  }
@@ -1,7 +1,6 @@
1
1
  import { NAMESPACE_FILTER_NS_FULL_PREFIX, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
2
2
  import { getPerformanceSetting } from '@shell/utils/settings';
3
-
4
- type Opt = { [key: string]: any, namespaced?: string[]}
3
+ import { ActionFindAllArgs } from '@shell/types/store/dashboard-store.types';
5
4
 
6
5
  class ProjectAndNamespaceFiltering {
7
6
  static param = 'projectsornamespaces'
@@ -9,7 +8,7 @@ class ProjectAndNamespaceFiltering {
9
8
  /**
10
9
  * Does the request `opt` definition require resources are fetched from a specific set namespaces/projects?
11
10
  */
12
- isApplicable(opt: Opt): boolean {
11
+ isApplicable(opt: ActionFindAllArgs): boolean {
13
12
  return Array.isArray(opt.namespaced);
14
13
  }
15
14
 
@@ -37,7 +36,7 @@ class ProjectAndNamespaceFiltering {
37
36
  /**
38
37
  * Check if `opt` requires resources from specific ns/projects, if so return the required query param (x=y)
39
38
  */
40
- checkAndCreateParam(opt: Opt): string {
39
+ checkAndCreateParam(opt: ActionFindAllArgs): string {
41
40
  if (!this.isApplicable(opt)) {
42
41
  return '';
43
42
  }
@@ -45,17 +44,36 @@ class ProjectAndNamespaceFiltering {
45
44
  return this.createParam(opt.namespaced);
46
45
  }
47
46
 
48
- private createParam(namespaceFilter: string[] | undefined): string {
47
+ public createParam(namespaceFilter: string[] | undefined): string {
49
48
  if (!namespaceFilter || !namespaceFilter.length) {
50
49
  return '';
51
50
  }
52
51
 
53
- const projectsOrNamespaces = namespaceFilter
54
- .map((f) => f.replace(NAMESPACE_FILTER_NS_FULL_PREFIX, '')
55
- .replace(NAMESPACE_FILTER_P_FULL_PREFIX, ''))
56
- .join(',');
52
+ const namespaces = namespaceFilter.reduce((res, n) => {
53
+ const name = n
54
+ .replace(NAMESPACE_FILTER_NS_FULL_PREFIX, '')
55
+ .replace(NAMESPACE_FILTER_P_FULL_PREFIX, '');
56
+
57
+ if (name.startsWith('-')) {
58
+ res.exclude.push(n.substring(1, n.length));
59
+ } else {
60
+ res.include.push(name);
61
+ }
62
+
63
+ return res;
64
+ }, { include: [] as string[], exclude: [] as string[] });
65
+
66
+ let res = '';
67
+
68
+ if (namespaces.include.length) {
69
+ res = `${ ProjectAndNamespaceFiltering.param }=${ namespaces.include.join(',') }`;
70
+ }
71
+
72
+ if (namespaces.exclude.length) {
73
+ res = `${ ProjectAndNamespaceFiltering.param }!=${ namespaces.exclude.join(',') }`;
74
+ }
57
75
 
58
- return `${ ProjectAndNamespaceFiltering.param }=${ projectsOrNamespaces }`;
76
+ return res;
59
77
  }
60
78
  }
61
79
 
@@ -0,0 +1,22 @@
1
+
2
+ export interface SchemaAttributeColumn {
3
+ description: string,
4
+ field: string,
5
+ format: string,
6
+ name: string,
7
+ priority: number,
8
+ type: string,
9
+ }
10
+
11
+ export interface SchemaAttribute {
12
+ columns: SchemaAttributeColumn[],
13
+ namespaced: boolean
14
+ }
15
+
16
+ /**
17
+ * At some point this will be properly typed, until then...
18
+ */
19
+ export interface Schema {
20
+ id: string,
21
+ attributes: SchemaAttribute
22
+ }
@@ -0,0 +1,368 @@
1
+ import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
2
+ import { PaginationParam, PaginationFilterField, PaginationParamProjectOrNamespace, PaginationParamFilter } from '@shell/types/store/pagination.types';
3
+ import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTER_P_FULL_PREFIX } from '@shell/utils/namespace-filter';
4
+ import Namespace from '@shell/models/namespace';
5
+ import { uniq } from '@shell/utils/array';
6
+ import {
7
+ CONFIG_MAP, MANAGEMENT, NAMESPACE, NODE, POD
8
+ } from '@shell/config/types';
9
+ import { Schema } from 'plugins/steve/schema';
10
+
11
+ class NamespaceProjectFilters {
12
+ /**
13
+ * User needs all resources.... except if there's some settings which should remove resources in specific circumstances
14
+ */
15
+ protected handlePrefAndSettingFilter(allNamespaces: Namespace[], showDynamicRancherNamespaces: boolean, productHidesSystemNamespaces: boolean): PaginationParamFilter[] {
16
+ // These are AND'd together
17
+ // Not ns 1 AND ns 2
18
+ return allNamespaces.reduce((res, ns) => {
19
+ // Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
20
+ const hideObscure = showDynamicRancherNamespaces ? false : ns.isObscure;
21
+ // Links to ns.isSystem and covers things like ns with system annotation, hardcoded list, etc
22
+ const hideSystem = productHidesSystemNamespaces ? ns.isSystem : false;
23
+
24
+ if (hideObscure || hideSystem) {
25
+ res.push(PaginationParamFilter.createSingleField({
26
+ field: 'metadata.namespace', value: ns.name, equals: false
27
+ }));
28
+ }
29
+
30
+ return res;
31
+ }, [] as PaginationParamFilter[]);
32
+ }
33
+
34
+ /**
35
+ * User needs either all user resources... or all system
36
+ *
37
+ * System resources revolve around the namespace's isSystem property
38
+ *
39
+ * Users resources are those not in system namespaces
40
+ */
41
+ protected handleSystemOrUserFilter(allNamespaces: Namespace[], isAllSystem: boolean, isAllUser: boolean) {
42
+ const allSystem = allNamespaces.filter((ns) => ns.isSystem);
43
+
44
+ // > Neither of these use projectsOrNamespaces to avoid scenarios where the local cluster provides a namespace which has
45
+ // > a matching project... which could lead to results in the user project resource being included in the system filter
46
+ if (isAllSystem) {
47
+ // return resources in system ns 1 OR in system ns 2 ...
48
+ // &filter=metadata.namespace=system ns 1,metadata.namespace=system ns 2
49
+ return [PaginationParamFilter.createMultipleFields(
50
+ allSystem.map(
51
+ (ns) => new PaginationFilterField({ field: 'metadata.namespace', value: ns.name })
52
+ )
53
+ )];
54
+ } else { // if isAllUser
55
+ // return resources not in system ns 1 AND not in system ns 2 ...
56
+ // &filter=metadata.namespace!=system ns 1&filter=metadata.namespace!=system ns 2
57
+ return allSystem.map((ns) => PaginationParamFilter.createSingleField({
58
+ field: 'metadata.namespace', value: ns.name, equals: false
59
+ }));
60
+ }
61
+ }
62
+
63
+ /**
64
+ * User needs resources in a set of projects or namespaces
65
+ */
66
+ protected handleSelectionFilter(neu: string[], isLocalCluster: boolean) {
67
+ // User has one or more projects or namespaces. We can pass this straight through to projectsornamespaces
68
+
69
+ // return resources in project 1 OR namespace 2
70
+ // &projectsornamespaces=project 1,namespace 2
71
+ const projectsOrNamespaces = [
72
+ new PaginationParamProjectOrNamespace({ projectOrNamespace: neu })
73
+ ];
74
+
75
+ if (isLocalCluster) {
76
+ // > As per `handleSystemOrUserFilter` above, we need to be careful of the local cluster where there's namespaces related to projects with the same id
77
+ // > In this case
78
+ // - We're including resources in the project and it's related namespace (via projectsornamespaces)
79
+ // - We're also then excluding resources in the related namespace (via below `filter`)
80
+
81
+ // Exclude resources NOT in projects namespace 1 AND not in projects namespace 2
82
+ // &filter=metadata.namespace!=pn1&filter=metadata.namespace!=pn2
83
+ return {
84
+ projectsOrNamespaces,
85
+ filters: neu
86
+ .filter((selection) => selection.startsWith(NAMESPACE_FILTER_P_FULL_PREFIX))
87
+ .map((projects) => PaginationParamFilter.createSingleField({
88
+ field: 'metadata.namespace', value: projects.replace(NAMESPACE_FILTER_P_FULL_PREFIX, ''), equals: false
89
+ }))
90
+ };
91
+ }
92
+
93
+ return { projectsOrNamespaces, filters: [] };
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Helper functions for steve pagination
99
+ */
100
+ class StevePaginationUtils extends NamespaceProjectFilters {
101
+ /**
102
+ * Filtering with the vai cache supports specific fields
103
+ * 1) Those listed here
104
+ * 2) Those references in the schema's attributes.fields list (which is used by generic lists)
105
+ */
106
+ static VALID_FIELDS: { [type: string]: { field: string, startsWith?: boolean }[]} = {
107
+ '': [// all types
108
+ { field: 'metadata.name' },
109
+ { field: 'metadata.namespace' },
110
+ // { field: 'id' }, // Pending API support
111
+ // { field: 'metadata.state.name' }, // Pending API support
112
+ { field: 'metadata.creationTimestamp' },
113
+ ],
114
+ [NODE]: [
115
+ { field: 'status.nodeInfo.kubeletVersion' },
116
+ { field: 'status.nodeInfo.operatingSystem' },
117
+ ],
118
+ [POD]: [
119
+ { field: 'spec.containers.image' },
120
+ { field: 'spec.nodeName' },
121
+ ],
122
+ [MANAGEMENT.NODE]: [
123
+ { field: 'status.nodeName' },
124
+ ],
125
+ [CONFIG_MAP]: [
126
+ { field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
127
+ ],
128
+ [NAMESPACE]: [
129
+ { field: 'metadata.labels[field.cattle.io/projectId]' }
130
+ ]
131
+ }
132
+
133
+ private convertArrayPath(path: string): string {
134
+ if (path.startsWith('metadata.fields.')) {
135
+ return `metadata.fields[${ path.substring(16) }]`;
136
+ }
137
+
138
+ return path;
139
+ }
140
+
141
+ public createSortForPagination(sortByPath: string): string {
142
+ return this.convertArrayPath(sortByPath);
143
+ }
144
+
145
+ /**
146
+ * Given the selection of projects or namespaces come up with `filter` and `projectsornamespace` query params
147
+ */
148
+ public createParamsFromNsFilter({
149
+ allNamespaces,
150
+ selection,
151
+ isAllNamespaces,
152
+ isLocalCluster,
153
+ showDynamicRancherNamespaces,
154
+ productHidesSystemNamespaces,
155
+ }: {
156
+ allNamespaces: Namespace[],
157
+ selection: string[],
158
+ /**
159
+ * There is no user provided filter
160
+ */
161
+ isAllNamespaces: boolean,
162
+ /**
163
+ * Weird things be happening if the target cluster is local / upstream. Uses this to check what cluster we're in
164
+ */
165
+ isLocalCluster: boolean,
166
+ /**
167
+ * Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
168
+ */
169
+ showDynamicRancherNamespaces: boolean,
170
+ /**
171
+ * Links to ns.isSystem and covers things like ns with system annotation, hardcoded list, etc
172
+ */
173
+ productHidesSystemNamespaces: boolean,
174
+ }): {
175
+ projectsOrNamespaces: PaginationParamProjectOrNamespace[],
176
+ filters: PaginationParamFilter[]
177
+ } {
178
+ // Hold up, why are we doing yet another way to convert the user's project / namespace filter to a set of something?
179
+ // - When doing this for local pagination `getActiveNamespaces` provides a full list of applicable namespaces.
180
+ // Lists then filter resource locally using those namespaces
181
+ // - Pagination cannot take this approach of 'gimme all resources in these namespaces' primarily for the 'Only User Namespaces' case
182
+ // - User could have 2k namespaces. This would result in 2k+ namespaces added to the url (namespace=1,namespace=2,namespace=3, etc)
183
+ // - Instead we do
184
+ // - All but not given settings - Gimme resources NOT in system or obscure namespaces
185
+ // - Only System Namespaces - Gimme resources in the system namespaces (which shouldn't be many namespaces)
186
+ // - Only User Namespaces - Gimme resources NOT in system namespaces
187
+ // - User selection - Gimme resources in specific Projects or Namespaces
188
+ if (isAllNamespaces && (showDynamicRancherNamespaces && !productHidesSystemNamespaces)) {
189
+ // No-op. Everything is returned
190
+ return {
191
+ projectsOrNamespaces: [],
192
+ filters: []
193
+ };
194
+ }
195
+
196
+ // used to return resources in / not in projects/namespaces (entries are checked in both types)
197
+ // &projectsornamespaces=project 1,namespace 2
198
+ let projectsOrNamespaces: PaginationParamProjectOrNamespace[] = [];
199
+ // used to return resources in / not in namespaces
200
+ // &filter=metadata.namespace=abc
201
+ let filters: PaginationParamFilter[] = [];
202
+
203
+ if (!showDynamicRancherNamespaces || productHidesSystemNamespaces) {
204
+ // We need to hide dynamic namespaces ('c-', 'p-', etc) OR system namespaces
205
+ filters = this.handlePrefAndSettingFilter(allNamespaces, showDynamicRancherNamespaces, productHidesSystemNamespaces);
206
+ }
207
+
208
+ const isAllSystem = selection[0] === NAMESPACE_FILTER_ALL_SYSTEM;
209
+ const isAllUser = selection[0] === NAMESPACE_FILTER_ALL_USER;
210
+
211
+ if (selection.length === 1 && (isAllSystem || isAllUser)) {
212
+ // Filter by resources either in or not in system namespaces
213
+ filters.push(...this.handleSystemOrUserFilter(allNamespaces, isAllSystem, isAllUser ));
214
+ } else {
215
+ // User has one or more projects or namespaces
216
+ const res = this.handleSelectionFilter(selection, isLocalCluster);
217
+
218
+ projectsOrNamespaces = res.projectsOrNamespaces;
219
+ filters.push(...res.filters);
220
+ }
221
+
222
+ return {
223
+ projectsOrNamespaces,
224
+ filters
225
+ };
226
+ }
227
+
228
+ public createParamsForPagination(schema: Schema, opt: ActionFindPageArgs): string | undefined {
229
+ if (!opt.pagination) {
230
+ return;
231
+ }
232
+
233
+ const params: string[] = [];
234
+ const namespaceParam = this.convertPaginationParams(schema, opt.pagination.projectsOrNamespaces);
235
+
236
+ if (namespaceParam) {
237
+ params.push(namespaceParam);
238
+ }
239
+
240
+ if (opt.pagination.page) {
241
+ params.push(`page=${ opt.pagination.page }`);
242
+ }
243
+
244
+ if (opt.pagination.pageSize) {
245
+ params.push(`pagesize=${ opt.pagination.pageSize }`);
246
+ }
247
+
248
+ if (opt.pagination.sort?.length) {
249
+ const validateFields = {
250
+ checked: new Array<string>(),
251
+ invalid: new Array<string>(),
252
+ };
253
+
254
+ const joined = opt.pagination.sort
255
+ .map((s) => {
256
+ this.validateField(validateFields, schema, s.field);
257
+
258
+ return `${ s.asc ? '' : '-' }${ this.convertArrayPath(s.field) }`;
259
+ })
260
+ .join(',');
261
+
262
+ params.push(`sort=${ joined }`);
263
+
264
+ if (validateFields.invalid.length) {
265
+ console.warn(`Pagination API does not support sorting '${ schema.id }' by the requested fields: ${ uniq(validateFields.invalid).join(', ') }`); // eslint-disable-line no-console
266
+ }
267
+ }
268
+
269
+ if (opt.pagination.filters?.length) {
270
+ const filters = this.convertPaginationParams(schema, opt.pagination.filters);
271
+
272
+ if (filters) {
273
+ params.push(filters);
274
+ }
275
+ }
276
+
277
+ // Note - There is a `limit` property that is by default 100,000. This can be disabled by using `limit=-1`,
278
+ // but we shouldn't be fetching any pages big enough to exceed the default
279
+
280
+ return params.join('&');
281
+ }
282
+
283
+ /**
284
+ * Check if the API supports filtering by this field
285
+ */
286
+ private validateField(state: { checked: string[], invalid: string[]}, schema: Schema, field?: string) {
287
+ if (!field) {
288
+ return; // no field, so not invalid
289
+ }
290
+
291
+ if (state.checked.includes(field)) {
292
+ return; // already checked, exit early
293
+ }
294
+
295
+ state.checked.push(field);
296
+
297
+ // First check in our hardcoded list of supported filters
298
+ if ([
299
+ StevePaginationUtils.VALID_FIELDS[''], // Global
300
+ StevePaginationUtils.VALID_FIELDS[schema.id], // Type specific
301
+ ].find((fields) => fields?.find((f) => {
302
+ if (f.startsWith) {
303
+ if (field.startsWith(f.field)) {
304
+ return true;
305
+ }
306
+ } else {
307
+ return field === f.field;
308
+ }
309
+ }))) {
310
+ return;
311
+ }
312
+
313
+ // Then check in schema (the api automatically supports these)
314
+ if (!!schema?.attributes.columns.find(
315
+ // This isn't the most performant, but the string is tiny
316
+ (at) => at.field.replace('$.', '').replace('[', '.').replace(']', '') === field
317
+ )) {
318
+ return;
319
+ }
320
+
321
+ state.invalid.push(field);
322
+ }
323
+
324
+ /**
325
+ * Convert our {@link PaginationParam} definition of params to a set of url params
326
+ */
327
+ private convertPaginationParams(schema: Schema, filters: PaginationParam[] = []): string {
328
+ const validateFields = {
329
+ checked: new Array<string>(),
330
+ invalid: new Array<string>(),
331
+ };
332
+ const filterStrings = filters
333
+ .filter((filter) => !!filter.fields.length)
334
+ .map((filter) => {
335
+ const joined = filter.fields
336
+ .map((field) => {
337
+ if (field.field) {
338
+ // Check if the API supports filtering by this field
339
+ this.validateField(validateFields, schema, field.field);
340
+
341
+ const exactPartial = field.exact ? `'${ field.value }'` : field.value;
342
+
343
+ return `${ this.convertArrayPath(field.field) }${ field.equals ? '=' : '!=' }${ exactPartial }`;
344
+ }
345
+
346
+ return field.value;
347
+ })
348
+ .join(','); // This means OR
349
+
350
+ return `${ filter.param }${ filter.equals ? '=' : '!=' }${ joined }`;
351
+ });
352
+ const unique = filterStrings.reduce((res, s) => {
353
+ res[s] = true;
354
+
355
+ return res;
356
+ }, { } as {[filterString: string] : boolean });
357
+
358
+ const res = Object.keys(unique).join('&'); // This means AND
359
+
360
+ if (validateFields.invalid.length) {
361
+ console.warn(`Pagination API does not support filtering '${ schema.id }' by the requested fields: ${ uniq(validateFields.invalid).join(', ') }`); // eslint-disable-line no-console
362
+ }
363
+
364
+ return res;
365
+ }
366
+ }
367
+
368
+ export default new StevePaginationUtils();