@rancher/shell 0.3.7 → 0.3.9
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 +55 -14
- package/babel.config.js +17 -4
- package/components/CodeMirror.vue +146 -14
- package/components/ContainerResourceLimit.vue +14 -1
- package/components/CruResource.vue +21 -5
- package/components/ExplorerProjectsNamespaces.vue +5 -1
- package/components/GroupPanel.vue +57 -0
- package/components/Inactivity.vue +229 -0
- package/components/YamlEditor.vue +2 -2
- package/components/form/ArrayList.vue +1 -1
- package/components/form/KeyValue.vue +34 -1
- package/components/form/MatchExpressions.vue +120 -21
- package/components/form/NodeAffinity.vue +54 -4
- package/components/form/PodAffinity.vue +160 -47
- package/components/form/Tolerations.vue +40 -4
- package/components/form/__tests__/ArrayList.test.ts +3 -3
- package/components/form/__tests__/MatchExpressions.test.ts +1 -1
- package/components/nav/Header.vue +2 -0
- package/config/settings.ts +10 -1
- package/core/plugins-loader.js +0 -2
- package/creators/app/files/.gitignore +73 -0
- package/creators/app/init +1 -0
- package/edit/configmap.vue +33 -6
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +326 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +63 -15
- package/edit/workload/mixins/workload.js +12 -4
- package/layouts/blank.vue +4 -0
- package/layouts/default.vue +3 -0
- package/layouts/home.vue +4 -1
- package/layouts/plain.vue +4 -1
- package/mixins/chart.js +1 -1
- package/models/batch.cronjob.js +18 -3
- package/models/provisioning.cattle.io.cluster.js +24 -0
- package/models/workload.js +1 -1
- package/package.json +2 -3
- package/pages/auth/login.vue +1 -0
- package/pages/c/_cluster/explorer/index.vue +1 -4
- package/pages/c/_cluster/settings/performance.vue +61 -7
- package/pages/prefs.vue +18 -2
- package/pkg/vue.config.js +0 -1
- package/plugins/codemirror.js +158 -0
- package/public/index.html +1 -1
- package/store/index.js +36 -21
- package/types/shell/index.d.ts +20 -1
- package/utils/create-yaml.js +105 -8
- package/utils/settings.ts +12 -0
- package/vue.config.js +2 -2
|
@@ -621,6 +621,7 @@ export default {
|
|
|
621
621
|
<div
|
|
622
622
|
v-if="showUserMenu"
|
|
623
623
|
class="user user-menu"
|
|
624
|
+
data-testid="nav_header_showUserMenu"
|
|
624
625
|
tabindex="0"
|
|
625
626
|
@blur="showMenu(false)"
|
|
626
627
|
@click="showMenu(true)"
|
|
@@ -654,6 +655,7 @@ export default {
|
|
|
654
655
|
>
|
|
655
656
|
<ul
|
|
656
657
|
class="list-unstyled dropdown"
|
|
658
|
+
data-testid="user-menu-dropdown"
|
|
657
659
|
@click.stop="showMenu(false)"
|
|
658
660
|
>
|
|
659
661
|
<li
|
package/config/settings.ts
CHANGED
|
@@ -83,7 +83,12 @@ export const SETTING = {
|
|
|
83
83
|
* both pre and post log in. If not present defaults to the usual process
|
|
84
84
|
*/
|
|
85
85
|
THEME: 'ui-theme',
|
|
86
|
-
SYSTEM_NAMESPACES: 'system-namespaces'
|
|
86
|
+
SYSTEM_NAMESPACES: 'system-namespaces',
|
|
87
|
+
/**
|
|
88
|
+
* Cluster Agent configuration
|
|
89
|
+
*/
|
|
90
|
+
CLUSTER_AGENT_DEFAULT_AFFINITY: 'cluster-agent-default-affinity',
|
|
91
|
+
FLEET_AGENT_DEFAULT_AFFINITY: 'fleet-agent-default-affinity',
|
|
87
92
|
};
|
|
88
93
|
|
|
89
94
|
// These are the settings that are allowed to be edited via the UI
|
|
@@ -140,6 +145,10 @@ export const ALLOWED_SETTINGS: GlobalSetting = {
|
|
|
140
145
|
};
|
|
141
146
|
|
|
142
147
|
export const DEFAULT_PERF_SETTING = {
|
|
148
|
+
inactivity: {
|
|
149
|
+
enabled: false,
|
|
150
|
+
threshold: 900,
|
|
151
|
+
},
|
|
143
152
|
incrementalLoading: {
|
|
144
153
|
enabled: true,
|
|
145
154
|
threshold: 1500,
|
package/core/plugins-loader.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
|
-
import $ from 'jquery';
|
|
3
2
|
import JSZip from 'jszip';
|
|
4
3
|
import jsyaml from 'js-yaml';
|
|
5
4
|
|
|
@@ -26,7 +25,6 @@ export default function({
|
|
|
26
25
|
window.Vue = Vue;
|
|
27
26
|
|
|
28
27
|
// Global libraries - allows us to externalise these to reduce package bundle size
|
|
29
|
-
window.$ = $;
|
|
30
28
|
window.__jszip = JSZip;
|
|
31
29
|
window.__jsyaml = jsyaml;
|
|
32
30
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# compiled output
|
|
2
|
+
/dist
|
|
3
|
+
/tmp
|
|
4
|
+
/out-tsc
|
|
5
|
+
|
|
6
|
+
# Runtime data
|
|
7
|
+
pids
|
|
8
|
+
*.pid
|
|
9
|
+
*.seed
|
|
10
|
+
*.pid.lock
|
|
11
|
+
|
|
12
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
13
|
+
lib-cov
|
|
14
|
+
|
|
15
|
+
# Coverage directory used by tools like istanbul
|
|
16
|
+
coverage
|
|
17
|
+
|
|
18
|
+
# nyc test coverage
|
|
19
|
+
.nyc_output
|
|
20
|
+
|
|
21
|
+
# IDEs and editors
|
|
22
|
+
.idea
|
|
23
|
+
.project
|
|
24
|
+
.classpath
|
|
25
|
+
.c9/
|
|
26
|
+
*.launch
|
|
27
|
+
.settings/
|
|
28
|
+
*.sublime-workspace
|
|
29
|
+
|
|
30
|
+
# IDE - VSCode
|
|
31
|
+
.vscode/*
|
|
32
|
+
!.vscode/settings.json
|
|
33
|
+
!.vscode/tasks.json
|
|
34
|
+
!.vscode/launch.json
|
|
35
|
+
!.vscode/extensions.json
|
|
36
|
+
|
|
37
|
+
# misc
|
|
38
|
+
.sass-cache
|
|
39
|
+
connect.lock
|
|
40
|
+
typings
|
|
41
|
+
|
|
42
|
+
# Logs
|
|
43
|
+
logs
|
|
44
|
+
*.log
|
|
45
|
+
npm-debug.log*
|
|
46
|
+
yarn-debug.log*
|
|
47
|
+
yarn-error.log*
|
|
48
|
+
|
|
49
|
+
# Dependency directories
|
|
50
|
+
node_modules/
|
|
51
|
+
jspm_packages/
|
|
52
|
+
|
|
53
|
+
# Optional npm cache directory
|
|
54
|
+
.npm
|
|
55
|
+
|
|
56
|
+
# Optional eslint cache
|
|
57
|
+
.eslintcache
|
|
58
|
+
|
|
59
|
+
# Optional REPL history
|
|
60
|
+
.node_repl_history
|
|
61
|
+
|
|
62
|
+
# Output of 'npm pack'
|
|
63
|
+
*.tgz
|
|
64
|
+
|
|
65
|
+
# Yarn Integrity file
|
|
66
|
+
.yarn-integrity
|
|
67
|
+
|
|
68
|
+
# dotenv environment variables file
|
|
69
|
+
.env
|
|
70
|
+
|
|
71
|
+
# System Files
|
|
72
|
+
.DS_Store
|
|
73
|
+
Thumbs.db
|
package/creators/app/init
CHANGED
package/edit/configmap.vue
CHANGED
|
@@ -31,40 +31,65 @@ export default {
|
|
|
31
31
|
computed: {
|
|
32
32
|
hasBinaryData() {
|
|
33
33
|
return Object.keys(this.binaryData).length > 0;
|
|
34
|
-
}
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Keep all newlines from end, see: https://yaml-multiline.info
|
|
37
|
+
* Apply to 'data' field
|
|
38
|
+
*/
|
|
39
|
+
yamlModifiers() {
|
|
40
|
+
return {
|
|
41
|
+
data: Object.keys(this.data).reduce((acc, key) => ({
|
|
42
|
+
...acc,
|
|
43
|
+
[key]: { chomping: '+' },
|
|
44
|
+
}), {}),
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
validationPassed() {
|
|
49
|
+
return !!this.value.name;
|
|
50
|
+
},
|
|
35
51
|
},
|
|
36
52
|
|
|
37
53
|
watch: {
|
|
38
|
-
data(neu
|
|
54
|
+
data(neu) {
|
|
39
55
|
this.updateValue(neu, 'data');
|
|
40
56
|
},
|
|
41
|
-
binaryData(neu
|
|
57
|
+
binaryData(neu) {
|
|
42
58
|
this.updateValue(neu, 'binaryData');
|
|
43
59
|
},
|
|
44
60
|
},
|
|
45
61
|
|
|
46
62
|
methods: {
|
|
63
|
+
async saveConfigMap() {
|
|
64
|
+
const yaml = this.$refs.cru.createResourceYaml(this.yamlModifiers);
|
|
65
|
+
|
|
66
|
+
await this.value.saveYaml(yaml);
|
|
67
|
+
this.done();
|
|
68
|
+
},
|
|
69
|
+
|
|
47
70
|
updateValue(val, type) {
|
|
48
71
|
this.$set(this.value, type, {});
|
|
49
72
|
|
|
50
73
|
Object.keys(val).forEach((key) => {
|
|
51
74
|
this.$set(this.value[type], key, val[key]);
|
|
52
75
|
});
|
|
53
|
-
}
|
|
76
|
+
},
|
|
54
77
|
}
|
|
55
78
|
};
|
|
56
79
|
</script>
|
|
57
80
|
|
|
58
81
|
<template>
|
|
59
82
|
<CruResource
|
|
83
|
+
ref="cru"
|
|
60
84
|
:done-route="doneRoute"
|
|
61
85
|
:mode="mode"
|
|
62
86
|
:resource="value"
|
|
63
87
|
:subtypes="[]"
|
|
64
|
-
:validation-passed="
|
|
88
|
+
:validation-passed="validationPassed"
|
|
89
|
+
:yaml-modifiers="yamlModifiers"
|
|
65
90
|
:errors="errors"
|
|
66
91
|
@error="e=>errors = e"
|
|
67
|
-
@finish="
|
|
92
|
+
@finish="saveConfigMap"
|
|
68
93
|
@cancel="done"
|
|
69
94
|
>
|
|
70
95
|
<NameNsDescription
|
|
@@ -86,6 +111,8 @@ export default {
|
|
|
86
111
|
:protip="t('configmap.tabs.data.protip')"
|
|
87
112
|
:initial-empty-row="true"
|
|
88
113
|
:value-can-be-empty="true"
|
|
114
|
+
:value-trim="false"
|
|
115
|
+
:value-markdown-multiline="true"
|
|
89
116
|
:read-multiple="true"
|
|
90
117
|
:read-accept="'*'"
|
|
91
118
|
/>
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { Banner } from '@components/Banner';
|
|
3
|
+
import GroupPanel from '@shell/components/GroupPanel';
|
|
4
|
+
import PodAffinity from '@shell/components/form/PodAffinity';
|
|
5
|
+
import NodeAffinity from '@shell/components/form/NodeAffinity';
|
|
6
|
+
import ContainerResourceLimit from '@shell/components/ContainerResourceLimit';
|
|
7
|
+
import Tolerations from '@shell/components/form/Tolerations';
|
|
8
|
+
import { cleanUp } from '@shell/utils/object';
|
|
9
|
+
import { fetchSetting } from '@shell/utils/settings';
|
|
10
|
+
import { RadioGroup } from '@components/Form/Radio';
|
|
11
|
+
|
|
12
|
+
export function cleanAgentConfiguration(model, key) {
|
|
13
|
+
if (!model || !model[key]) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const v = model[key];
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(v) && v.length === 0) {
|
|
20
|
+
delete model[key];
|
|
21
|
+
} else if (v && typeof v === 'object') {
|
|
22
|
+
Object.keys(v).forEach((k) => {
|
|
23
|
+
// delete these auxiliary props used in podAffinity and nodeAffinity that shouldn't be sent to the server
|
|
24
|
+
if (k === '_namespaceOption' || k === '_namespaces' || k === '_anti' || k === '_id') {
|
|
25
|
+
delete v[k];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// prevent cleanup of namespaceSelector when an empty object because it represents all namespaces in pod/node affinity
|
|
29
|
+
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#podaffinityterm-v1-core
|
|
30
|
+
if (k !== 'namespaceSelector') {
|
|
31
|
+
cleanAgentConfiguration(v, k);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (Object.keys(v).length === 0) {
|
|
36
|
+
delete model[key];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Affinity radio button choices
|
|
42
|
+
const DEFAULT = 'default';
|
|
43
|
+
const CUSTOM = 'custom';
|
|
44
|
+
|
|
45
|
+
// This is the form for Agent Configuration
|
|
46
|
+
// Used for both Cluster Agent and Fleet Agent configuration
|
|
47
|
+
export default {
|
|
48
|
+
components: {
|
|
49
|
+
Banner,
|
|
50
|
+
ContainerResourceLimit,
|
|
51
|
+
GroupPanel,
|
|
52
|
+
PodAffinity,
|
|
53
|
+
NodeAffinity,
|
|
54
|
+
RadioGroup,
|
|
55
|
+
Tolerations,
|
|
56
|
+
},
|
|
57
|
+
props: {
|
|
58
|
+
value: {
|
|
59
|
+
type: Object,
|
|
60
|
+
default: () => {},
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
mode: {
|
|
64
|
+
type: String,
|
|
65
|
+
required: true,
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
type: {
|
|
69
|
+
type: String,
|
|
70
|
+
required: true,
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
async fetch() {
|
|
75
|
+
// Default affinity
|
|
76
|
+
const settingId = `${ this.type }-agent-default-affinity`;
|
|
77
|
+
const setting = await fetchSetting(this.$store, settingId);
|
|
78
|
+
|
|
79
|
+
if (setting) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(setting.value || setting.default);
|
|
82
|
+
|
|
83
|
+
this.defaultAffinity = parsed || {};
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error('Could not parse agent default setting', e); // eslint-disable-line no-console
|
|
86
|
+
this.defaultAffinity = {};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
data() {
|
|
92
|
+
const nodeAffinity = this.value?.overrideAffinity?.nodeAffinity;
|
|
93
|
+
const podAffinity = this.value?.overrideAffinity?.podAffinity;
|
|
94
|
+
const podAntiAffinity = this.value?.overrideAffinity?.podAntiAffinity;
|
|
95
|
+
|
|
96
|
+
let hasAffinityPopulated = false;
|
|
97
|
+
|
|
98
|
+
if ((nodeAffinity && Object.keys(nodeAffinity).length) ||
|
|
99
|
+
(podAffinity && Object.keys(podAffinity).length) ||
|
|
100
|
+
(podAntiAffinity && Object.keys(podAntiAffinity).length)) {
|
|
101
|
+
hasAffinityPopulated = true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
defaultAffinity: {},
|
|
106
|
+
affinitySetting: hasAffinityPopulated ? CUSTOM : DEFAULT,
|
|
107
|
+
nodeAffinity: {}
|
|
108
|
+
};
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
created() {
|
|
112
|
+
this.ensureValue();
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
computed: {
|
|
116
|
+
flatResources: {
|
|
117
|
+
get() {
|
|
118
|
+
const { limits = {}, requests = {} } = this.value.overrideResourceRequirements || {};
|
|
119
|
+
const {
|
|
120
|
+
cpu: limitsCpu,
|
|
121
|
+
memory: limitsMemory,
|
|
122
|
+
} = limits;
|
|
123
|
+
const { cpu: requestsCpu, memory: requestsMemory } = requests;
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
limitsCpu,
|
|
127
|
+
limitsMemory,
|
|
128
|
+
requestsCpu,
|
|
129
|
+
requestsMemory,
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
set(neu) {
|
|
133
|
+
const {
|
|
134
|
+
limitsCpu,
|
|
135
|
+
limitsMemory,
|
|
136
|
+
requestsCpu,
|
|
137
|
+
requestsMemory,
|
|
138
|
+
} = neu;
|
|
139
|
+
|
|
140
|
+
const existing = this.value?.overrideResourceRequirements || {};
|
|
141
|
+
|
|
142
|
+
delete existing.requests;
|
|
143
|
+
delete existing.limits;
|
|
144
|
+
|
|
145
|
+
const out = {
|
|
146
|
+
...existing,
|
|
147
|
+
requests: {
|
|
148
|
+
cpu: requestsCpu,
|
|
149
|
+
memory: requestsMemory,
|
|
150
|
+
},
|
|
151
|
+
limits: {
|
|
152
|
+
cpu: limitsCpu,
|
|
153
|
+
memory: limitsMemory,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
this.$set(this.value, 'overrideResourceRequirements', cleanUp(out));
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
affinityOptions() {
|
|
162
|
+
return [{
|
|
163
|
+
label: this.t('cluster.agentConfig.affinity.default'),
|
|
164
|
+
value: DEFAULT,
|
|
165
|
+
}, {
|
|
166
|
+
label: this.t('cluster.agentConfig.affinity.custom'),
|
|
167
|
+
value: CUSTOM,
|
|
168
|
+
}];
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
canEditAffinity() {
|
|
172
|
+
return this.affinitySetting === CUSTOM;
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
watch: {
|
|
177
|
+
value() {
|
|
178
|
+
this.ensureValue();
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
methods: {
|
|
183
|
+
ensureValue() {
|
|
184
|
+
// Ensure we have the model structure needed for the form controls
|
|
185
|
+
if (this.value) {
|
|
186
|
+
this.value.overrideAffinity = this.value.overrideAffinity || {};
|
|
187
|
+
this.value.appendTolerations = this.value.appendTolerations || [];
|
|
188
|
+
this.value.overrideResourceRequirements = this.value.overrideResourceRequirements || {};
|
|
189
|
+
|
|
190
|
+
this.nodeAffinity = this.value?.overrideAffinity?.nodeAffinity || {};
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
affinitySettingChange() {
|
|
195
|
+
if (this.affinitySetting === CUSTOM) {
|
|
196
|
+
const parsedDefaultAffinites = JSON.parse(JSON.stringify(this.defaultAffinity));
|
|
197
|
+
|
|
198
|
+
// Copy the default so that the user can edit it
|
|
199
|
+
// this will cover the pod affinities
|
|
200
|
+
this.$set(this.value, 'overrideAffinity', parsedDefaultAffinites);
|
|
201
|
+
|
|
202
|
+
// in order not to break the node affinity component, let's go for a slightly different way of handling the logic here
|
|
203
|
+
if (parsedDefaultAffinites.nodeAffinity) {
|
|
204
|
+
this.nodeAffinity = parsedDefaultAffinites.nodeAffinity;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
this.$set(this.value, 'overrideAffinity', {});
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
updateNodeAffinity(val) {
|
|
211
|
+
this.$set(this.value.overrideAffinity, 'nodeAffinity', val);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
</script>
|
|
216
|
+
|
|
217
|
+
<template>
|
|
218
|
+
<div v-if="value && Object.keys(value).length">
|
|
219
|
+
<Banner
|
|
220
|
+
:closable="false"
|
|
221
|
+
color="info"
|
|
222
|
+
label-key="cluster.agentConfig.banners.advanced"
|
|
223
|
+
/>
|
|
224
|
+
|
|
225
|
+
<GroupPanel
|
|
226
|
+
label-key="cluster.agentConfig.groups.podRequestsAndLimits"
|
|
227
|
+
class="mt-20"
|
|
228
|
+
>
|
|
229
|
+
<Banner
|
|
230
|
+
:closable="false"
|
|
231
|
+
color="info"
|
|
232
|
+
label-key="cluster.agentConfig.banners.limits"
|
|
233
|
+
/>
|
|
234
|
+
<ContainerResourceLimit
|
|
235
|
+
v-model="flatResources"
|
|
236
|
+
:mode="mode"
|
|
237
|
+
:show-tip="false"
|
|
238
|
+
:handle-gpu-limit="false"
|
|
239
|
+
class="mt-10"
|
|
240
|
+
/>
|
|
241
|
+
</GroupPanel>
|
|
242
|
+
|
|
243
|
+
<GroupPanel
|
|
244
|
+
label-key="cluster.agentConfig.groups.podTolerations"
|
|
245
|
+
class="mt-20"
|
|
246
|
+
>
|
|
247
|
+
<Banner
|
|
248
|
+
:closable="false"
|
|
249
|
+
color="info"
|
|
250
|
+
label-key="cluster.agentConfig.banners.tolerations"
|
|
251
|
+
/>
|
|
252
|
+
<Tolerations
|
|
253
|
+
v-model="value.appendTolerations"
|
|
254
|
+
:mode="mode"
|
|
255
|
+
class="mt-10"
|
|
256
|
+
/>
|
|
257
|
+
</GroupPanel>
|
|
258
|
+
|
|
259
|
+
<GroupPanel
|
|
260
|
+
label-key="cluster.agentConfig.groups.podAffinity"
|
|
261
|
+
class="mt-20"
|
|
262
|
+
>
|
|
263
|
+
<RadioGroup
|
|
264
|
+
v-model="affinitySetting"
|
|
265
|
+
name="affinity-override"
|
|
266
|
+
:mode="mode"
|
|
267
|
+
:options="affinityOptions"
|
|
268
|
+
class="mt-10"
|
|
269
|
+
data-testid="affinity-options"
|
|
270
|
+
@input="affinitySettingChange"
|
|
271
|
+
/>
|
|
272
|
+
|
|
273
|
+
<Banner
|
|
274
|
+
v-if="canEditAffinity"
|
|
275
|
+
:closable="false"
|
|
276
|
+
color="warning"
|
|
277
|
+
>
|
|
278
|
+
<p v-clean-html="t('cluster.agentConfig.banners.windowsCompatibility', {}, true)" />
|
|
279
|
+
</Banner>
|
|
280
|
+
|
|
281
|
+
<h4 v-if="canEditAffinity">
|
|
282
|
+
{{ t('cluster.agentConfig.subGroups.podAffinityAnti') }}
|
|
283
|
+
</h4>
|
|
284
|
+
|
|
285
|
+
<PodAffinity
|
|
286
|
+
v-if="canEditAffinity"
|
|
287
|
+
v-model="value"
|
|
288
|
+
field="overrideAffinity"
|
|
289
|
+
:mode="mode"
|
|
290
|
+
class="mt-0 mb-20"
|
|
291
|
+
:all-namespaces-option-available="true"
|
|
292
|
+
:force-input-namespace-selection="true"
|
|
293
|
+
:remove-labeled-input-namespace-label="true"
|
|
294
|
+
data-testid="pod-affinity"
|
|
295
|
+
/>
|
|
296
|
+
|
|
297
|
+
<div
|
|
298
|
+
v-if="canEditAffinity"
|
|
299
|
+
class="separator"
|
|
300
|
+
/>
|
|
301
|
+
<h4
|
|
302
|
+
v-if="canEditAffinity"
|
|
303
|
+
class="mt-20"
|
|
304
|
+
>
|
|
305
|
+
{{ t('cluster.agentConfig.subGroups.nodeAffinity') }}
|
|
306
|
+
</h4>
|
|
307
|
+
|
|
308
|
+
<NodeAffinity
|
|
309
|
+
v-if="canEditAffinity"
|
|
310
|
+
v-model="nodeAffinity"
|
|
311
|
+
:matching-selector-display="true"
|
|
312
|
+
:mode="mode"
|
|
313
|
+
class="mt-0"
|
|
314
|
+
data-testid="node-affinity"
|
|
315
|
+
@input="updateNodeAffinity"
|
|
316
|
+
/>
|
|
317
|
+
</GroupPanel>
|
|
318
|
+
</div>
|
|
319
|
+
</template>
|
|
320
|
+
|
|
321
|
+
<style lang="scss" scoped>
|
|
322
|
+
.separator {
|
|
323
|
+
width: 100%;
|
|
324
|
+
border-top: 1px solid var(--border);
|
|
325
|
+
}
|
|
326
|
+
</style>
|