@rancher/shell 3.0.5-rc.6 → 3.0.5-rc.8

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 (243) hide show
  1. package/assets/brand/classic/metadata.json +3 -0
  2. package/assets/styles/app.scss +1 -0
  3. package/assets/styles/base/_color.scss +16 -0
  4. package/assets/styles/base/_helpers.scss +10 -0
  5. package/assets/styles/base/_variables.scss +18 -12
  6. package/assets/styles/fonts/_icons.scss +1 -32
  7. package/assets/styles/global/_layout.scss +1 -1
  8. package/assets/styles/themes/_dark.scss +262 -258
  9. package/assets/styles/themes/_light.scss +538 -509
  10. package/assets/styles/themes/_modern.scss +914 -0
  11. package/assets/translations/en-us.yaml +110 -29
  12. package/chart/__tests__/S3.test.ts +2 -1
  13. package/cloud-credential/generic.vue +18 -10
  14. package/cloud-credential/harvester.vue +1 -9
  15. package/components/AdvancedSection.vue +8 -0
  16. package/components/ChartReadme.vue +17 -7
  17. package/components/CodeMirror.vue +1 -1
  18. package/components/Drawer/Chrome.vue +0 -1
  19. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +27 -28
  20. package/components/Drawer/ResourceDetailDrawer/composables.ts +4 -24
  21. package/components/Drawer/ResourceDetailDrawer/index.vue +18 -4
  22. package/components/InstallHelmCharts.vue +656 -0
  23. package/components/LazyImage.vue +60 -4
  24. package/components/Loading.vue +1 -1
  25. package/components/LocaleSelector.vue +7 -2
  26. package/components/Markdown.vue +4 -0
  27. package/components/PaginatedResourceTable.vue +46 -1
  28. package/components/PromptRestore.vue +22 -44
  29. package/components/Resource/Detail/Masthead/composable.ts +16 -0
  30. package/components/Resource/Detail/Masthead/index.vue +37 -0
  31. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +10 -2
  32. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +26 -7
  33. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +8 -1
  34. package/components/Resource/Detail/Metadata/KeyValue.vue +12 -10
  35. package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
  36. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -17
  37. package/components/Resource/Detail/Metadata/composables.ts +9 -7
  38. package/components/Resource/Detail/Metadata/index.vue +17 -2
  39. package/components/Resource/Detail/Page.vue +35 -21
  40. package/components/Resource/Detail/SpacedRow.vue +1 -1
  41. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -9
  42. package/components/Resource/Detail/TitleBar/composables.ts +5 -5
  43. package/components/Resource/Detail/TitleBar/index.vue +12 -3
  44. package/components/ResourceDetail/Masthead/legacy.vue +1 -1
  45. package/components/ResourceDetail/index.vue +569 -72
  46. package/components/ResourceList/index.vue +1 -0
  47. package/components/ResourceTable.vue +6 -1
  48. package/components/ResourceYaml.vue +1 -1
  49. package/components/RichTranslation.vue +106 -0
  50. package/components/SlideInPanelManager.vue +13 -10
  51. package/components/SortableTable/index.vue +5 -5
  52. package/components/SortableTable/selection.js +0 -1
  53. package/components/Tabbed/index.vue +35 -4
  54. package/components/__tests__/LazyImage.spec.ts +121 -0
  55. package/components/__tests__/PromptRestore.test.ts +1 -65
  56. package/components/__tests__/RichTranslation.test.ts +115 -0
  57. package/components/fleet/FleetStatus.vue +4 -0
  58. package/components/fleet/dashboard/ResourcePanel.vue +2 -1
  59. package/components/form/ClusterAppearance.vue +5 -0
  60. package/components/form/FileImageSelector.vue +1 -1
  61. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  62. package/components/form/NameNsDescription.vue +1 -0
  63. package/components/form/Networking.vue +24 -19
  64. package/components/form/ProjectMemberEditor.vue +1 -1
  65. package/components/form/ResourceLabeledSelect.vue +22 -8
  66. package/components/form/ResourceTabs/index.vue +20 -0
  67. package/components/form/SecretSelector.vue +9 -0
  68. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  69. package/components/form/__tests__/Networking.test.ts +116 -0
  70. package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
  71. package/components/formatter/FleetApplicationSource.vue +25 -17
  72. package/components/formatter/PodImages.vue +1 -1
  73. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  74. package/components/google/AccountAccess.vue +44 -46
  75. package/components/nav/Favorite.vue +4 -0
  76. package/components/nav/Group.vue +4 -1
  77. package/components/nav/NotificationCenter/Notification.vue +1 -27
  78. package/components/nav/WindowManager/index.vue +3 -3
  79. package/composables/resources.ts +2 -2
  80. package/config/labels-annotations.js +3 -2
  81. package/config/pagination-table-headers.js +8 -1
  82. package/config/product/explorer.js +27 -2
  83. package/config/product/manager.js +0 -1
  84. package/config/query-params.js +10 -0
  85. package/config/router/routes.js +21 -1
  86. package/config/system-namespaces.js +1 -1
  87. package/config/table-headers.js +30 -1
  88. package/config/types.js +1 -1
  89. package/config/version.js +1 -1
  90. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
  91. package/detail/__tests__/workload.test.ts +164 -0
  92. package/detail/configmap.vue +33 -75
  93. package/detail/projectsecret.vue +11 -0
  94. package/detail/provisioning.cattle.io.cluster.vue +351 -369
  95. package/detail/secret.vue +49 -308
  96. package/detail/workload/index.vue +38 -21
  97. package/dialog/InstallExtensionDialog.vue +8 -5
  98. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  99. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  100. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  101. package/edit/auth/ldap/config.vue +24 -0
  102. package/edit/compliance.cattle.io.clusterscan.vue +1 -1
  103. package/edit/configmap.vue +4 -1
  104. package/edit/fleet.cattle.io.gitrepo.vue +5 -6
  105. package/edit/fleet.cattle.io.helmop.vue +78 -56
  106. package/edit/logging.banzaicloud.io.output/index.vue +1 -1
  107. package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
  108. package/edit/networking.k8s.io.ingress/Certificate.vue +20 -22
  109. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
  110. package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
  111. package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
  112. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
  113. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
  114. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
  115. package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
  116. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
  117. package/edit/provisioning.cattle.io.cluster/rke2.vue +123 -61
  118. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
  119. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +22 -13
  120. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
  121. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
  122. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
  123. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
  124. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +32 -33
  125. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
  126. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
  127. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
  128. package/edit/secret/basic.vue +1 -0
  129. package/edit/secret/index.vue +126 -15
  130. package/edit/workload/index.vue +5 -14
  131. package/list/projectsecret.vue +345 -0
  132. package/list/provisioning.cattle.io.cluster.vue +1 -69
  133. package/list/secret.vue +109 -0
  134. package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
  135. package/machine-config/google.vue +9 -1
  136. package/machine-config/vmwarevsphere.vue +7 -17
  137. package/mixins/__tests__/brand.spec.ts +2 -2
  138. package/mixins/chart.js +0 -2
  139. package/mixins/create-edit-view/impl.js +10 -1
  140. package/mixins/resource-fetch-api-pagination.js +11 -12
  141. package/mixins/resource-fetch.js +3 -1
  142. package/models/__tests__/chart.test.ts +111 -80
  143. package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
  144. package/models/__tests__/node.test.ts +7 -63
  145. package/models/catalog.cattle.io.app.js +1 -1
  146. package/models/catalog.cattle.io.operation.js +1 -1
  147. package/models/chart.js +36 -20
  148. package/models/cloudcredential.js +2 -163
  149. package/models/cluster/node.js +7 -7
  150. package/models/cluster.x-k8s.io.machine.js +3 -3
  151. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  152. package/models/compliance.cattle.io.clusterscan.js +2 -2
  153. package/models/configmap.js +4 -0
  154. package/models/constraints.gatekeeper.sh.constraint.js +1 -1
  155. package/models/fleet-application.js +0 -17
  156. package/models/fleet.cattle.io.cluster.js +2 -2
  157. package/models/fleet.cattle.io.gitrepo.js +15 -1
  158. package/models/fleet.cattle.io.helmop.js +26 -22
  159. package/models/management.cattle.io.setting.js +4 -0
  160. package/models/persistentvolumeclaim.js +1 -1
  161. package/models/pod.js +2 -2
  162. package/models/provisioning.cattle.io.cluster.js +39 -67
  163. package/models/rke.cattle.io.etcdsnapshot.js +1 -1
  164. package/models/secret.js +161 -2
  165. package/models/storage.k8s.io.storageclass.js +2 -2
  166. package/models/workload.js +3 -3
  167. package/package.json +11 -10
  168. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +1 -0
  169. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
  170. package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
  171. package/pages/c/_cluster/apps/charts/chart.vue +422 -174
  172. package/pages/c/_cluster/apps/charts/index.vue +46 -35
  173. package/pages/c/_cluster/apps/charts/install.vue +1 -1
  174. package/pages/c/_cluster/explorer/projectsecret.vue +24 -0
  175. package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
  176. package/pages/c/_cluster/fleet/index.vue +103 -45
  177. package/pages/c/_cluster/manager/cloudCredential/index.vue +2 -59
  178. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +10 -3
  179. package/pages/c/_cluster/uiplugins/index.vue +36 -25
  180. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  181. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  182. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  183. package/plugins/dashboard-store/actions.js +42 -22
  184. package/plugins/dashboard-store/normalize.js +29 -17
  185. package/plugins/dashboard-store/resource-class.js +83 -17
  186. package/plugins/steve/__tests__/getters.test.ts +1 -1
  187. package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
  188. package/plugins/steve/getters.js +8 -2
  189. package/plugins/steve/resourceWatcher.js +10 -3
  190. package/plugins/steve/steve-pagination-utils.ts +14 -3
  191. package/plugins/steve/subscribe.js +192 -19
  192. package/plugins/steve/worker/web-worker.advanced.js +2 -0
  193. package/rancher-components/Card/Card.vue +0 -18
  194. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
  195. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
  196. package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
  197. package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
  198. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
  199. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
  200. package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
  201. package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
  202. package/rancher-components/Pill/types.ts +2 -0
  203. package/rancher-components/RcButton/RcButton.vue +1 -1
  204. package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
  205. package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
  206. package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
  207. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
  208. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
  209. package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
  210. package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
  211. package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
  212. package/rancher-components/RcItemCard/RcItemCard.vue +40 -6
  213. package/store/__tests__/catalog.test.ts +93 -1
  214. package/store/aws.js +19 -8
  215. package/store/catalog.js +8 -3
  216. package/types/kube/kube-api.ts +12 -0
  217. package/types/resources/settings.d.ts +1 -1
  218. package/types/shell/index.d.ts +643 -585
  219. package/types/store/pagination.types.ts +16 -6
  220. package/types/uiplugins.ts +73 -0
  221. package/utils/__tests__/back-off.test.ts +354 -0
  222. package/utils/__tests__/create-yaml.test.ts +235 -0
  223. package/utils/__tests__/kontainer.test.ts +19 -0
  224. package/utils/__tests__/uiplugins.test.ts +84 -0
  225. package/utils/back-off.ts +176 -0
  226. package/utils/create-yaml.js +103 -9
  227. package/utils/dynamic-importer.js +8 -0
  228. package/utils/kontainer.ts +3 -5
  229. package/utils/pagination-utils.ts +18 -0
  230. package/utils/style.ts +3 -0
  231. package/utils/uiplugins.ts +29 -2
  232. package/utils/validators/__tests__/setting.test.js +92 -0
  233. package/utils/validators/formRules/__tests__/index.test.ts +88 -7
  234. package/utils/validators/formRules/index.ts +83 -8
  235. package/utils/validators/setting.js +17 -0
  236. package/cloud-credential/__tests__/harvester.test.ts +0 -18
  237. package/components/ResourceDetail/__tests__/index.test.ts +0 -135
  238. package/components/ResourceDetail/legacy.vue +0 -562
  239. package/components/formatter/CloudCredExpired.vue +0 -69
  240. package/models/etcdbackup.js +0 -45
  241. package/pages/explorer/resource/detail/configmap.vue +0 -42
  242. package/pages/explorer/resource/detail/secret.vue +0 -50
  243. package/utils/aws.js +0 -0
@@ -41,22 +41,6 @@ export default class HelmOp extends FleetApplication {
41
41
  enabled: !!this.links.update && this.spec?.paused === true
42
42
  });
43
43
 
44
- insertAt(out, 2, {
45
- action: 'enablePollingAction',
46
- label: this.t('fleet.helmOp.actions.enablePolling.label'),
47
- icon: 'icon icon-endpoints_connected',
48
- bulkable: true,
49
- enabled: !!this.links.update && !!this.spec?.disablePolling
50
- });
51
-
52
- insertAt(out, 3, {
53
- action: 'disablePollingAction',
54
- label: this.t('fleet.helmOp.actions.disablePolling.label'),
55
- icon: 'icon icon-endpoints_disconnected',
56
- bulkable: true,
57
- enabled: !!this.links.update && !this.spec?.disablePolling
58
- });
59
-
60
44
  insertAt(out, 5, { divider: true });
61
45
 
62
46
  return out;
@@ -88,7 +72,7 @@ export default class HelmOp extends FleetApplication {
88
72
  return false;
89
73
  }
90
74
 
91
- repoDisplay(repo) {
75
+ sourceDisplay(repo) {
92
76
  if (!repo) {
93
77
  return null;
94
78
  }
@@ -140,9 +124,14 @@ export default class HelmOp extends FleetApplication {
140
124
 
141
125
  switch (this.sourceType) {
142
126
  case SOURCE_TYPE.REPO:
143
- case SOURCE_TYPE.OCI:
144
127
  value = this.spec.helm?.repo || '';
145
128
  break;
129
+ case SOURCE_TYPE.OCI: {
130
+ const parsed = parse(this.spec.helm?.repo || '');
131
+
132
+ value = parsed?.host ? `oci://${ parsed.host }` : '';
133
+ break;
134
+ }
146
135
  case SOURCE_TYPE.TARBALL:
147
136
  value = this.spec.helm?.chart || '';
148
137
  }
@@ -158,15 +147,25 @@ export default class HelmOp extends FleetApplication {
158
147
 
159
148
  return {
160
149
  value,
161
- display: this.repoDisplay(value),
150
+ display: this.sourceDisplay(value),
162
151
  icon: 'icon icon-application',
163
- showLink: matchHttps || matchSSH
152
+ showLink: !!(matchHttps || matchSSH)
164
153
  };
165
154
  }
166
155
 
167
156
  get sourceSub() {
157
+ // Version label
158
+ const semanticVersion = this.spec.helm?.version || '';
159
+ const installedVersion = this.status?.version || '';
160
+
161
+ let labelVersion = semanticVersion || installedVersion || '';
162
+
163
+ if (semanticVersion && installedVersion && semanticVersion !== installedVersion) {
164
+ labelVersion = `${ semanticVersion } -> ${ installedVersion }`;
165
+ }
166
+
167
+ // Chart label
168
168
  let chart = '';
169
- const version = this.spec.helm.version || '';
170
169
 
171
170
  switch (this.sourceType) {
172
171
  case SOURCE_TYPE.REPO:
@@ -180,7 +179,12 @@ export default class HelmOp extends FleetApplication {
180
179
  }
181
180
  }
182
181
 
183
- const value = chart && version ? chart.concat(':', version) : chart;
182
+ // Concat chart label and version label
183
+ let value = chart || labelVersion || '';
184
+
185
+ if (chart && labelVersion) {
186
+ value = `${ chart } : ${ labelVersion }`;
187
+ }
184
188
 
185
189
  return {
186
190
  value,
@@ -68,4 +68,8 @@ export default class Setting extends HybridModel {
68
68
  super.goToEdit();
69
69
  }
70
70
  }
71
+
72
+ get disableResourceDetailDrawer() {
73
+ return true;
74
+ }
71
75
  }
@@ -41,7 +41,7 @@ export default class PVC extends SteveModel {
41
41
  insertAt(out, 0, {
42
42
  action: 'goToEditVolumeSize',
43
43
  enabled: this.expandable && this.bound,
44
- icon: 'icon icon-fw icon-plus',
44
+ icon: 'icon icon-plus',
45
45
  label: this.t('persistentVolumeClaim.expand.label'),
46
46
  });
47
47
 
package/models/pod.js CHANGED
@@ -61,7 +61,7 @@ export default class Pod extends WorkloadService {
61
61
  return {
62
62
  action: 'openShell',
63
63
  enabled: !!this.links.view && this.isRunning,
64
- icon: 'icon icon-fw icon-chevron-right',
64
+ icon: 'icon-chevron-right',
65
65
  label: 'Execute Shell',
66
66
  total: 1,
67
67
  };
@@ -71,7 +71,7 @@ export default class Pod extends WorkloadService {
71
71
  return {
72
72
  action: 'openLogs',
73
73
  enabled: !!this.links.view,
74
- icon: 'icon icon-fw icon-chevron-right',
74
+ icon: 'icon icon-chevron-right',
75
75
  label: 'View Logs',
76
76
  total: 1,
77
77
  };
@@ -13,6 +13,7 @@ import { CAPI as CAPI_ANNOTATIONS, NODE_ARCHITECTURE } from '@shell/config/label
13
13
  import { KEV1 } from '@shell/models/management.cattle.io.kontainerdriver';
14
14
 
15
15
  const RKE1_ALLOWED_ACTIONS = [
16
+ 'promptRemove',
16
17
  'openShell',
17
18
  'downloadKubeConfig',
18
19
  'copyKubeConfig',
@@ -73,15 +74,17 @@ export default class ProvCluster extends SteveModel {
73
74
  return super.creationTimestamp;
74
75
  }
75
76
 
76
- // Models can specify a single action that will be shown as a button in the details masthead
77
- get detailsAction() {
78
- const canExplore = this.mgmt?.isReady && !this.hasError;
77
+ get canExplore() {
78
+ return this.mgmt?.isReady && !this.hasError;
79
+ }
79
80
 
80
- return {
81
- action: 'explore',
82
- label: this.$rootGetters['i18n/t']('cluster.explore'),
83
- enabled: canExplore,
84
- };
81
+ get canEdit() {
82
+ // If the cluster is a KEV1 cluster or Harvester cluster then prevent edit
83
+ if (this.isKev1 || this.isHarvester) {
84
+ return false;
85
+ }
86
+
87
+ return super.canEdit;
85
88
  }
86
89
 
87
90
  get _availableActions() {
@@ -100,7 +103,7 @@ export default class ProvCluster extends SteveModel {
100
103
 
101
104
  const canEditRKE2cluster = this.isRke2 && ready && this.canUpdate;
102
105
 
103
- const canSnapshot = ready && ((this.isRke2 && this.canUpdate) || (this.isRke1 && this.mgmt?.hasAction('backupEtcd')));
106
+ const canSnapshot = ready && this.isRke2 && this.canUpdate;
104
107
 
105
108
  const actions = [
106
109
  // Note: Actions are not supported in the Steve API, so we check
@@ -133,7 +136,7 @@ export default class ProvCluster extends SteveModel {
133
136
  }, {
134
137
  action: 'restoreSnapshotAction',
135
138
  label: this.$rootGetters['i18n/t']('nav.restoreSnapshot'),
136
- icon: 'icon icon-fw icon-backup-restore',
139
+ icon: 'icon icon-backup-restore',
137
140
  enabled: canSnapshot,
138
141
  }, {
139
142
  action: 'rotateCertificates',
@@ -147,19 +150,6 @@ export default class ProvCluster extends SteveModel {
147
150
  enabled: canEditRKE2cluster
148
151
  }, { divider: true }];
149
152
 
150
- // Harvester Cluster 1:1 Harvester Cloud Cred
151
- if (this.cloudCredential?.canRenew || this.cloudCredential?.canBulkRenew) {
152
- out.splice(0, 0, { divider: true });
153
- out.splice(0, 0, {
154
- action: 'renew',
155
- enabled: this.cloudCredential?.canRenew,
156
- bulkable: this.cloudCredential?.canBulkRenew,
157
- bulkAction: 'renewBulk',
158
- icon: 'icon icon-fw icon-refresh',
159
- label: this.$rootGetters['i18n/t']('cluster.cloudCredentials.renew'),
160
- });
161
- }
162
-
163
153
  const all = actions.concat(out);
164
154
 
165
155
  // If the cluster is a KEV1 cluster or Harvester cluster then prevent edit
@@ -822,33 +812,6 @@ export default class ProvCluster extends SteveModel {
822
812
  return this._stateObj;
823
813
  }
824
814
 
825
- get rkeTemplate() {
826
- if (!this.isRke1 || !this.mgmt) {
827
- // Not an RKE! cluster or no management cluster available
828
- return false;
829
- }
830
-
831
- if (!this.mgmt.spec?.clusterTemplateRevisionName) {
832
- // Cluster does not use an RKE template
833
- return false;
834
- }
835
-
836
- const clusterTemplateName = this.mgmt.spec.clusterTemplateName.replace(':', '/');
837
- const clusterTemplateRevisionName = this.mgmt.spec.clusterTemplateRevisionName.replace(':', '/');
838
- const template = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE).find((t) => t.id === clusterTemplateName);
839
- const revision = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE_REVISION).find((t) => t.spec.enabled && t.id === clusterTemplateRevisionName);
840
-
841
- if (!template || !revision) {
842
- return false;
843
- }
844
-
845
- return {
846
- displayName: `${ template.spec?.displayName }/${ revision.spec?.displayName }`,
847
- template,
848
- revision,
849
- };
850
- }
851
-
852
815
  get _stateObj() {
853
816
  if (!this.isRke2) {
854
817
  return this.mgmt?.stateObj || this.metadata?.state;
@@ -1011,6 +974,28 @@ export default class ProvCluster extends SteveModel {
1011
974
  return null;
1012
975
  }
1013
976
 
977
+ /**
978
+ * Gets the options for fields that should be commented out in the YAML representation
979
+ * of the model. This is particularly useful for conditionally commenting out certain
980
+ * fields based on the model's configuration.
981
+ *
982
+ * @returns {null | Array.<{path: string, key: string}>}
983
+ * - `path`: A dot-separated string indicating the path to the object containing the key.
984
+ * - `key`: The specific key within the object at the given path that should be commented out.
985
+ */
986
+ get commentFieldsOptions() {
987
+ if ( this.isRke2 ) {
988
+ return [
989
+ {
990
+ path: 'spec.rkeConfig.machineGlobalConfig',
991
+ key: 'profile'
992
+ }
993
+ ];
994
+ }
995
+
996
+ return null;
997
+ }
998
+
1014
999
  // JSON Paths that should be folded in the YAML editor by default
1015
1000
  get yamlFolding() {
1016
1001
  return [
@@ -1022,24 +1007,11 @@ export default class ProvCluster extends SteveModel {
1022
1007
  return super.description || this.mgmt?.description;
1023
1008
  }
1024
1009
 
1025
- renew() {
1026
- return this.cloudCredential?.renew();
1027
- }
1028
-
1029
- renewBulk(clusters = []) {
1030
- // In theory we don't need to filter by cloudCred, but do so for safety
1031
- const cloudCredentials = clusters.filter((c) => c.cloudCredential).map((c) => c.cloudCredential);
1032
-
1033
- return this.cloudCredential?.renewBulk(cloudCredentials);
1010
+ get disableResourceDetailDrawerConfigTab() {
1011
+ return !!this.isHarvester;
1034
1012
  }
1035
1013
 
1036
- get cloudCredential() {
1037
- return this.$rootGetters['rancher/all'](NORMAN.CLOUD_CREDENTIAL).find((cc) => cc.id === this.spec.cloudCredentialSecretName);
1038
- }
1039
-
1040
- get cloudCredentialWarning() {
1041
- const expireData = this.cloudCredential?.expireData;
1042
-
1043
- return expireData?.expired || expireData?.expiring;
1014
+ get fullDetailPageOverride() {
1015
+ return true;
1044
1016
  }
1045
1017
  }
@@ -17,7 +17,7 @@ export default class EtcdBackup extends NormanModel {
17
17
  return [{
18
18
  action: 'promptRestore',
19
19
  enabled,
20
- icon: 'icon icon-fw icon-backup-restore',
20
+ icon: 'icon icon-backup-restore',
21
21
  label: 'Restore'
22
22
  }];
23
23
  }
package/models/secret.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import r from 'jsrsasign';
2
- import { CERTMANAGER, KUBERNETES } from '@shell/config/labels-annotations';
2
+ import { CERTMANAGER, KUBERNETES, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
3
3
  import { base64Decode, base64Encode } from '@shell/utils/crypto';
4
4
  import { removeObjects } from '@shell/utils/array';
5
- import { SERVICE_ACCOUNT } from '@shell/config/types';
5
+ import { MANAGEMENT, SERVICE_ACCOUNT, VIRTUAL_TYPES } from '@shell/config/types';
6
6
  import { set } from '@shell/utils/object';
7
7
  import { NAME as MANAGER } from '@shell/config/product/manager';
8
8
  import SteveModel from '@shell/plugins/steve/steve-class';
@@ -10,6 +10,8 @@ import { colorForState, stateDisplay, STATES_ENUM } from '@shell/plugins/dashboa
10
10
  import { diffFrom } from '@shell/utils/time';
11
11
  import day from 'dayjs';
12
12
  import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
13
+ import { STORE } from '@shell/store/store-types';
14
+ import { escapeHtml } from '@shell/utils/string';
13
15
 
14
16
  export const TYPES = {
15
17
  OPAQUE: 'Opaque',
@@ -159,6 +161,10 @@ export default class Secret extends SteveModel {
159
161
  }
160
162
 
161
163
  get canUpdate() {
164
+ if (this.isProjectSecretCopy) {
165
+ return false;
166
+ }
167
+
162
168
  if ( !this.hasLink('update') ) {
163
169
  return false;
164
170
  }
@@ -170,6 +176,20 @@ export default class Secret extends SteveModel {
170
176
  return this.$rootGetters['type-map/optionsFor'](this.type).isEditable;
171
177
  }
172
178
 
179
+ get canDelete() {
180
+ // Deleting a copy / synced secret that was created in a namespace in a project that has a project scoped secret
181
+ // will only be temporary (the parent project scoped secret will recreate it)
182
+ return this.isProjectSecretCopy ? false : super.canDelete;
183
+ }
184
+
185
+ get canCreate() {
186
+ return this.isProjectSecretCopy ? false : super.canCreate;
187
+ }
188
+
189
+ get canEditYaml() {
190
+ return this.isProjectSecretCopy ? false : super.canEditYaml;
191
+ }
192
+
173
193
  get keysDisplay() {
174
194
  const keys = [
175
195
  ...Object.keys(this.data || []),
@@ -470,4 +490,143 @@ export default class Secret extends SteveModel {
470
490
 
471
491
  return steveCleanForDownload(yaml, { rootKeys: ['id', 'links', 'actions'] });
472
492
  }
493
+
494
+ /**
495
+ * is this a project scoped secret .... or also a cloned project scoped secret
496
+ */
497
+ get isProjectScopedRelated() {
498
+ return !!this.metadata.labels?.[UI_PROJECT_SECRET];
499
+ }
500
+
501
+ /**
502
+ * is this a project scoped secret
503
+ */
504
+ get isProjectScoped() {
505
+ return this.isProjectScopedRelated && !this.isProjectSecretCopy && this.$rootGetters['isRancher'];
506
+ }
507
+
508
+ get projectScopedClusterId() {
509
+ if (!this.projectScopedProjectId) {
510
+ return undefined;
511
+ }
512
+
513
+ const clusterId = this.metadata.namespace.replace(`-${ this.projectScopedProjectId }`, '');
514
+
515
+ // default and system pss don't follow the patter of <cluster>-<project>, so if they match assume its one of them
516
+ return clusterId === this.metadata.namespace ? 'local' : clusterId;
517
+ }
518
+
519
+ get projectScopedProjectId() {
520
+ return this.metadata.labels?.[UI_PROJECT_SECRET];
521
+ }
522
+
523
+ get isProjectSecretCopy() {
524
+ return this.metadata?.annotations?.[UI_PROJECT_SECRET_COPY] === 'true';
525
+ }
526
+
527
+ get projectCluster() {
528
+ if (!this.isProjectScoped) {
529
+ return undefined;
530
+ }
531
+
532
+ return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.CLUSTER, this.projectScopedClusterId);
533
+ }
534
+
535
+ /**
536
+ * If this is a project scoped secret, return it
537
+ */
538
+ get project() {
539
+ if (!this.isProjectScoped ) {
540
+ return undefined;
541
+ }
542
+
543
+ return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.PROJECT, `${ this.projectScopedClusterId }/${ this.projectScopedProjectId }`);
544
+ }
545
+
546
+ get projectScopedSecretCluster() {
547
+ if (!this.isProjectScoped ) {
548
+ return undefined;
549
+ }
550
+
551
+ return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.PROJECT, `${ this.projectScopedClusterId }/${ this.projectScopedProjectId }`);
552
+ }
553
+
554
+ get clusterAndProjectLabel() {
555
+ if (!this.isProjectScoped) {
556
+ return '';
557
+ }
558
+ const clusterName = this.projectCluster?.nameDisplay;
559
+ // project is going to be empty if upstream and trying to show pss from downstream clusters
560
+ // we only ever have the current clusters projects. if we change this (fetch them in the list)
561
+ // we wipe out the header ns filter projects
562
+ const projectName = this.project?.nameDisplay || this.projectScopedProjectId;
563
+
564
+ if (clusterName && projectName) {
565
+ return `${ projectName } (${ clusterName })`;
566
+ }
567
+
568
+ return '';
569
+ }
570
+
571
+ get detailLocation() {
572
+ if (this.isProjectScoped) {
573
+ const id = this.id?.replace(/.*\//, '');
574
+
575
+ return {
576
+ name: `c-cluster-product-${ VIRTUAL_TYPES.PROJECT_SECRETS }-namespace-id`,
577
+ params: {
578
+ product: this.$rootGetters['productId'],
579
+ cluster: this.$rootGetters['clusterId'],
580
+ namespace: this.metadata?.namespace,
581
+ resource: VIRTUAL_TYPES.PROJECT_SECRETS,
582
+ id,
583
+ }
584
+ };
585
+ }
586
+
587
+ return this._detailLocation;
588
+ }
589
+
590
+ get listLocation() {
591
+ if (!this.isProjectScoped) {
592
+ return super.listLocation;
593
+ }
594
+
595
+ return {
596
+ name: 'c-cluster-product-resource',
597
+ params: {
598
+ product: this.$rootGetters['productId'],
599
+ cluster: this.$rootGetters['clusterId'],
600
+ resource: VIRTUAL_TYPES.PROJECT_SECRETS,
601
+ }
602
+ };
603
+ }
604
+
605
+ get parentNameOverride() {
606
+ if (!this.isProjectScoped) {
607
+ return super.parentNameOverride;
608
+ }
609
+
610
+ return this.$rootGetters['i18n/t'](`typeLabel."${ VIRTUAL_TYPES.PROJECT_SECRETS }"`, { count: 1 })?.trim();
611
+ }
612
+
613
+ get parentLocationOverride() {
614
+ if (!this.isProjectScoped) {
615
+ return super.parentNameOverride;
616
+ }
617
+
618
+ return this.listLocation;
619
+ }
620
+
621
+ get groupByProject() {
622
+ if (!this.isProjectScoped) {
623
+ return undefined;
624
+ }
625
+
626
+ return this.t('resourceTable.groupLabel.project', { name: escapeHtml(this?.project?.nameDisplay || '') }, true);
627
+ }
628
+
629
+ get fullDetailPageOverride() {
630
+ return true;
631
+ }
473
632
  }
@@ -141,14 +141,14 @@ export default class extends SteveModel {
141
141
  out.unshift({
142
142
  action: 'resetDefault',
143
143
  enabled: true,
144
- icon: 'icon icon-fw icon-checkmark',
144
+ icon: 'icon icon-checkmark',
145
145
  label: this.t('storageClass.actions.resetDefault'),
146
146
  });
147
147
  } else {
148
148
  out.unshift({
149
149
  action: 'setDefault',
150
150
  enabled: true,
151
- icon: 'icon icon-fw icon-checkmark',
151
+ icon: 'icon icon-checkmark',
152
152
  label: this.t('storageClass.actions.setAsDefault'),
153
153
  });
154
154
  }
@@ -1,7 +1,7 @@
1
1
  import { findBy, insertAt } from '@shell/utils/array';
2
2
  import { CATTLE_PUBLIC_ENDPOINTS } from '@shell/config/labels-annotations';
3
3
  import { WORKLOAD_TYPES, SERVICE, POD } from '@shell/config/types';
4
- import { get, set } from '@shell/utils/object';
4
+ import { set } from '@shell/utils/object';
5
5
  import day from 'dayjs';
6
6
  import { convertSelectorObj, parse } from '@shell/utils/selector';
7
7
  import { SEPARATOR } from '@shell/config/workload';
@@ -76,7 +76,7 @@ export default class Workload extends WorkloadService {
76
76
  insertAt(out, 0, {
77
77
  action: 'openShell',
78
78
  enabled: !!this.links.view,
79
- icon: 'icon icon-fw icon-chevron-right',
79
+ icon: 'icon icon-chevron-right',
80
80
  label: this.t('action.openShell'),
81
81
  total: 1,
82
82
  });
@@ -632,7 +632,7 @@ export default class Workload extends WorkloadService {
632
632
  return undefined;
633
633
  }
634
634
 
635
- return (get(this, 'metadata.relationships') || []).filter((relationship) => relationship.toType === WORKLOAD_TYPES.JOB);
635
+ return this.metadata?.relationships?.filter((relationship) => relationship.toType === WORKLOAD_TYPES.JOB) || [];
636
636
  }
637
637
 
638
638
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.5-rc.6",
3
+ "version": "3.0.5-rc.8",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -27,17 +27,18 @@
27
27
  "e2e:dev": "start-server-and-test dev https://localhost:8005 cy:open"
28
28
  },
29
29
  "dependencies": {
30
- "@aws-sdk/client-ec2": "3.658.1",
31
- "@aws-sdk/client-eks": "3.1.0",
32
- "@aws-sdk/client-iam": "3.658.1",
33
- "@aws-sdk/client-kms": "3.8.1",
30
+ "@aws-sdk/client-ec2": "3.863.0",
31
+ "@aws-sdk/client-eks": "3.863.0",
32
+ "@aws-sdk/client-iam": "3.863.0",
33
+ "@aws-sdk/client-kms": "3.863.0",
34
+ "@smithy/fetch-http-handler": "5.1.1",
34
35
  "@babel/plugin-proposal-optional-chaining": "7.21.0",
35
36
  "@babel/plugin-proposal-private-methods": "7.18.6",
36
37
  "@babel/plugin-proposal-private-property-in-object": "7.14.5",
37
38
  "@babel/preset-typescript": "7.16.7",
38
39
  "@novnc/novnc": "1.2.0",
39
40
  "@popperjs/core": "2.11.8",
40
- "@rancher/icons": "2.0.29",
41
+ "@rancher/icons": "2.0.38",
41
42
  "@types/is-url": "1.2.30",
42
43
  "@types/node": "20.10.8",
43
44
  "@types/semver": "^7.5.8",
@@ -64,14 +65,14 @@
64
65
  "cookie-universal": "2.2.2",
65
66
  "cookie": "0.7.0",
66
67
  "core-js": "3.40.0",
67
- "cron-validator": "1.3.1",
68
+ "cron-validator": "1.4.0",
68
69
  "cronstrue": "2.53.0",
69
70
  "cross-env": "7.0.3",
70
71
  "css-loader": "6.7.3",
71
72
  "csv-loader": "3.0.3",
72
73
  "custom-event-polyfill": "^1.0.7",
73
74
  "cypress": "11.1.0",
74
- "d3-selection": "1.4.1",
75
+ "d3-selection": "3.0.0",
75
76
  "d3": "7.3.0",
76
77
  "dayjs": "1.8.29",
77
78
  "defu": "5.0.1",
@@ -108,7 +109,7 @@
108
109
  "jsdiff": "1.1.1",
109
110
  "jsonpath-plus": "10.3.0",
110
111
  "jsrsasign": "11.0.0",
111
- "jszip": "3.8.0",
112
+ "jszip": "3.10.1",
112
113
  "lodash": "4.17.21",
113
114
  "marked": "4.0.17",
114
115
  "node-polyfill-webpack-plugin": "3.0.0",
@@ -117,7 +118,7 @@
117
118
  "papaparse": "5.3.0",
118
119
  "portal-vue": "~3.0.0",
119
120
  "sass-loader": "12.6.0",
120
- "sass": "1.83.1",
121
+ "sass": "1.89.2",
121
122
  "serve-static": "1.14.1",
122
123
  "set-cookie-parser": "2.4.6",
123
124
  "shell-quote": "1.7.3",
@@ -35,6 +35,7 @@ function onClickItem(type: string, label: string) {
35
35
  <rc-item-card-action
36
36
  v-for="(label, j) in footerItem.labels"
37
37
  :key="j"
38
+ v-clean-tooltip="footerItem.labelTooltip"
38
39
  class="app-chart-card-footer-item-text secondary-text-link"
39
40
  data-testid="app-chart-card-footer-item-text"
40
41
  tabindex="0"
@@ -4,6 +4,7 @@ interface SubHeaderItem {
4
4
  icon: string;
5
5
  iconTooltip?: Record<{key?: string, text?: string}>;
6
6
  label: string;
7
+ labelTooltip?: string;
7
8
  }
8
9
 
9
10
  defineProps<{
@@ -24,7 +25,9 @@ defineProps<{
24
25
  v-clean-tooltip="t(subHeaderItem.iconTooltip.key)"
25
26
  :class="['icon', 'app-chart-card-sub-header-item-icon', subHeaderItem.icon]"
26
27
  />
27
- <p>{{ subHeaderItem.label }}</p>
28
+ <p v-clean-tooltip="subHeaderItem.labelTooltip">
29
+ {{ subHeaderItem.label }}
30
+ </p>
28
31
  </div>
29
32
  </div>
30
33
  </template>
@@ -0,0 +1,41 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import AppChartCardFooter from '../AppChartCardFooter.vue';
3
+ import { REPO } from '@shell/config/query-params';
4
+
5
+ describe('component: AppChartCardFooter', () => {
6
+ it('should render', () => {
7
+ const wrapper = shallowMount(AppChartCardFooter, {
8
+ propsData: { items: [] },
9
+ stubs: { 'rc-item-card-action': true },
10
+ });
11
+
12
+ expect(wrapper.exists()).toBe(true);
13
+ });
14
+
15
+ it('should apply tooltips to labels', () => {
16
+ const tooltipContent = 'my tooltip';
17
+ const items = [
18
+ {
19
+ type: REPO,
20
+ labels: ['label1', 'label2'],
21
+ labelTooltip: tooltipContent,
22
+ },
23
+ ];
24
+
25
+ const wrapper = shallowMount(AppChartCardFooter, {
26
+ propsData: { items },
27
+ stubs: { 'rc-item-card-action': true },
28
+ directives: {
29
+ 'clean-tooltip': (el, binding) => {
30
+ el.setAttribute('data-tooltip-value', binding.value);
31
+ },
32
+ },
33
+ });
34
+
35
+ const actions = wrapper.findAll('[data-tooltip-value]');
36
+
37
+ expect(actions).toHaveLength(2);
38
+ expect(actions.at(0).attributes('data-tooltip-value')).toBe(tooltipContent);
39
+ expect(actions.at(1).attributes('data-tooltip-value')).toBe(tooltipContent);
40
+ });
41
+ });