@rancher/shell 0.1.1 → 0.1.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/translations/en-us.yaml +8 -2
- package/assets/translations/zh-hans.yaml +158 -25
- package/components/auth/RoleDetailEdit.vue +14 -1
- package/components/form/ResourceTabs/index.vue +27 -18
- package/components/formatter/ClusterLink.vue +13 -0
- package/components/formatter/PodImages.vue +11 -1
- package/components/formatter/RKETemplateName.vue +37 -0
- package/config/types.js +3 -1
- package/creators/app/tsconfig.json +6 -1
- package/creators/pkg/init +3 -0
- package/creators/pkg/tsconfig.json +7 -2
- package/detail/provisioning.cattle.io.cluster.vue +10 -0
- package/edit/cloudcredential.vue +7 -1
- package/edit/networking.k8s.io.ingress/index.vue +2 -1
- package/edit/persistentvolumeclaim.vue +32 -2
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +21 -6
- package/edit/workload/types/Deployment.vue +1 -1
- package/edit/workload/types/Generic.vue +1 -1
- package/list/provisioning.cattle.io.cluster.vue +6 -0
- package/mixins/brand.js +3 -4
- package/mixins/create-edit-view/impl.js +0 -8
- package/models/chart.js +1 -1
- package/models/cluster/node.js +12 -1
- package/models/management.cattle.io.globalrole.js +0 -19
- package/models/management.cattle.io.roletemplate.js +2 -21
- package/models/provisioning.cattle.io.cluster.js +67 -0
- package/models/service.js +5 -1
- package/nuxt.config.js +3 -3
- package/package.json +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +0 -6
- package/plugins/console.js +10 -5
- package/plugins/dashboard-store/actions.js +8 -3
- package/plugins/dashboard-store/getters.js +7 -2
- package/plugins/steve/steve-description-class.js +32 -0
- package/rancher-components/Banner/Banner.vue +2 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +0 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
- package/rancher-components/Form/Radio/RadioButton.vue +14 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
- package/{components/form → rancher-components/Form/ToggleSwitch}/ToggleSwitch.vue +18 -8
- package/rancher-components/Form/ToggleSwitch/index.ts +1 -0
- package/rancher-components/Form/index.ts +1 -0
- package/scripts/test-plugins-build.sh +18 -1
- package/types/{index.d.ts → rancher/index.d.ts} +0 -0
- package/plugins/lookup.js +0 -50
- package/yarn-error.log +0 -196
|
@@ -66,22 +66,21 @@ export default {
|
|
|
66
66
|
}
|
|
67
67
|
},
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
data() {
|
|
70
70
|
const inStore = this.$store.getters['currentStore'](EVENT);
|
|
71
71
|
|
|
72
|
-
if ( this.$store.getters[`${ inStore }/schemaFor`](EVENT) ) {
|
|
73
|
-
this.hasEvents = true; // @TODO be smarter about which ones actually ever have events
|
|
74
|
-
this.allEvents = await this.$store.dispatch(`${ inStore }/findAll`, { type: EVENT });
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
data() {
|
|
79
72
|
return {
|
|
80
|
-
hasEvents:
|
|
81
|
-
allEvents:
|
|
73
|
+
hasEvents: this.$store.getters[`${ inStore }/schemaFor`](EVENT), // @TODO be smarter about which resources actually ever have events
|
|
74
|
+
allEvents: [],
|
|
75
|
+
selectedTab: this.defaultTab,
|
|
76
|
+
didLoadEvents: false,
|
|
82
77
|
};
|
|
83
78
|
},
|
|
84
79
|
|
|
80
|
+
beforeDestroy() {
|
|
81
|
+
this.$store.dispatch('cluster/forgetType', EVENT);
|
|
82
|
+
},
|
|
83
|
+
|
|
85
84
|
computed: {
|
|
86
85
|
showConditions() {
|
|
87
86
|
const inStore = this.$store.getters['currentStore'](this.value.type);
|
|
@@ -89,10 +88,10 @@ export default {
|
|
|
89
88
|
return this.isView && this.needConditions && this.value?.type && this.$store.getters[`${ inStore }/pathExistsInSchema`](this.value.type, 'status.conditions');
|
|
90
89
|
},
|
|
91
90
|
showEvents() {
|
|
92
|
-
return this.isView && this.needEvents &&
|
|
91
|
+
return this.isView && this.needEvents && this.hasEvents && (this.events.length || this.alwaysShowEvents);
|
|
93
92
|
},
|
|
94
93
|
showRelated() {
|
|
95
|
-
return this.isView && this.needRelated
|
|
94
|
+
return this.isView && this.needRelated;
|
|
96
95
|
},
|
|
97
96
|
eventHeaders() {
|
|
98
97
|
return [
|
|
@@ -146,17 +145,26 @@ export default {
|
|
|
146
145
|
}
|
|
147
146
|
},
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
//
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
methods: {
|
|
149
|
+
// Ensures we only fetch events and show the table when the events tab has been activated
|
|
150
|
+
tabChange(neu) {
|
|
151
|
+
this.selectedTab = neu?.selectedName;
|
|
152
|
+
|
|
153
|
+
if (!this.didLoadEvents && this.selectedTab === 'events') {
|
|
154
|
+
const inStore = this.$store.getters['currentStore'](EVENT);
|
|
155
|
+
|
|
156
|
+
this.$store.dispatch(`${ inStore }/findAll`, { type: EVENT }).then((events) => {
|
|
157
|
+
this.allEvents = events;
|
|
158
|
+
this.didLoadEvents = true;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
153
161
|
}
|
|
154
|
-
}
|
|
162
|
+
}
|
|
155
163
|
};
|
|
156
164
|
</script>
|
|
157
165
|
|
|
158
166
|
<template>
|
|
159
|
-
<Tabbed v-bind="$attrs" :default-tab="defaultTab">
|
|
167
|
+
<Tabbed v-bind="$attrs" :default-tab="defaultTab" @changed="tabChange">
|
|
160
168
|
<slot />
|
|
161
169
|
|
|
162
170
|
<Tab v-if="showConditions" label-key="resourceTabs.conditions.tab" name="conditions" :weight="-1" :display-alert-icon="conditionsHaveIssues">
|
|
@@ -165,6 +173,7 @@ export default {
|
|
|
165
173
|
|
|
166
174
|
<Tab v-if="showEvents" label-key="resourceTabs.events.tab" name="events" :weight="-2">
|
|
167
175
|
<SortableTable
|
|
176
|
+
v-if="selectedTab === 'events'"
|
|
168
177
|
:rows="events"
|
|
169
178
|
:headers="eventHeaders"
|
|
170
179
|
key-field="id"
|
|
@@ -63,6 +63,11 @@ export default {
|
|
|
63
63
|
{{ value }}
|
|
64
64
|
</n-link>
|
|
65
65
|
<span v-else>{{ value }}</span>
|
|
66
|
+
<i
|
|
67
|
+
v-if="row.rkeTemplateUpgrade"
|
|
68
|
+
v-tooltip="t('cluster.rkeTemplateUpgrade', { name: row.rkeTemplateUpgrade })"
|
|
69
|
+
class="template-upgrade-icon icon-alert icon"
|
|
70
|
+
/>
|
|
66
71
|
<i
|
|
67
72
|
v-if="clusterHasIssues"
|
|
68
73
|
v-tooltip="{ content: `<div>${formattedConditions}</div>`, html: true }"
|
|
@@ -93,4 +98,12 @@ export default {
|
|
|
93
98
|
.mytooltip ul {
|
|
94
99
|
outline: 1px dashed red;
|
|
95
100
|
}
|
|
101
|
+
.template-upgrade-icon {
|
|
102
|
+
border: 1px solid var(--warning);
|
|
103
|
+
border-radius: 50%;
|
|
104
|
+
color: var(--warning);
|
|
105
|
+
margin-left: 4px;
|
|
106
|
+
font-size: 14px;
|
|
107
|
+
padding: 2px;
|
|
108
|
+
}
|
|
96
109
|
</style>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { mapGetters } from 'vuex';
|
|
3
3
|
|
|
4
|
+
// For the main image hat we show, use these to ignore istio proxy images so that
|
|
5
|
+
// we are more likely to show the important main iamge and not the istio sidecar
|
|
6
|
+
const IGNORE_IMAGES = ['istio/proxy', 'gcr.io/istio-release/proxy', 'mirrored-istio-proxy'];
|
|
7
|
+
|
|
4
8
|
export default {
|
|
5
9
|
props: {
|
|
6
10
|
value: {
|
|
@@ -38,6 +42,12 @@ export default {
|
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
return null;
|
|
45
|
+
},
|
|
46
|
+
mainImage() {
|
|
47
|
+
const images = this.images;
|
|
48
|
+
const filter = images.filter(image => !IGNORE_IMAGES.find(i => image.includes(i)));
|
|
49
|
+
|
|
50
|
+
return filter.length > 0 ? filter[0] : images[0];
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
|
|
@@ -46,7 +56,7 @@ export default {
|
|
|
46
56
|
|
|
47
57
|
<template>
|
|
48
58
|
<span>
|
|
49
|
-
<span>{{
|
|
59
|
+
<span>{{ mainImage }}</span><br>
|
|
50
60
|
<span
|
|
51
61
|
v-if="images.length-1>0"
|
|
52
62
|
v-tooltip.bottom="imageLabels"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export default {
|
|
3
|
+
props: {
|
|
4
|
+
value: {
|
|
5
|
+
type: Object,
|
|
6
|
+
required: true
|
|
7
|
+
},
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="rke-template">
|
|
14
|
+
<span>{{ value.displayName }}</span>
|
|
15
|
+
<i
|
|
16
|
+
v-if="value.upgrade"
|
|
17
|
+
v-tooltip="t('cluster.rkeTemplateUpgrade', { name: value.upgrade })"
|
|
18
|
+
class="template-upgrade-icon icon-alert icon"
|
|
19
|
+
/>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<style lang="scss" scoped>
|
|
24
|
+
.rke-template {
|
|
25
|
+
align-items: center;
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
|
|
28
|
+
.template-upgrade-icon {
|
|
29
|
+
border: 1px solid var(--warning);
|
|
30
|
+
border-radius: 50%;
|
|
31
|
+
color: var(--warning);
|
|
32
|
+
margin-left: 4px;
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
padding: 2px;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
</style>
|
package/config/types.js
CHANGED
|
@@ -169,7 +169,9 @@ export const MANAGEMENT = {
|
|
|
169
169
|
POD_SECURITY_POLICY_TEMPLATE: 'management.cattle.io.podsecuritypolicytemplate',
|
|
170
170
|
MANAGED_CHART: 'management.cattle.io.managedchart',
|
|
171
171
|
USER_NOTIFICATION: 'management.cattle.io.rancherusernotification',
|
|
172
|
-
GLOBAL_DNS_PROVIDER: 'management.cattle.io.globaldnsprovider'
|
|
172
|
+
GLOBAL_DNS_PROVIDER: 'management.cattle.io.globaldnsprovider',
|
|
173
|
+
RKE_TEMPLATE: 'management.cattle.io.clustertemplate',
|
|
174
|
+
RKE_TEMPLATE_REVISION: 'management.cattle.io.clustertemplaterevision',
|
|
173
175
|
};
|
|
174
176
|
|
|
175
177
|
export const CAPI = {
|
|
@@ -25,10 +25,15 @@
|
|
|
25
25
|
"./node_modules/@rancher/shell/*"
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
|
+
"typeRoots": [
|
|
29
|
+
"./node_modules",
|
|
30
|
+
"./node_modules/@rancher/shell/types"
|
|
31
|
+
],
|
|
28
32
|
"types": [
|
|
29
33
|
"@types/node",
|
|
30
34
|
"@nuxt/types",
|
|
31
|
-
"cypress"
|
|
35
|
+
"cypress",
|
|
36
|
+
"rancher"
|
|
32
37
|
]
|
|
33
38
|
},
|
|
34
39
|
"exclude": [
|
package/creators/pkg/init
CHANGED
|
@@ -137,6 +137,9 @@ if (!isNodeModulesShell) {
|
|
|
137
137
|
tsconfig.compilerOptions.paths[p] = updateArray(tsconfig.compilerOptions.paths[p]);
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
+
// Update typeRoots
|
|
141
|
+
tsconfig.compilerOptions.typeRoots = updateArray(tsconfig.compilerOptions.typeRoots);
|
|
142
|
+
|
|
140
143
|
fs.writeFileSync(path.join(pkgFolder, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));
|
|
141
144
|
console.log(' Updated tsconfig.json for shell folder location');
|
|
142
145
|
}
|
|
@@ -13,9 +13,15 @@
|
|
|
13
13
|
"sourceMap": true,
|
|
14
14
|
"baseUrl": ".",
|
|
15
15
|
"preserveSymlinks": true,
|
|
16
|
+
"typeRoots": [
|
|
17
|
+
"../../node_modules",
|
|
18
|
+
"../../node_modules/@rancher/shell/types"
|
|
19
|
+
],
|
|
16
20
|
"types": [
|
|
17
21
|
"node",
|
|
18
|
-
"webpack-env"
|
|
22
|
+
"webpack-env",
|
|
23
|
+
"@nuxt/types",
|
|
24
|
+
"rancher"
|
|
19
25
|
],
|
|
20
26
|
"lib": [
|
|
21
27
|
"esnext",
|
|
@@ -39,7 +45,6 @@
|
|
|
39
45
|
"**/*.ts",
|
|
40
46
|
"**/*.tsx",
|
|
41
47
|
"**/*.vue",
|
|
42
|
-
"../../node_modules/@rancher/shell/types/*.d.ts",
|
|
43
48
|
"../../node_modules/@rancher/shell/core/types.ts"
|
|
44
49
|
],
|
|
45
50
|
"exclude": [
|
|
@@ -146,6 +146,16 @@ export default {
|
|
|
146
146
|
this.allNodePools = fetchTwoRes.allNodePools || [];
|
|
147
147
|
this.haveNodePools = !!fetchTwoRes.allNodePools;
|
|
148
148
|
this.machineTemplates = fetchTwoRes.mdtt || [];
|
|
149
|
+
|
|
150
|
+
// Fetch RKE template revisions so we can show when an updated template is available
|
|
151
|
+
// This request does not need to be blocking
|
|
152
|
+
if ( this.$store.getters['management/canList'](MANAGEMENT.RKE_TEMPLATE) ) {
|
|
153
|
+
this.$store.dispatch('management/findAll', { type: MANAGEMENT.RKE_TEMPLATE });
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if ( this.$store.getters['management/canList'](MANAGEMENT.RKE_TEMPLATE_REVISION) ) {
|
|
157
|
+
this.$store.dispatch('management/findAll', { type: MANAGEMENT.RKE_TEMPLATE_REVISION });
|
|
158
|
+
}
|
|
149
159
|
},
|
|
150
160
|
|
|
151
161
|
created() {
|
package/edit/cloudcredential.vue
CHANGED
|
@@ -260,7 +260,13 @@ export default {
|
|
|
260
260
|
@select-type="selectType"
|
|
261
261
|
@error="e=>errors = e"
|
|
262
262
|
>
|
|
263
|
-
<NameNsDescription
|
|
263
|
+
<NameNsDescription
|
|
264
|
+
v-model="value"
|
|
265
|
+
name-key="_name"
|
|
266
|
+
description-key="description"
|
|
267
|
+
:mode="mode"
|
|
268
|
+
:namespaced="false"
|
|
269
|
+
/>
|
|
264
270
|
<keep-alive>
|
|
265
271
|
<component
|
|
266
272
|
:is="cloudComponent"
|
|
@@ -44,10 +44,11 @@ export default {
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
async fetch() {
|
|
47
|
+
const ingressClassSchema = this.$store.getters[`cluster/schemaFor`](INGRESS_CLASS);
|
|
47
48
|
const hash = await allHash({
|
|
48
49
|
secrets: this.$store.dispatch('cluster/findAll', { type: SECRET }),
|
|
49
50
|
services: this.$store.dispatch('cluster/findAll', { type: SERVICE }),
|
|
50
|
-
ingressClasses: this.$store.dispatch('cluster/findAll', { type: INGRESS_CLASS }),
|
|
51
|
+
ingressClasses: ingressClassSchema ? this.$store.dispatch('cluster/findAll', { type: INGRESS_CLASS }) : Promise.resolve([]),
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
this.allServices = hash.services;
|
|
@@ -5,6 +5,7 @@ import CruResource from '@shell/components/CruResource';
|
|
|
5
5
|
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
|
6
6
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
7
7
|
import { RadioGroup } from '@components/Form/Radio';
|
|
8
|
+
import LabeledInput from '@components/Form/LabeledInput/LabeledInput.vue';
|
|
8
9
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
9
10
|
import UnitInput from '@shell/components/form/UnitInput';
|
|
10
11
|
import uniq from 'lodash/uniq';
|
|
@@ -24,6 +25,7 @@ export default {
|
|
|
24
25
|
Banner,
|
|
25
26
|
Checkbox,
|
|
26
27
|
CruResource,
|
|
28
|
+
LabeledInput,
|
|
27
29
|
LabeledSelect,
|
|
28
30
|
Labels,
|
|
29
31
|
NameNsDescription,
|
|
@@ -38,7 +40,9 @@ export default {
|
|
|
38
40
|
async fetch() {
|
|
39
41
|
const storageClasses = await this.$store.dispatch('cluster/findAll', { type: STORAGE_CLASS });
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
if (this.$store.getters['management/canList'](PV)) {
|
|
44
|
+
this.persistentVolumes = await this.$store.dispatch('cluster/findAll', { type: PV });
|
|
45
|
+
}
|
|
42
46
|
|
|
43
47
|
this.storageClassOptions = storageClasses.map(s => s.name).sort();
|
|
44
48
|
this.storageClassOptions.unshift(this.t('persistentVolumeClaim.useDefault'));
|
|
@@ -55,6 +59,8 @@ export default {
|
|
|
55
59
|
this.$set(this.value.spec, 'storageClassName', this.value.spec.storageClassName || this.storageClassOptions[0]);
|
|
56
60
|
},
|
|
57
61
|
data() {
|
|
62
|
+
const canListPersistentVolumes = this.$store.getters['management/canList'](PV);
|
|
63
|
+
const canListStorageClasses = this.$store.getters['management/canList'](STORAGE_CLASS);
|
|
58
64
|
const sourceOptions = [
|
|
59
65
|
{
|
|
60
66
|
label: this.t('persistentVolumeClaim.source.options.new'),
|
|
@@ -65,6 +71,7 @@ export default {
|
|
|
65
71
|
value: 'existing'
|
|
66
72
|
}
|
|
67
73
|
];
|
|
74
|
+
|
|
68
75
|
const defaultAccessModes = ['ReadWriteOnce'];
|
|
69
76
|
|
|
70
77
|
this.$set(this.value, 'spec', this.value.spec || {});
|
|
@@ -85,6 +92,8 @@ export default {
|
|
|
85
92
|
persistentVolumes: [],
|
|
86
93
|
storageClassOptions: [],
|
|
87
94
|
defaultTab,
|
|
95
|
+
canListPersistentVolumes,
|
|
96
|
+
canListStorageClasses,
|
|
88
97
|
};
|
|
89
98
|
},
|
|
90
99
|
computed: {
|
|
@@ -216,16 +225,37 @@ export default {
|
|
|
216
225
|
<div class="col span-6">
|
|
217
226
|
<div class="row">
|
|
218
227
|
<div v-if="source === 'new'" class="col span-12">
|
|
219
|
-
<LabeledSelect
|
|
228
|
+
<LabeledSelect
|
|
229
|
+
v-if="canListStorageClasses"
|
|
230
|
+
v-model="value.spec.storageClassName"
|
|
231
|
+
:options="storageClassOptions"
|
|
232
|
+
:label="t('persistentVolumeClaim.volumeClaim.storageClass')"
|
|
233
|
+
:mode="immutableMode"
|
|
234
|
+
/>
|
|
235
|
+
<LabeledInput
|
|
236
|
+
v-else
|
|
237
|
+
v-model="value.spec.storageClassName"
|
|
238
|
+
:label="t('persistentVolumeClaim.volumeClaim.storageClass')"
|
|
239
|
+
:mode="immutableMode"
|
|
240
|
+
:tooltip="t('persistentVolumeClaim.volumeClaim.tooltips.noStorageClass')"
|
|
241
|
+
/>
|
|
220
242
|
</div>
|
|
221
243
|
<div v-else class="col span-12">
|
|
222
244
|
<LabeledSelect
|
|
245
|
+
v-if="canListPersistentVolumes"
|
|
223
246
|
v-model="persistentVolume"
|
|
224
247
|
:options="persistentVolumeOptions"
|
|
225
248
|
:label="t('persistentVolumeClaim.volumeClaim.persistentVolume')"
|
|
226
249
|
:selectable="isPersistentVolumeSelectable"
|
|
227
250
|
:mode="immutableMode"
|
|
228
251
|
/>
|
|
252
|
+
<LabeledInput
|
|
253
|
+
v-else
|
|
254
|
+
v-model="persistentVolume"
|
|
255
|
+
:label="t('persistentVolumeClaim.volumeClaim.persistentVolume')"
|
|
256
|
+
:mode="immutableMode"
|
|
257
|
+
:tooltip="t('persistentVolumeClaim.volumeClaim.tooltips.noPersistentVolume')"
|
|
258
|
+
/>
|
|
229
259
|
</div>
|
|
230
260
|
</div>
|
|
231
261
|
<div class="row">
|
|
@@ -210,7 +210,7 @@ export default {
|
|
|
210
210
|
:mode="mode"
|
|
211
211
|
:output-modifier="true"
|
|
212
212
|
:base-unit="t('cluster.machinePool.autoReplace.unit')"
|
|
213
|
-
@input="value.pool.unhealthyNodeTimeout = `${unhealthyNodeTimeoutInteger}
|
|
213
|
+
@input="value.pool.unhealthyNodeTimeout = `${unhealthyNodeTimeoutInteger}s`"
|
|
214
214
|
/>
|
|
215
215
|
</div>
|
|
216
216
|
<div class="col span-4">
|
|
@@ -4,7 +4,7 @@ import Loading from '@shell/components/Loading';
|
|
|
4
4
|
import CruResource from '@shell/components/CruResource';
|
|
5
5
|
import SelectIconGrid from '@shell/components/SelectIconGrid';
|
|
6
6
|
import EmberPage from '@shell/components/EmberPage';
|
|
7
|
-
import ToggleSwitch from '@
|
|
7
|
+
import { ToggleSwitch } from '@components/Form/ToggleSwitch';
|
|
8
8
|
import {
|
|
9
9
|
CHART, FROM_CLUSTER, SUB_TYPE, _EDIT, _IMPORT, _CONFIG, _VIEW
|
|
10
10
|
} from '@shell/config/query-params';
|
|
@@ -249,10 +249,6 @@ export default {
|
|
|
249
249
|
set(this.value.spec, 'defaultPodSecurityPolicyTemplateName', '');
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
if (this.isHarvesterDriver && this.mode === _CREATE && this.agentConfig['cloud-provider-name'] === undefined) {
|
|
253
|
-
this.agentConfig['cloud-provider-name'] = HARVESTER;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
252
|
await this.initAddons();
|
|
257
253
|
await this.initRegistry();
|
|
258
254
|
|
|
@@ -501,11 +497,17 @@ export default {
|
|
|
501
497
|
// If we have a preferred provider... only show default, preferred and external
|
|
502
498
|
const isPreferred = opt === preferred;
|
|
503
499
|
const isExternal = opt === 'external';
|
|
500
|
+
let disabled = false;
|
|
501
|
+
|
|
502
|
+
if (this.isHarvesterExternalCredential && isPreferred) {
|
|
503
|
+
disabled = true;
|
|
504
|
+
}
|
|
504
505
|
|
|
505
506
|
if (showAllOptions || isPreferred || isExternal) {
|
|
506
507
|
out.push({
|
|
507
508
|
label: this.$store.getters['i18n/withFallback'](`cluster.cloudProvider."${ opt }".label`, null, opt),
|
|
508
509
|
value: opt,
|
|
510
|
+
disabled,
|
|
509
511
|
});
|
|
510
512
|
}
|
|
511
513
|
}
|
|
@@ -843,7 +845,11 @@ export default {
|
|
|
843
845
|
|
|
844
846
|
showForm() {
|
|
845
847
|
return !!this.credentialId || !this.needCredential;
|
|
846
|
-
}
|
|
848
|
+
},
|
|
849
|
+
|
|
850
|
+
isHarvesterExternalCredential() {
|
|
851
|
+
return this.credential?.harvestercredentialConfig?.clusterType === 'external';
|
|
852
|
+
},
|
|
847
853
|
},
|
|
848
854
|
|
|
849
855
|
watch: {
|
|
@@ -861,6 +867,7 @@ export default {
|
|
|
861
867
|
credentialId(val) {
|
|
862
868
|
if ( val ) {
|
|
863
869
|
this.credential = this.$store.getters['rancher/byId'](NORMAN.CLOUD_CREDENTIAL, this.credentialId);
|
|
870
|
+
this.setHarvesterDefaultCloudProvider();
|
|
864
871
|
} else {
|
|
865
872
|
this.credential = null;
|
|
866
873
|
}
|
|
@@ -1552,7 +1559,15 @@ export default {
|
|
|
1552
1559
|
}
|
|
1553
1560
|
});
|
|
1554
1561
|
},
|
|
1555
|
-
get
|
|
1562
|
+
get,
|
|
1563
|
+
|
|
1564
|
+
setHarvesterDefaultCloudProvider() {
|
|
1565
|
+
if (this.isHarvesterDriver && this.mode === _CREATE && this.agentConfig['cloud-provider-name'] === undefined && !this.isHarvesterExternalCredential) {
|
|
1566
|
+
this.agentConfig['cloud-provider-name'] = HARVESTER;
|
|
1567
|
+
} else {
|
|
1568
|
+
this.agentConfig['cloud-provider-name'] = '';
|
|
1569
|
+
}
|
|
1570
|
+
},
|
|
1556
1571
|
},
|
|
1557
1572
|
};
|
|
1558
1573
|
</script>
|
|
@@ -249,7 +249,7 @@ export default {
|
|
|
249
249
|
<LabeledInput v-model.number="podTemplateSpec.priority" :mode="mode" :label="t('workload.scheduling.priority.priority')" />
|
|
250
250
|
</div>
|
|
251
251
|
<div class="col span-6">
|
|
252
|
-
<LabeledInput v-model="podTemplateSpec.
|
|
252
|
+
<LabeledInput v-model="podTemplateSpec.priorityClassName" :mode="mode" :label="t('workload.scheduling.priority.className')" />
|
|
253
253
|
</div>
|
|
254
254
|
</div>
|
|
255
255
|
</div>
|
|
@@ -196,7 +196,7 @@ export default {
|
|
|
196
196
|
<LabeledInput v-model.number="podTemplateSpec.priority" :mode="mode" :label="t('workload.scheduling.priority.priority')" />
|
|
197
197
|
</div>
|
|
198
198
|
<div class="col span-6">
|
|
199
|
-
<LabeledInput v-model="podTemplateSpec.
|
|
199
|
+
<LabeledInput v-model="podTemplateSpec.priorityClassName" :mode="mode" :label="t('workload.scheduling.priority.className')" />
|
|
200
200
|
</div>
|
|
201
201
|
</div>
|
|
202
202
|
</div>
|
|
@@ -41,6 +41,12 @@ export default {
|
|
|
41
41
|
hash.machineDeployments = this.$store.dispatch('management/findAll', { type: CAPI.MACHINE_DEPLOYMENT });
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// Fetch RKE template revisions so we can show when an updated template is available
|
|
45
|
+
// This request does not need to be blocking
|
|
46
|
+
if ( this.$store.getters['management/canList'](MANAGEMENT.RKE_TEMPLATE_REVISION) ) {
|
|
47
|
+
this.$store.dispatch('management/findAll', { type: MANAGEMENT.RKE_TEMPLATE_REVISION });
|
|
48
|
+
}
|
|
49
|
+
|
|
44
50
|
const res = await allHash(hash);
|
|
45
51
|
|
|
46
52
|
this.mgmtClusters = res.mgmtClusters;
|
package/mixins/brand.js
CHANGED
|
@@ -12,16 +12,15 @@ export default {
|
|
|
12
12
|
this.apps = await this.$store.dispatch('management/findAll', { type: CATALOG.APP });
|
|
13
13
|
}
|
|
14
14
|
} catch (e) {}
|
|
15
|
+
|
|
16
|
+
this.globalSettings = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.SETTING });
|
|
15
17
|
},
|
|
16
18
|
|
|
17
19
|
data() {
|
|
18
|
-
return { apps: [] };
|
|
20
|
+
return { apps: [], globalSettings: [] };
|
|
19
21
|
},
|
|
20
22
|
|
|
21
23
|
computed: {
|
|
22
|
-
globalSettings() {
|
|
23
|
-
return this.$store.getters['management/all'](MANAGEMENT.SETTING);
|
|
24
|
-
},
|
|
25
24
|
|
|
26
25
|
brand() {
|
|
27
26
|
const setting = findBy(this.globalSettings, 'id', SETTING.BRAND);
|
|
@@ -12,14 +12,6 @@ export default {
|
|
|
12
12
|
|
|
13
13
|
mixins: [ChildHook],
|
|
14
14
|
|
|
15
|
-
mounted() {
|
|
16
|
-
// For easy access debugging...
|
|
17
|
-
if ( typeof window !== 'undefined' ) {
|
|
18
|
-
window.v = this.value;
|
|
19
|
-
window.c = this;
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
|
|
23
15
|
data() {
|
|
24
16
|
// Keep label and annotation filters in data so each resource CRUD page can alter individually
|
|
25
17
|
return { errors: [] };
|
package/models/chart.js
CHANGED
|
@@ -10,7 +10,7 @@ export default class Chart extends SteveModel {
|
|
|
10
10
|
let version;
|
|
11
11
|
const chartVersions = this.versions;
|
|
12
12
|
const currentCluster = this.$rootGetters['currentCluster'];
|
|
13
|
-
const workerOSs = currentCluster
|
|
13
|
+
const workerOSs = currentCluster?.workerOSs;
|
|
14
14
|
const compatibleVersions = compatibleVersionsFor(this, workerOSs);
|
|
15
15
|
|
|
16
16
|
if (compatibleVersions.length) {
|
package/models/cluster/node.js
CHANGED
|
@@ -7,6 +7,7 @@ import { parseSi } from '@shell/utils/units';
|
|
|
7
7
|
import findLast from 'lodash/findLast';
|
|
8
8
|
|
|
9
9
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
10
|
+
import { LOCAL } from '@shell/config/query-params';
|
|
10
11
|
|
|
11
12
|
export default class ClusterNode extends SteveModel {
|
|
12
13
|
get _availableActions() {
|
|
@@ -254,10 +255,20 @@ export default class ClusterNode extends SteveModel {
|
|
|
254
255
|
}));
|
|
255
256
|
}
|
|
256
257
|
|
|
258
|
+
/**
|
|
259
|
+
*Find the node's cluster id from it's url
|
|
260
|
+
*/
|
|
257
261
|
get clusterId() {
|
|
258
262
|
const parts = this.links.self.split('/');
|
|
259
263
|
|
|
260
|
-
|
|
264
|
+
// Local cluster url links omit `/k8s/clusters/<cluster id>`
|
|
265
|
+
// `/v1/nodes` vs `k8s/clusters/c-m-274kcrc4/v1/nodes`
|
|
266
|
+
// Be safe when determining this, so work back through the url from a known point
|
|
267
|
+
if (parts.length > 6 && parts[parts.length - 6] === 'k8s' && parts[parts.length - 5] === 'clusters') {
|
|
268
|
+
return parts[parts.length - 4];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return LOCAL;
|
|
261
272
|
}
|
|
262
273
|
|
|
263
274
|
get normanNodeId() {
|
|
@@ -14,25 +14,6 @@ const SPECIAL = [BASE, ADMIN, USER];
|
|
|
14
14
|
const GLOBAL = SUBTYPE_MAPPING.GLOBAL.key;
|
|
15
15
|
|
|
16
16
|
export default class GlobalRole extends SteveModel {
|
|
17
|
-
get availableActions() {
|
|
18
|
-
const out = super._availableActions;
|
|
19
|
-
|
|
20
|
-
const toFilter = ['goToEdit', 'promptRemove'];
|
|
21
|
-
const editActions = out.filter((a) => {
|
|
22
|
-
if ( toFilter.includes(a.action) ) {
|
|
23
|
-
return a;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if ( editActions.length > 0 ) {
|
|
28
|
-
editActions.forEach((a) => {
|
|
29
|
-
a.enabled = !this.builtin;
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
17
|
get customValidationRules() {
|
|
37
18
|
return Role.customValidationRules();
|
|
38
19
|
}
|
|
@@ -2,7 +2,7 @@ import Vue from 'vue';
|
|
|
2
2
|
import { get } from '@shell/utils/object';
|
|
3
3
|
import { DESCRIPTION } from '@shell/config/labels-annotations';
|
|
4
4
|
import { NORMAN } from '@shell/config/types';
|
|
5
|
-
import
|
|
5
|
+
import SteveDescriptionModel from '@shell/plugins/steve/steve-description-class';
|
|
6
6
|
import Role from './rbac.authorization.k8s.io.role';
|
|
7
7
|
|
|
8
8
|
export const CATTLE_API_GROUP = '.cattle.io';
|
|
@@ -55,26 +55,7 @@ export const VERBS = [
|
|
|
55
55
|
'watch',
|
|
56
56
|
];
|
|
57
57
|
|
|
58
|
-
export default class RoleTemplate extends
|
|
59
|
-
get availableActions() {
|
|
60
|
-
const out = super._availableActions;
|
|
61
|
-
|
|
62
|
-
const toFilter = ['goToEdit', 'promptRemove'];
|
|
63
|
-
const editActions = out.filter((a) => {
|
|
64
|
-
if ( toFilter.includes(a.action) ) {
|
|
65
|
-
return a;
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
if ( editActions.length > 0 ) {
|
|
70
|
-
editActions.forEach((a) => {
|
|
71
|
-
a.enabled = !this.builtin;
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return out;
|
|
76
|
-
}
|
|
77
|
-
|
|
58
|
+
export default class RoleTemplate extends SteveDescriptionModel {
|
|
78
59
|
get customValidationRules() {
|
|
79
60
|
return Role.customValidationRules();
|
|
80
61
|
}
|