@rancher/shell 3.0.0-rc.9 → 3.0.0
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/translations/en-us.yaml +12 -11
- package/assets/translations/zh-hans.yaml +1 -4
- package/components/EmberPage.vue +0 -8
- package/components/ResourceTable.vue +26 -1
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +17 -1
- package/components/SortableTable/selection.js +1 -1
- package/components/SortableTable/sorting.js +11 -3
- package/components/fleet/FleetClusters.vue +0 -3
- package/components/form/HookOption.vue +31 -29
- package/components/form/LabeledSelect.vue +0 -1
- package/components/form/LifecycleHooks.vue +2 -2
- package/components/formatter/SecretData.vue +1 -1
- package/components/nav/Header.vue +10 -13
- package/components/nav/TopLevelMenu.vue +0 -40
- package/components/nav/WorkspaceSwitcher.vue +0 -1
- package/config/private-label.js +2 -1
- package/config/router/routes.js +2 -26
- package/config/settings.ts +5 -0
- package/config/version.js +2 -0
- package/detail/catalog.cattle.io.app.vue +17 -4
- package/detail/fleet.cattle.io.cluster.vue +11 -9
- package/detail/fleet.cattle.io.gitrepo.vue +1 -1
- package/edit/cis.cattle.io.clusterscan.vue +4 -3
- package/edit/fleet.cattle.io.gitrepo.vue +11 -8
- package/edit/management.cattle.io.project.vue +2 -1
- package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +5 -5
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +26 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +63 -149
- package/edit/provisioning.cattle.io.cluster/rke2.vue +3 -1
- package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +7 -2
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +108 -35
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +1 -1
- package/edit/workload/mixins/workload.js +1 -1
- package/mixins/browser-tab-visibility.js +1 -1
- package/mixins/chart.js +6 -2
- package/mixins/metric-poller.js +1 -1
- package/mixins/resource-fetch.js +1 -1
- package/models/catalog.cattle.io.app.js +108 -21
- package/models/cloudcredential.js +4 -4
- package/models/fleet.cattle.io.gitrepo.js +8 -13
- package/models/management.cattle.io.cluster.js +13 -2
- package/models/management.cattle.io.project.js +4 -0
- package/models/provisioning.cattle.io.cluster.js +1 -2
- package/models/workload.js +1 -1
- package/package.json +3 -3
- package/pages/auth/logout.vue +7 -9
- package/pages/auth/setup.vue +3 -0
- package/pages/c/_cluster/apps/charts/install.vue +11 -3
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +1 -1
- package/pages/c/_cluster/explorer/index.vue +1 -2
- package/pages/c/_cluster/fleet/index.vue +11 -5
- package/pages/c/_cluster/uiplugins/index.vue +4 -2
- package/pages/diagnostic.vue +1 -0
- package/plugins/steve/mutations.js +4 -1
- package/plugins/steve/subscribe.js +3 -4
- package/types/shell/index.d.ts +13 -0
- package/utils/__tests__/object.test.ts +152 -1
- package/utils/object.js +37 -0
- package/utils/string.js +9 -0
- package/utils/validators/formRules/index.ts +1 -1
- package/config/product/multi-cluster-apps.js +0 -61
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
|
|
2
2
|
<script>
|
|
3
|
-
import { Checkbox } from '@components/Form/Checkbox';
|
|
4
3
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
5
4
|
import { _CREATE } from '@shell/config/query-params';
|
|
5
|
+
import RadioGroup from '@components/Form/Radio/RadioGroup.vue';
|
|
6
|
+
|
|
7
|
+
export const DATA_DIR_RADIO_OPTIONS = {
|
|
8
|
+
DEFAULT: 'defaultDataDir',
|
|
9
|
+
COMMON: 'commonBaseDataDir',
|
|
10
|
+
CUSTOM: 'customDataDir',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const DEFAULT_COMMON_BASE_PATH = '/var/lib/rancher';
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_SUBDIRS = {
|
|
16
|
+
AGENT: 'agent',
|
|
17
|
+
PROVISIONING: 'provisioning',
|
|
18
|
+
K8S_DISTRO_RKE2: 'rke2',
|
|
19
|
+
K8S_DISTRO_K3S: 'k3s',
|
|
20
|
+
};
|
|
6
21
|
|
|
7
22
|
export default {
|
|
8
23
|
name: 'DirectoryConfig',
|
|
9
24
|
components: {
|
|
10
|
-
Checkbox,
|
|
11
25
|
LabeledInput,
|
|
26
|
+
RadioGroup
|
|
12
27
|
},
|
|
13
28
|
props: {
|
|
14
29
|
mode: {
|
|
@@ -16,52 +31,114 @@ export default {
|
|
|
16
31
|
required: true,
|
|
17
32
|
},
|
|
18
33
|
|
|
34
|
+
k8sVersion: {
|
|
35
|
+
type: String,
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
|
|
19
39
|
value: {
|
|
20
40
|
type: Object,
|
|
21
41
|
required: true,
|
|
22
42
|
},
|
|
23
43
|
},
|
|
24
44
|
data() {
|
|
25
|
-
let
|
|
26
|
-
let
|
|
27
|
-
|
|
28
|
-
if (this.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
45
|
+
let dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
|
|
46
|
+
let k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
|
|
47
|
+
|
|
48
|
+
if (this.k8sVersion && this.k8sVersion.includes('k3s')) {
|
|
49
|
+
k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_K3S;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (this.mode !== _CREATE) {
|
|
53
|
+
if (this.value?.systemAgent?.length || this.value?.provisioning?.length || this.value?.k8sDistro?.length) {
|
|
54
|
+
dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
|
|
33
55
|
}
|
|
34
56
|
}
|
|
35
57
|
|
|
36
58
|
return {
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
DATA_DIR_RADIO_OPTIONS,
|
|
60
|
+
dataConfigRadioValue,
|
|
61
|
+
k8sDistroSubDir,
|
|
62
|
+
commonConfig: '',
|
|
39
63
|
};
|
|
40
64
|
},
|
|
41
65
|
watch: {
|
|
42
66
|
commonConfig(neu) {
|
|
43
|
-
if (neu && neu.length && this.
|
|
44
|
-
this.value.systemAgent = neu
|
|
45
|
-
this.value.provisioning = neu
|
|
46
|
-
this.value.k8sDistro = neu
|
|
67
|
+
if (neu && neu.length && this.dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.COMMON) {
|
|
68
|
+
this.value.systemAgent = `${ neu }/${ DEFAULT_SUBDIRS.AGENT }`;
|
|
69
|
+
this.value.provisioning = `${ neu }/${ DEFAULT_SUBDIRS.PROVISIONING }`;
|
|
70
|
+
this.value.k8sDistro = `${ neu }/${ this.k8sDistroSubDir }`;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
k8sVersion: {
|
|
74
|
+
handler(neu) {
|
|
75
|
+
if (neu && neu.includes('k3s')) {
|
|
76
|
+
this.k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_K3S;
|
|
77
|
+
} else {
|
|
78
|
+
this.k8sDistroSubDir = DEFAULT_SUBDIRS.K8S_DISTRO_RKE2;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (this.value.k8sDistro) {
|
|
82
|
+
this.value.k8sDistro = `${ neu }/${ this.k8sDistroSubDir }`;
|
|
83
|
+
}
|
|
47
84
|
}
|
|
48
85
|
}
|
|
49
86
|
},
|
|
50
87
|
computed: {
|
|
51
|
-
|
|
52
|
-
|
|
88
|
+
dataConfigRadioOptions() {
|
|
89
|
+
const defaultDataDirOption = {
|
|
90
|
+
value: DATA_DIR_RADIO_OPTIONS.DEFAULT,
|
|
91
|
+
label: this.t('cluster.directoryConfig.radioInput.defaultLabel')
|
|
92
|
+
};
|
|
93
|
+
const customDataDirOption = {
|
|
94
|
+
value: DATA_DIR_RADIO_OPTIONS.CUSTOM,
|
|
95
|
+
label: this.t('cluster.directoryConfig.radioInput.customLabel')
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (this.mode === _CREATE) {
|
|
99
|
+
return [
|
|
100
|
+
defaultDataDirOption,
|
|
101
|
+
{ value: DATA_DIR_RADIO_OPTIONS.COMMON, label: this.t('cluster.directoryConfig.radioInput.commonLabel') },
|
|
102
|
+
customDataDirOption
|
|
103
|
+
];
|
|
104
|
+
} else {
|
|
105
|
+
return [
|
|
106
|
+
defaultDataDirOption,
|
|
107
|
+
customDataDirOption
|
|
108
|
+
];
|
|
109
|
+
}
|
|
53
110
|
}
|
|
54
111
|
},
|
|
55
112
|
methods: {
|
|
56
|
-
|
|
57
|
-
|
|
113
|
+
handleRadioInput(val) {
|
|
114
|
+
switch (val) {
|
|
115
|
+
case DATA_DIR_RADIO_OPTIONS.DEFAULT:
|
|
116
|
+
if (this.mode === _CREATE) {
|
|
117
|
+
this.commonConfig = '';
|
|
118
|
+
}
|
|
119
|
+
this.value.systemAgent = '';
|
|
120
|
+
this.value.provisioning = '';
|
|
121
|
+
this.value.k8sDistro = '';
|
|
122
|
+
|
|
123
|
+
this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.DEFAULT;
|
|
124
|
+
break;
|
|
125
|
+
case DATA_DIR_RADIO_OPTIONS.COMMON:
|
|
126
|
+
this.commonConfig = DEFAULT_COMMON_BASE_PATH;
|
|
127
|
+
|
|
128
|
+
this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.COMMON;
|
|
129
|
+
break;
|
|
130
|
+
// default is custom config
|
|
131
|
+
default:
|
|
132
|
+
if (this.mode === _CREATE) {
|
|
133
|
+
this.commonConfig = '';
|
|
134
|
+
}
|
|
58
135
|
|
|
59
|
-
if (val) {
|
|
60
136
|
this.value.systemAgent = '';
|
|
61
137
|
this.value.provisioning = '';
|
|
62
138
|
this.value.k8sDistro = '';
|
|
63
|
-
|
|
64
|
-
this.
|
|
139
|
+
|
|
140
|
+
this.dataConfigRadioValue = DATA_DIR_RADIO_OPTIONS.CUSTOM;
|
|
141
|
+
break;
|
|
65
142
|
}
|
|
66
143
|
}
|
|
67
144
|
},
|
|
@@ -74,33 +151,31 @@ export default {
|
|
|
74
151
|
<h3 class="mb-20">
|
|
75
152
|
{{ t('cluster.directoryConfig.title') }}
|
|
76
153
|
</h3>
|
|
77
|
-
<
|
|
154
|
+
<RadioGroup
|
|
155
|
+
:value="dataConfigRadioValue"
|
|
78
156
|
class="mb-10"
|
|
79
|
-
:value="isSettingCommonConfig"
|
|
80
157
|
:mode="mode"
|
|
81
|
-
:
|
|
82
|
-
|
|
83
|
-
data-testid="rke2-directory-config-
|
|
84
|
-
@update:value="
|
|
158
|
+
:options="dataConfigRadioOptions"
|
|
159
|
+
name="directory-config-radio"
|
|
160
|
+
data-testid="rke2-directory-config-radio-input"
|
|
161
|
+
@update:value="handleRadioInput"
|
|
85
162
|
/>
|
|
86
163
|
<LabeledInput
|
|
87
|
-
v-if="
|
|
164
|
+
v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.COMMON"
|
|
88
165
|
v-model:value="commonConfig"
|
|
89
166
|
class="mb-20"
|
|
90
167
|
:mode="mode"
|
|
91
168
|
:label="t('cluster.directoryConfig.common.label')"
|
|
92
169
|
:tooltip="t('cluster.directoryConfig.common.tooltip')"
|
|
93
|
-
:disabled="disableEditInput"
|
|
94
170
|
data-testid="rke2-directory-config-common-data-dir"
|
|
95
171
|
/>
|
|
96
|
-
<div v-if="
|
|
172
|
+
<div v-if="dataConfigRadioValue === DATA_DIR_RADIO_OPTIONS.CUSTOM">
|
|
97
173
|
<LabeledInput
|
|
98
174
|
v-model:value="value.systemAgent"
|
|
99
175
|
class="mb-20"
|
|
100
176
|
:mode="mode"
|
|
101
177
|
:label="t('cluster.directoryConfig.systemAgent.label')"
|
|
102
178
|
:tooltip="t('cluster.directoryConfig.systemAgent.tooltip')"
|
|
103
|
-
:disabled="disableEditInput"
|
|
104
179
|
data-testid="rke2-directory-config-systemAgent-data-dir"
|
|
105
180
|
/>
|
|
106
181
|
<LabeledInput
|
|
@@ -109,7 +184,6 @@ export default {
|
|
|
109
184
|
:mode="mode"
|
|
110
185
|
:label="t('cluster.directoryConfig.provisioning.label')"
|
|
111
186
|
:tooltip="t('cluster.directoryConfig.provisioning.tooltip')"
|
|
112
|
-
:disabled="disableEditInput"
|
|
113
187
|
data-testid="rke2-directory-config-provisioning-data-dir"
|
|
114
188
|
/>
|
|
115
189
|
<LabeledInput
|
|
@@ -118,7 +192,6 @@ export default {
|
|
|
118
192
|
:mode="mode"
|
|
119
193
|
:label="t('cluster.directoryConfig.k8sDistro.label')"
|
|
120
194
|
:tooltip="t('cluster.directoryConfig.k8sDistro.tooltip')"
|
|
121
|
-
:disabled="disableEditInput"
|
|
122
195
|
data-testid="rke2-directory-config-k8sDistro-data-dir"
|
|
123
196
|
/>
|
|
124
197
|
</div>
|
|
@@ -154,7 +154,6 @@ export default {
|
|
|
154
154
|
:mode="mode"
|
|
155
155
|
:data-testid="`registry-auth-host-input-${i}`"
|
|
156
156
|
/>
|
|
157
|
-
|
|
158
157
|
<SelectOrCreateAuthSecret
|
|
159
158
|
v-model:value="row.value.authConfigSecretName"
|
|
160
159
|
:register-before-hook="wrapRegisterBeforeHook"
|
|
@@ -168,6 +167,7 @@ export default {
|
|
|
168
167
|
generate-name="registryconfig-auth-"
|
|
169
168
|
:data-testid="`registry-auth-select-or-create-${i}`"
|
|
170
169
|
:cache-secrets="true"
|
|
170
|
+
@update:value="update"
|
|
171
171
|
/>
|
|
172
172
|
</div>
|
|
173
173
|
<div class="col span-6">
|
package/mixins/chart.js
CHANGED
|
@@ -291,6 +291,8 @@ export default {
|
|
|
291
291
|
id: `${ this.query.appNamespace }/${ this.query.appName }`,
|
|
292
292
|
});
|
|
293
293
|
|
|
294
|
+
await this.existing?.fetchValues(true);
|
|
295
|
+
|
|
294
296
|
this.mode = _EDIT;
|
|
295
297
|
} catch (e) {
|
|
296
298
|
this.mode = _CREATE;
|
|
@@ -450,10 +452,12 @@ export default {
|
|
|
450
452
|
}
|
|
451
453
|
}
|
|
452
454
|
if (existingCRDApp) {
|
|
455
|
+
await existingCRDApp.fetchValues(true);
|
|
456
|
+
|
|
453
457
|
// spec.values are any non-default values the user configured
|
|
454
458
|
// the installation form should show these, as well as any default values from the chart
|
|
455
|
-
const existingValues = clone(existingCRDApp.
|
|
456
|
-
const defaultValues = clone(existingCRDApp.
|
|
459
|
+
const existingValues = clone(existingCRDApp.values || {});
|
|
460
|
+
const defaultValues = clone(existingCRDApp.chartValues || {});
|
|
457
461
|
|
|
458
462
|
crdVersionInfo.existingValues = existingValues;
|
|
459
463
|
crdVersionInfo.allValues = merge(defaultValues, existingValues);
|
package/mixins/metric-poller.js
CHANGED
package/mixins/resource-fetch.js
CHANGED
|
@@ -48,7 +48,7 @@ export default {
|
|
|
48
48
|
};
|
|
49
49
|
},
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
beforeUnmount() {
|
|
52
52
|
// make sure this only runs once, for the initialized instance
|
|
53
53
|
if (this.init) {
|
|
54
54
|
// clear up the store to make sure we aren't storing anything that might interfere with the next rendered list view
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import { CATALOG as CATALOG_ANNOTATIONS, FLEET } from '@shell/config/labels-annotations';
|
|
5
5
|
import { compare, isPrerelease, sortable } from '@shell/utils/version';
|
|
6
6
|
import { filterBy } from '@shell/utils/array';
|
|
7
|
-
import { CATALOG, MANAGEMENT, NORMAN } from '@shell/config/types';
|
|
7
|
+
import { CATALOG, MANAGEMENT, NORMAN, SECRET } from '@shell/config/types';
|
|
8
8
|
import { SHOW_PRE_RELEASE } from '@shell/store/prefs';
|
|
9
9
|
import { set } from '@shell/utils/object';
|
|
10
10
|
|
|
@@ -280,28 +280,115 @@ export default class CatalogApp extends SteveModel {
|
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
}
|
|
283
|
+
async deployedAsLegacy() {
|
|
284
|
+
await this.fetchValues();
|
|
285
|
+
|
|
286
|
+
if (this.values?.global) {
|
|
287
|
+
const { clusterName, projectName } = this.values.global;
|
|
288
|
+
|
|
289
|
+
if (clusterName && projectName) {
|
|
290
|
+
try {
|
|
291
|
+
const legacyApp = await this.$dispatch('rancher/find', {
|
|
292
|
+
type: NORMAN.APP,
|
|
293
|
+
id: `${ projectName }:${ this.metadata?.name }`,
|
|
294
|
+
opt: { url: `/v3/project/${ clusterName }:${ projectName }/apps/${ projectName }:${ this.metadata?.name }` }
|
|
295
|
+
}, { root: true });
|
|
296
|
+
|
|
297
|
+
if (legacyApp) {
|
|
298
|
+
return legacyApp;
|
|
299
|
+
}
|
|
300
|
+
} catch (e) {}
|
|
301
301
|
}
|
|
302
|
+
}
|
|
302
303
|
|
|
303
|
-
|
|
304
|
-
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* User and Chart values live in a helm secret, so fetch it (with special param)
|
|
309
|
+
*/
|
|
310
|
+
async fetchValues(force = false) {
|
|
311
|
+
if (!this.secretId) {
|
|
312
|
+
// If there's no secret id this isn't ever going to work, no need to carry on
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const haveValues = !!this._values && !!this._chartValues;
|
|
317
|
+
|
|
318
|
+
if (haveValues && !force) {
|
|
319
|
+
// If we already have the required values and we're not forced to re-fetch, no need to carry on
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
await this.$dispatch('find', {
|
|
325
|
+
type: SECRET,
|
|
326
|
+
id: this.secretId,
|
|
327
|
+
opt: {
|
|
328
|
+
force: force || (!!this._secret && !haveValues), // force if explicitly requested or there's ean existing secret without the required values we have a secret without the values in (Secret has been fetched another way)
|
|
329
|
+
watch: false, // Cannot watch with custom params (they are dropped on calls made when resyncing over socket)
|
|
330
|
+
params: { includeHelmData: true }
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
} catch (e) {
|
|
334
|
+
console.error(`Cannot find values for ${ this.id } (unable to fetch)`, e); // eslint-disable-line no-console
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
get secretId() {
|
|
339
|
+
const metadata = this.metadata;
|
|
340
|
+
const secretReference = metadata.ownerReferences?.find((ow) => ow.kind.toLowerCase() === SECRET);
|
|
341
|
+
|
|
342
|
+
const secretId = secretReference?.name;
|
|
343
|
+
const secretNamespace = metadata.namespace;
|
|
344
|
+
|
|
345
|
+
if (!secretNamespace || !secretId) {
|
|
346
|
+
console.warn(`Cannot find values for ${ this.id } (cannot find related secret namespace or id)`); // eslint-disable-line no-console
|
|
347
|
+
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return `${ secretNamespace }/${ secretId }`;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
get _secret() {
|
|
355
|
+
return this.secretId ? this.$getters['byId'](SECRET, this.secretId) : null;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
_validateSecret(noun) {
|
|
359
|
+
if (this._secret === undefined) {
|
|
360
|
+
throw new Error(`Cannot find ${ noun } for ${ this.id } (chart secret has not been fetched via app \`fetchValues\`)`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (this._secret === null) {
|
|
364
|
+
throw new Error(`Cannot find ${ noun } for ${ this.id } (chart secret cannot or has failed to fetch) `);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* The user's helm values
|
|
370
|
+
*/
|
|
371
|
+
get values() {
|
|
372
|
+
this._validateSecret('values');
|
|
373
|
+
|
|
374
|
+
return this._values;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
get _values() {
|
|
378
|
+
return this._secret?.data?.release?.config;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* The Charts default helm values
|
|
383
|
+
*/
|
|
384
|
+
get chartValues() {
|
|
385
|
+
this._validateSecret('chartValues');
|
|
386
|
+
|
|
387
|
+
return this._chartValues;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
get _chartValues() {
|
|
391
|
+
return this._secret?.data?.release?.chart?.values;
|
|
305
392
|
}
|
|
306
393
|
}
|
|
307
394
|
|
|
@@ -241,9 +241,9 @@ export default class CloudCredential extends NormanModel {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
get expiresForSort() {
|
|
244
|
-
// Why not just `expires`? Ensures the correct sort order of
|
|
245
|
-
// (instead of expired -->
|
|
246
|
-
return this.expires
|
|
244
|
+
// Why not just `expires`? Ensures the correct sort order of expired --> expiring --> never expires
|
|
245
|
+
// (instead of 'never expired' --> 'expired' --> 'expiring')
|
|
246
|
+
return this.expires !== undefined ? this.expires : Number.MAX_SAFE_INTEGER;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
get expires() {
|
|
@@ -296,7 +296,7 @@ export default class CloudCredential extends NormanModel {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
get expiresIn() {
|
|
299
|
-
if (
|
|
299
|
+
if (this.expires === undefined) {
|
|
300
300
|
return null;
|
|
301
301
|
}
|
|
302
302
|
|
|
@@ -176,6 +176,10 @@ export default class GitRepo extends SteveModel {
|
|
|
176
176
|
get repoDisplay() {
|
|
177
177
|
let repo = this.spec.repo;
|
|
178
178
|
|
|
179
|
+
if (!repo) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
179
183
|
repo = repo.replace(/.git$/, '');
|
|
180
184
|
repo = repo.replace(/^https:\/\//, '');
|
|
181
185
|
repo = repo.replace(/\/+$/, '');
|
|
@@ -307,20 +311,11 @@ export default class GitRepo extends SteveModel {
|
|
|
307
311
|
bundle.namespacedName.startsWith(`${ this.namespace }:${ this.name }`));
|
|
308
312
|
}
|
|
309
313
|
|
|
314
|
+
/**
|
|
315
|
+
* Bundles with state of active
|
|
316
|
+
*/
|
|
310
317
|
get bundlesReady() {
|
|
311
|
-
|
|
312
|
-
return this.bundles.filter((bundle) => bundle.state === 'active');
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return 0;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
get targetClustersReady() {
|
|
319
|
-
if (this.targetClusters && this.targetClusters.length) {
|
|
320
|
-
return this.targetClusters.filter((cluster) => cluster.state === 'active');
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return 0;
|
|
318
|
+
return this.bundles?.filter((bundle) => bundle.state === 'active');
|
|
324
319
|
}
|
|
325
320
|
|
|
326
321
|
get bundleDeployments() {
|
|
@@ -16,6 +16,8 @@ import { KONTAINER_TO_DRIVER } from './management.cattle.io.kontainerdriver';
|
|
|
16
16
|
import { PINNED_CLUSTERS } from '@shell/store/prefs';
|
|
17
17
|
import { copyTextToClipboard } from '@shell/utils/clipboard';
|
|
18
18
|
|
|
19
|
+
const DEFAULT_BADGE_COLOR = '#707070';
|
|
20
|
+
|
|
19
21
|
// See translation file cluster.providers for list of providers
|
|
20
22
|
// If the logo is not named with the provider name, add an override here
|
|
21
23
|
const PROVIDER_LOGO_OVERRIDE = {};
|
|
@@ -306,13 +308,22 @@ export default class MgmtCluster extends SteveModel {
|
|
|
306
308
|
return undefined;
|
|
307
309
|
}
|
|
308
310
|
|
|
309
|
-
|
|
311
|
+
let color = this.metadata?.annotations[CLUSTER_BADGE.COLOR] || DEFAULT_BADGE_COLOR;
|
|
310
312
|
const iconText = this.metadata?.annotations[CLUSTER_BADGE.ICON_TEXT] || '';
|
|
313
|
+
let foregroundColor;
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
foregroundColor = textColor(parseColor(color.trim())); // Remove any whitespace
|
|
317
|
+
} catch (_e) {
|
|
318
|
+
// If we could not parse the badge color, use the defaults
|
|
319
|
+
color = DEFAULT_BADGE_COLOR;
|
|
320
|
+
foregroundColor = textColor(parseColor(color));
|
|
321
|
+
}
|
|
311
322
|
|
|
312
323
|
return {
|
|
313
324
|
text: comment || undefined,
|
|
314
325
|
color,
|
|
315
|
-
textColor:
|
|
326
|
+
textColor: foregroundColor,
|
|
316
327
|
iconText: iconText.substr(0, 3)
|
|
317
328
|
};
|
|
318
329
|
}
|
|
@@ -10,7 +10,6 @@ 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 capitalize from 'lodash/capitalize';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* Class representing Cluster resource.
|
|
@@ -424,7 +423,7 @@ export default class ProvCluster extends SteveModel {
|
|
|
424
423
|
if (!node.metadata?.state?.transitioning) {
|
|
425
424
|
const architecture = node.status?.nodeLabels?.[NODE_ARCHITECTURE];
|
|
426
425
|
|
|
427
|
-
const key = architecture
|
|
426
|
+
const key = architecture || this.t('cluster.architecture.label.unknown');
|
|
428
427
|
|
|
429
428
|
obj[key] = (obj[key] || 0) + 1;
|
|
430
429
|
}
|
package/models/workload.js
CHANGED
|
@@ -110,7 +110,7 @@ export default class Workload extends WorkloadService {
|
|
|
110
110
|
spec.template = {
|
|
111
111
|
spec: {
|
|
112
112
|
restartPolicy: this.type === WORKLOAD_TYPES.JOB ? 'Never' : 'Always',
|
|
113
|
-
containers: [{ ...defaultContainer }],
|
|
113
|
+
containers: [{ ...structuredClone(defaultContainer) }],
|
|
114
114
|
initContainers: []
|
|
115
115
|
}
|
|
116
116
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"dagre-d3": "0.6.4",
|
|
75
75
|
"dayjs": "1.8.29",
|
|
76
76
|
"diff2html": "3.4.24",
|
|
77
|
-
"dompurify": "2.4
|
|
77
|
+
"dompurify": "2.5.4",
|
|
78
78
|
"element-matches": "^0.1.2",
|
|
79
79
|
"eslint": "7.32.0",
|
|
80
80
|
"eslint-config-standard": "16.0.3",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"js-yaml": "4.1.0",
|
|
103
103
|
"js-yaml-loader": "1.2.2",
|
|
104
104
|
"jsdiff": "1.1.1",
|
|
105
|
-
"jsonpath-plus": "
|
|
105
|
+
"jsonpath-plus": "10.0.0",
|
|
106
106
|
"jsrsasign": "10.5.25",
|
|
107
107
|
"jszip": "3.8.0",
|
|
108
108
|
"lodash": "4.17.21",
|
package/pages/auth/logout.vue
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
2
|
+
import { configType } from '@shell/models/management.cattle.io.authconfig';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
async fetch() {
|
|
6
|
-
const
|
|
6
|
+
const publicAuthProviders = await this.$store.dispatch('auth/getAuthProviders');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const authProvider = authInfo.enabled[0];
|
|
8
|
+
const samlAuthProvider = publicAuthProviders.find((authProvider) => configType[authProvider.id] === 'saml');
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} = authProvider;
|
|
10
|
+
if (!!samlAuthProvider) {
|
|
11
|
+
const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = samlAuthProvider;
|
|
14
12
|
|
|
15
|
-
if (
|
|
13
|
+
if (logoutAllSupported && logoutAllEnabled && logoutAllForced) {
|
|
16
14
|
// SAML - force SLO (logout from all apps)
|
|
17
15
|
await this.$store.dispatch('auth/logout', {
|
|
18
|
-
force: true, slo: true, provider:
|
|
16
|
+
force: true, slo: true, provider: samlAuthProvider
|
|
19
17
|
}, { root: true });
|
|
20
18
|
} else {
|
|
21
19
|
// simple logout
|
package/pages/auth/setup.vue
CHANGED
|
@@ -496,6 +496,7 @@ export default {
|
|
|
496
496
|
|
|
497
497
|
.span-6 {
|
|
498
498
|
padding: 0 60px;
|
|
499
|
+
margin: 0;
|
|
499
500
|
}
|
|
500
501
|
|
|
501
502
|
.landscape {
|
|
@@ -503,6 +504,7 @@ export default {
|
|
|
503
504
|
margin: 0;
|
|
504
505
|
object-fit: cover;
|
|
505
506
|
padding: 0;
|
|
507
|
+
width: 49%;
|
|
506
508
|
}
|
|
507
509
|
}
|
|
508
510
|
|
|
@@ -512,6 +514,7 @@ export default {
|
|
|
512
514
|
overflow-y: auto;
|
|
513
515
|
position: relative;
|
|
514
516
|
height: 100vh;
|
|
517
|
+
width: 51%;
|
|
515
518
|
|
|
516
519
|
& > div:first-of-type {
|
|
517
520
|
flex:3;
|