@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) 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/styles/base/_variables.scss +2 -0
  54. package/assets/styles/fonts/_fontstack.scss +132 -8
  55. package/assets/styles/global/_layout.scss +4 -0
  56. package/assets/translations/en-us.yaml +165 -45
  57. package/assets/translations/zh-hans.yaml +1 -7
  58. package/chart/monitoring/ClusterSelector.vue +0 -21
  59. package/chart/monitoring/index.vue +10 -1
  60. package/chart/monitoring/prometheus/index.vue +6 -3
  61. package/components/ActionDropdownShell.vue +2 -1
  62. package/components/CruResource.vue +161 -14
  63. package/components/CruResourceFooter.vue +9 -5
  64. package/components/ExplorerMembers.vue +8 -4
  65. package/components/ExplorerProjectsNamespaces.vue +11 -7
  66. package/components/GrowlManager.vue +4 -0
  67. package/components/InstallHelmCharts.vue +2 -2
  68. package/components/LandingPagePreference.vue +14 -5
  69. package/components/MgmtNodeList.vue +184 -0
  70. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
  71. package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
  72. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
  73. package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
  74. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +17 -1
  75. package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
  76. package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
  77. package/components/Resource/Detail/Metadata/index.vue +6 -0
  78. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  79. package/components/Resource/Detail/SpacedRow.vue +3 -1
  80. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  81. package/components/ResourceDetail/index.vue +1 -1
  82. package/components/ResourceList/Masthead.vue +19 -9
  83. package/components/ResourceList/index.vue +82 -1
  84. package/components/RichTranslation.vue +5 -2
  85. package/components/SelectIconGrid.vue +0 -10
  86. package/components/Setting.vue +1 -0
  87. package/components/SingleClusterInfo.vue +1 -0
  88. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  89. package/components/SortableTable/index.vue +6 -9
  90. package/components/SortableTable/selection.js +23 -5
  91. package/components/SortableTable/sorting.js +6 -3
  92. package/components/SubtleLink.vue +31 -6
  93. package/components/Tabbed/Tab.vue +29 -3
  94. package/components/Tabbed/index.vue +25 -3
  95. package/components/TableOfContents/TableOfContents.vue +109 -0
  96. package/components/TableOfContents/composables.ts +258 -0
  97. package/components/Window/ContainerShell.vue +21 -11
  98. package/components/Window/__tests__/ContainerShell.test.ts +107 -37
  99. package/components/Wizard.vue +23 -17
  100. package/components/fleet/AppCoChartGrid.vue +401 -0
  101. package/components/fleet/AppCoEmptyState.vue +127 -0
  102. package/components/fleet/AppCoPageHeader.vue +119 -0
  103. package/components/fleet/AppCoVersionSelect.vue +70 -0
  104. package/components/fleet/FleetBundles.vue +100 -12
  105. package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
  106. package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
  107. package/components/fleet/FleetClusterTargets/index.vue +226 -161
  108. package/components/fleet/FleetIntro.vue +7 -3
  109. package/components/fleet/FleetNoWorkspaces.vue +7 -3
  110. package/components/fleet/FleetSecretSelector.vue +5 -3
  111. package/components/fleet/FleetValuesFrom.vue +8 -2
  112. package/components/fleet/GitRepoTargetTab.vue +0 -2
  113. package/components/fleet/HelmOpAdvancedTab.vue +19 -53
  114. package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
  115. package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
  116. package/components/fleet/HelmOpResourcesSection.vue +82 -0
  117. package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
  118. package/components/fleet/HelmOpTargetTab.vue +64 -60
  119. package/components/fleet/HelmOpValuesTab.vue +129 -105
  120. package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
  121. package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
  122. package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +402 -115
  124. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  125. package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
  127. package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
  128. package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
  129. package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
  130. package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
  131. package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
  132. package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
  133. package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
  134. package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
  135. package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
  136. package/components/fleet/dashboard/Empty.vue +8 -4
  137. package/components/fleet/dashboard/ResourceCard.vue +28 -0
  138. package/components/fleet/dashboard/ResourceDetails.vue +28 -0
  139. package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
  140. package/components/form/ArrayList.vue +61 -4
  141. package/components/form/KeyValue.vue +23 -2
  142. package/components/form/LabeledSelect.vue +59 -4
  143. package/components/form/Labels.vue +22 -3
  144. package/components/form/NameNsDescription.vue +24 -5
  145. package/components/form/ResourceTabs/index.vue +1 -0
  146. package/components/form/Security.vue +6 -2
  147. package/components/form/WorkloadPorts.vue +2 -7
  148. package/components/form/__tests__/NameNsDescription.test.ts +75 -0
  149. package/components/form/__tests__/Security.test.ts +76 -0
  150. package/components/formatter/Autoscaler.vue +4 -4
  151. package/components/formatter/ClusterKubeVersion.vue +27 -0
  152. package/components/formatter/ClusterLink.vue +1 -7
  153. package/components/formatter/ClusterProvider.vue +6 -10
  154. package/components/formatter/FleetSummaryGraph.vue +0 -3
  155. package/components/formatter/InternalExternalIP.vue +10 -4
  156. package/components/formatter/MachineSummaryGraph.vue +1 -1
  157. package/components/formatter/PodsUsage.vue +2 -2
  158. package/components/formatter/ServiceTargets.vue +26 -7
  159. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  160. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  161. package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
  162. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  163. package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
  164. package/components/nav/Header.vue +4 -0
  165. package/components/nav/NamespaceFilter.vue +2 -2
  166. package/components/nav/TopLevelMenu.helper.ts +15 -3
  167. package/components/nav/TopLevelMenu.vue +22 -6
  168. package/components/nav/__tests__/Header.test.ts +15 -0
  169. package/components/nav/__tests__/TopLevelMenu.test.ts +263 -21
  170. package/components/templates/default.vue +9 -4
  171. package/components/templates/home.vue +23 -0
  172. package/components/templates/plain.vue +23 -0
  173. package/components/templates/standalone.vue +17 -0
  174. package/composables/useFormValidation.ts +93 -0
  175. package/composables/useHelmOpResources.test.ts +56 -0
  176. package/composables/useHelmOpResources.ts +32 -0
  177. package/composables/useStateColor.test.ts +325 -0
  178. package/composables/useStateColor.ts +128 -0
  179. package/composables/useVeeValidateField.test.ts +159 -0
  180. package/composables/useVeeValidateField.ts +67 -0
  181. package/config/home-links.js +1 -1
  182. package/config/labels-annotations.js +1 -0
  183. package/config/pagination-table-headers.js +18 -1
  184. package/config/product/explorer.js +17 -4
  185. package/config/product/manager.js +84 -21
  186. package/config/router/index.js +16 -0
  187. package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
  188. package/config/router/navigation-guards/authentication.js +10 -4
  189. package/config/router/routes.js +26 -6
  190. package/config/settings.ts +0 -2
  191. package/config/table-headers.js +23 -5
  192. package/config/types.js +11 -1
  193. package/core/__tests__/plugin-products.test.ts +904 -20
  194. package/core/plugin-products-base.ts +110 -10
  195. package/core/plugin-products.ts +4 -0
  196. package/core/plugin-types.ts +194 -31
  197. package/core/plugin.ts +18 -7
  198. package/core/productDebugger.js +9 -4
  199. package/core/types-provisioning.ts +77 -31
  200. package/core/types.ts +72 -22
  201. package/detail/__tests__/pod.test.ts +41 -0
  202. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
  203. package/detail/__tests__/workload.test.ts +3 -152
  204. package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
  205. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  206. package/detail/pod.vue +1 -1
  207. package/detail/provisioning.cattle.io.cluster.vue +34 -14
  208. package/detail/workload/index.vue +12 -55
  209. package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
  210. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
  211. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  212. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
  213. package/edit/auth/__tests__/azuread.test.ts +247 -39
  214. package/edit/auth/__tests__/github.test.ts +234 -0
  215. package/edit/auth/__tests__/oidc.test.ts +26 -6
  216. package/edit/auth/__tests__/saml.test.ts +196 -0
  217. package/edit/auth/azuread.vue +197 -56
  218. package/edit/auth/github.vue +72 -13
  219. package/edit/auth/ldap/__tests__/index.test.ts +206 -0
  220. package/edit/auth/ldap/config.vue +8 -0
  221. package/edit/auth/ldap/index.vue +75 -1
  222. package/edit/auth/oidc.vue +119 -73
  223. package/edit/auth/saml.vue +76 -12
  224. package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
  225. package/edit/fleet.cattle.io.helmop.vue +491 -136
  226. package/edit/management.cattle.io.user.vue +5 -2
  227. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  228. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  229. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  230. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  231. package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
  232. package/edit/provisioning.cattle.io.cluster/rke2.vue +92 -14
  233. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +22 -0
  234. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  235. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  236. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  237. package/edit/secret/__tests__/ssh.test.ts +5 -6
  238. package/edit/secret/basic.vue +31 -0
  239. package/edit/secret/index.vue +68 -17
  240. package/edit/secret/registry.vue +38 -0
  241. package/edit/secret/ssh.vue +29 -0
  242. package/edit/secret/tls.vue +30 -0
  243. package/edit/service.vue +4 -4
  244. package/edit/workload/Upgrading.vue +3 -3
  245. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  246. package/edit/workload/mixins/workload.js +2 -1
  247. package/list/fleet.cattle.io.bundle.vue +7 -104
  248. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  249. package/list/group.principal.vue +5 -4
  250. package/list/harvesterhci.io.management.cluster.vue +8 -9
  251. package/list/management.cattle.io.user.vue +12 -9
  252. package/list/provisioning.cattle.io.cluster.vue +268 -180
  253. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  254. package/mixins/__tests__/auth-config.test.ts +90 -0
  255. package/mixins/__tests__/chart.test.ts +206 -0
  256. package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
  257. package/mixins/auth-config.js +7 -0
  258. package/mixins/brand.js +2 -1
  259. package/mixins/chart.js +22 -9
  260. package/mixins/child-hook.js +12 -6
  261. package/mixins/create-edit-view/impl.js +5 -3
  262. package/mixins/resource-fetch-api-pagination.js +62 -6
  263. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
  264. package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
  265. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  266. package/models/__tests__/fleet-application.test.ts +175 -0
  267. package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
  268. package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
  269. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  270. package/models/__tests__/management.cattle.io.node.ts +28 -5
  271. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  272. package/models/__tests__/namespace.test.ts +36 -0
  273. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +81 -11
  274. package/models/__tests__/workload.test.ts +401 -26
  275. package/models/base-cluster.x-k8s.io.js +26 -0
  276. package/models/catalog.cattle.io.clusterrepo.js +28 -4
  277. package/models/cluster.js +1 -1
  278. package/models/cluster.x-k8s.io.machine.js +4 -22
  279. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  280. package/models/cluster.x-k8s.io.machineset.js +2 -20
  281. package/models/compliance.cattle.io.clusterscan.js +165 -2
  282. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  283. package/models/fleet-application.js +7 -1
  284. package/models/fleet.cattle.io.helmop.js +20 -1
  285. package/models/management.cattle.io.cluster.js +434 -41
  286. package/models/management.cattle.io.node.js +50 -7
  287. package/models/management.cattle.io.nodepool.js +1 -1
  288. package/models/namespace.js +1 -1
  289. package/models/networking.k8s.io.ingress.js +12 -4
  290. package/models/pod.js +33 -1
  291. package/models/provisioning.cattle.io.cluster.js +51 -334
  292. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  293. package/models/workload.js +108 -13
  294. package/models/workload.service.js +5 -0
  295. package/package.json +22 -39
  296. package/pages/__tests__/readme.test.ts +49 -0
  297. package/pages/about.vue +5 -6
  298. package/pages/auth/login.vue +0 -35
  299. package/pages/auth/setup.vue +13 -3
  300. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
  301. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
  302. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
  303. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
  304. package/pages/c/_cluster/apps/charts/chart.vue +62 -9
  305. package/pages/c/_cluster/apps/charts/index.vue +48 -10
  306. package/pages/c/_cluster/apps/charts/install.vue +122 -113
  307. package/pages/c/_cluster/auth/roles/index.vue +5 -4
  308. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  309. package/pages/c/_cluster/explorer/index.vue +5 -49
  310. package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
  311. package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
  312. package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
  313. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
  314. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
  315. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
  316. package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
  317. package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
  318. package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
  319. package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
  320. package/pages/c/_cluster/fleet/application/create.vue +187 -136
  321. package/pages/c/_cluster/fleet/application/index.vue +5 -3
  322. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
  323. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
  324. package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
  325. package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
  326. package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
  327. package/pages/c/_cluster/fleet/index.vue +2 -2
  328. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  329. package/pages/c/_cluster/istio/index.vue +21 -6
  330. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
  331. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +815 -2
  332. package/pages/c/_cluster/uiplugins/index.vue +218 -197
  333. package/pages/diagnostic.vue +13 -17
  334. package/pages/fail-whale.vue +30 -7
  335. package/pages/home.vue +93 -306
  336. package/pages/readme.vue +88 -0
  337. package/plugins/clean-html.d.ts +9 -0
  338. package/plugins/dashboard-store/__tests__/resource-class.test.ts +181 -0
  339. package/plugins/dashboard-store/actions.js +40 -18
  340. package/plugins/dashboard-store/resource-class.js +67 -9
  341. package/plugins/steve/__tests__/actions.test.ts +212 -0
  342. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  343. package/plugins/steve/actions.js +96 -0
  344. package/plugins/steve/steve-pagination-utils.ts +12 -4
  345. package/plugins/steve/subscribe.js +35 -5
  346. package/rancher-components/Accordion/Accordion.vue +53 -9
  347. package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
  348. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
  349. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
  350. package/rancher-components/Form/Radio/RadioButton.vue +17 -1
  351. package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
  352. package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
  353. package/rancher-components/RcButton/RcButton.test.ts +140 -1
  354. package/rancher-components/RcButton/RcButton.vue +126 -17
  355. package/rancher-components/RcButton/types.ts +3 -0
  356. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  357. package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
  358. package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
  359. package/rancher-components/RcSection/RcSection.vue +28 -3
  360. package/scripts/extension/helm/package/Dockerfile +1 -1
  361. package/scripts/test-plugins-build.sh +2 -1
  362. package/store/__tests__/catalog.test.ts +115 -1
  363. package/store/__tests__/notifications.test.ts +434 -0
  364. package/store/__tests__/type-map.test.ts +556 -1
  365. package/store/action-menu.js +8 -3
  366. package/store/auth.js +1 -1
  367. package/store/aws.js +27 -16
  368. package/store/catalog.js +84 -3
  369. package/store/digitalocean.js +20 -38
  370. package/store/index.js +2 -0
  371. package/store/linode.js +25 -40
  372. package/store/plugins.js +7 -4
  373. package/store/pnap.js +1 -0
  374. package/store/type-map.js +111 -29
  375. package/tsconfig.paths.json +8 -8
  376. package/types/components/buttonGroup.ts +5 -0
  377. package/types/kube/kube-api.ts +14 -1
  378. package/types/rancher/steve.api.ts +12 -12
  379. package/types/resources/settings.d.ts +2 -1
  380. package/types/shell/index.d.ts +206 -72
  381. package/types/store/dashboard-store.types.ts +108 -11
  382. package/types/store/pagination.types.ts +6 -3
  383. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  384. package/utils/__tests__/async.test.ts +87 -0
  385. package/utils/__tests__/auth.test.ts +273 -0
  386. package/utils/__tests__/aws.test.ts +140 -0
  387. package/utils/__tests__/banners.test.ts +176 -0
  388. package/utils/__tests__/chart.test.ts +64 -1
  389. package/utils/__tests__/color.test.ts +226 -0
  390. package/utils/__tests__/computed.test.ts +193 -0
  391. package/utils/__tests__/cspAdaptor.test.ts +163 -0
  392. package/utils/__tests__/dom.test.ts +81 -0
  393. package/utils/__tests__/duration.test.ts +176 -0
  394. package/utils/__tests__/dynamic-importer.test.ts +102 -0
  395. package/utils/__tests__/fleet-appco.test.ts +312 -0
  396. package/utils/__tests__/fleet.test.ts +340 -0
  397. package/utils/__tests__/ingress.test.ts +553 -0
  398. package/utils/__tests__/kube.test.ts +68 -0
  399. package/utils/__tests__/monitoring.test.ts +130 -0
  400. package/utils/__tests__/namespace-filter.test.ts +109 -0
  401. package/utils/__tests__/object.test.ts +22 -0
  402. package/utils/__tests__/pagination-utils.test.ts +361 -0
  403. package/utils/__tests__/parse-externalid.test.ts +137 -0
  404. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  405. package/utils/__tests__/platform.test.ts +91 -0
  406. package/utils/__tests__/poller-sequential.test.ts +177 -0
  407. package/utils/__tests__/poller.test.ts +170 -0
  408. package/utils/__tests__/position.test.ts +237 -0
  409. package/utils/__tests__/promise.test.ts +346 -0
  410. package/utils/__tests__/provider.test.ts +51 -1
  411. package/utils/__tests__/queue.test.ts +232 -0
  412. package/utils/__tests__/release-notes.test.ts +221 -0
  413. package/utils/__tests__/router.test.js +254 -1
  414. package/utils/__tests__/select.test.ts +208 -0
  415. package/utils/__tests__/settings.test.ts +140 -0
  416. package/utils/__tests__/sort-utils.test.ts +301 -0
  417. package/utils/__tests__/string-utils.test.ts +798 -0
  418. package/utils/__tests__/string.test.ts +23 -1
  419. package/utils/__tests__/style.test.ts +154 -0
  420. package/utils/__tests__/svg-filter.test.ts +184 -0
  421. package/utils/__tests__/time.test.ts +265 -1
  422. package/utils/__tests__/title.test.ts +47 -0
  423. package/utils/__tests__/units.test.ts +417 -0
  424. package/utils/__tests__/versions.test.ts +128 -0
  425. package/utils/__tests__/width.test.ts +53 -0
  426. package/utils/__tests__/window.test.ts +158 -0
  427. package/utils/__tests__/xccdf.test.ts +511 -0
  428. package/utils/chart.js +36 -0
  429. package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
  430. package/utils/crypto/__tests__/index.test.ts +144 -0
  431. package/utils/duration.ts +104 -0
  432. package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
  433. package/utils/dynamic-content/info.ts +2 -1
  434. package/utils/error.js +13 -0
  435. package/utils/fleet-appco.ts +323 -0
  436. package/utils/fleet.ts +13 -3
  437. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  438. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  439. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  440. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  441. package/utils/gc/__tests__/gc.test.ts +487 -0
  442. package/utils/ingress.ts +9 -1
  443. package/utils/object.js +22 -2
  444. package/utils/pagination-utils.ts +2 -1
  445. package/utils/provider.ts +12 -0
  446. package/utils/string.js +25 -2
  447. package/utils/uiplugins.ts +5 -5
  448. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  449. package/utils/validators/__tests__/container-images.test.ts +104 -0
  450. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  451. package/utils/validators/__tests__/flow-output.test.ts +91 -0
  452. package/utils/validators/__tests__/index.test.ts +481 -0
  453. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  454. package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
  455. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  456. package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
  457. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  458. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  459. package/utils/validators/__tests__/role-template.test.ts +149 -0
  460. package/utils/validators/__tests__/service.test.ts +283 -0
  461. package/utils/validators/__tests__/setting.test.js +32 -0
  462. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  463. package/utils/validators/formRules/index.ts +5 -5
  464. package/utils/validators/machine-pool.ts +1 -1
  465. package/utils/validators/setting.js +18 -3
  466. package/utils/xccdf.ts +415 -0
  467. package/vue.config.js +1 -1
  468. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  469. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  470. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  471. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
  472. package/pages/support/index.vue +0 -264
  473. package/utils/duration.js +0 -43
@@ -1,6 +1,6 @@
1
1
  import Workload from '@shell/models/workload.js';
2
2
  import { steveClassJunkObject } from '@shell/plugins/steve/__tests__/utils/steve-mocks';
3
- import { WORKLOAD_TYPES, SERVICE } from '@shell/config/types';
3
+ import { WORKLOAD_TYPES, SERVICE, INGRESS } from '@shell/config/types';
4
4
 
5
5
  describe('class: Workload', () => {
6
6
  describe('given custom workload keys', () => {
@@ -160,12 +160,7 @@ describe('class: Workload', () => {
160
160
  });
161
161
 
162
162
  describe('getter: relatedServices', () => {
163
- it('should return services that match workload pods', () => {
164
- const mockPod = {
165
- metadata: {
166
- name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
167
- }
168
- };
163
+ it('should return services that match workload pod template labels', () => {
169
164
  const mockService = {
170
165
  metadata: { name: 'my-service', namespace: 'default' },
171
166
  spec: { selector: { app: 'my-app' } }
@@ -173,7 +168,7 @@ describe('class: Workload', () => {
173
168
  const workload = new Workload({
174
169
  type: WORKLOAD_TYPES.DEPLOYMENT,
175
170
  metadata: { name: 'test', namespace: 'default' },
176
- spec: {}
171
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
177
172
  }, {
178
173
  getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
179
174
  dispatch: jest.fn(),
@@ -183,20 +178,12 @@ describe('class: Workload', () => {
183
178
  },
184
179
  });
185
180
 
186
- // Mock pods getter
187
- Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
188
-
189
181
  const related = workload.relatedServices;
190
182
 
191
183
  expect(related).toContain(mockService);
192
184
  });
193
185
 
194
186
  it('should not return services from different namespace', () => {
195
- const mockPod = {
196
- metadata: {
197
- name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
198
- }
199
- };
200
187
  const mockService = {
201
188
  metadata: { name: 'my-service', namespace: 'other-namespace' },
202
189
  spec: { selector: { app: 'my-app' } }
@@ -204,7 +191,7 @@ describe('class: Workload', () => {
204
191
  const workload = new Workload({
205
192
  type: WORKLOAD_TYPES.DEPLOYMENT,
206
193
  metadata: { name: 'test', namespace: 'default' },
207
- spec: {}
194
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
208
195
  }, {
209
196
  getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
210
197
  dispatch: jest.fn(),
@@ -214,19 +201,12 @@ describe('class: Workload', () => {
214
201
  },
215
202
  });
216
203
 
217
- Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
218
-
219
204
  const related = workload.relatedServices;
220
205
 
221
206
  expect(related).toHaveLength(0);
222
207
  });
223
208
 
224
209
  it('should not return services with non-matching selectors', () => {
225
- const mockPod = {
226
- metadata: {
227
- name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
228
- }
229
- };
230
210
  const mockService = {
231
211
  metadata: { name: 'my-service', namespace: 'default' },
232
212
  spec: { selector: { app: 'different-app' } }
@@ -234,7 +214,7 @@ describe('class: Workload', () => {
234
214
  const workload = new Workload({
235
215
  type: WORKLOAD_TYPES.DEPLOYMENT,
236
216
  metadata: { name: 'test', namespace: 'default' },
237
- spec: {}
217
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
238
218
  }, {
239
219
  getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
240
220
  dispatch: jest.fn(),
@@ -244,7 +224,28 @@ describe('class: Workload', () => {
244
224
  },
245
225
  });
246
226
 
247
- Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
227
+ const related = workload.relatedServices;
228
+
229
+ expect(related).toHaveLength(0);
230
+ });
231
+
232
+ it('should return empty array when pod template has no labels', () => {
233
+ const mockService = {
234
+ metadata: { name: 'my-service', namespace: 'default' },
235
+ spec: { selector: { app: 'my-app' } }
236
+ };
237
+ const workload = new Workload({
238
+ type: WORKLOAD_TYPES.DEPLOYMENT,
239
+ metadata: { name: 'test', namespace: 'default' },
240
+ spec: { template: { metadata: {} } }
241
+ }, {
242
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
243
+ dispatch: jest.fn(),
244
+ rootGetters: {
245
+ 'i18n/t': jest.fn(),
246
+ 'cluster/all': (type: string) => (type === SERVICE ? [mockService] : [])
247
+ },
248
+ });
248
249
 
249
250
  const related = workload.relatedServices;
250
251
 
@@ -506,4 +507,378 @@ describe('class: Workload', () => {
506
507
  expect(jobsCard).toBeDefined();
507
508
  });
508
509
  });
510
+
511
+ describe('getter: matchingIngresses', () => {
512
+ const makeWorkload = (services: any[], ingresses: any[], pods: any[] = []) => {
513
+ const workload = new Workload({
514
+ type: WORKLOAD_TYPES.DEPLOYMENT,
515
+ metadata: { name: 'test', namespace: 'default' },
516
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
517
+ }, {
518
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
519
+ dispatch: jest.fn(),
520
+ rootGetters: {
521
+ 'i18n/t': jest.fn(),
522
+ 'cluster/all': (type: string) => {
523
+ if (type === SERVICE) {
524
+ return services;
525
+ }
526
+ if (type === INGRESS) {
527
+ return ingresses;
528
+ }
529
+
530
+ return [];
531
+ }
532
+ },
533
+ });
534
+
535
+ Object.defineProperty(workload, 'pods', { get: () => pods });
536
+
537
+ return workload;
538
+ };
539
+
540
+ it('should return empty array when no related services', () => {
541
+ const workload = makeWorkload([], [
542
+ {
543
+ metadata: { namespace: 'default' },
544
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] }
545
+ }
546
+ ]);
547
+
548
+ expect(workload.matchingIngresses).toStrictEqual([]);
549
+ });
550
+
551
+ it('should find matching ingresses', () => {
552
+ const mockPod = {
553
+ metadata: {
554
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
555
+ }
556
+ };
557
+ const mockService = {
558
+ metadata: { name: 'svc1', namespace: 'default' },
559
+ spec: { selector: { app: 'my-app' } }
560
+ };
561
+ const mockIngress = {
562
+ metadata: { namespace: 'default' },
563
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] }
564
+ };
565
+
566
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
567
+
568
+ expect(workload.matchingIngresses).toHaveLength(1);
569
+ expect(workload.matchingIngresses[0]).toStrictEqual(mockIngress);
570
+ });
571
+
572
+ it('should not match ingresses from other namespaces', () => {
573
+ const mockPod = {
574
+ metadata: {
575
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
576
+ }
577
+ };
578
+ const mockService = {
579
+ metadata: { name: 'svc1', namespace: 'default' },
580
+ spec: { selector: { app: 'my-app' } }
581
+ };
582
+ const mockIngress = {
583
+ metadata: { namespace: 'other' },
584
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] }
585
+ };
586
+
587
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
588
+
589
+ expect(workload.matchingIngresses).toHaveLength(0);
590
+ });
591
+
592
+ it('should not match ingresses pointing to other services', () => {
593
+ const mockPod = {
594
+ metadata: {
595
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
596
+ }
597
+ };
598
+ const mockService = {
599
+ metadata: { name: 'svc1', namespace: 'default' },
600
+ spec: { selector: { app: 'my-app' } }
601
+ };
602
+ const mockIngress = {
603
+ metadata: { namespace: 'default' },
604
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc2' } } }] } }] }
605
+ };
606
+
607
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
608
+
609
+ expect(workload.matchingIngresses).toHaveLength(0);
610
+ });
611
+
612
+ it('should handle ingresses with no rules', () => {
613
+ const mockPod = {
614
+ metadata: {
615
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
616
+ }
617
+ };
618
+ const mockService = {
619
+ metadata: { name: 'svc1', namespace: 'default' },
620
+ spec: { selector: { app: 'my-app' } }
621
+ };
622
+ const mockIngress = {
623
+ metadata: { namespace: 'default' },
624
+ spec: {}
625
+ };
626
+
627
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
628
+
629
+ expect(workload.matchingIngresses).toHaveLength(0);
630
+ });
631
+
632
+ it('should handle ingress rules with no paths', () => {
633
+ const mockPod = {
634
+ metadata: {
635
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
636
+ }
637
+ };
638
+ const mockService = {
639
+ metadata: { name: 'svc1', namespace: 'default' },
640
+ spec: { selector: { app: 'my-app' } }
641
+ };
642
+ const mockIngress = {
643
+ metadata: { namespace: 'default' },
644
+ spec: { rules: [{ http: {} }] }
645
+ };
646
+
647
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
648
+
649
+ expect(workload.matchingIngresses).toHaveLength(0);
650
+ });
651
+
652
+ it('should handle ingress paths with no backend service', () => {
653
+ const mockPod = {
654
+ metadata: {
655
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
656
+ }
657
+ };
658
+ const mockService = {
659
+ metadata: { name: 'svc1', namespace: 'default' },
660
+ spec: { selector: { app: 'my-app' } }
661
+ };
662
+ const mockIngress = {
663
+ metadata: { namespace: 'default' },
664
+ spec: { rules: [{ http: { paths: [{ backend: {} }] } }] }
665
+ };
666
+
667
+ const workload = makeWorkload([mockService], [mockIngress], [mockPod]);
668
+
669
+ expect(workload.matchingIngresses).toHaveLength(0);
670
+ });
671
+
672
+ it('should find one of many ingresses', () => {
673
+ const mockPod = {
674
+ metadata: {
675
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
676
+ }
677
+ };
678
+ const mockService = {
679
+ metadata: { name: 'svc1', namespace: 'default' },
680
+ spec: { selector: { app: 'my-app' } }
681
+ };
682
+ const ingresses = [
683
+ {
684
+ metadata: { namespace: 'other' },
685
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] }
686
+ },
687
+ {
688
+ metadata: { namespace: 'default' },
689
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] }
690
+ },
691
+ {
692
+ metadata: { namespace: 'default' },
693
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc2' } } }] } }] }
694
+ }
695
+ ];
696
+
697
+ const workload = makeWorkload([mockService], ingresses, [mockPod]);
698
+
699
+ expect(workload.matchingIngresses).toHaveLength(1);
700
+ expect(workload.matchingIngresses[0]).toStrictEqual(ingresses[1]);
701
+ });
702
+ });
703
+
704
+ describe('getter: resourcesCardRows', () => {
705
+ it('should include services row when related services exist', () => {
706
+ const mockPod = {
707
+ metadata: {
708
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
709
+ }
710
+ };
711
+ const mockService = {
712
+ metadata: { name: 'svc1', namespace: 'default' },
713
+ spec: { selector: { app: 'my-app' } },
714
+ stateDisplay: 'Active',
715
+ stateSimpleColor: 'success'
716
+ };
717
+
718
+ const workload = new Workload({
719
+ type: WORKLOAD_TYPES.DEPLOYMENT,
720
+ metadata: { name: 'test', namespace: 'default' },
721
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
722
+ }, {
723
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
724
+ dispatch: jest.fn(),
725
+ rootGetters: {
726
+ 'i18n/t': (key: string) => key,
727
+ 'cluster/all': (type: string) => {
728
+ if (type === SERVICE) {
729
+ return [mockService];
730
+ }
731
+
732
+ return [];
733
+ }
734
+ },
735
+ });
736
+
737
+ Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
738
+
739
+ const rows = workload.resourcesCardRows;
740
+ const servicesRow = rows.find((r: any) => r.label === 'component.resource.detail.card.resourcesCard.rows.services');
741
+
742
+ expect(servicesRow).toBeDefined();
743
+ });
744
+
745
+ it('should include ingresses row when matching ingresses exist', () => {
746
+ const mockPod = {
747
+ metadata: {
748
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
749
+ }
750
+ };
751
+ const mockService = {
752
+ metadata: { name: 'svc1', namespace: 'default' },
753
+ spec: { selector: { app: 'my-app' } },
754
+ stateDisplay: 'Active',
755
+ stateSimpleColor: 'success'
756
+ };
757
+ const mockIngress = {
758
+ metadata: { namespace: 'default' },
759
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] },
760
+ stateDisplay: 'Active',
761
+ stateSimpleColor: 'success'
762
+ };
763
+
764
+ const workload = new Workload({
765
+ type: WORKLOAD_TYPES.DEPLOYMENT,
766
+ metadata: { name: 'test', namespace: 'default' },
767
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
768
+ }, {
769
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
770
+ dispatch: jest.fn(),
771
+ rootGetters: {
772
+ 'i18n/t': (key: string) => key,
773
+ 'cluster/all': (type: string) => {
774
+ if (type === SERVICE) {
775
+ return [mockService];
776
+ }
777
+ if (type === INGRESS) {
778
+ return [mockIngress];
779
+ }
780
+
781
+ return [];
782
+ }
783
+ },
784
+ });
785
+
786
+ Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
787
+
788
+ const rows = workload.resourcesCardRows;
789
+ const ingressesRow = rows.find((r: any) => r.label === 'component.resource.detail.card.resourcesCard.rows.ingresses');
790
+
791
+ expect(ingressesRow).toBeDefined();
792
+ expect(ingressesRow.to).toBe('#ingresses');
793
+ });
794
+
795
+ it('should order services before ingresses', () => {
796
+ const mockPod = {
797
+ metadata: {
798
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
799
+ }
800
+ };
801
+ const mockService = {
802
+ metadata: { name: 'svc1', namespace: 'default' },
803
+ spec: { selector: { app: 'my-app' } },
804
+ stateDisplay: 'Active',
805
+ stateSimpleColor: 'success'
806
+ };
807
+ const mockIngress = {
808
+ metadata: { namespace: 'default' },
809
+ spec: { rules: [{ http: { paths: [{ backend: { service: { name: 'svc1' } } }] } }] },
810
+ stateDisplay: 'Active',
811
+ stateSimpleColor: 'success'
812
+ };
813
+
814
+ const workload = new Workload({
815
+ type: WORKLOAD_TYPES.DEPLOYMENT,
816
+ metadata: { name: 'test', namespace: 'default' },
817
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
818
+ }, {
819
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
820
+ dispatch: jest.fn(),
821
+ rootGetters: {
822
+ 'i18n/t': (key: string) => key,
823
+ 'cluster/all': (type: string) => {
824
+ if (type === SERVICE) {
825
+ return [mockService];
826
+ }
827
+ if (type === INGRESS) {
828
+ return [mockIngress];
829
+ }
830
+
831
+ return [];
832
+ }
833
+ },
834
+ });
835
+
836
+ Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
837
+
838
+ const rows = workload.resourcesCardRows;
839
+
840
+ expect(rows[0].label).toBe('component.resource.detail.card.resourcesCard.rows.services');
841
+ expect(rows[1].label).toBe('component.resource.detail.card.resourcesCard.rows.ingresses');
842
+ });
843
+
844
+ it('should not include ingresses row when no matching ingresses', () => {
845
+ const mockPod = {
846
+ metadata: {
847
+ name: 'pod-1', namespace: 'default', labels: { app: 'my-app' }
848
+ }
849
+ };
850
+ const mockService = {
851
+ metadata: { name: 'svc1', namespace: 'default' },
852
+ spec: { selector: { app: 'my-app' } },
853
+ stateDisplay: 'Active',
854
+ stateSimpleColor: 'success'
855
+ };
856
+
857
+ const workload = new Workload({
858
+ type: WORKLOAD_TYPES.DEPLOYMENT,
859
+ metadata: { name: 'test', namespace: 'default' },
860
+ spec: { template: { metadata: { labels: { app: 'my-app' } } } }
861
+ }, {
862
+ getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
863
+ dispatch: jest.fn(),
864
+ rootGetters: {
865
+ 'i18n/t': (key: string) => key,
866
+ 'cluster/all': (type: string) => {
867
+ if (type === SERVICE) {
868
+ return [mockService];
869
+ }
870
+
871
+ return [];
872
+ }
873
+ },
874
+ });
875
+
876
+ Object.defineProperty(workload, 'pods', { get: () => [mockPod] });
877
+
878
+ const rows = workload.resourcesCardRows;
879
+ const ingressesRow = rows.find((r: any) => r.label === 'component.resource.detail.card.resourcesCard.rows.ingresses');
880
+
881
+ expect(ingressesRow).toBeUndefined();
882
+ });
883
+ });
509
884
  });
@@ -0,0 +1,26 @@
1
+ import { escapeHtml } from '@shell/utils/string';
2
+ import SteveModel from '@shell/plugins/steve/steve-class';
3
+ import { CAPI } from '@shell/config/types';
4
+
5
+ export default class CapiMachineRoot extends SteveModel {
6
+ get cluster() {
7
+ if ( !this.spec.clusterName ) {
8
+ return null;
9
+ }
10
+
11
+ // This is used to get the cluster's human name
12
+ // Ideally we get this via the management cluster. To find it though we have to go via the provisioning cluster. So might as well just use that
13
+
14
+ const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
15
+
16
+ return this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
17
+ }
18
+
19
+ get clusterName() {
20
+ return this.cluster?.nameDisplay || this.spec.clusterName;
21
+ }
22
+
23
+ get groupByLabel() {
24
+ return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(this.clusterName) });
25
+ }
26
+ }
@@ -4,8 +4,10 @@ import { insertAt } from '@shell/utils/array';
4
4
  import { CLUSTER_REPO_APPCO_AUTH_GENERATE_NAME, CATALOG as CATALOG_TYPE } from '@shell/config/types';
5
5
  import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
6
6
  import { _CREATE } from '@shell/config/query-params';
7
+ import { formatDuration } from '@shell/utils/duration';
7
8
 
8
9
  import SteveModel from '@shell/plugins/steve/steve-class';
10
+ import { SUSE_APPCO_DISPLAY_NAME } from '@shell/utils/fleet-appco';
9
11
 
10
12
  export default class ClusterRepo extends SteveModel {
11
13
  applyDefaults() {
@@ -183,7 +185,7 @@ export default class ClusterRepo extends SteveModel {
183
185
 
184
186
  get typeDisplay() {
185
187
  if (this.isSuseAppCollectionFromUI) {
186
- return 'SUSE AppCo';
188
+ return SUSE_APPCO_DISPLAY_NAME;
187
189
  }
188
190
  if ( this.spec.gitRepo ) {
189
191
  return 'git';
@@ -218,15 +220,37 @@ export default class ClusterRepo extends SteveModel {
218
220
  return this.spec?.gitBranch || '(default)';
219
221
  }
220
222
 
223
+ get defaultRefreshIntervalHours() {
224
+ return this.isOciType ? 24 : 1;
225
+ }
226
+
227
+ get defaultRefreshInterval() {
228
+ return 60 * 60 * this.defaultRefreshIntervalHours;
229
+ }
230
+
231
+ get refreshIntervalDisplay() {
232
+ const val = this.spec?.refreshInterval;
233
+
234
+ if (val < 0) {
235
+ return this.t('generic.disabled');
236
+ }
237
+
238
+ return formatDuration(val ?? this.defaultRefreshInterval);
239
+ }
240
+
221
241
  get details() {
222
242
  return [
223
243
  {
224
- label: 'Type',
244
+ label: this.t('generic.type'),
225
245
  content: this.typeDisplay,
226
246
  },
227
247
  {
228
- label: 'Downloaded',
229
- content: this.status.downloadTime,
248
+ label: this.t('catalog.repo.refreshInterval.label'),
249
+ content: this.refreshIntervalDisplay,
250
+ },
251
+ {
252
+ label: this.t('catalog.repo.downloaded.label'),
253
+ content: this.status?.downloadTime,
230
254
  formatter: 'LiveDate',
231
255
  formatterOpts: { addSuffix: true },
232
256
  },
package/models/cluster.js CHANGED
@@ -69,6 +69,6 @@ export default class NormanCluster extends NormanModel {
69
69
  const id = this.provisioningClusterId;
70
70
 
71
71
  return id && !!this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, id);
72
- }, this.$rootGetters['i18n/t']('cluster.managementTimeout'), timeout, interval);
72
+ }, this.$rootGetters['i18n/t']('cluster.managementTimeout', { type: CAPI.RANCHER_CLUSTER, name: this.provisioningClusterId }), timeout, interval);
73
73
  }
74
74
  }
@@ -2,11 +2,10 @@ import { ADDRESSES, CAPI, NODE } from '@shell/config/types';
2
2
  import { CAPI as CAPI_LABELS, MACHINE_ROLES } from '@shell/config/labels-annotations';
3
3
  import { NAME as EXPLORER } from '@shell/config/product/explorer';
4
4
  import { listNodeRoles } from '@shell/models/cluster/node';
5
- import { escapeHtml } from '@shell/utils/string';
6
5
  import { insertAt, findBy } from '@shell/utils/array';
7
6
  import { get } from '@shell/utils/object';
8
7
  import { downloadUrl } from '@shell/utils/download';
9
- import SteveModel from '@shell/plugins/steve/steve-class';
8
+ import CapiMachineRoot from '@shell/models/base-cluster.x-k8s.io';
10
9
 
11
10
  /**
12
11
  * Prevent scaling down control plane or etcd machines to zero
@@ -53,7 +52,8 @@ export function notOnlyOfRole(current, all) {
53
52
 
54
53
  return false;
55
54
  }
56
- export default class CapiMachine extends SteveModel {
55
+
56
+ export default class CapiMachine extends CapiMachineRoot {
57
57
  get _availableActions() {
58
58
  const out = super._availableActions;
59
59
 
@@ -144,18 +144,6 @@ export default class CapiMachine extends SteveModel {
144
144
  return await this.$dispatch('find', { type: kind, id });
145
145
  }
146
146
 
147
- get cluster() {
148
- if ( !this.spec.clusterName ) {
149
- return null;
150
- }
151
-
152
- const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
153
-
154
- const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
155
-
156
- return cluster;
157
- }
158
-
159
147
  get poolName() {
160
148
  return this.metadata?.labels?.[ CAPI_LABELS.DEPLOYMENT_NAME ] || '';
161
149
  }
@@ -182,7 +170,7 @@ export default class CapiMachine extends SteveModel {
182
170
  return {
183
171
  name: 'c-cluster-product-resource-id',
184
172
  params: {
185
- cluster: this.cluster.status.clusterName,
173
+ cluster,
186
174
  product: EXPLORER,
187
175
  resource: NODE,
188
176
  id: kubeId
@@ -193,12 +181,6 @@ export default class CapiMachine extends SteveModel {
193
181
  return kubeId;
194
182
  }
195
183
 
196
- get groupByLabel() {
197
- const name = this.cluster?.nameDisplay || this.spec.clusterName;
198
-
199
- return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
200
- }
201
-
202
184
  get labels() {
203
185
  return this.metadata?.labels || {};
204
186
  }
@@ -1,33 +1,15 @@
1
1
  import { CAPI } from '@shell/config/types';
2
2
  import { escapeHtml } from '@shell/utils/string';
3
3
  import { sortBy } from '@shell/utils/sort';
4
- import SteveModel from '@shell/plugins/steve/steve-class';
5
4
  import { exceptionToErrorsArray } from '@shell/utils/error';
6
5
  import { handleConflict } from '@shell/plugins/dashboard-store/normalize';
7
6
  import { CAPI as CAPI_ANNOTATIONS, MACHINE_ROLES } from '@shell/config/labels-annotations';
8
7
  import { notOnlyOfRole } from '@shell/models/cluster.x-k8s.io.machine';
9
8
  import { KIND } from '../config/elemental-types';
10
9
  import { KIND as HARVESTER_KIND } from '../config/harvester-manager-types';
10
+ import CapiMachineRoot from '@shell/models/base-cluster.x-k8s.io';
11
11
 
12
- export default class CapiMachineDeployment extends SteveModel {
13
- get cluster() {
14
- if ( !this.spec.clusterName ) {
15
- return null;
16
- }
17
-
18
- const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
19
-
20
- const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
21
-
22
- return cluster;
23
- }
24
-
25
- get groupByLabel() {
26
- const name = this.cluster?.nameDisplay || this.spec.clusterName;
27
-
28
- return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
29
- }
30
-
12
+ export default class CapiMachineDeployment extends CapiMachineRoot {
31
13
  get groupByPoolLabel() {
32
14
  return `${ this.$rootGetters['i18n/t']('resourceTable.groupLabel.machinePool', { name: escapeHtml(this.nameDisplay) }) }`;
33
15
  }