@rancher/shell 3.0.9-rc.1 → 3.0.9-rc.2

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 (184) hide show
  1. package/assets/styles/base/_color.scss +1 -0
  2. package/assets/styles/base/_typography.scss +14 -5
  3. package/assets/styles/themes/_light.scss +1 -1
  4. package/assets/styles/themes/_modern.scss +1 -1
  5. package/assets/translations/en-us.yaml +94 -33
  6. package/assets/translations/zh-hans.yaml +0 -2
  7. package/components/ActionMenuShell.vue +4 -4
  8. package/components/CodeMirror.vue +4 -3
  9. package/components/DetailText.vue +54 -7
  10. package/components/Drawer/Chrome.vue +11 -4
  11. package/components/Drawer/DrawerCard.vue +19 -0
  12. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +3 -11
  13. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +2 -2
  14. package/components/Drawer/ResourceDetailDrawer/index.vue +3 -20
  15. package/components/Drawer/types.ts +1 -0
  16. package/components/DynamicContent/DynamicContentCloseButton.vue +2 -2
  17. package/components/LocaleSelector.vue +1 -1
  18. package/components/Markdown.vue +1 -1
  19. package/components/PopoverCard.vue +3 -3
  20. package/components/Resource/Detail/Card/ExtrasCard.vue +39 -0
  21. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +142 -0
  22. package/components/Resource/Detail/Card/StateCard/composables.ts +41 -11
  23. package/components/Resource/Detail/Card/StateCard/index.vue +3 -9
  24. package/components/Resource/Detail/Card/StateCard/types.ts +6 -0
  25. package/components/Resource/Detail/Card/{PodsCard → StatusCard}/index.vue +11 -10
  26. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +24 -25
  27. package/components/Resource/Detail/Cards.vue +27 -0
  28. package/components/Resource/Detail/Masthead/__tests__/index.test.ts +70 -0
  29. package/components/Resource/Detail/Masthead/index.vue +5 -0
  30. package/components/Resource/Detail/Metadata/KeyValueRow.vue +4 -2
  31. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -2
  32. package/components/Resource/Detail/ResourceRow.types.ts +14 -0
  33. package/components/Resource/Detail/ResourceRow.vue +23 -35
  34. package/components/Resource/Detail/StatusRow.vue +5 -2
  35. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +38 -7
  36. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +106 -2
  37. package/components/Resource/Detail/TitleBar/composables.ts +2 -1
  38. package/components/Resource/Detail/TitleBar/index.vue +41 -6
  39. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +49 -1
  40. package/components/ResourceDetail/Masthead/__tests__/latest.test.ts +85 -0
  41. package/components/ResourceDetail/Masthead/index.vue +1 -0
  42. package/components/ResourceDetail/Masthead/latest.vue +8 -1
  43. package/components/ResourceDetail/Masthead/legacy.vue +1 -1
  44. package/components/Setting.vue +1 -1
  45. package/components/SortableTable/index.vue +25 -0
  46. package/components/SortableTable/selection.js +25 -12
  47. package/components/SortableTable/sorting.js +1 -1
  48. package/components/Tabbed/Tab.vue +1 -0
  49. package/components/Tabbed/index.vue +29 -6
  50. package/components/Window/ContainerShell.vue +10 -13
  51. package/components/fleet/FleetClusterTargets/TargetsList.vue +47 -29
  52. package/components/fleet/FleetClusterTargets/index.vue +82 -29
  53. package/components/fleet/FleetClusters.vue +26 -12
  54. package/components/fleet/FleetGitRepoPaths.vue +2 -2
  55. package/components/fleet/FleetResources.vue +14 -0
  56. package/components/fleet/FleetValuesFrom.vue +2 -2
  57. package/components/fleet/__tests__/FleetClusterTargets.test.ts +531 -0
  58. package/components/fleet/__tests__/FleetClusters.test.ts +576 -0
  59. package/components/fleet/dashboard/ResourceDetails.vue +96 -123
  60. package/components/form/Conditions.vue +1 -15
  61. package/components/form/HookOption.vue +5 -0
  62. package/components/form/LabeledSelect.vue +1 -1
  63. package/components/form/LifecycleHooks.vue +2 -6
  64. package/components/form/ResourceLabeledSelect.vue +12 -1
  65. package/components/form/SeccompProfile.vue +113 -0
  66. package/components/form/Security.vue +244 -133
  67. package/components/form/__tests__/LabeledSelect.test.ts +1 -1
  68. package/components/form/__tests__/SeccompProfile.test.js +124 -0
  69. package/components/form/__tests__/Security.test.ts +125 -37
  70. package/components/formatter/Autoscaler.vue +2 -2
  71. package/components/formatter/FleetSummaryGraph.vue +4 -1
  72. package/components/nav/Group.vue +5 -0
  73. package/components/nav/Header.vue +3 -3
  74. package/components/nav/HeaderPageActionMenu.vue +1 -1
  75. package/components/nav/NamespaceFilter.vue +6 -6
  76. package/components/nav/NotificationCenter/index.vue +1 -1
  77. package/components/nav/TopLevelMenu.helper.ts +41 -16
  78. package/components/nav/TopLevelMenu.vue +45 -25
  79. package/components/nav/WorkspaceSwitcher.vue +1 -1
  80. package/components/nav/__tests__/TopLevelMenu.helper.test.ts +277 -0
  81. package/components/nav/__tests__/TopLevelMenu.test.ts +160 -4
  82. package/components/templates/default.vue +0 -3
  83. package/components/templates/home.vue +0 -3
  84. package/components/templates/plain.vue +0 -3
  85. package/composables/useClickOutside.ts +1 -1
  86. package/config/product/explorer.js +1 -2
  87. package/config/types.js +41 -8
  88. package/detail/__tests__/workload.test.ts +8 -16
  89. package/detail/catalog.cattle.io.app.vue +5 -0
  90. package/detail/fleet.cattle.io.cluster.vue +6 -0
  91. package/detail/workload/index.vue +7 -109
  92. package/edit/__tests__/projectsecret.test.ts +42 -0
  93. package/edit/auth/__tests__/oidc.test.ts +50 -0
  94. package/edit/auth/oidc.vue +68 -44
  95. package/edit/autoscaling.horizontalpodautoscaler/index.vue +140 -59
  96. package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +41 -5
  97. package/edit/projectsecret.vue +29 -0
  98. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +89 -200
  99. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +58 -17
  100. package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -0
  101. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +3 -63
  102. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +82 -14
  103. package/edit/workload/__tests__/index.test.ts +3 -4
  104. package/edit/workload/index.vue +47 -28
  105. package/edit/workload/mixins/workload.js +66 -31
  106. package/list/catalog.cattle.io.clusterrepo.vue +1 -1
  107. package/list/projectsecret.vue +2 -2
  108. package/machine-config/__tests__/vmwarevsphere.test.ts +64 -0
  109. package/machine-config/amazonec2.vue +2 -2
  110. package/machine-config/vmwarevsphere.vue +58 -4
  111. package/mixins/__tests__/chart.test.ts +63 -0
  112. package/mixins/chart.js +56 -51
  113. package/models/__tests__/catalog.cattle.io.app.test.ts +33 -0
  114. package/models/__tests__/workload.test.ts +333 -0
  115. package/models/catalog.cattle.io.app.js +8 -0
  116. package/models/pod.js +14 -0
  117. package/models/secret.js +1 -1
  118. package/models/workload.js +93 -27
  119. package/package.json +4 -4
  120. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +91 -0
  121. package/pages/c/_cluster/apps/charts/install.vue +4 -4
  122. package/pages/c/_cluster/explorer/EventsTable.vue +2 -2
  123. package/pages/c/_cluster/fleet/index.vue +14 -8
  124. package/pages/c/_cluster/manager/hostedprovider/index.vue +1 -19
  125. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  126. package/pages/c/_cluster/uiplugins/index.vue +1 -1
  127. package/plugins/dashboard-store/__tests__/resource-class.test.ts +234 -0
  128. package/plugins/dashboard-store/actions.js +9 -8
  129. package/plugins/dashboard-store/resource-class.js +97 -1
  130. package/plugins/steve/__tests__/revision.test.ts +84 -0
  131. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +30 -0
  132. package/plugins/steve/__tests__/subscribe.spec.ts +134 -0
  133. package/plugins/steve/revision.ts +26 -0
  134. package/plugins/steve/steve-pagination-utils.ts +6 -5
  135. package/plugins/steve/subscribe.js +188 -49
  136. package/plugins/subscribe-events.ts +2 -2
  137. package/rancher-components/Form/Checkbox/Checkbox.vue +13 -0
  138. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -1
  139. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +1 -1
  140. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +3 -1
  141. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -1
  142. package/rancher-components/Pill/RcTag/RcTag.vue +1 -1
  143. package/rancher-components/Pill/index.ts +4 -0
  144. package/rancher-components/RcButton/RcButton.test.ts +53 -9
  145. package/rancher-components/RcButton/RcButton.vue +217 -25
  146. package/rancher-components/RcButton/types.ts +27 -1
  147. package/rancher-components/RcDropdown/RcDropdownMenu.vue +4 -4
  148. package/rancher-components/RcDropdown/types.ts +3 -3
  149. package/rancher-components/RcIcon/RcIcon.test.ts +42 -0
  150. package/rancher-components/RcIcon/RcIcon.vue +9 -6
  151. package/rancher-components/RcIcon/types.ts +13 -9
  152. package/rancher-components/utils/status.test.ts +10 -15
  153. package/rancher-components/utils/status.ts +5 -6
  154. package/store/aws.js +18 -12
  155. package/store/index.js +4 -8
  156. package/store/type-map.utils.ts +1 -1
  157. package/types/kube/kube-api.ts +29 -3
  158. package/types/rancher/steve.api.ts +40 -0
  159. package/types/shell/index.d.ts +99 -0
  160. package/types/store/pagination.types.ts +1 -0
  161. package/types/store/subscribe-events.types.ts +1 -0
  162. package/utils/__tests__/azure.test.ts +56 -0
  163. package/utils/__tests__/back-off.test.ts +364 -245
  164. package/utils/__tests__/error.test.ts +44 -0
  165. package/utils/__tests__/fleet.test.ts +8 -1
  166. package/utils/__tests__/pagination-wrapper.test.ts +167 -0
  167. package/utils/__tests__/version.test.ts +55 -1
  168. package/utils/azure.js +12 -0
  169. package/utils/back-off.ts +302 -69
  170. package/utils/dynamic-content/__tests__/index.test.ts +1 -1
  171. package/utils/dynamic-content/__tests__/new-release.test.ts +48 -7
  172. package/utils/dynamic-content/__tests__/support-notice.test.ts +1 -4
  173. package/utils/dynamic-content/index.ts +1 -6
  174. package/utils/dynamic-content/new-release.ts +5 -3
  175. package/utils/dynamic-content/types.d.ts +0 -1
  176. package/utils/error.js +9 -0
  177. package/utils/fleet.ts +2 -2
  178. package/utils/inactivity.ts +2 -3
  179. package/utils/pagination-wrapper.ts +99 -15
  180. package/utils/validators/formRules/index.ts +3 -0
  181. package/utils/version.js +38 -0
  182. package/components/auth/AzureWarning.vue +0 -77
  183. /package/components/Resource/Detail/{Card/PodsCard/Bubble.vue → Bubble.vue} +0 -0
  184. /package/components/Resource/Detail/Card/{PodsCard → StatusCard}/composable.ts +0 -0
@@ -1,4 +1,4 @@
1
- import { computed } from 'vue';
1
+ import { computed, Ref } from 'vue';
2
2
 
3
3
  export const StatusDefinitions = {
4
4
  info: {
@@ -28,7 +28,6 @@ export const StatusDefinitions = {
28
28
  };
29
29
 
30
30
  export type Status = keyof typeof StatusDefinitions;
31
- export type StatusObject = { status: Status };
32
31
  export type Style = 'solid' | 'outlined';
33
32
 
34
33
  export function wrapIfVar(colorVar: string) {
@@ -38,13 +37,13 @@ export function wrapIfVar(colorVar: string) {
38
37
  /**
39
38
  * A composable to make it easier to use status colors in multiple components
40
39
  *
41
- * @param propsWithStatus The props which contain a `status: Status` property. Ideally I'd prefer to just pass status but doing so either forces the consumer to wrap the values in a Ref or this code is no longer reactive.
40
+ * @param status A Ref containing the status value
42
41
  * @param style {@link Style} Will the block of code being using the solid or outlined styling
43
42
  * @returns An object containing the relevant style colors
44
43
  */
45
- export function useStatusColors(propsWithStatus: StatusObject, style: Style) {
44
+ export function useStatusColors(status: Ref<Status>, style: Style) {
46
45
  const statusColors = computed(() => {
47
- return StatusDefinitions[propsWithStatus.status];
46
+ return StatusDefinitions[status.value];
48
47
  });
49
48
  const isOutlined = style === 'outlined';
50
49
 
@@ -55,7 +54,7 @@ export function useStatusColors(propsWithStatus: StatusObject, style: Style) {
55
54
  });
56
55
 
57
56
  const backgroundColor = computed(() => {
58
- if (propsWithStatus.status === 'none') {
57
+ if (status.value === 'none') {
59
58
  return 'none';
60
59
  }
61
60
  const colorVar = isOutlined ? statusColors.value.secondary : statusColors.value.primary;
package/store/aws.js CHANGED
@@ -2,6 +2,7 @@ import { sortBy } from '@shell/utils/sort';
2
2
  import { randomStr } from '@shell/utils/string';
3
3
  import { FetchHttpHandler } from '@smithy/fetch-http-handler';
4
4
  import { isArray, addObjects } from '@shell/utils/array';
5
+ import { formatAWSError } from '@shell/utils/error';
5
6
 
6
7
  export const state = () => {
7
8
  return {
@@ -247,21 +248,26 @@ export const actions = {
247
248
  opt = opt || {};
248
249
 
249
250
  while ( hasNext ) {
250
- const res = await client[cmd](opt);
251
+ try {
252
+ const res = await client[cmd](opt);
251
253
 
252
- if ( !key ) {
253
- key = Object.keys(res).find((x) => isArray(res[x]));
254
- }
254
+ if ( !key ) {
255
+ key = Object.keys(res).find((x) => isArray(res[x]));
256
+ }
255
257
 
256
- addObjects(out, res[key]);
257
- if (res.NextToken) {
258
- opt.NextToken = res.NextToken;
259
- hasNext = true;
260
- } else if (res.Marker) {
261
- opt.Marker = res.Marker;
262
- hasNext = true;
263
- } else {
258
+ addObjects(out, res[key]);
259
+ if (res.NextToken) {
260
+ opt.NextToken = res.NextToken;
261
+ hasNext = true;
262
+ } else if (res.Marker) {
263
+ opt.Marker = res.Marker;
264
+ hasNext = true;
265
+ } else {
266
+ hasNext = false;
267
+ }
268
+ } catch (err) {
264
269
  hasNext = false;
270
+ throw formatAWSError(err);
265
271
  }
266
272
  }
267
273
 
package/store/index.js CHANGED
@@ -36,7 +36,8 @@ import { sortBy } from '@shell/utils/sort';
36
36
  import { addParam } from '@shell/utils/url';
37
37
  import semver from 'semver';
38
38
  import { STORE, BLANK_CLUSTER } from '@shell/store/store-types';
39
- import { isDevBuild } from '@shell/utils/version';
39
+ import { getReleaseNotesURL } from '@shell/utils/version';
40
+ import { getVersionData } from '@shell/config/version';
40
41
  import { markRaw } from 'vue';
41
42
  import paginationUtils from '@shell/utils/pagination-utils';
42
43
  import { addReleaseNotesNotification } from '@shell/utils/release-notes';
@@ -628,14 +629,9 @@ export const getters = {
628
629
 
629
630
  releaseNotesUrl(state, getters) {
630
631
  const version = getters['management/byId'](MANAGEMENT.SETTING, SETTING.VERSION_RANCHER)?.value;
632
+ const isPrime = getVersionData().RancherPrime === 'true';
631
633
 
632
- const base = 'https://github.com/rancher/rancher/releases';
633
-
634
- if (version && !isDevBuild(version)) {
635
- return `${ base }/tag/${ version }`;
636
- }
637
-
638
- return `${ base }/latest`;
634
+ return getReleaseNotesURL(isPrime, version);
639
635
  },
640
636
 
641
637
  ...gcGetters
@@ -142,7 +142,7 @@ export function headerFromSchemaColString(colName: string, schema: Schema, rootG
142
142
  export function headerFromSchemaCol(col: SchemaAttributeColumn, rootGetters: VuexStoreGetters, pagination: boolean, ageColumn: TableColumn): TableColumn {
143
143
  let formatter, width, formatterOpts;
144
144
 
145
- if ( (col.format === '' || col.format === 'date') && col.name === 'Age' && ageColumn ) {
145
+ if ( (col.format === '' || col.format === 'date' || col.type === 'date') && col.name.toLowerCase() === 'age' && ageColumn ) {
146
146
  return ageColumn;
147
147
  }
148
148
 
@@ -25,11 +25,37 @@ export interface KubeLabelSelector {
25
25
  * https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#objectmeta-v1-meta
26
26
  */
27
27
  export interface KubeMetadata {
28
+ namespace?: string,
29
+ name: string
30
+
28
31
  labels?: { [key: string]: string },
29
32
  annotations?: { [key: string]: string },
30
33
  }
31
34
 
32
- export interface RancherKubeMetadata extends KubeMetadata {
33
- namespace?: string,
34
- name: string
35
+ /**
36
+ * Kube API JSON response for LIST requests
37
+ */
38
+ export interface KubeListResponse<T = any> {
39
+ kind: string,
40
+ apiVersion: string,
41
+
42
+ items: T[],
43
+
44
+ // Bucket for everything else (hopefully to remove once above populated)
45
+ [key: string]: any
46
+ }
47
+
48
+ /**
49
+ * Kube API JSON response for GET requests
50
+ */
51
+ export interface KubeGetResponse {
52
+ kind: string,
53
+ apiVersion: string,
54
+
55
+ metadata: KubeMetadata,
56
+ spec: any,
57
+ status: any,
58
+
59
+ // Bucket for everything else (hopefully to remove once above populated)
60
+ [key: string]: any
35
61
  }
@@ -0,0 +1,40 @@
1
+ import { KubeGetResponse, KubeMetadata } from '@shell/types/kube/kube-api';
2
+
3
+ /**
4
+ * Collection of string based values used by the Steve API response's `code` field
5
+ */
6
+ export const STEVE_RESPONSE_CODE = {
7
+ /**
8
+ * When the query param `revision` is sent and it's not in the vai cache then return this error
9
+ */
10
+ UNKNOWN_REVISION: 'unknown revision'
11
+ };
12
+
13
+ /**
14
+ * Steve API JSON response for LIST requests
15
+ */
16
+ export interface SteveListResponse<T = any> {
17
+ actions: any,
18
+ count: number,
19
+ data: T[],
20
+ links: any,
21
+ resourceType: string,
22
+ revision: string,
23
+ type: string,
24
+
25
+ // Bucket for everything else (hopefully to remove once above populated)
26
+ [key: string]: any
27
+ }
28
+
29
+ /**
30
+ * Steve API JSON response for GET requests
31
+ */
32
+ export interface SteveGetResponse extends KubeGetResponse {
33
+ // Rancher specific properties (there are more)
34
+ id: string,
35
+
36
+ // Bucket for everything else (hopefully to remove once above populated)
37
+ [key: string]: any
38
+ }
39
+
40
+ export type RancherKubeMetadata = KubeMetadata
@@ -2097,9 +2097,34 @@ export namespace WORKLOAD_TYPES {
2097
2097
  let REPLICA_SET: string;
2098
2098
  let REPLICATION_CONTROLLER: string;
2099
2099
  }
2100
+ export namespace WORKLOAD_KINDS {
2101
+ let DEPLOYMENT_1: string;
2102
+ export { DEPLOYMENT_1 as DEPLOYMENT };
2103
+ let CRON_JOB_1: string;
2104
+ export { CRON_JOB_1 as CRON_JOB };
2105
+ let DAEMON_SET_1: string;
2106
+ export { DAEMON_SET_1 as DAEMON_SET };
2107
+ let JOB_1: string;
2108
+ export { JOB_1 as JOB };
2109
+ let STATEFUL_SET_1: string;
2110
+ export { STATEFUL_SET_1 as STATEFUL_SET };
2111
+ let REPLICA_SET_1: string;
2112
+ export { REPLICA_SET_1 as REPLICA_SET };
2113
+ let REPLICATION_CONTROLLER_1: string;
2114
+ export { REPLICATION_CONTROLLER_1 as REPLICATION_CONTROLLER };
2115
+ }
2116
+ /**
2117
+ * Map Rancher Workload types to Kube Workload Kinds
2118
+ */
2100
2119
  export const WORKLOAD_TYPE_TO_KIND_MAPPING: {
2101
2120
  [x: string]: string;
2102
2121
  };
2122
+ /**
2123
+ * Map Kube Workload Kinds types to Rancher Workload
2124
+ */
2125
+ export const WORKLOAD_KIND_TO_TYPE_MAPPING: {
2126
+ [x: string]: string;
2127
+ };
2103
2128
  export const METRICS_SUPPORTED_KINDS: string[];
2104
2129
  export namespace SCALABLE_WORKLOAD_TYPES { }
2105
2130
  export namespace LIST_WORKLOAD_TYPES {
@@ -3434,6 +3459,46 @@ export default class Resource {
3434
3459
  id: any;
3435
3460
  };
3436
3461
  };
3462
+ /**
3463
+ * Override this getter to provide additional action buttons or a custom component
3464
+ * for the detail page title bar.
3465
+ *
3466
+ * @returns {undefined|object|Array} A Vue component definition, an array of RcButton props, or undefined
3467
+ *
3468
+ * @example
3469
+ * // Using an array of button props with the new variant/size props
3470
+ * get detailPageAdditionalActions() {
3471
+ * return [
3472
+ * { label: 'Action 1', variant: 'secondary', onClick: () => this.doAction1() },
3473
+ * { label: 'Action 2', variant: 'primary', size: 'large', onClick: () => this.doAction2() }
3474
+ * ];
3475
+ * }
3476
+ *
3477
+ * @example
3478
+ * // Using defineComponent with h() render function for custom rendering
3479
+ * import { defineComponent, h } from 'vue';
3480
+ * import RcButton from '@components/RcButton/RcButton.vue';
3481
+ *
3482
+ * get detailPageAdditionalActions() {
3483
+ * return defineComponent({
3484
+ * render() {
3485
+ * return h(RcButton, {
3486
+ * variant: 'primary',
3487
+ * onClick: () => console.log('clicked')
3488
+ * }, () => 'Click Me');
3489
+ * }
3490
+ * });
3491
+ * }
3492
+ *
3493
+ * @example
3494
+ * // Using dynamic import for a custom component
3495
+ * import { defineAsyncComponent } from 'vue';
3496
+ *
3497
+ * get detailPageAdditionalActions() {
3498
+ * return defineAsyncComponent(() => import('@shell/components/MyCustomActions.vue'));
3499
+ * }
3500
+ */
3501
+ get detailPageAdditionalActions(): any;
3437
3502
  goToDetail(): void;
3438
3503
  /**
3439
3504
  * Resource action redirects to the detail page with a query parameter 'clone'
@@ -3647,6 +3712,33 @@ export default class Resource {
3647
3712
  * Allows model to specify JSON Paths that should be folded in the YAML editor by default
3648
3713
  */
3649
3714
  get yamlFolding(): any[];
3715
+ get resourceConditions(): any;
3716
+ get resourceEvents(): any;
3717
+ get insightCardProps(): {
3718
+ title: any;
3719
+ rows: any[];
3720
+ };
3721
+ get insightCard(): {
3722
+ component: any;
3723
+ props: {
3724
+ title: any;
3725
+ rows: any[];
3726
+ };
3727
+ };
3728
+ get _cards(): {
3729
+ component: any;
3730
+ props: {
3731
+ title: any;
3732
+ rows: any[];
3733
+ };
3734
+ }[];
3735
+ get cards(): {
3736
+ component: any;
3737
+ props: {
3738
+ title: any;
3739
+ rows: any[];
3740
+ };
3741
+ }[];
3650
3742
  }
3651
3743
  }
3652
3744
 
@@ -4461,6 +4553,7 @@ export class ApiError extends Error {
4461
4553
  };
4462
4554
  }
4463
4555
  export function normalizeError(err: any): any;
4556
+ export function formatAWSError(err: any): any;
4464
4557
  }
4465
4558
 
4466
4559
  // @shell/utils/favicon
@@ -5318,6 +5411,12 @@ export function seenReleaseNotes(store: any): boolean;
5318
5411
  export function markSeenReleaseNotes(store: any): Promise<void>;
5319
5412
  export function readReleaseNotes(store: any): boolean;
5320
5413
  export function markReadReleaseNotes(store: any): Promise<void>;
5414
+ /**
5415
+ * Get the release notes URL for a given version
5416
+ *
5417
+ * @param {Get} version s
5418
+ */
5419
+ export function getReleaseNotesURL(isPrime: any, version: Get): string;
5321
5420
  }
5322
5421
 
5323
5422
  // @shell/utils/width
@@ -599,6 +599,7 @@ export interface StorePaginationResult {
599
599
  * The last time the resource was updated. Used to assist list watching for changes
600
600
  */
601
601
  timestamp: number,
602
+ revision: string,
602
603
  }
603
604
 
604
605
  export interface StorePaginationRequest {
@@ -17,6 +17,7 @@ export interface STEVE_WATCH_EVENT_PARAMS_COMMON {
17
17
  */
18
18
  export type STEVE_WATCH_EVENT_LISTENER_CALLBACK_PARAMS = {
19
19
  forceWatch?: boolean,
20
+ revision?: string,
20
21
  }
21
22
 
22
23
  /**
@@ -0,0 +1,56 @@
1
+ import { parseAzureError } from '@shell/utils/azure';
2
+
3
+ describe('azure.js', () => {
4
+ describe('parseAzureError', () => {
5
+ it('should extract error from Message="..." format', () => {
6
+ const err = 'Something went wrong Message="Failure"';
7
+
8
+ expect(parseAzureError(err)).toBe('Failure');
9
+ });
10
+
11
+ it('should extract error_description from single-line Response body JSON', () => {
12
+ const err = 'Error X Response body: {"error_description": "Failure"}';
13
+
14
+ expect(parseAzureError(err)).toBe('Failure');
15
+ });
16
+
17
+ it('should extract error.message from multiline JSON containing "error":', () => {
18
+ const err = `
19
+ { "error": { "code": "NoRegisteredProviderFound", "message": "No registered resource provider found for location 'X'" } }
20
+ `;
21
+
22
+ expect(parseAzureError(err)).toBe("No registered resource provider found for location 'X'");
23
+ });
24
+
25
+ it('should return undefined if single-line JSON exists but lacks error_description', () => {
26
+ // Note: Current implementation returns undefined immediately if JSON parses but key is missing
27
+ const err = 'Response body: {"other_field": "value"}';
28
+
29
+ expect(parseAzureError(err)).toBeUndefined();
30
+ });
31
+
32
+ it('should return false if multiline JSON exists but lacks error.message', () => {
33
+ const err = `
34
+ {
35
+ "error": {
36
+ "code": "NoMessage"
37
+ }
38
+ }
39
+ `;
40
+
41
+ expect(parseAzureError(err)).toBe(false);
42
+ });
43
+
44
+ it('should return false if JSON parsing fails', () => {
45
+ const err1 = 'Response body: { invalid json }';
46
+ const err2 = '{ "error": { invalid } }';
47
+
48
+ expect(parseAzureError(err1)).toBe(false);
49
+ expect(parseAzureError(err2)).toBe(false);
50
+ });
51
+
52
+ it('should return false for unmatched strings', () => {
53
+ expect(parseAzureError('error string')).toBe(false);
54
+ });
55
+ });
56
+ });