Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('component: RKE2Networking', () => {
expect(dropdown.props('options')).toHaveLength(3);
});

it('should show an error when an ipv6 pool is present and the user selects the ipv4-only stack preference', async() => {
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() => {
const spec = { ...defaultSpec, rkeConfig: { ...defaultSpec.rkeConfig, networking: { stackPreference: 'ipv4' } } };
const wrapper = mount(Networking, {
propsData: {
Expand Down Expand Up @@ -129,4 +129,27 @@ describe('component: RKE2Networking', () => {

expect(banner.exists()).toBe(false);
});

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() => {
const spec = { ...defaultSpec, rkeConfig: { ...defaultSpec.rkeConfig, networking: { stackPreference: 'ipv4' } } };
const wrapper = mount(Networking, {
propsData: {
mode: 'edit',
value: { spec },
selectedVersion: { serverArgs: mockServerArgs },
hasSomeIpv6Pools: true,
},
global: {
mocks: {
...defaultMocks,
$store: { getters: defaultGetters },
},
},
});

await wrapper.vm.$nextTick();

expect(wrapper.emitted('validationChanged')?.[0]?.[0]).toBe(true);
expect(wrapper.emitted('stack-preference-changed')).toBeUndefined();
});
});
12 changes: 7 additions & 5 deletions shell/edit/provisioning.cattle.io.cluster/rke2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -990,15 +990,16 @@ export default {
},

hasSomeIpv6Pools(neu) {
const stackPreference = this.localValue.spec.rkeConfig.networking.stackPreference;
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
if (neu) {
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.DUAL;

return;
}

if (neu && (stackPreference === STACK_PREFS.IPV4 || !stackPreference)) { // localValue.spec.rkeConfig.networking is initialized in the beforeCreate hook
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.DUAL;
} else if (stackPreference === STACK_PREFS.DUAL) {
this.localValue.spec.rkeConfig.networking.stackPreference = STACK_PREFS.IPV4;
}
},

},

created() {
Expand Down Expand Up @@ -2256,6 +2257,7 @@ export default {
handleTabChange(data) {
this.activeTab = data;
},

}
};
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { LabeledInput } from '@components/Form/LabeledInput';
import { Banner } from '@components/Banner';
import { Checkbox } from '@components/Form/Checkbox';
import { _EDIT, _VIEW } from '@shell/config/query-params';
import { _EDIT, _VIEW, _CREATE } from '@shell/config/query-params';
import ArrayList from '@shell/components/form/ArrayList';
import ACE from '@shell/edit/provisioning.cattle.io.cluster/tabs/networking/ACE';
import LabeledSelect from '@shell/components/form/LabeledSelect';
Expand Down Expand Up @@ -128,11 +128,12 @@ export default {
methods: {
// if ipv6 pools are detected, we enforce dual-stack or ipv6 stack prefs.
// If ipv6 pools are not detected we don't know for sure they aren't there so we don't validate the input
// 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
stackPreferenceValidator(val) {
const value = val?.value || val;
let isValid;

if (this.hasSomeIpv6Pools) {
if (this.hasSomeIpv6Pools && this.mode === _CREATE) {
isValid = value !== STACK_PREFS.IPV4;

return isValid ? null : this.t('cluster.rke2.stackPreference.errorNeedsIpv6');
Expand Down
8 changes: 7 additions & 1 deletion shell/machine-config/amazonec2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ export default {
machinePools: {
type: Array,
default: () => []
}
},

poolCreateMode: {
type: Boolean,
default: true
},
},

async fetch() {
Expand Down Expand Up @@ -383,6 +388,7 @@ export default {
:machine-pools="machinePools"
:has-ipv6="hasIpv6"
:disabled="disabled"
:is-new="poolCreateMode"
@update:has-ipv6="e=>$emit('update:hasIpv6', e)"
@validation-changed="e=>$emit('validationChanged',e)"
/>
Expand Down
51 changes: 32 additions & 19 deletions shell/machine-config/components/EC2Networking.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ export default {
machinePools: {
type: Array,
default: () => []
}
},

isNew: {
type: Boolean,
default: true
},
},

created() {
Expand All @@ -107,6 +112,10 @@ export default {
} else if (this.vpcId) {
this.enableIpv6 = !!vpcs.find((vpc) => vpc.VpcId === this.vpcId && vpc.Ipv6CidrBlockAssociationSet && !isEmpty(vpc.Ipv6CidrBlockAssociationSet));
}

if (this.isNew && this.somePoolHasIpv6OrDual) {
this.enableIpv6 = true;
}
},

data() {
Expand All @@ -115,13 +124,13 @@ export default {

watch: {
region() {
if (this.isCreate) {
if (this.isNew) {
this.updateNetwork();
}
},

enableIpv6(neu) {
if (this.isCreate) {
if (this.isNew) {
this.updateNetwork();
}
this.$emit('update:hasIpv6', neu);
Expand All @@ -144,16 +153,16 @@ export default {
}
},

ipv6AddressOnly(neu) {
this.$emit('update:hasIpv6', neu);
},

allValid(neu) {
this.$emit('validationChanged', neu);
}
},

computed: {
isCreate() {
return this.mode === _CREATE;
},

allNetworkOptions() {
if ( !this.vpcInfo || !this.subnetInfo ) {
return [];
Expand Down Expand Up @@ -266,14 +275,18 @@ export default {
return opt && opt.hasIpv6 && !opt.hasIpv4;
},

poolsInvalid() {
const hasIpv6 = !!this.machinePools.find((p) => {
return p.hasIpv6;
});
somePoolHasIpv6OrDual() {
return !!this.machinePools.find((p) => p.hasIpv6);
},

showIpv6Options() {
return this.mode === _CREATE || (this.isNew && this.somePoolHasIpv6OrDual) || this.enableIpv6;
},

const hasNotIpv6 = !!this.machinePools.find((p) => !p.hasIpv6);
poolsInvalid() {
const somePoolHasIpv4 = !!this.machinePools.find((p) => !p.hasIpv6);

return hasIpv6 && hasNotIpv6;
return this.somePoolHasIpv6OrDual && somePoolHasIpv4;
},

addressCountInvalid() {
Expand Down Expand Up @@ -335,7 +348,7 @@ export default {
data-testid="amazonEc2__ipv6Warning"
/>
<div
v-if="isCreate || enableIpv6"
v-if="showIpv6Options"
class="row mb-20"
>
<div
Expand All @@ -344,7 +357,7 @@ export default {
>
<Checkbox
v-model:value="enableIpv6"
:disabled="!isCreate"
:disabled="!isNew"
:label="t('cluster.machineConfig.amazonEc2.enableIpv6.label')"
data-testid="amazonEc2__enableIpv6"
:mode="mode"
Expand Down Expand Up @@ -387,7 +400,7 @@ export default {
class="col span-3"
>
<Checkbox
:disabled="!isCreate || !dualStackSelected"
:disabled="!isNew || !dualStackSelected"
:value="ipv6AddressOnly"
:label="t('cluster.machineConfig.amazonEc2.ipv6AddressOnly.label')"
:mode="mode"
Expand All @@ -403,7 +416,7 @@ export default {
<div class="col span-6">
<Checkbox
:value="httpProtocolIpv6==='enabled'"
:disabled="!isCreate"
:disabled="!isNew"
:label="t('cluster.machineConfig.amazonEc2.httpProtocolIpv6.label')"
data-testid="amazonEc2__enableIpv6"
:mode="mode"
Expand All @@ -417,7 +430,7 @@ export default {
>
<div class="col span-3">
<LabeledInput
:disabled="!isCreate"
:disabled="!isNew"
min="1"
:mode="mode"
:value="ipv6AddressCount"
Expand All @@ -429,7 +442,7 @@ export default {
</div>
<div class="col span-9">
<Checkbox
:disabled="!isCreate"
:disabled="!isNew"
:value="enablePrimaryIpv6"
:label="t('cluster.machineConfig.amazonEc2.enablePrimaryIpv6.label')"
:mode="mode"
Expand Down
30 changes: 30 additions & 0 deletions shell/machine-config/components/__tests__/EC2Networking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,34 @@ describe('component: EC2Networking', () => {

expect(ipv6Warning.exists()).toBe(shouldShowError);
});

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', () => {
const wrapper = shallowMount(EC2Networking, {
...defaultCreateSetup,
propsData: {
...defaultCreateSetup.propsData,
machinePools: [{ hasIpv6: true }],
},
});

const ipv6AddressCountInput = wrapper.findComponent('[data-testid="amazonEc2__ipv6AddressCount"]');

expect(wrapper.vm.enableIpv6).toBe(true);
expect(ipv6AddressCountInput.exists()).toBe(true);
});

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', () => {
const wrapper = shallowMount(EC2Networking, {
...defaultCreateSetup,
propsData: {
...defaultCreateSetup.propsData,
machinePools: [{ hasIpv6: false }],
},
});

const ipv6AddressCountInput = wrapper.findComponent('[data-testid="amazonEc2__ipv6AddressCount"]');

expect(wrapper.vm.enableIpv6).toBe(false);
expect(ipv6AddressCountInput.exists()).toBe(false);
});
});