@rancher/shell 3.0.12-rc.3 → 3.0.12-rc.4
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/global/_layout.scss +4 -0
- package/assets/translations/en-us.yaml +144 -41
- package/assets/translations/zh-hans.yaml +1 -7
- package/chart/monitoring/ClusterSelector.vue +0 -21
- package/chart/monitoring/prometheus/index.vue +6 -3
- package/components/CruResource.vue +161 -14
- package/components/ExplorerMembers.vue +8 -4
- package/components/ExplorerProjectsNamespaces.vue +10 -6
- package/components/GrowlManager.vue +4 -0
- package/components/MgmtNodeList.vue +184 -0
- package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
- package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
- package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
- package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +2 -0
- package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
- package/components/ResourceDetail/index.vue +1 -1
- package/components/ResourceList/Masthead.vue +7 -1
- package/components/ResourceList/index.vue +82 -1
- package/components/RichTranslation.vue +5 -2
- package/components/Setting.vue +1 -0
- package/components/SubtleLink.vue +31 -6
- package/components/Tabbed/Tab.vue +29 -3
- package/components/Tabbed/index.vue +25 -3
- package/components/TableOfContents/TableOfContents.vue +109 -0
- package/components/TableOfContents/composables.ts +258 -0
- package/components/Window/ContainerShell.vue +21 -11
- package/components/Window/__tests__/ContainerShell.test.ts +107 -37
- package/components/Wizard.vue +9 -4
- package/components/fleet/AppCoChartGrid.vue +401 -0
- package/components/fleet/AppCoEmptyState.vue +127 -0
- package/components/fleet/AppCoPageHeader.vue +119 -0
- package/components/fleet/AppCoVersionSelect.vue +70 -0
- package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
- package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
- package/components/fleet/FleetClusterTargets/index.vue +189 -146
- package/components/fleet/FleetIntro.vue +7 -3
- package/components/fleet/FleetNoWorkspaces.vue +7 -3
- package/components/fleet/FleetSecretSelector.vue +5 -3
- package/components/fleet/FleetValuesFrom.vue +8 -2
- package/components/fleet/GitRepoTargetTab.vue +0 -2
- package/components/fleet/HelmOpAdvancedTab.vue +19 -53
- package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
- package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
- package/components/fleet/HelmOpResourcesSection.vue +82 -0
- package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
- package/components/fleet/HelmOpTargetTab.vue +64 -60
- package/components/fleet/HelmOpValuesTab.vue +129 -105
- package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
- package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
- package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +253 -0
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
- package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
- package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
- package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
- package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
- package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
- package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
- package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
- package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
- package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
- package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
- package/components/fleet/dashboard/Empty.vue +8 -4
- package/components/fleet/dashboard/ResourceCard.vue +28 -0
- package/components/fleet/dashboard/ResourceDetails.vue +28 -0
- package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
- package/components/form/ArrayList.vue +61 -4
- package/components/form/KeyValue.vue +23 -2
- package/components/form/LabeledSelect.vue +39 -1
- package/components/form/Labels.vue +22 -3
- package/components/form/NameNsDescription.vue +13 -5
- package/components/form/ResourceTabs/index.vue +1 -0
- package/components/form/__tests__/NameNsDescription.test.ts +75 -0
- package/components/formatter/InternalExternalIP.vue +10 -4
- package/components/formatter/ServiceTargets.vue +26 -7
- package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
- package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
- package/components/nav/Header.vue +4 -0
- package/components/nav/TopLevelMenu.vue +7 -2
- package/components/nav/__tests__/Header.test.ts +15 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +120 -2
- package/components/templates/default.vue +9 -4
- package/components/templates/home.vue +9 -4
- package/components/templates/plain.vue +9 -4
- package/composables/useHelmOpResources.test.ts +56 -0
- package/composables/useHelmOpResources.ts +32 -0
- package/composables/useStateColor.test.ts +325 -0
- package/composables/useStateColor.ts +128 -0
- package/config/home-links.js +1 -1
- package/config/labels-annotations.js +1 -0
- package/config/product/explorer.js +17 -4
- package/config/product/manager.js +2 -0
- package/config/router/index.js +16 -0
- package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
- package/config/router/navigation-guards/authentication.js +10 -4
- package/config/router/routes.js +20 -6
- package/config/settings.ts +0 -2
- package/config/table-headers.js +3 -4
- package/config/types.js +9 -0
- package/core/plugin-products-base.ts +3 -3
- package/core/plugin-types.ts +83 -30
- package/core/plugin.ts +3 -0
- package/core/types-provisioning.ts +34 -1
- package/core/types.ts +15 -2
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
- package/detail/__tests__/workload.test.ts +3 -152
- package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +30 -4
- package/detail/workload/index.vue +12 -55
- package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
- package/edit/auth/__tests__/azuread.test.ts +34 -9
- package/edit/auth/__tests__/github.test.ts +234 -0
- package/edit/auth/__tests__/oidc.test.ts +26 -6
- package/edit/auth/__tests__/saml.test.ts +196 -0
- package/edit/auth/azuread.vue +128 -95
- package/edit/auth/github.vue +72 -13
- package/edit/auth/ldap/__tests__/index.test.ts +206 -0
- package/edit/auth/ldap/config.vue +8 -0
- package/edit/auth/ldap/index.vue +75 -1
- package/edit/auth/oidc.vue +119 -73
- package/edit/auth/saml.vue +76 -12
- package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
- package/edit/fleet.cattle.io.helmop.vue +491 -136
- package/edit/management.cattle.io.user.vue +5 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +84 -10
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
- package/list/group.principal.vue +5 -4
- package/list/harvesterhci.io.management.cluster.vue +8 -9
- package/list/management.cattle.io.user.vue +12 -9
- package/list/provisioning.cattle.io.cluster.vue +16 -10
- package/mixins/__tests__/auth-config.test.ts +90 -0
- package/mixins/__tests__/chart.test.ts +94 -0
- package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
- package/mixins/auth-config.js +7 -0
- package/mixins/chart.js +11 -2
- package/mixins/child-hook.js +12 -6
- package/mixins/create-edit-view/impl.js +5 -3
- package/mixins/resource-fetch-api-pagination.js +21 -1
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
- package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
- package/models/__tests__/fleet-application.test.ts +175 -0
- package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
- package/models/__tests__/management.cattle.io.node.ts +22 -0
- package/models/__tests__/namespace.test.ts +36 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +49 -0
- package/models/__tests__/workload.test.ts +401 -26
- package/models/catalog.cattle.io.clusterrepo.js +28 -4
- package/models/compliance.cattle.io.clusterscan.js +39 -4
- package/models/fleet-application.js +4 -0
- package/models/fleet.cattle.io.helmop.js +20 -1
- package/models/management.cattle.io.cluster.js +18 -2
- package/models/management.cattle.io.node.js +44 -3
- package/models/namespace.js +1 -1
- package/models/pod.js +33 -1
- package/models/provisioning.cattle.io.cluster.js +5 -5
- package/models/workload.js +108 -13
- package/models/workload.service.js +5 -0
- package/package.json +14 -13
- package/pages/about.vue +5 -6
- package/pages/auth/login.vue +0 -35
- package/pages/auth/setup.vue +11 -0
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
- package/pages/c/_cluster/apps/charts/chart.vue +2 -1
- package/pages/c/_cluster/apps/charts/index.vue +48 -10
- package/pages/c/_cluster/apps/charts/install.vue +122 -116
- package/pages/c/_cluster/auth/roles/index.vue +5 -4
- package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
- package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
- package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
- package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
- package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
- package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
- package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
- package/pages/c/_cluster/fleet/application/create.vue +187 -136
- package/pages/c/_cluster/fleet/application/index.vue +5 -3
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
- package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
- package/pages/c/_cluster/fleet/index.vue +2 -2
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +96 -0
- package/pages/c/_cluster/uiplugins/index.vue +15 -0
- package/pages/fail-whale.vue +16 -11
- package/pages/home.vue +16 -46
- package/plugins/clean-html.d.ts +9 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +93 -0
- package/plugins/dashboard-store/resource-class.js +62 -7
- package/plugins/steve/__tests__/actions.test.ts +212 -0
- package/plugins/steve/actions.js +96 -0
- package/plugins/steve/steve-pagination-utils.ts +1 -1
- package/rancher-components/Accordion/Accordion.vue +53 -9
- package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
- package/rancher-components/Form/Radio/RadioButton.vue +17 -1
- package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
- package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
- package/rancher-components/RcButton/RcButton.test.ts +103 -0
- package/rancher-components/RcButton/RcButton.vue +94 -15
- package/rancher-components/RcButton/types.ts +3 -0
- package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
- package/rancher-components/RcSection/RcSection.vue +28 -3
- package/scripts/extension/helm/package/Dockerfile +1 -1
- package/scripts/test-plugins-build.sh +2 -1
- package/store/__tests__/notifications.test.ts +434 -0
- package/store/catalog.js +57 -0
- package/store/plugins.js +7 -4
- package/types/components/buttonGroup.ts +5 -0
- package/types/shell/index.d.ts +104 -70
- package/utils/__tests__/auth.test.ts +273 -0
- package/utils/__tests__/computed.test.ts +193 -0
- package/utils/__tests__/cspAdaptor.test.ts +163 -0
- package/utils/__tests__/dom.test.ts +81 -0
- package/utils/__tests__/duration.test.ts +37 -1
- package/utils/__tests__/dynamic-importer.test.ts +102 -0
- package/utils/__tests__/fleet-appco.test.ts +312 -0
- package/utils/__tests__/monitoring.test.ts +130 -0
- package/utils/__tests__/object.test.ts +22 -0
- package/utils/__tests__/platform.test.ts +91 -0
- package/utils/__tests__/position.test.ts +237 -0
- package/utils/__tests__/provider.test.ts +51 -1
- package/utils/__tests__/queue.test.ts +232 -0
- package/utils/__tests__/release-notes.test.ts +221 -0
- package/utils/__tests__/router.test.js +254 -1
- package/utils/__tests__/select.test.ts +208 -0
- package/utils/__tests__/time.test.ts +265 -1
- package/utils/__tests__/title.test.ts +47 -0
- package/utils/__tests__/width.test.ts +53 -0
- package/utils/__tests__/window.test.ts +158 -0
- package/utils/__tests__/xccdf.test.ts +126 -6
- package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
- package/utils/crypto/__tests__/index.test.ts +144 -0
- package/utils/duration.ts +104 -0
- package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
- package/utils/dynamic-content/info.ts +2 -1
- package/utils/error.js +13 -0
- package/utils/fleet-appco.ts +323 -0
- package/utils/object.js +22 -2
- package/utils/provider.ts +12 -0
- package/utils/validators/__tests__/container-images.test.ts +104 -0
- package/utils/validators/__tests__/flow-output.test.ts +91 -0
- package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
- package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
- package/utils/xccdf.ts +39 -42
- package/vue.config.js +1 -1
- package/pages/support/index.vue +0 -264
- package/utils/duration.js +0 -43
|
@@ -174,7 +174,7 @@ export default {
|
|
|
174
174
|
await wait(5000);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
const user = this.value.save();
|
|
177
|
+
const user = await this.value.save();
|
|
178
178
|
|
|
179
179
|
return user;
|
|
180
180
|
},
|
|
@@ -214,8 +214,10 @@ export default {
|
|
|
214
214
|
return;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
const userId = user?.id || this.value.id;
|
|
218
|
+
|
|
217
219
|
try {
|
|
218
|
-
await this.$refs.grb.save(
|
|
220
|
+
await this.$refs.grb.save(userId);
|
|
219
221
|
} catch (err) {
|
|
220
222
|
if (this.isCreate) {
|
|
221
223
|
try {
|
|
@@ -245,6 +247,7 @@ export default {
|
|
|
245
247
|
:can-yaml="false"
|
|
246
248
|
class="create-edit"
|
|
247
249
|
@finish="save"
|
|
250
|
+
@error="e=>errors = e"
|
|
248
251
|
>
|
|
249
252
|
<div class="credentials">
|
|
250
253
|
<h2> {{ t("user.edit.credentials.label") }}</h2>
|
|
@@ -94,8 +94,8 @@ const NODE_TOTAL = {
|
|
|
94
94
|
};
|
|
95
95
|
const CLUSTER_AGENT_CUSTOMIZATION = 'clusterAgentDeploymentCustomization';
|
|
96
96
|
const FLEET_AGENT_CUSTOMIZATION = 'fleetAgentDeploymentCustomization';
|
|
97
|
-
|
|
98
97
|
const REGISTRIES_TAB_NAME = 'registry';
|
|
98
|
+
const INIT_HOOKS = '_initHooks';
|
|
99
99
|
|
|
100
100
|
const isAzureK8sUnsupported = (version) => semver.gte(version, '1.30.0');
|
|
101
101
|
|
|
@@ -274,6 +274,7 @@ export default {
|
|
|
274
274
|
truncateLimit: this.value.defaultHostnameLengthLimit || 0,
|
|
275
275
|
busy: false,
|
|
276
276
|
machinePoolValidation: {}, // map of validation states for each machine pool
|
|
277
|
+
infrastructureClusterValid: true,
|
|
277
278
|
machinePoolErrors: {},
|
|
278
279
|
addonConfigValidation: {}, // validation state of each addon config (boolean of whether codemirror's yaml lint passed)
|
|
279
280
|
stackPreferenceError: false, // spec.networking.stackPreference is validated in conjunction with hasOnlyIpv6Pools
|
|
@@ -300,6 +301,7 @@ export default {
|
|
|
300
301
|
basicsValid: true,
|
|
301
302
|
registryConfigValid: true,
|
|
302
303
|
originalIngressController: this.value.spec.rkeConfig.machineGlobalConfig?.[INGRESS_CONTROLLER] || INGRESS_NONE,
|
|
304
|
+
infrastructureCluster: null,
|
|
303
305
|
};
|
|
304
306
|
},
|
|
305
307
|
|
|
@@ -329,6 +331,14 @@ export default {
|
|
|
329
331
|
return this.provider === ELEMENTAL_CLUSTER_PROVIDER || this.value?.machineProvider?.toLowerCase() === KIND.MACHINE_INV_SELECTOR_TEMPLATES.toLowerCase();
|
|
330
332
|
},
|
|
331
333
|
|
|
334
|
+
isUpstreamCAPIProvider() {
|
|
335
|
+
if (this.extensionProvider?.isUpstreamCAPIProvider !== undefined) {
|
|
336
|
+
return !!this.extensionProvider.isUpstreamCAPIProvider;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return false;
|
|
340
|
+
},
|
|
341
|
+
|
|
332
342
|
chartValues() {
|
|
333
343
|
return this.value.spec.rkeConfig.chartValues;
|
|
334
344
|
},
|
|
@@ -548,7 +558,7 @@ export default {
|
|
|
548
558
|
getters: this.$store.getters,
|
|
549
559
|
axios: this.$store.$axios,
|
|
550
560
|
$extension: this.$store.app.$extension,
|
|
551
|
-
|
|
561
|
+
t: (...args) => this.t.apply(this, args),
|
|
552
562
|
isCreate: this.isCreate
|
|
553
563
|
});
|
|
554
564
|
}
|
|
@@ -826,6 +836,10 @@ export default {
|
|
|
826
836
|
return null;
|
|
827
837
|
},
|
|
828
838
|
|
|
839
|
+
extensionInfrastructureSection() {
|
|
840
|
+
return this.extensionProvider?.extensionInfrastructureSection || null;
|
|
841
|
+
},
|
|
842
|
+
|
|
829
843
|
showForm() {
|
|
830
844
|
return !!this.credentialId || !this.needCredential;
|
|
831
845
|
},
|
|
@@ -879,7 +893,9 @@ export default {
|
|
|
879
893
|
|
|
880
894
|
const hasAddonConfigErrors = Object.values(this.addonConfigValidation).filter((v) => v === false).length > 0;
|
|
881
895
|
|
|
882
|
-
|
|
896
|
+
const hasInfrastructureClusterError = this.isUpstreamCAPIProvider ? !this.infrastructureClusterValid : false;
|
|
897
|
+
|
|
898
|
+
return validRequiredPools && base && !hasAddonConfigErrors && !hasInfrastructureClusterError && !this.stackPreferenceError;
|
|
883
899
|
},
|
|
884
900
|
|
|
885
901
|
currentCluster() {
|
|
@@ -1015,6 +1031,11 @@ export default {
|
|
|
1015
1031
|
},
|
|
1016
1032
|
|
|
1017
1033
|
created() {
|
|
1034
|
+
// Hooks to be run when cluster is getting initialized
|
|
1035
|
+
if (this.extensionProvider?.registerInitHooks) {
|
|
1036
|
+
this.extensionProvider.registerInitHooks(this.registerHook.bind(this, INIT_HOOKS), this.value);
|
|
1037
|
+
}
|
|
1038
|
+
// Other hooks to be run before/after saving the cluster
|
|
1018
1039
|
this.registerBeforeHook(this.showIpv6Warning, 'show-ipv6-warning', 1);
|
|
1019
1040
|
this.registerBeforeHook(this.saveMachinePools, 'save-machine-pools', 2);
|
|
1020
1041
|
this.registerBeforeHook(this.setRegistryConfig, 'set-registry-config');
|
|
@@ -1033,6 +1054,21 @@ export default {
|
|
|
1033
1054
|
methods: {
|
|
1034
1055
|
set,
|
|
1035
1056
|
|
|
1057
|
+
updateExtensionInfrastructureSection(neu) {
|
|
1058
|
+
if (!neu || typeof neu !== 'object') {
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
if (!this.infrastructureCluster || typeof this.infrastructureCluster !== 'object') {
|
|
1063
|
+
this.infrastructureCluster = neu;
|
|
1064
|
+
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// Preserve the original resource model instance while applying extension updates.
|
|
1069
|
+
mergeWithReplace(this.infrastructureCluster, neu, { mutateOriginal: true });
|
|
1070
|
+
},
|
|
1071
|
+
|
|
1036
1072
|
async handleVsphereCpiSecret() {
|
|
1037
1073
|
return VsphereUtils.handleVsphereCpiSecret(this);
|
|
1038
1074
|
},
|
|
@@ -1056,8 +1092,8 @@ export default {
|
|
|
1056
1092
|
if (!this.value.spec.machineSelectorConfig.find((x) => !x.machineLabelSelector)) {
|
|
1057
1093
|
this.value.spec.machineSelectorConfig.unshift({ config: {} });
|
|
1058
1094
|
}
|
|
1059
|
-
|
|
1060
|
-
if (this.value.spec.cloudCredentialSecretName) {
|
|
1095
|
+
// TODO handle upstream capi once credentials part is clear
|
|
1096
|
+
if (this.value.spec.cloudCredentialSecretName ) {
|
|
1061
1097
|
await this.$store.dispatch('rancher/findAll', { type: NORMAN.CLOUD_CREDENTIAL });
|
|
1062
1098
|
this.credentialId = `${ this.value.spec.cloudCredentialSecretName }`;
|
|
1063
1099
|
}
|
|
@@ -1106,6 +1142,9 @@ export default {
|
|
|
1106
1142
|
if ( isEmpty(this.value?.spec?.localClusterAuthEndpoint) ) {
|
|
1107
1143
|
set(this.value, 'spec.localClusterAuthEndpoint', { enabled: false });
|
|
1108
1144
|
}
|
|
1145
|
+
|
|
1146
|
+
await this.applyHooks(INIT_HOOKS, this.value);
|
|
1147
|
+
this.localValue = this.value;
|
|
1109
1148
|
},
|
|
1110
1149
|
|
|
1111
1150
|
/**
|
|
@@ -1281,6 +1320,10 @@ export default {
|
|
|
1281
1320
|
|
|
1282
1321
|
if (this.isElementalCluster) {
|
|
1283
1322
|
type = ELEMENTAL_SCHEMA_IDS.MACHINE_INV_SELECTOR_TEMPLATES;
|
|
1323
|
+
} else if (this.isUpstreamCAPIProvider && pool.machineConfigRef?.apiVersion) {
|
|
1324
|
+
const [group] = (pool.machineConfigRef.apiVersion || '').split('/');
|
|
1325
|
+
|
|
1326
|
+
type = `${ group }.${ pool.machineConfigRef.kind.toLowerCase() }`;
|
|
1284
1327
|
} else {
|
|
1285
1328
|
type = `${ CAPI.MACHINE_CONFIG_GROUP }.${ pool.machineConfigRef.kind.toLowerCase() }`;
|
|
1286
1329
|
}
|
|
@@ -1386,10 +1429,20 @@ export default {
|
|
|
1386
1429
|
pool.pool.machineOS = 'linux';
|
|
1387
1430
|
}
|
|
1388
1431
|
|
|
1389
|
-
if (this.isElementalCluster) {
|
|
1432
|
+
if (this.isElementalCluster && this.machineConfigSchema?.attributes) {
|
|
1390
1433
|
pool.pool.machineConfigRef.apiVersion = `${ this.machineConfigSchema.attributes.group }/${ this.machineConfigSchema.attributes.version }`;
|
|
1391
1434
|
}
|
|
1392
1435
|
|
|
1436
|
+
// Upstream CAPI MachineTemplate resources are referenced by full apiVersion so that
|
|
1437
|
+
// initMachinePools can resolve the correct management store type on subsequent loads.
|
|
1438
|
+
if (this.isUpstreamCAPIProvider && this.machineConfigSchema?.attributes) {
|
|
1439
|
+
const { group, version } = this.machineConfigSchema.attributes;
|
|
1440
|
+
|
|
1441
|
+
if (group && version) {
|
|
1442
|
+
pool.pool.machineConfigRef.apiVersion = `${ group }/${ version }`;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1393
1446
|
this.machinePools.push(pool);
|
|
1394
1447
|
|
|
1395
1448
|
this.$nextTick(() => {
|
|
@@ -1538,6 +1591,10 @@ export default {
|
|
|
1538
1591
|
},
|
|
1539
1592
|
|
|
1540
1593
|
async cleanupMachinePools() {
|
|
1594
|
+
// Allow the extension provider to handle its own resource cleanup
|
|
1595
|
+
if (this.extensionProvider?.cleanupMachinePools) {
|
|
1596
|
+
return await this.extensionProvider.cleanupMachinePools(this.machinePools);
|
|
1597
|
+
}
|
|
1541
1598
|
for (const entry of this.machinePools) {
|
|
1542
1599
|
if (entry.remove && entry.config) {
|
|
1543
1600
|
try {
|
|
@@ -2349,7 +2406,8 @@ export default {
|
|
|
2349
2406
|
if (this.errors) {
|
|
2350
2407
|
clear(this.errors);
|
|
2351
2408
|
}
|
|
2352
|
-
|
|
2409
|
+
|
|
2410
|
+
if ( this.value.cloudProvider === 'aws') {
|
|
2353
2411
|
const missingProfileName = this.machinePools.some((mp) => !mp.config.iamInstanceProfile);
|
|
2354
2412
|
|
|
2355
2413
|
if (missingProfileName) {
|
|
@@ -2358,7 +2416,7 @@ export default {
|
|
|
2358
2416
|
}
|
|
2359
2417
|
|
|
2360
2418
|
for (const [index] of this.machinePools.entries()) { // validator machine config
|
|
2361
|
-
if (typeof this.$refs.pool[index]?.test === 'function') {
|
|
2419
|
+
if (typeof this.$refs.pool?.[index]?.test === 'function') {
|
|
2362
2420
|
try {
|
|
2363
2421
|
const res = await this.$refs.pool[index].test();
|
|
2364
2422
|
|
|
@@ -2475,7 +2533,22 @@ export default {
|
|
|
2475
2533
|
>
|
|
2476
2534
|
{{ appsOSWarning }}
|
|
2477
2535
|
</Banner>
|
|
2478
|
-
|
|
2536
|
+
<div class="span-12">
|
|
2537
|
+
<component
|
|
2538
|
+
:is="extensionInfrastructureSection"
|
|
2539
|
+
v-if="extensionInfrastructureSection"
|
|
2540
|
+
:value="infrastructureCluster"
|
|
2541
|
+
:mode="mode"
|
|
2542
|
+
:provider="provider"
|
|
2543
|
+
:credential-id="credentialId"
|
|
2544
|
+
:provisioning-cluster="value"
|
|
2545
|
+
data-testid="extension-top-section"
|
|
2546
|
+
class="span-12"
|
|
2547
|
+
@update:value="updateExtensionInfrastructureSection"
|
|
2548
|
+
@error="e => errors.push(e)"
|
|
2549
|
+
@validationChanged="(val) => infrastructureClusterValid = val"
|
|
2550
|
+
/>
|
|
2551
|
+
</div>
|
|
2479
2552
|
<!-- Pools Extras -->
|
|
2480
2553
|
<template v-if="hasMachinePools">
|
|
2481
2554
|
<div class="clearfix">
|
|
@@ -2509,7 +2582,6 @@ export default {
|
|
|
2509
2582
|
/>
|
|
2510
2583
|
</div>
|
|
2511
2584
|
</div>
|
|
2512
|
-
|
|
2513
2585
|
<!-- Extra Tabs for Machine Pool -->
|
|
2514
2586
|
<Tabbed
|
|
2515
2587
|
ref="pools"
|
|
@@ -2544,6 +2616,8 @@ export default {
|
|
|
2544
2616
|
:busy="busy"
|
|
2545
2617
|
:pool-id="obj.id"
|
|
2546
2618
|
:pool-create-mode="obj.create"
|
|
2619
|
+
:infrastructure-cluster="infrastructureCluster"
|
|
2620
|
+
:hide-advanced="isUpstreamCAPIProvider"
|
|
2547
2621
|
@error="handleMachinePoolError"
|
|
2548
2622
|
@validationChanged="v => machinePoolValidationChanged(obj.id, v)"
|
|
2549
2623
|
/>
|
|
@@ -41,6 +41,11 @@ export default {
|
|
|
41
41
|
default: () => ({})
|
|
42
42
|
},
|
|
43
43
|
|
|
44
|
+
infrastructureCluster: {
|
|
45
|
+
type: Object,
|
|
46
|
+
default: () => ({})
|
|
47
|
+
},
|
|
48
|
+
|
|
44
49
|
// no credentials are required for elemental machine pools
|
|
45
50
|
credentialId: {
|
|
46
51
|
type: String,
|
|
@@ -86,6 +91,10 @@ export default {
|
|
|
86
91
|
poolCreateMode: {
|
|
87
92
|
type: Boolean,
|
|
88
93
|
required: true,
|
|
94
|
+
},
|
|
95
|
+
hideAdvanced: {
|
|
96
|
+
type: Boolean,
|
|
97
|
+
default: false
|
|
89
98
|
}
|
|
90
99
|
},
|
|
91
100
|
|
|
@@ -368,6 +377,7 @@ export default {
|
|
|
368
377
|
v-model:is-ipv6="value.isIpv6"
|
|
369
378
|
v-model:is-dualStack="value.isDualStack"
|
|
370
379
|
:cluster="cluster"
|
|
380
|
+
:infrastructure-cluster="infrastructureCluster"
|
|
371
381
|
:uuid="uuid"
|
|
372
382
|
:mode="mode"
|
|
373
383
|
:value="value.config"
|
|
@@ -396,6 +406,7 @@ export default {
|
|
|
396
406
|
/>
|
|
397
407
|
|
|
398
408
|
<AdvancedSection
|
|
409
|
+
v-if="!hideAdvanced"
|
|
399
410
|
ref="advanced"
|
|
400
411
|
:mode="mode"
|
|
401
412
|
class="advanced"
|
package/list/group.principal.vue
CHANGED
|
@@ -9,10 +9,11 @@ import { NAME } from '@shell/config/product/auth';
|
|
|
9
9
|
import { MODE, _EDIT } from '@shell/config/query-params';
|
|
10
10
|
import { mapState } from 'vuex';
|
|
11
11
|
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
12
|
+
import { RcButton } from '@components/RcButton';
|
|
12
13
|
|
|
13
14
|
export default {
|
|
14
15
|
components: {
|
|
15
|
-
AsyncButton, ResourceTable, Masthead, Loading
|
|
16
|
+
AsyncButton, ResourceTable, Masthead, Loading, RcButton
|
|
16
17
|
},
|
|
17
18
|
props: {
|
|
18
19
|
resource: {
|
|
@@ -130,13 +131,13 @@ export default {
|
|
|
130
131
|
:class="{'mr-5': canCreateGlobalRoleBinding}"
|
|
131
132
|
@click="refreshGroupMemberships"
|
|
132
133
|
/>
|
|
133
|
-
<
|
|
134
|
+
<rc-button
|
|
134
135
|
v-if="canCreateGlobalRoleBinding"
|
|
136
|
+
size="large"
|
|
135
137
|
:to="assignLocation"
|
|
136
|
-
class="btn role-primary"
|
|
137
138
|
>
|
|
138
139
|
{{ t("authGroups.actions.assignRoles") }}
|
|
139
|
-
</
|
|
140
|
+
</rc-button>
|
|
140
141
|
</template>
|
|
141
142
|
</Masthead>
|
|
142
143
|
|
|
@@ -8,6 +8,7 @@ import { HARVESTER_NAME as VIRTUAL } from '@shell/config/features';
|
|
|
8
8
|
import { CAPI, HCI, MANAGEMENT } from '@shell/config/types';
|
|
9
9
|
import { isHarvesterCluster } from '@shell/utils/cluster';
|
|
10
10
|
import { allHash } from '@shell/utils/promise';
|
|
11
|
+
import { RcButton } from '@components/RcButton';
|
|
11
12
|
|
|
12
13
|
export default {
|
|
13
14
|
components: {
|
|
@@ -15,7 +16,8 @@ export default {
|
|
|
15
16
|
ResourceTable,
|
|
16
17
|
Masthead,
|
|
17
18
|
TypeDescription,
|
|
18
|
-
Loading
|
|
19
|
+
Loading,
|
|
20
|
+
RcButton,
|
|
19
21
|
},
|
|
20
22
|
|
|
21
23
|
props: {
|
|
@@ -128,12 +130,12 @@ export default {
|
|
|
128
130
|
v-if="canCreateCluster"
|
|
129
131
|
slot="extraActions"
|
|
130
132
|
>
|
|
131
|
-
<
|
|
133
|
+
<rc-button
|
|
132
134
|
:to="importLocation"
|
|
133
|
-
|
|
135
|
+
size="large"
|
|
134
136
|
>
|
|
135
137
|
{{ t('cluster.importAction') }}
|
|
136
|
-
</
|
|
138
|
+
</rc-button>
|
|
137
139
|
</template>
|
|
138
140
|
</Masthead>
|
|
139
141
|
|
|
@@ -166,12 +168,9 @@ export default {
|
|
|
166
168
|
</template>
|
|
167
169
|
|
|
168
170
|
<template #cell:harvester="{row}">
|
|
169
|
-
<
|
|
170
|
-
class="btn btn-sm role-primary"
|
|
171
|
-
:to="row.detailLocation"
|
|
172
|
-
>
|
|
171
|
+
<rc-button :to="row.detailLocation">
|
|
173
172
|
{{ t('harvesterManager.manage') }}
|
|
174
|
-
</
|
|
173
|
+
</rc-button>
|
|
175
174
|
</template>
|
|
176
175
|
</ResourceTable>
|
|
177
176
|
<div v-else>
|
|
@@ -7,6 +7,7 @@ import Masthead from '@shell/components/ResourceList/Masthead';
|
|
|
7
7
|
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
8
8
|
import { isAdminUser } from '@shell/store/type-map';
|
|
9
9
|
import TableDataUserIcon from '@shell/components/TableDataUserIcon';
|
|
10
|
+
import { RcButton } from '@components/RcButton';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
13
|
components: {
|
|
@@ -14,6 +15,7 @@ export default {
|
|
|
14
15
|
ResourceTable,
|
|
15
16
|
Masthead,
|
|
16
17
|
TableDataUserIcon,
|
|
18
|
+
RcButton
|
|
17
19
|
},
|
|
18
20
|
mixins: [ResourceFetch],
|
|
19
21
|
props: {
|
|
@@ -128,14 +130,17 @@ export default {
|
|
|
128
130
|
v-if="isAdmin"
|
|
129
131
|
#subHeader
|
|
130
132
|
>
|
|
131
|
-
<
|
|
133
|
+
<rc-button
|
|
134
|
+
variant="link"
|
|
135
|
+
class="btn-user-retention"
|
|
132
136
|
:to="{ name: 'c-cluster-auth-user.retention'}"
|
|
133
|
-
class="btn role-link btn-sm btn-user-retention"
|
|
134
137
|
data-testid="router-link-user-retention"
|
|
135
138
|
>
|
|
136
|
-
<
|
|
139
|
+
<template #before>
|
|
140
|
+
<i class="icon icon-gear" />
|
|
141
|
+
</template>
|
|
137
142
|
{{ t('user.retention.button.label') }}
|
|
138
|
-
</
|
|
143
|
+
</rc-button>
|
|
139
144
|
</template>
|
|
140
145
|
</Masthead>
|
|
141
146
|
|
|
@@ -159,10 +164,8 @@ export default {
|
|
|
159
164
|
</div>
|
|
160
165
|
</template>
|
|
161
166
|
|
|
162
|
-
<style lang="scss">
|
|
163
|
-
.btn-user-retention {
|
|
164
|
-
|
|
165
|
-
gap: 0.25rem;
|
|
166
|
-
padding: 0;
|
|
167
|
+
<style lang="scss" scoped>
|
|
168
|
+
a.rc-button.variant-link.btn-user-retention {
|
|
169
|
+
padding: 0; //retain the padding override for left-alignment with the header
|
|
167
170
|
}
|
|
168
171
|
</style>
|
|
@@ -17,10 +17,15 @@ import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
|
|
|
17
17
|
import ManagementClusterUtils from '@shell/list/utils/management.cattle.io.cluster.utils';
|
|
18
18
|
import { STEVE_AUTOSCALER_ENABLED } from '@shell/config/pagination-table-headers';
|
|
19
19
|
import { filterHiddenLocalCluster, filterOnlyKubernetesClusters } from '@shell/utils/cluster';
|
|
20
|
+
import { RcButton } from '@components/RcButton';
|
|
20
21
|
|
|
21
22
|
export default {
|
|
22
23
|
components: {
|
|
23
|
-
Banner,
|
|
24
|
+
Banner,
|
|
25
|
+
PaginatedResourceTable,
|
|
26
|
+
Masthead,
|
|
27
|
+
MachineSummaryGraph,
|
|
28
|
+
RcButton,
|
|
24
29
|
},
|
|
25
30
|
|
|
26
31
|
data() {
|
|
@@ -289,13 +294,14 @@ export default {
|
|
|
289
294
|
v-if="canImport"
|
|
290
295
|
#extraActions
|
|
291
296
|
>
|
|
292
|
-
<
|
|
297
|
+
<rc-button
|
|
298
|
+
size="large"
|
|
299
|
+
class="mr-10"
|
|
293
300
|
:to="importLocation"
|
|
294
|
-
class="btn role-primary mr-10"
|
|
295
301
|
data-testid="cluster-manager-list-import"
|
|
296
302
|
>
|
|
297
303
|
{{ t('cluster.importAction') }}
|
|
298
|
-
</
|
|
304
|
+
</rc-button>
|
|
299
305
|
</template>
|
|
300
306
|
</Masthead>
|
|
301
307
|
|
|
@@ -329,22 +335,22 @@ export default {
|
|
|
329
335
|
</template>
|
|
330
336
|
<template #cell:explorer="{row}">
|
|
331
337
|
<!-- Align side nav cluster, home page name link and cluster management cluster explor buttons on canExplore -->
|
|
332
|
-
<
|
|
338
|
+
<rc-button
|
|
333
339
|
v-if="row.canExplore"
|
|
340
|
+
variant="secondary"
|
|
334
341
|
data-testid="cluster-manager-list-explore-management"
|
|
335
|
-
class="btn btn-sm role-secondary"
|
|
336
342
|
:to="{name: 'c-cluster', params: {cluster: row.id}}"
|
|
337
343
|
>
|
|
338
344
|
{{ t('cluster.explore') }}
|
|
339
|
-
</
|
|
340
|
-
<button
|
|
345
|
+
</rc-button>
|
|
346
|
+
<rc-button
|
|
341
347
|
v-else
|
|
348
|
+
variant="secondary"
|
|
342
349
|
data-testid="cluster-manager-list-explore"
|
|
343
350
|
:disabled="true"
|
|
344
|
-
class="btn btn-sm role-secondary"
|
|
345
351
|
>
|
|
346
352
|
{{ t('cluster.explore') }}
|
|
347
|
-
</button>
|
|
353
|
+
</rc-button>
|
|
348
354
|
</template>
|
|
349
355
|
</PaginatedResourceTable>
|
|
350
356
|
</template>
|
|
@@ -69,4 +69,94 @@ describe('mixin: authConfigMixin', () => {
|
|
|
69
69
|
expect(instance.model.scope).toStrictEqual(scope);
|
|
70
70
|
});
|
|
71
71
|
});
|
|
72
|
+
|
|
73
|
+
describe('accessMode on enable', () => {
|
|
74
|
+
const FakeComponent = {
|
|
75
|
+
render() {},
|
|
76
|
+
mixins: [authConfigMixin, childHook],
|
|
77
|
+
methods: { applyHooks: jest.fn() },
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const createMock = (model: any, overrides: Record<string, any> = {}) => ({
|
|
81
|
+
data: () => ({
|
|
82
|
+
value: { configType: 'oidc' },
|
|
83
|
+
model,
|
|
84
|
+
...overrides,
|
|
85
|
+
}),
|
|
86
|
+
computed: { principal: () => ({ me: {} }) },
|
|
87
|
+
global: {
|
|
88
|
+
mocks: {
|
|
89
|
+
$store: { dispatch: () => model },
|
|
90
|
+
$route: {
|
|
91
|
+
params: { id: model.id || '123' },
|
|
92
|
+
query: { mode: 'edit' },
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it.each([
|
|
99
|
+
'github',
|
|
100
|
+
'githubapp',
|
|
101
|
+
])('should default accessMode to restricted for %s on enable', async(id) => {
|
|
102
|
+
const model = {
|
|
103
|
+
id,
|
|
104
|
+
enabled: false,
|
|
105
|
+
authConfigName: 'whatever',
|
|
106
|
+
doAction: jest.fn(),
|
|
107
|
+
save: jest.fn(),
|
|
108
|
+
};
|
|
109
|
+
const instance = mount(FakeComponent, createMock(model)).vm as any;
|
|
110
|
+
|
|
111
|
+
await instance.save(jest.fn());
|
|
112
|
+
|
|
113
|
+
expect(model.save).toHaveBeenCalled();
|
|
114
|
+
expect(instance.model.accessMode).toStrictEqual('required');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should default accessMode to unrestricted for non-github oauth on enable', async() => {
|
|
118
|
+
const model = {
|
|
119
|
+
id: 'googleoauth',
|
|
120
|
+
enabled: false,
|
|
121
|
+
authConfigName: 'whatever',
|
|
122
|
+
doAction: jest.fn(),
|
|
123
|
+
save: jest.fn(),
|
|
124
|
+
};
|
|
125
|
+
const instance = mount(FakeComponent, createMock(model)).vm as any;
|
|
126
|
+
|
|
127
|
+
await instance.save(jest.fn());
|
|
128
|
+
|
|
129
|
+
expect(instance.model.accessMode).toStrictEqual('required');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should set accessMode to required after enabling a provider', async() => {
|
|
133
|
+
const model = {
|
|
134
|
+
enabled: false,
|
|
135
|
+
accessMode: 'unrestricted',
|
|
136
|
+
authConfigName: 'whatever',
|
|
137
|
+
doAction: jest.fn(),
|
|
138
|
+
save: async() => {}
|
|
139
|
+
};
|
|
140
|
+
const instance = mount(FakeComponent, createMock(model)).vm as any;
|
|
141
|
+
|
|
142
|
+
await instance.save(jest.fn());
|
|
143
|
+
|
|
144
|
+
expect(instance.model.accessMode).toStrictEqual('required');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('should not change accessMode when editing an already enabled provider', async() => {
|
|
148
|
+
const model = {
|
|
149
|
+
enabled: true,
|
|
150
|
+
accessMode: 'unrestricted',
|
|
151
|
+
authConfigName: 'whatever',
|
|
152
|
+
doAction: jest.fn(),
|
|
153
|
+
save: async() => {}
|
|
154
|
+
};
|
|
155
|
+
const instance = mount(FakeComponent, createMock(model, { editConfig: true })).vm as any;
|
|
156
|
+
|
|
157
|
+
await instance.save(jest.fn());
|
|
158
|
+
|
|
159
|
+
expect(instance.model.accessMode).toStrictEqual('unrestricted');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
72
162
|
});
|
|
@@ -581,5 +581,99 @@ describe('chartMixin', () => {
|
|
|
581
581
|
'0.0.1'
|
|
582
582
|
]);
|
|
583
583
|
});
|
|
584
|
+
|
|
585
|
+
it('should correctly format current version when it is Linux-only', () => {
|
|
586
|
+
const versions = [
|
|
587
|
+
{
|
|
588
|
+
version: '1.0.0',
|
|
589
|
+
created: '2026-01-01',
|
|
590
|
+
annotations: { 'catalog.cattle.io/permits-os': 'linux' }
|
|
591
|
+
}
|
|
592
|
+
];
|
|
593
|
+
|
|
594
|
+
const mockStore = {
|
|
595
|
+
dispatch: jest.fn(() => Promise.resolve()),
|
|
596
|
+
getters: {
|
|
597
|
+
currentCluster: () => ({ workerOSs: ['linux'] }),
|
|
598
|
+
isRancher: () => true,
|
|
599
|
+
'catalog/repo': () => () => 'repo',
|
|
600
|
+
'catalog/chart': () => ({ versions }),
|
|
601
|
+
'prefs/get': () => () => true,
|
|
602
|
+
'i18n/t': () => jest.fn()
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
const DummyComponent = {
|
|
607
|
+
mixins: [ChartMixin],
|
|
608
|
+
template: '<div></div>',
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
const wrapper = mount(
|
|
612
|
+
DummyComponent,
|
|
613
|
+
{
|
|
614
|
+
data: () => ({
|
|
615
|
+
chart: { versions },
|
|
616
|
+
existing: { spec: { chart: { metadata: { version: '1.0.0' } } } }
|
|
617
|
+
}),
|
|
618
|
+
global: {
|
|
619
|
+
mocks: {
|
|
620
|
+
$store: mockStore,
|
|
621
|
+
$route: { query: { version: '1.0.0' } },
|
|
622
|
+
t: (key: string, args: any) => `${ args?.ver } (Current, Linux-only)`
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
const result = (wrapper.vm as any).mappedVersions;
|
|
628
|
+
|
|
629
|
+
expect(result[0].label).toBe('1.0.0 (Current, Linux-only)');
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
it('should correctly format current version when it is not OS-restricted', () => {
|
|
633
|
+
const versions = [
|
|
634
|
+
{
|
|
635
|
+
version: '1.0.0',
|
|
636
|
+
created: '2026-01-01',
|
|
637
|
+
annotations: {}
|
|
638
|
+
}
|
|
639
|
+
];
|
|
640
|
+
|
|
641
|
+
const mockStore = {
|
|
642
|
+
dispatch: jest.fn(() => Promise.resolve()),
|
|
643
|
+
getters: {
|
|
644
|
+
currentCluster: () => ({ workerOSs: ['linux'] }),
|
|
645
|
+
isRancher: () => true,
|
|
646
|
+
'catalog/repo': () => () => 'repo',
|
|
647
|
+
'catalog/chart': () => ({ versions }),
|
|
648
|
+
'prefs/get': () => () => true,
|
|
649
|
+
'i18n/t': () => jest.fn()
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
const DummyComponent = {
|
|
654
|
+
mixins: [ChartMixin],
|
|
655
|
+
template: '<div></div>',
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const wrapper = mount(
|
|
659
|
+
DummyComponent,
|
|
660
|
+
{
|
|
661
|
+
data: () => ({
|
|
662
|
+
chart: { versions },
|
|
663
|
+
existing: { spec: { chart: { metadata: { version: '1.0.0' } } } }
|
|
664
|
+
}),
|
|
665
|
+
global: {
|
|
666
|
+
mocks: {
|
|
667
|
+
$store: mockStore,
|
|
668
|
+
$route: { query: { version: '1.0.0' } },
|
|
669
|
+
t: (key: string, args: any) => `${ args?.ver } (Current)`
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
const result = (wrapper.vm as any).mappedVersions;
|
|
675
|
+
|
|
676
|
+
expect(result[0].label).toBe('1.0.0 (Current)');
|
|
677
|
+
});
|
|
584
678
|
});
|
|
585
679
|
});
|