@rancher/shell 3.0.2-rc.5 → 3.0.2
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/providers/nutanix.svg +12 -1
- package/assets/styles/base/_basic.scss +2 -1
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/global/_labeled-input.scss +5 -13
- package/assets/styles/global/_layout.scss +4 -1
- package/assets/styles/global/_select.scss +5 -0
- package/assets/styles/themes/_dark.scss +1 -3
- package/assets/styles/themes/_light.scss +5 -1
- package/assets/translations/en-us.yaml +130 -23
- package/assets/translations/zh-hans.yaml +0 -3
- package/cloud-credential/azure.vue +1 -1
- package/components/ActionMenuShell.vue +105 -0
- package/components/AppModal.vue +2 -2
- package/components/AsyncButton.vue +2 -0
- package/components/ButtonGroup.vue +9 -2
- package/components/ClusterBadge.vue +1 -0
- package/components/ClusterIconMenu.vue +3 -0
- package/components/ClusterProviderIcon.vue +14 -1
- package/components/CodeMirror.vue +96 -5
- package/components/Collapse.vue +16 -3
- package/components/CruResource.vue +9 -0
- package/components/CruResourceFooter.vue +1 -1
- package/components/ExplorerMembers.vue +2 -1
- package/components/FixedBanner.vue +19 -12
- package/components/Import.vue +14 -1
- package/components/LandingPagePreference.vue +4 -2
- package/components/PodSecurityAdmission.vue +8 -6
- package/components/PromptChangePassword.vue +1 -0
- package/components/PromptRemove.vue +23 -21
- package/components/ResourceDetail/Masthead.vue +30 -11
- package/components/ResourceDetail/__tests__/Masthead.test.ts +61 -0
- package/components/ResourceDetail/index.vue +6 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +1 -0
- package/components/Setting.vue +115 -0
- package/components/SortableTable/THead.vue +2 -0
- package/components/SortableTable/index.vue +7 -12
- package/components/StatusBadge.vue +71 -0
- package/components/Tabbed/index.vue +16 -15
- package/components/Wizard.vue +108 -104
- package/components/YamlEditor.vue +12 -2
- package/components/__tests__/Collapse.test.ts +2 -2
- package/components/__tests__/FixedBanner.test.ts +3 -3
- package/components/auth/Principal.vue +29 -17
- package/components/auth/__tests__/Principal.test.ts +40 -0
- package/components/auth/login/ldap.vue +7 -0
- package/components/fleet/FleetBundles.vue +1 -1
- package/components/fleet/FleetRepos.vue +1 -1
- package/components/fleet/FleetResources.vue +0 -2
- package/components/fleet/FleetSummary.vue +60 -65
- package/components/fleet/ForceDirectedTreeChart/index.vue +5 -1
- package/components/fleet/__tests__/FleetSummary.test.ts +49 -9
- package/components/form/ArrayList.vue +6 -2
- package/components/form/ColorInput.vue +1 -0
- package/components/form/KeyValue.vue +11 -12
- package/components/form/LabeledSelect.vue +15 -3
- package/components/form/Labels.vue +8 -1
- package/components/form/Members/MembershipEditor.vue +230 -222
- package/components/form/Members/__tests__/MembershipEditor.test.ts +62 -0
- package/components/form/Password.vue +3 -0
- package/components/form/ProjectMemberEditor.vue +6 -3
- package/components/form/ResourceTabs/index.vue +15 -13
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +5 -4
- package/components/form/SchedulingCustomization.vue +85 -0
- package/components/form/Select.vue +3 -2
- package/components/form/SelectOrCreateAuthSecret.vue +2 -1
- package/components/form/UnitInput.vue +3 -4
- package/components/form/__tests__/ArrayList.test.ts +9 -6
- package/components/form/__tests__/LabeledSelect.test.ts +37 -0
- package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +34 -0
- package/components/form/__tests__/UnitInput.test.ts +4 -5
- package/components/formatter/LiveDate.vue +3 -1
- package/components/formatter/ServiceType.vue +12 -4
- package/components/formatter/WorkloadHealthScale.vue +2 -1
- package/components/nav/Header.vue +35 -2
- package/components/nav/HeaderPageActionMenu.vue +11 -40
- package/components/nav/Jump.vue +8 -2
- package/components/nav/NamespaceFilter.vue +5 -4
- package/components/nav/Pinned.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +5 -5
- package/components/nav/TopLevelMenu.vue +1 -12
- package/components/nav/WindowManager/ContainerLogs.vue +96 -58
- package/components/nav/WindowManager/ContainerShell.vue +99 -18
- package/components/nav/WindowManager/index.vue +74 -6
- package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
- package/components/templates/default.vue +2 -47
- package/config/features.js +1 -0
- package/config/labels-annotations.js +11 -1
- package/config/router/navigation-guards/index.js +2 -1
- package/config/router/navigation-guards/record-last-route.js +24 -0
- package/config/settings.ts +66 -98
- package/config/version.js +1 -1
- package/core/types-provisioning.ts +7 -0
- package/detail/fleet.cattle.io.bundle.vue +7 -0
- package/detail/fleet.cattle.io.cluster.vue +0 -3
- package/detail/fleet.cattle.io.gitrepo.vue +8 -15
- package/detail/provisioning.cattle.io.cluster.vue +8 -2
- package/dialog/DeactivateDriverDialog.vue +5 -5
- package/dialog/GitRepoForceUpdateDialog.vue +132 -0
- package/directives/strip-html-aria-label.js +19 -0
- package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +87 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +217 -37
- package/edit/auth/__tests__/oidc.test.ts +60 -12
- package/edit/auth/ldap/__tests__/config.test.ts +40 -0
- package/edit/auth/ldap/config.vue +67 -89
- package/edit/auth/oidc.vue +16 -2
- package/edit/catalog.cattle.io.clusterrepo.vue +12 -8
- package/edit/cis.cattle.io.clusterscan.vue +13 -1
- package/edit/fleet.cattle.io.gitrepo.vue +198 -72
- package/edit/logging-flow/Match.vue +0 -21
- package/edit/management.cattle.io.project.vue +1 -1
- package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +10 -3
- package/edit/monitoring.coreos.com.prometheusrule/RecordingRule.vue +5 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +5 -2
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +8 -1
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +55 -15
- package/edit/provisioning.cattle.io.cluster/index.vue +28 -30
- package/edit/provisioning.cattle.io.cluster/rke2.vue +64 -13
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +37 -2
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +3 -2
- package/edit/resources.cattle.io.backup.vue +150 -15
- package/edit/secret/__tests__/ssh.test.ts +79 -0
- package/edit/secret/ssh.vue +7 -1
- package/edit/service.vue +0 -3
- package/edit/workload/Job.vue +8 -8
- package/edit/workload/__tests__/Job.test.ts +0 -1
- package/edit/workload/index.vue +3 -1
- package/initialize/install-directives.js +2 -0
- package/initialize/install-plugins.js +6 -1
- package/list/catalog.cattle.io.app.vue +21 -4
- package/list/fleet.cattle.io.bundle.vue +1 -1
- package/list/management.cattle.io.setting.vue +34 -132
- package/list/provisioning.cattle.io.cluster.vue +11 -3
- package/machine-config/vmwarevsphere.vue +15 -8
- package/mixins/__tests__/auth-config.test.ts +74 -0
- package/mixins/__tests__/chart.test.ts +5 -4
- package/mixins/__tests__/create-edit-view.test.ts +38 -0
- package/mixins/auth-config.js +8 -0
- package/mixins/chart.js +2 -2
- package/mixins/create-edit-view/impl.js +4 -1
- package/mixins/vue-select-overrides.js +10 -0
- package/models/__tests__/catalog.cattle.io.app.test.ts +148 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +157 -0
- package/models/__tests__/secret.test.ts +56 -13
- package/models/catalog.cattle.io.app.js +112 -37
- package/models/cluster.js +11 -0
- package/models/fleet.cattle.io.bundle.js +40 -2
- package/models/fleet.cattle.io.gitrepo.js +169 -109
- package/models/management.cattle.io.fleetworkspace.js +4 -0
- package/models/management.cattle.io.kontainerdriver.js +7 -0
- package/models/nodedriver.js +4 -1
- package/models/provisioning.cattle.io.cluster.js +24 -0
- package/models/secret.js +1 -1
- package/package.json +5 -5
- package/pages/auth/login.vue +5 -11
- package/pages/auth/verify.vue +11 -1
- package/pages/c/_cluster/apps/charts/index.vue +6 -4
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/ConfigBadge.vue +3 -5
- package/pages/c/_cluster/explorer/EventsTable.vue +3 -2
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +9 -9
- package/pages/c/_cluster/explorer/index.vue +33 -35
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/fleet/index.vue +0 -5
- package/pages/c/_cluster/legacy/project/index.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +52 -53
- package/pages/c/_cluster/uiplugins/index.vue +19 -22
- package/pages/home.vue +17 -12
- package/pages/prefs.vue +5 -1
- package/plugins/shortkey.js +10 -1
- package/plugins/steve/steve-pagination-utils.ts +58 -8
- package/promptRemove/management.cattle.io.fleetworkspace.vue +98 -0
- package/promptRemove/management.cattle.io.globalrole.vue +1 -1
- package/promptRemove/management.cattle.io.project.vue +2 -8
- package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
- package/promptRemove/mixin/roleDeletionCheck.js +1 -7
- package/promptRemove/pod.vue +7 -28
- package/rancher-components/Card/Card.vue +9 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +42 -6
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +30 -3
- package/rancher-components/Form/Radio/RadioButton.vue +18 -3
- package/rancher-components/Form/Radio/RadioGroup.vue +39 -5
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +13 -1
- package/rancher-components/RcButton/RcButton.test.ts +97 -0
- package/rancher-components/RcButton/RcButton.vue +14 -9
- package/rancher-components/RcDropdown/RcDropdown.vue +3 -1
- package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -2
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +66 -0
- package/rancher-components/RcDropdown/index.ts +1 -0
- package/rancher-components/RcDropdown/types.ts +27 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +5 -2
- package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +2 -2
- package/scripts/typegen.sh +1 -0
- package/store/__tests__/auth.test.ts +120 -0
- package/store/action-menu.js +13 -3
- package/store/auth.js +14 -9
- package/store/aws.js +9 -2
- package/store/catalog.js +14 -7
- package/store/features.js +1 -0
- package/store/prefs.js +9 -28
- package/store/type-map.utils.ts +4 -0
- package/types/resources/settings.d.ts +27 -20
- package/types/shell/index.d.ts +18 -12
- package/utils/__tests__/array.test.ts +13 -1
- package/utils/__tests__/string.test.ts +80 -1
- package/utils/array.ts +13 -0
- package/utils/auth.js +4 -0
- package/utils/banners.js +0 -45
- package/utils/cluster.js +1 -1
- package/{edit/monitoring.coreos.com.prometheusrule → utils}/duration.js +5 -3
- package/utils/object.js +0 -3
- package/utils/pagination-utils.ts +15 -2
- package/utils/string.js +31 -7
- package/utils/validators/formRules/__tests__/index.test.ts +27 -0
- package/utils/validators/formRules/index.ts +16 -0
- package/edit/provisioning.cattle.io.cluster/import.vue +0 -198
|
@@ -2,7 +2,7 @@ import { convert, matching, convertSelectorObj } from '@shell/utils/selector';
|
|
|
2
2
|
import jsyaml from 'js-yaml';
|
|
3
3
|
import isEmpty from 'lodash/isEmpty';
|
|
4
4
|
import { escapeHtml } from '@shell/utils/string';
|
|
5
|
-
import { FLEET } from '@shell/config/types';
|
|
5
|
+
import { FLEET, MANAGEMENT } from '@shell/config/types';
|
|
6
6
|
import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
7
7
|
import { addObject, addObjects, findBy, insertAt } from '@shell/utils/array';
|
|
8
8
|
import { set } from '@shell/utils/object';
|
|
@@ -42,6 +42,10 @@ function normalizeStateCounts(data) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export default class GitRepo extends SteveModel {
|
|
45
|
+
get currentUser() {
|
|
46
|
+
return this.$rootGetters['auth/v3User'] || {};
|
|
47
|
+
}
|
|
48
|
+
|
|
45
49
|
applyDefaults() {
|
|
46
50
|
const spec = this.spec || {};
|
|
47
51
|
const meta = this.metadata || {};
|
|
@@ -68,7 +72,7 @@ export default class GitRepo extends SteveModel {
|
|
|
68
72
|
|
|
69
73
|
insertAt(out, 0, {
|
|
70
74
|
action: 'pause',
|
|
71
|
-
label: '
|
|
75
|
+
label: this.t('fleet.gitRepo.actions.pause.label'),
|
|
72
76
|
icon: 'icon icon-pause',
|
|
73
77
|
bulkable: true,
|
|
74
78
|
enabled: !!this.links.update && !this.spec?.paused
|
|
@@ -76,21 +80,38 @@ export default class GitRepo extends SteveModel {
|
|
|
76
80
|
|
|
77
81
|
insertAt(out, 1, {
|
|
78
82
|
action: 'unpause',
|
|
79
|
-
label: '
|
|
83
|
+
label: this.t('fleet.gitRepo.actions.unpause.label'),
|
|
80
84
|
icon: 'icon icon-play',
|
|
81
85
|
bulkable: true,
|
|
82
86
|
enabled: !!this.links.update && this.spec?.paused === true
|
|
83
87
|
});
|
|
84
88
|
|
|
85
89
|
insertAt(out, 2, {
|
|
86
|
-
action: '
|
|
87
|
-
label: '
|
|
88
|
-
icon: 'icon icon-
|
|
90
|
+
action: 'enablePolling',
|
|
91
|
+
label: this.t('fleet.gitRepo.actions.enablePolling.label'),
|
|
92
|
+
icon: 'icon icon-endpoints_connected',
|
|
89
93
|
bulkable: true,
|
|
90
|
-
enabled: !!this.links.update
|
|
94
|
+
enabled: !!this.links.update && !!this.spec?.disablePolling
|
|
91
95
|
});
|
|
92
96
|
|
|
93
|
-
insertAt(out, 3, {
|
|
97
|
+
insertAt(out, 3, {
|
|
98
|
+
action: 'disablePolling',
|
|
99
|
+
label: this.t('fleet.gitRepo.actions.disablePolling.label'),
|
|
100
|
+
icon: 'icon icon-endpoints_disconnected',
|
|
101
|
+
bulkable: true,
|
|
102
|
+
enabled: !!this.links.update && !this.spec?.disablePolling
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
insertAt(out, 4, {
|
|
106
|
+
action: 'forceUpdate',
|
|
107
|
+
label: this.t('fleet.gitRepo.actions.forceUpdate.label'),
|
|
108
|
+
icon: 'icon icon-refresh',
|
|
109
|
+
bulkable: true,
|
|
110
|
+
bulkAction: 'forceUpdateBulk',
|
|
111
|
+
enabled: !!this.links.update
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
insertAt(out, 5, { divider: true });
|
|
94
115
|
|
|
95
116
|
return out;
|
|
96
117
|
}
|
|
@@ -105,13 +126,42 @@ export default class GitRepo extends SteveModel {
|
|
|
105
126
|
this.save();
|
|
106
127
|
}
|
|
107
128
|
|
|
108
|
-
|
|
109
|
-
|
|
129
|
+
enablePolling() {
|
|
130
|
+
this.spec.disablePolling = false;
|
|
131
|
+
this.save();
|
|
132
|
+
}
|
|
110
133
|
|
|
111
|
-
|
|
134
|
+
disablePolling() {
|
|
135
|
+
this.spec.disablePolling = true;
|
|
112
136
|
this.save();
|
|
113
137
|
}
|
|
114
138
|
|
|
139
|
+
goToClone() {
|
|
140
|
+
if (this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID]) {
|
|
141
|
+
delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME]) {
|
|
145
|
+
delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
super.goToClone();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
forceUpdate(resources = [this]) {
|
|
152
|
+
this.$dispatch('promptModal', {
|
|
153
|
+
componentProps: { repositories: resources },
|
|
154
|
+
component: 'GitRepoForceUpdateDialog'
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
forceUpdateBulk(resources) {
|
|
159
|
+
this.$dispatch('promptModal', {
|
|
160
|
+
componentProps: { repositories: resources },
|
|
161
|
+
component: 'GitRepoForceUpdateDialog'
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
115
165
|
get state() {
|
|
116
166
|
if (this.spec?.paused === true) {
|
|
117
167
|
return 'paused';
|
|
@@ -326,47 +376,32 @@ export default class GitRepo extends SteveModel {
|
|
|
326
376
|
}
|
|
327
377
|
|
|
328
378
|
get bundles() {
|
|
329
|
-
return this.$getters['matching'](FLEET.BUNDLE, {
|
|
379
|
+
return this.$getters['matching'](FLEET.BUNDLE, { [FLEET_ANNOTATIONS.REPO_NAME]: this.name }, this.namespace);
|
|
330
380
|
}
|
|
331
381
|
|
|
332
382
|
get bundleDeployments() {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return bds.filter((bd) => bd.metadata?.labels?.['fleet.cattle.io/repo-name'] === this.name);
|
|
383
|
+
return this.$getters['matching'](FLEET.BUNDLE_DEPLOYMENT, { [FLEET_ANNOTATIONS.REPO_NAME]: this.name });
|
|
336
384
|
}
|
|
337
385
|
|
|
338
386
|
get allBundlesStatuses() {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (!acc[bundleId]) {
|
|
344
|
-
acc[bundleId] = {
|
|
345
|
-
total: 0,
|
|
346
|
-
states: { [STATES_ENUM.READY]: 0 },
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
acc[bundleId].total++;
|
|
350
|
-
|
|
351
|
-
if (!acc[bundleId].states[state]) {
|
|
352
|
-
acc[bundleId].states[state] = 0;
|
|
387
|
+
return this.bundles.reduce((acc, bundle) => {
|
|
388
|
+
if (isEmpty(bundle.status?.summary)) {
|
|
389
|
+
return acc;
|
|
353
390
|
}
|
|
354
|
-
acc[bundleId].states[state]++;
|
|
355
391
|
|
|
356
|
-
|
|
357
|
-
}, {});
|
|
358
|
-
const bundleIds = Object.keys(bundleDeploymentCountsPerBundle);
|
|
392
|
+
const { nonReadyResources, ...summary } = bundle.status?.summary;
|
|
359
393
|
|
|
360
|
-
|
|
361
|
-
const state = primaryDisplayStatusFromCount(
|
|
394
|
+
const bdCounts = normalizeStateCounts(summary);
|
|
395
|
+
const state = primaryDisplayStatusFromCount(bdCounts.states);
|
|
362
396
|
|
|
363
397
|
if (!acc.states[state]) {
|
|
364
398
|
acc.states[state] = 0;
|
|
365
399
|
}
|
|
366
400
|
acc.states[state]++;
|
|
401
|
+
acc.total++;
|
|
367
402
|
|
|
368
403
|
return acc;
|
|
369
|
-
}, { total:
|
|
404
|
+
}, { total: 0, states: { [STATES_ENUM.READY]: 0 } } );
|
|
370
405
|
}
|
|
371
406
|
|
|
372
407
|
get allResourceStatuses() {
|
|
@@ -378,91 +413,79 @@ export default class GitRepo extends SteveModel {
|
|
|
378
413
|
return {};
|
|
379
414
|
}
|
|
380
415
|
|
|
381
|
-
return this.
|
|
382
|
-
.filter((bd) => FleetUtils.clusterIdFromBundleDeploymentLabels(bd.metadata?.labels) === clusterId)
|
|
383
|
-
.map((bd) => FleetUtils.resourcesFromBundleDeploymentStatus(bd.status))
|
|
384
|
-
.flat()
|
|
385
|
-
.map((r) => r.state)
|
|
386
|
-
.reduce((prev, state) => {
|
|
387
|
-
if (!prev[state]) {
|
|
388
|
-
prev[state] = 0;
|
|
389
|
-
}
|
|
390
|
-
prev[state]++;
|
|
391
|
-
prev.desiredReady++;
|
|
392
|
-
|
|
393
|
-
return prev;
|
|
394
|
-
}, { desiredReady: 0 });
|
|
416
|
+
return this.status?.perClusterResourceCounts[clusterId] || { desiredReady: 0 };
|
|
395
417
|
}
|
|
396
418
|
|
|
397
419
|
get resourcesStatuses() {
|
|
398
|
-
|
|
420
|
+
if (isEmpty(this.status?.resources)) {
|
|
421
|
+
return [];
|
|
422
|
+
}
|
|
423
|
+
|
|
399
424
|
const clusters = (this.targetClusters || []).reduce((res, c) => {
|
|
400
425
|
res[c.id] = c;
|
|
401
426
|
|
|
402
427
|
return res;
|
|
403
428
|
}, {});
|
|
429
|
+
const resources = this.status?.resources?.reduce((acc, resourceInfo) => {
|
|
430
|
+
const { perClusterState, ...resource } = resourceInfo;
|
|
404
431
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const clusterId = FleetUtils.clusterIdFromBundleDeploymentLabels(bd.metadata?.labels);
|
|
409
|
-
const c = clusters[clusterId];
|
|
410
|
-
|
|
411
|
-
if (!c) {
|
|
412
|
-
continue;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const resources = FleetUtils.resourcesFromBundleDeploymentStatus(bd.status);
|
|
416
|
-
|
|
417
|
-
resources.forEach((r) => {
|
|
418
|
-
const id = FleetUtils.resourceId(r);
|
|
419
|
-
const type = FleetUtils.resourceType(r);
|
|
420
|
-
const state = r.state;
|
|
421
|
-
|
|
422
|
-
const color = colorForState(state).replace('text-', 'bg-');
|
|
423
|
-
const display = stateDisplay(state);
|
|
424
|
-
|
|
425
|
-
const detailLocation = {
|
|
426
|
-
name: `c-cluster-product-resource${ r.namespace ? '-namespace' : '' }-id`,
|
|
427
|
-
params: {
|
|
428
|
-
product: NAME,
|
|
429
|
-
cluster: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME], // explorer uses the "management" Cluster name, which differs from the Fleet Cluster name
|
|
430
|
-
resource: type,
|
|
431
|
-
namespace: r.namespace,
|
|
432
|
-
id: r.name,
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
|
|
436
|
-
const key = `${ c.id }-${ type }-${ r.namespace }-${ r.name }`;
|
|
437
|
-
|
|
438
|
-
out.push({
|
|
439
|
-
key,
|
|
440
|
-
tableKey: key,
|
|
441
|
-
|
|
442
|
-
// Needed?
|
|
443
|
-
id,
|
|
444
|
-
type,
|
|
445
|
-
clusterId: c.id,
|
|
446
|
-
|
|
447
|
-
// columns, see FleetResources.vue
|
|
448
|
-
state: mapStateToEnum(state),
|
|
449
|
-
clusterName: c.nameDisplay,
|
|
450
|
-
apiVersion: r.apiVersion,
|
|
451
|
-
kind: r.kind,
|
|
452
|
-
name: r.name,
|
|
453
|
-
namespace: r.namespace,
|
|
454
|
-
creationTimestamp: r.createdAt,
|
|
455
|
-
|
|
456
|
-
// other properties
|
|
457
|
-
stateBackground: color,
|
|
458
|
-
stateDisplay: display,
|
|
459
|
-
stateSort: stateSort(color, display),
|
|
460
|
-
detailLocation,
|
|
432
|
+
Object.entries(perClusterState).forEach(([state, clusterIds]) => {
|
|
433
|
+
clusterIds.filter((id) => !!clusters[id]).forEach((clusterId) => {
|
|
434
|
+
acc.push(Object.assign({}, resource, { clusterId, state }));
|
|
461
435
|
});
|
|
462
436
|
});
|
|
463
|
-
}
|
|
464
437
|
|
|
465
|
-
|
|
438
|
+
return acc;
|
|
439
|
+
}, []);
|
|
440
|
+
|
|
441
|
+
return resources.map((r) => {
|
|
442
|
+
const {
|
|
443
|
+
namespace, name, clusterId, state
|
|
444
|
+
} = r;
|
|
445
|
+
const id = FleetUtils.resourceId(r);
|
|
446
|
+
const type = FleetUtils.resourceType(r);
|
|
447
|
+
const c = clusters[clusterId];
|
|
448
|
+
|
|
449
|
+
const color = colorForState(state).replace('text-', 'bg-');
|
|
450
|
+
const display = stateDisplay(state);
|
|
451
|
+
|
|
452
|
+
const detailLocation = state !== STATES_ENUM.MISSING ? {
|
|
453
|
+
name: `c-cluster-product-resource${ r.namespace ? '-namespace' : '' }-id`,
|
|
454
|
+
params: {
|
|
455
|
+
product: NAME,
|
|
456
|
+
cluster: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME], // explorer uses the "management" Cluster name, which differs from the Fleet Cluster name
|
|
457
|
+
resource: type,
|
|
458
|
+
namespace,
|
|
459
|
+
id: name,
|
|
460
|
+
}
|
|
461
|
+
} : undefined;
|
|
462
|
+
|
|
463
|
+
const key = `${ clusterId }-${ type }-${ namespace }-${ name }`;
|
|
464
|
+
|
|
465
|
+
return {
|
|
466
|
+
key,
|
|
467
|
+
tableKey: key,
|
|
468
|
+
|
|
469
|
+
// Needed?
|
|
470
|
+
id,
|
|
471
|
+
type,
|
|
472
|
+
clusterId,
|
|
473
|
+
|
|
474
|
+
// columns, see FleetResources.vue
|
|
475
|
+
state: mapStateToEnum(state),
|
|
476
|
+
clusterName: c.nameDisplay,
|
|
477
|
+
apiVersion: r.apiVersion,
|
|
478
|
+
kind: r.kind,
|
|
479
|
+
name: r.name,
|
|
480
|
+
namespace: r.namespace,
|
|
481
|
+
|
|
482
|
+
// other properties
|
|
483
|
+
stateBackground: color,
|
|
484
|
+
stateDisplay: display,
|
|
485
|
+
stateSort: stateSort(color, display),
|
|
486
|
+
detailLocation,
|
|
487
|
+
};
|
|
488
|
+
});
|
|
466
489
|
}
|
|
467
490
|
|
|
468
491
|
get clusterInfo() {
|
|
@@ -485,4 +508,41 @@ export default class GitRepo extends SteveModel {
|
|
|
485
508
|
get clustersList() {
|
|
486
509
|
return this.$getters['all'](FLEET.CLUSTER);
|
|
487
510
|
}
|
|
511
|
+
|
|
512
|
+
get authorId() {
|
|
513
|
+
return this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
get author() {
|
|
517
|
+
if (this.authorId) {
|
|
518
|
+
return this.$rootGetters['management/byId'](MANAGEMENT.USER, this.authorId);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
get createdBy() {
|
|
525
|
+
const displayName = this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME];
|
|
526
|
+
|
|
527
|
+
if (!displayName) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return {
|
|
532
|
+
displayName,
|
|
533
|
+
location: !this.author ? null : {
|
|
534
|
+
name: 'c-cluster-product-resource-id',
|
|
535
|
+
params: {
|
|
536
|
+
cluster: '_',
|
|
537
|
+
product: 'auth',
|
|
538
|
+
resource: MANAGEMENT.USER,
|
|
539
|
+
id: this.author.id,
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
get showCreatedBy() {
|
|
546
|
+
return !!this.createdBy;
|
|
547
|
+
}
|
|
488
548
|
}
|
|
@@ -29,6 +29,13 @@ export const KONTAINER_TO_DRIVER = {
|
|
|
29
29
|
opentelekomcloudcontainerengine: 'otccce',
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
// Legacy KEV1 Hosted cluster drivers
|
|
33
|
+
export const KEV1 = [
|
|
34
|
+
'amazonelasticcontainerservice',
|
|
35
|
+
'azurekubernetesservice',
|
|
36
|
+
'googlekubernetesengine',
|
|
37
|
+
];
|
|
38
|
+
|
|
32
39
|
// And the Import page has even shorter ones that don't match kontainer or create...
|
|
33
40
|
export const DRIVER_TO_IMPORT = {
|
|
34
41
|
googlegke: 'gke',
|
package/models/nodedriver.js
CHANGED
|
@@ -3,7 +3,10 @@ import Driver from '@shell/models/driver';
|
|
|
3
3
|
/**
|
|
4
4
|
* Overrides for spec.addCloudCredential
|
|
5
5
|
*/
|
|
6
|
-
export const CLOUD_CREDENTIAL_OVERRIDE = {
|
|
6
|
+
export const CLOUD_CREDENTIAL_OVERRIDE = {
|
|
7
|
+
nutanix: true,
|
|
8
|
+
oci: true
|
|
9
|
+
};
|
|
7
10
|
|
|
8
11
|
export default class NodeDriver extends Driver {
|
|
9
12
|
get doneRoute() {
|
|
@@ -10,6 +10,7 @@ import { compare } from '@shell/utils/version';
|
|
|
10
10
|
import { AS, MODE, _VIEW, _YAML } from '@shell/config/query-params';
|
|
11
11
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
12
12
|
import { CAPI as CAPI_ANNOTATIONS, NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
|
|
13
|
+
import { KEV1 } from '@shell/models/management.cattle.io.kontainerdriver';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Class representing Cluster resource.
|
|
@@ -180,6 +181,15 @@ export default class ProvCluster extends SteveModel {
|
|
|
180
181
|
|
|
181
182
|
const all = actions.concat(out);
|
|
182
183
|
|
|
184
|
+
// If the cluster is a KEV1 cluster then prevent edit
|
|
185
|
+
if (this.isKev1) {
|
|
186
|
+
const edit = all.find((action) => action.action === 'goToEdit');
|
|
187
|
+
|
|
188
|
+
if (edit) {
|
|
189
|
+
edit.enabled = false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
183
193
|
// If we have a helper that wants to modify the available actions, let it do it
|
|
184
194
|
if (this.customProvisionerHelper?.availableActions) {
|
|
185
195
|
// Provider can either modify the provided list or return one of its own
|
|
@@ -189,6 +199,15 @@ export default class ProvCluster extends SteveModel {
|
|
|
189
199
|
return all;
|
|
190
200
|
}
|
|
191
201
|
|
|
202
|
+
get detailLocation() {
|
|
203
|
+
// Prevent going to detail page for a KEV1 cluster
|
|
204
|
+
if (this.isKev1) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return super.detailLocation;
|
|
209
|
+
}
|
|
210
|
+
|
|
192
211
|
get normanCluster() {
|
|
193
212
|
const name = this.status?.clusterName;
|
|
194
213
|
|
|
@@ -289,6 +308,11 @@ export default class ProvCluster extends SteveModel {
|
|
|
289
308
|
return this.mgmt?.isLocal;
|
|
290
309
|
}
|
|
291
310
|
|
|
311
|
+
// Is the cluster a legacy (unsupported) KEV1 cluster?
|
|
312
|
+
get isKev1() {
|
|
313
|
+
return KEV1.includes(this.mgmt?.spec?.genericEngineConfig?.driverName);
|
|
314
|
+
}
|
|
315
|
+
|
|
292
316
|
get isImported() {
|
|
293
317
|
if (this.isLocal) {
|
|
294
318
|
return false;
|
package/models/secret.js
CHANGED
|
@@ -51,7 +51,7 @@ export default class Secret extends SteveModel {
|
|
|
51
51
|
|
|
52
52
|
// For Fleet SSH secrets - does the secret have the 'known_hosts' data key?
|
|
53
53
|
get supportsSshKnownHosts() {
|
|
54
|
-
return this._type === TYPES.SSH && 'known_hosts' in this.data;
|
|
54
|
+
return this._type === TYPES.SSH && !!this.data && 'known_hosts' in this.data;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
get issuer() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.2
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -79,13 +79,13 @@
|
|
|
79
79
|
"element-matches": "^0.1.2",
|
|
80
80
|
"entities": "4.5.0",
|
|
81
81
|
"eslint-config-standard": "16.0.3",
|
|
82
|
-
"eslint-import-resolver-node": "0.3.
|
|
82
|
+
"eslint-import-resolver-node": "0.3.9",
|
|
83
83
|
"eslint-module-utils": "2.6.1",
|
|
84
84
|
"eslint-plugin-cypress": "2.12.1",
|
|
85
85
|
"eslint-plugin-import": "2.31.0",
|
|
86
86
|
"eslint-plugin-jest": "24.4.0",
|
|
87
87
|
"eslint-plugin-n": "15.2.0",
|
|
88
|
-
"eslint-plugin-vue": "9.
|
|
88
|
+
"eslint-plugin-vue": "9.32.0",
|
|
89
89
|
"eslint": "7.32.0",
|
|
90
90
|
"event-target-shim": "5.0.1",
|
|
91
91
|
"express": "4.17.1",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"jexl": "2.3.0",
|
|
102
102
|
"jest": "27.5.1",
|
|
103
103
|
"jquery": "3.5.1",
|
|
104
|
-
"js-cookie": "
|
|
104
|
+
"js-cookie": "3.0.5",
|
|
105
105
|
"js-yaml-loader": "1.2.2",
|
|
106
106
|
"js-yaml": "4.1.0",
|
|
107
107
|
"jsdiff": "1.1.1",
|
|
@@ -170,4 +170,4 @@
|
|
|
170
170
|
".vue"
|
|
171
171
|
]
|
|
172
172
|
}
|
|
173
|
-
}
|
|
173
|
+
}
|
package/pages/auth/login.vue
CHANGED
|
@@ -30,7 +30,6 @@ import {
|
|
|
30
30
|
} from '@shell/config/private-label';
|
|
31
31
|
import loadPlugins from '@shell/plugins/plugin';
|
|
32
32
|
import Loading from '@shell/components/Loading';
|
|
33
|
-
import { getGlobalBannerFontSizes } from '@shell/utils/banners';
|
|
34
33
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
35
34
|
|
|
36
35
|
export default {
|
|
@@ -105,6 +104,10 @@ export default {
|
|
|
105
104
|
return this.t('login.clientError');
|
|
106
105
|
} else if (this.err === LOGIN_ERRORS.CLIENT || this.err === LOGIN_ERRORS.SERVER) {
|
|
107
106
|
return this.t('login.error');
|
|
107
|
+
} else if (this.err === LOGIN_ERRORS.NONCE) {
|
|
108
|
+
return this.t('login.invalidResponseError');
|
|
109
|
+
} else if (this.err === LOGIN_ERRORS.USER_UNAUTHORIZED) {
|
|
110
|
+
return this.t('login.userUnauthorized');
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
return this.err?.length ? this.t('login.specificError', { msg: this.err }) : '';
|
|
@@ -129,13 +132,6 @@ export default {
|
|
|
129
132
|
hasLoginMessage() {
|
|
130
133
|
return this.errorToDisplay || this.loggedOut || this.timedOut;
|
|
131
134
|
},
|
|
132
|
-
|
|
133
|
-
// Apply bottom margin so that the locale secletor control lifts up to avoid the footer fixed banner, if it is shown
|
|
134
|
-
localeSelectorStyle() {
|
|
135
|
-
const globalBannerSettings = getGlobalBannerFontSizes(this.$store);
|
|
136
|
-
|
|
137
|
-
return { marginBottom: globalBannerSettings?.footerFont };
|
|
138
|
-
}
|
|
139
135
|
},
|
|
140
136
|
|
|
141
137
|
async fetch() {
|
|
@@ -433,7 +429,6 @@ export default {
|
|
|
433
429
|
<div class="mb-20">
|
|
434
430
|
<LabeledInput
|
|
435
431
|
v-if="!firstLogin"
|
|
436
|
-
id="username"
|
|
437
432
|
ref="username"
|
|
438
433
|
v-model:value.trim="username"
|
|
439
434
|
data-testid="local-login-username"
|
|
@@ -443,7 +438,6 @@ export default {
|
|
|
443
438
|
</div>
|
|
444
439
|
<div class="">
|
|
445
440
|
<Password
|
|
446
|
-
id="password"
|
|
447
441
|
ref="password"
|
|
448
442
|
v-model:value="password"
|
|
449
443
|
data-testid="local-login-password"
|
|
@@ -507,7 +501,6 @@ export default {
|
|
|
507
501
|
class="locale-selector"
|
|
508
502
|
>
|
|
509
503
|
<LocaleSelector
|
|
510
|
-
:style="localeSelectorStyle"
|
|
511
504
|
mode="login"
|
|
512
505
|
/>
|
|
513
506
|
</div>
|
|
@@ -524,6 +517,7 @@ export default {
|
|
|
524
517
|
<style lang="scss" scoped>
|
|
525
518
|
.login {
|
|
526
519
|
overflow: hidden;
|
|
520
|
+
position: relative; // Used to keep the locale selector positioned correctly
|
|
527
521
|
|
|
528
522
|
.row {
|
|
529
523
|
align-items: center;
|
package/pages/auth/verify.vue
CHANGED
|
@@ -5,9 +5,12 @@ import {
|
|
|
5
5
|
import { get } from '@shell/utils/object';
|
|
6
6
|
import { base64Decode } from '@shell/utils/crypto';
|
|
7
7
|
import loadPlugins from '@shell/plugins/plugin';
|
|
8
|
+
import { LOGIN_ERRORS } from '@shell/store/auth';
|
|
8
9
|
|
|
9
10
|
const samlProviders = ['ping', 'adfs', 'keycloak', 'okta', 'shibboleth'];
|
|
10
11
|
|
|
12
|
+
const oauthProviders = ['github', 'googleoauth', 'azuread'];
|
|
13
|
+
|
|
11
14
|
function reply(err, code) {
|
|
12
15
|
try {
|
|
13
16
|
window.opener.window.onAuthTest(err, code);
|
|
@@ -114,7 +117,14 @@ export default {
|
|
|
114
117
|
this.$router.replace(`/auth/login?err=${ escape(res) }`);
|
|
115
118
|
}
|
|
116
119
|
} catch (err) {
|
|
117
|
-
|
|
120
|
+
let errCode = err;
|
|
121
|
+
|
|
122
|
+
// If the provider is OAUTH, then the client error is not that the credentials are wrong, but that the user is not authorized
|
|
123
|
+
if (oauthProviders.includes(provider) && err === LOGIN_ERRORS.CLIENT_UNAUTHORIZED) {
|
|
124
|
+
errCode = LOGIN_ERRORS.USER_UNAUTHORIZED;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this.$router.replace(`/auth/login?err=${ escape(errCode) }`);
|
|
118
128
|
}
|
|
119
129
|
},
|
|
120
130
|
|
|
@@ -58,12 +58,14 @@ export default {
|
|
|
58
58
|
showHidden: null,
|
|
59
59
|
chartOptions: [
|
|
60
60
|
{
|
|
61
|
-
label:
|
|
62
|
-
value:
|
|
61
|
+
label: this.t('catalog.charts.browseBtn'),
|
|
62
|
+
value: 'browse',
|
|
63
|
+
ariaLabel: this.t('catalog.charts.browseAriaLabel')
|
|
63
64
|
},
|
|
64
65
|
{
|
|
65
|
-
label:
|
|
66
|
-
value:
|
|
66
|
+
label: this.t('catalog.charts.featuredBtn'),
|
|
67
|
+
value: 'featured',
|
|
68
|
+
ariaLabel: this.t('catalog.charts.featuredAriaLabel')
|
|
67
69
|
}
|
|
68
70
|
]
|
|
69
71
|
};
|
|
@@ -502,7 +502,7 @@ export default {
|
|
|
502
502
|
},
|
|
503
503
|
|
|
504
504
|
charts() {
|
|
505
|
-
const current = this.existing?.
|
|
505
|
+
const current = this.existing?.matchingCharts(true)[0];
|
|
506
506
|
|
|
507
507
|
const out = this.$store.getters['catalog/charts'].filter((x) => {
|
|
508
508
|
if ( x.key === current?.key || x.chartName === current?.chartName ) {
|
|
@@ -27,16 +27,14 @@ export default {
|
|
|
27
27
|
<div class="config-badge">
|
|
28
28
|
<div>
|
|
29
29
|
<button
|
|
30
|
+
v-clean-tooltip="{content: tooltip, triggers: ['hover', 'touch', 'focus'] }"
|
|
31
|
+
v-stripped-aria-label="tooltip"
|
|
30
32
|
class="badge-install btn btn-sm role-secondary"
|
|
31
33
|
data-testid="add-custom-cluster-badge"
|
|
32
34
|
role="button"
|
|
33
|
-
tabindex="0"
|
|
34
35
|
@click="customBadgeDialog"
|
|
35
36
|
>
|
|
36
|
-
<i
|
|
37
|
-
v-clean-tooltip="tooltip"
|
|
38
|
-
class="icon icon-brush-icon"
|
|
39
|
-
/>
|
|
37
|
+
<i class="icon icon-brush-icon" />
|
|
40
38
|
</button>
|
|
41
39
|
</div>
|
|
42
40
|
</div>
|
|
@@ -35,7 +35,7 @@ export default {
|
|
|
35
35
|
|
|
36
36
|
const schema = this.$store.getters['cluster/schemaFor'](EVENT);
|
|
37
37
|
|
|
38
|
-
const paginationHeaders = [
|
|
38
|
+
const paginationHeaders = schema ? [
|
|
39
39
|
reason,
|
|
40
40
|
STEVE_EVENT_OBJECT,
|
|
41
41
|
MESSAGE,
|
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
defaultSort: true,
|
|
50
50
|
},
|
|
51
51
|
headerFromSchemaColString('Count', schema, this.$store.getters, true),
|
|
52
|
-
];
|
|
52
|
+
] : [];
|
|
53
53
|
|
|
54
54
|
return {
|
|
55
55
|
schema,
|
|
@@ -88,6 +88,7 @@ export default {
|
|
|
88
88
|
|
|
89
89
|
<template>
|
|
90
90
|
<PaginatedResourceTable
|
|
91
|
+
v-if="!!schema"
|
|
91
92
|
:schema="schema"
|
|
92
93
|
:headers="eventHeaders"
|
|
93
94
|
:pagination-headers="paginationHeaders"
|