@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
@@ -1,74 +1,18 @@
1
- import Node from '@shell/models/management.cattle.io.node';
1
+ import Node from '@shell/models/cluster/node';
2
2
 
3
3
  describe('class Node', () => {
4
- const foo = 'foo';
5
- const bar = 'bar';
6
- const t = jest.fn(() => bar);
7
- const ctx = { rootGetters: { 'i18n/t': t } };
8
-
9
4
  const resetMocks = () => {
10
5
  // Clear all mock function calls:
11
6
  jest.clearAllMocks();
12
7
  };
13
8
 
14
- it('should not return addresses if they are not present in the resource status', () => {
15
- const node = new Node({ status: {} });
9
+ it.each([
10
+ ['1200', 1200],
11
+ ['1k', 1000]
12
+ ])('given %p status pod capacity value from the backend, should parse the value correctly as %p', (value, result) => {
13
+ const node = new Node({ status: { capacity: { pods: value } } });
16
14
 
17
- expect(node.addresses).toStrictEqual([]);
15
+ expect(node.podCapacity).toStrictEqual(result);
18
16
  resetMocks();
19
17
  });
20
-
21
- describe('should return addresses', () => {
22
- const addresses = [foo];
23
-
24
- it('if they are present directly on the resource status', () => {
25
- const node = new Node({ status: { addresses } });
26
-
27
- expect(node.addresses).toStrictEqual(addresses);
28
- });
29
- });
30
-
31
- describe('should return an internalIp', () => {
32
- const addresses = [{ type: 'InternalIP', address: foo }];
33
-
34
- it('if addresses includes an object with an appropriate type and address', () => {
35
- const node = new Node({ status: { addresses } });
36
-
37
- expect(node.internalIp).toStrictEqual(foo);
38
- });
39
- });
40
-
41
- describe('should return an externalIp', () => {
42
- const addresses = [{ type: 'ExternalIP', address: foo }];
43
-
44
- it('if addresses includes an object with an appropriate type and address', () => {
45
- const node = new Node({ status: { addresses } });
46
-
47
- expect(node.externalIp).toStrictEqual(foo);
48
- });
49
- it('if internalNodeStatus.addresses includes an object with an appropriate type and address', () => {
50
- const node = new Node({ status: { internalNodeStatus: { addresses } } });
51
-
52
- expect(node.externalIp).toStrictEqual(foo);
53
- });
54
- });
55
-
56
- describe('should return an appropriate message', () => {
57
- it('if there is no internalIp to display', () => {
58
- const node = new Node({ status: {} }, ctx);
59
-
60
- expect(node.internalIp).toStrictEqual(bar);
61
- expect(t).toHaveBeenCalledTimes(1);
62
- expect(t).toHaveBeenCalledWith('generic.none');
63
- resetMocks();
64
- });
65
- it('if there is no externalIp to display', () => {
66
- const node = new Node({ status: {} }, ctx);
67
-
68
- expect(node.externalIp).toStrictEqual(bar);
69
- expect(t).toHaveBeenCalledTimes(1);
70
- expect(t).toHaveBeenCalledWith('generic.none');
71
- resetMocks();
72
- });
73
- });
74
18
  });
@@ -31,7 +31,7 @@ export default class CatalogApp extends SteveModel {
31
31
  const upgrade = {
32
32
  action: 'goToUpgrade',
33
33
  enabled: true,
34
- icon: 'icon icon-fw icon-edit',
34
+ icon: 'icon icon-edit',
35
35
  label: this.t('catalog.install.action.goToUpgrade'),
36
36
  };
37
37
 
@@ -17,7 +17,7 @@ export default class CatalogOperation extends SteveModel {
17
17
  const openLogs = {
18
18
  action: 'openLogs',
19
19
  enabled: true,
20
- icon: 'icon icon-fw icon-chevron-right',
20
+ icon: 'icon icon-chevron-right',
21
21
  label: this.t('action.openLogs'),
22
22
  total: 1,
23
23
  };
package/models/chart.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from '@shell/config/query-params';
5
5
  import { BLANK_CLUSTER } from '@shell/store/store-types.js';
6
6
  import SteveModel from '@shell/plugins/steve/steve-class';
7
- import { CATALOG } from '@shell/config/types';
7
+ import { CATALOG, ZERO_TIME } from '@shell/config/types';
8
8
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
9
9
  import day from 'dayjs';
10
10
 
@@ -121,42 +121,58 @@ export default class Chart extends SteveModel {
121
121
  */
122
122
  get cardContent() {
123
123
  if (!this._cardContent) {
124
- const subHeaderItems = [
125
- {
124
+ const latestVersion = this.versions?.[0] || {};
125
+ const subHeaderItems = [];
126
+
127
+ if (latestVersion) {
128
+ const hasZeroTime = latestVersion.created === ZERO_TIME;
129
+
130
+ subHeaderItems.push({
126
131
  icon: 'icon-version-alt',
127
132
  iconTooltip: { key: 'tableHeaders.version' },
128
- label: this.versions[0].version
129
- },
130
- {
133
+ label: latestVersion.version
134
+ });
135
+
136
+ const lastUpdatedItem = {
131
137
  icon: 'icon-refresh-alt',
132
138
  iconTooltip: { key: 'tableHeaders.lastUpdated' },
133
- label: day(this.versions[0].created).format('MMM D, YYYY')
139
+ label: hasZeroTime ? this.t('generic.na') : day(latestVersion.created).format('MMM D, YYYY')
140
+ };
141
+
142
+ if (hasZeroTime) {
143
+ lastUpdatedItem.labelTooltip = this.t('catalog.charts.appChartCard.subHeaderItem.missingVersionDate');
134
144
  }
135
- ];
145
+
146
+ subHeaderItems.push(lastUpdatedItem);
147
+ }
148
+
136
149
  const footerItems = [
137
150
  {
138
- type: REPO,
139
- icon: 'icon-repository-alt',
140
- iconTooltip: { key: 'tableHeaders.repoName' },
141
- labels: [this.repoNameDisplay]
151
+ type: REPO,
152
+ icon: 'icon-repository-alt',
153
+ iconTooltip: { key: 'tableHeaders.repoName' },
154
+ labels: [this.repoNameDisplay],
155
+ labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.repo') }, true)
142
156
  }
143
157
  ];
144
158
 
145
159
  if (this.categories.length) {
146
160
  footerItems.push( {
147
- type: CATEGORY,
148
- icon: 'icon-category-alt',
149
- iconTooltip: { key: 'generic.category' },
150
- labels: this.categories
161
+ type: CATEGORY,
162
+ icon: 'icon-category-alt',
163
+ iconTooltip: { key: 'generic.category' },
164
+ labels: this.categories,
165
+ labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.category') }, true)
151
166
  });
152
167
  }
153
168
 
154
169
  if (this.tags.length) {
155
170
  footerItems.push({
156
- type: TAG,
157
- icon: 'icon-tag-alt',
158
- iconTooltip: { key: 'generic.tags' },
159
- labels: this.tags
171
+ type: TAG,
172
+ icon: 'icon-tag-alt',
173
+ iconTooltip: { key: 'generic.tags' },
174
+ labels: this.tags,
175
+ labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.tag') }, true)
160
176
  });
161
177
  }
162
178
 
@@ -1,65 +1,11 @@
1
- import { CAPI, CLOUD_CREDENTIALS } from '@shell/config/labels-annotations';
1
+ import { CAPI } from '@shell/config/labels-annotations';
2
2
  import { fullFields, prefixFields, simplify, suffixFields } from '@shell/store/plugins';
3
3
  import { isEmpty, set } from '@shell/utils/object';
4
- import { MANAGEMENT, SECRET } from '@shell/config/types';
4
+ import { SECRET } from '@shell/config/types';
5
5
  import { escapeHtml } from '@shell/utils/string';
6
6
  import NormanModel from '@shell/plugins/steve/norman-class';
7
- import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
8
- import day from 'dayjs';
9
-
10
- const harvesterProvider = 'harvester';
11
-
12
- const renew = {
13
- [harvesterProvider]: {
14
- renew: ({ cloudCredential, $ctx }) => {
15
- return renew[harvesterProvider].renewBulk(
16
- { cloudCredentials: [cloudCredential], $ctx }
17
- );
18
- },
19
- renewBulk: async({ cloudCredentials, $ctx }) => {
20
- // A harvester cloud credential (at the moment) is a kubeconfig complete with expiring token
21
- // So to renew we just need to generate a new kubeconfig and save it to the cc (similar to shell/cloud-credential/harvester.vue)
22
- await Promise.all(cloudCredentials.map(async(cc) => {
23
- try {
24
- if (!cc.harvestercredentialConfig?.clusterId) {
25
- throw new Error(`credential has no matching harvester cluster`);
26
- }
27
- const mgmtCluster = $ctx.rootGetters['management/byId'](MANAGEMENT.CLUSTER, cc.harvestercredentialConfig.clusterId);
28
-
29
- if (!mgmtCluster) {
30
- throw new Error(`cannot find harvester cluster`);
31
- }
32
-
33
- const kubeconfigContent = await mgmtCluster.generateKubeConfig();
34
-
35
- cc.setData('kubeconfigContent', kubeconfigContent);
36
-
37
- await cc.save();
38
- } catch (error) {
39
- console.error(`Unable to refresh harvester cloud credential '${ cc.id }'`, error); // eslint-disable-line no-console
40
- }
41
- }));
42
- }
43
- }
44
- };
45
7
 
46
8
  export default class CloudCredential extends NormanModel {
47
- get _availableActions() {
48
- const out = super._availableActions;
49
-
50
- out.splice(0, 0, { divider: true });
51
- out.splice(0, 0, {
52
- action: 'renew',
53
- enabled: this.canRenew,
54
- bulkable: this.canBulkRenew,
55
- bulkAction: 'renewBulk',
56
- icon: 'icon icon-fw icon-refresh',
57
- label: this.t('manager.cloudCredentials.renew'),
58
- });
59
-
60
- return out;
61
- }
62
-
63
9
  get hasSensitiveData() {
64
10
  return true;
65
11
  }
@@ -231,111 +177,4 @@ export default class CloudCredential extends NormanModel {
231
177
  get doneRoute() {
232
178
  return 'c-cluster-manager-secret';
233
179
  }
234
-
235
- get canRenew() {
236
- return !!renew[this.provider]?.renew && this.expires !== undefined && this.canUpdate;
237
- }
238
-
239
- get canBulkRenew() {
240
- return !!renew[this.provider]?.renewBulk;
241
- }
242
-
243
- get expiresForSort() {
244
- // Why not just `expires`? Ensures the correct sort order of expired --> expiring --> never expires
245
- // (instead of 'never expired' --> 'expired' --> 'expiring')
246
- return this.expires !== undefined ? this.expires : Number.MAX_SAFE_INTEGER;
247
- }
248
-
249
- get expires() {
250
- const expires = this.annotations[CLOUD_CREDENTIALS.EXPIRATION];
251
-
252
- if (typeof expires === 'string') {
253
- return parseInt(expires);
254
- } else if (typeof expires === 'number') {
255
- return expires;
256
- }
257
-
258
- return undefined; // Weird things happen if this isn't a number
259
- }
260
-
261
- get expireData() {
262
- if (typeof this.expiresIn !== 'number') {
263
- return null;
264
- }
265
-
266
- const sevenDays = 1000 * 60 * 60 * 24 * 7;
267
-
268
- if (this.expiresIn === 0) {
269
- return {
270
- expired: true,
271
- expiring: false,
272
- };
273
- } else if (this.expiresIn < sevenDays) {
274
- return {
275
- expired: false,
276
- expiring: true,
277
- };
278
- } else if (this.expiresIn) {
279
- return {
280
- expired: false,
281
- expiring: false,
282
- };
283
- }
284
-
285
- return null;
286
- }
287
-
288
- get expiresString() {
289
- if (this.expires === undefined) {
290
- return '';
291
- }
292
-
293
- if (this.expireData.expired) {
294
- return this.t('manager.cloudCredentials.expired');
295
- }
296
-
297
- const dateFormat = escapeHtml( this.$rootGetters['prefs/get'](DATE_FORMAT));
298
- const timeFormat = escapeHtml( this.$rootGetters['prefs/get'](TIME_FORMAT));
299
-
300
- return day(this.expires).format(`${ dateFormat } ${ timeFormat }`);
301
- }
302
-
303
- get expiresIn() {
304
- if (this.expires === undefined) {
305
- return null;
306
- }
307
-
308
- const timeThen = this.expires;
309
- const timeNow = Date.now();
310
-
311
- const expiresIn = timeThen - timeNow;
312
-
313
- return expiresIn < 0 ? 0 : expiresIn;
314
- }
315
-
316
- renew() {
317
- const renewFn = renew[this.provider]?.renew;
318
-
319
- if (!renewFn) {
320
- console.error('No fn renew function for ', this.provider); // eslint-disable-line no-console
321
- }
322
-
323
- return renewFn({
324
- cloudCredential: this,
325
- $ctx: this.$ctx
326
- });
327
- }
328
-
329
- async renewBulk(cloudCredentials = []) {
330
- const renewBulkFn = renew[this.provider]?.renewBulk;
331
-
332
- if (!renewBulkFn) {
333
- console.error('No fn renew bulk function for ', this.provider); // eslint-disable-line no-console
334
- }
335
-
336
- return renewBulkFn({
337
- cloudCredentials,
338
- $ctx: this.$ctx
339
- });
340
- }
341
180
  }
@@ -16,7 +16,7 @@ export default class ClusterNode extends SteveModel {
16
16
  const cordon = {
17
17
  action: 'cordon',
18
18
  enabled: !!normanAction.cordon,
19
- icon: 'icon icon-fw icon-pause',
19
+ icon: 'icon icon-pause',
20
20
  label: 'Cordon',
21
21
  total: 1,
22
22
  bulkable: true
@@ -25,7 +25,7 @@ export default class ClusterNode extends SteveModel {
25
25
  const uncordon = {
26
26
  action: 'uncordon',
27
27
  enabled: !!normanAction.uncordon,
28
- icon: 'icon icon-fw icon-play',
28
+ icon: 'icon icon-play',
29
29
  label: 'Uncordon',
30
30
  total: 1,
31
31
  bulkable: true
@@ -34,7 +34,7 @@ export default class ClusterNode extends SteveModel {
34
34
  const drain = {
35
35
  action: 'drain',
36
36
  enabled: !!normanAction.drain,
37
- icon: 'icon icon-fw icon-dot-open',
37
+ icon: 'icon icon-dot-open',
38
38
  label: this.t('drainNode.action'),
39
39
  bulkable: true,
40
40
  bulkAction: 'drain'
@@ -43,7 +43,7 @@ export default class ClusterNode extends SteveModel {
43
43
  const stopDrain = {
44
44
  action: 'stopDrain',
45
45
  enabled: !!normanAction.stopDrain,
46
- icon: 'icon icon-fw icon-x',
46
+ icon: 'icon icon-x',
47
47
  label: this.t('drainNode.actionStop'),
48
48
  bulkable: true,
49
49
  };
@@ -51,14 +51,14 @@ export default class ClusterNode extends SteveModel {
51
51
  const openSsh = {
52
52
  action: 'openSsh',
53
53
  enabled: !!this.provisionedMachine?.links?.shell,
54
- icon: 'icon icon-fw icon-chevron-right',
54
+ icon: 'icon icon-chevron-right',
55
55
  label: 'SSH Shell',
56
56
  };
57
57
 
58
58
  const downloadKeys = {
59
59
  action: 'downloadKeys',
60
60
  enabled: !!this.provisionedMachine?.links?.sshkeys,
61
- icon: 'icon icon-fw icon-download',
61
+ icon: 'icon icon-download',
62
62
  label: this.t('node.actions.downloadSSHKey'),
63
63
  };
64
64
 
@@ -227,7 +227,7 @@ export default class ClusterNode extends SteveModel {
227
227
  }
228
228
 
229
229
  get podCapacity() {
230
- return Number.parseInt(this.status.capacity?.pods);
230
+ return parseSi(this.status.capacity?.pods);
231
231
  }
232
232
 
233
233
  get podConsumed() {
@@ -60,13 +60,13 @@ export default class CapiMachine extends SteveModel {
60
60
  const openSsh = {
61
61
  action: 'openSsh',
62
62
  enabled: !!this.links.shell && this.isRunning,
63
- icon: 'icon icon-fw icon-chevron-right',
63
+ icon: 'icon icon-chevron-right',
64
64
  label: 'SSH Shell',
65
65
  };
66
66
  const downloadKeys = {
67
67
  action: 'downloadKeys',
68
68
  enabled: !!this.links.sshkeys,
69
- icon: 'icon icon-fw icon-download',
69
+ icon: 'icon icon-download',
70
70
  label: this.t('node.actions.downloadSSHKey'),
71
71
  };
72
72
  const forceRemove = {
@@ -80,7 +80,7 @@ export default class CapiMachine extends SteveModel {
80
80
  action: 'toggleScaleDownModal',
81
81
  bulkAction: 'toggleScaleDownModal',
82
82
  enabled: !!this.canScaleDown,
83
- icon: 'icon icon-minus icon-fw',
83
+ icon: 'icon icon-minus',
84
84
  label: this.t('node.actions.scaleDown'),
85
85
  bulkable: true
86
86
  };
@@ -125,7 +125,7 @@ export default class CapiMachineDeployment extends SteveModel {
125
125
  return;
126
126
  }
127
127
 
128
- const initialValue = this.cluster.toJSON();
128
+ const initialValue = this.cluster;
129
129
 
130
130
  this.inClusterSpec.quantity += delta;
131
131
 
@@ -145,7 +145,16 @@ export default class CapiMachineDeployment extends SteveModel {
145
145
  let errors = exceptionToErrorsArray(err);
146
146
 
147
147
  if ( err.status === 409 && depth < 2 ) {
148
- const conflicts = await handleConflict(initialValue, value, liveModel, this.$rootGetters, { dispatch: this.$dispatch }, 'management');
148
+ const conflicts = await handleConflict(
149
+ initialValue,
150
+ value,
151
+ liveModel,
152
+ {
153
+ dispatch: this.$dispatch,
154
+ getters: this.$rootGetters
155
+ },
156
+ 'management'
157
+ );
149
158
 
150
159
  if ( conflicts === false ) {
151
160
  // It was automatically figured out, save again
@@ -52,7 +52,7 @@ export default class ClusterScan extends SteveModel {
52
52
  const downloadReport = {
53
53
  action: 'downloadLatestReport',
54
54
  enabled: this.hasReport,
55
- icon: 'icon icon-fw icon-download',
55
+ icon: 'icon icon-download',
56
56
  label: t('compliance.downloadReport'),
57
57
  total: 1,
58
58
  };
@@ -60,7 +60,7 @@ export default class ClusterScan extends SteveModel {
60
60
  const downloadAllReports = {
61
61
  action: 'downloadAllReports',
62
62
  enabled: this.hasReport,
63
- icon: 'icon icon-fw icon-download',
63
+ icon: 'icon icon-download',
64
64
  label: t('compliance.downloadAllReports'),
65
65
  total: 1,
66
66
  };
@@ -17,4 +17,8 @@ export default class ConfigMap extends SteveModel {
17
17
 
18
18
  return keys.join(', ');
19
19
  }
20
+
21
+ get fullDetailPageOverride() {
22
+ return true;
23
+ }
20
24
  }
@@ -15,7 +15,7 @@ export default class GateKeeperConstraint extends SteveModel {
15
15
 
16
16
  const downloadViolations = {
17
17
  action: 'downloadViolations',
18
- icon: 'icon icon-fw icon-download',
18
+ icon: 'icon icon-download',
19
19
  label: t('gatekeeperConstraint.downloadViolations'),
20
20
  total: 1,
21
21
  };
@@ -8,9 +8,6 @@ import SteveModel from '@shell/plugins/steve/steve-class';
8
8
  import { mapStateToEnum, primaryDisplayStatusFromCount, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
9
9
  import FleetUtils from '@shell/utils/fleet';
10
10
 
11
- export const MINIMUM_POLLING_INTERVAL = 15;
12
- export const DEFAULT_POLLING_INTERVAL = 60;
13
-
14
11
  function normalizeStateCounts(data) {
15
12
  if (isEmpty(data)) {
16
13
  return {
@@ -46,16 +43,6 @@ export default class FleetApplication extends SteveModel {
46
43
  this.save();
47
44
  }
48
45
 
49
- enablePollingAction() {
50
- this.spec.disablePolling = false;
51
- this.save();
52
- }
53
-
54
- disablePollingAction() {
55
- this.spec.disablePolling = true;
56
- this.save();
57
- }
58
-
59
46
  goToClone() {
60
47
  if (this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID]) {
61
48
  delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
@@ -68,10 +55,6 @@ export default class FleetApplication extends SteveModel {
68
55
  super.goToClone();
69
56
  }
70
57
 
71
- get isPollingEnabled() {
72
- return !this.spec.disablePolling;
73
- }
74
-
75
58
  get state() {
76
59
  if (this.spec?.paused === true) {
77
60
  return 'paused';
@@ -223,8 +223,8 @@ export default class FleetCluster extends SteveModel {
223
223
  return parsedLabels;
224
224
  }
225
225
 
226
- async saveYaml(yaml) {
227
- await this._saveYaml(yaml);
226
+ async saveYaml(yaml, initialYaml) {
227
+ await this._saveYaml(yaml, initialYaml);
228
228
 
229
229
  const parsed = jsyaml.load(yaml);
230
230
 
@@ -76,6 +76,16 @@ export default class GitRepo extends FleetApplication {
76
76
  return out;
77
77
  }
78
78
 
79
+ enablePollingAction() {
80
+ this.spec.disablePolling = false;
81
+ this.save();
82
+ }
83
+
84
+ disablePollingAction() {
85
+ this.spec.disablePolling = true;
86
+ this.save();
87
+ }
88
+
79
89
  forceUpdate(resources = [this]) {
80
90
  this.$dispatch('promptModal', {
81
91
  componentProps: { repositories: resources },
@@ -90,6 +100,10 @@ export default class GitRepo extends FleetApplication {
90
100
  });
91
101
  }
92
102
 
103
+ get isPollingEnabled() {
104
+ return !this.spec.disablePolling;
105
+ }
106
+
93
107
  get isWebhookConfigured() {
94
108
  return !!this.status?.webhookCommit;
95
109
  }
@@ -185,7 +199,7 @@ export default class GitRepo extends FleetApplication {
185
199
  value,
186
200
  display: this.repoDisplay,
187
201
  icon: this.resourceIcon,
188
- showLink: matchHttps || matchSSH
202
+ showLink: !!(matchHttps || matchSSH)
189
203
  };
190
204
  }
191
205