@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.
- package/assets/styles/base/_basic.scss +5 -7
- package/assets/styles/global/_button.scss +10 -0
- package/assets/styles/global/_tooltip.scss +2 -2
- package/assets/styles/themes/_dark.scss +14 -2
- package/assets/styles/themes/_light.scss +7 -2
- package/assets/styles/vendor/vue-select.scss +4 -0
- package/assets/translations/en-us.yaml +44 -5
- package/components/BannerGraphic.vue +0 -42
- package/components/ButtonMultiAction.vue +1 -1
- package/components/Carousel.vue +36 -29
- package/components/CommunityLinks.vue +6 -1
- package/components/GrowlManager.vue +9 -2
- package/components/LocaleSelector.vue +8 -1
- package/components/PaginatedResourceTable.vue +4 -7
- package/components/ProgressBarMulti.vue +14 -0
- package/components/Questions/Reference.vue +57 -28
- package/components/SelectIconGrid.vue +12 -1
- package/components/SideNav.vue +12 -38
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/index.vue +12 -1
- package/components/YamlEditor.vue +1 -0
- package/components/auth/Principal.vue +5 -3
- package/components/fleet/FleetClusters.vue +82 -1
- package/components/fleet/FleetRepos.vue +13 -30
- package/components/fleet/ForceDirectedTreeChart/index.vue +2 -2
- package/components/form/ChangePassword.vue +2 -0
- package/components/form/ColorInput.vue +24 -1
- package/components/form/FileSelector.vue +2 -0
- package/components/form/KeyValue.vue +230 -160
- package/components/form/LabeledSelect.vue +1 -1
- package/components/form/PlusMinus.vue +14 -2
- package/components/form/ResourceLabeledSelect.vue +13 -53
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +79 -36
- package/components/form/SecretSelector.vue +2 -2
- package/components/form/__tests__/KeyValue.test.ts +1 -1
- package/components/formatter/FleetClusterSummaryGraph.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +6 -7
- package/components/formatter/WorkloadHealthScale.vue +7 -0
- package/components/nav/Group.vue +30 -4
- package/components/nav/Header.vue +82 -114
- package/components/nav/HeaderPageActionMenu.vue +27 -131
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/Type.vue +15 -0
- package/config/home-links.js +21 -13
- package/config/labels-annotations.js +2 -0
- package/config/page-actions.js +1 -0
- package/config/pagination-table-headers.js +15 -1
- package/config/product/explorer.js +7 -17
- package/config/table-headers.js +6 -0
- package/config/version.js +5 -1
- package/core/plugin.ts +41 -1
- package/core/plugins.js +125 -72
- package/core/types-provisioning.ts +91 -2
- package/core/types.ts +55 -0
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +12 -3
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/fleet.cattle.io.cluster.vue +3 -3
- package/detail/namespace.vue +13 -19
- package/detail/networking.k8s.io.ingress.vue +13 -53
- package/detail/provisioning.cattle.io.cluster.vue +12 -1
- package/detail/workload/index.vue +3 -3
- package/dialog/AddCustomBadgeDialog.vue +5 -1
- package/edit/auth/ldap/__tests__/config.test.ts +18 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/auth/saml.vue +8 -6
- package/edit/fleet.cattle.io.gitrepo.vue +7 -1
- package/edit/logging-flow/index.vue +4 -19
- package/edit/networking.k8s.io.ingress/index.vue +18 -65
- package/edit/networking.k8s.io.networkpolicy/index.vue +4 -5
- package/edit/provisioning.cattle.io.cluster/index.vue +13 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -115
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue +14 -28
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +25 -12
- package/edit/service.vue +1 -2
- package/list/networking.k8s.io.ingress.vue +1 -1
- package/list/node.vue +15 -8
- package/list/persistentvolume.vue +12 -4
- package/list/service.vue +1 -1
- package/list/workload.vue +4 -0
- package/mixins/chart.js +4 -1
- package/models/catalog.cattle.io.app.js +3 -1
- package/models/catalog.cattle.io.clusterrepo.js +56 -7
- package/models/fleet.cattle.io.bundle.js +0 -11
- package/models/fleet.cattle.io.cluster.js +17 -1
- package/models/fleet.cattle.io.gitrepo.js +86 -50
- package/models/provisioning.cattle.io.cluster.js +47 -2
- package/models/service.js +1 -0
- package/models/workload.js +19 -1
- package/package.json +5 -4
- package/pages/c/_cluster/apps/charts/index.vue +4 -0
- package/pages/c/_cluster/explorer/ConfigBadge.vue +8 -7
- package/pages/c/_cluster/explorer/index.vue +13 -6
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +3 -3
- package/pages/c/_cluster/fleet/index.vue +75 -89
- package/pages/c/_cluster/settings/links.vue +2 -2
- package/pages/diagnostic.vue +17 -15
- package/pages/home.vue +32 -6
- package/plugins/clean-html.js +50 -0
- package/plugins/dashboard-store/resource-class.js +4 -0
- package/plugins/plugin.js +54 -49
- package/plugins/steve/mutations.js +1 -1
- package/plugins/steve/steve-class.js +8 -0
- package/plugins/steve/steve-pagination-utils.ts +3 -1
- package/rancher-components/Accordion/Accordion.vue +4 -4
- package/rancher-components/BadgeState/BadgeState.vue +7 -0
- package/rancher-components/Card/Card.vue +27 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +9 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +18 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +39 -2
- package/rancher-components/RcButton/RcButton.vue +90 -0
- package/rancher-components/RcButton/index.ts +2 -0
- package/rancher-components/RcButton/types.ts +17 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +111 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +127 -0
- package/rancher-components/RcDropdown/RcDropdownSeparator.vue +6 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +43 -0
- package/rancher-components/RcDropdown/index.ts +4 -0
- package/rancher-components/RcDropdown/types.ts +22 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +45 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +83 -0
- package/scripts/test-plugins-build.sh +2 -0
- package/scripts/typegen.sh +2 -0
- package/store/catalog.js +1 -1
- package/tsconfig.json +2 -1
- package/types/components/paginatedResourceTable.ts +25 -0
- package/types/components/resourceLabeledSelect.ts +48 -0
- package/types/resources/fleet.d.ts +17 -0
- package/types/shell/index.d.ts +61 -0
- package/utils/auth.js +5 -1
- package/utils/cluster.js +106 -0
- package/utils/fleet.ts +35 -3
- package/utils/ingress.ts +64 -0
- package/utils/uiplugins.ts +56 -44
- package/utils/validators/cron-schedule.js +7 -2
- package/utils/validators/formRules/__tests__/index.test.ts +53 -17
- package/utils/validators/formRules/index.ts +20 -5
- package/vue.config.js +1 -1
- 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
|
package/scripts/typegen.sh
CHANGED
|
@@ -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
|
@@ -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
|
+
}
|
package/types/shell/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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?.[
|
|
151
|
-
const clusterName = labels?.[
|
|
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();
|