@rancher/shell 0.1.3 → 0.1.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/brand/suse/dark/rancher-logo.svg +1 -148
- package/assets/brand/suse/rancher-logo.svg +1 -130
- package/assets/images/featured/img1.jpg +0 -0
- package/assets/images/featured.jpg +0 -0
- package/assets/images/generic-plugin.svg +7 -0
- package/assets/styles/themes/_dark.scss +3 -0
- package/assets/styles/themes/_light.scss +3 -0
- package/assets/styles/themes/_suse.scss +1 -1
- package/assets/translations/en-us.yaml +183 -45
- package/assets/translations/zh-hans.yaml +21 -24
- package/components/AsyncButton.vue +17 -2
- package/components/ButtonDropdown.vue +4 -0
- package/components/Carousel.vue +291 -0
- package/components/CommunityLinks.vue +69 -18
- package/components/CruResource.vue +11 -3
- package/components/Dialog.vue +102 -0
- package/components/ExplorerMembers.vue +2 -4
- package/components/ExplorerProjectsNamespaces.vue +6 -7
- package/components/IconMessage.vue +9 -1
- package/components/LocaleSelector.vue +62 -29
- package/components/ResourceTable.vue +7 -2
- package/components/SimpleBox.vue +6 -4
- package/components/SortableTable/index.vue +11 -21
- package/components/Tabbed/Tab.vue +5 -0
- package/components/Tabbed/index.vue +29 -2
- package/components/auth/Principal.vue +1 -0
- package/components/fleet/FleetBundles.vue +8 -3
- package/components/fleet/FleetSummary.vue +6 -0
- package/components/form/KeyValue.vue +80 -58
- package/components/form/NameNsDescription.vue +10 -4
- package/components/form/ResourceTabs/index.vue +5 -1
- package/components/formatter/ClusterLink.vue +3 -7
- package/components/nav/NamespaceFilter.vue +3 -3
- package/components/nav/TopLevelMenu.vue +10 -28
- package/config/footer.js +13 -14
- package/config/labels-annotations.js +2 -1
- package/config/product/explorer.js +5 -4
- package/config/product/legacy.js +0 -47
- package/config/product/multi-cluster-apps.js +0 -12
- package/config/product/settings.js +12 -1
- package/config/product/uiplugins.js +17 -0
- package/config/settings.js +21 -2
- package/config/types.js +5 -1
- package/config/uiplugins.js +60 -0
- package/content/docs/en-us/getting-started.md +1 -26
- package/core/plugins.js +12 -0
- package/detail/provisioning.cattle.io.cluster.vue +3 -3
- package/detail/workload/index.vue +2 -2
- package/dialog/DiagnosticTimingsDialog.vue +116 -0
- package/dialog/RotateCertificatesDialog.vue +9 -3
- package/edit/auth/azuread.vue +28 -9
- package/edit/networking.k8s.io.ingress/index.vue +2 -2
- package/edit/persistentvolume/index.vue +3 -0
- package/edit/pod.vue +27 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
- package/edit/service.vue +7 -5
- package/edit/workload/__tests__/Upgrading.test.ts +1 -0
- package/edit/workload/index.vue +13 -1
- package/edit/workload/mixins/workload.js +13 -13
- package/edit/workload/storage/ContainerMountPaths.vue +240 -0
- package/edit/workload/storage/Mount.vue +1 -0
- package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
- package/edit/workload/storage/azureDisk.vue +22 -2
- package/edit/workload/storage/azureFile.vue +20 -2
- package/edit/workload/storage/csi/index.vue +23 -1
- package/edit/workload/storage/gcePersistentDisk.vue +20 -2
- package/edit/workload/storage/index.vue +23 -49
- package/edit/workload/storage/vsphereVolume.vue +11 -1
- package/layouts/default.vue +14 -8
- package/layouts/home.vue +9 -4
- package/layouts/plain.vue +10 -5
- package/list/management.cattle.io.setting.vue +3 -3
- package/list/provisioning.cattle.io.cluster.vue +1 -1
- package/machine-config/harvester.vue +5 -3
- package/models/catalog.cattle.io.uiplugin.js +34 -0
- package/models/cluster/node.js +25 -2
- package/models/fleet.cattle.io.bundle.js +1 -1
- package/models/harvesterhci.io.management.cluster.js +11 -5
- package/models/provisioning.cattle.io.cluster.js +12 -6
- package/models/workload.js +5 -3
- package/nuxt.config.js +69 -25
- package/package.json +108 -109
- package/pages/auth/login.vue +1 -1
- package/pages/c/_cluster/apps/charts/index.vue +46 -1
- package/pages/c/_cluster/apps/charts/install.vue +10 -9
- package/pages/c/_cluster/explorer/index.vue +72 -9
- package/pages/c/_cluster/explorer/tools/index.vue +12 -5
- package/pages/c/_cluster/mcapps/index.vue +1 -1
- package/pages/c/_cluster/settings/brand.vue +0 -40
- package/pages/c/_cluster/settings/links.vue +200 -0
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
- package/pages/c/_cluster/uiplugins/index.vue +694 -0
- package/pages/diagnostic.vue +185 -101
- package/pages/docs/_doc.vue +3 -1
- package/pages/home.vue +21 -56
- package/pages/prefs.vue +108 -88
- package/pages/safeMode.vue +17 -0
- package/pages/support/index.vue +23 -15
- package/pkg/dynamic-importer.lib.js +4 -0
- package/plugins/dashboard-store/resource-class.js +2 -2
- package/plugins/formatters.js +15 -0
- package/plugins/plugin.js +56 -4
- package/plugins/steve/mutations.js +1 -1
- package/plugins/steve/subscribe.js +94 -72
- package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
- package/promptRemove/management.cattle.io.globalrole.vue +47 -0
- package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
- package/promptRemove/mixin/roleDeletionCheck.js +97 -0
- package/scripts/publish-shell.sh +1 -1
- package/scripts/sync-shell-deps +37 -0
- package/store/catalog.js +9 -8
- package/store/i18n.js +10 -1
- package/store/prefs.js +16 -0
- package/store/type-map.js +32 -5
- package/store/uiplugins.ts +15 -61
- package/utils/__tests__/object.test.ts +0 -24
- package/utils/__tests__/selector.test.ts +1 -1
- package/utils/dynamic-importer.js +4 -0
- package/utils/grafana.js +2 -6
- package/utils/socket.js +41 -20
- package/utils/string.js +1 -7
- package/utils/validators/formRules/__tests__/index.test.ts +108 -0
- package/utils/validators/formRules/index.ts +9 -1
- package/yarn-error.log +195 -0
- package/pages/plugins.vue +0 -387
- package/server/verdaccio-middleware.js +0 -56
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
3
|
+
|
|
4
|
+
import AsyncButton from '@shell/components/AsyncButton';
|
|
5
|
+
import { Card } from '@components/Card';
|
|
6
|
+
import { Banner } from '@components/Banner';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
components: {
|
|
10
|
+
Card,
|
|
11
|
+
AsyncButton,
|
|
12
|
+
Banner,
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
props: {
|
|
16
|
+
resources: {
|
|
17
|
+
type: Array,
|
|
18
|
+
required: true
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
data() {
|
|
23
|
+
return { errors: [] };
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
computed: {
|
|
27
|
+
config() {
|
|
28
|
+
return this.resources[0];
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
applyMode() {
|
|
32
|
+
return 'diagnostic';
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
title() {
|
|
36
|
+
return this.t('about.diagnostic.modal.title');
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
body() {
|
|
40
|
+
return this.t('about.diagnostic.modal.body');
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
methods: {
|
|
45
|
+
close() {
|
|
46
|
+
this.$emit('close');
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
apply(btnCb) {
|
|
50
|
+
try {
|
|
51
|
+
this.config.downloadData(btnCb);
|
|
52
|
+
this.close();
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error(err); // eslint-disable-line
|
|
55
|
+
this.errors = exceptionToErrorsArray(err);
|
|
56
|
+
btnCb(false);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<template>
|
|
64
|
+
<Card class="prompt-restore" :show-highlight-border="false">
|
|
65
|
+
<h4 slot="title" class="text-default-text" v-html="title" />
|
|
66
|
+
|
|
67
|
+
<template slot="body">
|
|
68
|
+
<slot name="body">
|
|
69
|
+
<div class="pl-10 pr-10" style="min-height: 50px;">
|
|
70
|
+
<div class="row">
|
|
71
|
+
{{ body }}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<AsyncButton
|
|
75
|
+
mode="timing"
|
|
76
|
+
class="row mt-20"
|
|
77
|
+
@click="config.gatherResponseTimes"
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
</slot>
|
|
81
|
+
</template>
|
|
82
|
+
|
|
83
|
+
<div slot="actions" class="bottom">
|
|
84
|
+
<Banner v-for="(err, i) in errors" :key="i" color="error" :label="err" />
|
|
85
|
+
<div class="buttons">
|
|
86
|
+
<button class="btn role-secondary mr-10" @click="close">
|
|
87
|
+
{{ t('generic.cancel') }}
|
|
88
|
+
</button>
|
|
89
|
+
|
|
90
|
+
<AsyncButton
|
|
91
|
+
:mode="applyMode"
|
|
92
|
+
@click="apply"
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</Card>
|
|
97
|
+
</template>
|
|
98
|
+
<style lang='scss' scoped>
|
|
99
|
+
.prompt-restore {
|
|
100
|
+
margin: 0;
|
|
101
|
+
}
|
|
102
|
+
.bottom {
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: column;
|
|
105
|
+
flex: 1;
|
|
106
|
+
.banner {
|
|
107
|
+
margin-top: 0
|
|
108
|
+
}
|
|
109
|
+
.buttons {
|
|
110
|
+
display: flex;
|
|
111
|
+
justify-content: flex-end;
|
|
112
|
+
width: 100%;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
</style>
|
|
@@ -40,19 +40,25 @@ export default {
|
|
|
40
40
|
|
|
41
41
|
serviceOptions() {
|
|
42
42
|
if (this.cluster.isRke2) {
|
|
43
|
-
|
|
43
|
+
const options = [
|
|
44
44
|
'admin',
|
|
45
45
|
'api-server',
|
|
46
46
|
'controller-manager',
|
|
47
47
|
'scheduler',
|
|
48
|
-
'rke2-controller',
|
|
49
|
-
'rke2-server',
|
|
50
48
|
'cloud-controller',
|
|
51
49
|
'etcd',
|
|
52
50
|
'auth-proxy',
|
|
53
51
|
'kubelet',
|
|
54
52
|
'kube-proxy'
|
|
55
53
|
];
|
|
54
|
+
|
|
55
|
+
if ( this.cluster.isK3s ) {
|
|
56
|
+
options.push('k3s-controller', 'k3s-server');
|
|
57
|
+
} else {
|
|
58
|
+
options.push('rke2-controller', 'rke2-server');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return options.sort();
|
|
56
62
|
}
|
|
57
63
|
// For RKE1 clusters, Norman provides the list of service options:
|
|
58
64
|
// type RotateCertificateInput struct {
|
package/edit/auth/azuread.vue
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
2
3
|
import Loading from '@shell/components/Loading';
|
|
3
4
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
4
5
|
import CruResource from '@shell/components/CruResource';
|
|
@@ -76,6 +77,8 @@ export default {
|
|
|
76
77
|
data() {
|
|
77
78
|
return {
|
|
78
79
|
endpoint: 'standard',
|
|
80
|
+
oldEndpoint: false,
|
|
81
|
+
|
|
79
82
|
// Storing the applicationSecret is necessary because norman doesn't support returning secrets and when we
|
|
80
83
|
// override the steve authconfig with a norman config the applicationSecret is lost
|
|
81
84
|
applicationSecret: this.value.applicationSecret
|
|
@@ -147,9 +150,6 @@ export default {
|
|
|
147
150
|
handler() {
|
|
148
151
|
this.model.accessMode = this.model.accessMode || 'unrestricted';
|
|
149
152
|
this.model.rancherUrl = this.model.rancherUrl || this.replyUrl;
|
|
150
|
-
if (this.endpoint !== 'custom') {
|
|
151
|
-
this.setEndpoints(this.endpoint);
|
|
152
|
-
}
|
|
153
153
|
|
|
154
154
|
if (this.model.applicationSecret) {
|
|
155
155
|
this.$set(this, 'applicationSecret', this.model.applicationSecret);
|
|
@@ -162,11 +162,13 @@ export default {
|
|
|
162
162
|
methods: {
|
|
163
163
|
setEndpoints(endpoint) {
|
|
164
164
|
if (this.editConfig || !this.model.enabled) {
|
|
165
|
-
|
|
165
|
+
const endpointType = this.oldEndpoint && endpoint !== 'custom' ? OLD_ENDPOINTS : ENDPOINT_MAPPING;
|
|
166
|
+
|
|
167
|
+
Object.keys(endpointType[endpoint]).forEach((key) => {
|
|
166
168
|
this.$set(
|
|
167
169
|
this.model,
|
|
168
170
|
key,
|
|
169
|
-
|
|
171
|
+
endpointType[endpoint][key].replace(
|
|
170
172
|
TENANT_ID_TOKEN,
|
|
171
173
|
this.model.tenantId
|
|
172
174
|
)
|
|
@@ -176,13 +178,30 @@ export default {
|
|
|
176
178
|
},
|
|
177
179
|
|
|
178
180
|
setInitialEndpoint(endpoint) {
|
|
179
|
-
const
|
|
181
|
+
const newEndpointKey = this.determineEndpointKeyType(ENDPOINT_MAPPING);
|
|
182
|
+
const oldEndpointKey = Object.keys(OLD_ENDPOINTS).find(key => OLD_ENDPOINTS[key].graphEndpoint === endpoint);
|
|
180
183
|
|
|
181
|
-
if (
|
|
182
|
-
this.endpoint =
|
|
184
|
+
if ( oldEndpointKey ) {
|
|
185
|
+
this.endpoint = this.determineEndpointKeyType(OLD_ENDPOINTS);
|
|
186
|
+
this.oldEndpoint = true;
|
|
183
187
|
} else {
|
|
184
|
-
this.endpoint =
|
|
188
|
+
this.endpoint = newEndpointKey;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
determineEndpointKeyType(endpointTypes) {
|
|
193
|
+
let out = 'custom';
|
|
194
|
+
|
|
195
|
+
for ( const [endpointKey, endpointKeyValues] of Object.entries(endpointTypes) ) {
|
|
196
|
+
const mappedValues = Object.values(endpointKeyValues).map(endpoint => endpoint.replace(TENANT_ID_TOKEN, this.model?.tenantId));
|
|
197
|
+
const valuesToCheck = Object.keys(endpointKeyValues).map(key => this.value[key]);
|
|
198
|
+
|
|
199
|
+
if ( isEqual(mappedValues, valuesToCheck) ) {
|
|
200
|
+
out = endpointKey;
|
|
201
|
+
}
|
|
185
202
|
}
|
|
203
|
+
|
|
204
|
+
return out;
|
|
186
205
|
},
|
|
187
206
|
|
|
188
207
|
getNewApplicationSecret() {
|
|
@@ -65,7 +65,7 @@ export default {
|
|
|
65
65
|
path: 'metadata.name', rules: ['required', 'hostname'], translationKey: 'nameNsDescription.name.label'
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
|
-
path: 'spec.rules.host', rules: ['
|
|
68
|
+
path: 'spec.rules.host', rules: ['wildcardHostname'], translationKey: 'ingress.rules.requestHost.label'
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
path: 'spec.rules.http.paths.path', rules: ['absolutePath'], translationKey: 'ingress.rules.path.label'
|
|
@@ -83,7 +83,7 @@ export default {
|
|
|
83
83
|
{
|
|
84
84
|
path: 'spec.defaultBackend.service.port.number', rules: ['required', 'requiredInt', 'portNumber'], translationKey: 'ingress.defaultBackend.port.label'
|
|
85
85
|
},
|
|
86
|
-
{ path: 'spec.tls.hosts', rules: ['required', '
|
|
86
|
+
{ path: 'spec.tls.hosts', rules: ['required', 'wildcardHostname'] }
|
|
87
87
|
],
|
|
88
88
|
fvReportedValidationPaths: ['spec.rules.http.paths.backend.service.port.number', 'spec.rules.http.paths.path', 'spec.rules.http.paths.backend.service.name']
|
|
89
89
|
};
|
package/edit/pod.vue
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
3
|
+
import FormValidation from '@shell/mixins/form-validation';
|
|
4
|
+
import WorkLoadMixin from '@shell/edit/workload/mixins/workload';
|
|
5
|
+
import Workload from '@shell/edit/workload/index.vue';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
name: 'WorkloadDeployments',
|
|
9
|
+
components: { Workload },
|
|
10
|
+
mixins: [CreateEditView, FormValidation, WorkLoadMixin],
|
|
11
|
+
props: {
|
|
12
|
+
value: {
|
|
13
|
+
type: Object,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
mode: {
|
|
18
|
+
type: String,
|
|
19
|
+
default: 'create',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<Workload v-bind="$props" />
|
|
27
|
+
</template>
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
NORMAN,
|
|
15
15
|
SCHEMA,
|
|
16
16
|
DEFAULT_WORKSPACE,
|
|
17
|
-
SECRET
|
|
17
|
+
SECRET,
|
|
18
|
+
HCI,
|
|
18
19
|
} from '@shell/config/types';
|
|
19
20
|
import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
|
|
20
21
|
|
|
@@ -311,7 +312,8 @@ export default {
|
|
|
311
312
|
clusterIsAlreadyCreated: !!this.value.id,
|
|
312
313
|
fvFormRuleSets: [{
|
|
313
314
|
path: 'metadata.name', rules: ['subDomain'], translationKey: 'nameNsDescription.name.label'
|
|
314
|
-
}]
|
|
315
|
+
}],
|
|
316
|
+
harvesterVersionRange: {},
|
|
315
317
|
};
|
|
316
318
|
},
|
|
317
319
|
|
|
@@ -499,7 +501,7 @@ export default {
|
|
|
499
501
|
const isExternal = opt === 'external';
|
|
500
502
|
let disabled = false;
|
|
501
503
|
|
|
502
|
-
if (this.isHarvesterExternalCredential && isPreferred) {
|
|
504
|
+
if ((this.isHarvesterExternalCredential || this.isHarvesterIncompatible) && isPreferred) {
|
|
503
505
|
disabled = true;
|
|
504
506
|
}
|
|
505
507
|
|
|
@@ -850,6 +852,33 @@ export default {
|
|
|
850
852
|
isHarvesterExternalCredential() {
|
|
851
853
|
return this.credential?.harvestercredentialConfig?.clusterType === 'external';
|
|
852
854
|
},
|
|
855
|
+
|
|
856
|
+
isHarvesterIncompatible() {
|
|
857
|
+
let ccmRke2Version = (this.chartVersions['harvester-cloud-provider'] || {})['version'];
|
|
858
|
+
let csiRke2Version = (this.chartVersions['harvester-csi-driver'] || {})['version'];
|
|
859
|
+
|
|
860
|
+
const ccmVersion = this.harvesterVersionRange?.['harvester-cloud-provider'];
|
|
861
|
+
const csiVersion = this.harvesterVersionRange?.['harvester-csi-provider'];
|
|
862
|
+
|
|
863
|
+
if ((ccmRke2Version || '').endsWith('00')) {
|
|
864
|
+
ccmRke2Version = ccmRke2Version.slice(0, -2);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if ((csiRke2Version || '').endsWith('00')) {
|
|
868
|
+
csiRke2Version = csiRke2Version.slice(0, -2);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
if (ccmVersion && csiVersion) {
|
|
872
|
+
if (semver.satisfies(ccmRke2Version, ccmVersion) &&
|
|
873
|
+
semver.satisfies(csiRke2Version, csiVersion)) {
|
|
874
|
+
return false;
|
|
875
|
+
} else {
|
|
876
|
+
return true;
|
|
877
|
+
}
|
|
878
|
+
} else {
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
881
|
+
},
|
|
853
882
|
},
|
|
854
883
|
|
|
855
884
|
watch: {
|
|
@@ -867,7 +896,10 @@ export default {
|
|
|
867
896
|
credentialId(val) {
|
|
868
897
|
if ( val ) {
|
|
869
898
|
this.credential = this.$store.getters['rancher/byId'](NORMAN.CLOUD_CREDENTIAL, this.credentialId);
|
|
870
|
-
|
|
899
|
+
|
|
900
|
+
if (this.isHarvesterDriver) {
|
|
901
|
+
this.setHarvesterVersionRange();
|
|
902
|
+
}
|
|
871
903
|
} else {
|
|
872
904
|
this.credential = null;
|
|
873
905
|
}
|
|
@@ -1562,12 +1594,36 @@ export default {
|
|
|
1562
1594
|
get,
|
|
1563
1595
|
|
|
1564
1596
|
setHarvesterDefaultCloudProvider() {
|
|
1565
|
-
if (this.isHarvesterDriver &&
|
|
1597
|
+
if (this.isHarvesterDriver &&
|
|
1598
|
+
this.mode === _CREATE &&
|
|
1599
|
+
!this.agentConfig['cloud-provider-name'] &&
|
|
1600
|
+
!this.isHarvesterExternalCredential &&
|
|
1601
|
+
!this.isHarvesterIncompatible
|
|
1602
|
+
) {
|
|
1566
1603
|
this.agentConfig['cloud-provider-name'] = HARVESTER;
|
|
1567
1604
|
} else {
|
|
1568
1605
|
this.agentConfig['cloud-provider-name'] = '';
|
|
1569
1606
|
}
|
|
1570
1607
|
},
|
|
1608
|
+
|
|
1609
|
+
async setHarvesterVersionRange() {
|
|
1610
|
+
const clusterId = this.credential?.decodedData?.clusterId;
|
|
1611
|
+
const clusterType = this.credential?.decodedData?.clusterType;
|
|
1612
|
+
|
|
1613
|
+
if (clusterId && clusterType === 'imported') {
|
|
1614
|
+
const url = `/k8s/clusters/${ clusterId }/v1`;
|
|
1615
|
+
const res = await this.$store.dispatch('cluster/request', { url: `${ url }/${ HCI.SETTING }s` });
|
|
1616
|
+
|
|
1617
|
+
const version = (res?.data || []).find(s => s.id === 'harvester-csi-ccm-versions');
|
|
1618
|
+
|
|
1619
|
+
if (version) {
|
|
1620
|
+
this.harvesterVersionRange = JSON.parse(version.value || version.default || '{}');
|
|
1621
|
+
} else {
|
|
1622
|
+
this.harvesterVersionRange = {};
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
this.setHarvesterDefaultCloudProvider();
|
|
1626
|
+
},
|
|
1571
1627
|
},
|
|
1572
1628
|
};
|
|
1573
1629
|
</script>
|
|
@@ -1686,6 +1742,14 @@ export default {
|
|
|
1686
1742
|
<Tab name="basic" label-key="cluster.tabs.basic" :weight="11" @active="refreshYamls">
|
|
1687
1743
|
<Banner v-if="!haveArgInfo" color="warning" label="Configuration information is not available for the selected Kubernetes version. The options available in this screen will be limited, you may want to use the YAML editor." />
|
|
1688
1744
|
<Banner v-if="showk8s21LegacyWarning" color="warning" :label="t('cluster.legacyWarning')" />
|
|
1745
|
+
<Banner
|
|
1746
|
+
v-if="isHarvesterDriver && isHarvesterIncompatible && showCloudProvider"
|
|
1747
|
+
color="warning"
|
|
1748
|
+
>
|
|
1749
|
+
<span
|
|
1750
|
+
v-html="t('cluster.harvester.warning.cloudProvider.incompatible', null, true)"
|
|
1751
|
+
/>
|
|
1752
|
+
</Banner>
|
|
1689
1753
|
<div class="row mb-10">
|
|
1690
1754
|
<div class="col span-6">
|
|
1691
1755
|
<LabeledSelect
|
|
@@ -1788,6 +1852,12 @@ export default {
|
|
|
1788
1852
|
</div>
|
|
1789
1853
|
</div>
|
|
1790
1854
|
|
|
1855
|
+
<div v-if="serverConfig.cni === 'cilium' && value.spec.enableNetworkPolicy" class="row">
|
|
1856
|
+
<div class="col span-12">
|
|
1857
|
+
<Banner color="info" :label="t('cluster.rke2.enableNetworkPolicy.warning')" />
|
|
1858
|
+
</div>
|
|
1859
|
+
</div>
|
|
1860
|
+
|
|
1791
1861
|
<div class="spacer" />
|
|
1792
1862
|
|
|
1793
1863
|
<div v-if="serverArgs.disable" class="row">
|
|
@@ -2089,6 +2159,7 @@ export default {
|
|
|
2089
2159
|
</Tab>
|
|
2090
2160
|
|
|
2091
2161
|
<Tab
|
|
2162
|
+
v-if="haveArgInfo || agentArgs['protect-kernel-defaults']"
|
|
2092
2163
|
name="advanced"
|
|
2093
2164
|
label-key="cluster.tabs.advanced"
|
|
2094
2165
|
:weight="-1"
|
package/edit/service.vue
CHANGED
|
@@ -198,7 +198,8 @@ export default {
|
|
|
198
198
|
},
|
|
199
199
|
|
|
200
200
|
watch: {
|
|
201
|
-
'value.
|
|
201
|
+
'value.metadata.namespace': 'updateMatchingPods',
|
|
202
|
+
'value.spec.selector': 'updateMatchingPods',
|
|
202
203
|
'value.spec.sessionAffinity'(val) {
|
|
203
204
|
if (val === 'ClientIP') {
|
|
204
205
|
this.value.spec.sessionAffinityConfig = { clientIP: { timeoutSeconds: null } };
|
|
@@ -240,21 +241,22 @@ export default {
|
|
|
240
241
|
|
|
241
242
|
methods: {
|
|
242
243
|
updateMatchingPods: throttle(function() {
|
|
243
|
-
const {
|
|
244
|
+
const { value: { spec: { selector = { } } } } = this;
|
|
245
|
+
const allInNamespace = this.allPods.filter(pod => pod.metadata.namespace === this.value?.metadata?.namespace);
|
|
244
246
|
|
|
245
247
|
if (isEmpty(selector)) {
|
|
246
248
|
this.matchingPods = {
|
|
247
249
|
matched: 0,
|
|
248
|
-
total:
|
|
250
|
+
total: allInNamespace.length,
|
|
249
251
|
none: true,
|
|
250
252
|
sample: null,
|
|
251
253
|
};
|
|
252
254
|
} else {
|
|
253
|
-
const match = matching(
|
|
255
|
+
const match = matching(allInNamespace, selector);
|
|
254
256
|
|
|
255
257
|
this.matchingPods = {
|
|
256
258
|
matched: match.length,
|
|
257
|
-
total:
|
|
259
|
+
total: allInNamespace.length,
|
|
258
260
|
none: match.length === 0,
|
|
259
261
|
sample: match[0] ? match[0].nameDisplay : null,
|
|
260
262
|
};
|
|
@@ -26,6 +26,7 @@ describe('component: Upgrading', () => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
// TODO: #6179: Integrate test with component fix, as the scope is not to check the value of the input
|
|
29
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
|
29
30
|
it.skip.each([
|
|
30
31
|
['surge', 'maxSurge', '%'],
|
|
31
32
|
['unavailable', 'maxUnavailable', '%'],
|
package/edit/workload/index.vue
CHANGED
|
@@ -197,6 +197,19 @@ export default {
|
|
|
197
197
|
<Tab :label="t('workload.container.titles.securityContext')" name="securityContext" :weight="tabWeightMap['securityContext']">
|
|
198
198
|
<Security v-model="allContainers[i].securityContext" :mode="mode" />
|
|
199
199
|
</Tab>
|
|
200
|
+
<Tab :label="t('workload.storage.title')" name="storage" :weight="tabWeightMap['storage']">
|
|
201
|
+
<ContainerMountPaths
|
|
202
|
+
v-model="podTemplateSpec"
|
|
203
|
+
:namespace="value.metadata.namespace"
|
|
204
|
+
:register-before-hook="registerBeforeHook"
|
|
205
|
+
:mode="mode"
|
|
206
|
+
:secrets="namespacedSecrets"
|
|
207
|
+
:config-maps="namespacedConfigMaps"
|
|
208
|
+
:container="allContainers[i]"
|
|
209
|
+
:save-pvc-hook-name="savePvcHookName"
|
|
210
|
+
@removePvcForm="clearPvcFormState"
|
|
211
|
+
/>
|
|
212
|
+
</Tab>
|
|
200
213
|
</Tabbed>
|
|
201
214
|
</Tab>
|
|
202
215
|
<Tab v-if="!isPod" :label="nameDisplayFor(type)" :name="nameDisplayFor(type)" :weight="99">
|
|
@@ -220,7 +233,6 @@ export default {
|
|
|
220
233
|
:mode="mode"
|
|
221
234
|
:secrets="namespacedSecrets"
|
|
222
235
|
:config-maps="namespacedConfigMaps"
|
|
223
|
-
:container="container"
|
|
224
236
|
:save-pvc-hook-name="savePvcHookName"
|
|
225
237
|
@removePvcForm="clearPvcFormState"
|
|
226
238
|
/>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
PVC,
|
|
10
10
|
SERVICE_ACCOUNT,
|
|
11
11
|
CAPI,
|
|
12
|
+
POD,
|
|
12
13
|
} from '@shell/config/types';
|
|
13
14
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
14
15
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
@@ -36,6 +37,7 @@ import CruResource from '@shell/components/CruResource';
|
|
|
36
37
|
import Command from '@shell/components/form/Command';
|
|
37
38
|
import LifecycleHooks from '@shell/components/form/LifecycleHooks';
|
|
38
39
|
import Storage from '@shell/edit/workload/storage';
|
|
40
|
+
import ContainerMountPaths from '@shell/edit/workload/storage/ContainerMountPaths.vue';
|
|
39
41
|
import Labels from '@shell/components/form/Labels';
|
|
40
42
|
import { RadioGroup } from '@components/Form/Radio';
|
|
41
43
|
import { UI_MANAGED } from '@shell/config/labels-annotations';
|
|
@@ -89,6 +91,7 @@ export default {
|
|
|
89
91
|
Upgrading,
|
|
90
92
|
VolumeClaimTemplate,
|
|
91
93
|
WorkloadPorts,
|
|
94
|
+
ContainerMountPaths
|
|
92
95
|
},
|
|
93
96
|
|
|
94
97
|
mixins: [CreateEditView],
|
|
@@ -148,7 +151,6 @@ export default {
|
|
|
148
151
|
},
|
|
149
152
|
|
|
150
153
|
data() {
|
|
151
|
-
let defaultTab;
|
|
152
154
|
let type = this.$route.params.resource;
|
|
153
155
|
const createSidecar = !!this.$route.query.sidecar;
|
|
154
156
|
const isInitContainer = !!this.$route.query.init;
|
|
@@ -159,24 +161,18 @@ export default {
|
|
|
159
161
|
|
|
160
162
|
if (!this.value.spec) {
|
|
161
163
|
this.value.spec = {};
|
|
162
|
-
if (this.value.type ===
|
|
164
|
+
if (this.value.type === POD) {
|
|
163
165
|
const podContainers = [{
|
|
164
166
|
imagePullPolicy: 'Always',
|
|
165
167
|
name: `container-0`,
|
|
166
168
|
}];
|
|
167
169
|
|
|
168
|
-
defaultTab = 'container-0';
|
|
169
|
-
|
|
170
170
|
const podSpec = { template: { spec: { containers: podContainers, initContainers: [] } } };
|
|
171
171
|
|
|
172
172
|
this.$set(this.value, 'spec', podSpec);
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
if (this.mode === _CREATE) {
|
|
177
|
-
defaultTab = 'container-0';
|
|
178
|
-
}
|
|
179
|
-
|
|
180
176
|
if ((this.mode === _EDIT || this.mode === _VIEW ) && this.value.type === 'pod' ) {
|
|
181
177
|
const podSpec = { ...this.value.spec };
|
|
182
178
|
|
|
@@ -214,7 +210,6 @@ export default {
|
|
|
214
210
|
imagePullPolicy: 'Always',
|
|
215
211
|
name: `container-${ allContainers.length }`,
|
|
216
212
|
});
|
|
217
|
-
defaultTab = 'container-0';
|
|
218
213
|
|
|
219
214
|
containers = podTemplateSpec.initContainers;
|
|
220
215
|
}
|
|
@@ -224,8 +219,6 @@ export default {
|
|
|
224
219
|
name: `container-${ allContainers.length }`,
|
|
225
220
|
};
|
|
226
221
|
|
|
227
|
-
defaultTab = 'container-0';
|
|
228
|
-
|
|
229
222
|
containers.push(container);
|
|
230
223
|
} else {
|
|
231
224
|
container = containers[0];
|
|
@@ -261,7 +254,6 @@ export default {
|
|
|
261
254
|
path: 'image', rootObject: this.container, rules: ['required'], translationKey: 'workload.container.image'
|
|
262
255
|
}],
|
|
263
256
|
fvReportedValidationPaths: ['spec'],
|
|
264
|
-
defaultTab
|
|
265
257
|
|
|
266
258
|
};
|
|
267
259
|
},
|
|
@@ -271,6 +263,14 @@ export default {
|
|
|
271
263
|
return { general: this.fvGetPathErrors(['image'])?.length > 0 };
|
|
272
264
|
},
|
|
273
265
|
|
|
266
|
+
defaultTab() {
|
|
267
|
+
if (!!this.$route.query.sidecar || this.$route.query.init || this.mode === _CREATE) {
|
|
268
|
+
return 'container-0';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return this.allContainers.length ? this.allContainers[0].name : '';
|
|
272
|
+
},
|
|
273
|
+
|
|
274
274
|
isEdit() {
|
|
275
275
|
return this.mode === _EDIT;
|
|
276
276
|
},
|
|
@@ -297,7 +297,7 @@ export default {
|
|
|
297
297
|
},
|
|
298
298
|
|
|
299
299
|
isPod() {
|
|
300
|
-
return this.value.type ===
|
|
300
|
+
return this.value.type === POD;
|
|
301
301
|
},
|
|
302
302
|
|
|
303
303
|
isStatefulSet() {
|