@rancher/shell 3.0.2-rc.2 → 3.0.2-rc.3

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 (141) hide show
  1. package/assets/styles/base/_basic.scss +5 -7
  2. package/assets/styles/global/_button.scss +10 -0
  3. package/assets/styles/global/_tooltip.scss +2 -2
  4. package/assets/styles/themes/_dark.scss +14 -2
  5. package/assets/styles/themes/_light.scss +7 -2
  6. package/assets/styles/vendor/vue-select.scss +4 -0
  7. package/assets/translations/en-us.yaml +44 -5
  8. package/components/BannerGraphic.vue +0 -42
  9. package/components/ButtonMultiAction.vue +1 -1
  10. package/components/Carousel.vue +36 -29
  11. package/components/CommunityLinks.vue +6 -1
  12. package/components/GrowlManager.vue +9 -2
  13. package/components/LocaleSelector.vue +8 -1
  14. package/components/PaginatedResourceTable.vue +4 -7
  15. package/components/ProgressBarMulti.vue +14 -0
  16. package/components/Questions/Reference.vue +57 -28
  17. package/components/SelectIconGrid.vue +12 -1
  18. package/components/SideNav.vue +12 -38
  19. package/components/SortableTable/index.vue +1 -0
  20. package/components/Tabbed/index.vue +12 -1
  21. package/components/YamlEditor.vue +1 -0
  22. package/components/auth/Principal.vue +5 -3
  23. package/components/fleet/FleetClusters.vue +82 -1
  24. package/components/fleet/FleetRepos.vue +13 -30
  25. package/components/fleet/ForceDirectedTreeChart/index.vue +2 -2
  26. package/components/form/ChangePassword.vue +2 -0
  27. package/components/form/ColorInput.vue +24 -1
  28. package/components/form/FileSelector.vue +2 -0
  29. package/components/form/KeyValue.vue +230 -160
  30. package/components/form/LabeledSelect.vue +1 -1
  31. package/components/form/PlusMinus.vue +14 -2
  32. package/components/form/ResourceLabeledSelect.vue +13 -53
  33. package/components/form/ResourceSelector.vue +1 -0
  34. package/components/form/ResourceTabs/index.vue +79 -36
  35. package/components/form/SecretSelector.vue +2 -2
  36. package/components/form/__tests__/KeyValue.test.ts +1 -1
  37. package/components/formatter/FleetClusterSummaryGraph.vue +2 -2
  38. package/components/formatter/FleetSummaryGraph.vue +6 -7
  39. package/components/formatter/WorkloadHealthScale.vue +7 -0
  40. package/components/nav/Group.vue +30 -4
  41. package/components/nav/Header.vue +82 -114
  42. package/components/nav/HeaderPageActionMenu.vue +27 -131
  43. package/components/nav/NamespaceFilter.vue +1 -1
  44. package/components/nav/Type.vue +15 -0
  45. package/config/home-links.js +21 -13
  46. package/config/labels-annotations.js +2 -0
  47. package/config/page-actions.js +1 -0
  48. package/config/pagination-table-headers.js +15 -1
  49. package/config/product/explorer.js +7 -17
  50. package/config/table-headers.js +6 -0
  51. package/config/version.js +5 -1
  52. package/core/plugin.ts +41 -1
  53. package/core/plugins.js +125 -72
  54. package/core/types-provisioning.ts +91 -2
  55. package/core/types.ts +55 -0
  56. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +12 -3
  57. package/detail/catalog.cattle.io.app.vue +1 -1
  58. package/detail/fleet.cattle.io.cluster.vue +3 -3
  59. package/detail/namespace.vue +13 -19
  60. package/detail/networking.k8s.io.ingress.vue +13 -53
  61. package/detail/provisioning.cattle.io.cluster.vue +12 -1
  62. package/detail/workload/index.vue +3 -3
  63. package/dialog/AddCustomBadgeDialog.vue +5 -1
  64. package/edit/auth/ldap/__tests__/config.test.ts +18 -0
  65. package/edit/auth/ldap/config.vue +24 -0
  66. package/edit/auth/saml.vue +8 -6
  67. package/edit/fleet.cattle.io.gitrepo.vue +7 -1
  68. package/edit/logging-flow/index.vue +4 -19
  69. package/edit/networking.k8s.io.ingress/index.vue +18 -65
  70. package/edit/networking.k8s.io.networkpolicy/index.vue +4 -5
  71. package/edit/provisioning.cattle.io.cluster/index.vue +13 -1
  72. package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -115
  73. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +2 -2
  74. package/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue +14 -28
  75. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +25 -12
  76. package/edit/service.vue +1 -2
  77. package/list/networking.k8s.io.ingress.vue +1 -1
  78. package/list/node.vue +15 -8
  79. package/list/persistentvolume.vue +12 -4
  80. package/list/service.vue +1 -1
  81. package/list/workload.vue +4 -0
  82. package/mixins/chart.js +4 -1
  83. package/models/catalog.cattle.io.app.js +3 -1
  84. package/models/catalog.cattle.io.clusterrepo.js +56 -7
  85. package/models/fleet.cattle.io.bundle.js +0 -11
  86. package/models/fleet.cattle.io.cluster.js +17 -1
  87. package/models/fleet.cattle.io.gitrepo.js +86 -50
  88. package/models/provisioning.cattle.io.cluster.js +47 -2
  89. package/models/service.js +1 -0
  90. package/models/workload.js +19 -1
  91. package/package.json +5 -4
  92. package/pages/c/_cluster/apps/charts/index.vue +4 -0
  93. package/pages/c/_cluster/explorer/ConfigBadge.vue +8 -7
  94. package/pages/c/_cluster/explorer/index.vue +13 -6
  95. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +3 -3
  96. package/pages/c/_cluster/fleet/index.vue +75 -89
  97. package/pages/c/_cluster/settings/links.vue +2 -2
  98. package/pages/diagnostic.vue +17 -15
  99. package/pages/home.vue +32 -6
  100. package/plugins/clean-html.js +50 -0
  101. package/plugins/dashboard-store/resource-class.js +4 -0
  102. package/plugins/plugin.js +54 -49
  103. package/plugins/steve/mutations.js +1 -1
  104. package/plugins/steve/steve-class.js +8 -0
  105. package/plugins/steve/steve-pagination-utils.ts +3 -1
  106. package/rancher-components/Accordion/Accordion.vue +4 -4
  107. package/rancher-components/BadgeState/BadgeState.vue +7 -0
  108. package/rancher-components/Card/Card.vue +27 -1
  109. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -2
  110. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
  111. package/rancher-components/Form/LabeledInput/LabeledInput.vue +18 -1
  112. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +39 -2
  113. package/rancher-components/RcButton/RcButton.vue +90 -0
  114. package/rancher-components/RcButton/index.ts +2 -0
  115. package/rancher-components/RcButton/types.ts +17 -0
  116. package/rancher-components/RcDropdown/RcDropdown.vue +111 -0
  117. package/rancher-components/RcDropdown/RcDropdownItem.vue +127 -0
  118. package/rancher-components/RcDropdown/RcDropdownSeparator.vue +6 -0
  119. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +43 -0
  120. package/rancher-components/RcDropdown/index.ts +4 -0
  121. package/rancher-components/RcDropdown/types.ts +22 -0
  122. package/rancher-components/RcDropdown/useDropdownCollection.ts +45 -0
  123. package/rancher-components/RcDropdown/useDropdownContext.ts +83 -0
  124. package/scripts/test-plugins-build.sh +2 -0
  125. package/scripts/typegen.sh +2 -0
  126. package/store/catalog.js +1 -1
  127. package/tsconfig.json +2 -1
  128. package/types/components/paginatedResourceTable.ts +25 -0
  129. package/types/components/resourceLabeledSelect.ts +48 -0
  130. package/types/resources/fleet.d.ts +17 -0
  131. package/types/shell/index.d.ts +61 -0
  132. package/utils/auth.js +5 -1
  133. package/utils/cluster.js +106 -0
  134. package/utils/fleet.ts +35 -3
  135. package/utils/ingress.ts +64 -0
  136. package/utils/uiplugins.ts +56 -44
  137. package/utils/validators/cron-schedule.js +7 -2
  138. package/utils/validators/formRules/__tests__/index.test.ts +53 -17
  139. package/utils/validators/formRules/index.ts +20 -5
  140. package/vue.config.js +1 -1
  141. package/components/RelatedWorkloadsTable.vue +0 -50
@@ -0,0 +1,22 @@
1
+ import { Ref, ref } from 'vue';
2
+ import type { RcButtonType } from '@components/RcButton';
3
+
4
+ export type DropdownContext = {
5
+ handleKeydown: () => void;
6
+ showMenu: (show: boolean) => void;
7
+ registerTrigger: (triggerRef: RcButtonType | null) => void;
8
+ dropdownItems: Ref<Element[]>;
9
+ focusFirstElement: () => void;
10
+ isMenuOpen: Ref<boolean>;
11
+ close: () => void;
12
+ }
13
+
14
+ export const defaultContext: DropdownContext = {
15
+ handleKeydown: () => null,
16
+ showMenu: (_show: boolean | null) => null,
17
+ registerTrigger: (_triggerRef: RcButtonType | null) => null,
18
+ dropdownItems: ref([]),
19
+ focusFirstElement: () => null,
20
+ isMenuOpen: ref(false),
21
+ close: () => null,
22
+ };
@@ -0,0 +1,45 @@
1
+ import { ref } from 'vue';
2
+
3
+ /**
4
+ * Manages a collection of dropdown items. Includes methods for registering
5
+ * dropdown items and providing the collection to descendant components.
6
+ *
7
+ * @returns Dropdown collection methods and state.
8
+ */
9
+ export const useDropdownCollection = () => {
10
+ const dropdownItems = ref<Element[]>([]);
11
+ const dropdownContainer = ref<HTMLElement | null>(null);
12
+ const firstDropdownItem = ref<HTMLElement | null>(null);
13
+
14
+ /**
15
+ * Registers the dropdown container and initializes dropdown items.
16
+ * @param target - The dropdown container element.
17
+ */
18
+ const registerDropdownCollection = (target: HTMLElement | null) => {
19
+ dropdownContainer.value = target;
20
+ if (dropdownContainer.value?.firstElementChild instanceof HTMLElement) {
21
+ registerDropdownItems();
22
+ if (dropdownItems.value[0] instanceof HTMLElement) {
23
+ firstDropdownItem.value = dropdownItems.value[0];
24
+ }
25
+ }
26
+ };
27
+
28
+ /**
29
+ * Registers dropdown items by querying the dropdown container for elements.
30
+ */
31
+ const registerDropdownItems = () => {
32
+ dropdownItems.value = [];
33
+ const dropdownNodeList = dropdownContainer.value?.querySelectorAll('[dropdown-menu-item]');
34
+
35
+ dropdownNodeList?.forEach((element) => {
36
+ dropdownItems.value.push(element);
37
+ });
38
+ };
39
+
40
+ return {
41
+ dropdownItems,
42
+ firstDropdownItem,
43
+ registerDropdownCollection,
44
+ };
45
+ };
@@ -0,0 +1,83 @@
1
+ import { ref, provide, nextTick } from 'vue';
2
+ import { useDropdownCollection } from './useDropdownCollection';
3
+ import { RcButtonType } from '@components/RcButton';
4
+
5
+ /**
6
+ * Composable that provides the context for a dropdown menu. Includes methods
7
+ * and state for managing the dropdown's visibility, focus, and keyboard
8
+ * interactions.
9
+ *
10
+ * @param firstDropdownItem - First item in the dropdown menu.
11
+ * @returns Dropdown context methods and state. Used for programmatic
12
+ * interactions and setting focus.
13
+ */
14
+ export const useDropdownContext = () => {
15
+ const { dropdownItems, firstDropdownItem, registerDropdownCollection } = useDropdownCollection();
16
+
17
+ const isMenuOpen = ref(false);
18
+
19
+ /**
20
+ * Controls the visibility of the dropdown menu.
21
+ * @param show - Whether to show or hide the dropdown menu.
22
+ */
23
+ const showMenu = (show: boolean) => {
24
+ isMenuOpen.value = show;
25
+ };
26
+
27
+ /**
28
+ * A ref for the dropdown trigger element. Used for programmatic
29
+ * interactions and setting focus.
30
+ */
31
+ const dropdownTrigger = ref<RcButtonType | null>(null);
32
+
33
+ /**
34
+ * Registers the dropdown trigger element.
35
+ * @param triggerRef - The dropdown trigger element.
36
+ */
37
+ const registerTrigger = (triggerRef: RcButtonType) => {
38
+ dropdownTrigger.value = triggerRef;
39
+ };
40
+
41
+ /**
42
+ * Returns focus to the dropdown trigger and closes the menu.
43
+ */
44
+ const returnFocus = () => {
45
+ showMenu(false);
46
+ dropdownTrigger?.value?.focus();
47
+ };
48
+
49
+ /**
50
+ * Sets focus to the first dropdown item if a keydown event has occurred.
51
+ */
52
+ const setFocus = () => {
53
+ nextTick(() => {
54
+ firstDropdownItem.value?.focus();
55
+ });
56
+ };
57
+
58
+ /**
59
+ * Provides Dropdown Context data and methods to descendants of RcDropdown.
60
+ * Accessed in descendents with the `inject()` function.
61
+ */
62
+ const provideDropdownContext = () => {
63
+ provide('dropdownContext', {
64
+ showMenu,
65
+ registerTrigger,
66
+ isMenuOpen,
67
+ dropdownItems,
68
+ close: () => returnFocus(),
69
+ focusFirstElement: () => {
70
+ setFocus();
71
+ },
72
+ });
73
+ };
74
+
75
+ return {
76
+ isMenuOpen,
77
+ showMenu,
78
+ returnFocus,
79
+ setFocus,
80
+ provideDropdownContext,
81
+ registerDropdownCollection,
82
+ };
83
+ };
@@ -141,6 +141,8 @@ if [ "${SKIP_STANDALONE}" == "false" ]; then
141
141
  pushd test-app > /dev/null
142
142
 
143
143
  yarn install
144
+ # this is the "same" as doing a yarn dev (in a build sense)
145
+ # it's to make sure the dev environment is running properly
144
146
  FORCE_COLOR=true yarn build | cat
145
147
 
146
148
  # Add test list component to the test package
@@ -21,10 +21,12 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/query-params.js --declarat
21
21
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/table-headers.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
22
22
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/types.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
23
23
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/labels-annotations.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
24
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/config/version.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/config > /dev/null
24
25
 
25
26
  # # store
26
27
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/features.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
27
28
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/prefs.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
29
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/plugins.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
28
30
 
29
31
  # # plugins
30
32
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/normalize.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
package/store/catalog.js CHANGED
@@ -57,7 +57,7 @@ export const getters = {
57
57
  const clustered = state.clusterRepos || [];
58
58
  const namespaced = state.namespacedRepos || [];
59
59
 
60
- return [...clustered, ...namespaced];
60
+ return [...clustered, ...namespaced].filter((r) => r.spec?.enabled !== false);
61
61
  },
62
62
 
63
63
  // Raw charts
package/tsconfig.json CHANGED
@@ -29,7 +29,8 @@
29
29
  "./**/*.ts",
30
30
  "./**/*.d.ts",
31
31
  "./**/*.tsx",
32
- "./**/*.vue"
32
+ "./**/*.vue",
33
+ "../pkg/rancher-components/src/**/*"
33
34
  ],
34
35
  "exclude": [
35
36
  "node_modules",
@@ -0,0 +1,25 @@
1
+ import { StorePaginationResult } from '@shell/types/store/pagination.types';
2
+
3
+ /**
4
+ * see {@link PagTableFetchSecondaryResources}
5
+ */
6
+ export type PagTableFetchSecondaryResourcesOpts = { canPaginate: boolean }
7
+ /**
8
+ * see {@link PagTableFetchSecondaryResources}
9
+ */
10
+ export type PagTableFetchSecondaryResourcesReturns = Promise<any>
11
+ /**
12
+ * Function to fetch resources that are required to supplement information needed by rows in a PaginatedResourceTable
13
+ *
14
+ * Used in scenarios where ALL resources are expected
15
+ */
16
+ export type PagTableFetchSecondaryResources = (opts: PagTableFetchSecondaryResourcesOpts) => PagTableFetchSecondaryResourcesReturns
17
+
18
+ /**
19
+ * see {@link PagTableFetchPageSecondaryResources}
20
+ */
21
+ export type PagTableFetchPageSecondaryResourcesOpts = { canPaginate: boolean, force: boolean, page: any[], pagResult: StorePaginationResult }
22
+ /**
23
+ * Function to fetch resources that are required to supplement information needed by a single page in a PaginatedResourceTable
24
+ */
25
+ export type PagTableFetchPageSecondaryResources = (opts: PagTableFetchPageSecondaryResourcesOpts) => Promise<any>
@@ -0,0 +1,48 @@
1
+ import { LabelSelectPaginationFunctionOptions } from '@shell/components/form/labeled-select-utils/labeled-select.utils';
2
+ import { LabelSelectPaginateFn } from '@shell/types/components/labeledSelect';
3
+
4
+ type PaginateTypeOverridesFn = (opts: LabelSelectPaginationFunctionOptions) => LabelSelectPaginationFunctionOptions;
5
+
6
+ interface SharedSettings {
7
+ /**
8
+ * Provide specific LabelSelect options for this mode (paginated / not paginated)
9
+ */
10
+ labelSelectOptions?: { [key: string]: any },
11
+ /**
12
+ * Map, filter, tweak, etc the resources to show in the LabelSelect
13
+ */
14
+ updateResources?: (resources: any[]) => any[]
15
+ }
16
+
17
+ /**
18
+ * Settings to use when the LabelSelect is paginating
19
+ */
20
+ export interface ResourceLabeledSelectPaginateSettings extends SharedSettings {
21
+ /**
22
+ * Override the convenience function which fetches a page of results
23
+ */
24
+ overrideRequest?: LabelSelectPaginateFn,
25
+ /**
26
+ * Override the default settings used in the convenience function to fetch a page of results
27
+ */
28
+ requestSettings?: PaginateTypeOverridesFn,
29
+ }
30
+
31
+ /**
32
+ * Settings to use when the LabelSelect is fetching all resources (not paginating)
33
+ */
34
+ export type ResourceLabeledSelectSettings = SharedSettings
35
+
36
+ /**
37
+ * Force a specific mode
38
+ */
39
+ export enum RESOURCE_LABEL_SELECT_MODE {
40
+ /**
41
+ * Fetch all resources
42
+ */
43
+ ALL_RESOURCES = 'ALL', // eslint-disable-line no-unused-vars
44
+ /**
45
+ * Determine if all resources are fetched given system settings
46
+ */
47
+ DYNAMIC = 'DYNAMIC', // eslint-disable-line no-unused-vars
48
+ }
@@ -24,10 +24,19 @@ export interface BundleNonReadyBundle {
24
24
  nonReadyStatus: BundleNonReadyResource[],
25
25
  }
26
26
 
27
+ export interface Condition {
28
+ status: string,
29
+ type: string,
30
+ }
31
+
27
32
  export interface BundleDeploymentStatus {
28
33
  resources?: BundleDeploymentResource[],
29
34
  modifiedStatus?: BundleModifiedResource[],
30
35
  nonReadyStatus?: BundleNonReadyResource[],
36
+ appliedDeploymentId?: string,
37
+ ready: boolean
38
+ nonModified: boolean
39
+ conditions: Condition[],
31
40
  }
32
41
 
33
42
  export interface BundleStatusSummary {
@@ -38,3 +47,11 @@ export interface BundleStatus {
38
47
  resourceKey?: BundleResourceKey[],
39
48
  summary?: BundleStatusSummary,
40
49
  }
50
+
51
+ export interface BundleDeployment {
52
+ spec: {
53
+ deploymentId: string,
54
+ stagedDeploymentId: string,
55
+ }
56
+ status?: BundleDeploymentStatus
57
+ }
@@ -125,6 +125,8 @@ export namespace FLEET {
125
125
  export let CLUSTER_DISPLAY_NAME: string;
126
126
  export let CLUSTER_NAME: string;
127
127
  export let BUNDLE_ID: string;
128
+ export let BUNDLE_NAME: string;
129
+ export let BUNDLE_NAMESPACE: string;
128
130
  let MANAGED_1: string;
129
131
  export { MANAGED_1 as MANAGED };
130
132
  let CLUSTER_NAMESPACE_1: string;
@@ -997,6 +999,9 @@ export namespace LAST_SEEN_TIME {
997
999
  export { sort_50 as sort };
998
1000
  export let tooltip: string;
999
1001
  }
1002
+ export namespace EVENT_LAST_SEEN_TIME {
1003
+ let defaultSort: boolean;
1004
+ }
1000
1005
  export namespace LAST_HEARTBEAT_TIME {
1001
1006
  let name_58: string;
1002
1007
  export { name_58 as name };
@@ -2203,6 +2208,21 @@ export const DEPRECATED: "Deprecated";
2203
2208
  export const EXPERIMENTAL: "Experimental";
2204
2209
  }
2205
2210
 
2211
+ // @shell/config/version
2212
+
2213
+ declare module '@shell/config/version' {
2214
+ export function isRancherPrime(): boolean;
2215
+ export function getVersionData(): {
2216
+ Version: string;
2217
+ RancherPrime: string;
2218
+ GitCommit: string;
2219
+ };
2220
+ export function setVersionData(v: any): void;
2221
+ export function getKubeVersionData(): {};
2222
+ export function setKubeVersionData(v: any): void;
2223
+ export const CURRENT_RANCHER_VERSION: "2.10";
2224
+ }
2225
+
2206
2226
  // @shell/mixins/create-edit-view/impl
2207
2227
 
2208
2228
  declare module '@shell/mixins/create-edit-view/impl' {
@@ -2402,8 +2422,11 @@ export default class ClusterRepo {
2402
2422
  spec: {
2403
2423
  url: string;
2404
2424
  };
2425
+ get _isClusterRepoDisabled(): boolean;
2405
2426
  get _availableActions(): any;
2406
2427
  refresh(): Promise<void>;
2428
+ disableClusterRepo(): Promise<void>;
2429
+ enableClusterRepo(): Promise<void>;
2407
2430
  get isGit(): boolean;
2408
2431
  get isOciType(): any;
2409
2432
  get isRancherSource(): boolean;
@@ -2429,6 +2452,8 @@ export default class ClusterRepo {
2429
2452
  };
2430
2453
  })[];
2431
2454
  get stateObj(): any;
2455
+ get stateDisplay(): any;
2456
+ get stateBackground(): any;
2432
2457
  waitForOperation(operationId: any, timeout: any, interval?: number): any;
2433
2458
  }
2434
2459
  }
@@ -2816,6 +2841,7 @@ export default class Resource {
2816
2841
  get $dispatch(): any;
2817
2842
  get $state(): any;
2818
2843
  get $rootState(): any;
2844
+ get $plugin(): any;
2819
2845
  get customValidationRules(): any[];
2820
2846
  get _key(): any;
2821
2847
  get schema(): any;
@@ -3117,6 +3143,10 @@ export default class SteveModel extends HybridModel {
3117
3143
  set description(value: any);
3118
3144
  get description(): any;
3119
3145
  _description: any;
3146
+ /**
3147
+ * Get all model extensions for this model
3148
+ */
3149
+ get modelExtensions(): any;
3120
3150
  cleanForSave(data: any, forNew: any): any;
3121
3151
  }
3122
3152
  import HybridModel from './hybrid-class';
@@ -3153,6 +3183,31 @@ export namespace actions {
3153
3183
  }
3154
3184
  }
3155
3185
 
3186
+ // @shell/store/plugins
3187
+
3188
+ declare module '@shell/store/plugins' {
3189
+ export function simplify(key: any): any;
3190
+ export function configureCredential(name: any, opt: any): void;
3191
+ export function mapDriver(name: any, to: any): void;
3192
+ export const rke1Supports: string[];
3193
+ export const likelyFields: any[];
3194
+ export const iffyFields: any[];
3195
+ export const fullFields: any[];
3196
+ export const prefixFields: any[];
3197
+ export const suffixFields: any[];
3198
+ export function state(): {};
3199
+ export namespace getters {
3200
+ function credentialOptions(): (name: any) => any;
3201
+ function credentialDriverFor(): (name: any) => any;
3202
+ function credentialFieldForDriver(): (name: any) => any;
3203
+ function clusterDrivers(): any[];
3204
+ function schemaForDriver(state: any, getters: any, rootState: any, rootGetters: any): (name: any) => any;
3205
+ function fieldNamesForDriver(state: any, getters: any): (name: any) => Promise<string[]>;
3206
+ function fieldsForDriver(state: any, getters: any): (name: any) => Promise<{}>;
3207
+ function cloudProviderForDriver(): (name: any) => any;
3208
+ }
3209
+ }
3210
+
3156
3211
  // @shell/store/prefs
3157
3212
 
3158
3213
  declare module '@shell/store/prefs' {
@@ -3440,6 +3495,8 @@ export function filterHiddenLocalCluster(mgmtClusters: any, store: any): any;
3440
3495
  */
3441
3496
  export function abbreviateClusterName(input: string): string;
3442
3497
  export function labelForAddon(store: any, name: any, configuration?: boolean): any;
3498
+ export function filterOutDeprecatedPatchVersions(allVersions: any, currentVersion: any): any;
3499
+ export function getAllOptionsAfterCurrentVersion(store: any, versions: any, currentVersion: any, defaultVersion: any): any;
3443
3500
  }
3444
3501
 
3445
3502
  // @shell/utils/color
@@ -4502,6 +4559,10 @@ export function containerImages(spec: any, getters: any, errors: any): void;
4502
4559
 
4503
4560
  declare module '@shell/utils/validators/cron-schedule' {
4504
4561
  export function cronSchedule(schedule: string, getters: any, errors: any): void;
4562
+ export namespace cronScheduleRule {
4563
+ function validation(text: any): string;
4564
+ let message: string;
4565
+ }
4505
4566
  }
4506
4567
 
4507
4568
  // @shell/utils/validators/flow-output
package/utils/auth.js CHANGED
@@ -116,7 +116,11 @@ export const checkSchemasForFindAllHash = (types, store) => {
116
116
  const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema;
117
117
 
118
118
  if (validSchema) {
119
- hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type, opt: value.opt } );
119
+ const res = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type, opt: value.opt } );
120
+
121
+ if (!value.skipWait) {
122
+ hash[key] = res;
123
+ }
120
124
  }
121
125
  }
122
126
 
package/utils/cluster.js CHANGED
@@ -4,6 +4,8 @@ import { CAPI } from '@shell/config/labels-annotations';
4
4
  import { MANAGEMENT, VIRTUAL_HARVESTER_PROVIDER } from '@shell/config/types';
5
5
  import { SETTING } from '@shell/config/settings';
6
6
  import { PaginationFilterField, PaginationParamFilter } from '@shell/types/store/pagination.types';
7
+ import { compare, sortable } from '@shell/utils/version';
8
+ import { sortBy } from '@shell/utils/sort';
7
9
 
8
10
  /**
9
11
  * Combination of paginationFilterHiddenLocalCluster and paginationFilterOnlyKubernetesClusters
@@ -190,3 +192,107 @@ export function labelForAddon(store, name, configuration = true) {
190
192
 
191
193
  return store.getters['i18n/withFallback'](key, null, fallback);
192
194
  }
195
+
196
+ function getMostRecentPatchVersions(sortedVersions) {
197
+ // Get the most recent patch version for each Kubernetes minor version.
198
+ const versionMap = {};
199
+
200
+ sortedVersions.forEach((version) => {
201
+ const majorMinor = `${ semver.major(version.value) }.${ semver.minor(version.value) }`;
202
+
203
+ if (!versionMap[majorMinor]) {
204
+ // Because we start with a sorted list of versions, we know the
205
+ // highest patch version is first in the list, so we only keep the
206
+ // first of each minor version in the list.
207
+ versionMap[majorMinor] = version.value;
208
+ }
209
+ });
210
+
211
+ return versionMap;
212
+ }
213
+
214
+ export function filterOutDeprecatedPatchVersions(allVersions, currentVersion) {
215
+ // Get the most recent patch version for each Kubernetes minor version.
216
+ const mostRecentPatchVersions = getMostRecentPatchVersions(allVersions);
217
+
218
+ const filteredVersions = allVersions.filter((version) => {
219
+ // Always show pre-releases
220
+ if (semver.prerelease(version.value)) {
221
+ return true;
222
+ }
223
+
224
+ const majorMinor = `${ semver.major(version.value) }.${ semver.minor(version.value) }`;
225
+
226
+ // Always show current version, else show if we haven't shown anything for this major.minor version yet
227
+ if (version.value === currentVersion || mostRecentPatchVersions[majorMinor] === version.value) {
228
+ return true;
229
+ }
230
+
231
+ return false;
232
+ });
233
+
234
+ return filteredVersions;
235
+ }
236
+
237
+ export function getAllOptionsAfterCurrentVersion(store, versions, currentVersion, defaultVersion) {
238
+ const out = (versions || []).filter((obj) => !!obj.serverArgs).map((obj) => {
239
+ let disabled = false;
240
+ let experimental = false;
241
+ let isCurrentVersion = false;
242
+ let label = obj.id;
243
+
244
+ if (currentVersion) {
245
+ disabled = compare(obj.id, currentVersion) < 0;
246
+ isCurrentVersion = compare(obj.id, currentVersion) === 0;
247
+ }
248
+
249
+ if (defaultVersion) {
250
+ experimental = compare(defaultVersion, obj.id) < 0;
251
+ }
252
+
253
+ if (isCurrentVersion) {
254
+ label = `${ label } ${ store.getters['i18n/t']('cluster.kubernetesVersion.current') }`;
255
+ }
256
+
257
+ if (experimental) {
258
+ label = `${ label } ${ store.getters['i18n/t']('cluster.kubernetesVersion.experimental') }`;
259
+ }
260
+
261
+ return {
262
+ label,
263
+ value: obj.id,
264
+ sort: sortable(obj.id),
265
+ serverArgs: obj.serverArgs,
266
+ agentArgs: obj.agentArgs,
267
+ charts: obj.charts,
268
+ disabled,
269
+ };
270
+ });
271
+
272
+ if (currentVersion && !out.find((obj) => obj.value === currentVersion)) {
273
+ out.push({
274
+ label: `${ currentVersion } ${ store.getters['i18n/t']('cluster.kubernetesVersion.current') }`,
275
+ value: currentVersion,
276
+ sort: sortable(currentVersion),
277
+ });
278
+ }
279
+
280
+ const sorted = sortBy(out, 'sort:desc');
281
+
282
+ const mostRecentPatchVersions = getMostRecentPatchVersions(sorted);
283
+
284
+ const sortedWithDeprecatedLabel = sorted.map((optionData) => {
285
+ const majorMinor = `${ semver.major(optionData.value) }.${ semver.minor(optionData.value) }`;
286
+
287
+ if (mostRecentPatchVersions[majorMinor] === optionData.value) {
288
+ return optionData;
289
+ }
290
+
291
+ return {
292
+ ...optionData,
293
+ label: `${ optionData.label } ${ store.getters['i18n/t']('cluster.kubernetesVersion.deprecated') }`
294
+ };
295
+ });
296
+
297
+ return sortedWithDeprecatedLabel;
298
+ }
package/utils/fleet.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  BundleDeploymentResource,
3
3
  BundleResourceKey,
4
+ BundleDeployment,
4
5
  BundleDeploymentStatus,
5
6
  BundleStatus,
7
+ Condition,
6
8
  } from '@shell/types/resources/fleet';
7
9
  import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
8
- import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
10
+ import { FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
9
11
 
10
12
  interface Resource extends BundleDeploymentResource {
11
13
  state: string,
@@ -28,6 +30,14 @@ function resourceKey(r: BundleResourceKey): string {
28
30
  return `${ r.kind }/${ r.namespace }/${ r.name }`;
29
31
  }
30
32
 
33
+ function conditionIsTrue(conditions: Condition[] | undefined, type: string): boolean {
34
+ if (!conditions) {
35
+ return false;
36
+ }
37
+
38
+ return !!conditions.find((c) => c.type === type && c.status.toLowerCase() === 'true');
39
+ }
40
+
31
41
  class Fleet {
32
42
  resourceId(r: BundleResourceKey): string {
33
43
  return r.namespace ? `${ r.namespace }/${ r.name }` : r.name;
@@ -147,11 +157,33 @@ class Fleet {
147
157
  }
148
158
 
149
159
  clusterIdFromBundleDeploymentLabels(labels?: Labels): string {
150
- const clusterNamespace = labels?.[FLEET_ANNOTATIONS.CLUSTER_NAMESPACE];
151
- const clusterName = labels?.[FLEET_ANNOTATIONS.CLUSTER];
160
+ const clusterNamespace = labels?.[FLEET_LABELS.CLUSTER_NAMESPACE];
161
+ const clusterName = labels?.[FLEET_LABELS.CLUSTER];
152
162
 
153
163
  return `${ clusterNamespace }/${ clusterName }`;
154
164
  }
165
+
166
+ bundleIdFromBundleDeploymentLabels(labels?: Labels): string {
167
+ const bundleNamespace = labels?.[FLEET_LABELS.BUNDLE_NAMESPACE];
168
+ const bundleName = labels?.[FLEET_LABELS.BUNDLE_NAME];
169
+
170
+ return `${ bundleNamespace }/${ bundleName }`;
171
+ }
172
+
173
+ bundleDeploymentState(bd: BundleDeployment): string {
174
+ // Ported from https://github.com/rancher/fleet/blob/534dbfdd6f74caf97bccd4cf977e42c5009b2432/internal/cmd/controller/summary/summary.go#L89
175
+ if (bd.status?.appliedDeploymentId !== bd.spec.deploymentId) {
176
+ return conditionIsTrue(bd.status?.conditions, 'Deployed') ? STATES_ENUM.WAIT_APPLIED : STATES_ENUM.ERR_APPLIED;
177
+ } else if (!bd.status?.ready) {
178
+ return STATES_ENUM.NOT_READY;
179
+ } else if (bd.spec.deploymentId !== bd.spec.stagedDeploymentId) {
180
+ return STATES_ENUM.OUT_OF_SYNC;
181
+ } else if (!bd.status?.nonModified) {
182
+ return STATES_ENUM.MODIFIED;
183
+ } else {
184
+ return STATES_ENUM.READY;
185
+ }
186
+ }
155
187
  }
156
188
 
157
189
  const instance = new Fleet();