@rancher/shell 3.0.1-rc.2 → 3.0.1-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/styles/app.scss +0 -1
- package/assets/translations/en-us.yaml +14 -12
- package/assets/translations/zh-hans.yaml +0 -9
- package/components/GlobalRoleBindings.vue +0 -7
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +66 -11
- package/components/ResourceYaml.vue +0 -53
- package/components/SortableTable/THead.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +0 -16
- package/components/form/UnitInput.vue +1 -1
- package/components/form/__tests__/UnitInput.test.ts +1 -1
- package/components/nav/TopLevelMenu.vue +1 -1
- package/components/nav/WindowManager/ContainerShell.vue +13 -4
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +20 -18
- package/composables/useLabeledFormElement.ts +6 -2
- package/config/router/navigation-guards/index.js +1 -2
- package/config/settings.ts +2 -7
- package/edit/catalog.cattle.io.clusterrepo.vue +0 -9
- package/edit/provisioning.cattle.io.cluster/rke2.vue +3 -4
- 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/models/__tests__/management.cattle.io.cluster.test.ts +0 -42
- package/models/management.cattle.io.cluster.js +0 -24
- package/models/management.cattle.io.globalrole.js +1 -0
- package/models/nodedriver.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +24 -2
- package/package.json +2 -3
- package/pages/auth/setup.vue +7 -28
- package/pages/c/_cluster/auth/roles/index.vue +1 -11
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +71 -1
- package/pages/c/_cluster/explorer/index.vue +6 -2
- 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 +3 -1
- 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/test-plugins-build.sh +3 -2
- package/types/shell/index.d.ts +20 -0
- package/utils/__tests__/object.test.ts +30 -1
- package/utils/object.js +28 -0
- package/utils/uiplugins.ts +293 -0
- package/vue.config.js +2 -1
- package/components/templates/error.vue +0 -131
- package/config/router/navigation-guards/history.js +0 -13
- package/machine-config/__tests__/vmwarevsphere-pool-config-merge.test.ts +0 -30
- package/machine-config/vmwarevsphere-pool-config-merge.ts +0 -25
- package/plugins/back-button.js +0 -3
|
@@ -4,7 +4,6 @@ import { install as installAuthentication } from '@shell/config/router/navigatio
|
|
|
4
4
|
import { install as installRuntimeExtensionRoute } from '@shell/config/router/navigation-guards/runtime-extension-route';
|
|
5
5
|
import { install as installI18N } from '@shell/config/router/navigation-guards/i18n';
|
|
6
6
|
import { install as installProducts } from '@shell/config/router/navigation-guards/products';
|
|
7
|
-
import { install as installHistory } from '@shell/config/router/navigation-guards/history';
|
|
8
7
|
import { install as installClusters } from '@shell/config/router/navigation-guards/clusters';
|
|
9
8
|
import { install as installHandleInstallRedirect } from '@shell/config/router/navigation-guards/install-redirect';
|
|
10
9
|
import { install as installPageTitle } from '@shell/config/router/navigation-guards/page-title';
|
|
@@ -17,7 +16,7 @@ export function installNavigationGuards(router, context) {
|
|
|
17
16
|
// NOTE: the order of the installation matters.
|
|
18
17
|
// Be intentional when adding, removing or modifying the guards that are installed.
|
|
19
18
|
|
|
20
|
-
const navigationGuardInstallers = [installLoadInitialSettings, installAttemptFirstLogin, installAuthentication, installProducts,
|
|
19
|
+
const navigationGuardInstallers = [installLoadInitialSettings, installAttemptFirstLogin, installAuthentication, installProducts, installClusters, installRuntimeExtensionRoute, installI18N, installHandleInstallRedirect, installPageTitle, installServerUpgradeGrowl];
|
|
21
20
|
|
|
22
21
|
navigationGuardInstallers.forEach((installer) => installer(router, context));
|
|
23
22
|
}
|
package/config/settings.ts
CHANGED
|
@@ -51,7 +51,6 @@ export const SETTING = {
|
|
|
51
51
|
INGRESS_IP_DOMAIN: 'ingress-ip-domain',
|
|
52
52
|
SERVER_URL: 'server-url',
|
|
53
53
|
RKE_METADATA_CONFIG: 'rke-metadata-config',
|
|
54
|
-
TELEMETRY: 'telemetry-opt',
|
|
55
54
|
EULA_AGREED: 'eula-agreed',
|
|
56
55
|
AUTH_USER_INFO_MAX_AGE_SECONDS: 'auth-user-info-max-age-seconds',
|
|
57
56
|
AUTH_USER_SESSION_TTL_MINUTES: 'auth-user-session-ttl-minutes',
|
|
@@ -156,12 +155,8 @@ export const ALLOWED_SETTINGS: GlobalSetting = {
|
|
|
156
155
|
},
|
|
157
156
|
[SETTING.BRAND]: { canReset: true },
|
|
158
157
|
[SETTING.CLUSTER_TEMPLATE_ENFORCEMENT]: { kind: 'boolean' },
|
|
159
|
-
[SETTING.
|
|
160
|
-
|
|
161
|
-
options: ['prompt', 'in', 'out']
|
|
162
|
-
},
|
|
163
|
-
[SETTING.HIDE_LOCAL_CLUSTER]: { kind: 'boolean' },
|
|
164
|
-
[SETTING.AGENT_TLS_MODE]: {
|
|
158
|
+
[SETTING.HIDE_LOCAL_CLUSTER]: { kind: 'boolean' },
|
|
159
|
+
[SETTING.AGENT_TLS_MODE]: {
|
|
165
160
|
kind: 'enum',
|
|
166
161
|
options: ['strict', 'system-store'],
|
|
167
162
|
warning: 'agent-tls-mode'
|
|
@@ -287,12 +287,3 @@ export default {
|
|
|
287
287
|
/>
|
|
288
288
|
</form>
|
|
289
289
|
</template>
|
|
290
|
-
|
|
291
|
-
<style lang="scss">
|
|
292
|
-
span.oci-experimental-badge {
|
|
293
|
-
background-color: var(--warning);
|
|
294
|
-
color: var(--darker-active-bg);
|
|
295
|
-
font-size: 12px;
|
|
296
|
-
padding: 2px 6px;
|
|
297
|
-
}
|
|
298
|
-
</style>
|
|
@@ -22,11 +22,10 @@ import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
|
|
|
22
22
|
import { findBy, removeObject, clear } from '@shell/utils/array';
|
|
23
23
|
import { createYaml } from '@shell/utils/create-yaml';
|
|
24
24
|
import {
|
|
25
|
-
clone, diff, set, get, isEmpty
|
|
25
|
+
clone, diff, set, get, isEmpty, mergeWithReplaceArrays
|
|
26
26
|
} from '@shell/utils/object';
|
|
27
27
|
import { allHash } from '@shell/utils/promise';
|
|
28
28
|
import { sortBy } from '@shell/utils/sort';
|
|
29
|
-
import { vspherePoolConfigMerge } from '@shell/machine-config/vmwarevsphere-pool-config-merge';
|
|
30
29
|
|
|
31
30
|
import { compare, sortable } from '@shell/utils/version';
|
|
32
31
|
import { isHarvesterSatisfiesVersion, labelForAddon } from '@shell/utils/cluster';
|
|
@@ -1260,7 +1259,7 @@ export default {
|
|
|
1260
1259
|
delete clonedCurrentConfig.metadata;
|
|
1261
1260
|
|
|
1262
1261
|
if (this.provider === VMWARE_VSPHERE) {
|
|
1263
|
-
machinePool.config =
|
|
1262
|
+
machinePool.config = mergeWithReplaceArrays(clonedLatestConfig, clonedCurrentConfig);
|
|
1264
1263
|
} else {
|
|
1265
1264
|
machinePool.config = merge(clonedLatestConfig, clonedCurrentConfig);
|
|
1266
1265
|
}
|
|
@@ -1644,7 +1643,7 @@ export default {
|
|
|
1644
1643
|
const defaultChartValue = this.versionInfo[name];
|
|
1645
1644
|
const key = this.chartVersionKey(name);
|
|
1646
1645
|
|
|
1647
|
-
return
|
|
1646
|
+
return mergeWithReplaceArrays(defaultChartValue?.values, this.userChartValues[key]);
|
|
1648
1647
|
},
|
|
1649
1648
|
|
|
1650
1649
|
initServerAgentArgs() {
|
package/edit/workload/index.vue
CHANGED
|
@@ -44,6 +44,33 @@ export default {
|
|
|
44
44
|
|
|
45
45
|
...mapGetters({ t: 'i18n/t' })
|
|
46
46
|
},
|
|
47
|
+
|
|
48
|
+
methods: {
|
|
49
|
+
/**
|
|
50
|
+
* Retrieves the label for a given option
|
|
51
|
+
* @param option The option for which to retrieve the label. option can be
|
|
52
|
+
* either a string or an object. If it is an object, is should have a `label`
|
|
53
|
+
* property associated with it.
|
|
54
|
+
*/
|
|
55
|
+
getOptionLabel(option) {
|
|
56
|
+
if (typeof option === 'string') {
|
|
57
|
+
return this.getOptionLabelString(option);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { label } = option;
|
|
61
|
+
|
|
62
|
+
return this.getOptionLabelString(label);
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Translates a given key into a localized string.
|
|
66
|
+
* @param key The key to be translated.
|
|
67
|
+
*/
|
|
68
|
+
getOptionLabelString(key) {
|
|
69
|
+
// Periods are replaced with `-` to prevent conflict with the default key
|
|
70
|
+
// separator.
|
|
71
|
+
return this.t(`workload.storage.csi.drivers.'${ key.replaceAll('.', '-') }'`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
47
74
|
};
|
|
48
75
|
</script>
|
|
49
76
|
|
|
@@ -71,10 +98,11 @@ export default {
|
|
|
71
98
|
<div class="col span-6">
|
|
72
99
|
<LabeledSelect
|
|
73
100
|
v-model:value="value.csi.driver"
|
|
101
|
+
data-testid="workload-storage-driver"
|
|
74
102
|
:mode="mode"
|
|
75
103
|
:label="t('workload.storage.driver')"
|
|
76
104
|
:options="driverOpts"
|
|
77
|
-
:get-option-label="
|
|
105
|
+
:get-option-label="getOptionLabel"
|
|
78
106
|
:required="true"
|
|
79
107
|
/>
|
|
80
108
|
</div>
|
package/initialize/App.vue
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import NuxtError from '@shell/components/templates/error.vue';
|
|
3
2
|
import NuxtLoading from '@shell/components/nav/GlobalLoading.vue';
|
|
4
3
|
|
|
5
4
|
import '@shell/assets/styles/app.scss';
|
|
6
5
|
|
|
7
6
|
export default {
|
|
8
|
-
data: () => ({
|
|
9
|
-
isOnline: true,
|
|
10
|
-
|
|
11
|
-
showErrorPage: false,
|
|
12
|
-
}),
|
|
7
|
+
data: () => ({ isOnline: true }),
|
|
13
8
|
|
|
14
9
|
created() {
|
|
15
10
|
// add to window so we can listen when ready
|
|
@@ -60,7 +55,7 @@ export default {
|
|
|
60
55
|
},
|
|
61
56
|
},
|
|
62
57
|
|
|
63
|
-
components: { NuxtLoading
|
|
58
|
+
components: { NuxtLoading }
|
|
64
59
|
};
|
|
65
60
|
</script>
|
|
66
61
|
<template>
|
|
@@ -68,10 +63,8 @@ export default {
|
|
|
68
63
|
<NuxtLoading ref="loading" />
|
|
69
64
|
<div
|
|
70
65
|
id="__layout"
|
|
71
|
-
:key="showErrorPage"
|
|
72
66
|
>
|
|
73
|
-
<
|
|
74
|
-
<router-view v-else />
|
|
67
|
+
<router-view />
|
|
75
68
|
</div>
|
|
76
69
|
</div>
|
|
77
70
|
</template>
|
|
@@ -15,7 +15,6 @@ import axios from '@shell/utils/axios';
|
|
|
15
15
|
import cookieUniversal from '@shell/utils/cookie-universal';
|
|
16
16
|
import config from '@shell/utils/config';
|
|
17
17
|
import axiosShell from '@shell/plugins/axios';
|
|
18
|
-
import backButton from '@shell/plugins/back-button';
|
|
19
18
|
import codeMirror from '@shell/plugins/codemirror-loader';
|
|
20
19
|
import { InstallCodeMirror } from 'codemirror-editor-vue3';
|
|
21
20
|
import * as intNumber from '@shell/directives/int-number';
|
|
@@ -42,7 +41,7 @@ export async function installPlugins(vueApp) {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
export async function installInjectedPlugins(app, vueApp) {
|
|
45
|
-
const pluginDefinitions = [config, cookieUniversal, axios, plugins, pluginsLoader, axiosShell, intNumber, codeMirror, nuxtClientInit, replaceAll,
|
|
44
|
+
const pluginDefinitions = [config, cookieUniversal, axios, plugins, pluginsLoader, axiosShell, intNumber, codeMirror, nuxtClientInit, replaceAll, plugin, steveCreateWorker, emberCookie];
|
|
46
45
|
|
|
47
46
|
const installations = pluginDefinitions.map(async(pluginDefinition) => {
|
|
48
47
|
if (typeof pluginDefinition === 'function') {
|
|
@@ -19,13 +19,17 @@ export default {
|
|
|
19
19
|
required: true,
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
|
+
emits: ['error'],
|
|
22
23
|
|
|
23
24
|
async fetch() {
|
|
24
25
|
const inStore = this.$store.getters['currentStore']();
|
|
25
26
|
|
|
27
|
+
try {
|
|
26
28
|
// Fetch storage classes so we can determine if a PVC can be expanded
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
await this.$store.dispatch(`${ inStore }/findAll`, { type: STORAGE_CLASS });
|
|
30
|
+
} catch (e) {
|
|
31
|
+
this.$emit('error', e?.data || e);
|
|
32
|
+
}
|
|
29
33
|
await this.$fetchType(this.resource);
|
|
30
34
|
}
|
|
31
35
|
};
|
|
@@ -4,28 +4,6 @@ jest.mock('@shell/utils/clipboard', () => {
|
|
|
4
4
|
return { copyTextToClipboard: jest.fn(() => Promise.resolve({})) };
|
|
5
5
|
});
|
|
6
6
|
|
|
7
|
-
const importedRKE2ClusterInfo = { status: { driver: 'rke2', provider: 'rke2' } };
|
|
8
|
-
|
|
9
|
-
const provisionedRKE2ClusterInfo = { status: { driver: 'rke2', provider: 'imported' } };
|
|
10
|
-
|
|
11
|
-
const importedK3sClusterInfo = { status: { driver: 'k3s', provider: 'k3s' } };
|
|
12
|
-
|
|
13
|
-
const provisionedK3sClusterInfo = { status: { driver: 'k3s', provider: 'imported' } };
|
|
14
|
-
|
|
15
|
-
const importedAksClusterInfo = { spec: { aksConfig: { imported: true } }, status: { provider: 'aks', driver: 'AKS' } };
|
|
16
|
-
|
|
17
|
-
const provisionedAksClusterInfo = { spec: { aksConfig: { imported: false } }, status: { provider: 'aks', driver: 'AKS' } };
|
|
18
|
-
|
|
19
|
-
const importedRKE1ClusterInfo = { status: { provider: 'rke', driver: 'imported' } };
|
|
20
|
-
|
|
21
|
-
const provisionedRKE1ClusterInfo = { status: { provider: 'rke', driver: 'rancherKubernetesEngine' } };
|
|
22
|
-
|
|
23
|
-
const localRKE1ClusterInfo = { status: { provider: 'rke', driver: 'imported' } };
|
|
24
|
-
|
|
25
|
-
const localRKE2ClusterInfo = { status: { provider: 'rke2', driver: 'rke2' } };
|
|
26
|
-
|
|
27
|
-
const localEKSClusterInfo = { status: { provider: 'eks', driver: 'imported' } };
|
|
28
|
-
|
|
29
7
|
describe('class MgmtCluster', () => {
|
|
30
8
|
describe('provisioner', () => {
|
|
31
9
|
const testCases = [
|
|
@@ -42,24 +20,4 @@ describe('class MgmtCluster', () => {
|
|
|
42
20
|
}
|
|
43
21
|
);
|
|
44
22
|
});
|
|
45
|
-
|
|
46
|
-
describe('isImported', () => {
|
|
47
|
-
it.each([
|
|
48
|
-
[importedRKE2ClusterInfo, true],
|
|
49
|
-
[provisionedRKE2ClusterInfo, false],
|
|
50
|
-
[importedK3sClusterInfo, true],
|
|
51
|
-
[provisionedK3sClusterInfo, false],
|
|
52
|
-
[importedAksClusterInfo, true],
|
|
53
|
-
[provisionedAksClusterInfo, false],
|
|
54
|
-
[importedRKE1ClusterInfo, true],
|
|
55
|
-
[provisionedRKE1ClusterInfo, false],
|
|
56
|
-
[localRKE1ClusterInfo, true],
|
|
57
|
-
[localRKE2ClusterInfo, true],
|
|
58
|
-
[localEKSClusterInfo, true]
|
|
59
|
-
])('should return isImported based on props data', (clusterData, expected) => {
|
|
60
|
-
const cluster = new MgmtCluster(clusterData);
|
|
61
|
-
|
|
62
|
-
expect(cluster.isImported).toBe(expected);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
23
|
});
|
|
@@ -89,30 +89,6 @@ export default class MgmtCluster extends SteveModel {
|
|
|
89
89
|
return pools.filter((x) => x.spec?.clusterName === this.id);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
get isImported() {
|
|
93
|
-
if (this.isLocal) {
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
// imported rke2 and k3s have status.driver === rke2 and k3s respectively
|
|
97
|
-
// Provisioned rke2 and k3s have status.driver === imported
|
|
98
|
-
if (this.status?.provider === 'k3s' || this.status?.provider === 'rke2') {
|
|
99
|
-
return this.status?.driver === this.status?.provider;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// imported KEv2
|
|
103
|
-
const kontainerConfigs = ['aksConfig', 'eksConfig', 'gkeConfig'];
|
|
104
|
-
|
|
105
|
-
const isImportedKontainer = kontainerConfigs.filter((key) => {
|
|
106
|
-
return this.spec?.[key]?.imported === true;
|
|
107
|
-
}).length;
|
|
108
|
-
|
|
109
|
-
if (isImportedKontainer) {
|
|
110
|
-
return true;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return this.provisioner === 'imported';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
92
|
get provisioner() {
|
|
117
93
|
// For imported K3s clusters, this.status.driver is 'k3s.'
|
|
118
94
|
return this.status?.driver ? this.status.driver : 'imported';
|
|
@@ -117,6 +117,7 @@ export default class GlobalRole extends SteveDescriptionModel {
|
|
|
117
117
|
norman.id = this.id;
|
|
118
118
|
norman.name = this.displayName;
|
|
119
119
|
norman.description = this.description;
|
|
120
|
+
norman.inheritedClusterRoles = this.inheritedClusterRoles;
|
|
120
121
|
|
|
121
122
|
return norman;
|
|
122
123
|
})();
|
package/models/nodedriver.js
CHANGED
|
@@ -18,7 +18,7 @@ export default class NodeDriver extends Driver {
|
|
|
18
18
|
icon: 'icon icon-play',
|
|
19
19
|
bulkable: true,
|
|
20
20
|
bulkAction: 'activateBulk',
|
|
21
|
-
enabled: !!this.actions
|
|
21
|
+
enabled: !!this.actions?.activate && this.state === 'inactive',
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
action: 'deactivate',
|
|
@@ -26,7 +26,7 @@ export default class NodeDriver extends Driver {
|
|
|
26
26
|
icon: 'icon icon-pause',
|
|
27
27
|
bulkable: true,
|
|
28
28
|
bulkAction: 'deactivateBulk',
|
|
29
|
-
enabled: !!this.actions
|
|
29
|
+
enabled: !!this.actions?.deactivate && this.state === 'active',
|
|
30
30
|
weight: -1,
|
|
31
31
|
},
|
|
32
32
|
{ divider: true },
|
|
@@ -245,7 +245,7 @@ export default class ProvCluster extends SteveModel {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
get canDelete() {
|
|
248
|
-
return super.canDelete && this.stateObj
|
|
248
|
+
return super.canDelete && this.stateObj?.name !== 'removing';
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
get canEditYaml() {
|
|
@@ -282,7 +282,29 @@ export default class ProvCluster extends SteveModel {
|
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
get isImported() {
|
|
285
|
-
|
|
285
|
+
if (this.isLocal) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// imported rke2 and k3s have status.driver === rke2 and k3s respectively
|
|
290
|
+
// Provisioned rke2 and k3s have status.driver === imported
|
|
291
|
+
if (this.mgmt?.status?.provider === 'k3s' || this.mgmt?.status?.provider === 'rke2') {
|
|
292
|
+
return this.mgmt?.status?.driver === this.mgmt?.status?.provider;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// imported KEv2
|
|
296
|
+
// we can't rely on this.provisioner to determine imported-ness for these clusters, as it will return 'aks' 'eks' 'gke' for both provisioned and imported clusters
|
|
297
|
+
const kontainerConfigs = ['aksConfig', 'eksConfig', 'gkeConfig'];
|
|
298
|
+
|
|
299
|
+
const isImportedKontainer = kontainerConfigs.filter((key) => {
|
|
300
|
+
return this.mgmt?.spec?.[key]?.imported === true;
|
|
301
|
+
}).length;
|
|
302
|
+
|
|
303
|
+
if (isImportedKontainer) {
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return this.provisioner === 'imported';
|
|
286
308
|
}
|
|
287
309
|
|
|
288
310
|
get isCustom() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.1-rc.
|
|
3
|
+
"version": "3.0.1-rc.4",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -131,7 +131,6 @@
|
|
|
131
131
|
"vue-router": "4.4.3",
|
|
132
132
|
"vue-select": "4.0.0-beta.6",
|
|
133
133
|
"vue-server-renderer": "2.7.16",
|
|
134
|
-
"vue-template-compiler": "2.7.16",
|
|
135
134
|
"vue3-resize": "0.2.0",
|
|
136
135
|
"vue3-virtual-scroll-list": "0.2.1",
|
|
137
136
|
"vuedraggable": "4.1.0",
|
|
@@ -170,4 +169,4 @@
|
|
|
170
169
|
".vue"
|
|
171
170
|
]
|
|
172
171
|
}
|
|
173
|
-
}
|
|
172
|
+
}
|
package/pages/auth/setup.vue
CHANGED
|
@@ -11,7 +11,6 @@ import { getVendor, getProduct, setVendor } from '@shell/config/private-label';
|
|
|
11
11
|
import { RadioGroup } from '@components/Form/Radio';
|
|
12
12
|
import { setSetting } from '@shell/utils/settings';
|
|
13
13
|
import { SETTING } from '@shell/config/settings';
|
|
14
|
-
import { isDevBuild } from '@shell/utils/version';
|
|
15
14
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
16
15
|
import Password from '@shell/components/form/Password';
|
|
17
16
|
import { applyProducts } from '@shell/store/type-map';
|
|
@@ -66,7 +65,6 @@ export default {
|
|
|
66
65
|
v3User: null,
|
|
67
66
|
serverUrl: null,
|
|
68
67
|
mcmEnabled: null,
|
|
69
|
-
telemetry: null,
|
|
70
68
|
eula: false,
|
|
71
69
|
principals: null,
|
|
72
70
|
errors: []
|
|
@@ -101,16 +99,7 @@ export default {
|
|
|
101
99
|
},
|
|
102
100
|
|
|
103
101
|
async fetch() {
|
|
104
|
-
const telemetrySetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.TELEMETRY);
|
|
105
102
|
const serverUrlSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SERVER_URL);
|
|
106
|
-
const rancherVersionSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.VERSION_RANCHER);
|
|
107
|
-
let telemetry = true;
|
|
108
|
-
|
|
109
|
-
if (telemetrySetting?.value && telemetrySetting.value !== 'prompt') {
|
|
110
|
-
telemetry = telemetrySetting.value !== 'out';
|
|
111
|
-
} else if (!rancherVersionSetting?.value || isDevBuild(rancherVersionSetting?.value)) {
|
|
112
|
-
telemetry = false;
|
|
113
|
-
}
|
|
114
103
|
|
|
115
104
|
let plSetting;
|
|
116
105
|
|
|
@@ -163,7 +152,6 @@ export default {
|
|
|
163
152
|
this['v3User'] = v3User;
|
|
164
153
|
this['serverUrl'] = serverUrl;
|
|
165
154
|
this['mcmEnabled'] = mcmEnabled;
|
|
166
|
-
this['telemetry'] = telemetry;
|
|
167
155
|
this['principals'] = principals;
|
|
168
156
|
},
|
|
169
157
|
|
|
@@ -244,7 +232,6 @@ export default {
|
|
|
244
232
|
|
|
245
233
|
if (this.isFirstLogin) {
|
|
246
234
|
promises.push( setSetting(this.$store, SETTING.EULA_AGREED, (new Date()).toISOString()) );
|
|
247
|
-
promises.push( setSetting(this.$store, SETTING.TELEMETRY, this.telemetry ? 'in' : 'out') );
|
|
248
235
|
|
|
249
236
|
if ( this.mcmEnabled && this.serverUrl ) {
|
|
250
237
|
promises.push( setSetting(this.$store, SETTING.SERVER_URL, this.serverUrl) );
|
|
@@ -406,20 +393,6 @@ export default {
|
|
|
406
393
|
</div>
|
|
407
394
|
</template>
|
|
408
395
|
|
|
409
|
-
<div class="checkbox mt-40">
|
|
410
|
-
<Checkbox
|
|
411
|
-
id="checkbox-telemetry"
|
|
412
|
-
v-model:value="telemetry"
|
|
413
|
-
>
|
|
414
|
-
<template #label>
|
|
415
|
-
<t
|
|
416
|
-
k="setup.telemetry"
|
|
417
|
-
:raw="true"
|
|
418
|
-
:name="productName"
|
|
419
|
-
/>
|
|
420
|
-
</template>
|
|
421
|
-
</Checkbox>
|
|
422
|
-
</div>
|
|
423
396
|
<div class="checkbox pt-10 eula">
|
|
424
397
|
<Checkbox
|
|
425
398
|
id="checkbox-eula"
|
|
@@ -461,6 +434,9 @@ export default {
|
|
|
461
434
|
</h4>
|
|
462
435
|
</div>
|
|
463
436
|
</div>
|
|
437
|
+
<div>
|
|
438
|
+
|
|
439
|
+
</div>
|
|
464
440
|
</div>
|
|
465
441
|
<BrandImage
|
|
466
442
|
class="col span-6 landscape"
|
|
@@ -517,11 +493,14 @@ export default {
|
|
|
517
493
|
width: 51%;
|
|
518
494
|
|
|
519
495
|
& > div:first-of-type {
|
|
520
|
-
flex:3;
|
|
496
|
+
flex: 3;
|
|
521
497
|
}
|
|
522
498
|
& > div:nth-of-type(2) {
|
|
523
499
|
flex: 9;
|
|
524
500
|
}
|
|
501
|
+
& > div:nth-of-type(3) {
|
|
502
|
+
flex: 2;
|
|
503
|
+
}
|
|
525
504
|
}
|
|
526
505
|
|
|
527
506
|
.setup-title {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { mapGetters } from 'vuex';
|
|
3
2
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
4
3
|
import Tabbed from '@shell/components/Tabbed';
|
|
5
4
|
import { MANAGEMENT } from '@shell/config/types';
|
|
@@ -8,7 +7,6 @@ import Loading from '@shell/components/Loading';
|
|
|
8
7
|
import { SUBTYPE_MAPPING, CREATE_VERBS } from '@shell/models/management.cattle.io.roletemplate';
|
|
9
8
|
import { NAME } from '@shell/config/product/auth';
|
|
10
9
|
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
11
|
-
import { Banner } from '@components/Banner';
|
|
12
10
|
|
|
13
11
|
const GLOBAL = SUBTYPE_MAPPING.GLOBAL.key;
|
|
14
12
|
const CLUSTER = SUBTYPE_MAPPING.CLUSTER.key;
|
|
@@ -33,7 +31,7 @@ export default {
|
|
|
33
31
|
name: 'Roles',
|
|
34
32
|
|
|
35
33
|
components: {
|
|
36
|
-
Tab, Tabbed, ResourceTable, Loading
|
|
34
|
+
Tab, Tabbed, ResourceTable, Loading
|
|
37
35
|
},
|
|
38
36
|
|
|
39
37
|
async fetch() {
|
|
@@ -100,8 +98,6 @@ export default {
|
|
|
100
98
|
},
|
|
101
99
|
|
|
102
100
|
computed: {
|
|
103
|
-
...mapGetters(['releaseNotesUrl']),
|
|
104
|
-
|
|
105
101
|
globalResources() {
|
|
106
102
|
return this.globalRoles;
|
|
107
103
|
},
|
|
@@ -183,12 +179,6 @@ export default {
|
|
|
183
179
|
:weight="tabs[GLOBAL].weight"
|
|
184
180
|
:label-key="tabs[GLOBAL].labelKey"
|
|
185
181
|
>
|
|
186
|
-
<Banner
|
|
187
|
-
color="warning"
|
|
188
|
-
class="mb-20"
|
|
189
|
-
>
|
|
190
|
-
<span v-clean-html="t('rbac.globalRoles.role.restricted-admin.deprecation', { releaseNotesUrl }, true)" />
|
|
191
|
-
</Banner>
|
|
192
182
|
<ResourceTable
|
|
193
183
|
:schema="tabs[GLOBAL].schema"
|
|
194
184
|
:rows="globalResources"
|
|
@@ -3,6 +3,7 @@ import Dashboard from '@shell/pages/c/_cluster/explorer/index.vue';
|
|
|
3
3
|
import { shallowMount } from '@vue/test-utils';
|
|
4
4
|
import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
5
5
|
import { NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
|
|
6
|
+
import { WORKLOAD_TYPES } from '@shell/config/types';
|
|
6
7
|
|
|
7
8
|
describe('page: cluster dashboard', () => {
|
|
8
9
|
const mountOptions = {
|
|
@@ -97,12 +98,81 @@ describe('page: cluster dashboard', () => {
|
|
|
97
98
|
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
|
|
98
99
|
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
|
|
99
100
|
]]
|
|
100
|
-
])('%p cluster - %p agent health box', (_, agentId, isLocal, agentResources, statuses) => {
|
|
101
|
+
])('%p cluster - %p agent health box :', (_, agentId, isLocal, agentResources, statuses) => {
|
|
102
|
+
it.each(statuses)('should NOT show %p status due to missing canList permissions', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
|
|
103
|
+
const options = clone(mountOptions);
|
|
104
|
+
|
|
105
|
+
options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
|
|
106
|
+
|
|
107
|
+
const resources = agentResources.reduce((acc, r) => {
|
|
108
|
+
const agent = {
|
|
109
|
+
metadata: { state: { error } },
|
|
110
|
+
spec: { replicas: 1 },
|
|
111
|
+
status: {
|
|
112
|
+
readyReplicas,
|
|
113
|
+
unavailableReplicas,
|
|
114
|
+
conditions
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return isLoaded ? {
|
|
119
|
+
...acc,
|
|
120
|
+
[r]: agent
|
|
121
|
+
} : 'loading';
|
|
122
|
+
}, {});
|
|
123
|
+
|
|
124
|
+
const wrapper = shallowMount(Dashboard, {
|
|
125
|
+
...options,
|
|
126
|
+
data: () => ({
|
|
127
|
+
...resources,
|
|
128
|
+
disconnected,
|
|
129
|
+
canViewAgents: true
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const box = wrapper.find(`[data-testid="k8s-service-${ agentId }"]`);
|
|
134
|
+
|
|
135
|
+
expect(box.exists()).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe.each([
|
|
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],
|
|
148
|
+
]],
|
|
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],
|
|
157
|
+
]],
|
|
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],
|
|
166
|
+
]]
|
|
167
|
+
])('%p cluster - %p agent health box ::', (_, agentId, isLocal, agentResources, statuses) => {
|
|
101
168
|
it.each(statuses)('should show %p status', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
|
|
102
169
|
const options = clone(mountOptions);
|
|
103
170
|
|
|
104
171
|
options.global.mocks.$store.getters.currentCluster.isLocal = isLocal;
|
|
105
172
|
|
|
173
|
+
// let's pass the canList now
|
|
174
|
+
options.global.mocks.$store.getters['cluster/canList'] = (type: string) => !!(type === WORKLOAD_TYPES.DEPLOYMENT) || !!(type === WORKLOAD_TYPES.STATEFUL_SET);
|
|
175
|
+
|
|
106
176
|
const resources = agentResources.reduce((acc, r) => {
|
|
107
177
|
const agent = {
|
|
108
178
|
metadata: { state: { error } },
|
|
@@ -188,7 +188,11 @@ export default {
|
|
|
188
188
|
},
|
|
189
189
|
|
|
190
190
|
fleetAgentNamespace() {
|
|
191
|
-
|
|
191
|
+
if (this.currentCluster.isLocal) {
|
|
192
|
+
return this.$store.getters['cluster/canList'](WORKLOAD_TYPES.DEPLOYMENT) && this.$store.getters['cluster/canList'](WORKLOAD_TYPES.STATEFUL_SET) && this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-fleet-system');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return this.$store.getters['cluster/canList'](WORKLOAD_TYPES.STATEFUL_SET) && this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-fleet-system');
|
|
192
196
|
},
|
|
193
197
|
|
|
194
198
|
cattleAgentNamespace() {
|
|
@@ -196,7 +200,7 @@ export default {
|
|
|
196
200
|
return;
|
|
197
201
|
}
|
|
198
202
|
|
|
199
|
-
return this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-system');
|
|
203
|
+
return this.$store.getters['cluster/canList'](WORKLOAD_TYPES.DEPLOYMENT) && this.$store.getters['cluster/byId'](NAMESPACE, 'cattle-system');
|
|
200
204
|
},
|
|
201
205
|
|
|
202
206
|
canViewAgents() {
|