k8s_cluster_api/v1beta1/infrastructure/aws/network.rs
1use super::*;
2
3mod impls;
4
5/// NetworkSpec encapsulates all things related to AWS network.
6#[skip_serializing_none]
7#[derive(Clone, Debug, Default, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct NetworkSpec {
10 /// VPC configuration.
11 // +optional
12 pub vpc: Option<VPCSpec>, // `json:"vpc,omitempty"`
13
14 /// Subnets configuration.
15 // +optional
16 pub subnets: Option<Subnets>, // `json:"subnets,omitempty"`
17
18 /// CNI configuration
19 // +optional
20 pub cni: Option<CNISpec>, // `json:"cni,omitempty"`
21
22 /// SecurityGroupOverrides is an optional set of security groups to use for cluster instances
23 /// This is optional - if not provided new security groups will be created for the cluster
24 // +optional
25 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
26 pub security_group_overrides: BTreeMap<SecurityGroupRole, String>, // `json:"securityGroupOverrides,omitempty"`
27}
28
29/// VPCSpec configures an AWS VPC.
30#[skip_serializing_none]
31#[derive(Clone, Debug, Default, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct VPCSpec {
34 /// ID is the vpc-id of the VPC this provider should use to create resources.
35 pub id: Option<String>, // `json:"id,omitempty"`
36
37 /// CidrBlock is the CIDR block to be used when the provider creates a managed VPC.
38 /// Defaults to 10.0.0.0/16.
39 pub cidr_block: Option<String>, // `json:"cidrBlock,omitempty"`
40
41 /// InternetGatewayID is the id of the internet gateway associated with the VPC.
42 // +optional
43 pub internet_gateway_id: Option<String>, // `json:"internetGatewayId,omitempty"`
44
45 /// Tags is a collection of tags describing the resource.
46 #[serde(default, skip_serializing_if = "Tags::is_empty")]
47 pub tags: Tags, // `json:"tags,omitempty"`
48
49 // AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that
50 // should be used in a region when automatically creating subnets. If a region has more
51 // than this number of AZs then this number of AZs will be picked randomly when creating
52 // default subnets. Defaults to 3
53 // +kubebuilder:default=3
54 // +kubebuilder:validation:Minimum=1
55 pub availability_zone_usage_limit: Option<i64>, // `json:"availabilityZoneUsageLimit,omitempty"`
56
57 // AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs
58 // in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes:
59 // Ordered - selects based on alphabetical order
60 // Random - selects AZs randomly in a region
61 // Defaults to Ordered
62 // +kubebuilder:default=Ordered
63 // +kubebuilder:validation:Enum=Ordered;Random
64 pub availability_zone_selection: Option<AZSelectionScheme>, // `json:"availabilityZoneSelection,omitempty"`
65}
66
67/// NetworkStatus encapsulates AWS networking resources.
68#[skip_serializing_none]
69#[derive(Clone, Debug, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct NetworkStatus {
72 /// SecurityGroups is a map from the role/kind of the security group to its unique name, if any.
73 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
74 pub security_groups: BTreeMap<SecurityGroupRole, SecurityGroup>, // `json:"securityGroups,omitempty"`
75
76 /// APIServerELB is the Kubernetes api server classic load balancer.
77 pub api_server_elb: Option<ClassicELB>, // `json:"apiServerElb,omitempty"`
78}
79
80/// ClassicELBScheme defines the scheme of a classic load balancer.
81#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
82pub enum ClassicELBScheme {
83 /// ClassicELBSchemeInternetFacing defines an internet-facing, publicly
84 /// accessible AWS Classic ELB scheme.
85 #[serde(rename = "internet-facing")]
86 InternetFacing,
87
88 /// ClassicELBSchemeInternal defines an internal-only facing
89 /// load balancer internal to an ELB.
90 #[serde(rename = "internal")]
91 Internal,
92
93 /// ClassicELBSchemeIncorrectInternetFacing was inaccurately used to define an internet-facing LB in v0.6 releases > v0.6.6 and v0.7.0 release.
94 #[serde(rename = "Internet-facing")]
95 IncorrectInternetFacing,
96}
97
98/// Subnets is a slice of Subnet.
99#[derive(Clone, Debug, Default, Serialize, Deserialize)]
100pub struct Subnets(pub Vec<SubnetSpec>);
101
102/// SubnetSpec configures an AWS Subnet.
103#[skip_serializing_none]
104#[derive(Clone, Debug, Default, Serialize, Deserialize)]
105#[serde(rename_all = "camelCase")]
106pub struct SubnetSpec {
107 /// ID defines a unique identifier to reference this resource.
108 pub id: Option<String>, // `json:"id,omitempty"`
109
110 /// CidrBlock is the CIDR block to be used when the provider creates a managed VPC.
111 pub cidr_block: Option<String>, // `json:"cidrBlock,omitempty"`
112
113 /// AvailabilityZone defines the availability zone to use for this subnet in the cluster's region.
114 pub availability_zone: Option<String>, // `json:"availabilityZone,omitempty"`
115
116 /// IsPublic defines the subnet as a public subnet. A subnet is public when it is associated with a route table that has a route to an internet gateway.
117 // +optional
118 pub is_public: Option<bool>, // `json:"isPublic"`
119
120 /// RouteTableID is the routing table id associated with the subnet.
121 // +optional
122 pub route_table_id: Option<String>, // `json:"routeTableId,omitempty"`
123
124 /// NatGatewayID is the NAT gateway id associated with the subnet.
125 /// Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet.
126 // +optional
127 pub nat_gateway_id: Option<String>, // `json:"natGatewayId,omitempty"`
128
129 /// Tags is a collection of tags describing the resource.
130 #[serde(default, skip_serializing_if = "Tags::is_empty")]
131 pub tags: Tags, // `json:"tags,omitempty"`
132}
133
134/// CNISpec defines configuration for CNI.
135#[skip_serializing_none]
136#[derive(Clone, Debug, Default, Serialize, Deserialize)]
137#[serde(rename_all = "camelCase")]
138pub struct CNISpec {
139 /// CNIIngressRules specify rules to apply to control plane and worker node security groups.
140 /// The source for the rule will be set to control plane and worker security group IDs.
141 #[serde(default, skip_serializing_if = "Vec::is_empty")]
142 pub cni_ingress_rules: Vec<CNIIngressRule>, // `json:"cniIngressRules,omitempty"`
143}
144
145/// CNIIngressRule defines an AWS ingress rule for CNI requirements.
146#[skip_serializing_none]
147#[derive(Clone, Debug, Serialize, Deserialize)]
148#[serde(rename_all = "camelCase")]
149pub struct CNIIngressRule {
150 pub description: String, // `json:"description"`
151 pub protocol: SecurityGroupProtocol, // `json:"protocol"`
152 pub from_port: i64, // `json:"fromPort"`
153 pub to_port: i64, // `json:"toPort"`
154}
155
156// SecurityGroupProtocol defines the protocol type for a security group rule.
157#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
158pub enum SecurityGroupProtocol {
159 /// SecurityGroupProtocolAll is a wildcard for all IP protocols.
160 #[serde(rename = "-1")]
161 All,
162
163 /// SecurityGroupProtocolIPinIP represents the IP in IP protocol in ingress rules.
164 #[serde(rename = "4")]
165 IPinIP,
166
167 /// SecurityGroupProtocolTCP represents the TCP protocol in ingress rules.
168 #[serde(rename = "tcp")]
169 Tcp,
170
171 /// SecurityGroupProtocolUDP represents the UDP protocol in ingress rules.
172 #[serde(rename = "udp")]
173 Udp,
174
175 /// SecurityGroupProtocolICMP represents the ICMP protocol in ingress rules.
176 #[serde(rename = "icmp")]
177 Icmp,
178
179 /// SecurityGroupProtocolICMPv6 represents the ICMPv6 protocol in ingress rules.
180 #[serde(rename = "58")]
181 Icmpv6,
182}
183
184/// SecurityGroupRole defines the unique role of a security group.
185#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
186pub enum SecurityGroupRole {
187 /// SecurityGroupBastion defines an SSH bastion role.
188 #[serde(rename = "bastion")]
189 Bastion,
190 /// SecurityGroupNode defines a Kubernetes workload node role.
191 #[serde(rename = "node")]
192 Node,
193 /// SecurityGroupEKSNodeAdditional defines an extra node group from eks nodes.
194 #[serde(rename = "node-eks-additional")]
195 EKSNodeAdditional,
196 /// SecurityGroupControlPlane defines a Kubernetes control plane node role.
197 #[serde(rename = "controlplane")]
198 ControlPlane,
199 /// SecurityGroupAPIServerLB defines a Kubernetes API Server Load Balancer role.
200 #[serde(rename = "apiserver-lb")]
201 APIServerLB,
202 /// SecurityGroupLB defines a container for the cloud provider to inject its load balancer ingress rules.
203 #[serde(rename = "lb")]
204 LB,
205}
206
207/// SecurityGroup defines an AWS security group.
208#[skip_serializing_none]
209#[derive(Clone, Debug, Serialize, Deserialize)]
210#[serde(rename_all = "camelCase")]
211pub struct SecurityGroup {
212 /// ID is a unique identifier.
213 pub id: String, // `json:"id"`
214
215 /// Name is the security group name.
216 pub name: String, // `json:"name"`
217
218 /// IngressRules is the inbound rules associated with the security group.
219 // +optional
220 pub ingress_rule: Option<Vec<IngressRule>>, // `json:"ingressRule,omitempty"`
221
222 /// Tags is a map of tags associated with the security group.
223 #[serde(default, skip_serializing_if = "Tags::is_empty")]
224 pub tags: Tags, // `json:"tags,omitempty"`
225}
226
227/// IngressRule defines an AWS ingress rule for security groups.
228#[skip_serializing_none]
229#[derive(Clone, Debug, Serialize, Deserialize)]
230#[serde(rename_all = "camelCase")]
231pub struct IngressRule {
232 pub description: String, // `json:"description"`
233 pub protocol: SecurityGroupProtocol, // `json:"protocol"`
234 pub from_port: i64, // `json:"fromPort"`
235 pub to_port: i64, // `json:"toPort"`
236
237 /// List of CIDR blocks to allow access from. Cannot be specified with SourceSecurityGroupID.
238 // +optional
239 pub cidr_blocks: Option<Vec<String>>, // `json:"cidrBlocks,omitempty"`
240
241 /// The security group id to allow access from. Cannot be specified with CidrBlocks.
242 // +optional
243 pub source_security_group_ids: Option<Vec<String>>, // `json:"sourceSecurityGroupIds,omitempty"`
244}
245
246// ClassicELB defines an AWS classic load balancer.
247#[skip_serializing_none]
248#[derive(Clone, Debug, Serialize, Deserialize)]
249#[serde(rename_all = "camelCase")]
250pub struct ClassicELB {
251 /// The name of the load balancer. It must be unique within the set of load balancers
252 /// defined in the region. It also serves as identifier.
253 pub name: Option<String>, // `json:"name,omitempty"`
254
255 /// DNSName is the dns name of the load balancer.
256 pub dns_name: Option<String>, // `json:"dnsName,omitempty"`
257
258 /// Scheme is the load balancer scheme, either internet-facing or private.
259 pub scheme: Option<ClassicELBScheme>, // `json:"scheme,omitempty"`
260
261 /// AvailabilityZones is an array of availability zones in the VPC attached to the load balancer.
262 #[serde(default, skip_serializing_if = "Vec::is_empty")]
263 pub availability_zones: Vec<String>, // `json:"availabilityZones,omitempty"`
264
265 /// SubnetIDs is an array of subnets in the VPC attached to the load balancer.
266 #[serde(default, skip_serializing_if = "Vec::is_empty")]
267 pub subnet_ids: Vec<String>, // `json:"subnetIds,omitempty"`
268
269 /// SecurityGroupIDs is an array of security groups assigned to the load balancer.
270 #[serde(default, skip_serializing_if = "Vec::is_empty")]
271 pub security_group_ids: Vec<String>, // `json:"securityGroupIds,omitempty"`
272
273 /// Listeners is an array of classic elb listeners associated with the load balancer. There must be at least one.
274 #[serde(default, skip_serializing_if = "Vec::is_empty")]
275 pub listeners: Vec<ClassicELBListener>, // `json:"listeners,omitempty"`
276
277 /// HealthCheck is the classic elb health check associated with the load balancer.
278 pub health_check: Option<ClassicELBHealthCheck>, // `json:"healthChecks,omitempty"`
279
280 /// Attributes defines extra attributes associated with the load balancer.
281 pub attributes: Option<ClassicELBAttributes>, // `json:"attributes,omitempty"`
282
283 /// Tags is a map of tags associated with the load balancer.
284 #[serde(default, skip_serializing_if = "Tags::is_empty")]
285 pub tags: Tags, // `json:"tags,omitempty"`
286}
287
288/// ClassicELBListener defines an AWS classic load balancer listener.
289#[skip_serializing_none]
290#[derive(Clone, Debug, Serialize, Deserialize)]
291#[serde(rename_all = "camelCase")]
292pub struct ClassicELBListener {
293 pub protocol: ClassicELBProtocol, // `json:"protocol"`
294 pub port: i64, // `json:"port"`
295 pub instance_protocol: ClassicELBProtocol, // `json:"instanceProtocol"`
296 pub instance_port: i64, // `json:"instancePort"`
297}
298
299/// ClassicELBProtocol defines listener protocols for a classic load balancer.
300#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
301pub enum ClassicELBProtocol {
302 /// ClassicELBProtocolTCP defines the ELB API string representing the TCP protocol.
303 #[serde(rename = "TCP")]
304 Tcp,
305 /// ClassicELBProtocolSSL defines the ELB API string representing the TLS protocol.
306 #[serde(rename = "SSL")]
307 Ssl,
308 /// ClassicELBProtocolHTTP defines the ELB API string representing the HTTP protocol at L7.
309 #[serde(rename = "HTTP")]
310 Http,
311 /// ClassicELBProtocolHTTPS defines the ELB API string representing the HTTPS protocol at L7.
312 #[serde(rename = "HTTPS")]
313 Https,
314}
315
316/// ClassicELBHealthCheck defines an AWS classic load balancer health check.
317#[serde_as]
318#[skip_serializing_none]
319#[derive(Clone, Debug, Serialize, Deserialize)]
320#[serde(rename_all = "camelCase")]
321pub struct ClassicELBHealthCheck {
322 pub target: String, // `json:"target"`
323 #[serde_as(as = "serde_with::DurationSeconds<i64>")]
324 pub interval: chrono::Duration, // `json:"interval"`
325 #[serde_as(as = "serde_with::DurationSeconds<i64>")]
326 pub timeout: chrono::Duration, // `json:"timeout"`
327 pub healthy_threshold: i64, // `json:"healthyThreshold"`
328 pub unhealthy_threshold: i64, // `json:"unhealthyThreshold"`
329}
330
331/// ClassicELBAttributes defines extra attributes associated with a classic load balancer.
332// #[serde_as]
333#[skip_serializing_none]
334#[derive(Clone, Debug, Serialize, Deserialize)]
335#[serde(rename_all = "camelCase")]
336pub struct ClassicELBAttributes {
337 /// IdleTimeout is time that the connection is allowed to be idle (no data
338 /// has been sent over the connection) before it is closed by the load balancer.
339 // #[serde_as(as = "serde_with::DurationSeconds<i64>")]
340 pub idle_timeout: Option<i64>, // `json:"idleTimeout,omitempty"`
341
342 /// CrossZoneLoadBalancing enables the classic load balancer load balancing.
343 // +optional
344 pub cross_zone_load_balancing: Option<bool>, // `json:"crossZoneLoadBalancing,omitempty"`
345}
346
347/* ============================================================================
348package v1beta1
349
350import (
351 "fmt"
352 "sort"
353 "time"
354)
355
356
357func (e ClassicELBScheme) String() string {
358 return string(e)
359}
360
361// IsUnmanaged returns true if the Classic ELB is unmanaged.
362func (b *ClassicELB) IsUnmanaged(clusterName string) bool {
363 return b.Name != "" && !Tags(b.Tags).HasOwned(clusterName)
364}
365
366// IsManaged returns true if Classic ELB is managed.
367func (b *ClassicELB) IsManaged(clusterName string) bool {
368 return !b.IsUnmanaged(clusterName)
369}
370
371
372
373// String returns a string representation of the VPC.
374func (v *VPCSpec) String() string {
375 return fmt.Sprintf("id=%s", v.ID)
376}
377
378// IsUnmanaged returns true if the VPC is unmanaged.
379func (v *VPCSpec) IsUnmanaged(clusterName string) bool {
380 return v.ID != "" && !v.Tags.HasOwned(clusterName)
381}
382
383// IsManaged returns true if VPC is managed.
384func (v *VPCSpec) IsManaged(clusterName string) bool {
385 return !v.IsUnmanaged(clusterName)
386}
387
388
389// String returns a string representation of the subnet.
390func (s *SubnetSpec) String() string {
391 return fmt.Sprintf("id=%s/az=%s/public=%v", s.ID, s.AvailabilityZone, s.IsPublic)
392}
393
394// ToMap returns a map from id to subnet.
395func (s Subnets) ToMap() map[string]*SubnetSpec {
396 res := make(map[string]*SubnetSpec)
397 for i := range s {
398 x := s[i]
399 res[x.ID] = &x
400 }
401 return res
402}
403
404// IDs returns a slice of the subnet ids.
405func (s Subnets) IDs() []string {
406 res := []string{}
407 for _, subnet := range s {
408 res = append(res, subnet.ID)
409 }
410 return res
411}
412
413// FindByID returns a single subnet matching the given id or nil.
414func (s Subnets) FindByID(id string) *SubnetSpec {
415 for _, x := range s {
416 if x.ID == id {
417 return &x
418 }
419 }
420
421 return nil
422}
423
424// FindEqual returns a subnet spec that is equal to the one passed in.
425// Two subnets are defined equal to each other if their id is equal
426// or if they are in the same vpc and the cidr block is the same.
427func (s Subnets) FindEqual(spec *SubnetSpec) *SubnetSpec {
428 for _, x := range s {
429 if (spec.ID != "" && x.ID == spec.ID) || (spec.CidrBlock == x.CidrBlock) {
430 return &x
431 }
432 }
433 return nil
434}
435
436// FilterPrivate returns a slice containing all subnets marked as private.
437func (s Subnets) FilterPrivate() (res Subnets) {
438 for _, x := range s {
439 if !x.IsPublic {
440 res = append(res, x)
441 }
442 }
443 return
444}
445
446// FilterPublic returns a slice containing all subnets marked as public.
447func (s Subnets) FilterPublic() (res Subnets) {
448 for _, x := range s {
449 if x.IsPublic {
450 res = append(res, x)
451 }
452 }
453 return
454}
455
456// FilterByZone returns a slice containing all subnets that live in the availability zone specified.
457func (s Subnets) FilterByZone(zone string) (res Subnets) {
458 for _, x := range s {
459 if x.AvailabilityZone == zone {
460 res = append(res, x)
461 }
462 }
463 return
464}
465
466// GetUniqueZones returns a slice containing the unique zones of the subnets.
467func (s Subnets) GetUniqueZones() []string {
468 keys := make(map[string]bool)
469 zones := []string{}
470 for _, x := range s {
471 if _, value := keys[x.AvailabilityZone]; !value {
472 keys[x.AvailabilityZone] = true
473 zones = append(zones, x.AvailabilityZone)
474 }
475 }
476 return zones
477}
478
479// RouteTable defines an AWS routing table.
480type RouteTable struct {
481 ID string `json:"id"`
482}
483
484
485// String returns a string representation of the security group.
486func (s *SecurityGroup) String() string {
487 return fmt.Sprintf("id=%s/name=%s", s.ID, s.Name)
488}
489
490
491
492// String returns a string representation of the ingress rule.
493func (i *IngressRule) String() string {
494 return fmt.Sprintf("protocol=%s/range=[%d-%d]/description=%s", i.Protocol, i.FromPort, i.ToPort, i.Description)
495}
496
497// IngressRules is a slice of AWS ingress rules for security groups.
498type IngressRules []IngressRule
499
500// Difference returns the difference between this slice and the other slice.
501func (i IngressRules) Difference(o IngressRules) (out IngressRules) {
502 for index := range i {
503 x := i[index]
504 found := false
505 for oIndex := range o {
506 y := o[oIndex]
507 if x.Equals(&y) {
508 found = true
509 break
510 }
511 }
512
513 if !found {
514 out = append(out, x)
515 }
516 }
517
518 return
519}
520
521// Equals returns true if two IngressRule are equal.
522func (i *IngressRule) Equals(o *IngressRule) bool {
523 if len(i.CidrBlocks) != len(o.CidrBlocks) {
524 return false
525 }
526
527 sort.Strings(i.CidrBlocks)
528 sort.Strings(o.CidrBlocks)
529
530 for i, v := range i.CidrBlocks {
531 if v != o.CidrBlocks[i] {
532 return false
533 }
534 }
535
536 if len(i.SourceSecurityGroupIDs) != len(o.SourceSecurityGroupIDs) {
537 return false
538 }
539
540 sort.Strings(i.SourceSecurityGroupIDs)
541 sort.Strings(o.SourceSecurityGroupIDs)
542
543 for i, v := range i.SourceSecurityGroupIDs {
544 if v != o.SourceSecurityGroupIDs[i] {
545 return false
546 }
547 }
548
549 if i.Description != o.Description || i.Protocol != o.Protocol {
550 return false
551 }
552
553 // AWS seems to ignore the From/To port when set on protocols where it doesn't apply, but
554 // we avoid serializing it out for clarity's sake.
555 // See: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_IpPermission.html
556 switch i.Protocol {
557 case SecurityGroupProtocolTCP,
558 SecurityGroupProtocolUDP,
559 SecurityGroupProtocolICMP,
560 SecurityGroupProtocolICMPv6:
561 return i.FromPort == o.FromPort && i.ToPort == o.ToPort
562 case SecurityGroupProtocolAll, SecurityGroupProtocolIPinIP:
563 // FromPort / ToPort are not applicable
564 }
565
566 return true
567}
568 ============================================================================ */