@rancher/shell 3.0.7 → 3.0.8-rc.1
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/images/vendor/githubapp.svg +13 -0
- package/assets/styles/base/_typography.scss +1 -1
- package/assets/styles/themes/_modern.scss +5 -5
- package/assets/translations/en-us.yaml +91 -11
- package/assets/translations/zh-hans.yaml +0 -4
- package/components/Inactivity.vue +222 -106
- package/components/InstallHelmCharts.vue +2 -2
- package/components/ResourceDetail/index.vue +1 -1
- package/components/SortableTable/index.vue +17 -2
- package/components/fleet/FleetConfigMapSelector.vue +117 -0
- package/components/fleet/FleetSecretSelector.vue +127 -0
- package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
- package/components/form/FileImageSelector.vue +13 -4
- package/components/form/FileSelector.vue +11 -2
- package/components/form/ResourceLabeledSelect.vue +1 -0
- package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
- package/components/nav/Header.vue +1 -0
- package/config/product/auth.js +1 -0
- package/config/query-params.js +1 -0
- package/config/settings.ts +8 -1
- package/config/types.js +2 -0
- package/dialog/AddonConfigConfirmationDialog.vue +45 -1
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
- package/edit/auth/AuthProviderWarningBanners.vue +14 -1
- package/edit/auth/github-app-steps.vue +97 -0
- package/edit/auth/github-steps.vue +75 -0
- package/edit/auth/github.vue +94 -65
- package/edit/fleet.cattle.io.helmop.vue +51 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
- package/edit/provisioning.cattle.io.cluster/rke2.vue +56 -9
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
- package/list/projectsecret.vue +1 -1
- package/machine-config/azure.vue +1 -1
- package/mixins/chart.js +1 -1
- package/models/__tests__/chart.test.ts +17 -9
- package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/chart.js +3 -1
- package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
- package/models/management.cattle.io.authconfig.js +1 -0
- package/package.json +2 -2
- package/pages/auth/login.vue +5 -2
- package/pages/auth/verify.vue +1 -1
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
- package/pages/c/_cluster/apps/charts/chart.vue +2 -2
- package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/settings/performance.vue +12 -25
- package/pages/home.vue +313 -12
- package/plugins/axios.js +2 -1
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/resource-class.js +17 -2
- package/plugins/steve/steve-pagination-utils.ts +2 -2
- package/scripts/extension/publish +1 -1
- package/store/auth.js +8 -3
- package/store/aws.js +8 -6
- package/store/features.js +1 -0
- package/store/index.js +9 -3
- package/store/prefs.js +6 -0
- package/types/kube/kube-api.ts +2 -1
- package/types/rancher/index.d.ts +1 -0
- package/types/resources/settings.d.ts +29 -7
- package/types/shell/index.d.ts +59 -0
- package/utils/__tests__/cluster.test.ts +379 -1
- package/utils/cluster.js +157 -3
- package/utils/dynamic-content/__tests__/config.test.ts +187 -0
- package/utils/dynamic-content/__tests__/index.test.ts +390 -0
- package/utils/dynamic-content/__tests__/info.test.ts +263 -0
- package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
- package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
- package/utils/dynamic-content/__tests__/util.test.ts +235 -0
- package/utils/dynamic-content/config.ts +55 -0
- package/utils/dynamic-content/index.ts +273 -0
- package/utils/dynamic-content/info.ts +219 -0
- package/utils/dynamic-content/new-release.ts +126 -0
- package/utils/dynamic-content/support-notice.ts +169 -0
- package/utils/dynamic-content/types.d.ts +101 -0
- package/utils/dynamic-content/util.ts +122 -0
- package/utils/inactivity.ts +104 -0
- package/utils/pagination-utils.ts +19 -4
- package/utils/release-notes.ts +1 -1
|
@@ -76,6 +76,13 @@ export default {
|
|
|
76
76
|
resource: MANAGEMENT.FEATURE
|
|
77
77
|
}
|
|
78
78
|
}).href,
|
|
79
|
+
settingsPageUrl: this.$router.resolve({
|
|
80
|
+
name: 'c-cluster-product-resource',
|
|
81
|
+
params: {
|
|
82
|
+
product: SETTING_PRODUCT,
|
|
83
|
+
resource: MANAGEMENT.SETTING
|
|
84
|
+
}
|
|
85
|
+
}).href,
|
|
79
86
|
ssPApplicableTypesOpen: false,
|
|
80
87
|
};
|
|
81
88
|
},
|
|
@@ -206,31 +213,11 @@ export default {
|
|
|
206
213
|
<!-- Inactivity -->
|
|
207
214
|
<div class="mt-20">
|
|
208
215
|
<h2>{{ t('performance.inactivity.title') }}</h2>
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
class="mt-10 mb-20"
|
|
215
|
-
:primary="true"
|
|
216
|
-
/>
|
|
217
|
-
<div class="ml-20">
|
|
218
|
-
<LabeledInput
|
|
219
|
-
v-model:value="value.inactivity.threshold"
|
|
220
|
-
data-testid="inactivity-threshold"
|
|
221
|
-
:mode="mode"
|
|
222
|
-
:label="t('performance.inactivity.inputLabel')"
|
|
223
|
-
:disabled="!value.inactivity.enabled"
|
|
224
|
-
class="input mb-10"
|
|
225
|
-
type="number"
|
|
226
|
-
min="0"
|
|
227
|
-
:rules="[validateInactivityThreshold]"
|
|
228
|
-
/>
|
|
229
|
-
<span
|
|
230
|
-
v-clean-html="t('performance.inactivity.information', {}, true)"
|
|
231
|
-
:class="{ 'text-muted': !value.incrementalLoading.enabled }"
|
|
232
|
-
/>
|
|
233
|
-
</div>
|
|
216
|
+
<Banner
|
|
217
|
+
color="warning"
|
|
218
|
+
>
|
|
219
|
+
<span v-clean-html="t(`performance.deprecatedInactivitySetting`, { settingsPageUrl }, true)" />
|
|
220
|
+
</Banner>
|
|
234
221
|
</div>
|
|
235
222
|
<!-- Websocket Notifications -->
|
|
236
223
|
<div class="mt-40">
|
package/pages/home.vue
CHANGED
|
@@ -8,9 +8,9 @@ import { BadgeState } from '@components/BadgeState';
|
|
|
8
8
|
import CommunityLinks from '@shell/components/CommunityLinks.vue';
|
|
9
9
|
import SingleClusterInfo from '@shell/components/SingleClusterInfo.vue';
|
|
10
10
|
import { mapGetters, mapState } from 'vuex';
|
|
11
|
-
import { MANAGEMENT, CAPI } from '@shell/config/types';
|
|
11
|
+
import { MANAGEMENT, CAPI, COUNT } from '@shell/config/types';
|
|
12
12
|
import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
13
|
-
import { STATE } from '@shell/config/table-headers';
|
|
13
|
+
import { AGE, STATE } from '@shell/config/table-headers';
|
|
14
14
|
import { MODE, _IMPORT } from '@shell/config/query-params';
|
|
15
15
|
import { createMemoryFormat, formatSi, parseSi, createMemoryValues } from '@shell/utils/units';
|
|
16
16
|
import { markSeenReleaseNotes } from '@shell/utils/version';
|
|
@@ -28,8 +28,12 @@ import { PaginationParamFilter, FilterArgs, PaginationFilterField, PaginationArg
|
|
|
28
28
|
import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
|
|
29
29
|
import { sameContents } from '@shell/utils/array';
|
|
30
30
|
import { PagTableFetchPageSecondaryResourcesOpts, PagTableFetchSecondaryResourcesOpts, PagTableFetchSecondaryResourcesReturns } from '@shell/types/components/paginatedResourceTable';
|
|
31
|
-
import { CURRENT_RANCHER_VERSION } from '@shell/config/version';
|
|
31
|
+
import { CURRENT_RANCHER_VERSION, getVersionData } from '@shell/config/version';
|
|
32
32
|
import { CAPI as CAPI_LAB_AND_ANO } from '@shell/config/labels-annotations';
|
|
33
|
+
import paginationUtils from '@shell/utils/pagination-utils';
|
|
34
|
+
import ResourceTable from '@shell/components/ResourceTable.vue';
|
|
35
|
+
import Preset from '@shell/mixins/preset';
|
|
36
|
+
import { PaginationFeatureHomePageClusterConfig } from '@shell/types/resources/settings';
|
|
33
37
|
|
|
34
38
|
export default defineComponent({
|
|
35
39
|
name: 'Home',
|
|
@@ -42,9 +46,10 @@ export default defineComponent({
|
|
|
42
46
|
CommunityLinks,
|
|
43
47
|
SingleClusterInfo,
|
|
44
48
|
TabTitle,
|
|
49
|
+
ResourceTable,
|
|
45
50
|
},
|
|
46
51
|
|
|
47
|
-
mixins: [PageHeaderActions],
|
|
52
|
+
mixins: [PageHeaderActions, Preset],
|
|
48
53
|
|
|
49
54
|
data() {
|
|
50
55
|
const options = this.$store.getters[`type-map/optionsFor`](CAPI.RANCHER_CLUSTER)?.custom || {};
|
|
@@ -200,15 +205,41 @@ export default defineComponent({
|
|
|
200
205
|
|
|
201
206
|
clusterCount: 0,
|
|
202
207
|
|
|
203
|
-
CURRENT_RANCHER_VERSION
|
|
208
|
+
CURRENT_RANCHER_VERSION,
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* User has decided to disable the alt list
|
|
212
|
+
*/
|
|
213
|
+
altClusterListDisabled: false,
|
|
214
|
+
/**
|
|
215
|
+
* There are too many clusters to show in the home page list.
|
|
216
|
+
*
|
|
217
|
+
* If not disabled, show alt table
|
|
218
|
+
*/
|
|
219
|
+
tooManyClusters: undefined as boolean | undefined,
|
|
220
|
+
altClusterListRows: undefined as any[] | undefined,
|
|
221
|
+
altClusterListFeature: paginationUtils.getFeature<PaginationFeatureHomePageClusterConfig>({ rootGetters: this.$store.getters }, 'homePageCluster'),
|
|
222
|
+
|
|
223
|
+
presetVersion: getVersionData()?.Version,
|
|
204
224
|
};
|
|
205
225
|
},
|
|
206
226
|
|
|
227
|
+
mounted() {
|
|
228
|
+
this.preset('altClusterListDisabled', 'boolean');
|
|
229
|
+
},
|
|
230
|
+
|
|
207
231
|
computed: {
|
|
208
232
|
...mapState(['managementReady']),
|
|
209
233
|
...mapGetters(['currentCluster', 'defaultClusterId']),
|
|
210
234
|
mcm: mapFeature(MULTI_CLUSTER),
|
|
211
235
|
|
|
236
|
+
vaiOnSettingsHeaders() {
|
|
237
|
+
return [
|
|
238
|
+
...this.headers, // include age as we're sorting by it
|
|
239
|
+
AGE
|
|
240
|
+
];
|
|
241
|
+
},
|
|
242
|
+
|
|
212
243
|
canCreateCluster() {
|
|
213
244
|
return !!this.provClusterSchema?.collectionMethods.find((x: string) => x.toLowerCase() === 'post');
|
|
214
245
|
},
|
|
@@ -216,6 +247,21 @@ export default defineComponent({
|
|
|
216
247
|
afterLoginRoute: mapPref(AFTER_LOGIN_ROUTE),
|
|
217
248
|
homePageCards: mapPref(HIDE_HOME_PAGE_CARDS),
|
|
218
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Show the alt table
|
|
252
|
+
*/
|
|
253
|
+
altClusterList() {
|
|
254
|
+
return this.tooManyClusters && !this.altClusterListDisabled;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
watch: {
|
|
260
|
+
async altClusterList(neu) {
|
|
261
|
+
if (neu) {
|
|
262
|
+
await this.initAltClusters();
|
|
263
|
+
}
|
|
264
|
+
},
|
|
219
265
|
},
|
|
220
266
|
|
|
221
267
|
async created() {
|
|
@@ -227,6 +273,12 @@ export default defineComponent({
|
|
|
227
273
|
// If we do not, then if they set the landing page, that won't work unless the release notes are marked read
|
|
228
274
|
// otherwise we always take them to the home page to see the release notes
|
|
229
275
|
markSeenReleaseNotes(this.$store);
|
|
276
|
+
|
|
277
|
+
this.tooManyClusters = this.isTooManyClusters();
|
|
278
|
+
|
|
279
|
+
if (this.altClusterList) {
|
|
280
|
+
await this.initAltClusters();
|
|
281
|
+
}
|
|
230
282
|
},
|
|
231
283
|
|
|
232
284
|
// Forget the types when we leave the page
|
|
@@ -458,7 +510,83 @@ export default defineComponent({
|
|
|
458
510
|
}
|
|
459
511
|
|
|
460
512
|
return pagination;
|
|
461
|
-
}
|
|
513
|
+
},
|
|
514
|
+
|
|
515
|
+
async toggleAltClusterListDisabled(disabled: boolean) {
|
|
516
|
+
// Clear the cache so the table doesn't show the previous mode's results
|
|
517
|
+
await this.$store.dispatch('management/forgetType', CAPI.RANCHER_CLUSTER);
|
|
518
|
+
|
|
519
|
+
this.altClusterListDisabled = disabled;
|
|
520
|
+
},
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Determine if we should use an alternative cluster list which contains most recently created clusters
|
|
524
|
+
*
|
|
525
|
+
* Checks
|
|
526
|
+
* - can view clusters
|
|
527
|
+
* - if vai is on
|
|
528
|
+
* - if alt list feature is on
|
|
529
|
+
* - if cluster count exceeds threshold
|
|
530
|
+
*/
|
|
531
|
+
isTooManyClusters(): boolean {
|
|
532
|
+
if (!this.provClusterSchema || !this.canViewMgmtClusters) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const featureConfig = this.altClusterListFeature;
|
|
537
|
+
|
|
538
|
+
if (!featureConfig || !featureConfig.enabled) { // vai is off, or feature is explicitly disabled
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const threshold = featureConfig.configuration?.threshold;
|
|
543
|
+
|
|
544
|
+
if (threshold === undefined) { // invalid config
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const counts = this.$store.getters[`management/all`](COUNT)?.[0]?.counts || {};
|
|
549
|
+
|
|
550
|
+
this.clusterCount = counts[CAPI.RANCHER_CLUSTER]?.summary.count;
|
|
551
|
+
|
|
552
|
+
return this.clusterCount > threshold;
|
|
553
|
+
},
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Fetch clusters used to populate alt table
|
|
557
|
+
*/
|
|
558
|
+
async initAltClusters() {
|
|
559
|
+
const featureConfig = this.altClusterListFeature;
|
|
560
|
+
const results = featureConfig?.configuration?.results || 50;
|
|
561
|
+
|
|
562
|
+
// Fetch a limited number of provisioning clusters
|
|
563
|
+
const opt1: ActionFindPageArgs = {
|
|
564
|
+
pagination: {
|
|
565
|
+
projectsOrNamespaces: [],
|
|
566
|
+
filters: paginationFilterClusters(this.$store, false),
|
|
567
|
+
page: 1,
|
|
568
|
+
pageSize: results, // We're fetching the total results... then paging locally
|
|
569
|
+
sort: [{ field: 'metadata.creationTimestamp', asc: false }]
|
|
570
|
+
},
|
|
571
|
+
watch: false,
|
|
572
|
+
};
|
|
573
|
+
const provClusters = await this.$store.dispatch('management/findPage', { type: CAPI.RANCHER_CLUSTER, opt: opt1 });
|
|
574
|
+
|
|
575
|
+
// Also fetch the management clusters associated with the provisioning clusters
|
|
576
|
+
const opt2: ActionFindPageArgs = {
|
|
577
|
+
pagination: new FilterArgs({
|
|
578
|
+
filters: PaginationParamFilter.createMultipleFields(provClusters.map((r: any) => new PaginationFilterField({
|
|
579
|
+
field: 'id',
|
|
580
|
+
value: r.mgmtClusterId
|
|
581
|
+
}))),
|
|
582
|
+
}),
|
|
583
|
+
watch: false,
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
await this.$store.dispatch(`management/findPage`, { type: MANAGEMENT.CLUSTER, opt: opt2 });
|
|
587
|
+
|
|
588
|
+
this.altClusterListRows = provClusters;
|
|
589
|
+
},
|
|
462
590
|
}
|
|
463
591
|
});
|
|
464
592
|
|
|
@@ -485,9 +613,164 @@ export default defineComponent({
|
|
|
485
613
|
<IndentedPanel class="mt-20 mb-20">
|
|
486
614
|
<div class="row home-panels">
|
|
487
615
|
<div class="col main-panel">
|
|
488
|
-
<div
|
|
616
|
+
<div
|
|
617
|
+
v-if="altClusterList !== undefined"
|
|
618
|
+
class="row panel"
|
|
619
|
+
>
|
|
620
|
+
<div
|
|
621
|
+
v-if="mcm && altClusterList"
|
|
622
|
+
class="col span-12"
|
|
623
|
+
>
|
|
624
|
+
<ResourceTable
|
|
625
|
+
:schema="provClusterSchema"
|
|
626
|
+
:table-actions="false"
|
|
627
|
+
:row-actions="false"
|
|
628
|
+
key-field="id"
|
|
629
|
+
|
|
630
|
+
:headers="vaiOnSettingsHeaders"
|
|
631
|
+
defaultSortBy="age"
|
|
632
|
+
|
|
633
|
+
:loading="!altClusterListRows"
|
|
634
|
+
|
|
635
|
+
:rows="altClusterListRows || []"
|
|
636
|
+
:rowsPerPage="altClusterListFeature?.configuration.pagesPerRow || 10"
|
|
637
|
+
|
|
638
|
+
:namespaced="false"
|
|
639
|
+
:groupable="false"
|
|
640
|
+
>
|
|
641
|
+
<template #header-left>
|
|
642
|
+
<div class="row table-heading">
|
|
643
|
+
<h1 class="mb-0">
|
|
644
|
+
{{ t('landing.clusters.title') }}
|
|
645
|
+
</h1>
|
|
646
|
+
</div>
|
|
647
|
+
</template>
|
|
648
|
+
<template #sub-header-row>
|
|
649
|
+
<h2 class="too-many-clusters">
|
|
650
|
+
{{ t('landing.clusters.tooMany.showingSome', { rows: altClusterListRows?.length || '...', total: clusterCount}) }}
|
|
651
|
+
<a @click="toggleAltClusterListDisabled(true)">{{ t('landing.clusters.tooMany.showAll') }}</a>
|
|
652
|
+
</h2>
|
|
653
|
+
</template>
|
|
654
|
+
<!--
|
|
655
|
+
Below is a big copy & paste from PaginatedResourceTable, however should be temporary (altClusterList removed in 2.14 once full SSP support for clusters if available)
|
|
656
|
+
-->
|
|
657
|
+
<template
|
|
658
|
+
v-if="canCreateCluster || !!provClusterSchema"
|
|
659
|
+
#header-middle
|
|
660
|
+
>
|
|
661
|
+
<div class="table-heading">
|
|
662
|
+
<router-link
|
|
663
|
+
v-if="!!provClusterSchema"
|
|
664
|
+
:to="manageLocation"
|
|
665
|
+
class="btn btn-sm role-secondary"
|
|
666
|
+
data-testid="cluster-management-manage-button"
|
|
667
|
+
role="button"
|
|
668
|
+
:aria-label="t('cluster.manageAction')"
|
|
669
|
+
@keyup.space="$router.push(manageLocation)"
|
|
670
|
+
>
|
|
671
|
+
{{ t('cluster.manageAction') }}
|
|
672
|
+
</router-link>
|
|
673
|
+
<router-link
|
|
674
|
+
v-if="canCreateCluster"
|
|
675
|
+
:to="importLocation"
|
|
676
|
+
class="btn btn-sm role-primary"
|
|
677
|
+
data-testid="cluster-create-import-button"
|
|
678
|
+
role="button"
|
|
679
|
+
:aria-label="t('cluster.importAction')"
|
|
680
|
+
@keyup.space="$router.push(importLocation)"
|
|
681
|
+
>
|
|
682
|
+
{{ t('cluster.importAction') }}
|
|
683
|
+
</router-link>
|
|
684
|
+
<router-link
|
|
685
|
+
v-if="canCreateCluster"
|
|
686
|
+
:to="createLocation"
|
|
687
|
+
class="btn btn-sm role-primary"
|
|
688
|
+
data-testid="cluster-create-button"
|
|
689
|
+
role="button"
|
|
690
|
+
:aria-label="t('generic.create')"
|
|
691
|
+
@keyup.space="$router.push(createLocation)"
|
|
692
|
+
>
|
|
693
|
+
{{ t('generic.create') }}
|
|
694
|
+
</router-link>
|
|
695
|
+
</div>
|
|
696
|
+
</template>
|
|
697
|
+
<template #col:name="{row}">
|
|
698
|
+
<td class="col-name">
|
|
699
|
+
<div class="list-cluster-name">
|
|
700
|
+
<p
|
|
701
|
+
v-if="row.mgmt"
|
|
702
|
+
class="cluster-name"
|
|
703
|
+
>
|
|
704
|
+
<router-link
|
|
705
|
+
v-if="row.mgmt.isReady && !row.hasError"
|
|
706
|
+
:to="{ name: 'c-cluster-explorer', params: { cluster: row.mgmt.id }}"
|
|
707
|
+
role="link"
|
|
708
|
+
:aria-label="row.nameDisplay"
|
|
709
|
+
>
|
|
710
|
+
{{ row.nameDisplay }}
|
|
711
|
+
</router-link>
|
|
712
|
+
<span v-else>{{ row.nameDisplay }}</span>
|
|
713
|
+
<i
|
|
714
|
+
v-if="row.unavailableMachines"
|
|
715
|
+
v-clean-tooltip="row.unavailableMachines"
|
|
716
|
+
class="conditions-alert-icon icon-alert icon"
|
|
717
|
+
/>
|
|
718
|
+
<i
|
|
719
|
+
v-if="row.isRke1"
|
|
720
|
+
v-clean-tooltip="t('cluster.rke1Unsupported')"
|
|
721
|
+
class="rke1-unsupported-icon icon-warning icon"
|
|
722
|
+
/>
|
|
723
|
+
</p>
|
|
724
|
+
<p
|
|
725
|
+
v-if="row.description"
|
|
726
|
+
class="cluster-description"
|
|
727
|
+
>
|
|
728
|
+
{{ row.description }}
|
|
729
|
+
</p>
|
|
730
|
+
</div>
|
|
731
|
+
</td>
|
|
732
|
+
</template>
|
|
733
|
+
<template #col:kubernetesVersion="{row}">
|
|
734
|
+
<td class="col-name">
|
|
735
|
+
<span>
|
|
736
|
+
{{ row.kubernetesVersion }}
|
|
737
|
+
</span>
|
|
738
|
+
<div
|
|
739
|
+
v-clean-tooltip="{content: row.architecture.tooltip, placement: 'left'}"
|
|
740
|
+
class="text-muted"
|
|
741
|
+
>
|
|
742
|
+
{{ row.architecture.label }}
|
|
743
|
+
</div>
|
|
744
|
+
</td>
|
|
745
|
+
</template>
|
|
746
|
+
<template #col:cpu="{row}">
|
|
747
|
+
<td v-if="row.mgmt && cpuAllocatable(row.mgmt)">
|
|
748
|
+
{{ `${cpuAllocatable(row.mgmt)} ${t('landing.clusters.cores', {count:cpuAllocatable(row.mgmt) })}` }}
|
|
749
|
+
</td>
|
|
750
|
+
<td v-else>
|
|
751
|
+
—
|
|
752
|
+
</td>
|
|
753
|
+
</template>
|
|
754
|
+
<template #col:memory="{row}">
|
|
755
|
+
<td v-if="row.mgmt && memoryAllocatable(row.mgmt) && !memoryAllocatable(row.mgmt).match(/^0 [a-zA-z]/)">
|
|
756
|
+
{{ memoryAllocatable(row.mgmt) }}
|
|
757
|
+
</td>
|
|
758
|
+
<td v-else>
|
|
759
|
+
—
|
|
760
|
+
</td>
|
|
761
|
+
</template>
|
|
762
|
+
<!-- <template #cell:explorer="{row}">
|
|
763
|
+
<router-link v-if="row && row.isReady" class="btn btn-sm role-primary" :to="{name: 'c-cluster', params: {cluster: row.id}}">
|
|
764
|
+
{{ t('landing.clusters.explore') }}
|
|
765
|
+
</router-link>
|
|
766
|
+
<button v-else :disabled="true" class="btn btn-sm role-primary">
|
|
767
|
+
{{ t('landing.clusters.explore') }}
|
|
768
|
+
</button>
|
|
769
|
+
</template> -->
|
|
770
|
+
</ResourceTable>
|
|
771
|
+
</div>
|
|
489
772
|
<div
|
|
490
|
-
v-if="mcm"
|
|
773
|
+
v-else-if="mcm"
|
|
491
774
|
class="col span-12"
|
|
492
775
|
>
|
|
493
776
|
<PaginatedResourceTable
|
|
@@ -511,16 +794,25 @@ export default defineComponent({
|
|
|
511
794
|
>
|
|
512
795
|
<template #header-left>
|
|
513
796
|
<div class="row table-heading">
|
|
514
|
-
<
|
|
797
|
+
<h1 class="mb-0">
|
|
515
798
|
{{ t('landing.clusters.title') }}
|
|
516
|
-
</
|
|
799
|
+
</h1>
|
|
517
800
|
<BadgeState
|
|
518
|
-
v-if="clusterCount"
|
|
801
|
+
v-if="clusterCount && !tooManyClusters"
|
|
519
802
|
:label="clusterCount.toString()"
|
|
520
|
-
color="
|
|
803
|
+
color="bg-info ml-20 mr-20"
|
|
521
804
|
/>
|
|
522
805
|
</div>
|
|
523
806
|
</template>
|
|
807
|
+
<template
|
|
808
|
+
v-if="tooManyClusters"
|
|
809
|
+
#sub-header-row
|
|
810
|
+
>
|
|
811
|
+
<h2 class="too-many-clusters">
|
|
812
|
+
{{ t('landing.clusters.tooMany.showingAll', { rows: altClusterListRows?.length || '...', total: clusterCount}) }}
|
|
813
|
+
<a @click="toggleAltClusterListDisabled(false)">{{ t('landing.clusters.tooMany.showSome') }}</a>
|
|
814
|
+
</h2>
|
|
815
|
+
</template>
|
|
524
816
|
<template
|
|
525
817
|
v-if="canCreateCluster || !!provClusterSchema"
|
|
526
818
|
#header-middle
|
|
@@ -663,6 +955,14 @@ export default defineComponent({
|
|
|
663
955
|
}
|
|
664
956
|
.main-panel {
|
|
665
957
|
flex: auto;
|
|
958
|
+
|
|
959
|
+
.too-many-clusters {
|
|
960
|
+
margin-bottom: 5px;
|
|
961
|
+
|
|
962
|
+
a {
|
|
963
|
+
cursor: pointer;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
666
966
|
}
|
|
667
967
|
|
|
668
968
|
.side-panel {
|
|
@@ -744,6 +1044,7 @@ export default defineComponent({
|
|
|
744
1044
|
.search {
|
|
745
1045
|
align-items: center;
|
|
746
1046
|
display: flex;
|
|
1047
|
+
height: 39px;
|
|
747
1048
|
|
|
748
1049
|
> INPUT {
|
|
749
1050
|
background-color: transparent;
|
package/plugins/axios.js
CHANGED
|
@@ -11,7 +11,8 @@ export default function({
|
|
|
11
11
|
const options = { parseJSON: false };
|
|
12
12
|
const csrf = store.getters['cookies/get']({ key: CSRF, options });
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// Request can ask not to send the CSRF header
|
|
15
|
+
if (csrf && !config.noApiCsrf) {
|
|
15
16
|
config.headers['x-api-csrf'] = csrf;
|
|
16
17
|
}
|
|
17
18
|
});
|
|
@@ -698,7 +698,7 @@ export default {
|
|
|
698
698
|
|
|
699
699
|
const res = await dispatch('request', { opt, type });
|
|
700
700
|
|
|
701
|
-
await dispatch('load', { data: res });
|
|
701
|
+
await dispatch('load', { data: res, invalidatePageCache: opt.invalidatePageCache });
|
|
702
702
|
|
|
703
703
|
if ( opt.watch !== false ) {
|
|
704
704
|
dispatch('watch', createFindWatchArg({
|
|
@@ -1264,6 +1264,12 @@ export default class Resource {
|
|
|
1264
1264
|
delete opt.replace;
|
|
1265
1265
|
}
|
|
1266
1266
|
|
|
1267
|
+
// Will loading this resource invalidate the resources in the cache that represent a page (resource is not from page)
|
|
1268
|
+
// By default we set this to no, it won't pollute the cache. Most likely either
|
|
1269
|
+
// 1. The resource came from a list already (loaded resource is already in the page that is in the cache)
|
|
1270
|
+
// 2. UI is not on a page with a list (cache doesn't represent a list)
|
|
1271
|
+
const invalidatePageCache = opt.invalidatePageCache || false;
|
|
1272
|
+
|
|
1267
1273
|
try {
|
|
1268
1274
|
const res = await this.$dispatch('request', { opt, type: this.type } );
|
|
1269
1275
|
|
|
@@ -1272,7 +1278,9 @@ export default class Resource {
|
|
|
1272
1278
|
|
|
1273
1279
|
// Steve sometimes returns Table responses instead of the resource you just saved.. ignore
|
|
1274
1280
|
if ( res && res.kind !== 'Table') {
|
|
1275
|
-
await this.$dispatch('load', {
|
|
1281
|
+
await this.$dispatch('load', {
|
|
1282
|
+
data: res, existing: (forNew ? this : undefined ), invalidatePageCache
|
|
1283
|
+
});
|
|
1276
1284
|
}
|
|
1277
1285
|
} catch (e) {
|
|
1278
1286
|
if ( this.type && this.id && e?._status === 409) {
|
|
@@ -1280,7 +1288,14 @@ export default class Resource {
|
|
|
1280
1288
|
await this.$dispatch('find', {
|
|
1281
1289
|
type: this.type,
|
|
1282
1290
|
id: this.id,
|
|
1283
|
-
opt: {
|
|
1291
|
+
opt: {
|
|
1292
|
+
// We want to update the value in cache, so force the request
|
|
1293
|
+
force: true,
|
|
1294
|
+
// We're not interested in opening a watch for this specific resource
|
|
1295
|
+
watch: false,
|
|
1296
|
+
// Unless overridden, this will be false, we're probably from a list and we don't want to clear it's state
|
|
1297
|
+
invalidatePageCache
|
|
1298
|
+
}
|
|
1284
1299
|
});
|
|
1285
1300
|
}
|
|
1286
1301
|
|
|
@@ -676,8 +676,8 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStores = {
|
|
|
676
676
|
enableAll: false,
|
|
677
677
|
enableSome: {
|
|
678
678
|
enabled: [
|
|
679
|
-
|
|
680
|
-
|
|
679
|
+
{ resource: CAPI.RANCHER_CLUSTER, context: ['side-bar'] },
|
|
680
|
+
{ resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
|
|
681
681
|
{ resource: CATALOG.APP, context: ['branding'] },
|
|
682
682
|
SECRET
|
|
683
683
|
],
|
|
@@ -164,7 +164,7 @@ if [ "${HAVE_COMMANDS}" == "false" ]; then
|
|
|
164
164
|
fi
|
|
165
165
|
|
|
166
166
|
# --------------------------------------------------------------------------------
|
|
167
|
-
# Only do
|
|
167
|
+
# Only do container args checks if not GitHub publish
|
|
168
168
|
# --------------------------------------------------------------------------------
|
|
169
169
|
if [ "${GITHUB_BUILD}" == "false" ]; then
|
|
170
170
|
BASE_EXT=$(jq -r .name ${BASE_DIR}/package.json)
|
package/store/auth.js
CHANGED
|
@@ -17,6 +17,7 @@ const SLO_TOKENS_ENDPOINT_LOGOUT_RES_BASETYPE = ['authConfigLogoutOutput'];
|
|
|
17
17
|
|
|
18
18
|
export const BASE_SCOPES = {
|
|
19
19
|
github: ['read:org'],
|
|
20
|
+
githubapp: ['read:org'],
|
|
20
21
|
googleoauth: ['openid profile email'],
|
|
21
22
|
azuread: [],
|
|
22
23
|
keycloakoidc: ['openid profile email'],
|
|
@@ -374,11 +375,11 @@ export const actions = {
|
|
|
374
375
|
commit('cookies/remove', { key: KEY }, { root: true });
|
|
375
376
|
},
|
|
376
377
|
|
|
377
|
-
uiLogout({ commit, dispatch }) {
|
|
378
|
+
uiLogout({ commit, dispatch }, options = {}) {
|
|
378
379
|
removeEmberPage();
|
|
379
380
|
|
|
380
381
|
commit('loggedOut');
|
|
381
|
-
dispatch('onLogout',
|
|
382
|
+
dispatch('onLogout', options, { root: true });
|
|
382
383
|
|
|
383
384
|
dispatch('uiplugins/setReady', false, { root: true });
|
|
384
385
|
},
|
|
@@ -430,6 +431,10 @@ export const actions = {
|
|
|
430
431
|
} catch (e) {
|
|
431
432
|
}
|
|
432
433
|
|
|
433
|
-
|
|
434
|
+
const propagateOptions = {};
|
|
435
|
+
|
|
436
|
+
propagateOptions.sessionIdle = options.sessionIdle;
|
|
437
|
+
|
|
438
|
+
dispatch('uiLogout', propagateOptions);
|
|
434
439
|
}
|
|
435
440
|
};
|
package/store/aws.js
CHANGED
|
@@ -213,18 +213,20 @@ export const actions = {
|
|
|
213
213
|
|
|
214
214
|
list.push({
|
|
215
215
|
apiName,
|
|
216
|
-
currentGeneration:
|
|
216
|
+
currentGeneration: row.CurrentGeneration || false,
|
|
217
217
|
groupLabel,
|
|
218
218
|
instanceClass,
|
|
219
|
-
memoryBytes:
|
|
220
|
-
supportedUsageClasses:
|
|
221
|
-
|
|
219
|
+
memoryBytes: row.MemoryInfo.SizeInMiB * 1024 * 1024,
|
|
220
|
+
supportedUsageClasses: row.SupportedUsageClasses,
|
|
221
|
+
supportedArchitectures: row.ProcessorInfo.SupportedArchitectures || [],
|
|
222
|
+
label: rootGetters['i18n/t']('cluster.machineConfig.aws.sizeLabel', {
|
|
222
223
|
apiName,
|
|
223
|
-
cpu:
|
|
224
|
-
memory:
|
|
224
|
+
cpu: row.VCpuInfo.DefaultVCpus,
|
|
225
|
+
memory: row.MemoryInfo.SizeInMiB / 1024,
|
|
225
226
|
storageSize,
|
|
226
227
|
storageUnit,
|
|
227
228
|
storageType,
|
|
229
|
+
architecture: (row.ProcessorInfo.SupportedArchitectures || []).map((a) => (a === 'arm64' ? 'ARM' : a)).join(', ')
|
|
228
230
|
}),
|
|
229
231
|
});
|
|
230
232
|
}
|
package/store/features.js
CHANGED
|
@@ -37,6 +37,7 @@ export const STEVE_CACHE = create('ui-sql-cache', false);
|
|
|
37
37
|
export const UIEXTENSION = create('uiextension', true);
|
|
38
38
|
export const PROVISIONING_PRE_BOOTSTRAP = create('provisioningprebootstrap', false);
|
|
39
39
|
export const SCHEDULING_CUSTOMIZATION = create(SCHEDULING_CUSTOMIZATION_FEATURE, false);
|
|
40
|
+
export const SCC = create('rancher-scc-registration-extension', true);
|
|
40
41
|
|
|
41
42
|
// Not currently used.. no point defining ones we don't use
|
|
42
43
|
// export const EMBEDDED_CLUSTER_API = create('embedded-cluster-api', true);
|
package/store/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { BACK_TO } from '@shell/config/local-storage';
|
|
|
2
2
|
import { setBrand, setVendor } from '@shell/config/private-label';
|
|
3
3
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
4
4
|
import {
|
|
5
|
-
LOGGED_OUT, IS_SSO, IS_SLO, TIMED_OUT, UPGRADED, _FLAGGED
|
|
5
|
+
LOGGED_OUT, IS_SSO, IS_SLO, TIMED_OUT, UPGRADED, _FLAGGED, IS_SESSION_IDLE
|
|
6
6
|
} from '@shell/config/query-params';
|
|
7
7
|
import { SETTING } from '@shell/config/settings';
|
|
8
8
|
import {
|
|
@@ -41,6 +41,7 @@ import { markRaw } from 'vue';
|
|
|
41
41
|
import paginationUtils from '@shell/utils/pagination-utils';
|
|
42
42
|
import { addReleaseNotesNotification } from '@shell/utils/release-notes';
|
|
43
43
|
import sideNavService from '@shell/components/nav/TopLevelMenu.helper';
|
|
44
|
+
import { fetchAndProcessDynamicContent } from '@shell/utils/dynamic-content';
|
|
44
45
|
|
|
45
46
|
// Disables strict mode for all store instances to prevent warning about changing state outside of mutations
|
|
46
47
|
// because it's more efficient to do that sometimes.
|
|
@@ -890,6 +891,8 @@ export const actions = {
|
|
|
890
891
|
// Add the notification for the release notes
|
|
891
892
|
if (isRancher) {
|
|
892
893
|
await addReleaseNotesNotification(dispatch, getters);
|
|
894
|
+
|
|
895
|
+
fetchAndProcessDynamicContent(dispatch, getters, this.$axios);
|
|
893
896
|
}
|
|
894
897
|
|
|
895
898
|
if (systemNamespaces) {
|
|
@@ -1168,7 +1171,7 @@ export const actions = {
|
|
|
1168
1171
|
}
|
|
1169
1172
|
},
|
|
1170
1173
|
|
|
1171
|
-
async onLogout(store) {
|
|
1174
|
+
async onLogout(store, options = {}) {
|
|
1172
1175
|
const { dispatch, commit, state } = store;
|
|
1173
1176
|
|
|
1174
1177
|
store.dispatch('gcStopIntervals');
|
|
@@ -1210,7 +1213,10 @@ export const actions = {
|
|
|
1210
1213
|
window.localStorage.setItem(BACK_TO, window.location.href);
|
|
1211
1214
|
}
|
|
1212
1215
|
|
|
1213
|
-
let QUERY = (LOGGED_OUT in route.query) ? LOGGED_OUT : TIMED_OUT;
|
|
1216
|
+
let QUERY = (LOGGED_OUT in route.query) || options.sessionIdle ? LOGGED_OUT : TIMED_OUT;
|
|
1217
|
+
|
|
1218
|
+
// adds IS_SESSION_IDLE query param to login route if logout came from a session idle (check auth/logout action)
|
|
1219
|
+
QUERY += options.sessionIdle ? `&${ IS_SESSION_IDLE }` : '';
|
|
1214
1220
|
|
|
1215
1221
|
// adds IS_SSO query param to login route if logout came with an auth provider enabled
|
|
1216
1222
|
QUERY += (IS_SSO in route.query) ? `&${ IS_SSO }` : '';
|