@rancher/shell 3.0.12-rc.1 → 3.0.12-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/apis/impl/apis.ts +6 -0
  2. package/apis/index.ts +26 -0
  3. package/apis/intf/resources-api/cluster-api.ts +18 -0
  4. package/apis/intf/resources-api/mgmt-api.ts +15 -0
  5. package/apis/intf/resources-api/resource-base.ts +107 -0
  6. package/apis/intf/resources-api/resource-constants.ts +147 -0
  7. package/apis/intf/resources-api/resources-api.ts +143 -0
  8. package/apis/intf/resources.ts +49 -0
  9. package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
  10. package/apis/intf/shell-api/proxy.ts +216 -0
  11. package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
  12. package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
  13. package/apis/intf/shell.ts +12 -6
  14. package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
  15. package/apis/resources/index.ts +22 -0
  16. package/apis/resources/resources-api-class.ts +187 -0
  17. package/apis/shell/__tests__/proxy.test.ts +369 -0
  18. package/apis/shell/index.ts +8 -1
  19. package/apis/shell/modal.ts +4 -1
  20. package/apis/shell/notifications.ts +9 -6
  21. package/apis/shell/proxy.ts +256 -0
  22. package/apis/shell/slide-in.ts +4 -1
  23. package/apis/vue-shim.d.ts +2 -1
  24. package/assets/data/aws-regions.json +4 -0
  25. package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
  26. package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
  27. package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
  28. package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
  29. package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
  30. package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
  31. package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
  32. package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
  33. package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
  34. package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
  35. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
  36. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
  37. package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
  38. package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
  39. package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
  40. package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
  41. package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
  42. package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
  43. package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
  44. package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
  45. package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
  46. package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
  47. package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
  48. package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
  49. package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
  50. package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
  51. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
  52. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
  53. package/assets/images/providers/entraid-black.svg +4 -0
  54. package/assets/images/providers/entraid.svg +9 -0
  55. package/assets/images/vendor/entraid.svg +9 -0
  56. package/assets/styles/app.scss +0 -1
  57. package/assets/styles/base/_variables.scss +2 -0
  58. package/assets/styles/fonts/_fontstack.scss +132 -8
  59. package/assets/translations/en-us.yaml +41 -22
  60. package/assets/translations/zh-hans.yaml +4 -8
  61. package/chart/__tests__/S3.test.ts +10 -3
  62. package/chart/monitoring/index.vue +10 -1
  63. package/components/ActionDropdownShell.vue +2 -1
  64. package/components/CountBox.vue +20 -0
  65. package/components/CreateDriver.vue +0 -12
  66. package/components/CruResourceFooter.vue +9 -5
  67. package/components/DetailText.vue +12 -3
  68. package/components/ExplorerProjectsNamespaces.vue +1 -1
  69. package/components/InstallHelmCharts.vue +2 -2
  70. package/components/LandingPagePreference.vue +14 -5
  71. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
  72. package/components/Resource/Detail/Metadata/index.vue +6 -0
  73. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  74. package/components/Resource/Detail/SpacedRow.vue +3 -1
  75. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  76. package/components/ResourceList/Masthead.vue +12 -8
  77. package/components/SelectIconGrid.vue +5 -10
  78. package/components/SingleClusterInfo.vue +1 -0
  79. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  80. package/components/SortableTable/index.vue +6 -9
  81. package/components/SortableTable/selection.js +23 -5
  82. package/components/SortableTable/sorting.js +6 -3
  83. package/components/Wizard.vue +14 -13
  84. package/components/__tests__/CountBox.test.ts +72 -0
  85. package/components/__tests__/DetailText.test.ts +113 -0
  86. package/components/fleet/FleetBundles.vue +100 -12
  87. package/components/fleet/FleetClusterTargets/index.vue +54 -15
  88. package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
  89. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  90. package/components/form/InputWithSelect.vue +18 -10
  91. package/components/form/KeyValue.vue +17 -1
  92. package/components/form/LabeledSelect.vue +101 -26
  93. package/components/form/NameNsDescription.vue +11 -0
  94. package/components/form/Security.vue +6 -2
  95. package/components/form/Select.vue +73 -56
  96. package/components/form/ServiceNameSelect.vue +13 -11
  97. package/components/form/WorkloadPorts.vue +2 -7
  98. package/components/form/__tests__/KeyValue.test.ts +66 -0
  99. package/components/form/__tests__/NodeScheduling.test.ts +9 -0
  100. package/components/form/__tests__/Security.test.ts +76 -0
  101. package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
  102. package/components/formatter/Autoscaler.vue +4 -4
  103. package/components/formatter/ClusterKubeVersion.vue +27 -0
  104. package/components/formatter/ClusterLink.vue +1 -7
  105. package/components/formatter/ClusterProvider.vue +6 -10
  106. package/components/formatter/FleetSummaryGraph.vue +0 -3
  107. package/components/formatter/MachineSummaryGraph.vue +1 -1
  108. package/components/formatter/PodsUsage.vue +2 -2
  109. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  110. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  111. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  112. package/components/nav/Group.vue +7 -6
  113. package/components/nav/Header.vue +24 -3
  114. package/components/nav/NamespaceFilter.vue +2 -2
  115. package/components/nav/NotificationCenter/Notification.vue +4 -1
  116. package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
  117. package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
  118. package/components/nav/TopLevelMenu.helper.ts +15 -3
  119. package/components/nav/TopLevelMenu.vue +16 -5
  120. package/components/nav/Type.vue +8 -7
  121. package/components/nav/WindowManager/index.vue +2 -1
  122. package/components/nav/WorkspaceSwitcher.vue +13 -0
  123. package/components/nav/__tests__/Group.test.ts +67 -0
  124. package/components/nav/__tests__/Header.test.ts +235 -0
  125. package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
  126. package/components/nav/__tests__/Type.test.ts +20 -3
  127. package/components/templates/default.vue +34 -4
  128. package/components/templates/home.vue +30 -25
  129. package/components/templates/plain.vue +31 -26
  130. package/components/templates/standalone.vue +17 -0
  131. package/composables/useFormValidation.ts +93 -0
  132. package/composables/useLabeledFormElement.ts +10 -2
  133. package/composables/useLabeledSelect.ts +60 -0
  134. package/composables/useUserRetentionValidation.ts +1 -49
  135. package/composables/useVeeValidateField.test.ts +159 -0
  136. package/composables/useVeeValidateField.ts +67 -0
  137. package/config/cookies.js +0 -1
  138. package/config/labels-annotations.js +1 -0
  139. package/config/pagination-table-headers.js +18 -1
  140. package/config/product/manager.js +82 -21
  141. package/config/query-params.js +1 -0
  142. package/config/router/routes.js +6 -8
  143. package/config/table-headers.js +20 -1
  144. package/config/types.js +2 -1
  145. package/core/__tests__/plugin-products.test.ts +1505 -30
  146. package/core/plugin-products-base.ts +137 -20
  147. package/core/plugin-products-helpers.ts +5 -4
  148. package/core/plugin-products.ts +4 -0
  149. package/core/plugin-types.ts +129 -4
  150. package/core/plugin.ts +15 -7
  151. package/core/productDebugger.js +9 -4
  152. package/core/types-provisioning.ts +43 -30
  153. package/core/types.ts +58 -19
  154. package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
  155. package/detail/__tests__/pod.test.ts +41 -0
  156. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  157. package/detail/management.cattle.io.fleetworkspace.vue +49 -0
  158. package/detail/pod.vue +1 -1
  159. package/detail/provisioning.cattle.io.cluster.vue +4 -10
  160. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
  161. package/edit/__tests__/kontainerDriver.test.ts +0 -13
  162. package/edit/__tests__/nodeDriver.test.ts +5 -11
  163. package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
  164. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  165. package/edit/auth/__tests__/azuread.test.ts +217 -34
  166. package/edit/auth/__tests__/oidc.test.ts +54 -0
  167. package/edit/auth/azuread.vue +123 -15
  168. package/edit/auth/oidc.vue +10 -2
  169. package/edit/kontainerDriver.vue +1 -2
  170. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  171. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  172. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  173. package/edit/nodeDriver.vue +0 -2
  174. package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
  175. package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
  176. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  177. package/edit/provisioning.cattle.io.cluster/index.vue +81 -106
  178. package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
  179. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
  180. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  181. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  182. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  183. package/edit/secret/__tests__/ssh.test.ts +5 -6
  184. package/edit/secret/basic.vue +31 -0
  185. package/edit/secret/index.vue +68 -17
  186. package/edit/secret/registry.vue +38 -0
  187. package/edit/secret/ssh.vue +29 -0
  188. package/edit/secret/tls.vue +30 -0
  189. package/edit/service.vue +4 -4
  190. package/edit/workload/Upgrading.vue +3 -3
  191. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  192. package/edit/workload/mixins/workload.js +2 -1
  193. package/initialize/App.vue +29 -2
  194. package/initialize/install-plugins.js +0 -2
  195. package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
  196. package/list/catalog.cattle.io.app.vue +25 -5
  197. package/list/fleet.cattle.io.bundle.vue +7 -104
  198. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  199. package/list/management.cattle.io.feature.vue +1 -1
  200. package/list/management.cattle.io.fleetworkspace.vue +8 -0
  201. package/list/provisioning.cattle.io.cluster.vue +262 -180
  202. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  203. package/machine-config/amazonec2.vue +1 -0
  204. package/mixins/__tests__/chart.test.ts +112 -0
  205. package/mixins/brand.js +2 -1
  206. package/mixins/chart.js +50 -15
  207. package/mixins/resource-fetch-api-pagination.js +41 -5
  208. package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
  209. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
  210. package/models/__tests__/chart.test.ts +99 -6
  211. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  212. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  213. package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
  214. package/models/__tests__/management.cattle.io.node.ts +6 -5
  215. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  216. package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
  217. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
  218. package/models/base-cluster.x-k8s.io.js +26 -0
  219. package/models/catalog.cattle.io.app.js +21 -17
  220. package/models/catalog.cattle.io.clusterrepo.js +39 -11
  221. package/models/chart.js +33 -19
  222. package/models/cluster.js +1 -1
  223. package/models/cluster.x-k8s.io.machine.js +4 -22
  224. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  225. package/models/cluster.x-k8s.io.machineset.js +2 -20
  226. package/models/compliance.cattle.io.clusterscan.js +130 -2
  227. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  228. package/models/fleet-application.js +4 -2
  229. package/models/fleet.cattle.io.bundle.js +1 -1
  230. package/models/kontainerdriver.js +11 -0
  231. package/models/management.cattle.io.authconfig.js +5 -1
  232. package/models/management.cattle.io.cluster.js +402 -78
  233. package/models/management.cattle.io.feature.js +3 -3
  234. package/models/management.cattle.io.kontainerdriver.js +1 -26
  235. package/models/management.cattle.io.node.js +6 -4
  236. package/models/management.cattle.io.nodepool.js +1 -1
  237. package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
  238. package/models/networking.k8s.io.ingress.js +12 -4
  239. package/models/nodedriver.js +7 -0
  240. package/models/provisioning.cattle.io.cluster.js +47 -330
  241. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  242. package/package.json +20 -37
  243. package/pages/__tests__/readme.test.ts +49 -0
  244. package/pages/auth/setup.vue +2 -3
  245. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +265 -0
  246. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
  247. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
  248. package/pages/c/_cluster/apps/charts/chart.vue +275 -39
  249. package/pages/c/_cluster/apps/charts/index.vue +2 -2
  250. package/pages/c/_cluster/apps/charts/install.vue +18 -10
  251. package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
  252. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  253. package/pages/c/_cluster/explorer/index.vue +5 -49
  254. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  255. package/pages/c/_cluster/istio/index.vue +21 -6
  256. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
  257. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +40 -2
  258. package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
  259. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +735 -13
  260. package/pages/c/_cluster/uiplugins/index.vue +226 -222
  261. package/pages/diagnostic.vue +13 -17
  262. package/pages/fail-whale.vue +18 -0
  263. package/pages/home.vue +77 -260
  264. package/pages/readme.vue +88 -0
  265. package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
  266. package/plugins/dashboard-store/actions.js +40 -18
  267. package/plugins/dashboard-store/resource-class.js +5 -2
  268. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  269. package/plugins/steve/steve-pagination-utils.ts +11 -3
  270. package/plugins/steve/subscribe.js +35 -5
  271. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +211 -1
  272. package/rancher-components/Form/LabeledInput/LabeledInput.vue +37 -4
  273. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
  274. package/rancher-components/RcButton/RcButton.test.ts +37 -1
  275. package/rancher-components/RcButton/RcButton.vue +38 -8
  276. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  277. package/scripts/test-plugins-build.sh +5 -2
  278. package/server/server-middleware.js +2 -2
  279. package/static/humans.txt +1 -0
  280. package/static/robots.txt +34 -0
  281. package/static/welcome-cow.svg +18 -0
  282. package/store/__tests__/catalog.test.ts +276 -12
  283. package/store/__tests__/type-map.test.ts +556 -1
  284. package/store/action-menu.js +8 -3
  285. package/store/auth.js +1 -4
  286. package/store/aws.js +27 -16
  287. package/store/catalog.js +87 -11
  288. package/store/digitalocean.js +20 -38
  289. package/store/index.js +2 -0
  290. package/store/linode.js +25 -40
  291. package/store/pnap.js +1 -0
  292. package/store/type-map.js +111 -29
  293. package/tsconfig.paths.json +8 -8
  294. package/types/kube/kube-api.ts +14 -1
  295. package/types/rancher/steve.api.ts +12 -12
  296. package/types/resources/settings.d.ts +2 -1
  297. package/types/shell/index.d.ts +128 -24
  298. package/types/store/dashboard-store.types.ts +108 -11
  299. package/types/store/pagination.types.ts +6 -3
  300. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  301. package/utils/__tests__/async.test.ts +87 -0
  302. package/utils/__tests__/aws.test.ts +140 -0
  303. package/utils/__tests__/banners.test.ts +176 -0
  304. package/utils/__tests__/chart.test.ts +64 -1
  305. package/utils/__tests__/color.test.ts +226 -0
  306. package/utils/__tests__/duration.test.ts +140 -0
  307. package/utils/__tests__/fleet.test.ts +340 -0
  308. package/utils/__tests__/git.test.ts +270 -0
  309. package/utils/__tests__/inactivity.test.ts +316 -0
  310. package/utils/__tests__/ingress.test.ts +553 -0
  311. package/utils/__tests__/kube.test.ts +68 -0
  312. package/utils/__tests__/namespace-filter.test.ts +109 -0
  313. package/utils/__tests__/object.test.ts +77 -0
  314. package/utils/__tests__/pagination-utils.test.ts +361 -0
  315. package/utils/__tests__/parse-externalid.test.ts +137 -0
  316. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  317. package/utils/__tests__/poller-sequential.test.ts +177 -0
  318. package/utils/__tests__/poller.test.ts +170 -0
  319. package/utils/__tests__/promise.test.ts +346 -0
  320. package/utils/__tests__/settings.test.ts +140 -0
  321. package/utils/__tests__/sort-utils.test.ts +301 -0
  322. package/utils/__tests__/string-utils.test.ts +798 -0
  323. package/utils/__tests__/string.test.ts +23 -1
  324. package/utils/__tests__/style.test.ts +154 -0
  325. package/utils/__tests__/svg-filter.test.ts +184 -0
  326. package/utils/__tests__/time.test.ts +14 -1
  327. package/utils/__tests__/units.test.ts +417 -0
  328. package/utils/__tests__/url.test.ts +246 -0
  329. package/utils/__tests__/versions.test.ts +128 -0
  330. package/utils/__tests__/xccdf.test.ts +391 -0
  331. package/utils/chart.js +36 -0
  332. package/utils/fleet.ts +13 -3
  333. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  334. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  335. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  336. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  337. package/utils/gc/__tests__/gc.test.ts +487 -0
  338. package/utils/ingress.ts +9 -1
  339. package/utils/object.js +33 -2
  340. package/utils/pagination-utils.ts +2 -1
  341. package/utils/string.js +25 -2
  342. package/utils/time.ts +5 -0
  343. package/utils/uiplugins.ts +5 -5
  344. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  345. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  346. package/utils/validators/__tests__/index.test.ts +481 -0
  347. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  348. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  349. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  350. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  351. package/utils/validators/__tests__/role-template.test.ts +149 -0
  352. package/utils/validators/__tests__/service.test.ts +283 -0
  353. package/utils/validators/__tests__/setting.test.js +32 -0
  354. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  355. package/utils/validators/formRules/index.ts +5 -5
  356. package/utils/validators/machine-pool.ts +1 -1
  357. package/utils/validators/setting.js +18 -3
  358. package/utils/xccdf.ts +418 -0
  359. package/vue.config.js +0 -9
  360. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  361. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  362. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  363. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
  364. package/assets/images/providers/azuread-black.svg +0 -22
  365. package/assets/images/providers/azuread.svg +0 -25
  366. package/assets/images/vendor/azuread.svg +0 -18
  367. package/assets/styles/fonts/_dots.scss +0 -18
  368. package/components/EmberPage.vue +0 -622
  369. package/components/EmberPageView.vue +0 -39
  370. package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
  371. package/mixins/labeled-form-element.ts +0 -225
  372. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
  373. package/pages/c/_cluster/manager/pages/_page.vue +0 -22
  374. package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
  375. package/plugins/ember-cookie.js +0 -17
  376. package/utils/ember-page.js +0 -30
@@ -0,0 +1,487 @@
1
+ import type defaultGc from '@shell/utils/gc/gc';
2
+ import { MANAGEMENT } from '@shell/config/types';
3
+
4
+ type GcInstance = typeof defaultGc;
5
+
6
+ const DEFAULT_PREFS = {
7
+ enabled: true,
8
+ enabledInterval: true,
9
+ interval: 300,
10
+ enabledOnNavigate: true,
11
+ ageThreshold: 120, // seconds → maxAge = 120_000 ms
12
+ countThreshold: 500,
13
+ };
14
+
15
+ let stampCounter = 1000;
16
+
17
+ function makeRootState(prefs = DEFAULT_PREFS, clusterReady = true): any {
18
+ stampCounter++;
19
+
20
+ return {
21
+ clusterReady,
22
+ management: {
23
+ types: {
24
+ [MANAGEMENT.SETTING]: {
25
+ list: [
26
+ {
27
+ id: 'ui-performance',
28
+ value: JSON.stringify({ garbageCollection: prefs }),
29
+ metadata: { generation: stampCounter, resourceVersion: '1' },
30
+ },
31
+ ],
32
+ },
33
+ },
34
+ },
35
+ };
36
+ }
37
+
38
+ function makeEmptyRootState(): any {
39
+ return {
40
+ clusterReady: true,
41
+ management: { types: { [MANAGEMENT.SETTING]: { list: [] } } },
42
+ };
43
+ }
44
+
45
+ function makeCtx(options: {
46
+ namespace?: string;
47
+ supportsGc?: boolean;
48
+ gcIgnoreTypes?: Record<string, boolean>;
49
+ prefs?: Partial<typeof DEFAULT_PREFS>;
50
+ dispatch?: jest.Mock;
51
+ countsByType?: Record<string, number>;
52
+ clusterReady?: boolean;
53
+ } = {}): any {
54
+ const {
55
+ namespace = 'teststore',
56
+ supportsGc = true,
57
+ gcIgnoreTypes = {},
58
+ prefs,
59
+ dispatch = jest.fn(),
60
+ countsByType = {},
61
+ clusterReady = true,
62
+ } = options;
63
+
64
+ const rootState = makeRootState(
65
+ prefs ? { ...DEFAULT_PREFS, ...prefs } : DEFAULT_PREFS,
66
+ clusterReady
67
+ );
68
+
69
+ return {
70
+ state: { config: { supportsGc, namespace } },
71
+ rootState,
72
+ getters: {
73
+ gcIgnoreTypes,
74
+ all: () => [{
75
+ counts: Object.fromEntries(
76
+ Object.entries(countsByType).map(([t, c]) => [t, { summary: { count: c } }])
77
+ ),
78
+ }],
79
+ },
80
+ dispatch,
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Each test in the outer describe gets a fresh gc instance (gcLastRun = 0,
86
+ * empty caches) so tests do not interfere with each other via shared singleton state.
87
+ */
88
+ describe('gc', () => {
89
+ let gc: GcInstance;
90
+
91
+ beforeEach(() => {
92
+ jest.resetModules();
93
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
94
+ gc = require('@shell/utils/gc/gc').default as GcInstance;
95
+ });
96
+
97
+ afterEach(() => {
98
+ jest.useRealTimers();
99
+ });
100
+
101
+ // ─── gcEnabledForStore ─────────────────────────────────────────────────────
102
+
103
+ describe('gcEnabledForStore', () => {
104
+ it.each([
105
+ {
106
+ desc: 'true when supportsGc is true', state: { config: { supportsGc: true } }, expected: true
107
+ },
108
+ {
109
+ desc: 'false when supportsGc is false', state: { config: { supportsGc: false } }, expected: false
110
+ },
111
+ {
112
+ desc: 'undefined when state is undefined', state: undefined, expected: undefined
113
+ },
114
+ ])('returns $desc', ({ state, expected }) => {
115
+ expect(gc.gcEnabledForStore(state)).toBe(expected);
116
+ });
117
+ });
118
+
119
+ // ─── gcEnabledForType ──────────────────────────────────────────────────────
120
+
121
+ describe('gcEnabledForType', () => {
122
+ it.each([
123
+ {
124
+ desc: 'false when type is empty string', gcIgnoreTypes: {}, type: '', expected: false
125
+ },
126
+ {
127
+ desc: 'false when type is in gcIgnoreTypes', gcIgnoreTypes: { pods: true }, type: 'pods', expected: false
128
+ },
129
+ {
130
+ desc: 'true when type is non-empty and not ignored', gcIgnoreTypes: {}, type: 'deployments', expected: true
131
+ },
132
+ ])('returns $desc', ({ gcIgnoreTypes, type, expected }) => {
133
+ expect(gc.gcEnabledForType({ getters: { gcIgnoreTypes } }, type)).toBe(expected);
134
+ });
135
+ });
136
+
137
+ // ─── gcEnabledSetting ──────────────────────────────────────────────────────
138
+
139
+ describe('gcEnabledSetting', () => {
140
+ it('returns true when GC is enabled in ui-performance setting', () => {
141
+ const ctx = { rootState: makeRootState({ ...DEFAULT_PREFS, enabled: true }) };
142
+
143
+ expect(gc.gcEnabledSetting(ctx)).toBe(true);
144
+ });
145
+
146
+ it('returns false when GC is disabled in ui-performance setting', () => {
147
+ const ctx = { rootState: makeRootState({ ...DEFAULT_PREFS, enabled: false }) };
148
+
149
+ expect(gc.gcEnabledSetting(ctx)).toBe(false);
150
+ });
151
+
152
+ it('returns undefined when ui-performance setting is absent', () => {
153
+ const ctx = { rootState: makeEmptyRootState() };
154
+
155
+ expect(gc.gcEnabledSetting(ctx)).toBeUndefined();
156
+ });
157
+ });
158
+
159
+ // ─── gcEnabledAll ──────────────────────────────────────────────────────────
160
+
161
+ describe('gcEnabledAll', () => {
162
+ it.each([
163
+ {
164
+ desc: 'true when all checks pass', options: {}, type: 'deployments', expected: true
165
+ },
166
+ {
167
+ desc: 'false when store does not support GC', options: { supportsGc: false }, type: 'deployments', expected: false
168
+ },
169
+ {
170
+ desc: 'false when GC is disabled in settings', options: { prefs: { enabled: false } }, type: 'deployments', expected: false
171
+ },
172
+ {
173
+ desc: 'false when type is in gcIgnoreTypes', options: { gcIgnoreTypes: { schema: true } }, type: 'schema', expected: false
174
+ },
175
+ ])('returns $desc', ({ options, type, expected }) => {
176
+ expect(gc.gcEnabledAll(makeCtx(options), type)).toBe(expected);
177
+ });
178
+ });
179
+
180
+ // ─── gcEnabledInterval ─────────────────────────────────────────────────────
181
+
182
+ describe('gcEnabledInterval', () => {
183
+ it('returns enabledInterval and interval from settings', () => {
184
+ const ctx = {
185
+ rootState: makeRootState({
186
+ ...DEFAULT_PREFS, enabledInterval: true, interval: 600
187
+ })
188
+ };
189
+
190
+ expect(gc.gcEnabledInterval(ctx)).toStrictEqual({ enabled: true, interval: 600 });
191
+ });
192
+
193
+ it('returns enabled: undefined and interval: 0 when setting is absent', () => {
194
+ const ctx = { rootState: makeEmptyRootState() };
195
+
196
+ expect(gc.gcEnabledInterval(ctx)).toStrictEqual({ enabled: undefined, interval: 0 });
197
+ });
198
+
199
+ it('returns interval: 0 when the interval value is falsy', () => {
200
+ const ctx = { rootState: makeRootState({ ...DEFAULT_PREFS, interval: 0 }) };
201
+
202
+ expect(gc.gcEnabledInterval(ctx)).toStrictEqual({ enabled: true, interval: 0 });
203
+ });
204
+ });
205
+
206
+ // ─── gcEnabledRoute ────────────────────────────────────────────────────────
207
+
208
+ describe('gcEnabledRoute', () => {
209
+ it('returns enabledOnNavigate from settings', () => {
210
+ const ctx = { rootState: makeRootState({ ...DEFAULT_PREFS, enabledOnNavigate: false }) };
211
+
212
+ expect(gc.gcEnabledRoute(ctx)).toBe(false);
213
+ });
214
+
215
+ it('returns undefined when setting is absent', () => {
216
+ const ctx = { rootState: makeEmptyRootState() };
217
+
218
+ expect(gc.gcEnabledRoute(ctx)).toBeUndefined();
219
+ });
220
+ });
221
+
222
+ // ─── gcUpdateRouteChanged ──────────────────────────────────────────────────
223
+
224
+ describe('gcUpdateRouteChanged', () => {
225
+ /**
226
+ * Condition in garbageCollect:
227
+ * if (lastRouteChange < lastAccessed) → skip (resource is in current route)
228
+ *
229
+ * So: route changed at T1, resource accessed at T2 > T1
230
+ * → lastRouteChange (T1) < lastAccessed (T2) → GC skips this type.
231
+ */
232
+ it('prevents a resource from being GC\'d when route changed before last access', () => {
233
+ const dispatch = jest.fn();
234
+ const type = 'pods';
235
+ const namespace = 'routetest';
236
+
237
+ jest.useFakeTimers();
238
+
239
+ // Route change at t=200_000 ms
240
+ jest.setSystemTime(200_000);
241
+ gc.gcUpdateRouteChanged();
242
+
243
+ // Resource accessed at t=300_000 ms (AFTER route change → in current route)
244
+ jest.setSystemTime(300_000);
245
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
246
+
247
+ // GC runs at t=600_000 ms
248
+ // now - lastAccessed = 300_000 > maxAge(120_000) ✓ age check passes
249
+ // lastRouteChange(200_000) < lastAccessed(300_000) → skip (in current route)
250
+ jest.setSystemTime(600_000);
251
+ gc.garbageCollect(makeCtx({
252
+ namespace,
253
+ countsByType: { [type]: 1000 },
254
+ dispatch,
255
+ }));
256
+
257
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
258
+ });
259
+ });
260
+
261
+ // ─── garbageCollect ────────────────────────────────────────────────────────
262
+
263
+ describe('garbageCollect', () => {
264
+ it('skips when recently run (within GC_RE_RUN_GAP of 5 s)', () => {
265
+ const dispatch = jest.fn();
266
+
267
+ jest.useFakeTimers();
268
+ jest.setSystemTime(10_000);
269
+
270
+ // First call: cluster not ready → gcLastRun = 10_000
271
+ gc.garbageCollect(makeCtx({ clusterReady: false, dispatch }));
272
+ // Second call at same time: 10_000 - 10_000 = 0 < 5000 → skips
273
+ gc.garbageCollect(makeCtx({ dispatch }));
274
+
275
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', expect.any(String));
276
+ });
277
+
278
+ it('skips when cluster is not ready', () => {
279
+ const dispatch = jest.fn();
280
+
281
+ jest.useFakeTimers();
282
+ jest.setSystemTime(10_000);
283
+
284
+ gc.garbageCollect(makeCtx({ clusterReady: false, dispatch }));
285
+
286
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', expect.any(String));
287
+ });
288
+
289
+ it('skips when ui-performance setting is absent', () => {
290
+ const dispatch = jest.fn();
291
+
292
+ jest.useFakeTimers();
293
+ jest.setSystemTime(10_000);
294
+
295
+ const ctx = {
296
+ state: { config: { supportsGc: true, namespace: 'teststore' } },
297
+ rootState: makeEmptyRootState(),
298
+ getters: { gcIgnoreTypes: {} },
299
+ dispatch,
300
+ };
301
+
302
+ gc.garbageCollect(ctx);
303
+
304
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', expect.any(String));
305
+ });
306
+
307
+ it('skips a type listed in the explicit ignoreTypes parameter', () => {
308
+ const dispatch = jest.fn();
309
+ const type = 'configmaps';
310
+ const namespace = 'ignoretypetest';
311
+
312
+ jest.useFakeTimers();
313
+
314
+ jest.setSystemTime(200_000);
315
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
316
+
317
+ jest.setSystemTime(300_000);
318
+ gc.gcUpdateRouteChanged();
319
+
320
+ jest.setSystemTime(400_000);
321
+ gc.garbageCollect(
322
+ makeCtx({
323
+ namespace, countsByType: { [type]: 1000 }, dispatch
324
+ }),
325
+ { [type]: true }
326
+ );
327
+
328
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
329
+ });
330
+
331
+ it('skips a type that was accessed within the ageThreshold', () => {
332
+ const dispatch = jest.fn();
333
+ const type = 'secrets';
334
+ const namespace = 'recenttest';
335
+
336
+ jest.useFakeTimers();
337
+
338
+ // Access 30 s ago (less than 120 s ageThreshold)
339
+ jest.setSystemTime(10_000);
340
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
341
+
342
+ jest.setSystemTime(40_000); // 30 s later
343
+ gc.garbageCollect(makeCtx({
344
+ namespace, countsByType: { [type]: 1000 }, dispatch
345
+ }));
346
+
347
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
348
+ });
349
+
350
+ it('skips a type whose count is below countThreshold', () => {
351
+ const dispatch = jest.fn();
352
+ const type = 'namespaces';
353
+ const namespace = 'lowcounttest';
354
+
355
+ jest.useFakeTimers();
356
+
357
+ jest.setSystemTime(200_000);
358
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
359
+
360
+ jest.setSystemTime(300_000);
361
+ gc.gcUpdateRouteChanged();
362
+
363
+ jest.setSystemTime(400_000);
364
+ // count(100) < countThreshold(500) → skip
365
+ gc.garbageCollect(makeCtx({
366
+ namespace, countsByType: { [type]: 100 }, dispatch
367
+ }));
368
+
369
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
370
+ });
371
+
372
+ it('dispatches forgetType for a resource that meets all GC criteria', () => {
373
+ const dispatch = jest.fn();
374
+ const type = 'events';
375
+ const namespace = 'gcqualifytest';
376
+
377
+ jest.useFakeTimers();
378
+
379
+ // Resource accessed at t=200_000
380
+ jest.setSystemTime(200_000);
381
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
382
+
383
+ // Route changed at t=300_000 (AFTER access → lastRouteChange > lastAccessed → no skip)
384
+ jest.setSystemTime(300_000);
385
+ gc.gcUpdateRouteChanged();
386
+
387
+ // GC at t=400_000: now - lastAccessed = 200_000 > maxAge(120_000) ✓
388
+ jest.setSystemTime(400_000);
389
+ gc.garbageCollect(makeCtx({
390
+ namespace, countsByType: { [type]: 1000 }, dispatch
391
+ }));
392
+
393
+ expect(dispatch).toHaveBeenCalledWith('forgetType', type);
394
+ });
395
+ });
396
+
397
+ // ─── gcResetStore ──────────────────────────────────────────────────────────
398
+
399
+ describe('gcResetStore', () => {
400
+ it('removes all cached entries for the store, preventing forgetType dispatch', () => {
401
+ const dispatch = jest.fn();
402
+ const type = 'ingresses';
403
+ const namespace = 'resetstoretest';
404
+
405
+ jest.useFakeTimers();
406
+
407
+ jest.setSystemTime(200_000);
408
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), type);
409
+
410
+ jest.setSystemTime(300_000);
411
+ gc.gcUpdateRouteChanged();
412
+
413
+ gc.gcResetStore({ config: { namespace } });
414
+
415
+ jest.setSystemTime(400_000);
416
+ gc.garbageCollect(makeCtx({
417
+ namespace, countsByType: { [type]: 1000 }, dispatch
418
+ }));
419
+
420
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
421
+ });
422
+ });
423
+
424
+ // ─── gcResetType ───────────────────────────────────────────────────────────
425
+
426
+ describe('gcResetType', () => {
427
+ it('removes a specific type so it is not GC\'d while leaving other types intact', () => {
428
+ const dispatch = jest.fn();
429
+ const typeA = 'storageclasses';
430
+ const typeB = 'persistentvolumes';
431
+ const namespace = 'resettypetest';
432
+
433
+ jest.useFakeTimers();
434
+
435
+ jest.setSystemTime(200_000);
436
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), typeA);
437
+ gc.gcUpdateLastAccessed(makeCtx({ namespace }), typeB);
438
+
439
+ jest.setSystemTime(300_000);
440
+ gc.gcUpdateRouteChanged();
441
+
442
+ gc.gcResetType({ config: { namespace } }, typeA);
443
+
444
+ jest.setSystemTime(400_000);
445
+ gc.garbageCollect(makeCtx({
446
+ namespace,
447
+ countsByType: { [typeA]: 1000, [typeB]: 1000 },
448
+ dispatch,
449
+ }));
450
+
451
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', typeA);
452
+ expect(dispatch).toHaveBeenCalledWith('forgetType', typeB);
453
+ });
454
+
455
+ it('is a no-op when the store has no cached entries', () => {
456
+ expect(() => {
457
+ gc.gcResetType({ config: { namespace: 'nonexistent-store' } }, 'pods');
458
+ }).not.toThrow();
459
+ });
460
+ });
461
+
462
+ // ─── gcUpdateLastAccessed ──────────────────────────────────────────────────
463
+
464
+ describe('gcUpdateLastAccessed', () => {
465
+ it('does not populate cache when GC is disabled for the store', () => {
466
+ const dispatch = jest.fn();
467
+ const type = 'replicasets';
468
+ const namespace = 'disabledgctest';
469
+
470
+ jest.useFakeTimers();
471
+
472
+ // supportsGc: false → gcEnabledAll = false → cache not updated
473
+ jest.setSystemTime(200_000);
474
+ gc.gcUpdateLastAccessed(makeCtx({ namespace, supportsGc: false }), type);
475
+
476
+ jest.setSystemTime(300_000);
477
+ gc.gcUpdateRouteChanged();
478
+
479
+ jest.setSystemTime(400_000);
480
+ gc.garbageCollect(makeCtx({
481
+ namespace, countsByType: { [type]: 1000 }, dispatch
482
+ }));
483
+
484
+ expect(dispatch).not.toHaveBeenCalledWith('forgetType', type);
485
+ });
486
+ });
487
+ });
package/utils/ingress.ts CHANGED
@@ -56,7 +56,15 @@ class IngressDetailEditHelper {
56
56
  return services.map((service) => ({
57
57
  label: service.metadata.name,
58
58
  value: service.metadata.name,
59
- ports: service.spec.ports?.map((p: any) => p.port)
59
+ ports: service.spec.ports?.flatMap((p: any) => {
60
+ const options = [p.port];
61
+
62
+ if (p.name) {
63
+ options.push(p.name);
64
+ }
65
+
66
+ return options;
67
+ })
60
68
  }));
61
69
  }
62
70
  }
package/utils/object.js CHANGED
@@ -220,8 +220,14 @@ export function diff(from, to, preventNull = false) {
220
220
  if ( Array.isArray(toVal) || Array.isArray(fromVal) ) {
221
221
  // Don't diff arrays, just use the whole value
222
222
  res[k] = toVal;
223
- } else if ( isObject(toVal) && isObject(from[k]) ) {
224
- res[k] = diff(fromVal, toVal);
223
+ } else if ( isObject(toVal) && isObject(fromVal) ) {
224
+ const nested = diff(fromVal, toVal, preventNull);
225
+
226
+ if (isEmpty(toVal) && !isEmpty(fromVal)) {
227
+ res[k] = {};
228
+ } else if (!isEmpty(nested)) {
229
+ res[k] = nested;
230
+ }
225
231
  } else {
226
232
  res[k] = toVal;
227
233
  }
@@ -235,6 +241,31 @@ export function diff(from, to, preventNull = false) {
235
241
 
236
242
  for ( const k of missing ) {
237
243
  // we need to gate this in order to prevent unforseen problems with addonConfig
244
+ const hasDescendant = toKeys.some(
245
+ (tk) => tk.startsWith(`${ k }.`)
246
+ );
247
+
248
+ if (hasDescendant) {
249
+ continue;
250
+ }
251
+
252
+ // If we already have a value in 'out' for any parent of this missing key, do NOT nullify the child.
253
+ const parts = splitObjectPath(k);
254
+ let hasUpdatedParent = false;
255
+
256
+ for (let i = 1; i < parts.length; i++) {
257
+ const parentPath = joinObjectPath(parts.slice(0, i));
258
+
259
+ if (get(out, parentPath) !== undefined) {
260
+ hasUpdatedParent = true;
261
+ break;
262
+ }
263
+ }
264
+
265
+ if (hasUpdatedParent) {
266
+ continue;
267
+ }
268
+
238
269
  if (preventNull) {
239
270
  // keys that come from "definedKeys" method are strings with "" chars inside... We need to clean them up
240
271
  // so that we can access the value of the obj property
@@ -24,9 +24,10 @@ import { EXT_IDS } from '@shell/core/plugin';
24
24
  import { ExtensionManager } from '@shell/types/extension-manager';
25
25
  import { DEFAULT_PERF_SETTING } from '@shell/config/settings';
26
26
 
27
+ // This feature will be removed soon - https://github.com/rancher/dashboard/issues/17323
27
28
  const homePageClusterFeature: PaginationFeature<PaginationFeatureHomePageClusterConfig> = {
28
29
  version: 1,
29
- enabled: true,
30
+ enabled: false,
30
31
  configuration: {
31
32
  threshold: 500, results: 250, pagesPerRow: 25
32
33
  }
package/utils/string.js CHANGED
@@ -349,10 +349,33 @@ export function xOfy(x, y) {
349
349
  return `${ typeof x === 'number' ? x : '?' }/${ typeof y === 'number' ? y : '?' }`;
350
350
  }
351
351
 
352
+ const BASE64_REGEX = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
353
+
352
354
  export function isBase64(value) {
353
- const base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
355
+ return BASE64_REGEX.test(value);
356
+ }
357
+
358
+ /**
359
+ * Checks if a value is a valid base64-encoded CA bundle.
360
+ * Unlike isBase64, this handles multiline base64 (e.g. openssl wraps at 76 chars)
361
+ * and rejects short strings that could be false positives.
362
+ * @param {string} value
363
+ * @returns {boolean}
364
+ */
365
+ export function isBase64EncodedCert(value) {
366
+ if (!value || typeof value !== 'string') {
367
+ return false;
368
+ }
369
+
370
+ // Strip whitespace to handle line-wrapped base64 output
371
+ const stripped = value.replace(/\s/g, '');
372
+
373
+ // CA certs are long enough that legitimate base64 will always exceed this
374
+ if (stripped.length < 16) {
375
+ return false;
376
+ }
354
377
 
355
- return base64regex.test(value);
378
+ return BASE64_REGEX.test(stripped);
356
379
  }
357
380
 
358
381
  export function generateRandomAlphaString(length) {
package/utils/time.ts CHANGED
@@ -2,6 +2,11 @@ import day from 'dayjs';
2
2
  import { escapeHtml } from '@shell/utils/string';
3
3
  import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
4
4
  import { type Store } from 'vuex';
5
+ import { ZERO_TIME } from '@shell/config/types';
6
+
7
+ export function isMissingDate(date: string | undefined | null): boolean {
8
+ return !date || date === ZERO_TIME;
9
+ }
5
10
 
6
11
  const FACTORS = [60, 60, 24];
7
12
  const LABELS = ['sec', 'min', 'hour', 'day'];
@@ -180,18 +180,19 @@ export async function getHelmRepositoryExact(store: any, url: string): Promise<H
180
180
  /**
181
181
  *
182
182
  * @param store Vue store
183
- * @param urlRegexes Regex to match a community repository
183
+ * @param urlRegexes Regex to match against the repository's urls
184
184
  * @param catalogImages Catalog images to match against the repository's labels
185
185
  * @returns HelmRepository
186
186
  */
187
187
  export async function getHelmRepositoryMatch(store: any, urlRegexes: string[], catalogImages: string[]): Promise<HelmRepository> {
188
188
  return await getHelmRepository(store, (repository: any) => {
189
- // if installed from rancher/ui-plugin-catalog or rancher/ui-extension-harvester-ui-extension
190
189
  const catalog = repository?.metadata?.labels?.[UI_PLUGIN_LABELS.CATALOG_IMAGE] || '';
191
190
 
192
- if (catalogImages.includes(catalog)) {
191
+ // if installed from rancher/ui-plugin-catalog or rancher/ui-extension-harvester-ui-extension
192
+ if (catalog && catalogImages.includes(catalog)) {
193
193
  return true;
194
194
  }
195
+
195
196
  const target = repository.spec?.gitBranch ? repository.spec?.gitRepo : repository.spec?.url;
196
197
 
197
198
  return matchesSomeRegex(target, urlRegexes);
@@ -272,8 +273,7 @@ export async function createHelmRepository(store: any, name: string, url: string
272
273
  });
273
274
 
274
275
  tries++;
275
-
276
- const downloaded = repo.status.conditions.find((s: any) => s.type === 'Downloaded');
276
+ const downloaded = repo.status?.conditions.find((s: any) => s.type === 'Downloaded');
277
277
 
278
278
  console.log(`Waiting for helm repository to be downloaded... try ${ tries } time(s).`); // eslint-disable-line no-console
279
279