Skip to content

Commit 60437fb

Browse files
authored
Merge pull request #4444 from MaxFedotov/vpc-ipam-manager
feat: support IPAM Manager for VPC creation
2 parents 1f688e3 + 5f272fb commit 60437fb

29 files changed

+490
-42
lines changed

api/v1beta1/awscluster_conversion.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
5555
}
5656
dst.Status.Network.NatGatewaysIPs = restored.Status.Network.NatGatewaysIPs
5757

58+
if restored.Spec.NetworkSpec.VPC.IPAMPool != nil {
59+
if dst.Spec.NetworkSpec.VPC.IPAMPool == nil {
60+
dst.Spec.NetworkSpec.VPC.IPAMPool = &infrav2.IPAMPool{}
61+
}
62+
63+
restoreIPAMPool(restored.Spec.NetworkSpec.VPC.IPAMPool, dst.Spec.NetworkSpec.VPC.IPAMPool)
64+
}
65+
66+
if restored.Spec.NetworkSpec.VPC.IsIPv6Enabled() && restored.Spec.NetworkSpec.VPC.IPv6.IPAMPool != nil {
67+
if dst.Spec.NetworkSpec.VPC.IPv6.IPAMPool == nil {
68+
dst.Spec.NetworkSpec.VPC.IPv6.IPAMPool = &infrav2.IPAMPool{}
69+
}
70+
71+
restoreIPAMPool(restored.Spec.NetworkSpec.VPC.IPv6.IPAMPool, dst.Spec.NetworkSpec.VPC.IPv6.IPAMPool)
72+
}
73+
5874
return nil
5975
}
6076

@@ -67,6 +83,14 @@ func restoreControlPlaneLoadBalancerStatus(restored, dst *infrav2.LoadBalancer)
6783
dst.ELBListeners = restored.ELBListeners
6884
}
6985

86+
// restoreIPAMPool manually restores the ipam pool data.
87+
// Assumes restored and dst are non-nil.
88+
func restoreIPAMPool(restored, dst *infrav2.IPAMPool) {
89+
dst.ID = restored.ID
90+
dst.Name = restored.Name
91+
dst.NetmaskLength = restored.NetmaskLength
92+
}
93+
7094
// restoreControlPlaneLoadBalancer manually restores the control plane loadbalancer data.
7195
// Assumes restored and dst are non-nil.
7296
func restoreControlPlaneLoadBalancer(restored, dst *infrav2.AWSLoadBalancerSpec) {

api/v1beta1/conversion.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,11 @@ func Convert_v1beta2_LoadBalancer_To_v1beta1_ClassicELB(in *v1beta2.LoadBalancer
8282
func Convert_v1beta2_IngressRule_To_v1beta1_IngressRule(in *v1beta2.IngressRule, out *IngressRule, s conversion.Scope) error {
8383
return autoConvert_v1beta2_IngressRule_To_v1beta1_IngressRule(in, out, s)
8484
}
85+
86+
func Convert_v1beta2_VPCSpec_To_v1beta1_VPCSpec(in *v1beta2.VPCSpec, out *VPCSpec, s conversion.Scope) error {
87+
return autoConvert_v1beta2_VPCSpec_To_v1beta1_VPCSpec(in, out, s)
88+
}
89+
90+
func Convert_v1beta2_IPv6_To_v1beta1_IPv6(in *v1beta2.IPv6, out *IPv6, s conversion.Scope) error {
91+
return autoConvert_v1beta2_IPv6_To_v1beta1_IPv6(in, out, s)
92+
}

api/v1beta1/zz_generated.conversion.go

Lines changed: 30 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1beta2/awscluster_webhook.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,15 @@ func (r *AWSCluster) validateNetwork() field.ErrorList {
228228
allErrs = append(allErrs, field.Invalid(field.NewPath("subnets"), r.Spec.NetworkSpec.Subnets, "IPv6 cannot be used with unmanaged clusters at this time."))
229229
}
230230
}
231+
232+
if r.Spec.NetworkSpec.VPC.CidrBlock != "" && r.Spec.NetworkSpec.VPC.IPAMPool != nil {
233+
allErrs = append(allErrs, field.Invalid(field.NewPath("cidrBlock"), r.Spec.NetworkSpec.VPC.CidrBlock, "cidrBlock and ipamPool cannot be used together"))
234+
}
235+
236+
if r.Spec.NetworkSpec.VPC.IPAMPool != nil && r.Spec.NetworkSpec.VPC.IPAMPool.ID == "" && r.Spec.NetworkSpec.VPC.IPAMPool.Name == "" {
237+
allErrs = append(allErrs, field.Invalid(field.NewPath("ipamPool"), r.Spec.NetworkSpec.VPC.IPAMPool, "ipamPool must have either id or name"))
238+
}
239+
231240
return allErrs
232241
}
233242

api/v1beta2/awscluster_webhook_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,33 @@ func TestAWSClusterValidateCreate(t *testing.T) {
335335
},
336336
wantErr: false,
337337
},
338+
{
339+
name: "rejects cidrBlock and ipamPool if set together",
340+
cluster: &AWSCluster{
341+
Spec: AWSClusterSpec{
342+
NetworkSpec: NetworkSpec{
343+
VPC: VPCSpec{
344+
CidrBlock: "10.0.0.0/16",
345+
IPAMPool: &IPAMPool{},
346+
},
347+
},
348+
},
349+
},
350+
wantErr: true,
351+
},
352+
{
353+
name: "rejects ipamPool if id or name not set",
354+
cluster: &AWSCluster{
355+
Spec: AWSClusterSpec{
356+
NetworkSpec: NetworkSpec{
357+
VPC: VPCSpec{
358+
IPAMPool: &IPAMPool{},
359+
},
360+
},
361+
},
362+
},
363+
wantErr: true,
364+
},
338365
}
339366
for _, tt := range tests {
340367
t.Run(tt.name, func(t *testing.T) {

api/v1beta2/network_types.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,16 +245,36 @@ type NetworkSpec struct {
245245
// IPv6 contains ipv6 specific settings for the network.
246246
type IPv6 struct {
247247
// CidrBlock is the CIDR block provided by Amazon when VPC has enabled IPv6.
248+
// Mutually exclusive with IPAMPool.
248249
// +optional
249250
CidrBlock string `json:"cidrBlock,omitempty"`
250251

251252
// PoolID is the IP pool which must be defined in case of BYO IP is defined.
253+
// Must be specified if CidrBlock is set.
254+
// Mutually exclusive with IPAMPool.
252255
// +optional
253256
PoolID string `json:"poolId,omitempty"`
254257

255258
// EgressOnlyInternetGatewayID is the id of the egress only internet gateway associated with an IPv6 enabled VPC.
256259
// +optional
257260
EgressOnlyInternetGatewayID *string `json:"egressOnlyInternetGatewayId,omitempty"`
261+
262+
// IPAMPool defines the IPAMv6 pool to be used for VPC.
263+
// Mutually exclusive with CidrBlock.
264+
// +optional
265+
IPAMPool *IPAMPool `json:"ipamPool,omitempty"`
266+
}
267+
268+
// IPAMPool defines the IPAM pool to be used for VPC.
269+
type IPAMPool struct {
270+
// ID is the ID of the IPAM pool this provider should use to create VPC.
271+
ID string `json:"id,omitempty"`
272+
// Name is the name of the IPAM pool this provider should use to create VPC.
273+
Name string `json:"name,omitempty"`
274+
// The netmask length of the IPv4 CIDR you want to allocate to VPC from
275+
// an Amazon VPC IP Address Manager (IPAM) pool.
276+
// Defaults to /16 for IPv4 if not specified.
277+
NetmaskLength int64 `json:"netmaskLength,omitempty"`
258278
}
259279

260280
// VPCSpec configures an AWS VPC.
@@ -264,8 +284,13 @@ type VPCSpec struct {
264284

265285
// CidrBlock is the CIDR block to be used when the provider creates a managed VPC.
266286
// Defaults to 10.0.0.0/16.
287+
// Mutually exclusive with IPAMPool.
267288
CidrBlock string `json:"cidrBlock,omitempty"`
268289

290+
// IPAMPool defines the IPAMv4 pool to be used for VPC.
291+
// Mutually exclusive with CidrBlock.
292+
IPAMPool *IPAMPool `json:"ipamPool,omitempty"`
293+
269294
// IPv6 contains ipv6 specific settings for the network. Supported only in managed clusters.
270295
// This field cannot be set on AWSCluster object.
271296
// +optional

api/v1beta2/zz_generated.deepcopy.go

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ func (t Template) ControllersPolicy() *iamv1.PolicyDocument {
8181
Effect: iamv1.EffectAllow,
8282
Resource: iamv1.Resources{iamv1.Any},
8383
Action: iamv1.Actions{
84+
"ec2:DescribeIpamPools",
85+
"ec2:AllocateIpamPoolCidr",
8486
"ec2:AttachNetworkInterface",
8587
"ec2:DetachNetworkInterface",
8688
"ec2:AllocateAddress",

cmd/clusterawsadm/cloudformation/bootstrap/fixtures/customsuffix.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ Resources:
140140
PolicyDocument:
141141
Statement:
142142
- Action:
143+
- ec2:DescribeIpamPools
144+
- ec2:AllocateIpamPoolCidr
143145
- ec2:AttachNetworkInterface
144146
- ec2:DetachNetworkInterface
145147
- ec2:AllocateAddress

cmd/clusterawsadm/cloudformation/bootstrap/fixtures/default.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ Resources:
140140
PolicyDocument:
141141
Statement:
142142
- Action:
143+
- ec2:DescribeIpamPools
144+
- ec2:AllocateIpamPoolCidr
143145
- ec2:AttachNetworkInterface
144146
- ec2:DetachNetworkInterface
145147
- ec2:AllocateAddress

0 commit comments

Comments
 (0)