Skip to content

Commit c6c9b98

Browse files
committed
RosaNetwork: new CRD & reconciler to provision net infra for ROSA-HCP
1 parent 60649f3 commit c6c9b98

22 files changed

+1147
-12
lines changed

PROJECT

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ resources:
5858
- group: infrastructure
5959
version: v1beta2
6060
kind: AWSManagedCluster
61+
- group: infrastructure
62+
kind: ROSANetwork
63+
version: v1beta2

config/crd/bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,22 @@ spec:
776776
x-kubernetes-validations:
777777
- message: rosaClusterName is immutable
778778
rule: self == oldSelf
779+
rosaNetworkRef:
780+
description: |-
781+
ROSANetworkRef references ROSANetwork custom resource that contains the networking infrastructure
782+
for Rosa HCP cluster
783+
properties:
784+
name:
785+
default: ""
786+
description: |-
787+
Name of the referent.
788+
This field is effectively required, but due to backwards compatibility is
789+
allowed to be empty. Instances of this type with an empty value here are
790+
almost certainly wrong.
791+
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
792+
type: string
793+
type: object
794+
x-kubernetes-map-type: atomic
779795
subnets:
780796
description: |-
781797
The Subnet IDs to use when installing the cluster.
@@ -809,14 +825,12 @@ spec:
809825
to worker instances.
810826
type: string
811827
required:
812-
- availabilityZones
813828
- channelGroup
814829
- installerRoleARN
815830
- oidcID
816831
- region
817832
- rolesRef
818833
- rosaClusterName
819-
- subnets
820834
- supportRoleARN
821835
- version
822836
- versionGate
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.19.0
7+
name: rosanetworks.infrastructure.cluster.x-k8s.io
8+
spec:
9+
group: infrastructure.cluster.x-k8s.io
10+
names:
11+
categories:
12+
- cluster-api
13+
kind: ROSANetwork
14+
listKind: ROSANetworkList
15+
plural: rosanetworks
16+
shortNames:
17+
- rosanet
18+
singular: rosanetwork
19+
scope: Namespaced
20+
versions:
21+
- name: v1beta2
22+
schema:
23+
openAPIV3Schema:
24+
description: ROSANetwork is the schema for the rosanetworks API
25+
properties:
26+
apiVersion:
27+
description: |-
28+
APIVersion defines the versioned schema of this representation of an object.
29+
Servers should convert recognized schemas to the latest internal value, and
30+
may reject unrecognized values.
31+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
32+
type: string
33+
kind:
34+
description: |-
35+
Kind is a string value representing the REST resource this object represents.
36+
Servers may infer this from the endpoint the client submits requests to.
37+
Cannot be updated.
38+
In CamelCase.
39+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
40+
type: string
41+
metadata:
42+
type: object
43+
spec:
44+
description: ROSANetworkSpec defines the desired state of ROSANetwork
45+
properties:
46+
availabilityZoneCount:
47+
default: 1
48+
description: |-
49+
The number of availability zones to be used for creation of the network infrastructure.
50+
You can specify anything between one and four, depending on the chosen AWS region.
51+
type: integer
52+
availabilityZones:
53+
description: |-
54+
The list of availability zones to be used for creation of the network infrastructure.
55+
You can specify anything between one and four valid availability zones from a given region.
56+
Should you specify both the availabilityZoneCount and availabilityZones, the list of availability zones takes preference.
57+
items:
58+
type: string
59+
type: array
60+
cidrBlock:
61+
description: CIDR block to be used for the VPC
62+
format: cidr
63+
type: string
64+
identityRef:
65+
description: |-
66+
IdentityRef is a reference to an identity to be used when reconciling rosa network.
67+
If no identity is specified, the default identity for this controller will be used.
68+
properties:
69+
kind:
70+
description: Kind of the identity.
71+
enum:
72+
- AWSClusterControllerIdentity
73+
- AWSClusterRoleIdentity
74+
- AWSClusterStaticIdentity
75+
type: string
76+
name:
77+
description: Name of the identity.
78+
minLength: 1
79+
type: string
80+
required:
81+
- kind
82+
- name
83+
type: object
84+
region:
85+
description: The AWS region in which the components of ROSA network
86+
infrastruture are to be crated
87+
type: string
88+
stackName:
89+
description: The name of the cloudformation stack under which the
90+
network infrastructure would be created
91+
type: string
92+
stackTags:
93+
additionalProperties:
94+
type: string
95+
description: |-
96+
StackTags is an optional set of tags to add to the created cloudformation stack.
97+
The stack tags will then be automatically applied to the supported AWS resources (VPC, subnets, ...).
98+
type: object
99+
required:
100+
- cidrBlock
101+
- region
102+
- stackName
103+
type: object
104+
status:
105+
description: ROSANetworkStatus defines the observed state of ROSANetwork
106+
properties:
107+
conditions:
108+
description: Conditions specifies the conditions for ROSANetwork
109+
items:
110+
description: Condition defines an observation of a Cluster API resource
111+
operational state.
112+
properties:
113+
lastTransitionTime:
114+
description: |-
115+
lastTransitionTime is the last time the condition transitioned from one status to another.
116+
This should be when the underlying condition changed. If that is not known, then using the time when
117+
the API field changed is acceptable.
118+
format: date-time
119+
type: string
120+
message:
121+
description: |-
122+
message is a human readable message indicating details about the transition.
123+
This field may be empty.
124+
maxLength: 10240
125+
minLength: 1
126+
type: string
127+
reason:
128+
description: |-
129+
reason is the reason for the condition's last transition in CamelCase.
130+
The specific API may choose whether or not this field is considered a guaranteed API.
131+
This field may be empty.
132+
maxLength: 256
133+
minLength: 1
134+
type: string
135+
severity:
136+
description: |-
137+
severity provides an explicit classification of Reason code, so the users or machines can immediately
138+
understand the current situation and act accordingly.
139+
The Severity field MUST be set only when Status=False.
140+
maxLength: 32
141+
type: string
142+
status:
143+
description: status of the condition, one of True, False, Unknown.
144+
type: string
145+
type:
146+
description: |-
147+
type of condition in CamelCase or in foo.example.com/CamelCase.
148+
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions
149+
can be useful (see .node.status.conditions), the ability to deconflict is important.
150+
maxLength: 256
151+
minLength: 1
152+
type: string
153+
required:
154+
- lastTransitionTime
155+
- status
156+
- type
157+
type: object
158+
type: array
159+
resources:
160+
description: Resources created in the cloudformation stack
161+
items:
162+
description: CFResource groups information pertaining to a resource
163+
created as a part of a cloudformation stack
164+
properties:
165+
logicalId:
166+
description: LogicalResourceID of the created resource.
167+
type: string
168+
physicalId:
169+
description: PhysicalResourceID of the created resource.
170+
type: string
171+
reason:
172+
description: Message pertaining to the status of the resource
173+
type: string
174+
resource:
175+
description: 'Type of the created resource: AWS::EC2::VPC, AWS::EC2::Subnet,
176+
...'
177+
type: string
178+
status:
179+
description: 'Status of the resource: CREATE_IN_PROGRESS, CREATE_COMPLETE,
180+
...'
181+
type: string
182+
required:
183+
- logicalId
184+
- physicalId
185+
- reason
186+
- resource
187+
- status
188+
type: object
189+
type: array
190+
subnets:
191+
description: Array of created private, public subnets and availability
192+
zones, grouped by availability zones
193+
items:
194+
description: ROSANetworkSubnet groups public and private subnet
195+
and the availability zone in which the two subnets got created
196+
properties:
197+
availabilityZone:
198+
description: Availability zone of the subnet pair, for example
199+
us-west-2a
200+
type: string
201+
privateSubnet:
202+
description: ID of the private subnet, for example subnet-07a20d6c41af2b725
203+
type: string
204+
publicSubnet:
205+
description: ID of the public subnet, for example subnet-0f7e49a3ce68ff338
206+
type: string
207+
required:
208+
- availabilityZone
209+
- privateSubnet
210+
- publicSubnet
211+
type: object
212+
type: array
213+
type: object
214+
type: object
215+
served: true
216+
storage: true
217+
subresources:
218+
status: {}

config/crd/kustomization.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ resources:
2626
- bases/controlplane.cluster.x-k8s.io_rosacontrolplanes.yaml
2727
- bases/infrastructure.cluster.x-k8s.io_rosaclusters.yaml
2828
- bases/infrastructure.cluster.x-k8s.io_rosamachinepools.yaml
29+
- bases/infrastructure.cluster.x-k8s.io_rosanetworks.yaml
2930
# +kubebuilder:scaffold:crdkustomizeresource
3031

3132
patchesStrategicMerge:
@@ -57,6 +58,7 @@ patchesStrategicMerge:
5758
- patches/cainjection_in_awsmanagedclustertemplates.yaml
5859
- patches/cainjection_in_eksconfigs.yaml
5960
- patches/cainjection_in_eksconfigtemplates.yaml
61+
- patches/cainjection_in_rosanetworks.yaml
6062
# +kubebuilder:scaffold:crdkustomizecainjectionpatch
6163

6264
# [LABEL] To enable label, uncomment all the sections with [LABEL] prefix.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# The following patch adds a directive for certmanager to inject CA into the CRD
2+
# CRD conversion requires k8s 1.13 or later.
3+
apiVersion: apiextensions.k8s.io/v1
4+
kind: CustomResourceDefinition
5+
metadata:
6+
annotations:
7+
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
8+
name: rosanetworks.infrastructure.cluster.x-k8s.io
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# The following patch enables conversion webhook for CRD
2+
# CRD conversion requires k8s 1.13 or later.
3+
apiVersion: apiextensions.k8s.io/v1beta1
4+
kind: CustomResourceDefinition
5+
metadata:
6+
name: rosanetworks.infrastructure.cluster.x-k8s.io
7+
spec:
8+
conversion:
9+
strategy: Webhook
10+
webhookClientConfig:
11+
service:
12+
namespace: system
13+
name: webhook-service
14+
path: /convert

config/rbac/role.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ rules:
176176
- awsfargateprofiles/status
177177
- rosaclusters/status
178178
- rosamachinepools/status
179+
- rosanetworks/status
179180
verbs:
180181
- get
181182
- patch
@@ -197,6 +198,7 @@ rules:
197198
- infrastructure.cluster.x-k8s.io
198199
resources:
199200
- awsmachines
201+
- rosanetworks
200202
verbs:
201203
- create
202204
- delete

controlplane/rosa/api/v1beta2/rosacontrolplane_types.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,14 @@ type RosaControlPlaneSpec struct { //nolint: maligned
9595

9696
// The Subnet IDs to use when installing the cluster.
9797
// SubnetIDs should come in pairs; two per availability zone, one private and one public.
98-
Subnets []string `json:"subnets"`
98+
// +optional
99+
Subnets []string `json:"subnets,omitempty"`
99100

100101
// AvailabilityZones describe AWS AvailabilityZones of the worker nodes.
101102
// should match the AvailabilityZones of the provided Subnets.
102103
// a machinepool will be created for each availabilityZone.
103-
AvailabilityZones []string `json:"availabilityZones"`
104+
// +optional
105+
AvailabilityZones []string `json:"availabilityZones,omitempty"`
104106

105107
// The AWS Region the cluster lives in.
106108
Region string `json:"region"`
@@ -231,6 +233,11 @@ type RosaControlPlaneSpec struct { //nolint: maligned
231233
// ClusterRegistryConfig represents registry config used with the cluster.
232234
// +optional
233235
ClusterRegistryConfig *RegistryConfig `json:"clusterRegistryConfig,omitempty"`
236+
237+
// ROSANetworkRef references ROSANetwork custom resource that contains the networking infrastructure
238+
// for Rosa HCP cluster
239+
// +optional
240+
ROSANetworkRef *corev1.LocalObjectReference `json:"rosaNetworkRef,omitempty"`
234241
}
235242

236243
// RegistryConfig for ROSA-HCP cluster

controlplane/rosa/api/v1beta2/rosacontrolplane_webhook.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ func (*rosaControlPlaneWebhook) ValidateCreate(_ context.Context, obj runtime.Ob
6161
allErrs = append(allErrs, r.validateNetwork()...)
6262
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
6363

64+
if err := r.validateROSANetwork(); err != nil {
65+
allErrs = append(allErrs, err)
66+
}
67+
6468
if len(allErrs) == 0 {
6569
return nil, nil
6670
}
@@ -179,6 +183,23 @@ func (r *ROSAControlPlane) validateExternalAuthProviders() *field.Error {
179183
return nil
180184
}
181185

186+
func (r *ROSAControlPlane) validateROSANetwork() *field.Error {
187+
if r.Spec.ROSANetworkRef != nil {
188+
if r.Spec.Subnets != nil {
189+
return field.Forbidden(field.NewPath("spec.rosaNetworkRef"), "spec.subnets and spec.rosaNetworkRef are mutually exclusive")
190+
}
191+
if r.Spec.AvailabilityZones != nil {
192+
return field.Forbidden(field.NewPath("spec.rosaNetworkRef"), "spec.availabilityZones and spec.rosaNetworkRef are mutually exclusive")
193+
}
194+
}
195+
196+
if r.Spec.ROSANetworkRef == nil && (r.Spec.Subnets == nil || r.Spec.AvailabilityZones == nil) {
197+
return field.Required(field.NewPath("spec.subnets"), "spec.subnets and spec.availabilityZones cannot be empty when spec.rosaNetworkRef is unspecified")
198+
}
199+
200+
return nil
201+
}
202+
182203
// Default implements admission.Defaulter.
183204
func (*rosaControlPlaneWebhook) Default(_ context.Context, obj runtime.Object) error {
184205
r, ok := obj.(*ROSAControlPlane)

controlplane/rosa/api/v1beta2/zz_generated.deepcopy.go

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

0 commit comments

Comments
 (0)