@rancher/shell 0.3.11 → 0.3.12
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 +51 -5
- package/chart/monitoring/StorageClassSelector.vue +1 -0
- package/chart/monitoring/index.vue +4 -0
- package/chart/monitoring/prometheus/index.vue +6 -3
- package/components/ActionMenu.vue +1 -1
- package/components/DetailTop.vue +0 -2
- package/components/ExplorerMembers.vue +22 -10
- package/components/ExplorerProjectsNamespaces.vue +1 -0
- package/components/GrafanaDashboard.vue +2 -2
- package/components/Inactivity.vue +1 -0
- package/components/ModalWithCard.vue +1 -0
- package/components/Tabbed/index.vue +2 -0
- package/components/Wizard.vue +4 -3
- package/components/form/KeyValue.vue +12 -7
- package/components/form/NodeAffinity.vue +29 -7
- package/components/form/PodAffinity.vue +27 -7
- package/components/form/Taints.vue +6 -0
- package/components/formatter/ExtensionCache.vue +74 -0
- package/components/nav/Header.vue +1 -0
- package/components/nav/WindowManager/ContainerShell.vue +10 -0
- package/components/nav/WindowManager/index.vue +1 -0
- package/config/product/explorer.js +1 -10
- package/config/product/monitoring.js +2 -1
- package/config/router.js +3 -3
- package/config/table-headers.js +32 -24
- package/config/uiplugins.js +11 -0
- package/config/workload.ts +1 -0
- package/core/types.ts +25 -7
- package/creators/pkg/files/.github/workflows/build-container.yml +64 -0
- package/creators/pkg/init +13 -6
- package/detail/node.vue +2 -2
- package/detail/workload/index.vue +1 -1
- package/edit/__tests__/management.cattle.io.setting.test.ts +1 -1
- package/edit/autoscaling.horizontalpodautoscaler/metric-target.vue +0 -2
- package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +43 -0
- package/edit/logging.banzaicloud.io.output/index.vue +8 -5
- package/edit/logging.banzaicloud.io.output/providers/__tests__/loki.test.ts +13 -0
- package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +0 -2
- package/edit/monitoring.coreos.com.receiver/index.vue +32 -1
- package/edit/monitoring.coreos.com.receiver/types/email.vue +12 -4
- package/edit/namespace.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +36 -6
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +2 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +58 -13
- package/middleware/authenticated.js +1 -0
- package/models/__tests__/batch.cronjob.test.ts +88 -0
- package/models/cluster/node.js +8 -0
- package/models/management.cattle.io.clusterroletemplatebinding.js +5 -1
- package/models/projectroletemplatebinding.js +9 -1
- package/models/workload.js +1 -1
- package/package.json +1 -1
- package/pages/__tests__/prefs.test.ts +96 -0
- package/pages/auth/setup.vue +13 -13
- package/pages/c/_cluster/apps/charts/chart.vue +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +5 -2
- package/pages/c/_cluster/monitoring/index.vue +10 -5
- package/pages/c/_cluster/settings/performance.vue +2 -0
- package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +601 -0
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +183 -0
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +50 -9
- package/pages/c/_cluster/uiplugins/index.vue +329 -224
- package/pages/fail-whale.vue +1 -1
- package/pages/home.vue +11 -0
- package/pages/prefs.vue +20 -1
- package/plugins/plugin.js +1 -1
- package/public/index.html +6 -1
- package/rancher-components/components/Card/Card.vue +1 -0
- package/rancher-components/components/Form/Radio/RadioGroup.vue +1 -0
- package/scripts/extension/bundle +20 -4
- package/scripts/extension/helm/charts/ui-plugin-server/.helmignore +23 -0
- package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +20 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/_helpers.tpl +52 -0
- package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +12 -0
- package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +6 -0
- package/scripts/extension/helm/package/Dockerfile +27 -0
- package/scripts/extension/helm/package/nginx.conf +17 -0
- package/scripts/extension/helm/scripts/package +23 -0
- package/scripts/extension/helm/scripts/patch +101 -0
- package/scripts/extension/helm/scripts/version +31 -0
- package/scripts/extension/helmpatch +3 -25
- package/scripts/extension/publish +47 -32
- package/types/shell/index.d.ts +30 -24
- package/utils/__tests__/grafana.test.ts +2 -2
- package/utils/error.js +11 -0
- package/utils/grafana.js +5 -4
- package/vue.config.js +3 -17
|
@@ -1274,9 +1274,6 @@ cluster:
|
|
|
1274
1274
|
label: KubeconfigContent
|
|
1275
1275
|
placeholder: 'Namespace/Name'
|
|
1276
1276
|
cluster: Imported Harvester Cluster
|
|
1277
|
-
affinity:
|
|
1278
|
-
namespaces:
|
|
1279
|
-
placeholder: e.g. default,system,base
|
|
1280
1277
|
installGuestAgent: Install guest agent
|
|
1281
1278
|
description:
|
|
1282
1279
|
label: Cluster Description
|
|
@@ -3994,12 +3991,14 @@ plugins:
|
|
|
3994
3991
|
builtin: Built-in
|
|
3995
3992
|
experimental: Experimental
|
|
3996
3993
|
third-party: Third-Party
|
|
3994
|
+
image: Image
|
|
3997
3995
|
installing: Installing ...
|
|
3998
3996
|
uninstalling: Uninstalling ...
|
|
3999
3997
|
descriptions:
|
|
4000
3998
|
experimental: This Extension is marked as experimental
|
|
4001
3999
|
third-party: This Extension is provided by a Third-Party
|
|
4002
4000
|
built-in: This Extension is built-in
|
|
4001
|
+
image: This Extension Image has been loaded manually
|
|
4003
4002
|
error:
|
|
4004
4003
|
title: Error loading extension
|
|
4005
4004
|
message: Could not load extension code
|
|
@@ -4029,12 +4028,53 @@ plugins:
|
|
|
4029
4028
|
available: No Extensions available
|
|
4030
4029
|
installed: No Extensions installed
|
|
4031
4030
|
updates: No updates available for installed Extensions
|
|
4031
|
+
images: No Extension Images installed
|
|
4032
4032
|
loadError: An error occurred loading the code for this extension
|
|
4033
4033
|
helmError: "An error occurred installing the extension via Helm"
|
|
4034
4034
|
manageRepos: Manage Repositories
|
|
4035
|
+
manageCharts: Manage Extension Charts
|
|
4036
|
+
manageCatalog:
|
|
4037
|
+
label: Manage Extension Catalogs
|
|
4038
|
+
title: Extension
|
|
4039
|
+
subtitle: Catalogs
|
|
4040
|
+
imageLoad:
|
|
4041
|
+
load: Import Extension Catalog
|
|
4042
|
+
prompt: An Extension Catalog contains extension assets bundled into an image, importing will take the image and host a Helm repository to act as a catalog for custom built Extensions.
|
|
4043
|
+
fields:
|
|
4044
|
+
image:
|
|
4045
|
+
label: Catalog Image Reference
|
|
4046
|
+
placeholder: "e.g. hub.docker.io/example-org/my-image:latest"
|
|
4047
|
+
secrets:
|
|
4048
|
+
banner: "If the registry that hosts the Catalog Image requires Pull Secrets, they must be created in the following namespace:<pre>cattle-ui-plugin-system</pre>"
|
|
4049
|
+
banner: This will create an Deployment, Service, and Helm repository to serve the extension charts.
|
|
4050
|
+
imageVersion:
|
|
4051
|
+
title: Image Version Not Found
|
|
4052
|
+
message: Unable to determine image version from {image}, defaulting to latest
|
|
4053
|
+
error:
|
|
4054
|
+
exists:
|
|
4055
|
+
deployment:
|
|
4056
|
+
title: Deployment Conflict
|
|
4057
|
+
message: A container with the image {image} already exists
|
|
4058
|
+
service:
|
|
4059
|
+
title: Service Conflict
|
|
4060
|
+
message: A service with the name {svc} already exists
|
|
4061
|
+
repo:
|
|
4062
|
+
title: Helm Repository Conflict
|
|
4063
|
+
message: A repository with the name {repo} already exists
|
|
4064
|
+
success:
|
|
4065
|
+
title: "Imported Extension Catalog from: {name}"
|
|
4066
|
+
message: Extension Catalog image was imported successfully
|
|
4067
|
+
headers:
|
|
4068
|
+
image:
|
|
4069
|
+
name: images
|
|
4070
|
+
label: Deployment Image
|
|
4071
|
+
cacheState:
|
|
4072
|
+
name: cacheState
|
|
4073
|
+
label: Cache State
|
|
4035
4074
|
tabs:
|
|
4036
4075
|
all: All
|
|
4037
4076
|
available: Available
|
|
4077
|
+
images: Images
|
|
4038
4078
|
installed: Installed
|
|
4039
4079
|
updates: Updates
|
|
4040
4080
|
title: Extensions
|
|
@@ -4057,6 +4097,7 @@ plugins:
|
|
|
4057
4097
|
label: Uninstall
|
|
4058
4098
|
title: "Uninstall Extension: {name}"
|
|
4059
4099
|
prompt: "Are you sure that you want to uninstall this Extension?"
|
|
4100
|
+
custom: "Are you sure that you want to uninstall this Extension Image? This will also remove any Extensions provided by this image."
|
|
4060
4101
|
upgradeAvailable: A newer version of this Extension is available
|
|
4061
4102
|
reload: Extensions changed - reload required
|
|
4062
4103
|
safeMode:
|
|
@@ -6349,8 +6390,13 @@ typeLabel:
|
|
|
6349
6390
|
}
|
|
6350
6391
|
management.cattle.io.clusterroletemplatebinding: |-
|
|
6351
6392
|
{count, plural,
|
|
6352
|
-
one { Cluster
|
|
6353
|
-
other { Cluster
|
|
6393
|
+
one { Cluster Membership }
|
|
6394
|
+
other { Cluster Memberships }
|
|
6395
|
+
}
|
|
6396
|
+
projectroletemplatebinding: |-
|
|
6397
|
+
{count, plural,
|
|
6398
|
+
one { Project Membership }
|
|
6399
|
+
other { Project Memberships }
|
|
6354
6400
|
}
|
|
6355
6401
|
management.cattle.io.feature: |-
|
|
6356
6402
|
{count, plural,
|
|
@@ -176,6 +176,10 @@ export default {
|
|
|
176
176
|
const selector =
|
|
177
177
|
prometheusSpec?.storageSpec?.volumeClaimTemplate?.spec?.selector;
|
|
178
178
|
|
|
179
|
+
// This works for UI editor installation
|
|
180
|
+
// However, it doesn't work for yaml editor installation
|
|
181
|
+
// Global values later merged again in charts/install.vue addGlobalValuesTo()
|
|
182
|
+
// We still need to remove the global values from charts/install.vue addGlobalValuesTo()
|
|
179
183
|
if (
|
|
180
184
|
selector &&
|
|
181
185
|
isEmpty(selector.matchExpressions) &&
|
|
@@ -72,7 +72,7 @@ export default {
|
|
|
72
72
|
let matchExpressions;
|
|
73
73
|
|
|
74
74
|
if (selector && selector?.matchExpressions) {
|
|
75
|
-
matchExpressions = convert((selector?.matchLabels || {}), selector
|
|
75
|
+
matchExpressions = convert((selector?.matchLabels || {}), selector?.matchExpressions);
|
|
76
76
|
|
|
77
77
|
return matchExpressions;
|
|
78
78
|
} else {
|
|
@@ -154,7 +154,6 @@ export default {
|
|
|
154
154
|
spec: {
|
|
155
155
|
accessModes: ['ReadWriteOnce'],
|
|
156
156
|
resources: { requests: { storage: '50Gi' } },
|
|
157
|
-
selector: { matchExpressions: [], matchLabels: {} },
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
);
|
|
@@ -311,6 +310,7 @@ export default {
|
|
|
311
310
|
<div class="col span-6">
|
|
312
311
|
<Checkbox
|
|
313
312
|
v-model="enablePersistentStorage"
|
|
313
|
+
data-testid="checkbox-chart-enable-persistent-storage"
|
|
314
314
|
:label="t('monitoring.prometheus.storage.label')"
|
|
315
315
|
/>
|
|
316
316
|
</div>
|
|
@@ -325,7 +325,10 @@ export default {
|
|
|
325
325
|
/>
|
|
326
326
|
</div>
|
|
327
327
|
<div class="col span-6">
|
|
328
|
-
<div
|
|
328
|
+
<div
|
|
329
|
+
v-if="showStorageClasses"
|
|
330
|
+
data-testid="select-chart-prometheus-storage-class"
|
|
331
|
+
>
|
|
329
332
|
<StorageClassSelector
|
|
330
333
|
:mode="mode"
|
|
331
334
|
:options="storageClasses"
|
package/components/DetailTop.vue
CHANGED
|
@@ -6,8 +6,6 @@ import { _VIEW } from '@shell/config/query-params';
|
|
|
6
6
|
import { ExtensionPoint, PanelLocation } from '@shell/core/types';
|
|
7
7
|
import ExtensionPanel from '@shell/components/ExtensionPanel';
|
|
8
8
|
|
|
9
|
-
export const SEPARATOR = { separator: true };
|
|
10
|
-
|
|
11
9
|
export default {
|
|
12
10
|
components: {
|
|
13
11
|
DetailText, Tag, ExtensionPanel
|
|
@@ -186,17 +186,25 @@ export default {
|
|
|
186
186
|
|
|
187
187
|
// We need to group each of the TemplateRoleBindings by the user + project
|
|
188
188
|
const userRoles = [...fakeRows, ...this.filteredProjectRoleTemplateBindings].reduce((rows, curr) => {
|
|
189
|
-
const {
|
|
189
|
+
const {
|
|
190
|
+
userId, groupPrincipalId, roleTemplate, projectId
|
|
191
|
+
} = curr;
|
|
190
192
|
|
|
191
|
-
const
|
|
193
|
+
const userOrGroup = userId || groupPrincipalId;
|
|
192
194
|
|
|
193
|
-
if (!
|
|
194
|
-
rows
|
|
195
|
-
rows[userKey].allRoles = [];
|
|
195
|
+
if (!userOrGroup) {
|
|
196
|
+
return rows;
|
|
196
197
|
}
|
|
197
198
|
|
|
198
|
-
|
|
199
|
-
|
|
199
|
+
const userOrGroupKey = userOrGroup + projectId;
|
|
200
|
+
|
|
201
|
+
if (!rows[userOrGroupKey] ) {
|
|
202
|
+
rows[userOrGroupKey] = curr;
|
|
203
|
+
rows[userOrGroupKey].allRoles = [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (roleTemplate) {
|
|
207
|
+
rows[userOrGroupKey].allRoles.push(curr.roleTemplate);
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
return rows;
|
|
@@ -242,9 +250,13 @@ export default {
|
|
|
242
250
|
},
|
|
243
251
|
|
|
244
252
|
getProjectRoleBinding(row, role) {
|
|
245
|
-
// Each row is a combination of user and project
|
|
253
|
+
// Each row is a combination of user/group and project
|
|
246
254
|
// So find the specfic roleBindingTemplate corresponding to the specific role + project
|
|
247
|
-
|
|
255
|
+
const userOrGroupKey = row.userId ? 'userId' : 'groupPrincipalId';
|
|
256
|
+
|
|
257
|
+
return this.projectRoleTemplateBindings.find((r) => {
|
|
258
|
+
return r.roleTemplateId === role.id && r[userOrGroupKey] === row[userOrGroupKey];
|
|
259
|
+
});
|
|
248
260
|
},
|
|
249
261
|
|
|
250
262
|
async removeRole(row, role, event) {
|
|
@@ -339,7 +351,7 @@ export default {
|
|
|
339
351
|
<button
|
|
340
352
|
v-if="canEditProjectMembers"
|
|
341
353
|
type="button"
|
|
342
|
-
class="create-namespace btn btn-sm role-secondary mr-
|
|
354
|
+
class="create-namespace btn btn-sm role-secondary mr-10 right"
|
|
343
355
|
@click="addProjectMember(group)"
|
|
344
356
|
>
|
|
345
357
|
{{ t('members.createActionLabel') }}
|
|
@@ -40,7 +40,7 @@ export default {
|
|
|
40
40
|
},
|
|
41
41
|
data() {
|
|
42
42
|
return {
|
|
43
|
-
loading: false, error: false, interval: null,
|
|
43
|
+
loading: false, error: false, interval: null, errorTimer: null, monitoringVersion: null
|
|
44
44
|
};
|
|
45
45
|
},
|
|
46
46
|
computed: {
|
|
@@ -242,7 +242,7 @@ export default {
|
|
|
242
242
|
v-show="!error"
|
|
243
243
|
ref="frame"
|
|
244
244
|
:class="{loading, frame: true}"
|
|
245
|
-
:src="
|
|
245
|
+
:src="currentUrl"
|
|
246
246
|
frameborder="0"
|
|
247
247
|
scrolling="no"
|
|
248
248
|
/>
|
|
@@ -239,10 +239,12 @@ export default {
|
|
|
239
239
|
v-for="tab in sortedTabs"
|
|
240
240
|
:id="tab.name"
|
|
241
241
|
:key="tab.name"
|
|
242
|
+
:data-testid="tab.name"
|
|
242
243
|
:class="{tab: true, active: tab.active, disabled: tab.disabled, error: (tab.error)}"
|
|
243
244
|
role="presentation"
|
|
244
245
|
>
|
|
245
246
|
<a
|
|
247
|
+
:data-testid="`btn-${tab.name}`"
|
|
246
248
|
:aria-controls="'#' + tab.name"
|
|
247
249
|
:aria-selected="tab.active"
|
|
248
250
|
role="tab"
|
package/components/Wizard.vue
CHANGED
|
@@ -400,7 +400,10 @@ export default {
|
|
|
400
400
|
@close="errors.splice(idx, 1)"
|
|
401
401
|
/>
|
|
402
402
|
</div>
|
|
403
|
-
<div
|
|
403
|
+
<div
|
|
404
|
+
id="wizard-footer-controls"
|
|
405
|
+
class="controls-row pt-20"
|
|
406
|
+
>
|
|
404
407
|
<slot
|
|
405
408
|
name="cancel"
|
|
406
409
|
:cancel="cancel"
|
|
@@ -468,7 +471,6 @@ $spacer: 10px;
|
|
|
468
471
|
flex-direction: column;
|
|
469
472
|
flex: 1;
|
|
470
473
|
padding: 0;
|
|
471
|
-
height: 0;
|
|
472
474
|
justify-content: flex-start;
|
|
473
475
|
}
|
|
474
476
|
|
|
@@ -647,7 +649,6 @@ $spacer: 10px;
|
|
|
647
649
|
overflow: hidden;
|
|
648
650
|
display: flex;
|
|
649
651
|
flex-direction: column;
|
|
650
|
-
height: 100%;
|
|
651
652
|
flex: 1;
|
|
652
653
|
}
|
|
653
654
|
}
|
|
@@ -246,7 +246,11 @@ export default {
|
|
|
246
246
|
parseLinesFromFile: {
|
|
247
247
|
default: false,
|
|
248
248
|
type: Boolean
|
|
249
|
-
}
|
|
249
|
+
},
|
|
250
|
+
disabled: {
|
|
251
|
+
default: false,
|
|
252
|
+
type: Boolean
|
|
253
|
+
},
|
|
250
254
|
},
|
|
251
255
|
data() {
|
|
252
256
|
const rows = this.getRows(this.value);
|
|
@@ -614,13 +618,14 @@ export default {
|
|
|
614
618
|
:keyName="keyName"
|
|
615
619
|
:valueName="valueName"
|
|
616
620
|
:queueUpdate="queueUpdate"
|
|
621
|
+
:disabled="disabled"
|
|
617
622
|
>
|
|
618
623
|
<Select
|
|
619
624
|
v-if="keyOptions"
|
|
620
625
|
ref="key"
|
|
621
626
|
v-model="row[keyName]"
|
|
622
627
|
:searchable="true"
|
|
623
|
-
:disabled="isProtected(row.key)"
|
|
628
|
+
:disabled="disabled || isProtected(row.key)"
|
|
624
629
|
:clearable="false"
|
|
625
630
|
:taggable="keyTaggable"
|
|
626
631
|
:options="calculateOptions(row[keyName])"
|
|
@@ -630,7 +635,7 @@ export default {
|
|
|
630
635
|
v-else
|
|
631
636
|
ref="key"
|
|
632
637
|
v-model="row[keyName]"
|
|
633
|
-
:disabled="isView || !keyEditable || isProtected(row.key)"
|
|
638
|
+
:disabled="isView || disabled || !keyEditable || isProtected(row.key)"
|
|
634
639
|
:placeholder="keyPlaceholder"
|
|
635
640
|
@input="queueUpdate"
|
|
636
641
|
@paste="onPaste(i, $event)"
|
|
@@ -672,7 +677,7 @@ export default {
|
|
|
672
677
|
v-else-if="valueMultiline"
|
|
673
678
|
v-model="row[valueName]"
|
|
674
679
|
:class="{'conceal': valueConcealed}"
|
|
675
|
-
:disabled="isProtected(row.key)"
|
|
680
|
+
:disabled="disabled || isProtected(row.key)"
|
|
676
681
|
:mode="mode"
|
|
677
682
|
:placeholder="valuePlaceholder"
|
|
678
683
|
:min-height="40"
|
|
@@ -682,7 +687,7 @@ export default {
|
|
|
682
687
|
<input
|
|
683
688
|
v-else
|
|
684
689
|
v-model="row[valueName]"
|
|
685
|
-
:disabled="isView || isProtected(row.key)"
|
|
690
|
+
:disabled="isView || disabled || isProtected(row.key)"
|
|
686
691
|
:type="valueConcealed ? 'password' : 'text'"
|
|
687
692
|
:placeholder="valuePlaceholder"
|
|
688
693
|
autocorrect="off"
|
|
@@ -717,7 +722,7 @@ export default {
|
|
|
717
722
|
>
|
|
718
723
|
<button
|
|
719
724
|
type="button"
|
|
720
|
-
:disabled="isView || isProtected(row.key)"
|
|
725
|
+
:disabled="isView || isProtected(row.key) || disabled"
|
|
721
726
|
class="btn role-link"
|
|
722
727
|
@click="remove(i)"
|
|
723
728
|
>
|
|
@@ -739,7 +744,7 @@ export default {
|
|
|
739
744
|
v-if="addAllowed"
|
|
740
745
|
type="button"
|
|
741
746
|
class="btn role-tertiary add"
|
|
742
|
-
:disabled="loading || (keyOptions && filteredKeyOptions.length === 0)"
|
|
747
|
+
:disabled="loading || disabled || (keyOptions && filteredKeyOptions.length === 0)"
|
|
743
748
|
@click="add()"
|
|
744
749
|
>
|
|
745
750
|
<i
|
|
@@ -95,10 +95,36 @@ export default {
|
|
|
95
95
|
const requiredDuringSchedulingIgnoredDuringExecution = { nodeSelectorTerms: [] };
|
|
96
96
|
const preferredDuringSchedulingIgnoredDuringExecution = [] ;
|
|
97
97
|
|
|
98
|
-
this.allSelectorTerms.forEach((
|
|
98
|
+
this.allSelectorTerms.forEach((t) => {
|
|
99
|
+
const term = { ...t };
|
|
100
|
+
|
|
101
|
+
// the 'matching' field isn't part of the affinity spec: including this in the save request will cause a flood of errors that might cause the request to fail
|
|
102
|
+
// same deal with term.preference.weight
|
|
103
|
+
if (term.matchExpressions) {
|
|
104
|
+
term.matchExpressions = (term.matchExpressions || []).map((expression) => {
|
|
105
|
+
const out = { ...expression };
|
|
106
|
+
|
|
107
|
+
delete out.matching;
|
|
108
|
+
|
|
109
|
+
return out;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (term.matchFields) {
|
|
114
|
+
term.matchFields = (term.matchFields || []).map((field) => {
|
|
115
|
+
const out = { ...field };
|
|
116
|
+
|
|
117
|
+
delete out.matching;
|
|
118
|
+
|
|
119
|
+
return out;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
99
123
|
if (term.weight) {
|
|
100
124
|
const neu = { weight: term.weight, preference: term };
|
|
101
125
|
|
|
126
|
+
delete neu.preference.weight;
|
|
127
|
+
|
|
102
128
|
preferredDuringSchedulingIgnoredDuringExecution.push(neu);
|
|
103
129
|
} else {
|
|
104
130
|
requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.push(term);
|
|
@@ -144,12 +170,8 @@ export default {
|
|
|
144
170
|
expressionsMatching[expression.matching || 'matchExpressions'].push(expression);
|
|
145
171
|
});
|
|
146
172
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
if (expressionsMatching.matchExpressions.length) {
|
|
151
|
-
this.$set(row, 'matchExpressions', expressionsMatching.matchExpressions);
|
|
152
|
-
}
|
|
173
|
+
this.$set(row, 'matchFields', expressionsMatching.matchFields);
|
|
174
|
+
this.$set(row, 'matchExpressions', expressionsMatching.matchExpressions);
|
|
153
175
|
|
|
154
176
|
this.update();
|
|
155
177
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { mapGetters } from 'vuex';
|
|
2
3
|
import { _VIEW } from '@shell/config/query-params';
|
|
3
4
|
import { get, set, isEmpty, clone } from '@shell/utils/object';
|
|
4
5
|
import { POD, NODE, NAMESPACE } from '@shell/config/types';
|
|
@@ -69,6 +70,11 @@ export default {
|
|
|
69
70
|
type: Boolean
|
|
70
71
|
},
|
|
71
72
|
|
|
73
|
+
overwriteLabels: {
|
|
74
|
+
type: Object,
|
|
75
|
+
default: null
|
|
76
|
+
},
|
|
77
|
+
|
|
72
78
|
loading: {
|
|
73
79
|
default: false,
|
|
74
80
|
type: Boolean
|
|
@@ -131,6 +137,7 @@ export default {
|
|
|
131
137
|
};
|
|
132
138
|
},
|
|
133
139
|
computed: {
|
|
140
|
+
...mapGetters({ t: 'i18n/t' }),
|
|
134
141
|
isView() {
|
|
135
142
|
return this.mode === _VIEW;
|
|
136
143
|
},
|
|
@@ -144,7 +151,7 @@ export default {
|
|
|
144
151
|
},
|
|
145
152
|
|
|
146
153
|
labeledInputNamespaceLabel() {
|
|
147
|
-
return this.removeLabeledInputNamespaceLabel ? '' : this.t('workload.scheduling.affinity.matchExpressions.inNamespaces');
|
|
154
|
+
return this.removeLabeledInputNamespaceLabel ? '' : this.overwriteLabels?.namespaceInputLabel || this.t('workload.scheduling.affinity.matchExpressions.inNamespaces');
|
|
148
155
|
},
|
|
149
156
|
|
|
150
157
|
allNamespacesOptions() {
|
|
@@ -185,6 +192,10 @@ export default {
|
|
|
185
192
|
},
|
|
186
193
|
|
|
187
194
|
namespaceSelectionLabels() {
|
|
195
|
+
if (this.overwriteLabels?.namespaceSelectionLabels) {
|
|
196
|
+
return this.overwriteLabels?.namespaceSelectionLabels;
|
|
197
|
+
}
|
|
198
|
+
|
|
188
199
|
if (this.allNamespacesOptionAvailable) {
|
|
189
200
|
return [
|
|
190
201
|
this.t('workload.scheduling.affinity.thisPodNamespace'),
|
|
@@ -199,6 +210,14 @@ export default {
|
|
|
199
210
|
];
|
|
200
211
|
},
|
|
201
212
|
|
|
213
|
+
addLabel() {
|
|
214
|
+
return this.overwriteLabels?.addLabel || this.t('podAffinity.addLabel');
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
topologyKeyPlaceholder() {
|
|
218
|
+
return this.overwriteLabels?.topologyKeyPlaceholder || this.t('workload.scheduling.affinity.topologyKey.placeholder');
|
|
219
|
+
},
|
|
220
|
+
|
|
202
221
|
hasNamespaces() {
|
|
203
222
|
return this.allNamespacesOptions.length;
|
|
204
223
|
},
|
|
@@ -230,8 +249,9 @@ export default {
|
|
|
230
249
|
this.allSelectorTerms.forEach((term) => {
|
|
231
250
|
if (term._anti) {
|
|
232
251
|
if (term.weight) {
|
|
233
|
-
const neu = { podAffinityTerm: term, weight: term.weight || this.defaultWeight };
|
|
252
|
+
const neu = { podAffinityTerm: { ...term }, weight: term.weight || this.defaultWeight };
|
|
234
253
|
|
|
254
|
+
delete neu.podAffinityTerm.weight;
|
|
235
255
|
podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution.push(neu);
|
|
236
256
|
} else {
|
|
237
257
|
podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.push(term);
|
|
@@ -340,7 +360,7 @@ export default {
|
|
|
340
360
|
class="mt-20"
|
|
341
361
|
:default-add-value="defaultAddValue"
|
|
342
362
|
:mode="mode"
|
|
343
|
-
:add-label="
|
|
363
|
+
:add-label="addLabel"
|
|
344
364
|
@remove="remove"
|
|
345
365
|
>
|
|
346
366
|
<template #default="props">
|
|
@@ -389,7 +409,7 @@ export default {
|
|
|
389
409
|
:multiple="true"
|
|
390
410
|
:taggable="true"
|
|
391
411
|
:options="allNamespacesOptions"
|
|
392
|
-
:label="
|
|
412
|
+
:label="labeledInputNamespaceLabel"
|
|
393
413
|
:data-testid="`pod-affinity-namespace-select-index${props.i}`"
|
|
394
414
|
@input="updateNamespaces(props.row.value, props.row.value.namespaces)"
|
|
395
415
|
/>
|
|
@@ -398,7 +418,7 @@ export default {
|
|
|
398
418
|
v-model="props.row.value._namespaces"
|
|
399
419
|
:mode="mode"
|
|
400
420
|
:label="labeledInputNamespaceLabel"
|
|
401
|
-
:placeholder="t('
|
|
421
|
+
:placeholder="t('harvesterManager.affinity.namespaces.placeholder')"
|
|
402
422
|
:data-testid="`pod-affinity-namespace-input-index${props.i}`"
|
|
403
423
|
@input="updateNamespaces(props.row.value, props.row.value._namespaces)"
|
|
404
424
|
/>
|
|
@@ -424,7 +444,7 @@ export default {
|
|
|
424
444
|
:mode="mode"
|
|
425
445
|
required
|
|
426
446
|
:label="t('workload.scheduling.affinity.topologyKey.label')"
|
|
427
|
-
:placeholder="
|
|
447
|
+
:placeholder="topologyKeyPlaceholder"
|
|
428
448
|
:options="existingNodeLabels"
|
|
429
449
|
:disabled="mode==='view'"
|
|
430
450
|
:loading="loading"
|
|
@@ -436,7 +456,7 @@ export default {
|
|
|
436
456
|
v-model="props.row.value.topologyKey"
|
|
437
457
|
:mode="mode"
|
|
438
458
|
:label="t('workload.scheduling.affinity.topologyKey.label')"
|
|
439
|
-
:placeholder="
|
|
459
|
+
:placeholder="topologyKeyPlaceholder"
|
|
440
460
|
required
|
|
441
461
|
:data-testid="`pod-affinity-topology-input-index${props.i}`"
|
|
442
462
|
@input="update"
|
|
@@ -20,6 +20,10 @@ export default {
|
|
|
20
20
|
mode: {
|
|
21
21
|
type: String,
|
|
22
22
|
default: _VIEW
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
default: false,
|
|
26
|
+
type: Boolean
|
|
23
27
|
}
|
|
24
28
|
},
|
|
25
29
|
|
|
@@ -59,6 +63,7 @@ export default {
|
|
|
59
63
|
:extra-columns="['effect']"
|
|
60
64
|
:preserve-keys="['effect']"
|
|
61
65
|
:add-label="t('labels.addTaint')"
|
|
66
|
+
:disabled="disabled"
|
|
62
67
|
>
|
|
63
68
|
<template #label:effect>
|
|
64
69
|
{{ t('tableHeaders.effect') }}
|
|
@@ -68,6 +73,7 @@ export default {
|
|
|
68
73
|
<Select
|
|
69
74
|
v-model="row.effect"
|
|
70
75
|
:options="effectOptions"
|
|
76
|
+
:disabled="disabled"
|
|
71
77
|
class="compact-select"
|
|
72
78
|
@input="queueUpdate"
|
|
73
79
|
/>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { BadgeState } from '@components/BadgeState';
|
|
3
|
+
import { stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
props: {
|
|
7
|
+
value: {
|
|
8
|
+
type: String,
|
|
9
|
+
default: ''
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
components: { BadgeState },
|
|
14
|
+
|
|
15
|
+
data() {
|
|
16
|
+
const STATES = {
|
|
17
|
+
cached: {
|
|
18
|
+
color: 'info', icon: 'dot-open', label: 'Cached', compoundIcon: 'checkmark'
|
|
19
|
+
},
|
|
20
|
+
pending: {
|
|
21
|
+
color: 'warning', icon: 'tag', label: 'In Progress', compoundIcon: 'info'
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
color: 'error', icon: 'dot-half', label: 'Cache Disabled', compoundIcon: 'info'
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
STATES,
|
|
30
|
+
stateDisplay: '',
|
|
31
|
+
stateBackground: ''
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
watch: {
|
|
36
|
+
value: {
|
|
37
|
+
handler() {
|
|
38
|
+
const out = this.value || 'pending';
|
|
39
|
+
const color = this.colorForState(out);
|
|
40
|
+
|
|
41
|
+
this.stateDisplay = stateDisplay(out);
|
|
42
|
+
this.stateBackground = color.replace('text-', 'bg-');
|
|
43
|
+
},
|
|
44
|
+
immediate: true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
methods: {
|
|
49
|
+
colorForState(state) {
|
|
50
|
+
const key = (state).toLowerCase();
|
|
51
|
+
let color;
|
|
52
|
+
|
|
53
|
+
if ( this.STATES[key] && this.STATES[key].color ) {
|
|
54
|
+
color = this.STATES[key].color;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if ( !color ) {
|
|
58
|
+
color = 'info';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return `text-${ color }`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<div>
|
|
69
|
+
<BadgeState
|
|
70
|
+
:color="stateBackground"
|
|
71
|
+
:label="stateDisplay"
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
</template>
|