@rancher/shell 3.0.1-rc.4 → 3.0.2-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/data/aws-regions.json +1 -0
- package/assets/styles/base/_basic.scss +22 -5
- package/assets/styles/base/_mixins.scss +10 -1
- package/assets/styles/global/_button.scss +15 -0
- package/assets/styles/global/_form.scss +2 -2
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +2 -0
- package/assets/translations/en-us.yaml +60 -16
- package/assets/translations/zh-hans.yaml +2 -2
- package/chart/monitoring/StorageClassSelector.vue +1 -1
- package/components/ActionMenu.vue +8 -0
- package/components/AssignTo.vue +1 -0
- package/components/AsyncButton.vue +9 -2
- package/components/BackLink.vue +8 -2
- package/components/BannerGraphic.vue +10 -0
- package/components/ButtonGroup.vue +2 -0
- package/components/ButtonMultiAction.vue +6 -0
- package/components/ClusterIconMenu.vue +1 -1
- package/components/CodeMirror.vue +28 -1
- package/components/CommunityLinks.vue +13 -0
- package/components/CruResource.vue +6 -0
- package/components/GrowlManager.vue +14 -4
- package/components/LocaleSelector.vue +49 -5
- package/components/PaginatedResourceTable.vue +136 -0
- package/components/ResourceDetail/Masthead.vue +11 -4
- package/components/ResourceList/index.vue +5 -4
- package/components/ResourceTable.vue +7 -2
- package/components/SortableTable/THead.vue +19 -4
- package/components/SortableTable/index.vue +21 -15
- package/components/SortableTable/selection.js +19 -5
- package/components/Tabbed/index.vue +35 -2
- package/components/YamlEditor.vue +2 -1
- package/components/auth/SelectPrincipal.vue +1 -1
- package/components/fleet/FleetBundles.vue +2 -1
- package/components/form/LabeledSelect.vue +20 -7
- package/components/form/NodeScheduling.vue +5 -1
- package/components/form/Password.vue +23 -13
- package/components/form/ResourceLabeledSelect.vue +3 -3
- package/components/form/ResourceTabs/index.vue +0 -23
- package/components/form/Select.vue +28 -6
- package/components/form/SelectOrCreateAuthSecret.vue +39 -11
- package/components/form/Taints.vue +1 -1
- package/components/form/__tests__/NodeScheduling.test.ts +44 -0
- package/components/formatter/Endpoints.vue +1 -1
- package/components/formatter/LiveExpiryDate.vue +5 -1
- package/components/formatter/ServiceTargets.vue +1 -1
- package/components/formatter/ServiceType.vue +19 -17
- package/components/nav/Pinned.vue +6 -1
- package/components/nav/TopLevelMenu.helper.ts +562 -0
- package/components/nav/TopLevelMenu.vue +268 -168
- package/components/nav/__tests__/TopLevelMenu.test.ts +338 -326
- package/config/pagination-table-headers.js +13 -5
- package/config/product/apps.js +63 -30
- package/config/product/explorer.js +184 -17
- package/config/product/settings.js +9 -1
- package/config/router/routes.js +1 -2
- package/config/settings.ts +32 -2
- package/config/table-headers.js +23 -15
- package/config/types.js +2 -1
- package/core/plugin.ts +8 -1
- package/core/types-provisioning.ts +5 -0
- package/core/types.ts +26 -1
- package/dialog/DrainNode.vue +6 -6
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +12 -3
- package/edit/catalog.cattle.io.clusterrepo.vue +95 -52
- package/edit/fleet.cattle.io.gitrepo.vue +40 -33
- package/edit/provisioning.cattle.io.cluster/index.vue +8 -3
- package/edit/provisioning.cattle.io.cluster/rke2.vue +13 -2
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +10 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +8 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +6 -3
- package/edit/workload/mixins/workload.js +15 -7
- package/list/catalog.cattle.io.app.vue +4 -11
- package/list/catalog.cattle.io.clusterrepo.vue +59 -25
- package/list/fleet.cattle.io.bundle.vue +2 -2
- package/list/management.cattle.io.feature.vue +12 -5
- package/list/management.cattle.io.setting.vue +30 -19
- package/list/namespace.vue +4 -1
- package/list/networking.k8s.io.ingress.vue +14 -11
- package/list/node.vue +72 -67
- package/list/persistentvolume.vue +55 -20
- package/list/persistentvolumeclaim.vue +3 -15
- package/list/service.vue +16 -21
- package/list/workload.vue +35 -49
- package/mixins/resource-fetch-api-pagination.js +40 -5
- package/mixins/resource-fetch.js +56 -6
- package/mixins/vue-select-overrides.js +10 -16
- package/models/management.cattle.io.cluster.js +6 -1
- package/models/management.cattle.io.nodepool.js +5 -4
- package/models/persistentvolume.js +1 -3
- package/models/provisioning.cattle.io.cluster.js +2 -10
- package/models/storage.k8s.io.storageclass.js +4 -0
- package/package.json +32 -33
- package/pages/about.vue +22 -0
- package/pages/c/_cluster/explorer/EventsTable.vue +58 -16
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +36 -24
- package/pages/c/_cluster/explorer/index.vue +103 -75
- package/pages/c/_cluster/settings/performance.vue +49 -23
- package/pages/home.vue +331 -125
- package/pages/support/index.vue +1 -1
- package/plugins/dashboard-store/__tests__/mutations.test.ts +2 -0
- package/plugins/dashboard-store/actions.js +29 -19
- package/plugins/dashboard-store/getters.js +5 -2
- package/plugins/dashboard-store/mutations.js +4 -2
- package/plugins/floating-vue.js +1 -1
- package/plugins/steve/__tests__/mutations.test.ts +2 -1
- package/plugins/steve/steve-pagination-utils.ts +107 -14
- package/plugins/steve/subscribe.js +22 -8
- package/rancher-components/Banner/Banner.vue +12 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -5
- package/rancher-components/Form/Radio/RadioButton.vue +0 -6
- package/rancher-components/Form/Radio/RadioGroup.vue +5 -1
- package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +2 -2
- package/scripts/extension/parse-tag-name +2 -0
- package/scripts/test-plugins-build.sh +21 -5
- package/scripts/typegen.sh +1 -0
- package/store/index.js +47 -9
- package/store/type-map.utils.ts +14 -1
- package/tsconfig.json +7 -1
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +1403 -1523
- package/types/store/dashboard-store.types.ts +4 -0
- package/types/store/pagination.types.ts +13 -0
- package/types/store/vuex.d.ts +9 -1
- package/types/vue-shim.d.ts +3 -34
- package/utils/cluster.js +92 -1
- package/utils/pagination-utils.ts +17 -8
- package/utils/pagination-wrapper.ts +70 -0
- package/utils/string.js +6 -0
- package/utils/uiplugins.ts +18 -4
- package/vue.config.js +3 -4
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
|
|
3
|
-
import SortableTable from '@shell/components/SortableTable';
|
|
4
3
|
import { MESSAGE, NAME, OBJECT, REASON } from '@shell/config/table-headers';
|
|
5
4
|
import { EVENT } from '@shell/config/types';
|
|
6
|
-
import
|
|
5
|
+
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
|
|
6
|
+
import { STEVE_EVENT_OBJECT, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
|
|
7
|
+
import { headerFromSchemaColString } from '@shell/store/type-map.utils';
|
|
8
|
+
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
7
9
|
|
|
8
10
|
export default {
|
|
9
|
-
components: {
|
|
10
|
-
|
|
11
|
-
async fetch() {
|
|
12
|
-
this.events = await fetchClusterResources(this.$store, EVENT);
|
|
13
|
-
},
|
|
11
|
+
components: { PaginatedResourceTable },
|
|
14
12
|
|
|
15
13
|
data() {
|
|
16
14
|
const reason = {
|
|
@@ -23,8 +21,7 @@ export default {
|
|
|
23
21
|
reason,
|
|
24
22
|
OBJECT,
|
|
25
23
|
MESSAGE,
|
|
26
|
-
NAME,
|
|
27
|
-
{
|
|
24
|
+
NAME, {
|
|
28
25
|
name: 'date',
|
|
29
26
|
label: 'Date',
|
|
30
27
|
labelKey: 'clusterIndexPage.sections.events.date.label',
|
|
@@ -36,9 +33,36 @@ export default {
|
|
|
36
33
|
},
|
|
37
34
|
];
|
|
38
35
|
|
|
36
|
+
const schema = this.$store.getters['cluster/schemaFor'](EVENT);
|
|
37
|
+
|
|
38
|
+
const paginationHeaders = [
|
|
39
|
+
reason,
|
|
40
|
+
STEVE_EVENT_OBJECT,
|
|
41
|
+
MESSAGE,
|
|
42
|
+
{
|
|
43
|
+
...STEVE_NAME_COL,
|
|
44
|
+
defaultSort: false,
|
|
45
|
+
},
|
|
46
|
+
headerFromSchemaColString('First Seen', schema, this.$store.getters, true),
|
|
47
|
+
{
|
|
48
|
+
...headerFromSchemaColString('Last Seen', schema, this.$store.getters, true),
|
|
49
|
+
defaultSort: true,
|
|
50
|
+
},
|
|
51
|
+
headerFromSchemaColString('Count', schema, this.$store.getters, true),
|
|
52
|
+
];
|
|
53
|
+
|
|
39
54
|
return {
|
|
40
|
-
|
|
55
|
+
schema,
|
|
56
|
+
events: [],
|
|
41
57
|
eventHeaders,
|
|
58
|
+
paginationHeaders,
|
|
59
|
+
allEventsLink: {
|
|
60
|
+
name: 'c-cluster-product-resource',
|
|
61
|
+
params: {
|
|
62
|
+
product: EXPLORER,
|
|
63
|
+
resource: EVENT,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
42
66
|
};
|
|
43
67
|
},
|
|
44
68
|
|
|
@@ -63,16 +87,34 @@ export default {
|
|
|
63
87
|
</script>
|
|
64
88
|
|
|
65
89
|
<template>
|
|
66
|
-
<
|
|
67
|
-
:
|
|
68
|
-
:rows="events"
|
|
90
|
+
<PaginatedResourceTable
|
|
91
|
+
:schema="schema"
|
|
69
92
|
:headers="eventHeaders"
|
|
93
|
+
:pagination-headers="paginationHeaders"
|
|
94
|
+
|
|
70
95
|
key-field="id"
|
|
71
96
|
:search="false"
|
|
72
97
|
:table-actions="false"
|
|
73
98
|
:row-actions="false"
|
|
74
|
-
:
|
|
99
|
+
:groupable="false"
|
|
75
100
|
:rows-per-page="10"
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
>
|
|
102
|
+
<template v-slot:header-right>
|
|
103
|
+
<router-link
|
|
104
|
+
data-testid="events-link"
|
|
105
|
+
:to="allEventsLink"
|
|
106
|
+
class="events-link"
|
|
107
|
+
>
|
|
108
|
+
<span>{{ t('glance.eventsTable') }}</span>
|
|
109
|
+
</router-link>
|
|
110
|
+
</template>
|
|
111
|
+
</PaginatedResourceTable>
|
|
78
112
|
</template>
|
|
113
|
+
|
|
114
|
+
<style lang="scss" scoped>
|
|
115
|
+
.events-link {
|
|
116
|
+
align-self: center;
|
|
117
|
+
padding-right: 20px;
|
|
118
|
+
min-width: 200px;
|
|
119
|
+
}
|
|
120
|
+
</style>
|
|
@@ -99,7 +99,7 @@ describe('page: cluster dashboard', () => {
|
|
|
99
99
|
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
|
|
100
100
|
]]
|
|
101
101
|
])('%p cluster - %p agent health box :', (_, agentId, isLocal, agentResources, statuses) => {
|
|
102
|
-
it.each(statuses)('should
|
|
102
|
+
it.each(statuses)('should NOT show %p status due to missing canList permissions', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
|
|
103
103
|
const options = clone(mountOptions);
|
|
104
104
|
|
|
105
105
|
options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
|
|
@@ -138,41 +138,48 @@ describe('page: cluster dashboard', () => {
|
|
|
138
138
|
|
|
139
139
|
describe.each([
|
|
140
140
|
['local', 'fleet', true, ['fleetDeployment', 'fleetStatefulSet'], [
|
|
141
|
-
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
|
|
142
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
|
|
143
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
|
|
144
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
|
|
145
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
|
|
146
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
|
|
147
|
-
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
|
|
141
|
+
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, false, '', 0, 0],
|
|
142
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, false, [{ status: 'False' }], 0, 0],
|
|
143
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, true, [{ status: 'True' }], 0, 0],
|
|
144
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, true, false, [{ status: 'True' }], 0, 0],
|
|
145
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 0],
|
|
146
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 1],
|
|
147
|
+
[STATES_ENUM.HEALTHY, 'icon-checkmark', false, true, false, false, [{ status: 'True' }], 1, 0],
|
|
148
148
|
]],
|
|
149
149
|
['downstream RKE2', 'fleet', false, ['fleetStatefulSet'], [
|
|
150
|
-
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
|
|
151
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
|
|
152
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
|
|
153
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
|
|
154
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
|
|
155
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
|
|
156
|
-
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
|
|
150
|
+
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, false, '', 0, 0],
|
|
151
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, false, [{ status: 'False' }], 0, 0],
|
|
152
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, true, [{ status: 'True' }], 0, 0],
|
|
153
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, true, false, [{ status: 'True' }], 0, 0],
|
|
154
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 0],
|
|
155
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 1],
|
|
156
|
+
[STATES_ENUM.HEALTHY, 'icon-checkmark', false, true, false, false, [{ status: 'True' }], 1, 0],
|
|
157
157
|
]],
|
|
158
158
|
['downstream RKE2', 'cattle', false, ['cattleDeployment'], [
|
|
159
|
-
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
|
|
160
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
|
|
161
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
|
|
162
|
-
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
|
|
163
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
|
|
164
|
-
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
|
|
165
|
-
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
|
|
159
|
+
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, false, '', 0, 0],
|
|
160
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, false, [{ status: 'False' }], 0, 0],
|
|
161
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, true, false, [{ status: 'True' }], 0, 0],
|
|
162
|
+
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, true, [{ status: 'True' }], 0, 0],
|
|
163
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 0],
|
|
164
|
+
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, false, [{ status: 'True' }], 0, 1],
|
|
165
|
+
[STATES_ENUM.HEALTHY, 'icon-checkmark', false, true, false, false, [{ status: 'True' }], 1, 0],
|
|
166
166
|
]]
|
|
167
167
|
])('%p cluster - %p agent health box ::', (_, agentId, isLocal, agentResources, statuses) => {
|
|
168
|
-
it.each(statuses)('should show %p status', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
|
|
168
|
+
it.each(statuses)('should show %p status', async(status, iconClass, clickable, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
|
|
169
|
+
let agentRoute = null;
|
|
170
|
+
|
|
169
171
|
const options = clone(mountOptions);
|
|
170
172
|
|
|
171
173
|
options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
|
|
172
174
|
|
|
173
|
-
// let's pass the canList now
|
|
174
175
|
options.global.mocks.$store.getters['cluster/canList'] = (type: string) => !!(type === WORKLOAD_TYPES.DEPLOYMENT) || !!(type === WORKLOAD_TYPES.STATEFUL_SET);
|
|
175
176
|
|
|
177
|
+
options.global.mocks.$router = {
|
|
178
|
+
push: (route: any) => {
|
|
179
|
+
agentRoute = route;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
176
183
|
const resources = agentResources.reduce((acc, r) => {
|
|
177
184
|
const agent = {
|
|
178
185
|
metadata: { state: { error } },
|
|
@@ -204,7 +211,12 @@ describe('page: cluster dashboard', () => {
|
|
|
204
211
|
|
|
205
212
|
expect(box.element).toBeDefined();
|
|
206
213
|
expect(box.element.classList).toContain(status);
|
|
214
|
+
expect(!!(box.element as any).$_popper).toBe(clickable);
|
|
207
215
|
expect(icon.element.classList).toContain(iconClass);
|
|
216
|
+
|
|
217
|
+
await box.trigger('click');
|
|
218
|
+
|
|
219
|
+
expect(!!agentRoute).toBe(clickable);
|
|
208
220
|
});
|
|
209
221
|
});
|
|
210
222
|
|
|
@@ -125,6 +125,13 @@ export default {
|
|
|
125
125
|
ROLES,
|
|
126
126
|
];
|
|
127
127
|
|
|
128
|
+
const clusterServiceIcons = {
|
|
129
|
+
[STATES_ENUM.IN_PROGRESS]: 'icon-spinner icon-spin',
|
|
130
|
+
[STATES_ENUM.HEALTHY]: 'icon-checkmark',
|
|
131
|
+
[STATES_ENUM.WARNING]: 'icon-warning',
|
|
132
|
+
[STATES_ENUM.UNHEALTHY]: 'icon-warning',
|
|
133
|
+
};
|
|
134
|
+
|
|
128
135
|
return {
|
|
129
136
|
nodeHeaders,
|
|
130
137
|
constraints: [],
|
|
@@ -148,6 +155,8 @@ export default {
|
|
|
148
155
|
clusterCounts,
|
|
149
156
|
selectedTab: 'cluster-events',
|
|
150
157
|
extensionCards: getApplicableExtensionEnhancements(this, ExtensionPoint.CARD, CardLocation.CLUSTER_DASHBOARD_CARD, this.$route),
|
|
158
|
+
canViewEvents: !!this.$store.getters['cluster/schemaFor'](EVENT),
|
|
159
|
+
clusterServiceIcons,
|
|
151
160
|
};
|
|
152
161
|
},
|
|
153
162
|
|
|
@@ -283,52 +292,51 @@ export default {
|
|
|
283
292
|
clusterServices() {
|
|
284
293
|
const services = [];
|
|
285
294
|
|
|
286
|
-
CLUSTER_COMPONENTS.forEach((
|
|
295
|
+
CLUSTER_COMPONENTS.forEach((name) => {
|
|
296
|
+
const component = this.getComponentStatus(name);
|
|
297
|
+
|
|
287
298
|
services.push({
|
|
288
|
-
name
|
|
289
|
-
status:
|
|
290
|
-
labelKey: `clusterIndexPage.sections.componentStatus.${
|
|
299
|
+
name,
|
|
300
|
+
status: component.state,
|
|
301
|
+
labelKey: `clusterIndexPage.sections.componentStatus.component.${ name }.label`,
|
|
302
|
+
icon: this.clusterServiceIcons[component.state],
|
|
303
|
+
tooltip: component.tooltip,
|
|
304
|
+
goTo: () => null,
|
|
291
305
|
});
|
|
292
306
|
});
|
|
293
307
|
|
|
294
308
|
if (this.cattleAgentNamespace) {
|
|
295
309
|
services.push({
|
|
296
310
|
name: 'cattle',
|
|
297
|
-
status: this.
|
|
298
|
-
labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
|
|
311
|
+
status: this.cattleAgent.state,
|
|
312
|
+
labelKey: 'clusterIndexPage.sections.componentStatus.component.cattle.label',
|
|
313
|
+
icon: this.clusterServiceIcons[this.cattleAgent.state],
|
|
314
|
+
tooltip: this.cattleAgent.tooltip,
|
|
315
|
+
goTo: () => this.goToClusterService(this.cattleAgent),
|
|
299
316
|
});
|
|
300
317
|
}
|
|
301
318
|
|
|
302
319
|
if (this.fleetAgentNamespace) {
|
|
303
320
|
services.push({
|
|
304
321
|
name: 'fleet',
|
|
305
|
-
status: this.
|
|
306
|
-
labelKey: 'clusterIndexPage.sections.componentStatus.fleet',
|
|
322
|
+
status: this.fleetAgent.state,
|
|
323
|
+
labelKey: 'clusterIndexPage.sections.componentStatus.component.fleet.label',
|
|
324
|
+
icon: this.clusterServiceIcons[this.fleetAgent.state],
|
|
325
|
+
tooltip: this.fleetAgent.tooltip,
|
|
326
|
+
goTo: () => this.goToClusterService(this.fleetAgent),
|
|
307
327
|
});
|
|
308
328
|
}
|
|
309
329
|
|
|
310
330
|
return services;
|
|
311
331
|
},
|
|
312
332
|
|
|
313
|
-
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
if (resource === 'loading') {
|
|
317
|
-
return STATES_ENUM.IN_PROGRESS;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (!resource || this.disconnected || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
|
|
321
|
-
return STATES_ENUM.UNHEALTHY;
|
|
322
|
-
}
|
|
333
|
+
cattleAgent() {
|
|
334
|
+
const resources = [this.cattleDeployment];
|
|
323
335
|
|
|
324
|
-
|
|
325
|
-
return STATES_ENUM.WARNING;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return STATES_ENUM.HEALTHY;
|
|
336
|
+
return this.getAgentStatus(resources, { checkDisconnected: true });
|
|
329
337
|
},
|
|
330
338
|
|
|
331
|
-
|
|
339
|
+
fleetAgent() {
|
|
332
340
|
const resources = this.currentCluster.isLocal ? [
|
|
333
341
|
/**
|
|
334
342
|
* 'fleetStatefulSet' could take a while to be created by rancher.
|
|
@@ -339,23 +347,7 @@ export default {
|
|
|
339
347
|
this.fleetStatefulSet
|
|
340
348
|
];
|
|
341
349
|
|
|
342
|
-
|
|
343
|
-
return STATES_ENUM.IN_PROGRESS;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
for (const resource of resources) {
|
|
347
|
-
if (!resource || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
|
|
348
|
-
return STATES_ENUM.UNHEALTHY;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
for (const resource of resources) {
|
|
353
|
-
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
|
|
354
|
-
return STATES_ENUM.WARNING;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
return STATES_ENUM.HEALTHY;
|
|
350
|
+
return this.getAgentStatus(resources);
|
|
359
351
|
},
|
|
360
352
|
|
|
361
353
|
totalCountGaugeInput() {
|
|
@@ -482,16 +474,6 @@ export default {
|
|
|
482
474
|
return !!this.currentCluster?.spec?.description;
|
|
483
475
|
},
|
|
484
476
|
|
|
485
|
-
allEventsLink() {
|
|
486
|
-
return {
|
|
487
|
-
name: 'c-cluster-product-resource',
|
|
488
|
-
params: {
|
|
489
|
-
product: EXPLORER,
|
|
490
|
-
resource: EVENT,
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
},
|
|
494
|
-
|
|
495
477
|
allSecretsLink() {
|
|
496
478
|
return {
|
|
497
479
|
name: 'c-cluster-product-resource',
|
|
@@ -532,25 +514,61 @@ export default {
|
|
|
532
514
|
}
|
|
533
515
|
},
|
|
534
516
|
|
|
517
|
+
getAgentStatus(resources, opt = { checkDisconnected: false }) {
|
|
518
|
+
if (resources.find((resource) => resource === 'loading')) {
|
|
519
|
+
return { state: STATES_ENUM.IN_PROGRESS };
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
for (const resource of resources) {
|
|
523
|
+
if (
|
|
524
|
+
!resource ||
|
|
525
|
+
(opt.checkDisconnected && this.disconnected) || // cattle
|
|
526
|
+
resource.status.conditions?.find((c) => c.status !== 'True') ||
|
|
527
|
+
resource.metadata.state?.error
|
|
528
|
+
) {
|
|
529
|
+
return {
|
|
530
|
+
resource,
|
|
531
|
+
tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.disconnected`),
|
|
532
|
+
state: STATES_ENUM.UNHEALTHY,
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
for (const resource of resources) {
|
|
538
|
+
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
|
|
539
|
+
return {
|
|
540
|
+
resource,
|
|
541
|
+
tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.unavailableReplicas`),
|
|
542
|
+
state: STATES_ENUM.WARNING,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
548
|
+
},
|
|
549
|
+
|
|
535
550
|
getComponentStatus(field) {
|
|
536
551
|
const matching = (this.currentCluster?.status?.componentStatuses || []).filter((s) => s.name.startsWith(field));
|
|
537
552
|
|
|
538
553
|
// If there's no matching component status, it's "healthy"
|
|
539
554
|
if ( !matching.length ) {
|
|
540
|
-
return STATES_ENUM.HEALTHY;
|
|
555
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
541
556
|
}
|
|
542
557
|
|
|
543
|
-
const
|
|
544
|
-
const
|
|
558
|
+
const errorConditions = matching.reduce((acc, status) => {
|
|
559
|
+
const condition = status.conditions.find((c) => c.status !== 'True');
|
|
545
560
|
|
|
546
|
-
return !
|
|
547
|
-
},
|
|
561
|
+
return !condition ? acc : [...acc, condition];
|
|
562
|
+
}, []);
|
|
548
563
|
|
|
549
|
-
if (
|
|
550
|
-
return
|
|
564
|
+
if (errorConditions.length > 0) {
|
|
565
|
+
return {
|
|
566
|
+
tooltip: errorConditions[0].message,
|
|
567
|
+
state: STATES_ENUM.UNHEALTHY
|
|
568
|
+
};
|
|
551
569
|
}
|
|
552
570
|
|
|
553
|
-
return STATES_ENUM.HEALTHY;
|
|
571
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
554
572
|
},
|
|
555
573
|
|
|
556
574
|
showActions() {
|
|
@@ -578,6 +596,23 @@ export default {
|
|
|
578
596
|
await provCluster.goToHarvesterCluster();
|
|
579
597
|
} catch {
|
|
580
598
|
}
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
goToClusterService(agent) {
|
|
602
|
+
if (!agent.resource || agent.state === STATES_ENUM.HEALTHY) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
this.$router.push({
|
|
607
|
+
name: 'c-cluster-product-resource-namespace-id',
|
|
608
|
+
params: {
|
|
609
|
+
cluster: this.currentCluster.id,
|
|
610
|
+
product: 'explorer',
|
|
611
|
+
resource: agent.resource.type,
|
|
612
|
+
namespace: agent.resource.metadata.namespace,
|
|
613
|
+
id: agent.resource.metadata.name,
|
|
614
|
+
}
|
|
615
|
+
});
|
|
581
616
|
}
|
|
582
617
|
},
|
|
583
618
|
};
|
|
@@ -722,21 +757,15 @@ export default {
|
|
|
722
757
|
<div
|
|
723
758
|
v-for="(service, i) in clusterServices"
|
|
724
759
|
:key="i"
|
|
760
|
+
v-clean-tooltip="service.tooltip"
|
|
725
761
|
class="k8s-service-status"
|
|
726
762
|
:class="{[service.status]: true }"
|
|
727
763
|
:data-testid="`k8s-service-${ service.name }`"
|
|
764
|
+
@click="service.goTo"
|
|
728
765
|
>
|
|
729
766
|
<i
|
|
730
|
-
|
|
731
|
-
class="icon
|
|
732
|
-
/>
|
|
733
|
-
<i
|
|
734
|
-
v-else-if="service.status === STATES_ENUM.HEALTHY"
|
|
735
|
-
class="icon icon-checkmark"
|
|
736
|
-
/>
|
|
737
|
-
<i
|
|
738
|
-
v-else
|
|
739
|
-
class="icon icon-warning"
|
|
767
|
+
class="icon"
|
|
768
|
+
:class="service.icon"
|
|
740
769
|
/>
|
|
741
770
|
<div class="label">
|
|
742
771
|
{{ t(service.labelKey) }}
|
|
@@ -747,15 +776,11 @@ export default {
|
|
|
747
776
|
<div class="mt-30">
|
|
748
777
|
<Tabbed @changed="tabChange">
|
|
749
778
|
<Tab
|
|
779
|
+
v-if="canViewEvents"
|
|
750
780
|
name="cluster-events"
|
|
751
781
|
:label="t('clusterIndexPage.sections.events.label')"
|
|
752
782
|
:weight="2"
|
|
753
783
|
>
|
|
754
|
-
<span class="events-table-link">
|
|
755
|
-
<router-link :to="allEventsLink">
|
|
756
|
-
<span>{{ t('glance.eventsTable') }}</span>
|
|
757
|
-
</router-link>
|
|
758
|
-
</span>
|
|
759
784
|
<EventsTable />
|
|
760
785
|
</Tab>
|
|
761
786
|
<Tab
|
|
@@ -916,7 +941,7 @@ export default {
|
|
|
916
941
|
}
|
|
917
942
|
}
|
|
918
943
|
|
|
919
|
-
.
|
|
944
|
+
.cert-table-link {
|
|
920
945
|
display: flex;
|
|
921
946
|
justify-content: flex-end;
|
|
922
947
|
margin-bottom: 20px;
|
|
@@ -948,6 +973,7 @@ export default {
|
|
|
948
973
|
|
|
949
974
|
&.unhealthy {
|
|
950
975
|
border-color: var(--error-border);
|
|
976
|
+
cursor: pointer;
|
|
951
977
|
|
|
952
978
|
> I {
|
|
953
979
|
color: var(--error)
|
|
@@ -955,6 +981,8 @@ export default {
|
|
|
955
981
|
}
|
|
956
982
|
|
|
957
983
|
&.warning {
|
|
984
|
+
cursor: pointer;
|
|
985
|
+
|
|
958
986
|
> I {
|
|
959
987
|
color: var(--warning)
|
|
960
988
|
}
|
|
@@ -103,17 +103,17 @@ export default {
|
|
|
103
103
|
resources.push(this.t('performance.serverPagination.resources.all'));
|
|
104
104
|
} else {
|
|
105
105
|
settings.resources.enableSome.enabled.forEach((resource) => {
|
|
106
|
-
resources.push(resource);
|
|
106
|
+
resources.push(!!resource.length ? resource : `${ resource.resource } (${ resource.context })`);
|
|
107
107
|
});
|
|
108
108
|
if (settings.resources.enableSome.generic) {
|
|
109
109
|
resources.push(this.t('performance.serverPagination.resources.generic', {}, true));
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
storeResources.push(
|
|
113
|
+
storeResources.push(`Resources in store '${ store }': ${ resources.join(', ') }`);
|
|
114
114
|
});
|
|
115
115
|
|
|
116
|
-
return storeResources.join('
|
|
116
|
+
return storeResources.join('<br><br>');
|
|
117
117
|
}
|
|
118
118
|
},
|
|
119
119
|
|
|
@@ -187,6 +187,13 @@ export default {
|
|
|
187
187
|
body: this.t(`performance.${ l10n[property] }.incompatibleDescription`, {}, true),
|
|
188
188
|
},
|
|
189
189
|
});
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
setPaginationDefaults() {
|
|
193
|
+
this.value = {
|
|
194
|
+
...this.value,
|
|
195
|
+
serverPagination: { ...DEFAULT_PERF_SETTING.serverPagination }
|
|
196
|
+
};
|
|
190
197
|
}
|
|
191
198
|
},
|
|
192
199
|
};
|
|
@@ -202,7 +209,9 @@ export default {
|
|
|
202
209
|
<div class="ui-perf-setting">
|
|
203
210
|
<!-- Server Side Pagination -->
|
|
204
211
|
<div class="mt-40">
|
|
205
|
-
<h2
|
|
212
|
+
<h2 id="ssp-setting">
|
|
213
|
+
{{ t('performance.serverPagination.label') }}
|
|
214
|
+
</h2>
|
|
206
215
|
<p>{{ t('performance.serverPagination.description') }}</p>
|
|
207
216
|
<Banner
|
|
208
217
|
color="error"
|
|
@@ -225,9 +234,17 @@ export default {
|
|
|
225
234
|
<p :class="{ 'text-muted': !value.serverPagination.enabled }">
|
|
226
235
|
{{ t('performance.serverPagination.applicable') }}
|
|
227
236
|
</p>
|
|
228
|
-
<p
|
|
229
|
-
|
|
230
|
-
|
|
237
|
+
<p
|
|
238
|
+
v-clean-html="steveCacheApplicableResources"
|
|
239
|
+
:class="{ 'text-muted': !value.serverPagination.enabled }"
|
|
240
|
+
/>
|
|
241
|
+
<button
|
|
242
|
+
class="btn btn-sm role-primary"
|
|
243
|
+
style="width: fit-content;"
|
|
244
|
+
@click.prevent="setPaginationDefaults()"
|
|
245
|
+
>
|
|
246
|
+
{{ t('performance.serverPagination.populateDefaults') }}
|
|
247
|
+
</button>
|
|
231
248
|
</div>
|
|
232
249
|
<!-- Inactivity -->
|
|
233
250
|
<div class="mt-20">
|
|
@@ -273,6 +290,11 @@ export default {
|
|
|
273
290
|
<!-- Incremental Loading -->
|
|
274
291
|
<div class="mt-40">
|
|
275
292
|
<h2>{{ t('performance.incrementalLoad.label') }}</h2>
|
|
293
|
+
<Banner
|
|
294
|
+
color="warning"
|
|
295
|
+
>
|
|
296
|
+
<span v-clean-html="t(`performance.deprecatedForSSP`, { setting: t('performance.incrementalLoad.label') }, true)" />
|
|
297
|
+
</Banner>
|
|
276
298
|
<p>{{ t('performance.incrementalLoad.description') }}</p>
|
|
277
299
|
<Checkbox
|
|
278
300
|
:value="value.incrementalLoading.enabled"
|
|
@@ -300,11 +322,12 @@ export default {
|
|
|
300
322
|
<!-- Enable manual refresh list views -->
|
|
301
323
|
<div class="mt-40">
|
|
302
324
|
<h2 v-t="'performance.manualRefresh.label'" />
|
|
303
|
-
<p>{{ t('performance.manualRefresh.description') }}</p>
|
|
304
325
|
<Banner
|
|
305
|
-
color="
|
|
306
|
-
|
|
307
|
-
|
|
326
|
+
color="warning"
|
|
327
|
+
>
|
|
328
|
+
<span v-clean-html="t(`performance.deprecatedForSSP`, { setting: t('performance.manualRefresh.label') }, true)" />
|
|
329
|
+
</Banner>
|
|
330
|
+
<p>{{ t('performance.manualRefresh.description') }}</p>
|
|
308
331
|
<Checkbox
|
|
309
332
|
:value="value.manualRefresh.enabled"
|
|
310
333
|
:mode="mode"
|
|
@@ -331,11 +354,12 @@ export default {
|
|
|
331
354
|
<!-- Enable GC of resources from store -->
|
|
332
355
|
<div class="mt-40">
|
|
333
356
|
<h2 v-t="'performance.gc.label'" />
|
|
334
|
-
<p>{{ t('performance.gc.description') }}</p>
|
|
335
357
|
<Banner
|
|
336
|
-
color="
|
|
337
|
-
|
|
338
|
-
|
|
358
|
+
color="warning"
|
|
359
|
+
>
|
|
360
|
+
<span v-clean-html="t(`performance.deprecatedForSSP`, { setting: t('performance.gc.label') }, true)" />
|
|
361
|
+
</Banner>
|
|
362
|
+
<p>{{ t('performance.gc.description') }}</p>
|
|
339
363
|
<Checkbox
|
|
340
364
|
v-model:value="value.garbageCollection.enabled"
|
|
341
365
|
:mode="mode"
|
|
@@ -411,11 +435,12 @@ export default {
|
|
|
411
435
|
<!-- Force NS filter -->
|
|
412
436
|
<div class="mt-40">
|
|
413
437
|
<h2>{{ t('performance.nsFiltering.label') }}</h2>
|
|
414
|
-
<p>{{ t('performance.nsFiltering.description') }}</p>
|
|
415
438
|
<Banner
|
|
416
|
-
color="
|
|
417
|
-
|
|
418
|
-
|
|
439
|
+
color="warning"
|
|
440
|
+
>
|
|
441
|
+
<span v-clean-html="t(`performance.deprecatedForSSP`, { setting: t('performance.nsFiltering.label') }, true)" />
|
|
442
|
+
</Banner>
|
|
443
|
+
<p>{{ t('performance.nsFiltering.description') }}</p>
|
|
419
444
|
<Checkbox
|
|
420
445
|
:value="value.forceNsFilterV2.enabled"
|
|
421
446
|
:mode="mode"
|
|
@@ -428,11 +453,12 @@ export default {
|
|
|
428
453
|
<!-- Advanced Websocket Worker -->
|
|
429
454
|
<div class="mt-40">
|
|
430
455
|
<h2>{{ t('performance.advancedWorker.label') }}</h2>
|
|
431
|
-
<p>{{ t('performance.advancedWorker.description') }}</p>
|
|
432
456
|
<Banner
|
|
433
|
-
color="
|
|
434
|
-
|
|
435
|
-
|
|
457
|
+
color="warning"
|
|
458
|
+
>
|
|
459
|
+
<span v-clean-html="t(`performance.deprecatedForSSP`, { setting: t('performance.advancedWorker.label') }, true)" />
|
|
460
|
+
</Banner>
|
|
461
|
+
<p>{{ t('performance.advancedWorker.description') }}</p>
|
|
436
462
|
<Checkbox
|
|
437
463
|
v-model:value="value.advancedWorker.enabled"
|
|
438
464
|
:mode="mode"
|