@rancher/shell 3.0.12-rc.2 → 3.0.12-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/apis/impl/apis.ts +6 -0
- package/apis/index.ts +26 -0
- package/apis/intf/resources-api/cluster-api.ts +18 -0
- package/apis/intf/resources-api/mgmt-api.ts +15 -0
- package/apis/intf/resources-api/resource-base.ts +107 -0
- package/apis/intf/resources-api/resource-constants.ts +147 -0
- package/apis/intf/resources-api/resources-api.ts +143 -0
- package/apis/intf/resources.ts +49 -0
- package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
- package/apis/intf/shell-api/proxy.ts +216 -0
- package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
- package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
- package/apis/intf/shell.ts +12 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
- package/apis/resources/index.ts +22 -0
- package/apis/resources/resources-api-class.ts +187 -0
- package/apis/shell/__tests__/proxy.test.ts +369 -0
- package/apis/shell/index.ts +8 -1
- package/apis/shell/modal.ts +4 -1
- package/apis/shell/notifications.ts +9 -6
- package/apis/shell/proxy.ts +256 -0
- package/apis/shell/slide-in.ts +4 -1
- package/apis/vue-shim.d.ts +2 -1
- package/assets/data/aws-regions.json +4 -0
- package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/fonts/_fontstack.scss +132 -8
- package/assets/translations/en-us.yaml +22 -5
- package/chart/monitoring/index.vue +10 -1
- package/components/ActionDropdownShell.vue +2 -1
- package/components/CruResourceFooter.vue +9 -5
- package/components/ExplorerProjectsNamespaces.vue +1 -1
- package/components/InstallHelmCharts.vue +2 -2
- package/components/LandingPagePreference.vue +14 -5
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
- package/components/Resource/Detail/Metadata/index.vue +6 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
- package/components/Resource/Detail/SpacedRow.vue +3 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -11
- package/components/ResourceList/Masthead.vue +12 -8
- package/components/SelectIconGrid.vue +0 -10
- package/components/SingleClusterInfo.vue +1 -0
- package/components/SortableTable/__tests__/sorting.test.ts +126 -0
- package/components/SortableTable/index.vue +6 -9
- package/components/SortableTable/selection.js +23 -5
- package/components/SortableTable/sorting.js +6 -3
- package/components/Wizard.vue +14 -13
- package/components/fleet/FleetBundles.vue +100 -12
- package/components/fleet/FleetClusterTargets/index.vue +37 -15
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
- package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
- package/components/form/LabeledSelect.vue +20 -3
- package/components/form/NameNsDescription.vue +11 -0
- package/components/form/Security.vue +6 -2
- package/components/form/WorkloadPorts.vue +2 -7
- package/components/form/__tests__/Security.test.ts +76 -0
- package/components/formatter/Autoscaler.vue +4 -4
- package/components/formatter/ClusterKubeVersion.vue +27 -0
- package/components/formatter/ClusterLink.vue +1 -7
- package/components/formatter/ClusterProvider.vue +6 -10
- package/components/formatter/FleetSummaryGraph.vue +0 -3
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/PodsUsage.vue +2 -2
- package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
- package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
- package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
- package/components/nav/NamespaceFilter.vue +2 -2
- package/components/nav/TopLevelMenu.helper.ts +15 -3
- package/components/nav/TopLevelMenu.vue +16 -5
- package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
- package/components/templates/home.vue +18 -0
- package/components/templates/plain.vue +18 -0
- package/components/templates/standalone.vue +17 -0
- package/composables/useFormValidation.ts +93 -0
- package/composables/useVeeValidateField.test.ts +159 -0
- package/composables/useVeeValidateField.ts +67 -0
- package/config/pagination-table-headers.js +18 -1
- package/config/product/manager.js +82 -21
- package/config/router/routes.js +6 -0
- package/config/table-headers.js +20 -1
- package/config/types.js +2 -1
- package/core/__tests__/plugin-products.test.ts +904 -20
- package/core/plugin-products-base.ts +107 -7
- package/core/plugin-products.ts +4 -0
- package/core/plugin-types.ts +111 -1
- package/core/plugin.ts +15 -7
- package/core/productDebugger.js +9 -4
- package/core/types-provisioning.ts +43 -30
- package/core/types.ts +57 -20
- package/detail/__tests__/pod.test.ts +41 -0
- package/detail/harvesterhci.io.management.cluster.vue +6 -2
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +4 -10
- package/edit/auth/__tests__/azuread.test.ts +217 -34
- package/edit/auth/azuread.vue +122 -14
- package/edit/auth/oidc.vue +2 -2
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
- package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
- package/edit/networking.k8s.io.ingress/index.vue +75 -20
- package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
- package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
- package/edit/secret/__tests__/ssh.test.ts +5 -6
- package/edit/secret/basic.vue +31 -0
- package/edit/secret/index.vue +68 -17
- package/edit/secret/registry.vue +38 -0
- package/edit/secret/ssh.vue +29 -0
- package/edit/secret/tls.vue +30 -0
- package/edit/service.vue +4 -4
- package/edit/workload/Upgrading.vue +3 -3
- package/edit/workload/__tests__/Upgrading.test.ts +6 -9
- package/edit/workload/mixins/workload.js +2 -1
- package/list/fleet.cattle.io.bundle.vue +7 -104
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
- package/list/provisioning.cattle.io.cluster.vue +262 -180
- package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
- package/mixins/__tests__/chart.test.ts +112 -0
- package/mixins/brand.js +2 -1
- package/mixins/chart.js +12 -8
- package/mixins/resource-fetch-api-pagination.js +41 -5
- package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
- package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
- package/models/__tests__/management.cattle.io.node.ts +6 -5
- package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
- package/models/base-cluster.x-k8s.io.js +26 -0
- package/models/cluster.js +1 -1
- package/models/cluster.x-k8s.io.machine.js +4 -22
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
- package/models/cluster.x-k8s.io.machineset.js +2 -20
- package/models/compliance.cattle.io.clusterscan.js +130 -2
- package/models/ext.cattle.io.kubeconfig.ts +4 -7
- package/models/fleet-application.js +3 -1
- package/models/management.cattle.io.cluster.js +417 -40
- package/models/management.cattle.io.node.js +6 -4
- package/models/management.cattle.io.nodepool.js +1 -1
- package/models/networking.k8s.io.ingress.js +12 -4
- package/models/provisioning.cattle.io.cluster.js +47 -330
- package/models/rke.cattle.io.etcdsnapshot.js +1 -2
- package/package.json +11 -29
- package/pages/__tests__/readme.test.ts +49 -0
- package/pages/auth/setup.vue +2 -3
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
- package/pages/c/_cluster/apps/charts/chart.vue +60 -8
- package/pages/c/_cluster/apps/charts/install.vue +10 -7
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
- package/pages/c/_cluster/explorer/index.vue +5 -49
- package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
- package/pages/c/_cluster/istio/index.vue +21 -6
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +719 -2
- package/pages/c/_cluster/uiplugins/index.vue +203 -197
- package/pages/diagnostic.vue +13 -17
- package/pages/fail-whale.vue +18 -0
- package/pages/home.vue +77 -260
- package/pages/readme.vue +88 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
- package/plugins/dashboard-store/actions.js +40 -18
- package/plugins/dashboard-store/resource-class.js +5 -2
- package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
- package/plugins/steve/steve-pagination-utils.ts +11 -3
- package/plugins/steve/subscribe.js +35 -5
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
- package/rancher-components/RcButton/RcButton.test.ts +37 -1
- package/rancher-components/RcButton/RcButton.vue +38 -8
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
- package/store/__tests__/catalog.test.ts +115 -1
- package/store/__tests__/type-map.test.ts +556 -1
- package/store/action-menu.js +8 -3
- package/store/auth.js +1 -1
- package/store/aws.js +27 -16
- package/store/catalog.js +27 -3
- package/store/digitalocean.js +20 -38
- package/store/index.js +2 -0
- package/store/linode.js +25 -40
- package/store/pnap.js +1 -0
- package/store/type-map.js +111 -29
- package/tsconfig.paths.json +8 -8
- package/types/kube/kube-api.ts +14 -1
- package/types/rancher/steve.api.ts +12 -12
- package/types/resources/settings.d.ts +2 -1
- package/types/shell/index.d.ts +102 -2
- package/types/store/dashboard-store.types.ts +108 -11
- package/types/store/pagination.types.ts +6 -3
- package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
- package/utils/__tests__/async.test.ts +87 -0
- package/utils/__tests__/aws.test.ts +140 -0
- package/utils/__tests__/banners.test.ts +176 -0
- package/utils/__tests__/chart.test.ts +64 -1
- package/utils/__tests__/color.test.ts +226 -0
- package/utils/__tests__/duration.test.ts +140 -0
- package/utils/__tests__/fleet.test.ts +340 -0
- package/utils/__tests__/ingress.test.ts +553 -0
- package/utils/__tests__/kube.test.ts +68 -0
- package/utils/__tests__/namespace-filter.test.ts +109 -0
- package/utils/__tests__/pagination-utils.test.ts +361 -0
- package/utils/__tests__/parse-externalid.test.ts +137 -0
- package/utils/__tests__/perf-setting.utils.test.ts +98 -0
- package/utils/__tests__/poller-sequential.test.ts +177 -0
- package/utils/__tests__/poller.test.ts +170 -0
- package/utils/__tests__/promise.test.ts +346 -0
- package/utils/__tests__/settings.test.ts +140 -0
- package/utils/__tests__/sort-utils.test.ts +301 -0
- package/utils/__tests__/string-utils.test.ts +798 -0
- package/utils/__tests__/string.test.ts +23 -1
- package/utils/__tests__/style.test.ts +154 -0
- package/utils/__tests__/svg-filter.test.ts +184 -0
- package/utils/__tests__/units.test.ts +417 -0
- package/utils/__tests__/versions.test.ts +128 -0
- package/utils/__tests__/xccdf.test.ts +391 -0
- package/utils/chart.js +36 -0
- package/utils/fleet.ts +13 -3
- package/utils/gatekeeper/__tests__/util.test.ts +174 -0
- package/utils/gc/__tests__/gc-interval.test.ts +119 -0
- package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
- package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
- package/utils/gc/__tests__/gc.test.ts +487 -0
- package/utils/ingress.ts +9 -1
- package/utils/pagination-utils.ts +2 -1
- package/utils/string.js +25 -2
- package/utils/uiplugins.ts +5 -5
- package/utils/validators/__tests__/cluster-name.test.ts +110 -0
- package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
- package/utils/validators/__tests__/index.test.ts +481 -0
- package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
- package/utils/validators/__tests__/misc-validators.test.ts +246 -0
- package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
- package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
- package/utils/validators/__tests__/role-template.test.ts +149 -0
- package/utils/validators/__tests__/service.test.ts +283 -0
- package/utils/validators/__tests__/setting.test.js +32 -0
- package/utils/validators/formRules/__tests__/index.test.ts +50 -0
- package/utils/validators/formRules/index.ts +5 -5
- package/utils/validators/machine-pool.ts +1 -1
- package/utils/validators/setting.js +18 -3
- package/utils/xccdf.ts +418 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import MgmtCluster from '@shell/models/management.cattle.io.cluster';
|
|
2
|
+
import { filterHiddenLocalCluster, filterOnlyKubernetesClusters, paginationFilterClusters } from '@shell/utils/cluster';
|
|
3
|
+
import { VuexStore } from '@shell/types/store/vuex';
|
|
4
|
+
import { FilterArgs, PaginationArgs, PaginationFilterEquality, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
5
|
+
import { sameContents } from '@shell/utils/array';
|
|
6
|
+
import { PagTableFetchPageSecondaryResourcesOpts, PagTableFetchSecondaryResourcesOpts } from '@shell/types/components/paginatedResourceTable';
|
|
7
|
+
import { CAPI } from '@shell/config/types';
|
|
8
|
+
import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
|
|
9
|
+
|
|
10
|
+
interface CommonConfig {
|
|
11
|
+
$store: VuexStore
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Utils to support listing management.cattle.io.clusters
|
|
16
|
+
*/
|
|
17
|
+
class ManagementClusterUtils {
|
|
18
|
+
/**
|
|
19
|
+
* Filter out hidden clusters from list of all clusters
|
|
20
|
+
*/
|
|
21
|
+
filterRowsLocal(rows: MgmtCluster[], { $store }: CommonConfig): MgmtCluster[] {
|
|
22
|
+
return filterHiddenLocalCluster(filterOnlyKubernetesClusters(rows || [], $store), $store);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Filter out hidden clusters via api
|
|
27
|
+
*/
|
|
28
|
+
filterRowsApi(pagination: PaginationArgs, { $store }: CommonConfig): PaginationArgs {
|
|
29
|
+
if (!pagination.filters) {
|
|
30
|
+
pagination.filters = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const existingFilters = pagination.filters;
|
|
34
|
+
const requiredFilters = paginationFilterClusters($store, false);
|
|
35
|
+
|
|
36
|
+
for (let i = 0; i < requiredFilters.length; i++) {
|
|
37
|
+
let found = false;
|
|
38
|
+
const required = requiredFilters[i];
|
|
39
|
+
|
|
40
|
+
for (let j = 0; j < existingFilters.length; j++) {
|
|
41
|
+
const existing = existingFilters[j];
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
required.fields.length === existing.fields.length &&
|
|
45
|
+
sameContents(required.fields.map((e) => e.field), existing.fields.map((e) => e.field))
|
|
46
|
+
) {
|
|
47
|
+
Object.assign(existing, required);
|
|
48
|
+
found = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!found) {
|
|
54
|
+
pagination.filters.push(required);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return pagination;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Fetch resources used to support vai off world
|
|
63
|
+
*
|
|
64
|
+
* Of type PagTableFetchSecondaryResources
|
|
65
|
+
*/
|
|
66
|
+
fetchSecondaryResources(opts: PagTableFetchSecondaryResourcesOpts, { $store }: CommonConfig): Promise<any>[] {
|
|
67
|
+
if (opts.canPaginate) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const promises = [];
|
|
72
|
+
|
|
73
|
+
if ( $store.getters['management/canList'](CAPI.RANCHER_CLUSTER) ) {
|
|
74
|
+
promises.push($store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER }));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return promises;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Fetch resources used to support vai on and the current page
|
|
82
|
+
*/
|
|
83
|
+
async fetchPageSecondaryResources({
|
|
84
|
+
canPaginate, force, page, pagResult
|
|
85
|
+
}: PagTableFetchPageSecondaryResourcesOpts, { $store }: CommonConfig): Promise<Promise<any>[]> {
|
|
86
|
+
if (!canPaginate || !page?.length) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const promises = [];
|
|
91
|
+
|
|
92
|
+
if ( $store.getters['management/canList'](CAPI.RANCHER_CLUSTER) ) {
|
|
93
|
+
const opt: ActionFindPageArgs = {
|
|
94
|
+
force,
|
|
95
|
+
pagination: new FilterArgs({
|
|
96
|
+
filters: new PaginationParamFilter({
|
|
97
|
+
fields: [{
|
|
98
|
+
value: page.map((r: any) => r.provClusterId).join(','),
|
|
99
|
+
equality: PaginationFilterEquality.IN,
|
|
100
|
+
field: 'id',
|
|
101
|
+
}],
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Prov clusters
|
|
107
|
+
promises.push($store.dispatch(`management/findPage`, { type: CAPI.RANCHER_CLUSTER, opt }));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return promises;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
forgetSecondaryResources({ context }: { context?: string } = {}, { $store }: CommonConfig) {
|
|
114
|
+
const canList = $store.getters['management/canList'](CAPI.RANCHER_CLUSTER);
|
|
115
|
+
const canPaginate = $store.getters['management/paginationEnabled']({
|
|
116
|
+
id: CAPI.RANCHER_CLUSTER,
|
|
117
|
+
context
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (canList && canPaginate) {
|
|
121
|
+
$store.dispatch('management/forgetType', CAPI.RANCHER_CLUSTER);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const instance = new ManagementClusterUtils();
|
|
127
|
+
|
|
128
|
+
export default instance;
|
|
@@ -214,6 +214,72 @@ describe('chartMixin', () => {
|
|
|
214
214
|
id: 'custom-ns/custom-name'
|
|
215
215
|
});
|
|
216
216
|
});
|
|
217
|
+
|
|
218
|
+
it('should fall back to matchingInstalledApps when version namespace lookup fails', async() => {
|
|
219
|
+
const installedApp = {
|
|
220
|
+
id: 'other-ns/custom-name',
|
|
221
|
+
spec: { chart: { metadata: { version: '0.9.0' } } }
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const mockStore = {
|
|
225
|
+
dispatch: jest.fn((action, payload) => {
|
|
226
|
+
if (action === 'cluster/find') {
|
|
227
|
+
return Promise.reject(new Error('not found'));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return Promise.resolve();
|
|
231
|
+
}),
|
|
232
|
+
getters: {
|
|
233
|
+
currentCluster: () => {},
|
|
234
|
+
isRancher: () => true,
|
|
235
|
+
'catalog/repo': () => {
|
|
236
|
+
return () => 'repo';
|
|
237
|
+
},
|
|
238
|
+
'catalog/chart': () => {
|
|
239
|
+
return {
|
|
240
|
+
id: 'chart-id',
|
|
241
|
+
versions: [{ version: '1.0.0' }],
|
|
242
|
+
matchingInstalledApps: [installedApp]
|
|
243
|
+
};
|
|
244
|
+
},
|
|
245
|
+
'catalog/version': () => ({
|
|
246
|
+
version: '1.0.0',
|
|
247
|
+
annotations: {
|
|
248
|
+
[CATALOG_ANNOTATIONS.NAMESPACE]: 'custom-ns',
|
|
249
|
+
[CATALOG_ANNOTATIONS.RELEASE_NAME]: 'custom-name',
|
|
250
|
+
}
|
|
251
|
+
}),
|
|
252
|
+
'prefs/get': () => {},
|
|
253
|
+
'i18n/t': () => jest.fn()
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const DummyComponent = {
|
|
258
|
+
mixins: [ChartMixin],
|
|
259
|
+
template: '<div></div>',
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const wrapper = mount(
|
|
263
|
+
DummyComponent,
|
|
264
|
+
{
|
|
265
|
+
global: {
|
|
266
|
+
mocks: {
|
|
267
|
+
$store: mockStore,
|
|
268
|
+
$route: {
|
|
269
|
+
query: {
|
|
270
|
+
chart: 'chart_name',
|
|
271
|
+
versionName: '1.0.0'
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
await wrapper.vm.fetchChart();
|
|
279
|
+
|
|
280
|
+
expect(wrapper.vm.existing).toStrictEqual(installedApp);
|
|
281
|
+
expect(wrapper.vm.mode).toStrictEqual('edit');
|
|
282
|
+
});
|
|
217
283
|
});
|
|
218
284
|
|
|
219
285
|
describe('action', () => {
|
|
@@ -366,6 +432,52 @@ describe('chartMixin', () => {
|
|
|
366
432
|
});
|
|
367
433
|
});
|
|
368
434
|
|
|
435
|
+
describe('isChartTargeted', () => {
|
|
436
|
+
const DummyComponent = {
|
|
437
|
+
mixins: [ChartMixin],
|
|
438
|
+
template: '<div></div>',
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
const mockStore = {
|
|
442
|
+
dispatch: jest.fn(() => Promise.resolve()),
|
|
443
|
+
getters: { 'i18n/t': (key: string) => key }
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
it('should return truthy when version annotations have both namespace and release-name', () => {
|
|
447
|
+
const wrapper = mount(DummyComponent, {
|
|
448
|
+
data: () => ({
|
|
449
|
+
version: {
|
|
450
|
+
annotations: {
|
|
451
|
+
[CATALOG_ANNOTATIONS.NAMESPACE]: 'custom-ns',
|
|
452
|
+
[CATALOG_ANNOTATIONS.RELEASE_NAME]: 'custom-name',
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}),
|
|
456
|
+
global: { mocks: { $store: mockStore } }
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
expect(wrapper.vm.isChartTargeted).toBeTruthy();
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
it('should return falsy when version annotations are missing', () => {
|
|
463
|
+
const wrapper = mount(DummyComponent, {
|
|
464
|
+
data: () => ({ version: { annotations: {} } }),
|
|
465
|
+
global: { mocks: { $store: mockStore } }
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
expect(wrapper.vm.isChartTargeted).toBeFalsy();
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
it('should return falsy when version is null', () => {
|
|
472
|
+
const wrapper = mount(DummyComponent, {
|
|
473
|
+
data: () => ({ version: null }),
|
|
474
|
+
global: { mocks: { $store: mockStore } }
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
expect(wrapper.vm.isChartTargeted).toBeFalsy();
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
|
|
369
481
|
describe('mappedVersions', () => {
|
|
370
482
|
it('should return versions sorted by semver (descending)', () => {
|
|
371
483
|
const versions = [
|
package/mixins/brand.js
CHANGED
|
@@ -183,7 +183,8 @@ export default {
|
|
|
183
183
|
},
|
|
184
184
|
setBodyClass() {
|
|
185
185
|
const body = document.getElementsByTagName('body')[0];
|
|
186
|
-
const
|
|
186
|
+
const isStandalone = this.$route?.meta?.standalone;
|
|
187
|
+
const cssClass = isStandalone ? 'dashboard-body' : 'overflow-hidden dashboard-body';
|
|
187
188
|
let bodyClass = `theme-${ this.theme } ${ cssClass }`;
|
|
188
189
|
|
|
189
190
|
if ( this.brand ) {
|
package/mixins/chart.js
CHANGED
|
@@ -13,7 +13,7 @@ import { CAPI, CATALOG } from '@shell/config/types';
|
|
|
13
13
|
import { isPrerelease } from '@shell/utils/version';
|
|
14
14
|
import { compareChartVersions } from '@shell/utils/chart';
|
|
15
15
|
import difference from 'lodash/difference';
|
|
16
|
-
import {
|
|
16
|
+
import { APP_UPGRADE_STATUS, isRancherRepo, getPermittedOSs } from '@shell/store/catalog';
|
|
17
17
|
import { clone } from '@shell/utils/object';
|
|
18
18
|
import { merge } from 'lodash';
|
|
19
19
|
|
|
@@ -84,7 +84,8 @@ export default {
|
|
|
84
84
|
keywords: version.keywords
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
const
|
|
87
|
+
const isRancher = isRancherRepo(this.repo, this.chart);
|
|
88
|
+
const permittedSystems = getPermittedOSs(version?.annotations, isRancher);
|
|
88
89
|
|
|
89
90
|
if (permittedSystems.length > 0 && difference(OSs, permittedSystems).length > 0) {
|
|
90
91
|
nue.disabled = true;
|
|
@@ -271,7 +272,7 @@ export default {
|
|
|
271
272
|
},
|
|
272
273
|
|
|
273
274
|
isChartTargeted() {
|
|
274
|
-
return this.
|
|
275
|
+
return this.version?.annotations?.[CATALOG_ANNOTATIONS.NAMESPACE] && this.version?.annotations?.[CATALOG_ANNOTATIONS.RELEASE_NAME];
|
|
275
276
|
},
|
|
276
277
|
|
|
277
278
|
hasQuestions() {
|
|
@@ -386,8 +387,8 @@ export default {
|
|
|
386
387
|
// Use those values to check for a catalog app resource.
|
|
387
388
|
// If found, set the form to edit mode. If not, set the
|
|
388
389
|
// form to create mode.
|
|
389
|
-
// This is a hard blocker - installing a new instance is NOT allowed.
|
|
390
390
|
|
|
391
|
+
// This is a hard blocker - installing a new instance is NOT allowed.
|
|
391
392
|
this.canInstallNew = false;
|
|
392
393
|
|
|
393
394
|
try {
|
|
@@ -410,11 +411,10 @@ export default {
|
|
|
410
411
|
if ( targetNamespace && targetName ) {
|
|
411
412
|
// If the app name and namespace values are not provided in the
|
|
412
413
|
// query, fall back on target values defined in the Helm chart itself.
|
|
413
|
-
|
|
414
414
|
// Ask to install a special chart with fixed namespace/name
|
|
415
415
|
// or edit it if there's an existing install.
|
|
416
|
-
// This is a hard blocker - installing a new instance is NOT allowed.
|
|
417
416
|
|
|
417
|
+
// This is a hard blocker - installing a new instance is NOT allowed.
|
|
418
418
|
this.canInstallNew = false;
|
|
419
419
|
|
|
420
420
|
try {
|
|
@@ -424,8 +424,12 @@ export default {
|
|
|
424
424
|
});
|
|
425
425
|
this.mode = _EDIT;
|
|
426
426
|
} catch (e) {
|
|
427
|
-
|
|
428
|
-
|
|
427
|
+
// Version targets a different namespace than where the app is installed.
|
|
428
|
+
// Fall back to matching installed apps (e.g. chart detail page).
|
|
429
|
+
const matching = this.chart?.matchingInstalledApps || [];
|
|
430
|
+
|
|
431
|
+
this.existing = matching[0] || null;
|
|
432
|
+
this.mode = this.existing ? _EDIT : _CREATE;
|
|
429
433
|
}
|
|
430
434
|
} else {
|
|
431
435
|
// Regular chart (not targeted) - check if there are installed instances.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NAMESPACE_FILTER_NAMESPACED_YES, NAMESPACE_FILTER_NAMESPACED_NO, NAMESPACE_FILTER_ALL } from '@shell/utils/namespace-filter';
|
|
2
|
-
import { NAMESPACE } from '@shell/config/types';
|
|
2
|
+
import { MANAGEMENT, NAMESPACE } from '@shell/config/types';
|
|
3
3
|
import { ALL_NAMESPACES } from '@shell/store/prefs';
|
|
4
4
|
import { mapGetters } from 'vuex';
|
|
5
5
|
import { ResourceListComponentName } from '../components/ResourceList/resource-list.config';
|
|
@@ -248,7 +248,7 @@ export default {
|
|
|
248
248
|
namespaceFilters: {
|
|
249
249
|
immediate: true,
|
|
250
250
|
async handler(neu, old) {
|
|
251
|
-
if (!this.canPaginate || !this.isNamespaced) {
|
|
251
|
+
if (!this.canPaginate || !this.isNamespaced || !this.currentProduct?.showNamespaceFilter) {
|
|
252
252
|
return;
|
|
253
253
|
}
|
|
254
254
|
|
|
@@ -283,7 +283,7 @@ export default {
|
|
|
283
283
|
allNamespaces: this.$store.getters[`${ this.currentProduct?.inStore }/all`](NAMESPACE),
|
|
284
284
|
selection: neu,
|
|
285
285
|
isAllNamespaces: this.isAllNamespaces,
|
|
286
|
-
isLocalCluster: this.$store.getters['currentCluster']
|
|
286
|
+
isLocalCluster: this.$store.getters['currentCluster']?.isLocal,
|
|
287
287
|
showReservedRancherNamespaces: this.showDynamicRancherNamespaces,
|
|
288
288
|
productHidesSystemNamespaces: this.productHidesSystemNamespaces,
|
|
289
289
|
});
|
|
@@ -354,15 +354,51 @@ export default {
|
|
|
354
354
|
|
|
355
355
|
async beforeUnmount() {
|
|
356
356
|
if (this.havePaginated) {
|
|
357
|
+
const store = this.overrideInStore || this.inStore;
|
|
357
358
|
// of type @STEVE_WATCH_PARAMS
|
|
358
359
|
const watchArgs = {
|
|
359
360
|
type: this.resource,
|
|
360
361
|
mode: STEVE_WATCH_MODE.RESOURCE_CHANGES,
|
|
361
362
|
};
|
|
362
363
|
|
|
363
|
-
|
|
364
|
-
|
|
364
|
+
// Ensure that a resource remains in the store... and it's the same reference as before
|
|
365
|
+
// We'll do this for the mgmt cluster if there's a currentCluster set, otherwise we become unstuck
|
|
366
|
+
// (on nav we ensure currentCluster exists, but beforeUnmount fires afterwards, removing the cluster from pages that are using it)
|
|
367
|
+
const retainResource = this.resource === MANAGEMENT.CLUSTER && this.currentCluster ? this.currentCluster : null;
|
|
368
|
+
|
|
369
|
+
// Forget (unwatch, clear from store) the list's resource
|
|
370
|
+
await this.$store.dispatch(`${ store }/forgetType`, {
|
|
371
|
+
type: this.resource,
|
|
372
|
+
compareWatches: (watchParams) => {
|
|
373
|
+
return watchParams.type === watchArgs.type && watchParams.mode === watchArgs.mode;
|
|
374
|
+
},
|
|
375
|
+
unwatch: true,
|
|
376
|
+
forget: !retainResource
|
|
365
377
|
});
|
|
378
|
+
|
|
379
|
+
if (!!retainResource) {
|
|
380
|
+
// The end state should be just like we've dispatched `${store}/find`
|
|
381
|
+
|
|
382
|
+
try {
|
|
383
|
+
// Clone to ensure we can load each property of A into B without worrying about them being the same reference
|
|
384
|
+
const clone = await this.$store.dispatch(`${ store }/clone`, { resource: retainResource });
|
|
385
|
+
|
|
386
|
+
// Load the resource. It's already in the store but this makes sure any legacy state (like havePage) is reset
|
|
387
|
+
await this.$store.dispatch(`${ store }/load`, {
|
|
388
|
+
data: clone,
|
|
389
|
+
existing: retainResource,
|
|
390
|
+
invalidatePageCache: true,
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Watch the resource.
|
|
394
|
+
await this.$store.dispatch(`${ store }/watch`, {
|
|
395
|
+
type: this.resource,
|
|
396
|
+
id: retainResource.id,
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
console.error('Error occurred whilst trying to retain the management cluster in cache and correctly watched', error); // eslint-disable-line no-console
|
|
400
|
+
}
|
|
401
|
+
}
|
|
366
402
|
}
|
|
367
403
|
}
|
|
368
404
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Kubeconfig from '@shell/models/ext.cattle.io.kubeconfig';
|
|
2
|
-
import {
|
|
2
|
+
import { MANAGEMENT } from '@shell/config/types';
|
|
3
3
|
|
|
4
4
|
// SteveModel is JS, so we need to type the constructor
|
|
5
5
|
const KubeconfigModel = Kubeconfig as unknown as new (data: object) => Kubeconfig;
|
|
@@ -19,8 +19,9 @@ describe('class Kubeconfig', () => {
|
|
|
19
19
|
// Mock $rootGetters before any getters are accessed
|
|
20
20
|
// Cast to any since $rootGetters is inherited from JS SteveModel
|
|
21
21
|
jest.spyOn(kubeconfig as any, '$rootGetters', 'get').mockReturnValue({
|
|
22
|
-
'i18n/t':
|
|
23
|
-
'management/all':
|
|
22
|
+
'i18n/t': mockT,
|
|
23
|
+
'management/all': () => [],
|
|
24
|
+
'management/byId': () => null,
|
|
24
25
|
...rootGetters
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -70,11 +71,12 @@ describe('class Kubeconfig', () => {
|
|
|
70
71
|
});
|
|
71
72
|
|
|
72
73
|
describe('referencedClusters', () => {
|
|
73
|
-
const mockProvCluster = {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
const mockProvCluster = { detailLocation: { name: 'c-cluster-product-resource-id', params: { cluster: 'my-cluster' } } };
|
|
75
|
+
|
|
76
|
+
const mockMgmtClusterWithProv = {
|
|
77
|
+
id: 'c-m-abc123',
|
|
78
|
+
nameDisplay: 'my-cluster',
|
|
79
|
+
provCluster: mockProvCluster
|
|
78
80
|
};
|
|
79
81
|
|
|
80
82
|
const mockMgmtCluster = {
|
|
@@ -99,12 +101,12 @@ describe('class Kubeconfig', () => {
|
|
|
99
101
|
spec: { clusters: ['c-m-abc123'] }
|
|
100
102
|
},
|
|
101
103
|
{
|
|
102
|
-
'management/
|
|
103
|
-
if (type ===
|
|
104
|
-
return
|
|
104
|
+
'management/byId': (type: string, id: string) => {
|
|
105
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-abc123') {
|
|
106
|
+
return mockMgmtClusterWithProv;
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
return
|
|
109
|
+
return null;
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
);
|
|
@@ -124,12 +126,12 @@ describe('class Kubeconfig', () => {
|
|
|
124
126
|
spec: { clusters: ['c-m-def456'] }
|
|
125
127
|
},
|
|
126
128
|
{
|
|
127
|
-
'management/
|
|
128
|
-
if (type === MANAGEMENT.CLUSTER) {
|
|
129
|
-
return
|
|
129
|
+
'management/byId': (type: string, id: string) => {
|
|
130
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-def456') {
|
|
131
|
+
return mockMgmtCluster;
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
return
|
|
134
|
+
return null;
|
|
133
135
|
}
|
|
134
136
|
}
|
|
135
137
|
);
|
|
@@ -157,11 +159,12 @@ describe('class Kubeconfig', () => {
|
|
|
157
159
|
expect(mockT).toHaveBeenCalledWith('"ext.cattle.io.kubeconfig".deleted', { name: 'c-m-deleted' });
|
|
158
160
|
});
|
|
159
161
|
|
|
160
|
-
it('should prefer provisioning cluster over management cluster', () => {
|
|
161
|
-
const
|
|
162
|
+
it('should prefer provisioning cluster over management cluster for location', () => {
|
|
163
|
+
const mgmtClusterBothLocs = {
|
|
162
164
|
id: 'c-m-abc123',
|
|
163
|
-
nameDisplay: '
|
|
164
|
-
detailLocation: { name: 'mgmt-location' }
|
|
165
|
+
nameDisplay: 'my-cluster',
|
|
166
|
+
detailLocation: { name: 'mgmt-location' },
|
|
167
|
+
provCluster: { detailLocation: { name: 'prov-location' } }
|
|
165
168
|
};
|
|
166
169
|
|
|
167
170
|
const kubeconfig = createKubeconfig(
|
|
@@ -170,15 +173,12 @@ describe('class Kubeconfig', () => {
|
|
|
170
173
|
spec: { clusters: ['c-m-abc123'] }
|
|
171
174
|
},
|
|
172
175
|
{
|
|
173
|
-
'management/
|
|
174
|
-
if (type ===
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
if (type === MANAGEMENT.CLUSTER) {
|
|
178
|
-
return [mgmtClusterSameId];
|
|
176
|
+
'management/byId': (type: string, id: string) => {
|
|
177
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-abc123') {
|
|
178
|
+
return mgmtClusterBothLocs;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
return
|
|
181
|
+
return null;
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
);
|
|
@@ -186,7 +186,7 @@ describe('class Kubeconfig', () => {
|
|
|
186
186
|
expect(kubeconfig.referencedClusters).toStrictEqual([
|
|
187
187
|
{
|
|
188
188
|
label: 'my-cluster',
|
|
189
|
-
location:
|
|
189
|
+
location: { name: 'prov-location' }
|
|
190
190
|
}
|
|
191
191
|
]);
|
|
192
192
|
});
|
|
@@ -195,7 +195,7 @@ describe('class Kubeconfig', () => {
|
|
|
195
195
|
describe('sortedReferencedClusters', () => {
|
|
196
196
|
it('should sort existing clusters before deleted clusters', () => {
|
|
197
197
|
const existingCluster = {
|
|
198
|
-
|
|
198
|
+
id: 'c-m-exists',
|
|
199
199
|
nameDisplay: 'existing-cluster',
|
|
200
200
|
detailLocation: { name: 'location' }
|
|
201
201
|
};
|
|
@@ -206,12 +206,12 @@ describe('class Kubeconfig', () => {
|
|
|
206
206
|
spec: { clusters: ['deleted-1', 'c-m-exists', 'deleted-2'] }
|
|
207
207
|
},
|
|
208
208
|
{
|
|
209
|
-
'management/
|
|
210
|
-
if (type ===
|
|
211
|
-
return
|
|
209
|
+
'management/byId': (type: string, id: string) => {
|
|
210
|
+
if (type === MANAGEMENT.CLUSTER && id === 'c-m-exists') {
|
|
211
|
+
return existingCluster;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
return
|
|
214
|
+
return null;
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
);
|
|
@@ -225,17 +225,17 @@ describe('class Kubeconfig', () => {
|
|
|
225
225
|
});
|
|
226
226
|
|
|
227
227
|
it('should sort existing clusters alphabetically', () => {
|
|
228
|
-
const clusters =
|
|
229
|
-
{
|
|
230
|
-
|
|
228
|
+
const clusters: Record<string, any> = {
|
|
229
|
+
'c-m-zebra': {
|
|
230
|
+
id: 'c-m-zebra', nameDisplay: 'zebra', detailLocation: { name: 'z' }
|
|
231
231
|
},
|
|
232
|
-
{
|
|
233
|
-
|
|
232
|
+
'c-m-alpha': {
|
|
233
|
+
id: 'c-m-alpha', nameDisplay: 'alpha', detailLocation: { name: 'a' }
|
|
234
234
|
},
|
|
235
|
-
{
|
|
236
|
-
|
|
235
|
+
'c-m-beta': {
|
|
236
|
+
id: 'c-m-beta', nameDisplay: 'beta', detailLocation: { name: 'b' }
|
|
237
237
|
}
|
|
238
|
-
|
|
238
|
+
};
|
|
239
239
|
|
|
240
240
|
const kubeconfig = createKubeconfig(
|
|
241
241
|
{
|
|
@@ -243,12 +243,12 @@ describe('class Kubeconfig', () => {
|
|
|
243
243
|
spec: { clusters: ['c-m-zebra', 'c-m-alpha', 'c-m-beta'] }
|
|
244
244
|
},
|
|
245
245
|
{
|
|
246
|
-
'management/
|
|
247
|
-
if (type ===
|
|
248
|
-
return clusters;
|
|
246
|
+
'management/byId': (type: string, id: string) => {
|
|
247
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
248
|
+
return clusters[id] || null;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
return
|
|
251
|
+
return null;
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
);
|
|
@@ -259,17 +259,17 @@ describe('class Kubeconfig', () => {
|
|
|
259
259
|
});
|
|
260
260
|
|
|
261
261
|
it('should sort numerically when names contain numbers', () => {
|
|
262
|
-
const clusters =
|
|
263
|
-
{
|
|
264
|
-
|
|
262
|
+
const clusters: Record<string, any> = {
|
|
263
|
+
'c-m-2': {
|
|
264
|
+
id: 'c-m-2', nameDisplay: 'cluster2', detailLocation: { name: 'c2' }
|
|
265
265
|
},
|
|
266
|
-
{
|
|
267
|
-
|
|
266
|
+
'c-m-10': {
|
|
267
|
+
id: 'c-m-10', nameDisplay: 'cluster10', detailLocation: { name: 'c10' }
|
|
268
268
|
},
|
|
269
|
-
{
|
|
270
|
-
|
|
269
|
+
'c-m-1': {
|
|
270
|
+
id: 'c-m-1', nameDisplay: 'cluster1', detailLocation: { name: 'c1' }
|
|
271
271
|
}
|
|
272
|
-
|
|
272
|
+
};
|
|
273
273
|
|
|
274
274
|
const kubeconfig = createKubeconfig(
|
|
275
275
|
{
|
|
@@ -277,12 +277,12 @@ describe('class Kubeconfig', () => {
|
|
|
277
277
|
spec: { clusters: ['c-m-2', 'c-m-10', 'c-m-1'] }
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
|
-
'management/
|
|
281
|
-
if (type ===
|
|
282
|
-
return clusters;
|
|
280
|
+
'management/byId': (type: string, id: string) => {
|
|
281
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
282
|
+
return clusters[id] || null;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
return
|
|
285
|
+
return null;
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
);
|
|
@@ -295,14 +295,14 @@ describe('class Kubeconfig', () => {
|
|
|
295
295
|
|
|
296
296
|
describe('referencedClustersSortable', () => {
|
|
297
297
|
it('should return comma-separated lowercase labels', () => {
|
|
298
|
-
const clusters =
|
|
299
|
-
{
|
|
300
|
-
|
|
298
|
+
const clusters: Record<string, any> = {
|
|
299
|
+
'c-m-1': {
|
|
300
|
+
id: 'c-m-1', nameDisplay: 'Alpha', detailLocation: { name: 'a' }
|
|
301
301
|
},
|
|
302
|
-
{
|
|
303
|
-
|
|
302
|
+
'c-m-2': {
|
|
303
|
+
id: 'c-m-2', nameDisplay: 'Beta', detailLocation: { name: 'b' }
|
|
304
304
|
}
|
|
305
|
-
|
|
305
|
+
};
|
|
306
306
|
|
|
307
307
|
const kubeconfig = createKubeconfig(
|
|
308
308
|
{
|
|
@@ -310,12 +310,12 @@ describe('class Kubeconfig', () => {
|
|
|
310
310
|
spec: { clusters: ['c-m-1', 'c-m-2'] }
|
|
311
311
|
},
|
|
312
312
|
{
|
|
313
|
-
'management/
|
|
314
|
-
if (type ===
|
|
315
|
-
return clusters;
|
|
313
|
+
'management/byId': (type: string, id: string) => {
|
|
314
|
+
if (type === MANAGEMENT.CLUSTER) {
|
|
315
|
+
return clusters[id] || null;
|
|
316
316
|
}
|
|
317
317
|
|
|
318
|
-
return
|
|
318
|
+
return null;
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
);
|
|
@@ -7,7 +7,7 @@ jest.mock('@shell/utils/clipboard', () => {
|
|
|
7
7
|
describe('class MgmtCluster', () => {
|
|
8
8
|
describe('provisioner', () => {
|
|
9
9
|
const testCases = [
|
|
10
|
-
[{ provider: '
|
|
10
|
+
[{ provider: 'rke2', driver: 'imported' }, 'rke2'],
|
|
11
11
|
[{ provider: 'k3s', driver: 'K3S' }, 'K3S'],
|
|
12
12
|
[{ provider: 'aks', driver: 'AKS' }, 'AKS'],
|
|
13
13
|
[{}, 'imported'],
|