@rancher/shell 3.0.1-rc.3 → 3.0.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 +5 -0
- package/assets/styles/base/_mixins.scss +8 -0
- package/assets/styles/global/_button.scss +5 -0
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +2 -0
- package/assets/translations/en-us.yaml +40 -22
- package/assets/translations/zh-hans.yaml +1 -7
- package/chart/monitoring/StorageClassSelector.vue +1 -1
- package/components/AssignTo.vue +1 -0
- package/components/AsyncButton.vue +1 -0
- package/components/BackLink.vue +8 -2
- package/components/PaginatedResourceTable.vue +135 -0
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +66 -11
- package/components/ResourceList/index.vue +0 -1
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +0 -53
- package/components/SortableTable/index.vue +8 -6
- package/components/Tabbed/index.vue +35 -2
- package/components/form/ResourceLabeledSelect.vue +2 -2
- package/components/form/ResourceTabs/index.vue +0 -23
- package/components/form/Taints.vue +1 -1
- package/components/form/UnitInput.vue +1 -1
- package/components/form/__tests__/UnitInput.test.ts +1 -1
- package/components/nav/TopLevelMenu.helper.ts +546 -0
- package/components/nav/TopLevelMenu.vue +125 -160
- package/components/nav/WindowManager/ContainerShell.vue +13 -4
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +20 -18
- package/components/nav/__tests__/TopLevelMenu.test.ts +338 -326
- package/composables/useLabeledFormElement.ts +6 -2
- package/config/pagination-table-headers.js +4 -4
- package/config/product/explorer.js +2 -0
- package/config/router/navigation-guards/index.js +1 -2
- package/config/router/routes.js +1 -1
- package/config/settings.ts +15 -8
- 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/catalog.cattle.io.clusterrepo.vue +95 -52
- package/edit/provisioning.cattle.io.cluster/index.vue +8 -3
- package/edit/workload/index.vue +1 -1
- package/edit/workload/storage/csi/index.vue +29 -1
- package/edit/workload/storage/index.vue +1 -0
- package/initialize/App.vue +3 -10
- package/initialize/install-plugins.js +1 -2
- package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +6 -2
- package/list/node.vue +8 -5
- package/mixins/resource-fetch-api-pagination.js +40 -5
- package/mixins/resource-fetch.js +48 -5
- package/models/management.cattle.io.nodepool.js +5 -4
- package/models/nodedriver.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +3 -11
- package/package.json +7 -8
- package/pages/about.vue +22 -0
- package/pages/auth/setup.vue +7 -28
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +36 -24
- package/pages/c/_cluster/explorer/index.vue +100 -59
- package/pages/home.vue +308 -123
- 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/steve/__tests__/mutations.test.ts +2 -1
- package/plugins/steve/steve-pagination-utils.ts +25 -2
- package/plugins/steve/subscribe.js +22 -8
- package/rancher-components/Banner/Banner.vue +1 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +2 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
- package/rancher-components/Form/Radio/RadioButton.vue +2 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +2 -0
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +2 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +3 -0
- package/rancher-components/StringList/StringList.test.ts +15 -15
- package/rancher-components/StringList/StringList.vue +3 -0
- package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +0 -2
- package/scripts/extension/parse-tag-name +2 -0
- package/scripts/test-plugins-build.sh +4 -2
- package/store/index.js +31 -9
- package/tsconfig.json +7 -1
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +1107 -1276
- package/types/store/dashboard-store.types.ts +4 -0
- package/types/store/pagination.types.ts +13 -0
- package/types/store/vuex.d.ts +8 -0
- package/types/vue-shim.d.ts +6 -31
- package/utils/cluster.js +92 -1
- package/utils/pagination-utils.ts +17 -8
- package/utils/pagination-wrapper.ts +70 -0
- package/utils/uiplugins.ts +307 -0
- package/components/templates/error.vue +0 -131
- package/config/router/navigation-guards/history.js +0 -13
- package/plugins/back-button.js +0 -3
|
@@ -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,7 @@ export default {
|
|
|
148
155
|
clusterCounts,
|
|
149
156
|
selectedTab: 'cluster-events',
|
|
150
157
|
extensionCards: getApplicableExtensionEnhancements(this, ExtensionPoint.CARD, CardLocation.CLUSTER_DASHBOARD_CARD, this.$route),
|
|
158
|
+
clusterServiceIcons,
|
|
151
159
|
};
|
|
152
160
|
},
|
|
153
161
|
|
|
@@ -283,52 +291,51 @@ export default {
|
|
|
283
291
|
clusterServices() {
|
|
284
292
|
const services = [];
|
|
285
293
|
|
|
286
|
-
CLUSTER_COMPONENTS.forEach((
|
|
294
|
+
CLUSTER_COMPONENTS.forEach((name) => {
|
|
295
|
+
const component = this.getComponentStatus(name);
|
|
296
|
+
|
|
287
297
|
services.push({
|
|
288
|
-
name
|
|
289
|
-
status:
|
|
290
|
-
labelKey: `clusterIndexPage.sections.componentStatus.${
|
|
298
|
+
name,
|
|
299
|
+
status: component.state,
|
|
300
|
+
labelKey: `clusterIndexPage.sections.componentStatus.component.${ name }.label`,
|
|
301
|
+
icon: this.clusterServiceIcons[component.state],
|
|
302
|
+
tooltip: component.tooltip,
|
|
303
|
+
goTo: () => null,
|
|
291
304
|
});
|
|
292
305
|
});
|
|
293
306
|
|
|
294
307
|
if (this.cattleAgentNamespace) {
|
|
295
308
|
services.push({
|
|
296
309
|
name: 'cattle',
|
|
297
|
-
status: this.
|
|
298
|
-
labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
|
|
310
|
+
status: this.cattleAgent.state,
|
|
311
|
+
labelKey: 'clusterIndexPage.sections.componentStatus.component.cattle.label',
|
|
312
|
+
icon: this.clusterServiceIcons[this.cattleAgent.state],
|
|
313
|
+
tooltip: this.cattleAgent.tooltip,
|
|
314
|
+
goTo: () => this.goToClusterService(this.cattleAgent),
|
|
299
315
|
});
|
|
300
316
|
}
|
|
301
317
|
|
|
302
318
|
if (this.fleetAgentNamespace) {
|
|
303
319
|
services.push({
|
|
304
320
|
name: 'fleet',
|
|
305
|
-
status: this.
|
|
306
|
-
labelKey: 'clusterIndexPage.sections.componentStatus.fleet',
|
|
321
|
+
status: this.fleetAgent.state,
|
|
322
|
+
labelKey: 'clusterIndexPage.sections.componentStatus.component.fleet.label',
|
|
323
|
+
icon: this.clusterServiceIcons[this.fleetAgent.state],
|
|
324
|
+
tooltip: this.fleetAgent.tooltip,
|
|
325
|
+
goTo: () => this.goToClusterService(this.fleetAgent),
|
|
307
326
|
});
|
|
308
327
|
}
|
|
309
328
|
|
|
310
329
|
return services;
|
|
311
330
|
},
|
|
312
331
|
|
|
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
|
-
}
|
|
323
|
-
|
|
324
|
-
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
|
|
325
|
-
return STATES_ENUM.WARNING;
|
|
326
|
-
}
|
|
332
|
+
cattleAgent() {
|
|
333
|
+
const resources = [this.cattleDeployment];
|
|
327
334
|
|
|
328
|
-
return
|
|
335
|
+
return this.getAgentStatus(resources, { checkDisconnected: true });
|
|
329
336
|
},
|
|
330
337
|
|
|
331
|
-
|
|
338
|
+
fleetAgent() {
|
|
332
339
|
const resources = this.currentCluster.isLocal ? [
|
|
333
340
|
/**
|
|
334
341
|
* 'fleetStatefulSet' could take a while to be created by rancher.
|
|
@@ -339,23 +346,7 @@ export default {
|
|
|
339
346
|
this.fleetStatefulSet
|
|
340
347
|
];
|
|
341
348
|
|
|
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;
|
|
349
|
+
return this.getAgentStatus(resources);
|
|
359
350
|
},
|
|
360
351
|
|
|
361
352
|
totalCountGaugeInput() {
|
|
@@ -532,25 +523,61 @@ export default {
|
|
|
532
523
|
}
|
|
533
524
|
},
|
|
534
525
|
|
|
526
|
+
getAgentStatus(resources, opt = { checkDisconnected: false }) {
|
|
527
|
+
if (resources.find((resource) => resource === 'loading')) {
|
|
528
|
+
return { state: STATES_ENUM.IN_PROGRESS };
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
for (const resource of resources) {
|
|
532
|
+
if (
|
|
533
|
+
!resource ||
|
|
534
|
+
(opt.checkDisconnected && this.disconnected) || // cattle
|
|
535
|
+
resource.status.conditions?.find((c) => c.status !== 'True') ||
|
|
536
|
+
resource.metadata.state?.error
|
|
537
|
+
) {
|
|
538
|
+
return {
|
|
539
|
+
resource,
|
|
540
|
+
tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.disconnected`),
|
|
541
|
+
state: STATES_ENUM.UNHEALTHY,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
for (const resource of resources) {
|
|
547
|
+
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
|
|
548
|
+
return {
|
|
549
|
+
resource,
|
|
550
|
+
tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.unavailableReplicas`),
|
|
551
|
+
state: STATES_ENUM.WARNING,
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
557
|
+
},
|
|
558
|
+
|
|
535
559
|
getComponentStatus(field) {
|
|
536
560
|
const matching = (this.currentCluster?.status?.componentStatuses || []).filter((s) => s.name.startsWith(field));
|
|
537
561
|
|
|
538
562
|
// If there's no matching component status, it's "healthy"
|
|
539
563
|
if ( !matching.length ) {
|
|
540
|
-
return STATES_ENUM.HEALTHY;
|
|
564
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
541
565
|
}
|
|
542
566
|
|
|
543
|
-
const
|
|
544
|
-
const
|
|
567
|
+
const errorConditions = matching.reduce((acc, status) => {
|
|
568
|
+
const condition = status.conditions.find((c) => c.status !== 'True');
|
|
545
569
|
|
|
546
|
-
return !
|
|
547
|
-
},
|
|
570
|
+
return !condition ? acc : [...acc, condition];
|
|
571
|
+
}, []);
|
|
548
572
|
|
|
549
|
-
if (
|
|
550
|
-
return
|
|
573
|
+
if (errorConditions.length > 0) {
|
|
574
|
+
return {
|
|
575
|
+
tooltip: errorConditions[0].message,
|
|
576
|
+
state: STATES_ENUM.UNHEALTHY
|
|
577
|
+
};
|
|
551
578
|
}
|
|
552
579
|
|
|
553
|
-
return STATES_ENUM.HEALTHY;
|
|
580
|
+
return { state: STATES_ENUM.HEALTHY };
|
|
554
581
|
},
|
|
555
582
|
|
|
556
583
|
showActions() {
|
|
@@ -578,6 +605,23 @@ export default {
|
|
|
578
605
|
await provCluster.goToHarvesterCluster();
|
|
579
606
|
} catch {
|
|
580
607
|
}
|
|
608
|
+
},
|
|
609
|
+
|
|
610
|
+
goToClusterService(agent) {
|
|
611
|
+
if (!agent.resource || agent.state === STATES_ENUM.HEALTHY) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
this.$router.push({
|
|
616
|
+
name: 'c-cluster-product-resource-namespace-id',
|
|
617
|
+
params: {
|
|
618
|
+
cluster: this.currentCluster.id,
|
|
619
|
+
product: 'explorer',
|
|
620
|
+
resource: agent.resource.type,
|
|
621
|
+
namespace: agent.resource.metadata.namespace,
|
|
622
|
+
id: agent.resource.metadata.name,
|
|
623
|
+
}
|
|
624
|
+
});
|
|
581
625
|
}
|
|
582
626
|
},
|
|
583
627
|
};
|
|
@@ -722,21 +766,15 @@ export default {
|
|
|
722
766
|
<div
|
|
723
767
|
v-for="(service, i) in clusterServices"
|
|
724
768
|
:key="i"
|
|
769
|
+
v-clean-tooltip="service.tooltip"
|
|
725
770
|
class="k8s-service-status"
|
|
726
771
|
:class="{[service.status]: true }"
|
|
727
772
|
:data-testid="`k8s-service-${ service.name }`"
|
|
773
|
+
@click="service.goTo"
|
|
728
774
|
>
|
|
729
775
|
<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"
|
|
776
|
+
class="icon"
|
|
777
|
+
:class="service.icon"
|
|
740
778
|
/>
|
|
741
779
|
<div class="label">
|
|
742
780
|
{{ t(service.labelKey) }}
|
|
@@ -948,6 +986,7 @@ export default {
|
|
|
948
986
|
|
|
949
987
|
&.unhealthy {
|
|
950
988
|
border-color: var(--error-border);
|
|
989
|
+
cursor: pointer;
|
|
951
990
|
|
|
952
991
|
> I {
|
|
953
992
|
color: var(--error)
|
|
@@ -955,6 +994,8 @@ export default {
|
|
|
955
994
|
}
|
|
956
995
|
|
|
957
996
|
&.warning {
|
|
997
|
+
cursor: pointer;
|
|
998
|
+
|
|
958
999
|
> I {
|
|
959
1000
|
color: var(--warning)
|
|
960
1001
|
}
|