@rancher/shell 0.3.16 → 0.3.17
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/images/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +69 -14
- package/assets/translations/zh-hans.yaml +87 -7
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/components/CommunityLinks.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/ResourceDetail/index.vue +4 -12
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/YamlEditor.vue +1 -0
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +2 -2
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/nav/Header.vue +2 -2
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +5 -1
- package/config/router.js +0 -4
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +20 -12
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +17 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/node.vue +6 -6
- package/detail/pod.vue +2 -6
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +9 -9
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +52 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +330 -150
- package/edit/ui.cattle.io.navlink.vue +2 -1
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +93 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/package.json +2 -2
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +1 -1
- package/pages/auth/logout.vue +11 -3
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- package/pages/c/_cluster/explorer/index.vue +1 -10
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +155 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +5 -5
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/resource-class.js +35 -2
- package/plugins/plugin.js +9 -1
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +44 -26
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +1 -0
- package/server/server-middleware.js +4 -12
- package/store/index.js +13 -0
- package/store/prefs.js +0 -3
- package/store/type-map.js +17 -29
- package/types/shell/index.d.ts +236 -83
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/settings.ts +2 -2
- package/vue.config.js +3 -2
- package/components/.DS_Store +0 -0
- package/components/__tests__/.DS_Store +0 -0
- package/creators/pkg/package-lock.json +0 -37
- package/pages/safeMode.vue +0 -17
- package/rancher-components/components/BadgeState/BadgeState.spec.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -63
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -420
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -23
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -355
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -287
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -254
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -170
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -149
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -151
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -484
- package/rancher-components/components/StringList/StringList.vue +0 -611
- package/rancher-components/components/StringList/index.ts +0 -1
- package/yarn-error.log +0 -196
- /package/rancher-components/{components/Card → Card}/Card.test.ts +0 -0
- /package/rancher-components/{components/Form → Form}/Radio/RadioButton.test.ts +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { mount, createLocalVue } from '@vue/test-utils';
|
|
2
|
+
import GitRepo from '@shell/edit/fleet.cattle.io.gitrepo.vue';
|
|
3
|
+
import Vuex from 'vuex';
|
|
4
|
+
|
|
5
|
+
const localVue = createLocalVue();
|
|
6
|
+
|
|
7
|
+
localVue.use(Vuex);
|
|
8
|
+
|
|
9
|
+
describe('view: fleet.cattle.io.gitrepo should', () => {
|
|
10
|
+
const mockStore = {
|
|
11
|
+
getters: {
|
|
12
|
+
'i18n/t': (text: string) => text,
|
|
13
|
+
t: (text: string) => text,
|
|
14
|
+
currentStore: () => 'current_store',
|
|
15
|
+
'current_store/schemaFor': jest.fn(),
|
|
16
|
+
'current_store/all': jest.fn(),
|
|
17
|
+
workspace: jest.fn(),
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const mocks = {
|
|
21
|
+
$store: mockStore,
|
|
22
|
+
$fetchState: { pending: false },
|
|
23
|
+
$route: {
|
|
24
|
+
query: { AS: '' },
|
|
25
|
+
name: {
|
|
26
|
+
endsWith: () => {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const values = {
|
|
33
|
+
metadata: { namespace: 'test' }, spec: { template: {}, correctDrift: { enabled: false } }, targetInfo: { mode: 'all' },
|
|
34
|
+
};
|
|
35
|
+
const wrapper = mount(GitRepo, {
|
|
36
|
+
localVue,
|
|
37
|
+
propsData: { value: values },
|
|
38
|
+
mocks
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should have self-healing checkbox and banner', () => {
|
|
42
|
+
const correctDriftCheckbox = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"]');
|
|
43
|
+
const correctDriftBanner = wrapper.find('[data-testid="GitRepo-correctDrift-banner"]');
|
|
44
|
+
|
|
45
|
+
expect(correctDriftCheckbox.exists()).toBeTruthy();
|
|
46
|
+
expect(correctDriftBanner.exists()).toBeTruthy();
|
|
47
|
+
expect(correctDriftCheckbox.props().value).toBeFalsy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should enable drift if self-healing is checked', async() => {
|
|
51
|
+
const correctDriftCheckbox = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"]');
|
|
52
|
+
const correctDriftContainer = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"] .checkbox-container');
|
|
53
|
+
|
|
54
|
+
expect(correctDriftContainer.exists()).toBeTruthy();
|
|
55
|
+
|
|
56
|
+
await correctDriftContainer.trigger('click');
|
|
57
|
+
|
|
58
|
+
expect(correctDriftCheckbox.emitted('input')).toHaveLength(1);
|
|
59
|
+
expect(correctDriftCheckbox.emitted('input')![0][0]).toBe(true);
|
|
60
|
+
expect(correctDriftCheckbox.props().value).toBeTruthy();
|
|
61
|
+
});
|
|
62
|
+
});
|
package/edit/auth/github.vue
CHANGED
|
@@ -163,6 +163,7 @@ export default {
|
|
|
163
163
|
<RadioGroup
|
|
164
164
|
v-model="targetType"
|
|
165
165
|
name="targetType"
|
|
166
|
+
data-testid="authConfig-gitHub"
|
|
166
167
|
:options="['public','private']"
|
|
167
168
|
:mode="mode"
|
|
168
169
|
:labels="[ t(`authConfig.${NAME}.target.public`), t(`authConfig.${NAME}.target.private`)]"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
import { _EDIT } from '@shell/config/query-params';
|
|
4
|
+
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
|
|
5
|
+
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
6
|
+
import ArrayListGrouped from '@shell/components/form/ArrayListGrouped.vue';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
components: {
|
|
10
|
+
ArrayListGrouped,
|
|
11
|
+
LabeledInput,
|
|
12
|
+
LabeledSelect
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
value: {
|
|
16
|
+
type: Object,
|
|
17
|
+
default: () => {
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
mode: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: _EDIT
|
|
23
|
+
},
|
|
24
|
+
type: {
|
|
25
|
+
type: String,
|
|
26
|
+
default: 'scaleUp'
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
data() {
|
|
30
|
+
if (!this.value.spec.behavior[this.type].policies) {
|
|
31
|
+
this.$set(this.value.spec.behavior[this.type], 'policies', []);
|
|
32
|
+
}
|
|
33
|
+
if (!this.value.spec.behavior[this.type].selectPolicy) {
|
|
34
|
+
this.$set(this.value.spec.behavior[this.type], 'selectPolicy', 'Max');
|
|
35
|
+
}
|
|
36
|
+
if (this.value.spec.behavior[this.type].stabilizationWindowSeconds === null || typeof this.value.spec.behavior[this.type].stabilizationWindowSeconds === 'undefined') {
|
|
37
|
+
if (this.type === 'scaleUp') {
|
|
38
|
+
this.$set(this.value.spec.behavior[this.type], 'stabilizationWindowSeconds', 0);
|
|
39
|
+
}
|
|
40
|
+
if (this.type === 'scaleDown') {
|
|
41
|
+
this.$set(this.value.spec.behavior[this.type], 'stabilizationWindowSeconds', 300);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { selectPolicyOptions: ['Max', 'Min', 'Disabled'], policyTypeOptions: ['Pods', 'Percent'] };
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<div>
|
|
52
|
+
<div class="row mb-20">
|
|
53
|
+
<div class="col span-12">
|
|
54
|
+
<ArrayListGrouped
|
|
55
|
+
v-model="value.spec.behavior[type].policies"
|
|
56
|
+
:add-label="t('hpa.scalingRule.addPolicy')"
|
|
57
|
+
:default-add-value="{}"
|
|
58
|
+
:mode="mode"
|
|
59
|
+
>
|
|
60
|
+
<template #default="props">
|
|
61
|
+
<div class="row">
|
|
62
|
+
<div class="col span-4">
|
|
63
|
+
<LabeledSelect
|
|
64
|
+
v-model="props.row.value.type"
|
|
65
|
+
:mode="mode"
|
|
66
|
+
:options="policyTypeOptions"
|
|
67
|
+
:multiple="false"
|
|
68
|
+
:taggable="true"
|
|
69
|
+
:searchable="true"
|
|
70
|
+
:required="true"
|
|
71
|
+
:tooltip="t('hpa.scalingRule.policy.typeTooltip')"
|
|
72
|
+
:label="t('hpa.scalingRule.policy.type')"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="col span-4">
|
|
76
|
+
<LabeledInput
|
|
77
|
+
v-model.number="props.row.value.value"
|
|
78
|
+
:mode="mode"
|
|
79
|
+
type="number"
|
|
80
|
+
min="1"
|
|
81
|
+
:required="true"
|
|
82
|
+
:tooltip="t('hpa.scalingRule.policy.valueTooltip')"
|
|
83
|
+
:label="t('hpa.scalingRule.policy.value')"
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="col span-4">
|
|
87
|
+
<LabeledInput
|
|
88
|
+
v-model.number="props.row.value.periodSeconds"
|
|
89
|
+
:mode="mode"
|
|
90
|
+
type="number"
|
|
91
|
+
min="1"
|
|
92
|
+
max="1800"
|
|
93
|
+
:required="true"
|
|
94
|
+
:tooltip="t('hpa.scalingRule.policy.periodSecondsTooltip')"
|
|
95
|
+
:label="t('hpa.scalingRule.policy.periodSeconds')"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</template>
|
|
100
|
+
</ArrayListGrouped>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="row">
|
|
104
|
+
<div class="col span-6">
|
|
105
|
+
<LabeledSelect
|
|
106
|
+
v-model="value.spec.behavior[type].selectPolicy"
|
|
107
|
+
:mode="mode"
|
|
108
|
+
:options="selectPolicyOptions"
|
|
109
|
+
:multiple="false"
|
|
110
|
+
:taggable="true"
|
|
111
|
+
:searchable="true"
|
|
112
|
+
:label="t('hpa.scalingRule.selectPolicy')"
|
|
113
|
+
:tooltip="t('hpa.scalingRule.selectPolicyTooltip')"
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="col span-6">
|
|
117
|
+
<LabeledInput
|
|
118
|
+
v-model.number="value.spec.behavior[type].stabilizationWindowSeconds"
|
|
119
|
+
:mode="mode"
|
|
120
|
+
type="number"
|
|
121
|
+
min="0"
|
|
122
|
+
max="3600"
|
|
123
|
+
:label="t('hpa.scalingRule.stabilizationWindowSeconds')"
|
|
124
|
+
:tooltip="t('hpa.scalingRule.stabilizationWindowSecondsTooltip')"
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="row mb-40" />
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
@@ -12,12 +12,14 @@ import Tabbed from '@shell/components/Tabbed';
|
|
|
12
12
|
import MetricsRow from '@shell/edit/autoscaling.horizontalpodautoscaler/metrics-row';
|
|
13
13
|
import ArrayListGrouped from '@shell/components/form/ArrayListGrouped';
|
|
14
14
|
import { DEFAULT_RESOURCE_METRIC } from '@shell/edit/autoscaling.horizontalpodautoscaler/resource-metric';
|
|
15
|
+
import { Checkbox } from '@components/Form/Checkbox';
|
|
15
16
|
|
|
16
17
|
import { API_SERVICE, SCALABLE_WORKLOAD_TYPES } from '@shell/config/types';
|
|
17
18
|
import isEmpty from 'lodash/isEmpty';
|
|
18
19
|
import find from 'lodash/find';
|
|
19
20
|
import endsWith from 'lodash/endsWith';
|
|
20
21
|
import { findBy } from '@shell/utils/array';
|
|
22
|
+
import HpaScalingRule from '@shell/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue';
|
|
21
23
|
|
|
22
24
|
const RESOURCE_METRICS_API_GROUP = 'metrics.k8s.io';
|
|
23
25
|
|
|
@@ -25,7 +27,9 @@ export default {
|
|
|
25
27
|
name: 'CruHPA',
|
|
26
28
|
|
|
27
29
|
components: {
|
|
30
|
+
HpaScalingRule,
|
|
28
31
|
ArrayListGrouped,
|
|
32
|
+
Checkbox,
|
|
29
33
|
CruResource,
|
|
30
34
|
LabeledInput,
|
|
31
35
|
LabeledSelect,
|
|
@@ -107,6 +111,40 @@ export default {
|
|
|
107
111
|
|
|
108
112
|
return match ?? null;
|
|
109
113
|
},
|
|
114
|
+
hasScaleDownRules: {
|
|
115
|
+
get() {
|
|
116
|
+
return !!this.value.spec.behavior?.scaleDown;
|
|
117
|
+
},
|
|
118
|
+
set(hasScaleDownRules) {
|
|
119
|
+
if (hasScaleDownRules) {
|
|
120
|
+
if (!this.value.spec.behavior) {
|
|
121
|
+
this.$set(this.value.spec, 'behavior', {});
|
|
122
|
+
}
|
|
123
|
+
if (!this.value.spec.behavior?.scaleDown) {
|
|
124
|
+
this.$set(this.value.spec.behavior, 'scaleDown', {});
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
this.$delete(this.value.spec.behavior, 'scaleDown');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
hasScaleUpRules: {
|
|
132
|
+
get() {
|
|
133
|
+
return !!this.value.spec.behavior?.scaleUp;
|
|
134
|
+
},
|
|
135
|
+
set(hasScaleUpRules) {
|
|
136
|
+
if (hasScaleUpRules) {
|
|
137
|
+
if (!this.value.spec.behavior) {
|
|
138
|
+
this.$set(this.value.spec, 'behavior', {});
|
|
139
|
+
}
|
|
140
|
+
if (!this.value.spec.behavior?.scaleUp) {
|
|
141
|
+
this.$set(this.value.spec.behavior, 'scaleUp', {});
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
this.$delete(this.value.spec.behavior, 'scaleUp');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
110
148
|
},
|
|
111
149
|
|
|
112
150
|
created() {
|
|
@@ -242,6 +280,47 @@ export default {
|
|
|
242
280
|
</template>
|
|
243
281
|
</ArrayListGrouped>
|
|
244
282
|
</Tab>
|
|
283
|
+
<Tab
|
|
284
|
+
name="behavior"
|
|
285
|
+
:label="t('hpa.tabs.behavior')"
|
|
286
|
+
>
|
|
287
|
+
<div class="col span-12 mb-10">
|
|
288
|
+
<h3>
|
|
289
|
+
{{ t('hpa.scaleDownRules.label') }}
|
|
290
|
+
</h3>
|
|
291
|
+
<div class="row mb-10">
|
|
292
|
+
<Checkbox
|
|
293
|
+
v-model="hasScaleDownRules"
|
|
294
|
+
:mode="mode"
|
|
295
|
+
:label="t('hpa.scaleDownRules.enable')"
|
|
296
|
+
/>
|
|
297
|
+
</div>
|
|
298
|
+
<HpaScalingRule
|
|
299
|
+
v-if="hasScaleDownRules"
|
|
300
|
+
v-model="value"
|
|
301
|
+
type="scaleDown"
|
|
302
|
+
:mode="mode"
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="col span-12">
|
|
306
|
+
<h3>
|
|
307
|
+
{{ t('hpa.scaleUpRules.label') }}
|
|
308
|
+
</h3>
|
|
309
|
+
<div class="row mb-10">
|
|
310
|
+
<Checkbox
|
|
311
|
+
v-model="hasScaleUpRules"
|
|
312
|
+
:mode="mode"
|
|
313
|
+
:label="t('hpa.scaleUpRules.enable')"
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
<HpaScalingRule
|
|
317
|
+
v-if="hasScaleUpRules"
|
|
318
|
+
v-model="value"
|
|
319
|
+
type="scaleUp"
|
|
320
|
+
:mode="mode"
|
|
321
|
+
/>
|
|
322
|
+
</div>
|
|
323
|
+
</Tab>
|
|
245
324
|
<Tab
|
|
246
325
|
name="labels-and-annotations"
|
|
247
326
|
:label="t('hpa.tabs.labels')"
|
|
@@ -604,6 +604,23 @@ export default {
|
|
|
604
604
|
</template>
|
|
605
605
|
<div class="spacer" />
|
|
606
606
|
<h2 v-t="'fleet.gitRepo.resources.label'" />
|
|
607
|
+
<div>
|
|
608
|
+
<Checkbox
|
|
609
|
+
v-model="value.spec.correctDrift.enabled"
|
|
610
|
+
data-testid="GitRepo-correctDrift-checkbox"
|
|
611
|
+
class="check"
|
|
612
|
+
type="checkbox"
|
|
613
|
+
label-key="fleet.gitRepo.resources.correctDrift"
|
|
614
|
+
:mode="mode"
|
|
615
|
+
/>
|
|
616
|
+
<Banner
|
|
617
|
+
data-testid="GitRepo-correctDrift-banner"
|
|
618
|
+
color="info"
|
|
619
|
+
>
|
|
620
|
+
{{ t('fleet.gitRepo.resources.correctDriftBanner') }}
|
|
621
|
+
</Banner>
|
|
622
|
+
</div>
|
|
623
|
+
|
|
607
624
|
<Checkbox
|
|
608
625
|
v-model="value.spec.keepResources"
|
|
609
626
|
class="check"
|
|
@@ -614,7 +631,7 @@ export default {
|
|
|
614
631
|
<Banner
|
|
615
632
|
color="info"
|
|
616
633
|
>
|
|
617
|
-
{{ t('fleet.gitRepo.resources.
|
|
634
|
+
{{ t('fleet.gitRepo.resources.keepResourcesBanner') }}
|
|
618
635
|
</Banner>
|
|
619
636
|
<div class="spacer" />
|
|
620
637
|
<h2 v-t="'fleet.gitRepo.paths.label'" />
|
package/edit/namespace.vue
CHANGED
|
@@ -17,6 +17,7 @@ import Loading from '@shell/components/Loading';
|
|
|
17
17
|
import { HARVESTER_TYPES, RANCHER_TYPES } from '@shell/components/form/ResourceQuota/shared';
|
|
18
18
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
19
19
|
import Labels from '@shell/components/form/Labels';
|
|
20
|
+
import { randomStr } from '@shell/utils/string';
|
|
20
21
|
|
|
21
22
|
export default {
|
|
22
23
|
components: {
|
|
@@ -58,6 +59,7 @@ export default {
|
|
|
58
59
|
projects: null,
|
|
59
60
|
viewMode: _VIEW,
|
|
60
61
|
containerResourceLimits: this.value.annotations?.[CONTAINER_DEFAULT_RESOURCE_LIMIT] || this.getDefaultContainerResourceLimits(projectName),
|
|
62
|
+
rerenderNums: randomStr(4),
|
|
61
63
|
projectName,
|
|
62
64
|
HARVESTER_TYPES,
|
|
63
65
|
RANCHER_TYPES,
|
|
@@ -152,6 +154,11 @@ export default {
|
|
|
152
154
|
const project = projects.find((p) => p.id.includes(projectName));
|
|
153
155
|
|
|
154
156
|
return project?.spec?.containerDefaultResourceLimit || {};
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
PSAChanged($event) {
|
|
160
|
+
this.value.setLabels($event);
|
|
161
|
+
this.rerenderNums = randomStr(4);
|
|
155
162
|
}
|
|
156
163
|
},
|
|
157
164
|
};
|
|
@@ -242,6 +249,7 @@ export default {
|
|
|
242
249
|
:weight="-1"
|
|
243
250
|
>
|
|
244
251
|
<Labels
|
|
252
|
+
:key="rerenderNums"
|
|
245
253
|
default-container-class="labels-and-annotations-container"
|
|
246
254
|
:value="value"
|
|
247
255
|
:mode="mode"
|
|
@@ -258,7 +266,7 @@ export default {
|
|
|
258
266
|
:labels="value.labels"
|
|
259
267
|
:mode="mode"
|
|
260
268
|
labels-prefix="pod-security.kubernetes.io/"
|
|
261
|
-
@updateLabels="
|
|
269
|
+
@updateLabels="PSAChanged"
|
|
262
270
|
/>
|
|
263
271
|
</Tab>
|
|
264
272
|
</Tabbed>
|
|
@@ -9,35 +9,6 @@ import { cleanUp } from '@shell/utils/object';
|
|
|
9
9
|
import { fetchSetting } from '@shell/utils/settings';
|
|
10
10
|
import { RadioGroup } from '@components/Form/Radio';
|
|
11
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
12
|
// Affinity radio button choices
|
|
42
13
|
const DEFAULT = 'default';
|
|
43
14
|
const CUSTOM = 'custom';
|
|
@@ -215,7 +186,7 @@ export default {
|
|
|
215
186
|
</script>
|
|
216
187
|
|
|
217
188
|
<template>
|
|
218
|
-
<div
|
|
189
|
+
<div>
|
|
219
190
|
<Banner
|
|
220
191
|
:closable="false"
|
|
221
192
|
color="info"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
1
|
+
import { mount, shallowMount } from '@vue/test-utils';
|
|
2
2
|
import rke2 from '@shell/edit/provisioning.cattle.io.cluster/rke2.vue';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -14,6 +14,7 @@ const defaultStubs = {
|
|
|
14
14
|
LabeledSelect: true,
|
|
15
15
|
ACE: true,
|
|
16
16
|
AgentEnv: true,
|
|
17
|
+
AgentConfiguration: true,
|
|
17
18
|
ArrayList: true,
|
|
18
19
|
ArrayListGrouped: true,
|
|
19
20
|
BadgeState: true,
|
|
@@ -267,4 +268,81 @@ describe('component: rke2', () => {
|
|
|
267
268
|
|
|
268
269
|
expect((wrapper.vm as any).validationPassed).toBe(true);
|
|
269
270
|
});
|
|
271
|
+
|
|
272
|
+
// TODO: Complete test after implementing fetch https://github.com/rancher/dashboard/issues/9322
|
|
273
|
+
// eslint-disable-next-line jest/no-disabled-tests
|
|
274
|
+
describe.skip('should initialize agent configuration values', () => {
|
|
275
|
+
it('adding default values if none', async() => {
|
|
276
|
+
const wrapper = shallowMount(rke2, {
|
|
277
|
+
propsData: {
|
|
278
|
+
mode: 'create',
|
|
279
|
+
value: { spec: { ...defaultSpec } },
|
|
280
|
+
provider: 'custom'
|
|
281
|
+
},
|
|
282
|
+
computed: defaultComputed,
|
|
283
|
+
mocks: {
|
|
284
|
+
...defaultMocks,
|
|
285
|
+
$store: {
|
|
286
|
+
getters: defaultGetters,
|
|
287
|
+
dispatch: {
|
|
288
|
+
'management/request': jest.fn(),
|
|
289
|
+
'management/find': jest.fn(),
|
|
290
|
+
'management/findAll': () => ([]),
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
stubs: defaultStubs
|
|
295
|
+
});
|
|
296
|
+
const defaultAgentConfig = {
|
|
297
|
+
clusterAgentDeploymentCustomization: {
|
|
298
|
+
overrideAffinity: {},
|
|
299
|
+
appendTolerations: [],
|
|
300
|
+
overrideResourceRequirements: {}
|
|
301
|
+
},
|
|
302
|
+
fleetAgentDeploymentCustomization: {
|
|
303
|
+
overrideAffinity: {},
|
|
304
|
+
appendTolerations: [],
|
|
305
|
+
overrideResourceRequirements: {}
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
// Setting RKE to avoid calls
|
|
310
|
+
wrapper.setData({ rke2Versions: [] });
|
|
311
|
+
|
|
312
|
+
// await rke2.fetch.call(wrapper.vm);
|
|
313
|
+
|
|
314
|
+
expect(wrapper.props().value.spec).toContain(defaultAgentConfig);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should display agent configuration tab', async() => {
|
|
318
|
+
const wrapper = shallowMount(rke2, {
|
|
319
|
+
propsData: {
|
|
320
|
+
mode: 'create',
|
|
321
|
+
value: { spec: { ...defaultSpec } },
|
|
322
|
+
provider: 'custom'
|
|
323
|
+
},
|
|
324
|
+
computed: defaultComputed,
|
|
325
|
+
mocks: {
|
|
326
|
+
...defaultMocks,
|
|
327
|
+
$store: {
|
|
328
|
+
getters: defaultGetters,
|
|
329
|
+
dispatch: {
|
|
330
|
+
'management/request': jest.fn(),
|
|
331
|
+
'management/find': jest.fn(),
|
|
332
|
+
'management/findAll': () => ([]),
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
stubs: defaultStubs
|
|
337
|
+
});
|
|
338
|
+
const agent = wrapper.find('[data-testid="rke2-cluster-agent-config"]');
|
|
339
|
+
|
|
340
|
+
// Setting RKE to avoid calls
|
|
341
|
+
wrapper.setData({ rke2Versions: [] });
|
|
342
|
+
|
|
343
|
+
await rke2.fetch.call(wrapper.vm);
|
|
344
|
+
|
|
345
|
+
expect(agent.element).toBeDefined();
|
|
346
|
+
});
|
|
347
|
+
});
|
|
270
348
|
});
|
|
@@ -138,6 +138,27 @@ export default {
|
|
|
138
138
|
this.iconClasses[name] = `machine-driver ${ name }`;
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
|
+
|
|
142
|
+
// Custom Providers from extensions - initialize each with the store and the i18n service
|
|
143
|
+
// Wrap in try ... catch, to prevent errors in an extension breaking the page
|
|
144
|
+
try {
|
|
145
|
+
const extensionClasses = this.$plugin.listDynamic('provisioner').map((name) => this.$plugin.getDynamic('provisioner', name));
|
|
146
|
+
|
|
147
|
+
// We can't pass in this.$store as this leads to a circular-reference that causes Vue to freeze,
|
|
148
|
+
// so pass in specific services that the provisioner extension may need
|
|
149
|
+
this.extensions = extensionClasses.map((c) => new c({
|
|
150
|
+
dispatch: this.$store.dispatch,
|
|
151
|
+
getters: this.$store.getters,
|
|
152
|
+
axios: this.$store.$axios,
|
|
153
|
+
$plugin: this.$store.app.$plugin,
|
|
154
|
+
t: (...args) => this.t.apply(this, args),
|
|
155
|
+
isCreate: this.isCreate,
|
|
156
|
+
isEdit: this.isEdit,
|
|
157
|
+
isView: this.isView,
|
|
158
|
+
}));
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.error('Error loading provisioner(s) from extensions', e); // eslint-disable-line no-console
|
|
161
|
+
}
|
|
141
162
|
},
|
|
142
163
|
|
|
143
164
|
data() {
|
|
@@ -148,6 +169,7 @@ export default {
|
|
|
148
169
|
return {
|
|
149
170
|
nodeDrivers: [],
|
|
150
171
|
kontainerDrivers: [],
|
|
172
|
+
extensions: [],
|
|
151
173
|
subType,
|
|
152
174
|
chart,
|
|
153
175
|
isImport,
|
|
@@ -285,6 +307,11 @@ export default {
|
|
|
285
307
|
addType(id, 'rke2', false);
|
|
286
308
|
});
|
|
287
309
|
|
|
310
|
+
// Add from extensions
|
|
311
|
+
this.extensions.forEach((ext) => {
|
|
312
|
+
addExtensionType(ext, getters);
|
|
313
|
+
});
|
|
314
|
+
|
|
288
315
|
addType('custom', 'custom2', false);
|
|
289
316
|
|
|
290
317
|
if (isElementalActive) {
|
|
@@ -295,6 +322,31 @@ export default {
|
|
|
295
322
|
|
|
296
323
|
return out;
|
|
297
324
|
|
|
325
|
+
function addExtensionType(ext, getters) {
|
|
326
|
+
let iconClass = ext.iconClass;
|
|
327
|
+
let icon = ext.icon;
|
|
328
|
+
|
|
329
|
+
if (icon) {
|
|
330
|
+
iconClass = undefined;
|
|
331
|
+
} else if (!iconClass) {
|
|
332
|
+
icon = require('~shell/assets/images/generic-driver.svg');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const subtype = {
|
|
336
|
+
id: ext.id,
|
|
337
|
+
label: ext.label || getters['i18n/t'](`cluster.provider.${ ext.id }`),
|
|
338
|
+
description: ext.description,
|
|
339
|
+
icon,
|
|
340
|
+
iconClass,
|
|
341
|
+
group: ext.group || 'rke2',
|
|
342
|
+
disabled: ext.disabled || false,
|
|
343
|
+
link: ext.link,
|
|
344
|
+
tag: ext.tag
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
out.push(subtype);
|
|
348
|
+
}
|
|
349
|
+
|
|
298
350
|
function addType(id, group, disabled = false, link = null, iconClass = undefined) {
|
|
299
351
|
const label = getters['i18n/withFallback'](`cluster.provider."${ id }"`, null, id);
|
|
300
352
|
const description = getters['i18n/withFallback'](`cluster.providerDescription."${ id }"`, null, '');
|