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

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 (315) hide show
  1. package/assets/styles/global/_button.scss +1 -1
  2. package/assets/styles/global/_layout.scss +4 -0
  3. package/assets/translations/en-us.yaml +183 -51
  4. package/assets/translations/zh-hans.yaml +1 -7
  5. package/chart/monitoring/ClusterSelector.vue +0 -21
  6. package/chart/monitoring/prometheus/index.vue +6 -3
  7. package/components/ActionDropdownShell.vue +5 -3
  8. package/components/ButtonGroup.vue +26 -1
  9. package/components/CruResource.vue +212 -16
  10. package/components/ExplorerMembers.vue +8 -4
  11. package/components/ExplorerProjectsNamespaces.vue +10 -6
  12. package/components/GrowlManager.vue +4 -0
  13. package/components/MgmtNodeList.vue +184 -0
  14. package/components/PromptRestore.vue +93 -32
  15. package/components/Questions/index.vue +1 -0
  16. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
  17. package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
  18. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
  19. package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
  20. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +2 -0
  21. package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
  22. package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
  23. package/components/ResourceDetail/index.vue +1 -1
  24. package/components/ResourceList/Masthead.vue +7 -1
  25. package/components/ResourceList/index.vue +82 -1
  26. package/components/ResourceTable.vue +1 -0
  27. package/components/RichTranslation.vue +5 -2
  28. package/components/Setting.vue +1 -0
  29. package/components/SortableTable/index.vue +4 -3
  30. package/components/SubtleLink.vue +31 -6
  31. package/components/Tabbed/Tab.vue +29 -3
  32. package/components/Tabbed/index.vue +25 -3
  33. package/components/TableOfContents/TableOfContents.vue +109 -0
  34. package/components/TableOfContents/composables.ts +258 -0
  35. package/components/Window/ContainerShell.vue +21 -11
  36. package/components/Window/__tests__/ContainerShell.test.ts +107 -37
  37. package/components/Wizard.vue +23 -5
  38. package/components/__tests__/ButtonGroup.test.ts +56 -0
  39. package/components/__tests__/PromptRestore.test.ts +169 -19
  40. package/components/fleet/AppCoChartGrid.vue +401 -0
  41. package/components/fleet/AppCoEmptyState.vue +127 -0
  42. package/components/fleet/AppCoPageHeader.vue +119 -0
  43. package/components/fleet/AppCoVersionSelect.vue +70 -0
  44. package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
  45. package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
  46. package/components/fleet/FleetClusterTargets/index.vue +189 -146
  47. package/components/fleet/FleetIntro.vue +7 -3
  48. package/components/fleet/FleetNoWorkspaces.vue +7 -3
  49. package/components/fleet/FleetSecretSelector.vue +5 -3
  50. package/components/fleet/FleetValuesFrom.vue +8 -2
  51. package/components/fleet/GitRepoAdvancedTab.vue +1 -0
  52. package/components/fleet/GitRepoMetadataTab.vue +5 -0
  53. package/components/fleet/GitRepoTargetTab.vue +0 -2
  54. package/components/fleet/HelmOpAdvancedTab.vue +19 -53
  55. package/components/fleet/HelmOpAppCoConfigTab.vue +597 -0
  56. package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
  57. package/components/fleet/HelmOpMetadataTab.vue +5 -0
  58. package/components/fleet/HelmOpResourcesSection.vue +82 -0
  59. package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
  60. package/components/fleet/HelmOpTargetTab.vue +64 -60
  61. package/components/fleet/HelmOpValuesTab.vue +129 -105
  62. package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
  63. package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
  64. package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
  65. package/components/fleet/__tests__/FleetClusterTargets.test.ts +253 -0
  66. package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
  67. package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
  68. package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
  69. package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
  70. package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
  71. package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
  72. package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
  73. package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
  74. package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
  75. package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
  76. package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
  77. package/components/fleet/dashboard/Empty.vue +8 -4
  78. package/components/fleet/dashboard/ResourceCard.vue +28 -0
  79. package/components/fleet/dashboard/ResourceDetails.vue +28 -0
  80. package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
  81. package/components/form/ArrayList.vue +61 -4
  82. package/components/form/FileSelector.vue +39 -1
  83. package/components/form/KeyValue.vue +23 -2
  84. package/components/form/LabeledSelect.vue +39 -1
  85. package/components/form/Labels.vue +22 -3
  86. package/components/form/NameNsDescription.vue +13 -5
  87. package/components/form/PrivateRegistry.constants.ts +7 -0
  88. package/components/form/PrivateRegistry.vue +253 -18
  89. package/components/form/ResourceTabs/index.vue +1 -0
  90. package/components/form/SelectOrCreateAuthSecret.vue +140 -17
  91. package/components/form/__tests__/FileSelector.test.ts +23 -0
  92. package/components/form/__tests__/NameNsDescription.test.ts +75 -0
  93. package/components/form/__tests__/PrivateRegistry.test.ts +463 -73
  94. package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +122 -0
  95. package/components/formatter/EtcdSnapshotName.vue +73 -0
  96. package/components/formatter/InternalExternalIP.vue +10 -4
  97. package/components/formatter/ServiceTargets.vue +26 -7
  98. package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
  99. package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
  100. package/components/nav/Header.vue +12 -1
  101. package/components/nav/TopLevelMenu.vue +7 -2
  102. package/components/nav/__tests__/Header.test.ts +15 -0
  103. package/components/nav/__tests__/TopLevelMenu.test.ts +120 -2
  104. package/components/templates/default.vue +16 -4
  105. package/components/templates/home.vue +9 -4
  106. package/components/templates/plain.vue +9 -4
  107. package/composables/useHelmOpResources.test.ts +56 -0
  108. package/composables/useHelmOpResources.ts +32 -0
  109. package/composables/useStateColor.test.ts +325 -0
  110. package/composables/useStateColor.ts +128 -0
  111. package/config/features.js +1 -0
  112. package/config/home-links.js +1 -1
  113. package/config/labels-annotations.js +3 -0
  114. package/config/product/explorer.js +17 -4
  115. package/config/product/manager.js +8 -0
  116. package/config/router/index.js +16 -0
  117. package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
  118. package/config/router/navigation-guards/authentication.js +10 -4
  119. package/config/router/routes.js +20 -6
  120. package/config/secret.ts +10 -0
  121. package/config/settings.ts +6 -4
  122. package/config/table-headers.js +3 -4
  123. package/config/types.js +16 -0
  124. package/core/plugin-products-base.ts +3 -3
  125. package/core/plugin-types.ts +83 -30
  126. package/core/plugin.ts +3 -0
  127. package/core/types-provisioning.ts +34 -1
  128. package/core/types.ts +15 -2
  129. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
  130. package/detail/__tests__/workload.test.ts +3 -152
  131. package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
  132. package/detail/provisioning.cattle.io.cluster.vue +109 -7
  133. package/detail/workload/index.vue +12 -55
  134. package/dialog/RotateEncryptionKeyDialog.vue +33 -9
  135. package/dialog/__tests__/RotateEncryptionKeyDialog.test.ts +78 -0
  136. package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
  137. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +92 -0
  138. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +206 -0
  139. package/edit/__tests__/management.cattle.io.setting.test.ts +2 -1
  140. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  141. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
  142. package/edit/auth/__tests__/azuread.test.ts +34 -9
  143. package/edit/auth/__tests__/github.test.ts +234 -0
  144. package/edit/auth/__tests__/oidc.test.ts +26 -6
  145. package/edit/auth/__tests__/saml.test.ts +196 -0
  146. package/edit/auth/azuread.vue +128 -95
  147. package/edit/auth/github.vue +72 -13
  148. package/edit/auth/ldap/__tests__/index.test.ts +206 -0
  149. package/edit/auth/ldap/config.vue +8 -0
  150. package/edit/auth/ldap/index.vue +75 -1
  151. package/edit/auth/oidc.vue +119 -73
  152. package/edit/auth/saml.vue +76 -12
  153. package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
  154. package/edit/compliance.cattle.io.clusterscanprofile.vue +39 -41
  155. package/edit/fleet.cattle.io.gitrepo.vue +70 -16
  156. package/edit/fleet.cattle.io.helmop.vue +542 -141
  157. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  158. package/edit/{management.cattle.io.setting.vue → management.cattle.io.setting/index.vue} +32 -9
  159. package/edit/management.cattle.io.setting/system-default-registry-pull-secrets.vue +81 -0
  160. package/edit/management.cattle.io.user.vue +5 -2
  161. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -12
  162. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +18 -0
  163. package/edit/provisioning.cattle.io.cluster/rke2.vue +89 -11
  164. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
  165. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +0 -1
  166. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +14 -55
  167. package/list/group.principal.vue +5 -4
  168. package/list/harvesterhci.io.management.cluster.vue +8 -9
  169. package/list/management.cattle.io.user.vue +12 -9
  170. package/list/provisioning.cattle.io.cluster.vue +16 -10
  171. package/mixins/__tests__/auth-config.test.ts +90 -0
  172. package/mixins/__tests__/chart.test.ts +94 -0
  173. package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
  174. package/mixins/auth-config.js +7 -0
  175. package/mixins/chart.js +11 -2
  176. package/mixins/child-hook.js +12 -6
  177. package/mixins/create-edit-view/impl.js +5 -3
  178. package/mixins/resource-fetch-api-pagination.js +21 -1
  179. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
  180. package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
  181. package/models/__tests__/fleet-application.test.ts +175 -0
  182. package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
  183. package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
  184. package/models/__tests__/management.cattle.io.node.ts +22 -0
  185. package/models/__tests__/namespace.test.ts +36 -0
  186. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +205 -0
  187. package/models/__tests__/secret.test.ts +68 -1
  188. package/models/__tests__/workload.test.ts +401 -26
  189. package/models/catalog.cattle.io.clusterrepo.js +28 -4
  190. package/models/compliance.cattle.io.clusterscan.js +39 -4
  191. package/models/fleet-application.js +4 -0
  192. package/models/fleet.cattle.io.helmop.js +20 -1
  193. package/models/management.cattle.io.cluster.js +39 -5
  194. package/models/management.cattle.io.node.js +44 -3
  195. package/models/namespace.js +1 -1
  196. package/models/pod.js +46 -3
  197. package/models/provisioning.cattle.io.cluster.js +64 -14
  198. package/models/rke.cattle.io.etcdsnapshot.js +17 -9
  199. package/models/secret.js +19 -0
  200. package/models/workload.js +120 -20
  201. package/models/workload.service.js +5 -0
  202. package/package.json +14 -13
  203. package/pages/about.vue +5 -6
  204. package/pages/auth/login.vue +0 -35
  205. package/pages/auth/setup.vue +11 -0
  206. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
  207. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
  208. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
  209. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +485 -107
  210. package/pages/c/_cluster/apps/charts/chart.vue +2 -1
  211. package/pages/c/_cluster/apps/charts/index.vue +48 -10
  212. package/pages/c/_cluster/apps/charts/install.vue +236 -144
  213. package/pages/c/_cluster/auth/roles/index.vue +5 -4
  214. package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
  215. package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
  216. package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
  217. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
  218. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
  219. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
  220. package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
  221. package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
  222. package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
  223. package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
  224. package/pages/c/_cluster/fleet/application/create.vue +187 -136
  225. package/pages/c/_cluster/fleet/application/index.vue +5 -3
  226. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
  227. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
  228. package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
  229. package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
  230. package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
  231. package/pages/c/_cluster/fleet/index.vue +2 -2
  232. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +96 -0
  233. package/pages/c/_cluster/uiplugins/index.vue +15 -0
  234. package/pages/fail-whale.vue +16 -11
  235. package/pages/home.vue +16 -46
  236. package/pkg/require-asset.lib.js +25 -0
  237. package/pkg/vue.config.js +7 -0
  238. package/plugins/clean-html.d.ts +9 -0
  239. package/plugins/dashboard-store/__tests__/resource-class.test.ts +177 -0
  240. package/plugins/dashboard-store/getters.js +0 -1
  241. package/plugins/dashboard-store/resource-class.js +114 -19
  242. package/plugins/steve/__tests__/actions.test.ts +212 -0
  243. package/plugins/steve/actions.js +96 -0
  244. package/plugins/steve/steve-pagination-utils.ts +1 -1
  245. package/rancher-components/Accordion/Accordion.vue +53 -9
  246. package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
  247. package/rancher-components/Form/Radio/RadioButton.vue +17 -1
  248. package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
  249. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +30 -0
  250. package/rancher-components/Form/TextArea/__tests__/TextAreaAutoGrow.test.ts +95 -0
  251. package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
  252. package/rancher-components/RcButton/RcButton.test.ts +103 -0
  253. package/rancher-components/RcButton/RcButton.vue +94 -15
  254. package/rancher-components/RcButton/index.ts +1 -1
  255. package/rancher-components/RcButton/types.ts +3 -0
  256. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +6 -1
  257. package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
  258. package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
  259. package/rancher-components/RcSection/RcSection.vue +28 -3
  260. package/scripts/extension/helm/package/Dockerfile +1 -1
  261. package/scripts/test-plugins-build.sh +2 -1
  262. package/store/__tests__/features.test.ts +131 -0
  263. package/store/__tests__/growl.test.ts +374 -0
  264. package/store/__tests__/modal.test.ts +131 -0
  265. package/store/__tests__/notifications.test.ts +434 -0
  266. package/store/__tests__/slideInPanel.test.ts +88 -0
  267. package/store/__tests__/type-map.utils.test.ts +433 -0
  268. package/store/catalog.js +57 -0
  269. package/store/features.js +4 -0
  270. package/store/plugins.js +7 -4
  271. package/types/components/buttonGroup.ts +5 -0
  272. package/types/shell/index.d.ts +166 -70
  273. package/utils/__tests__/auth.test.ts +273 -0
  274. package/utils/__tests__/computed.test.ts +193 -0
  275. package/utils/__tests__/cspAdaptor.test.ts +163 -0
  276. package/utils/__tests__/dom.test.ts +81 -0
  277. package/utils/__tests__/duration.test.ts +37 -1
  278. package/utils/__tests__/dynamic-importer.test.ts +102 -0
  279. package/utils/__tests__/fleet-appco.test.ts +312 -0
  280. package/utils/__tests__/monitoring.test.ts +130 -0
  281. package/utils/__tests__/object.test.ts +22 -0
  282. package/utils/__tests__/operation-cr.test.ts +34 -0
  283. package/utils/__tests__/platform.test.ts +91 -0
  284. package/utils/__tests__/position.test.ts +237 -0
  285. package/utils/__tests__/provider.test.ts +51 -1
  286. package/utils/__tests__/queue.test.ts +232 -0
  287. package/utils/__tests__/release-notes.test.ts +221 -0
  288. package/utils/__tests__/router.test.js +254 -1
  289. package/utils/__tests__/select.test.ts +208 -0
  290. package/utils/__tests__/time.test.ts +265 -1
  291. package/utils/__tests__/title.test.ts +47 -0
  292. package/utils/__tests__/width.test.ts +53 -0
  293. package/utils/__tests__/window.test.ts +158 -0
  294. package/utils/__tests__/xccdf.test.ts +126 -6
  295. package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
  296. package/utils/crypto/__tests__/index.test.ts +144 -0
  297. package/utils/duration.ts +104 -0
  298. package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
  299. package/utils/dynamic-content/info.ts +2 -1
  300. package/utils/error.js +13 -0
  301. package/utils/fleet-appco.ts +323 -0
  302. package/utils/object.js +22 -2
  303. package/utils/operation-cr.js +19 -0
  304. package/utils/provider.ts +12 -0
  305. package/utils/require-asset.ts +7 -0
  306. package/utils/validators/__tests__/container-images.test.ts +104 -0
  307. package/utils/validators/__tests__/flow-output.test.ts +91 -0
  308. package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
  309. package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
  310. package/utils/validators/__tests__/private-registry.test.ts +27 -15
  311. package/utils/validators/private-registry.ts +15 -4
  312. package/utils/xccdf.ts +39 -42
  313. package/vue.config.js +1 -1
  314. package/pages/support/index.vue +0 -264
  315. package/utils/duration.js +0 -43
@@ -1,4 +1,4 @@
1
- import { CATALOG, CLUSTER_BADGE, NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
1
+ import { CATALOG, CLUSTER_BADGE, NODE_ARCHITECTURE, OPERATION_ANNOTATIONS } from '@shell/config/labels-annotations';
2
2
  import {
3
3
  NODE, FLEET, MANAGEMENT, CAPI, EXT,
4
4
  NORMAN,
@@ -9,7 +9,7 @@ import { downloadFile } from '@shell/utils/download';
9
9
  import { parseSi } from '@shell/utils/units';
10
10
  import { parseColor, textColor } from '@shell/utils/color';
11
11
  import { isEmpty, isEqual } from '@shell/utils/object';
12
- import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
12
+ import { HARVESTER_NAME as HARVESTER, IMPORTED_DAY_2_OPS } from '@shell/config/features';
13
13
  import { isHarvesterCluster } from '@shell/utils/cluster';
14
14
  import SteveModel from '@shell/plugins/steve/steve-class';
15
15
  import { LINUX, WINDOWS } from '@shell/store/catalog';
@@ -17,10 +17,10 @@ import { KEV1 } from './management.cattle.io.kontainerdriver';
17
17
  import { requireAsset } from '@shell/utils/require-asset';
18
18
  import { PINNED_CLUSTERS } from '@shell/store/prefs';
19
19
  import { copyTextToClipboard } from '@shell/utils/clipboard';
20
- import { isHostedProvider } from '@shell/utils/provider';
20
+ import { isHostedProvider, isCAPIProvider } from '@shell/utils/provider';
21
21
  import { ucFirst } from '@shell/utils/string';
22
22
  import { sortBy } from '@shell/utils/sort';
23
-
23
+ import { SETTING } from '@shell/config/settings';
24
24
  const DEFAULT_BADGE_COLOR = '#707070';
25
25
 
26
26
  // See translation file cluster.providers for list of providers
@@ -180,7 +180,7 @@ export default class MgmtCluster extends SteveModel {
180
180
  }
181
181
 
182
182
  get machineProvider() {
183
- return this.status?.info.machineProvider;
183
+ return this.status?.info?.machineProvider;
184
184
  }
185
185
 
186
186
  get machineProviderDisplay() {
@@ -261,6 +261,22 @@ export default class MgmtCluster extends SteveModel {
261
261
  return !!capiMachines;
262
262
  }
263
263
 
264
+ get isCAPIProvider() {
265
+ if (!this.isCapiHybrid || !this.machineProvider) {
266
+ return false;
267
+ }
268
+
269
+ const context = {
270
+ dispatch: this.$dispatch,
271
+ getters: this.$getters,
272
+ axios: this.$axios,
273
+ $extension: this.$extension,
274
+ t: (...args) => this.t.apply(this, args),
275
+ };
276
+
277
+ return isCAPIProvider(context, this.machineProvider.toLowerCase());
278
+ }
279
+
264
280
  get isHostedKubernetesProvider() {
265
281
  const context = {
266
282
  dispatch: this.$dispatch,
@@ -373,6 +389,24 @@ export default class MgmtCluster extends SteveModel {
373
389
  return this.spec?.internal === true;
374
390
  }
375
391
 
392
+ get isDayTwoOpsFeatureEnabled() {
393
+ return this.$rootGetters['management/byId'](MANAGEMENT.FEATURE, IMPORTED_DAY_2_OPS)?.enabled || false;
394
+ }
395
+
396
+ /**
397
+ * Whether day 2 operations are enabled for this cluster.
398
+ * Reads the `operations.cattle.io/ops-enabled` annotation.
399
+ */
400
+ get isDayTwoOpsEnabled() {
401
+ const isImportedRke2K3s = !this.isLocal && (this.isImportedK3s || this.isImportedRke2);
402
+ const annotationExists = typeof this.metadata?.annotations?.[OPERATION_ANNOTATIONS.ENABLED] !== 'undefined';
403
+ const annotationEnabled = this.metadata?.annotations?.[OPERATION_ANNOTATIONS.ENABLED] === 'true';
404
+ const globalDefaultIsTrue = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.IMPORTED_CLUSTER_DAY2_OPS_DEFAULT)?.value === 'true';
405
+ const annotationEnabledOrDefault = annotationExists ? annotationEnabled : globalDefaultIsTrue;
406
+
407
+ return this.isDayTwoOpsFeatureEnabled && isImportedRke2K3s && annotationEnabledOrDefault;
408
+ }
409
+
376
410
  get isHarvester() {
377
411
  return isHarvesterCluster(this);
378
412
  }
@@ -10,7 +10,8 @@ import { notOnlyOfRole } from '@shell/models/cluster.x-k8s.io.machine';
10
10
  const RKE1_ALLOWED_ACTIONS = [
11
11
  'goToViewYaml',
12
12
  'download',
13
- 'viewInApi'
13
+ 'viewInApi',
14
+ 'showConfiguration'
14
15
  ];
15
16
 
16
17
  export default class MgmtNode extends HybridModel {
@@ -63,6 +64,10 @@ export default class MgmtNode extends HybridModel {
63
64
  }
64
65
 
65
66
  get pool() {
67
+ if (!this.spec?.nodePoolName) {
68
+ return undefined;
69
+ }
70
+
66
71
  const nodePoolID = this.spec.nodePoolName.replace(':', '/');
67
72
 
68
73
  return this.$rootGetters['management/byId'](MANAGEMENT.NODE_POOL, nodePoolID);
@@ -118,6 +123,42 @@ export default class MgmtNode extends HybridModel {
118
123
  return this.status?.addresses || this.status?.internalNodeStatus?.addresses || [];
119
124
  }
120
125
 
126
+ get internalIps() {
127
+ const internal = this.addresses.filter(({ type }) => {
128
+ return type === ADDRESSES.INTERNAL_IP;
129
+ });
130
+
131
+ if (!internal.length) {
132
+ // For RKE1 clusters in EC2, node addresses are
133
+ // under status.rkeNode.address and status.rkeNode.internalAddress
134
+ if (this.status?.rkeNode) {
135
+ return this.status.rkeNode.internalAddress ? [this.status.rkeNode.internalAddress] : [];
136
+ }
137
+
138
+ return [];
139
+ }
140
+
141
+ return internal.map(({ address }) => address);
142
+ }
143
+
144
+ get externalIps() {
145
+ const external = this.addresses.filter(({ type }) => {
146
+ return type === ADDRESSES.EXTERNAL_IP;
147
+ });
148
+
149
+ if (!external.length) {
150
+ // For RKE1 clusters in EC2, node addresses are
151
+ // under status.rkeNode.address and status.rkeNode.internalAddress
152
+ if (this.status?.rkeNode) {
153
+ return this.status.rkeNode.address ? [this.status.rkeNode.address] : [];
154
+ }
155
+
156
+ return [];
157
+ }
158
+
159
+ return external.map(({ address }) => address);
160
+ }
161
+
121
162
  get internalIp() {
122
163
  // This shows in the IP address column for RKE1 nodes in the
123
164
  // list of nodes in the cluster detail page of Cluster Management.
@@ -131,7 +172,7 @@ export default class MgmtNode extends HybridModel {
131
172
 
132
173
  // For RKE1 clusters in EC2, node addresses are
133
174
  // under status.rkeNode.address and status.rkeNode.internalAddress
134
- if (!internal && this.status.rkeNode) {
175
+ if (!internal && this.status?.rkeNode) {
135
176
  return this.status.rkeNode.internalAddress;
136
177
  }
137
178
 
@@ -147,7 +188,7 @@ export default class MgmtNode extends HybridModel {
147
188
 
148
189
  // For RKE1 clusters in EC2, node addresses are
149
190
  // under status.rkeNode.address and status.rkeNode.internalAddress
150
- if (!statusAddress && this.status.rkeNode) {
191
+ if (!statusAddress && this.status?.rkeNode) {
151
192
  return this.status.rkeNode.address;
152
193
  }
153
194
 
@@ -68,7 +68,7 @@ export default class Namespace extends SteveModel {
68
68
  label: this.t('namespace.move'),
69
69
  bulkable: true,
70
70
  bulkAction: 'move',
71
- enabled: true,
71
+ enabled: this.canUpdate,
72
72
  icon: 'icon icon-fork',
73
73
  weight: 3,
74
74
  });
package/models/pod.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import { insertAt } from '@shell/utils/array';
2
- import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
2
+ import { colorForState, simpleColorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
3
3
  import { NODE, WORKLOAD_TYPES } from '@shell/config/types';
4
4
  import { escapeHtml, shortenedImage } from '@shell/utils/string';
5
5
  import WorkloadService from '@shell/models/workload.service';
6
6
  import { deleteProperty } from '@shell/utils/object';
7
7
  import { POD_RESTARTS_REG_EX } from '@shell/types/resources/pod';
8
+ import { useResourceCardRow } from '@shell/components/Resource/Detail/Card/StateCard/composables';
9
+ import { POD_SHELL } from '@shell/store/features';
8
10
 
9
11
  export const WORKLOAD_PRIORITY = {
10
12
  [WORKLOAD_TYPES.DEPLOYMENT]: 1,
@@ -63,11 +65,16 @@ export default class Pod extends WorkloadService {
63
65
 
64
66
  get _availableActions() {
65
67
  const out = super._availableActions;
68
+ const podShellFeatureEnabled = !!this.$rootGetters['features/get'](POD_SHELL);
66
69
 
67
70
  // Add backwards, each one to the top
68
71
  insertAt(out, 0, { divider: true });
69
72
  insertAt(out, 0, this.openLogsMenuItem);
70
- insertAt(out, 0, this.openShellMenuItem);
73
+
74
+ // Only add the menu item for the pod shell if the feature flag is enabled
75
+ if (podShellFeatureEnabled) {
76
+ insertAt(out, 0, this.openShellMenuItem);
77
+ }
71
78
 
72
79
  return out;
73
80
  }
@@ -94,9 +101,14 @@ export default class Pod extends WorkloadService {
94
101
 
95
102
  get containerActions() {
96
103
  const out = [];
104
+ const podShellFeatureEnabled = !!this.$rootGetters['features/get'](POD_SHELL);
97
105
 
98
106
  insertAt(out, 0, this.openLogsMenuItem);
99
- insertAt(out, 0, this.openShellMenuItem);
107
+
108
+ // Only add the menu item for the container shell if the feature flag is enabled
109
+ if (podShellFeatureEnabled) {
110
+ insertAt(out, 0, this.openShellMenuItem);
111
+ }
100
112
 
101
113
  return out;
102
114
  }
@@ -156,6 +168,37 @@ export default class Pod extends WorkloadService {
156
168
  return initContainers.includes(container);
157
169
  }
158
170
 
171
+ get resourceContainers() {
172
+ const statuses = [...(this.status?.containerStatuses || []), ...(this.status?.initContainerStatuses || [])];
173
+
174
+ return statuses.map((s) => {
175
+ const state = Object.keys(s.state || {})[0] || 'unknown';
176
+
177
+ return {
178
+ stateDisplay: stateDisplay(state),
179
+ stateSimpleColor: simpleColorForState(state),
180
+ };
181
+ });
182
+ }
183
+
184
+ get resourcesCardRows() {
185
+ const rows = [...this._resourcesCardRows];
186
+
187
+ if (this.resourceContainers.length) {
188
+ rows.unshift(useResourceCardRow(this.t('workload.container.titles.containers'), this.resourceContainers, 'stateSimpleColor', 'stateDisplay', '#containers'));
189
+ }
190
+
191
+ return rows;
192
+ }
193
+
194
+ get cards() {
195
+ return [
196
+ this.resourcesCard,
197
+ this.insightCard,
198
+ ...this._cards
199
+ ].filter((c) => c);
200
+ }
201
+
159
202
  get imageNames() {
160
203
  return this.spec.containers.map((container) => shortenedImage(container.image));
161
204
  }
@@ -1,13 +1,16 @@
1
1
  import {
2
2
  CAPI, MANAGEMENT, NAMESPACE, NORMAN, SNAPSHOT, LOCAL_CLUSTER,
3
3
  CONFIG_MAP, AUTOSCALER_CONFIG_MAP_ID,
4
- EVENT
4
+ EVENT, OPERATION
5
5
  } from '@shell/config/types';
6
6
  import SteveModel from '@shell/plugins/steve/steve-class';
7
7
  import { findBy } from '@shell/utils/array';
8
8
  import { get, set } from '@shell/utils/object';
9
9
  import { compare } from '@shell/utils/version';
10
- import { CAPI as CAPI_ANNOTATIONS } from '@shell/config/labels-annotations';
10
+ import { IMPORTED_DAY_2_OPS } from '@shell/config/features';
11
+ import { CAPI as CAPI_ANNOTATIONS, OPERATION_ANNOTATIONS } from '@shell/config/labels-annotations';
12
+ import { SETTING } from '@shell/config/settings';
13
+ import { createOperationCR } from '@shell/utils/operation-cr';
11
14
  import jsyaml from 'js-yaml';
12
15
  import { defineAsyncComponent, markRaw } from 'vue';
13
16
  import stevePaginationUtils from '@shell/plugins/steve/steve-pagination-utils';
@@ -97,7 +100,7 @@ export default class ProvCluster extends SteveModel {
97
100
 
98
101
  get canEdit() {
99
102
  // If the cluster is a KEV1 cluster, Harvester cluster, or v2 provisioning cluster that uses upstream capi infrastructure providers, then prevent edit
100
- if (this.isKev1 || this.isHarvester || this.isCapiHybrid) {
103
+ if (this.isKev1 || this.isHarvester || this.isCapiWithoutExtension) {
101
104
  return false;
102
105
  }
103
106
 
@@ -105,7 +108,7 @@ export default class ProvCluster extends SteveModel {
105
108
  }
106
109
 
107
110
  get canCustomEdit() {
108
- return !this.isCapiHybrid && super.canCustomEdit;
111
+ return !this.isCapiWithoutExtension && super.canCustomEdit;
109
112
  }
110
113
 
111
114
  get _availableActions() {
@@ -122,10 +125,9 @@ export default class ProvCluster extends SteveModel {
122
125
  }
123
126
  const ready = this.mgmt?.isReady;
124
127
 
128
+ const canDayTwoOps = ready && this.isDayTwoOpsEnabled && this.canUpdate;
125
129
  const canEditRKE2cluster = this.isRke2 && ready && this.canUpdate;
126
130
 
127
- const canSnapshot = ready && this.isRke2 && this.canUpdate;
128
-
129
131
  const actions = [
130
132
  // Note: Actions are not supported in the Steve API, so we check
131
133
  // available actions for RKE1 clusters, but not RKE2 clusters.
@@ -153,12 +155,12 @@ export default class ProvCluster extends SteveModel {
153
155
  icon: 'icon icon-snapshot',
154
156
  bulkAction: 'snapshotBulk',
155
157
  bulkable: true,
156
- enabled: canSnapshot,
158
+ enabled: canDayTwoOps,
157
159
  }, {
158
160
  action: 'restoreSnapshotAction',
159
161
  label: this.$rootGetters['i18n/t']('nav.restoreSnapshot'),
160
162
  icon: 'icon icon-backup-restore',
161
- enabled: canSnapshot,
163
+ enabled: canDayTwoOps,
162
164
  }, {
163
165
  action: 'rotateCertificates',
164
166
  label: this.$rootGetters['i18n/t']('nav.rotateCertificates'),
@@ -168,7 +170,7 @@ export default class ProvCluster extends SteveModel {
168
170
  action: 'rotateEncryptionKey',
169
171
  label: this.$rootGetters['i18n/t']('nav.rotateEncryptionKeys'),
170
172
  icon: 'icon icon-refresh',
171
- enabled: canEditRKE2cluster
173
+ enabled: canDayTwoOps
172
174
  },
173
175
  {
174
176
  action: 'toggleAutoscalerRunner',
@@ -301,6 +303,35 @@ export default class ProvCluster extends SteveModel {
301
303
  return this.mgmt?.isImportedRke2;
302
304
  }
303
305
 
306
+ get isImportedRke2K3s() {
307
+ return this.isImportedRke2 || this.isImportedK3s;
308
+ }
309
+
310
+ /**
311
+ * Whether day 2 operations (snapshot, restore, cert rotation, encryption key rotation)
312
+ * are enabled for this cluster.
313
+ */
314
+ get isDayTwoOpsEnabled() {
315
+ return !!(this.isRke2 || this.isImportedWithDayTwoOps);
316
+ }
317
+
318
+ get isDayTwoOpsFeatureEnabled() {
319
+ return this.$rootGetters['management/byId'](MANAGEMENT.FEATURE, IMPORTED_DAY_2_OPS)?.enabled || false;
320
+ }
321
+
322
+ /**
323
+ * Whether this is an imported RKE2/K3s cluster with day 2 operations enabled.
324
+ */
325
+ get isImportedWithDayTwoOps() {
326
+ const annotationExists = typeof this.metadata?.annotations?.[OPERATION_ANNOTATIONS.ENABLED] !== 'undefined';
327
+ const annotationEnabled = this.mgmt?.metadata?.annotations?.[OPERATION_ANNOTATIONS.ENABLED] === 'true';
328
+ const globalDefaultIsTrue = this.$rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.IMPORTED_CLUSTER_DAY2_OPS_DEFAULT)?.value === 'true';
329
+ const annotationOrGlobalEnabled = annotationEnabled || (!annotationExists && globalDefaultIsTrue);
330
+ const canGetOpSchema = this.$getters['schemaFor'](OPERATION.ETCD_SNAPSHOT);
331
+
332
+ return !this.isLocal && canGetOpSchema && this.isDayTwoOpsFeatureEnabled && this.isImportedRke2K3s && annotationOrGlobalEnabled;
333
+ }
334
+
304
335
  get isK3s() {
305
336
  return this.mgmt?.isK3s;
306
337
  }
@@ -319,8 +350,8 @@ export default class ProvCluster extends SteveModel {
319
350
  }
320
351
 
321
352
  // identify v2 provisioning clusters created using upstream capi infrastructure providers instead of rancher/machine
322
- get isCapiHybrid() {
323
- return this.mgmt?.isCapiHybrid;
353
+ get isCapiWithoutExtension() {
354
+ return this.mgmt?.isCapiHybrid && !this.mgmt?.isCAPIProvider;
324
355
  }
325
356
 
326
357
  get mgmtClusterId() {
@@ -565,6 +596,21 @@ export default class ProvCluster extends SteveModel {
565
596
  url: `/v3/clusters/${ escape(this.mgmt.id) }?action=backupEtcd`,
566
597
  method: 'post',
567
598
  }, { root: true });
599
+ } else if ( this.isImportedWithDayTwoOps ) {
600
+ // For imported clusters with day 2 ops, create an operation CRD
601
+ const namespace = this.mgmt?.id;
602
+ const safePrefix = this.mgmt?.metadata?.name || this.mgmt?.id;
603
+ const spec = {
604
+ clusterRef: {
605
+ apiVersion: 'management.cattle.io/v3',
606
+ kind: 'Cluster',
607
+ name: this.mgmt?.id,
608
+ }
609
+ };
610
+
611
+ return createOperationCR(this.$dispatch, OPERATION.ETCD_SNAPSHOT, spec, namespace, safePrefix);
612
+ } else if (this.isImportedRke2K3s && !this.isDayTwoOpsFeatureEnabled) {
613
+ throw new Error(this.$rootGetters['i18n/t']('cluster.snapshot.day2OpsNotEnabled'));
568
614
  } else {
569
615
  const now = this.spec?.rkeConfig?.etcdSnapshotCreate?.generation || 0;
570
616
  const args = { generation: now + 1 };
@@ -582,6 +628,11 @@ export default class ProvCluster extends SteveModel {
582
628
  get etcdSnapshots() {
583
629
  const allSnapshots = this.$rootGetters['management/all']({ type: SNAPSHOT });
584
630
 
631
+ if (this.isImportedWithDayTwoOps) {
632
+ return allSnapshots
633
+ .filter((s) => s.metadata.namespace === this.mgmt?.id && s.spec?.clusterName === this.mgmt?.metadata?.name );
634
+ }
635
+
585
636
  return allSnapshots
586
637
  .filter((s) => s.metadata.namespace === this.namespace && s.clusterName === this.name );
587
638
  }
@@ -593,8 +644,7 @@ export default class ProvCluster extends SteveModel {
593
644
  rotateCertificates(cluster = this) {
594
645
  this.$dispatch('promptModal', {
595
646
  componentProps: { cluster },
596
-
597
- component: 'RotateCertificatesDialog'
647
+ component: 'RotateCertificatesDialog'
598
648
  });
599
649
  }
600
650
 
@@ -789,7 +839,7 @@ export default class ProvCluster extends SteveModel {
789
839
  }
790
840
 
791
841
  get disableResourceDetailDrawerConfigTab() {
792
- return !!this.isHarvester || this.isCapiHybrid;
842
+ return !!this.isHarvester || this.isCapiWithoutExtension;
793
843
  }
794
844
 
795
845
  get fullDetailPageOverride() {
@@ -1,6 +1,6 @@
1
1
  import NormanModel from '@shell/plugins/steve/norman-class';
2
2
  import { SNAPSHOT } from '@shell/config/labels-annotations';
3
- import { CAPI } from '@shell/config/types';
3
+ import { CAPI, DEFAULT_WORKSPACE } from '@shell/config/types';
4
4
  import { get } from '@shell/utils/object';
5
5
  import { base64Decode } from '@shell/utils/crypto';
6
6
  import { ucFirst } from '@shell/utils/string';
@@ -11,13 +11,11 @@ export default class EtcdBackup extends NormanModel {
11
11
  * Restrict actions for snapshots to restore only
12
12
  */
13
13
  get _availableActions() {
14
- const enabled = this.snapshotFile?.status === STATES_ENUM.SUCCESSFUL;
15
-
16
14
  return [{
17
- action: 'promptRestore',
18
- enabled,
19
- icon: 'icon icon-backup-restore',
20
- label: 'Restore'
15
+ action: 'promptRestore',
16
+ enabled: this.restoreEnabled,
17
+ icon: 'icon icon-backup-restore',
18
+ label: 'Restore'
21
19
  }];
22
20
  }
23
21
 
@@ -30,7 +28,7 @@ export default class EtcdBackup extends NormanModel {
30
28
  }
31
29
 
32
30
  get clusterId() {
33
- return this.cluster.id;
31
+ return this.cluster?.id;
34
32
  }
35
33
 
36
34
  get name() {
@@ -38,7 +36,9 @@ export default class EtcdBackup extends NormanModel {
38
36
  }
39
37
 
40
38
  get cluster() {
41
- return this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, `${ this.metadata.namespace }/${ this.clusterName }`);
39
+ const ns = this.metadata?.namespace || DEFAULT_WORKSPACE;
40
+
41
+ return this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, `${ ns }/${ this.clusterName }`);
42
42
  }
43
43
 
44
44
  get rke2() {
@@ -49,6 +49,14 @@ export default class EtcdBackup extends NormanModel {
49
49
  return this.snapshotFile?.name || this.name;
50
50
  }
51
51
 
52
+ get restoreEnabled() {
53
+ return this.snapshotFile?.status === STATES_ENUM.SUCCESSFUL && !this.isSnapshotTooOld;
54
+ }
55
+
56
+ get isSnapshotTooOld() {
57
+ return this.snapshotFile?.createdAt <= this.cluster?.metadata?.creationTimestamp;
58
+ }
59
+
52
60
  get errorMessage() {
53
61
  const inError = get(this, 'snapshotFile.status') === STATES_ENUM.FAILED;
54
62
 
package/models/secret.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import r from 'jsrsasign';
2
2
  import { CERTMANAGER, KUBERNETES, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
3
+ import { GITHUB_APP_SECRET_KEYS } from '@shell/config/secret';
3
4
  import { base64Decode, base64Encode } from '@shell/utils/crypto';
4
5
  import { removeObjects } from '@shell/utils/array';
5
6
  import { MANAGEMENT, SERVICE_ACCOUNT, VIRTUAL_TYPES } from '@shell/config/types';
@@ -57,6 +58,14 @@ export default class Secret extends SteveModel {
57
58
  return this._type === TYPES.SSH && !!this.data && 'known_hosts' in this.data;
58
59
  }
59
60
 
61
+ // A GitHub App auth secret is an Opaque secret holding the GitHub App data keys
62
+ get isGithubApp() {
63
+ return this._type === TYPES.OPAQUE && !!this.data &&
64
+ GITHUB_APP_SECRET_KEYS.APP_ID in this.data &&
65
+ GITHUB_APP_SECRET_KEYS.INSTALLATION_ID in this.data &&
66
+ GITHUB_APP_SECRET_KEYS.PRIVATE_KEY in this.data;
67
+ }
68
+
60
69
  get issuer() {
61
70
  const { metadata:{ annotations = {} } } = this;
62
71
 
@@ -237,6 +246,11 @@ export default class Secret extends SteveModel {
237
246
  return this.sshUser;
238
247
  } else if ( this._type === TYPES.SERVICE_ACCT ) {
239
248
  return this.metadata?.annotations?.['kubernetes.io/service-account.name'];
249
+ } else if ( this.isGithubApp ) {
250
+ const appId = base64Decode(this.data[GITHUB_APP_SECRET_KEYS.APP_ID]);
251
+ const installationId = base64Decode(this.data[GITHUB_APP_SECRET_KEYS.INSTALLATION_ID]);
252
+
253
+ return `${ appId } / ${ installationId }`;
240
254
  }
241
255
 
242
256
  return this.keysDisplay;
@@ -274,6 +288,11 @@ export default class Secret extends SteveModel {
274
288
 
275
289
  get subTypeDisplay() {
276
290
  const type = this._type || '';
291
+
292
+ if ( this.isGithubApp ) {
293
+ return this.$rootGetters['i18n/withFallback'](`secret.githubApp.label`, null, 'GitHub App');
294
+ }
295
+
277
296
  const fallback = type.replace(/^kubernetes.io\//, '');
278
297
 
279
298
  return this.$rootGetters['i18n/withFallback'](`secret.types."${ type }"`, null, fallback);