@rancher/shell 0.3.25 → 0.3.26
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 +7 -0
- package/components/CruResource.vue +7 -4
- package/components/__tests__/ProjectRow.test.ts +63 -0
- package/components/auth/RoleDetailEdit.vue +4 -0
- package/components/auth/__tests__/RoleDetailEdit.test.ts +41 -0
- package/components/form/ResourceQuota/ProjectRow.vue +6 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +18 -2
- package/models/management.cattle.io.globalrole.js +1 -1
- package/models/management.cattle.io.roletemplate.js +1 -1
- package/package.json +1 -1
- package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +2 -2
|
@@ -653,6 +653,10 @@ asyncButton:
|
|
|
653
653
|
action: Save
|
|
654
654
|
success: Saved
|
|
655
655
|
waiting: Saving…
|
|
656
|
+
editAndContinue:
|
|
657
|
+
action: Save and Continue
|
|
658
|
+
success: Saved
|
|
659
|
+
waiting: Saving…
|
|
656
660
|
enable:
|
|
657
661
|
action: Enable
|
|
658
662
|
success: Enabled
|
|
@@ -1841,6 +1845,9 @@ cluster:
|
|
|
1841
1845
|
pspChange:
|
|
1842
1846
|
title: Pod Security Policy deprecation
|
|
1843
1847
|
body: <p>Kubernetes has removed support for Pod Security Policies (PSPs) starting with version 1.25. If your cluster has PodSecurityPolicy admission controller enabled via "kube-apiserver-arg.enable-admission-plugins" in Cluster YAML, it has to be <i>manually</i> removed before proceeding with the upgrade. Additionally, any PSPs that may be present in the cluster will no longer be available/enforced. Do you want to proceed?</p>
|
|
1848
|
+
editYamlMachinePool:
|
|
1849
|
+
title: Save Machine Configurations
|
|
1850
|
+
body: Machine Configurations define how machines in Pools are deployed.<br><br> They will be saved upfront to ensure valid Cluster YAML can be saved.
|
|
1844
1851
|
snapshots:
|
|
1845
1852
|
suffix: Snapshots per node
|
|
1846
1853
|
systemService:
|
|
@@ -327,10 +327,13 @@ export default {
|
|
|
327
327
|
|
|
328
328
|
async showPreviewYaml() {
|
|
329
329
|
if ( this.applyHooks ) {
|
|
330
|
-
|
|
331
|
-
BEFORE_SAVE_HOOKS,
|
|
332
|
-
|
|
333
|
-
|
|
330
|
+
try {
|
|
331
|
+
await this.applyHooks(BEFORE_SAVE_HOOKS, CONTEXT_HOOK_EDIT_YAML);
|
|
332
|
+
} catch (e) {
|
|
333
|
+
console.warn('Unable to show yaml: ', e); // eslint-disable-line no-console
|
|
334
|
+
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
334
337
|
}
|
|
335
338
|
|
|
336
339
|
const resourceYaml = this.createResourceYaml(this.yamlModifiers);
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import ProjectRow from '@shell/components/form/ResourceQuota/ProjectRow.vue';
|
|
2
|
+
import { RANCHER_TYPES } from '@shell/components/form/ResourceQuota/shared';
|
|
3
|
+
import { shallowMount } from '@vue/test-utils';
|
|
4
|
+
import Vue from 'vue';
|
|
5
|
+
|
|
6
|
+
const CONFIGMAP_STRING = RANCHER_TYPES[0].value;
|
|
7
|
+
|
|
8
|
+
describe('component: ProjectRow.vue', () => {
|
|
9
|
+
const wrapper = shallowMount(ProjectRow,
|
|
10
|
+
{
|
|
11
|
+
propsData: {
|
|
12
|
+
mode: 'edit',
|
|
13
|
+
types: RANCHER_TYPES,
|
|
14
|
+
type: CONFIGMAP_STRING,
|
|
15
|
+
value: {
|
|
16
|
+
spec: {
|
|
17
|
+
namespaceDefaultResourceQuota: { limit: {} },
|
|
18
|
+
resourceQuota: { limit: {} }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should render the correct input fields and set the correct computed values, based on the provided data', () => {
|
|
25
|
+
const typeInput = wrapper.find(`[data-testid="projectrow-type-input"]`);
|
|
26
|
+
const projectQuotaInput = wrapper.find(`[data-testid="projectrow-project-quota-input"]`);
|
|
27
|
+
const namespaceQuotaInput = wrapper.find(`[data-testid="projectrow-namespace-quota-input"]`);
|
|
28
|
+
|
|
29
|
+
expect(typeInput.exists()).toBe(true);
|
|
30
|
+
expect(projectQuotaInput.exists()).toBe(true);
|
|
31
|
+
expect(namespaceQuotaInput.exists()).toBe(true);
|
|
32
|
+
expect(wrapper.vm.resourceQuotaLimit).toStrictEqual({});
|
|
33
|
+
expect(wrapper.vm.namespaceDefaultResourceQuotaLimit).toStrictEqual({});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('triggering "updateQuotaLimit" should trigger Vue.set with the correct data', () => {
|
|
37
|
+
const vueSet = jest.spyOn(Vue, 'set');
|
|
38
|
+
|
|
39
|
+
wrapper.vm.updateQuotaLimit('resourceQuota', CONFIGMAP_STRING, 10);
|
|
40
|
+
|
|
41
|
+
expect(vueSet).toHaveBeenCalledTimes(1);
|
|
42
|
+
expect(wrapper.vm.value).toStrictEqual({
|
|
43
|
+
spec: {
|
|
44
|
+
namespaceDefaultResourceQuota: { limit: {} },
|
|
45
|
+
resourceQuota: { limit: { [`${ CONFIGMAP_STRING }`]: 10 } }
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('triggering "updateType" with the same type that existed should clear limits and trigger emit', () => {
|
|
51
|
+
wrapper.vm.updateType(CONFIGMAP_STRING);
|
|
52
|
+
|
|
53
|
+
expect(wrapper.vm.value).toStrictEqual({
|
|
54
|
+
spec: {
|
|
55
|
+
namespaceDefaultResourceQuota: { limit: {} },
|
|
56
|
+
resourceQuota: { limit: {} }
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(wrapper.emitted('type-change')).toBeTruthy();
|
|
61
|
+
expect(wrapper.emitted('type-change')[0]).toStrictEqual([CONFIGMAP_STRING]);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -152,6 +152,10 @@ export default {
|
|
|
152
152
|
});
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
if (this.value?.metadata?.name && !this.value.displayName) {
|
|
156
|
+
this.$set(this.value, 'displayName', this.value.metadata.name);
|
|
157
|
+
}
|
|
158
|
+
|
|
155
159
|
this.$nextTick(() => {
|
|
156
160
|
this.$emit('set-subtype', this.label);
|
|
157
161
|
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import RoleDetailEdit from '@shell/components/auth/RoleDetailEdit.vue';
|
|
3
|
+
import { SUBTYPE_MAPPING } from '@shell/models/management.cattle.io.roletemplate';
|
|
4
|
+
|
|
5
|
+
const role = {
|
|
6
|
+
apiVersion: 'management.cattle.io/v3',
|
|
7
|
+
kind: 'GlobalRole',
|
|
8
|
+
metadata: { name: 'global-role-with-inherited' },
|
|
9
|
+
inheritedClusterRoles: ['cluster-admin'],
|
|
10
|
+
rules:
|
|
11
|
+
[{
|
|
12
|
+
verbs: ['get', 'list'],
|
|
13
|
+
resources: ['pods'],
|
|
14
|
+
apiGroups: ['']
|
|
15
|
+
}],
|
|
16
|
+
subtype: SUBTYPE_MAPPING.GLOBAL.id
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('component: RoleDetailEdit', () => {
|
|
20
|
+
it('does not have validation errors when the role has no displayName', () => {
|
|
21
|
+
const wrapper = mount(RoleDetailEdit, {
|
|
22
|
+
propsData: { value: role },
|
|
23
|
+
mocks: {
|
|
24
|
+
$fetchState: { pending: false },
|
|
25
|
+
$route: { name: 'anything' },
|
|
26
|
+
$store: {
|
|
27
|
+
getters: {
|
|
28
|
+
currentStore: () => 'store', 'i18n/t': jest.fn(), 'store/schemaFor': jest.fn()
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
stubs: {
|
|
33
|
+
CruResource: { template: '<div><slot></slot></div>' },
|
|
34
|
+
// NameNsDescription: true,
|
|
35
|
+
Tab: { template: '<div><slot></slot></div>' },
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect((wrapper.vm as any).fvFormIsValid).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import Select from '@shell/components/form/Select';
|
|
3
3
|
import UnitInput from '@shell/components/form/UnitInput';
|
|
4
4
|
import { ROW_COMPUTED } from './shared';
|
|
5
|
+
import Vue from 'vue';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
7
8
|
components: { Select, UnitInput },
|
|
@@ -57,10 +58,10 @@ export default {
|
|
|
57
58
|
|
|
58
59
|
updateQuotaLimit(prop, type, val) {
|
|
59
60
|
if (!this.value.spec[prop]) {
|
|
60
|
-
this.value.spec
|
|
61
|
+
Vue.set(this.value.spec, prop, { limit: { } });
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
this.value.spec[prop].limit
|
|
64
|
+
Vue.set(this.value.spec[prop].limit, type, val);
|
|
64
65
|
}
|
|
65
66
|
},
|
|
66
67
|
};
|
|
@@ -75,6 +76,7 @@ export default {
|
|
|
75
76
|
:mode="mode"
|
|
76
77
|
:value="type"
|
|
77
78
|
:options="types"
|
|
79
|
+
data-testid="projectrow-type-input"
|
|
78
80
|
@input="updateType($event)"
|
|
79
81
|
/>
|
|
80
82
|
<UnitInput
|
|
@@ -86,6 +88,7 @@ export default {
|
|
|
86
88
|
:input-exponent="typeOption.inputExponent"
|
|
87
89
|
:base-unit="typeOption.baseUnit"
|
|
88
90
|
:output-modifier="true"
|
|
91
|
+
data-testid="projectrow-project-quota-input"
|
|
89
92
|
@input="updateQuotaLimit('resourceQuota', type, $event)"
|
|
90
93
|
/>
|
|
91
94
|
<UnitInput
|
|
@@ -96,6 +99,7 @@ export default {
|
|
|
96
99
|
:input-exponent="typeOption.inputExponent"
|
|
97
100
|
:base-unit="typeOption.baseUnit"
|
|
98
101
|
:output-modifier="true"
|
|
102
|
+
data-testid="projectrow-namespace-quota-input"
|
|
99
103
|
@input="updateQuotaLimit('namespaceDefaultResourceQuota', type, $event)"
|
|
100
104
|
/>
|
|
101
105
|
</div>
|
|
@@ -864,7 +864,7 @@ export default {
|
|
|
864
864
|
},
|
|
865
865
|
|
|
866
866
|
created() {
|
|
867
|
-
this.registerBeforeHook(this.saveMachinePools, 'save-machine-pools');
|
|
867
|
+
this.registerBeforeHook(this.saveMachinePools, 'save-machine-pools', 1);
|
|
868
868
|
this.registerBeforeHook(this.setRegistryConfig, 'set-registry-config');
|
|
869
869
|
this.registerAfterHook(this.cleanupMachinePools, 'cleanup-machine-pools');
|
|
870
870
|
this.registerAfterHook(this.saveRoleBindings, 'save-role-bindings');
|
|
@@ -1235,7 +1235,23 @@ export default {
|
|
|
1235
1235
|
|
|
1236
1236
|
async saveMachinePools(hookContext) {
|
|
1237
1237
|
if (hookContext === CONTEXT_HOOK_EDIT_YAML) {
|
|
1238
|
-
|
|
1238
|
+
await new Promise((resolve, reject) => {
|
|
1239
|
+
this.$store.dispatch('cluster/promptModal', {
|
|
1240
|
+
component: 'GenericPrompt',
|
|
1241
|
+
componentProps: {
|
|
1242
|
+
title: this.t('cluster.rke2.modal.editYamlMachinePool.title'),
|
|
1243
|
+
body: this.t('cluster.rke2.modal.editYamlMachinePool.body'),
|
|
1244
|
+
applyMode: 'editAndContinue',
|
|
1245
|
+
confirm: (confirmed) => {
|
|
1246
|
+
if (confirmed) {
|
|
1247
|
+
resolve();
|
|
1248
|
+
} else {
|
|
1249
|
+
reject(new Error('User Cancelled'));
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
},
|
|
1253
|
+
});
|
|
1254
|
+
});
|
|
1239
1255
|
}
|
|
1240
1256
|
|
|
1241
1257
|
const finalPools = [];
|
|
@@ -144,7 +144,7 @@ export default class GlobalRole extends SteveDescriptionModel {
|
|
|
144
144
|
const norman = await this.norman;
|
|
145
145
|
|
|
146
146
|
for (const rule of norman.rules) {
|
|
147
|
-
if (rule.nonResourceURLs.length) {
|
|
147
|
+
if (rule.nonResourceURLs && rule.nonResourceURLs.length) {
|
|
148
148
|
delete rule.resources;
|
|
149
149
|
delete rule.apiGroups;
|
|
150
150
|
} else {
|
|
@@ -192,7 +192,7 @@ export default class RoleTemplate extends SteveDescriptionModel {
|
|
|
192
192
|
const norman = await this.norman;
|
|
193
193
|
|
|
194
194
|
for (const rule of norman.rules) {
|
|
195
|
-
if (rule.nonResourceURLs.length) {
|
|
195
|
+
if (rule.nonResourceURLs && rule.nonResourceURLs.length) {
|
|
196
196
|
delete rule.resources;
|
|
197
197
|
delete rule.apiGroups;
|
|
198
198
|
} else {
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
annotations:
|
|
2
2
|
catalog.cattle.io/certified: rancher # Any application we are adding as a helm chart
|
|
3
|
-
catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.
|
|
3
|
+
catalog.cattle.io/kube-version: '>= 1.16.0-0 < 1.29.0-0'
|
|
4
4
|
catalog.cattle.io/namespace: cattle-ui-plugin-system # Must prefix with cattle- and suffix with -system=
|
|
5
5
|
catalog.cattle.io/os: linux
|
|
6
6
|
catalog.cattle.io/permits-os: linux, windows
|
|
7
|
-
catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.
|
|
7
|
+
catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.9.0-0'
|
|
8
8
|
catalog.cattle.io/scope: management
|
|
9
9
|
catalog.cattle.io/ui-component: plugins
|
|
10
10
|
apiVersion: v2
|