Skip to content

Commit d022925

Browse files
committed
OSASINFRA-4029: loadbalancer: add LoadBalancer controller
Add support for OpenStack Octavia Load Balancer resources. This includes: - LoadBalancer CRD with support for VIP subnet/network/port references - Controller with create, update, delete, and import capabilities - Status reporting with provisioning and operating status - Dependency resolution for Subnet, Network, Port, and Project references - Kuttl tests for create, update, import, and dependency scenarios Closes #619
1 parent 57e1ef5 commit d022925

File tree

70 files changed

+4270
-305
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+4270
-305
lines changed

PROJECT

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ resources:
5656
kind: KeyPair
5757
path: github.com/k-orc/openstack-resource-controller/api/v1alpha1
5858
version: v1alpha1
59+
- api:
60+
crdVersion: v1
61+
namespaced: true
62+
domain: k-orc.cloud
63+
group: openstack
64+
kind: LoadBalancer
65+
path: github.com/k-orc/openstack-resource-controller/api/v1alpha1
66+
version: v1alpha1
5967
- api:
6068
crdVersion: v1
6169
namespaced: true

api/v1alpha1/loadbalancer_types.go

Lines changed: 146 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ limitations under the License.
1616

1717
package v1alpha1
1818

19+
// +kubebuilder:validation:MinLength:=1
20+
// +kubebuilder:validation:MaxLength:=255
21+
type LoadBalancerTag string
22+
1923
// LoadBalancerResourceSpec contains the desired state of the resource.
2024
type LoadBalancerResourceSpec struct {
2125
// name will be the name of the created resource. If not specified, the
@@ -29,20 +33,22 @@ type LoadBalancerResourceSpec struct {
2933
// +optional
3034
Description *string `json:"description,omitempty"`
3135

32-
// subnetRef is a reference to the ORC Subnet which this resource is associated with.
36+
// vipSubnetRef is the subnet on which to allocate the load balancer's address.
3337
// +optional
34-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="subnetRef is immutable"
35-
SubnetRef *KubernetesNameRef `json:"subnetRef,omitempty"`
38+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="vipSubnetRef is immutable"
39+
VipSubnetRef *KubernetesNameRef `json:"vipSubnetRef,omitempty"`
3640

37-
// networkRef is a reference to the ORC Network which this resource is associated with.
41+
// vipNetworkRef is the network on which to allocate the load balancer's address.
3842
// +optional
39-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="networkRef is immutable"
40-
NetworkRef *KubernetesNameRef `json:"networkRef,omitempty"`
43+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="vipNetworkRef is immutable"
44+
VipNetworkRef *KubernetesNameRef `json:"vipNetworkRef,omitempty"`
4145

42-
// portRef is a reference to the ORC Port which this resource is associated with.
46+
// vipPortRef is a reference to a neutron port to use for the VIP. If the port
47+
// has more than one subnet you must specify either vipSubnetRef or vipAddress
48+
// to clarify which address should be used for the VIP.
4349
// +optional
44-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="portRef is immutable"
45-
PortRef *KubernetesNameRef `json:"portRef,omitempty"`
50+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="vipPortRef is immutable"
51+
VipPortRef *KubernetesNameRef `json:"vipPortRef,omitempty"`
4652

4753
// flavorRef is a reference to the ORC Flavor which this resource is associated with.
4854
// +optional
@@ -54,13 +60,33 @@ type LoadBalancerResourceSpec struct {
5460
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="projectRef is immutable"
5561
ProjectRef *KubernetesNameRef `json:"projectRef,omitempty"`
5662

57-
// TODO(scaffolding): Add more types.
58-
// To see what is supported, you can take inspiration from the CreateOpts structure from
59-
// github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/loadbalancers
60-
//
61-
// Until you have implemented mutability for the field, you must add a CEL validation
62-
// preventing the field being modified:
63-
// `// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="<fieldname> is immutable"`
63+
// adminStateUp is the administrative state of the load balancer, which is up (true) or down (false)
64+
// +optional
65+
AdminStateUp *bool `json:"adminStateUp,omitempty"`
66+
67+
// availabilityZone is the availability zone in which to create the load balancer.
68+
// +kubebuilder:validation:MaxLength=255
69+
// +optional
70+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="availabilityZone is immutable"
71+
AvailabilityZone string `json:"availabilityZone,omitempty"`
72+
73+
// provider is the name of the load balancer provider.
74+
// +kubebuilder:validation:MaxLength=255
75+
// +optional
76+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="provider is immutable"
77+
Provider string `json:"provider,omitempty"`
78+
79+
// vipAddress is the specific IP address to use for the VIP (optional).
80+
// If not specified, one is allocated automatically from the subnet.
81+
// +optional
82+
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="vipAddress is immutable"
83+
VipAddress *IPvAny `json:"vipAddress,omitempty"`
84+
85+
// tags is a list of tags which will be applied to the load balancer.
86+
// +kubebuilder:validation:MaxItems:=64
87+
// +listType=set
88+
// +optional
89+
Tags []LoadBalancerTag `json:"tags,omitempty"`
6490
}
6591

6692
// LoadBalancerFilter defines an existing resource by its properties
@@ -76,9 +102,66 @@ type LoadBalancerFilter struct {
76102
// +optional
77103
Description *string `json:"description,omitempty"`
78104

79-
// TODO(scaffolding): Add more types.
80-
// To see what is supported, you can take inspiration from the ListOpts structure from
81-
// github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/loadbalancers
105+
// projectRef is a reference to the ORC Project this resource is associated with.
106+
// Typically, only used by admin.
107+
// +optional
108+
ProjectRef *KubernetesNameRef `json:"projectRef,omitempty"`
109+
110+
// vipSubnetRef filters by the subnet on which the load balancer's address is allocated.
111+
// +optional
112+
VipSubnetRef *KubernetesNameRef `json:"vipSubnetRef,omitempty"`
113+
114+
// vipNetworkRef filters by the network on which the load balancer's address is allocated.
115+
// +optional
116+
VipNetworkRef *KubernetesNameRef `json:"vipNetworkRef,omitempty"`
117+
118+
// vipPortRef filters by the neutron port used for the VIP.
119+
// +optional
120+
VipPortRef *KubernetesNameRef `json:"vipPortRef,omitempty"`
121+
122+
// availabilityZone is the availability zone in which to create the load balancer.
123+
// +kubebuilder:validation:MaxLength=255
124+
// +optional
125+
AvailabilityZone string `json:"availabilityZone,omitempty"`
126+
127+
// provider filters by the name of the load balancer provider.
128+
// +kubebuilder:validation:MaxLength=255
129+
// +optional
130+
Provider string `json:"provider,omitempty"`
131+
132+
// vipAddress filters by the IP address of the load balancer's VIP.
133+
// +kubebuilder:validation:MaxLength=64
134+
// +optional
135+
VipAddress string `json:"vipAddress,omitempty"`
136+
137+
// tags is a list of tags to filter by. If specified, the resource must
138+
// have all of the tags specified to be included in the result.
139+
// +listType=set
140+
// +optional
141+
// +kubebuilder:validation:MaxItems:=64
142+
Tags []LoadBalancerTag `json:"tags,omitempty"`
143+
144+
// tagsAny is a list of tags to filter by. If specified, the resource
145+
// must have at least one of the tags specified to be included in the
146+
// result.
147+
// +listType=set
148+
// +optional
149+
// +kubebuilder:validation:MaxItems:=64
150+
TagsAny []LoadBalancerTag `json:"tagsAny,omitempty"`
151+
152+
// notTags is a list of tags to filter by. If specified, resources which
153+
// contain all of the given tags will be excluded from the result.
154+
// +listType=set
155+
// +optional
156+
// +kubebuilder:validation:MaxItems:=64
157+
NotTags []LoadBalancerTag `json:"notTags,omitempty"`
158+
159+
// notTagsAny is a list of tags to filter by. If specified, resources
160+
// which contain any of the given tags will be excluded from the result.
161+
// +listType=set
162+
// +optional
163+
// +kubebuilder:validation:MaxItems:=64
164+
NotTagsAny []LoadBalancerTag `json:"notTagsAny,omitempty"`
82165
}
83166

84167
// LoadBalancerResourceStatus represents the observed state of the resource.
@@ -93,20 +176,20 @@ type LoadBalancerResourceStatus struct {
93176
// +optional
94177
Description string `json:"description,omitempty"`
95178

96-
// subnetID is the ID of the Subnet to which the resource is associated.
179+
// vipSubnetID is the ID of the Subnet to which the resource is associated.
97180
// +kubebuilder:validation:MaxLength=1024
98181
// +optional
99-
SubnetID string `json:"subnetID,omitempty"`
182+
VipSubnetID string `json:"vipSubnetID,omitempty"`
100183

101-
// networkID is the ID of the Network to which the resource is associated.
184+
// vipNetworkID is the ID of the Network to which the resource is associated.
102185
// +kubebuilder:validation:MaxLength=1024
103186
// +optional
104-
NetworkID string `json:"networkID,omitempty"`
187+
VipNetworkID string `json:"vipNetworkID,omitempty"`
105188

106-
// portID is the ID of the Port to which the resource is associated.
189+
// vipPortID is the ID of the Port to which the resource is associated.
107190
// +kubebuilder:validation:MaxLength=1024
108191
// +optional
109-
PortID string `json:"portID,omitempty"`
192+
VipPortID string `json:"vipPortID,omitempty"`
110193

111194
// flavorID is the ID of the Flavor to which the resource is associated.
112195
// +kubebuilder:validation:MaxLength=1024
@@ -118,7 +201,42 @@ type LoadBalancerResourceStatus struct {
118201
// +optional
119202
ProjectID string `json:"projectID,omitempty"`
120203

121-
// TODO(scaffolding): Add more types.
122-
// To see what is supported, you can take inspiration from the LoadBalancer structure from
123-
// github.com/gophercloud/gophercloud/v2/openstack/loadbalancer/v2/loadbalancers
204+
// adminStateUp is the administrative state of the load balancer,
205+
// which is up (true) or down (false).
206+
// +optional
207+
AdminStateUp *bool `json:"adminStateUp,omitempty"`
208+
209+
// tags is the list of tags on the resource.
210+
// +listType=atomic
211+
// +optional
212+
// +kubebuilder:validation:MaxItems:=64
213+
// +kubebuilder:validation:items:MaxLength=255
214+
Tags []string `json:"tags,omitempty"`
215+
216+
// availabilityZone is the availability zone where the load balancer is located.
217+
// +kubebuilder:validation:MaxLength=1024
218+
// +optional
219+
AvailabilityZone string `json:"availabilityZone,omitempty"`
220+
221+
// provisioningStatus is the provisioning status of the load balancer.
222+
// This value is ACTIVE, PENDING_CREATE or ERROR.
223+
// +kubebuilder:validation:MaxLength=1024
224+
// +optional
225+
ProvisioningStatus string `json:"provisioningStatus,omitempty"`
226+
227+
// operatingStatus is the operating status of the load balancer,
228+
// such as ONLINE or OFFLINE.
229+
// +kubebuilder:validation:MaxLength=1024
230+
// +optional
231+
OperatingStatus string `json:"operatingStatus,omitempty"`
232+
233+
// provider is the name of the load balancer provider.
234+
// +kubebuilder:validation:MaxLength=1024
235+
// +optional
236+
Provider string `json:"provider,omitempty"`
237+
238+
// vipAddress is the IP address of the load balancer's VIP.
239+
// +optional
240+
// +kubebuilder:validation:MaxLength=64
241+
VipAddress string `json:"vipAddress,omitempty"`
124242
}

0 commit comments

Comments
 (0)