@rancher/shell 3.0.8-rc.6 → 3.0.8-rc.8
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/brand/suse/favicon.png +0 -0
- package/assets/images/content/README.md +5 -0
- package/assets/images/content/cloud-native.svg +84 -0
- package/assets/images/content/dark/cloud-native.svg +21 -0
- package/assets/images/content/dark/shield.svg +59 -0
- package/assets/images/content/dark/suse.svg +10 -0
- package/assets/images/content/shield.svg +59 -0
- package/assets/images/content/suse.svg +10 -0
- package/assets/styles/themes/_dark.scss +1 -1
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +2 -2
- package/assets/styles/themes/_suse.scss +4 -3
- package/assets/translations/en-us.yaml +6 -0
- package/components/BannerGraphic.vue +4 -4
- package/components/Drawer/Chrome.vue +2 -6
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +3 -9
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
- package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
- package/components/Drawer/ResourceDetailDrawer/index.vue +3 -9
- package/components/Drawer/ResourceDetailDrawer/types.ts +16 -0
- package/components/Drawer/types.ts +3 -0
- package/components/DynamicContent/DynamicContentBanner.vue +102 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
- package/components/DynamicContent/DynamicContentIcon.vue +132 -0
- package/components/DynamicContent/DynamicContentPanel.vue +112 -0
- package/components/DynamicContent/content.ts +78 -0
- package/components/PaginatedResourceTable.vue +2 -6
- package/components/Resource/Detail/CopyToClipboard.vue +3 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
- package/components/Resource/Detail/Metadata/composables.ts +9 -9
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/composables.ts +12 -0
- package/components/nav/Header.vue +2 -3
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/index.vue +2 -1
- package/components/nav/TopLevelMenu.helper.ts +16 -6
- package/components/templates/plain.vue +30 -4
- package/core/plugin-helpers.ts +2 -0
- package/edit/auth/__tests__/oidc.test.ts +26 -0
- package/edit/auth/oidc.vue +5 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +24 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +7 -3
- package/edit/provisioning.cattle.io.cluster/rke2.vue +7 -5
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +3 -2
- package/edit/service.vue +8 -4
- package/machine-config/amazonec2.vue +7 -1
- package/machine-config/components/EC2Networking.vue +37 -21
- package/machine-config/components/__tests__/EC2Networking.test.ts +54 -0
- package/mixins/__tests__/chart.test.ts +21 -0
- package/mixins/chart.js +7 -1
- package/models/provisioning.cattle.io.cluster.js +5 -1
- package/package.json +1 -1
- package/pages/c/_cluster/manager/hostedprovider/index.vue +5 -0
- package/pages/home.vue +14 -3
- package/pkg/dynamic-importer.lib.js +4 -0
- package/plugins/dashboard-store/resource-class.js +1 -2
- package/plugins/steve/subscribe.js +17 -9
- package/plugins/subscribe-events.ts +4 -2
- package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
- package/store/index.js +32 -13
- package/store/notifications.ts +21 -5
- package/store/type-map.js +3 -3
- package/types/notifications/index.ts +3 -0
- package/types/shell/index.d.ts +1 -0
- package/types/store/subscribe-events.types.ts +8 -1
- package/types/store/subscribe.types.ts +1 -0
- package/types/window-manager.ts +2 -0
- package/utils/__tests__/version.test.ts +19 -1
- package/utils/back-off.ts +3 -3
- package/utils/dynamic-content/__tests__/info.test.ts +15 -9
- package/utils/dynamic-content/announcement.ts +71 -41
- package/utils/dynamic-content/info.ts +1 -2
- package/utils/dynamic-content/types.d.ts +21 -1
- package/utils/pagination-wrapper.ts +12 -8
- package/utils/version.js +15 -0
|
@@ -15,6 +15,8 @@ import BrowserTabVisibility from '@shell/mixins/browser-tab-visibility';
|
|
|
15
15
|
import Inactivity from '@shell/components/Inactivity';
|
|
16
16
|
import { mapGetters } from 'vuex';
|
|
17
17
|
import PromptModal from '@shell/components/PromptModal';
|
|
18
|
+
import WindowManager from '@shell/components/nav/WindowManager';
|
|
19
|
+
import { Layout } from '@shell/types/window-manager';
|
|
18
20
|
|
|
19
21
|
export default {
|
|
20
22
|
|
|
@@ -30,7 +32,8 @@ export default {
|
|
|
30
32
|
SlideInPanelManager,
|
|
31
33
|
AwsComplianceBanner,
|
|
32
34
|
AzureWarning,
|
|
33
|
-
Inactivity
|
|
35
|
+
Inactivity,
|
|
36
|
+
WindowManager
|
|
34
37
|
},
|
|
35
38
|
|
|
36
39
|
mixins: [Brand, BrowserTabVisibility],
|
|
@@ -40,6 +43,7 @@ export default {
|
|
|
40
43
|
// Assume home pages have routes where the name is the key to use for string lookup
|
|
41
44
|
name: this.$route.name,
|
|
42
45
|
noLocaleShortcut: process.env.dev || false,
|
|
46
|
+
layout: Layout.plain,
|
|
43
47
|
};
|
|
44
48
|
},
|
|
45
49
|
|
|
@@ -97,6 +101,7 @@ export default {
|
|
|
97
101
|
@shortkey="toggleNoneLocale()"
|
|
98
102
|
/>
|
|
99
103
|
</main>
|
|
104
|
+
<WindowManager :layout="layout" />
|
|
100
105
|
</div>
|
|
101
106
|
|
|
102
107
|
<FixedBanner :footer="true" />
|
|
@@ -117,10 +122,10 @@ export default {
|
|
|
117
122
|
flex-grow: 1;
|
|
118
123
|
|
|
119
124
|
grid-template-areas:
|
|
120
|
-
"header"
|
|
121
|
-
"main";
|
|
125
|
+
"header header header"
|
|
126
|
+
"wm-vl main wm-vr";
|
|
122
127
|
|
|
123
|
-
grid-template-columns: auto;
|
|
128
|
+
grid-template-columns: var(--wm-vl-width, 0px) auto var(--wm-vr-width, 0px);
|
|
124
129
|
grid-template-rows: var(--header-height) auto;
|
|
125
130
|
|
|
126
131
|
> HEADER {
|
|
@@ -128,6 +133,27 @@ export default {
|
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
.wm {
|
|
137
|
+
grid-area: wm;
|
|
138
|
+
overflow-y: hidden;
|
|
139
|
+
z-index: z-index('windowsManager');
|
|
140
|
+
position: relative;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.wm-vr {
|
|
144
|
+
grid-area: wm-vr;
|
|
145
|
+
overflow-y: hidden;
|
|
146
|
+
z-index: z-index('windowsManager');
|
|
147
|
+
position: relative;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.wm-vl {
|
|
151
|
+
grid-area: wm-vl;
|
|
152
|
+
overflow-y: hidden;
|
|
153
|
+
z-index: z-index('windowsManager');
|
|
154
|
+
position: relative;
|
|
155
|
+
}
|
|
156
|
+
|
|
131
157
|
MAIN {
|
|
132
158
|
grid-area: main;
|
|
133
159
|
overflow: auto;
|
package/core/plugin-helpers.ts
CHANGED
|
@@ -221,5 +221,31 @@ describe('oidc.vue', () => {
|
|
|
221
221
|
expect(issuer).toBe('');
|
|
222
222
|
expect(endpoint).toBe('');
|
|
223
223
|
});
|
|
224
|
+
|
|
225
|
+
it('custom claims fields should not appear in UI if Amazon cognito', async() => {
|
|
226
|
+
wrapper.vm.model.id = 'cognito';
|
|
227
|
+
|
|
228
|
+
const nameClaim = wrapper.find('[data-testid="input-name-claim"]');
|
|
229
|
+
const groupsClaim = wrapper.find('[data-testid="input-groups-claim"]');
|
|
230
|
+
const emailClaim = wrapper.find('[data-testid="input-email-claim"]');
|
|
231
|
+
|
|
232
|
+
expect(nameClaim.exists()).toBe(false);
|
|
233
|
+
expect(groupsClaim.exists()).toBe(false);
|
|
234
|
+
expect(emailClaim.exists()).toBe(false);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('custom claims fields should appear in UI if genericoidc', async() => {
|
|
238
|
+
wrapper.vm.model.id = 'genericoidc';
|
|
239
|
+
wrapper.vm.addCustomClaims = true;
|
|
240
|
+
await nextTick();
|
|
241
|
+
|
|
242
|
+
const nameClaim = wrapper.find('[data-testid="input-name-claim"]');
|
|
243
|
+
const groupsClaim = wrapper.find('[data-testid="input-groups-claim"]');
|
|
244
|
+
const emailClaim = wrapper.find('[data-testid="input-email-claim"]');
|
|
245
|
+
|
|
246
|
+
expect(nameClaim.exists()).toBe(true);
|
|
247
|
+
expect(groupsClaim.exists()).toBe(true);
|
|
248
|
+
expect(emailClaim.exists()).toBe(true);
|
|
249
|
+
});
|
|
224
250
|
});
|
|
225
251
|
});
|
package/edit/auth/oidc.vue
CHANGED
|
@@ -442,12 +442,14 @@ export default {
|
|
|
442
442
|
</div>
|
|
443
443
|
</template>
|
|
444
444
|
|
|
445
|
-
|
|
445
|
+
<!-- Custom Claims -->
|
|
446
|
+
<template v-if="addCustomClaims && isGenericOidc">
|
|
446
447
|
<h4>{{ t('authConfig.oidc.customClaims.label') }}</h4>
|
|
447
448
|
<div class="row mb-20">
|
|
448
449
|
<div class="col span-6">
|
|
449
450
|
<LabeledInput
|
|
450
451
|
v-model:value="model.nameClaim"
|
|
452
|
+
data-testid="input-name-claim"
|
|
451
453
|
:label="t(`authConfig.oidc.customClaims.nameClaim.label`)"
|
|
452
454
|
:mode="mode"
|
|
453
455
|
/>
|
|
@@ -455,6 +457,7 @@ export default {
|
|
|
455
457
|
<div class="col span-6">
|
|
456
458
|
<LabeledInput
|
|
457
459
|
v-model:value="model.groupsClaim"
|
|
460
|
+
data-testid="input-groups-claim"
|
|
458
461
|
:label="t(`authConfig.oidc.customClaims.groupsClaim.label`)"
|
|
459
462
|
:mode="mode"
|
|
460
463
|
/>
|
|
@@ -464,6 +467,7 @@ export default {
|
|
|
464
467
|
<div class="col span-6">
|
|
465
468
|
<LabeledInput
|
|
466
469
|
v-model:value="model.emailClaim"
|
|
470
|
+
data-testid="input-email-claim"
|
|
467
471
|
:label="t(`authConfig.oidc.customClaims.emailClaim.label`)"
|
|
468
472
|
:mode="mode"
|
|
469
473
|
/>
|
|
@@ -47,7 +47,7 @@ describe('component: RKE2Networking', () => {
|
|
|
47
47
|
expect(dropdown.props('options')).toHaveLength(3);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
it('should show an error when an ipv6 pool is present and the user selects the ipv4-only stack preference', async() => {
|
|
50
|
+
it('should show an error when an ipv6 pool is present and the user selects the ipv4-only stack preference when creating a new cluster', async() => {
|
|
51
51
|
const spec = { ...defaultSpec, rkeConfig: { ...defaultSpec.rkeConfig, networking: { stackPreference: 'ipv4' } } };
|
|
52
52
|
const wrapper = mount(Networking, {
|
|
53
53
|
propsData: {
|
|
@@ -129,4 +129,27 @@ describe('component: RKE2Networking', () => {
|
|
|
129
129
|
|
|
130
130
|
expect(banner.exists()).toBe(false);
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
it('should not automatically update stack preference or validate it when editing an existing cluster even if its set to ipv4 and the user appears to have ipv6 pools', async() => {
|
|
134
|
+
const spec = { ...defaultSpec, rkeConfig: { ...defaultSpec.rkeConfig, networking: { stackPreference: 'ipv4' } } };
|
|
135
|
+
const wrapper = mount(Networking, {
|
|
136
|
+
propsData: {
|
|
137
|
+
mode: 'edit',
|
|
138
|
+
value: { spec },
|
|
139
|
+
selectedVersion: { serverArgs: mockServerArgs },
|
|
140
|
+
hasSomeIpv6Pools: true,
|
|
141
|
+
},
|
|
142
|
+
global: {
|
|
143
|
+
mocks: {
|
|
144
|
+
...defaultMocks,
|
|
145
|
+
$store: { getters: defaultGetters },
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await wrapper.vm.$nextTick();
|
|
151
|
+
|
|
152
|
+
expect(wrapper.emitted('validationChanged')?.[0]?.[0]).toBe(true);
|
|
153
|
+
expect(wrapper.emitted('stack-preference-changed')).toBeUndefined();
|
|
154
|
+
});
|
|
132
155
|
});
|
|
@@ -163,9 +163,8 @@ export default {
|
|
|
163
163
|
};
|
|
164
164
|
|
|
165
165
|
this.extensions = this.$extension.getProviders(context);
|
|
166
|
-
},
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
// At this point, we know we definitely have the mgmt cluster, so we can access `isImported` and `isLocal`
|
|
169
168
|
let subType = null;
|
|
170
169
|
|
|
171
170
|
subType = this.$route.query[SUB_TYPE] || null;
|
|
@@ -176,6 +175,11 @@ export default {
|
|
|
176
175
|
} else if (this.value.isLocal) {
|
|
177
176
|
subType = LOCAL;
|
|
178
177
|
}
|
|
178
|
+
|
|
179
|
+
this.subType = subType;
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
data() {
|
|
179
183
|
const rkeType = this.$route.query[RKE_TYPE] || null;
|
|
180
184
|
const chart = this.$route.query[CHART] || null;
|
|
181
185
|
const isImport = this.realMode === _IMPORT;
|
|
@@ -184,7 +188,7 @@ export default {
|
|
|
184
188
|
nodeDrivers: [],
|
|
185
189
|
kontainerDrivers: [],
|
|
186
190
|
extensions: [],
|
|
187
|
-
subType,
|
|
191
|
+
subType: null,
|
|
188
192
|
rkeType,
|
|
189
193
|
chart,
|
|
190
194
|
isImport,
|
|
@@ -990,15 +990,16 @@ export default {
|
|
|
990
990
|
},
|
|
991
991
|
|
|
992
992
|
hasSomeIpv6Pools(neu) {
|
|
993
|
-
|
|
993
|
+
if (this.isCreate && this.localValue.spec.rkeConfig.networking.stackPreference !== STACK_PREFS.IPV6) { // if stack pref is ipv6, the user has manually configured that and we shouldn't change it
|
|
994
|
+
if (neu) {
|
|
995
|
+
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.DUAL;
|
|
996
|
+
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
994
999
|
|
|
995
|
-
if (neu && (stackPreference === STACK_PREFS.IPV4 || !stackPreference)) { // localValue.spec.rkeConfig.networking is initialized in the beforeCreate hook
|
|
996
|
-
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.DUAL;
|
|
997
|
-
} else if (stackPreference === STACK_PREFS.DUAL) {
|
|
998
1000
|
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.IPV4;
|
|
999
1001
|
}
|
|
1000
1002
|
},
|
|
1001
|
-
|
|
1002
1003
|
},
|
|
1003
1004
|
|
|
1004
1005
|
created() {
|
|
@@ -2256,6 +2257,7 @@ export default {
|
|
|
2256
2257
|
handleTabChange(data) {
|
|
2257
2258
|
this.activeTab = data;
|
|
2258
2259
|
},
|
|
2260
|
+
|
|
2259
2261
|
}
|
|
2260
2262
|
};
|
|
2261
2263
|
</script>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
3
3
|
import { Banner } from '@components/Banner';
|
|
4
4
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
5
|
-
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
5
|
+
import { _EDIT, _VIEW, _CREATE } from '@shell/config/query-params';
|
|
6
6
|
import ArrayList from '@shell/components/form/ArrayList';
|
|
7
7
|
import ACE from '@shell/edit/provisioning.cattle.io.cluster/tabs/networking/ACE';
|
|
8
8
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
@@ -128,11 +128,12 @@ export default {
|
|
|
128
128
|
methods: {
|
|
129
129
|
// if ipv6 pools are detected, we enforce dual-stack or ipv6 stack prefs.
|
|
130
130
|
// If ipv6 pools are not detected we don't know for sure they aren't there so we don't validate the input
|
|
131
|
+
// also not validating the input when editing existing clusters to ensure we don't prevent editing clusters using dual-stack VPCs provisioned before the ipv6 feature was added
|
|
131
132
|
stackPreferenceValidator(val) {
|
|
132
133
|
const value = val?.value || val;
|
|
133
134
|
let isValid;
|
|
134
135
|
|
|
135
|
-
if (this.hasSomeIpv6Pools) {
|
|
136
|
+
if (this.hasSomeIpv6Pools && this.mode === _CREATE) {
|
|
136
137
|
isValid = value !== STACK_PREFS.IPV4;
|
|
137
138
|
|
|
138
139
|
return isValid ? null : this.t('cluster.rke2.stackPreference.errorNeedsIpv6');
|
package/edit/service.vue
CHANGED
|
@@ -272,10 +272,14 @@ export default {
|
|
|
272
272
|
|
|
273
273
|
async loadPods() {
|
|
274
274
|
try {
|
|
275
|
-
const hash = {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
const hash = {};
|
|
276
|
+
|
|
277
|
+
if (this.$store.getters[`management/canList`](CAPI.RANCHER_CLUSTER)) {
|
|
278
|
+
hash.provClusters = this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
|
|
279
|
+
}
|
|
280
|
+
if (this.$store.getters[`management/canList`](HCI.HARVESTER_CONFIG)) {
|
|
281
|
+
hash.harvesterConfigs = this.$store.dispatch(`management/findAll`, { type: HCI.HARVESTER_CONFIG });
|
|
282
|
+
}
|
|
279
283
|
|
|
280
284
|
await allHash(hash);
|
|
281
285
|
this.updateMatchingPods();
|
|
@@ -55,7 +55,12 @@ export default {
|
|
|
55
55
|
machinePools: {
|
|
56
56
|
type: Array,
|
|
57
57
|
default: () => []
|
|
58
|
-
}
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
poolCreateMode: {
|
|
61
|
+
type: Boolean,
|
|
62
|
+
default: true
|
|
63
|
+
},
|
|
59
64
|
},
|
|
60
65
|
|
|
61
66
|
async fetch() {
|
|
@@ -383,6 +388,7 @@ export default {
|
|
|
383
388
|
:machine-pools="machinePools"
|
|
384
389
|
:has-ipv6="hasIpv6"
|
|
385
390
|
:disabled="disabled"
|
|
391
|
+
:is-new="poolCreateMode"
|
|
386
392
|
@update:has-ipv6="e=>$emit('update:hasIpv6', e)"
|
|
387
393
|
@validation-changed="e=>$emit('validationChanged',e)"
|
|
388
394
|
/>
|
|
@@ -92,7 +92,12 @@ export default {
|
|
|
92
92
|
machinePools: {
|
|
93
93
|
type: Array,
|
|
94
94
|
default: () => []
|
|
95
|
-
}
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
isNew: {
|
|
98
|
+
type: Boolean,
|
|
99
|
+
default: true
|
|
100
|
+
},
|
|
96
101
|
},
|
|
97
102
|
|
|
98
103
|
created() {
|
|
@@ -107,6 +112,10 @@ export default {
|
|
|
107
112
|
} else if (this.vpcId) {
|
|
108
113
|
this.enableIpv6 = !!vpcs.find((vpc) => vpc.VpcId === this.vpcId && vpc.Ipv6CidrBlockAssociationSet && !isEmpty(vpc.Ipv6CidrBlockAssociationSet));
|
|
109
114
|
}
|
|
115
|
+
|
|
116
|
+
if (this.isNew && this.somePoolHasIpv6OrDual) {
|
|
117
|
+
this.enableIpv6 = true;
|
|
118
|
+
}
|
|
110
119
|
},
|
|
111
120
|
|
|
112
121
|
data() {
|
|
@@ -115,13 +124,13 @@ export default {
|
|
|
115
124
|
|
|
116
125
|
watch: {
|
|
117
126
|
region() {
|
|
118
|
-
if (this.
|
|
127
|
+
if (this.isNew) {
|
|
119
128
|
this.updateNetwork();
|
|
120
129
|
}
|
|
121
130
|
},
|
|
122
131
|
|
|
123
132
|
enableIpv6(neu) {
|
|
124
|
-
if (this.
|
|
133
|
+
if (this.isNew) {
|
|
125
134
|
this.updateNetwork();
|
|
126
135
|
}
|
|
127
136
|
this.$emit('update:hasIpv6', neu);
|
|
@@ -144,16 +153,19 @@ export default {
|
|
|
144
153
|
}
|
|
145
154
|
},
|
|
146
155
|
|
|
147
|
-
|
|
148
|
-
this.$emit('
|
|
156
|
+
ipv6AddressOnly(neu) {
|
|
157
|
+
this.$emit('update:hasIpv6', neu);
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
allValid: {
|
|
161
|
+
handler(neu) {
|
|
162
|
+
this.$emit('validationChanged', neu);
|
|
163
|
+
},
|
|
164
|
+
immediate: true
|
|
149
165
|
}
|
|
150
166
|
},
|
|
151
167
|
|
|
152
168
|
computed: {
|
|
153
|
-
isCreate() {
|
|
154
|
-
return this.mode === _CREATE;
|
|
155
|
-
},
|
|
156
|
-
|
|
157
169
|
allNetworkOptions() {
|
|
158
170
|
if ( !this.vpcInfo || !this.subnetInfo ) {
|
|
159
171
|
return [];
|
|
@@ -266,14 +278,18 @@ export default {
|
|
|
266
278
|
return opt && opt.hasIpv6 && !opt.hasIpv4;
|
|
267
279
|
},
|
|
268
280
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
281
|
+
somePoolHasIpv6OrDual() {
|
|
282
|
+
return !!this.machinePools.find((p) => p.hasIpv6);
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
showIpv6Options() {
|
|
286
|
+
return this.mode === _CREATE || (this.isNew && this.somePoolHasIpv6OrDual) || this.enableIpv6;
|
|
287
|
+
},
|
|
273
288
|
|
|
274
|
-
|
|
289
|
+
poolsInvalid() {
|
|
290
|
+
const somePoolHasIpv4 = !!this.machinePools.find((p) => !p.hasIpv6);
|
|
275
291
|
|
|
276
|
-
return
|
|
292
|
+
return this.somePoolHasIpv6OrDual && somePoolHasIpv4;
|
|
277
293
|
},
|
|
278
294
|
|
|
279
295
|
addressCountInvalid() {
|
|
@@ -335,7 +351,7 @@ export default {
|
|
|
335
351
|
data-testid="amazonEc2__ipv6Warning"
|
|
336
352
|
/>
|
|
337
353
|
<div
|
|
338
|
-
v-if="
|
|
354
|
+
v-if="showIpv6Options"
|
|
339
355
|
class="row mb-20"
|
|
340
356
|
>
|
|
341
357
|
<div
|
|
@@ -344,7 +360,7 @@ export default {
|
|
|
344
360
|
>
|
|
345
361
|
<Checkbox
|
|
346
362
|
v-model:value="enableIpv6"
|
|
347
|
-
:disabled="!
|
|
363
|
+
:disabled="!isNew"
|
|
348
364
|
:label="t('cluster.machineConfig.amazonEc2.enableIpv6.label')"
|
|
349
365
|
data-testid="amazonEc2__enableIpv6"
|
|
350
366
|
:mode="mode"
|
|
@@ -387,7 +403,7 @@ export default {
|
|
|
387
403
|
class="col span-3"
|
|
388
404
|
>
|
|
389
405
|
<Checkbox
|
|
390
|
-
:disabled="!
|
|
406
|
+
:disabled="!isNew || !dualStackSelected"
|
|
391
407
|
:value="ipv6AddressOnly"
|
|
392
408
|
:label="t('cluster.machineConfig.amazonEc2.ipv6AddressOnly.label')"
|
|
393
409
|
:mode="mode"
|
|
@@ -403,7 +419,7 @@ export default {
|
|
|
403
419
|
<div class="col span-6">
|
|
404
420
|
<Checkbox
|
|
405
421
|
:value="httpProtocolIpv6==='enabled'"
|
|
406
|
-
:disabled="!
|
|
422
|
+
:disabled="!isNew"
|
|
407
423
|
:label="t('cluster.machineConfig.amazonEc2.httpProtocolIpv6.label')"
|
|
408
424
|
data-testid="amazonEc2__enableIpv6"
|
|
409
425
|
:mode="mode"
|
|
@@ -417,7 +433,7 @@ export default {
|
|
|
417
433
|
>
|
|
418
434
|
<div class="col span-3">
|
|
419
435
|
<LabeledInput
|
|
420
|
-
:disabled="!
|
|
436
|
+
:disabled="!isNew"
|
|
421
437
|
min="1"
|
|
422
438
|
:mode="mode"
|
|
423
439
|
:value="ipv6AddressCount"
|
|
@@ -429,7 +445,7 @@ export default {
|
|
|
429
445
|
</div>
|
|
430
446
|
<div class="col span-9">
|
|
431
447
|
<Checkbox
|
|
432
|
-
:disabled="!
|
|
448
|
+
:disabled="!isNew"
|
|
433
449
|
:value="enablePrimaryIpv6"
|
|
434
450
|
:label="t('cluster.machineConfig.amazonEc2.enablePrimaryIpv6.label')"
|
|
435
451
|
:mode="mode"
|
|
@@ -91,4 +91,58 @@ describe('component: EC2Networking', () => {
|
|
|
91
91
|
|
|
92
92
|
expect(ipv6Warning.exists()).toBe(shouldShowError);
|
|
93
93
|
});
|
|
94
|
+
|
|
95
|
+
it('should show ipv6 inputs and automatically check the enable ipv6 checkbox when adding a new pool if some other pool in the cluster is using ipv6 or dual stack', () => {
|
|
96
|
+
const wrapper = shallowMount(EC2Networking, {
|
|
97
|
+
...defaultCreateSetup,
|
|
98
|
+
propsData: {
|
|
99
|
+
...defaultCreateSetup.propsData,
|
|
100
|
+
machinePools: [{ hasIpv6: true }],
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const ipv6AddressCountInput = wrapper.findComponent('[data-testid="amazonEc2__ipv6AddressCount"]');
|
|
105
|
+
|
|
106
|
+
expect(wrapper.vm.enableIpv6).toBe(true);
|
|
107
|
+
expect(ipv6AddressCountInput.exists()).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should not show ipv6 inputs or automatically check the enable ipv6 checkbox when adding a new pool to a cluster that does not have existing ipv6 or dual stack pools', () => {
|
|
111
|
+
const wrapper = shallowMount(EC2Networking, {
|
|
112
|
+
...defaultCreateSetup,
|
|
113
|
+
propsData: {
|
|
114
|
+
...defaultCreateSetup.propsData,
|
|
115
|
+
machinePools: [{ hasIpv6: false }],
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const ipv6AddressCountInput = wrapper.findComponent('[data-testid="amazonEc2__ipv6AddressCount"]');
|
|
120
|
+
|
|
121
|
+
expect(wrapper.vm.enableIpv6).toBe(false);
|
|
122
|
+
expect(ipv6AddressCountInput.exists()).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('should emit a validationChanged: false event when created with ipv6 enabled while some other pools have ipv6 disabled', async() => {
|
|
126
|
+
const wrapper = shallowMount(EC2Networking, {
|
|
127
|
+
...defaultCreateSetup,
|
|
128
|
+
propsData: {
|
|
129
|
+
...defaultCreateSetup.propsData,
|
|
130
|
+
machinePools: [{ hasIpv6: true }, { hasIpv6: false }],
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect(wrapper.emitted('validationChanged')?.[0][0]).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should emit a validationChanged: true event when created with ipv6 enabled while all other pools also have ipv6 enabled', async() => {
|
|
138
|
+
const wrapper = shallowMount(EC2Networking, {
|
|
139
|
+
...defaultCreateSetup,
|
|
140
|
+
propsData: {
|
|
141
|
+
...defaultCreateSetup.propsData,
|
|
142
|
+
machinePools: [{ hasIpv6: true }, { hasIpv6: true }],
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(wrapper.emitted('validationChanged')?.[0][0]).toBe(true);
|
|
147
|
+
});
|
|
94
148
|
});
|
|
@@ -238,5 +238,26 @@ describe('chartMixin', () => {
|
|
|
238
238
|
icon: 'icon-downgrade-alt',
|
|
239
239
|
});
|
|
240
240
|
});
|
|
241
|
+
|
|
242
|
+
it('should return "upgrade" action when upgrading from a pre-release to a stable version', () => {
|
|
243
|
+
const wrapper = mount(DummyComponent, {
|
|
244
|
+
data: () => ({
|
|
245
|
+
existing: { spec: { chart: { metadata: { version: '1.0.0-rc1' } } } },
|
|
246
|
+
version: { version: '1.0.0' }
|
|
247
|
+
}),
|
|
248
|
+
global: {
|
|
249
|
+
mocks: {
|
|
250
|
+
$store: mockStore,
|
|
251
|
+
$route: { query: {} }
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
expect(wrapper.vm.action).toStrictEqual({
|
|
257
|
+
name: 'upgrade',
|
|
258
|
+
tKey: 'upgrade',
|
|
259
|
+
icon: 'icon-upgrade-alt',
|
|
260
|
+
});
|
|
261
|
+
});
|
|
241
262
|
});
|
|
242
263
|
});
|
package/mixins/chart.js
CHANGED
|
@@ -10,7 +10,7 @@ import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
|
10
10
|
import { OPA_GATE_KEEPER_ID } from '@shell/pages/c/_cluster/gatekeeper/index.vue';
|
|
11
11
|
import { formatSi, parseSi } from '@shell/utils/units';
|
|
12
12
|
import { CAPI, CATALOG } from '@shell/config/types';
|
|
13
|
-
import { isPrerelease, compare } from '@shell/utils/version';
|
|
13
|
+
import { isPrerelease, compare, isUpgradeFromPreToStable } from '@shell/utils/version';
|
|
14
14
|
import difference from 'lodash/difference';
|
|
15
15
|
import { LINUX, APP_UPGRADE_STATUS } from '@shell/store/catalog';
|
|
16
16
|
import { clone } from '@shell/utils/object';
|
|
@@ -240,6 +240,12 @@ export default {
|
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
if (isUpgradeFromPreToStable(this.currentVersion, this.targetVersion)) {
|
|
244
|
+
return {
|
|
245
|
+
name: 'upgrade', tKey: 'upgrade', icon: 'icon-upgrade-alt'
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
243
249
|
if (compare(this.currentVersion, this.targetVersion) < 0) {
|
|
244
250
|
return {
|
|
245
251
|
name: 'upgrade', tKey: 'upgrade', icon: 'icon-upgrade-alt'
|
|
@@ -369,7 +369,11 @@ export default class ProvCluster extends SteveModel {
|
|
|
369
369
|
}
|
|
370
370
|
|
|
371
371
|
get mgmtClusterId() {
|
|
372
|
-
|
|
372
|
+
// when a cluster is created `this` instance isn't immediately updated with `status.clusterName`
|
|
373
|
+
// Workaround - Get fresh copy from the store
|
|
374
|
+
const pCluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, this.id);
|
|
375
|
+
|
|
376
|
+
return this.status?.clusterName || pCluster?.status?.clusterName;
|
|
373
377
|
}
|
|
374
378
|
|
|
375
379
|
get mgmt() {
|
package/package.json
CHANGED
|
@@ -160,6 +160,11 @@ export default {
|
|
|
160
160
|
:type-display="t('providers.hosted.title')"
|
|
161
161
|
:is-creatable="false"
|
|
162
162
|
/>
|
|
163
|
+
<Banner
|
|
164
|
+
color="warning"
|
|
165
|
+
:label="t('providers.hosted.warning')"
|
|
166
|
+
:closable="false"
|
|
167
|
+
/>
|
|
163
168
|
<Banner
|
|
164
169
|
v-for="(err, i) in errors"
|
|
165
170
|
:key="i"
|
package/pages/home.vue
CHANGED
|
@@ -7,6 +7,8 @@ import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue
|
|
|
7
7
|
import { BadgeState } from '@components/BadgeState';
|
|
8
8
|
import CommunityLinks from '@shell/components/CommunityLinks.vue';
|
|
9
9
|
import SingleClusterInfo from '@shell/components/SingleClusterInfo.vue';
|
|
10
|
+
import DynamicContentBanner from '@shell/components/DynamicContent/DynamicContentBanner.vue';
|
|
11
|
+
import DynamicContentPanel from '@shell/components/DynamicContent/DynamicContentPanel.vue';
|
|
10
12
|
import { mapGetters, mapState } from 'vuex';
|
|
11
13
|
import { MANAGEMENT, CAPI, COUNT } from '@shell/config/types';
|
|
12
14
|
import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
@@ -47,6 +49,8 @@ export default defineComponent({
|
|
|
47
49
|
SingleClusterInfo,
|
|
48
50
|
TabTitle,
|
|
49
51
|
ResourceTable,
|
|
52
|
+
DynamicContentBanner,
|
|
53
|
+
DynamicContentPanel,
|
|
50
54
|
},
|
|
51
55
|
|
|
52
56
|
mixins: [PageHeaderActions, Preset],
|
|
@@ -298,8 +302,11 @@ export default defineComponent({
|
|
|
298
302
|
return Promise.resolve({});
|
|
299
303
|
}
|
|
300
304
|
|
|
305
|
+
const promises = [];
|
|
306
|
+
|
|
301
307
|
if ( this.canViewMgmtClusters ) {
|
|
302
|
-
|
|
308
|
+
// This is the only one we need to block on (needed for the initial sort on mgmt name)
|
|
309
|
+
promises.push(this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER }));
|
|
303
310
|
}
|
|
304
311
|
|
|
305
312
|
if ( this.canViewMachine ) {
|
|
@@ -319,7 +326,7 @@ export default defineComponent({
|
|
|
319
326
|
this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE_TEMPLATE });
|
|
320
327
|
}
|
|
321
328
|
|
|
322
|
-
return Promise.
|
|
329
|
+
return Promise.all(promises);
|
|
323
330
|
},
|
|
324
331
|
|
|
325
332
|
async fetchPageSecondaryResources({
|
|
@@ -609,6 +616,7 @@ export default defineComponent({
|
|
|
609
616
|
pref-key="welcomeBanner"
|
|
610
617
|
data-testid="home-banner-graphic"
|
|
611
618
|
/>
|
|
619
|
+
<DynamicContentBanner location="banner" />
|
|
612
620
|
<IndentedPanel class="mt-20 mb-20">
|
|
613
621
|
<div class="row home-panels">
|
|
614
622
|
<div class="col main-panel">
|
|
@@ -935,7 +943,10 @@ export default defineComponent({
|
|
|
935
943
|
</div>
|
|
936
944
|
</div>
|
|
937
945
|
</div>
|
|
938
|
-
<
|
|
946
|
+
<div class="col span-3 side-panel">
|
|
947
|
+
<CommunityLinks />
|
|
948
|
+
<DynamicContentPanel location="rhs" />
|
|
949
|
+
</div>
|
|
939
950
|
</div>
|
|
940
951
|
</IndentedPanel>
|
|
941
952
|
</div>
|