Skip to content

Commit d988356

Browse files
authored
Move lb frontend port definition from ScalewayCluster to Cluster (#29) (#30)
Move lb port definition from ScalewayCluster to Cluster Signed-off-by: Damien DASSIEU <[email protected]>
1 parent 1caa5a2 commit d988356

12 files changed

+143
-56
lines changed

.github/workflows/test-e2e.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ name: E2E Tests
33
on:
44
pull_request:
55
branches: [ "main" ]
6+
workflow_dispatch:
7+
branches: [ "main" ]
68

79
jobs:
810
test-e2e:
911
name: Run on Ubuntu
1012
runs-on: ubuntu-latest
13+
timeout-minutes: 40
1114
steps:
1215
- name: Clone the code
1316
uses: actions/checkout@v4

api/v1alpha1/scalewaycluster_types.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const ClusterFinalizer = "scalewaycluster.infrastructure.cluster.x-k8s.io/sc-pro
1515
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.controlPlanePrivateDNS)) == (has(oldSelf.network) && has(oldSelf.network.controlPlanePrivateDNS))",message="controlPlanePrivateDNS cannot be added or removed"
1616
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.privateNetwork)) == (has(oldSelf.network) && has(oldSelf.network.privateNetwork))",message="privateNetwork cannot be added or removed"
1717
//
18-
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.controlPlaneLoadBalancer) && has(self.network.controlPlaneLoadBalancer.port)) == (has(oldSelf.network) && has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.port))",message="port cannot be added or removed"
1918
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.controlPlaneLoadBalancer) && has(self.network.controlPlaneLoadBalancer.private)) == (has(oldSelf.network) && has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.private))",message="private cannot be added or removed"
2019
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.controlPlaneLoadBalancer) && has(self.network.controlPlaneLoadBalancer.ip)) == (has(oldSelf.network) && has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.ip))",message="ip cannot be added or removed"
2120
// +kubebuilder:validation:XValidation:rule="(has(self.network) && has(self.network.controlPlaneLoadBalancer) && has(self.network.controlPlaneLoadBalancer.zone)) == (has(oldSelf.network) && has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.zone))",message="zone cannot be added or removed"
@@ -127,12 +126,6 @@ type ControlPlaneLoadBalancerSpec struct {
127126
// +kubebuilder:validation:XValidation:rule="!has(oldSelf.privateIP) || self.privateIP == oldSelf.privateIP",message="privateIP is immutable"
128127
LoadBalancerSpec `json:",inline"`
129128

130-
// Port configured on the Load Balancer. It must be valid port range (1-65535).
131-
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
132-
// +kubebuilder:validation:Minimum=1
133-
// +kubebuilder:validation:Maximum=65535
134-
Port *int32 `json:"port,omitempty"`
135-
136129
// AllowedRanges allows to set a list of allowed IP ranges that can access
137130
// the cluster through the loadbalancer. When unset, all IP ranges are allowed.
138131
// To allow the cluster to work properly, public IPs of nodes and Public

api/v1alpha1/zz_generated.deepcopy.go

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

config/crd/bases/infrastructure.cluster.x-k8s.io_scalewayclusters.yaml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,6 @@ spec:
170170
description: IP to use when creating a loadbalancer.
171171
format: ipv4
172172
type: string
173-
port:
174-
description: Port configured on the Load Balancer. It must
175-
be valid port range (1-65535).
176-
format: int32
177-
maximum: 65535
178-
minimum: 1
179-
type: integer
180-
x-kubernetes-validations:
181-
- message: Value is immutable
182-
rule: self == oldSelf
183173
private:
184174
description: Private disables the creation of a public IP
185175
on the LoadBalancers when it's set to true.
@@ -360,10 +350,6 @@ spec:
360350
- message: privateNetwork cannot be added or removed
361351
rule: (has(self.network) && has(self.network.privateNetwork)) == (has(oldSelf.network)
362352
&& has(oldSelf.network.privateNetwork))
363-
- message: port cannot be added or removed
364-
rule: (has(self.network) && has(self.network.controlPlaneLoadBalancer)
365-
&& has(self.network.controlPlaneLoadBalancer.port)) == (has(oldSelf.network)
366-
&& has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.port))
367353
- message: private cannot be added or removed
368354
rule: (has(self.network) && has(self.network.controlPlaneLoadBalancer)
369355
&& has(self.network.controlPlaneLoadBalancer.private)) == (has(oldSelf.network)

config/crd/bases/infrastructure.cluster.x-k8s.io_scalewayclustertemplates.yaml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,16 +170,6 @@ spec:
170170
description: IP to use when creating a loadbalancer.
171171
format: ipv4
172172
type: string
173-
port:
174-
description: Port configured on the Load Balancer.
175-
It must be valid port range (1-65535).
176-
format: int32
177-
maximum: 65535
178-
minimum: 1
179-
type: integer
180-
x-kubernetes-validations:
181-
- message: Value is immutable
182-
rule: self == oldSelf
183173
private:
184174
description: Private disables the creation of a public
185175
IP on the LoadBalancers when it's set to true.
@@ -362,10 +352,6 @@ spec:
362352
- message: privateNetwork cannot be added or removed
363353
rule: (has(self.network) && has(self.network.privateNetwork))
364354
== (has(oldSelf.network) && has(oldSelf.network.privateNetwork))
365-
- message: port cannot be added or removed
366-
rule: (has(self.network) && has(self.network.controlPlaneLoadBalancer)
367-
&& has(self.network.controlPlaneLoadBalancer.port)) == (has(oldSelf.network)
368-
&& has(oldSelf.network.controlPlaneLoadBalancer) && has(oldSelf.network.controlPlaneLoadBalancer.port))
369355
- message: private cannot be added or removed
370356
rule: (has(self.network) && has(self.network.controlPlaneLoadBalancer)
371357
&& has(self.network.controlPlaneLoadBalancer.private)) ==

docs/scalewaycluster.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,28 @@ For more information about private DNS, please refer to the [Understanding Scale
151151
When creating a `ScalewayCluster`, a "main" Load Balancer is always created.
152152
It is also possible to specify "extra" Load Balancers to achieve regional redundancy.
153153

154+
#### Frontend API server port
155+
156+
The kube-apiserver Load Balancer's frontend port can be set at the cluster creation in the `Cluster` object.
157+
158+
Here is an example of a Load Balancer frontend port configuration:
159+
160+
```yaml
161+
apiVersion: cluster.x-k8s.io/v1beta1
162+
kind: Cluster
163+
metadata:
164+
name: my-cluster
165+
namespace: default
166+
spec:
167+
# ...
168+
clusterNetwork:
169+
apiServerPort: 443
170+
# ...
171+
```
172+
173+
- The `apiServerPort` field specifies the port of the Load Balancer frontend that exposes the kube-apiserver(s).
174+
This field should not be changed after the creation of the cluster.
175+
154176
#### Main Load Balancer
155177

156178
The main Load Balancer is always created by default, it is not possible to disable it.
@@ -168,7 +190,6 @@ spec:
168190
network:
169191
controlPlaneLoadBalancer:
170192
type: LB-S
171-
port: 443
172193
zone: fr-par-1
173194
ip: 42.42.42.42 # optional
174195
# private: true
@@ -177,8 +198,6 @@ spec:
177198
```
178199

179200
- The `type` field can be updated to migrate the Load Balancer to another type.
180-
- The `port` field specifies the port of the Load Balancer frontend that exposes the kube-apiserver(s).
181-
This field is immutable.
182201
- The `zone` field specifies where the Load Balancer will be created. Must be in the same region
183202
as the `ScalewayCluster` region. This defaults to the first availability zone of the region.
184203
This field is immutable.

internal/scope/cluster.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,9 @@ func (c *Cluster) PrivateNetworkID() (string, error) {
129129
func (c *Cluster) ControlPlaneLoadBalancerPort() int32 {
130130
var port int32 = defaultFrontendControlPlanePort
131131

132-
if c.ScalewayCluster.Spec.Network != nil &&
133-
c.ScalewayCluster.Spec.Network.ControlPlaneLoadBalancer != nil &&
134-
c.ScalewayCluster.Spec.Network.ControlPlaneLoadBalancer.Port != nil {
135-
port = *c.ScalewayCluster.Spec.Network.ControlPlaneLoadBalancer.Port
132+
if c.Cluster.Spec.ClusterNetwork != nil &&
133+
c.Cluster.Spec.ClusterNetwork.APIServerPort != nil {
134+
port = *c.Cluster.Spec.ClusterNetwork.APIServerPort
136135
}
137136

138137
return port

internal/scope/cluster_test.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
scwClient "github.com/scaleway/cluster-api-provider-scaleway/internal/service/scaleway/client"
1010
"github.com/scaleway/scaleway-sdk-go/scw"
1111
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
1213
"sigs.k8s.io/cluster-api/util/patch"
1314
)
1415

@@ -311,7 +312,7 @@ func TestCluster_PrivateNetworkID(t *testing.T) {
311312
func TestCluster_ControlPlaneLoadBalancerPort(t *testing.T) {
312313
t.Parallel()
313314
type fields struct {
314-
ScalewayCluster *infrav1.ScalewayCluster
315+
Cluster *clusterv1.Cluster
315316
}
316317
tests := []struct {
317318
name string
@@ -321,19 +322,17 @@ func TestCluster_ControlPlaneLoadBalancerPort(t *testing.T) {
321322
{
322323
name: "empty spec",
323324
fields: fields{
324-
ScalewayCluster: &infrav1.ScalewayCluster{},
325+
Cluster: &clusterv1.Cluster{},
325326
},
326327
want: defaultFrontendControlPlanePort,
327328
},
328329
{
329330
name: "override with 443",
330331
fields: fields{
331-
ScalewayCluster: &infrav1.ScalewayCluster{
332-
Spec: infrav1.ScalewayClusterSpec{
333-
Network: &infrav1.NetworkSpec{
334-
ControlPlaneLoadBalancer: &infrav1.ControlPlaneLoadBalancerSpec{
335-
Port: scw.Int32Ptr(443),
336-
},
332+
Cluster: &clusterv1.Cluster{
333+
Spec: clusterv1.ClusterSpec{
334+
ClusterNetwork: &clusterv1.ClusterNetwork{
335+
APIServerPort: scw.Int32Ptr(443),
337336
},
338337
},
339338
},
@@ -345,7 +344,7 @@ func TestCluster_ControlPlaneLoadBalancerPort(t *testing.T) {
345344
t.Run(tt.name, func(t *testing.T) {
346345
t.Parallel()
347346
c := &Cluster{
348-
ScalewayCluster: tt.fields.ScalewayCluster,
347+
Cluster: tt.fields.Cluster,
349348
}
350349
if got := c.ControlPlaneLoadBalancerPort(); got != tt.want {
351350
t.Errorf("Cluster.ControlPlaneLoadBalancerPort() = %v, want %v", got, tt.want)

internal/service/scaleway/lb/lb_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import (
1717
"github.com/scaleway/scaleway-sdk-go/scw"
1818
"go.uber.org/mock/gomock"
1919
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+
"k8s.io/utils/ptr"
21+
"sigs.k8s.io/cluster-api/api/v1beta1"
2022
)
2123

2224
const (
@@ -69,6 +71,12 @@ func TestService_Reconcile(t *testing.T) {
6971
Namespace: "default",
7072
},
7173
},
74+
Cluster: &v1beta1.Cluster{
75+
ObjectMeta: v1.ObjectMeta{
76+
Name: "cluster",
77+
Namespace: "default",
78+
},
79+
},
7280
},
7381
},
7482
args: args{
@@ -121,6 +129,79 @@ func TestService_Reconcile(t *testing.T) {
121129
g.Expect(c.ScalewayCluster.Status.Network.LoadBalancerIP).To(Equal(scw.StringPtr("42.42.42.42")))
122130
},
123131
},
132+
{
133+
name: "custom public LB, no extra LB, no Private Network, no ACL: create",
134+
fields: fields{
135+
Cluster: &scope.Cluster{
136+
ScalewayCluster: &v1alpha1.ScalewayCluster{
137+
ObjectMeta: v1.ObjectMeta{
138+
Name: "cluster",
139+
Namespace: "default",
140+
},
141+
},
142+
Cluster: &v1beta1.Cluster{
143+
ObjectMeta: v1.ObjectMeta{
144+
Name: "cluster",
145+
Namespace: "default",
146+
},
147+
Spec: v1beta1.ClusterSpec{
148+
ClusterNetwork: &v1beta1.ClusterNetwork{
149+
APIServerPort: ptr.To(int32(4242)),
150+
},
151+
},
152+
},
153+
},
154+
},
155+
args: args{
156+
ctx: context.TODO(),
157+
},
158+
expect: func(i *mock_client.MockInterfaceMockRecorder) {
159+
tags := []string{"caps-namespace=default", "caps-scalewaycluster=cluster"}
160+
161+
// Main LB
162+
i.GetZoneOrDefault(nil).Return(scw.ZoneFrPar1, nil)
163+
i.FindLB(gomock.Any(), scw.ZoneFrPar1, append(tags, CAPSMainLBTag)).Return(nil, client.ErrNoItemFound)
164+
i.CreateLB(gomock.Any(), scw.ZoneFrPar1, "cluster", "LB-S", nil, false, append(tags, CAPSMainLBTag)).Return(&lb.LB{
165+
ID: lbID,
166+
Name: "cluster",
167+
Status: lb.LBStatusReady,
168+
Zone: scw.ZoneFrPar1,
169+
IP: []*lb.IP{{IPAddress: "42.42.42.42"}},
170+
}, nil)
171+
172+
// Extra LBs
173+
i.FindLBs(gomock.Any(), append(tags, CAPSExtraLBTag)).Return([]*lb.LB{}, nil)
174+
175+
// Backend
176+
i.FindBackend(gomock.Any(), scw.ZoneFrPar1, lbID, BackendName).Return(nil, client.ErrNoItemFound)
177+
i.CreateBackend(gomock.Any(), scw.ZoneFrPar1, lbID, BackendName, nil, backendControlPlanePort).Return(&lb.Backend{
178+
ID: backendID,
179+
LB: &lb.LB{
180+
ID: lbID,
181+
Zone: scw.ZoneFrPar1,
182+
},
183+
}, nil)
184+
185+
// Frontend
186+
i.FindFrontend(gomock.Any(), scw.ZoneFrPar1, lbID, FrontendName).Return(nil, client.ErrNoItemFound)
187+
i.CreateFrontend(gomock.Any(), scw.ZoneFrPar1, lbID, FrontendName, backendID, int32(4242)).Return(&lb.Frontend{
188+
ID: frontendID,
189+
LB: &lb.LB{
190+
ID: lbID,
191+
Zone: scw.ZoneFrPar1,
192+
},
193+
}, nil)
194+
195+
// ACL
196+
i.FindLBACLByName(gomock.Any(), scw.ZoneFrPar1, frontendID, allowedRangesACLName).Return(nil, client.ErrNoItemFound)
197+
i.FindLBACLByName(gomock.Any(), scw.ZoneFrPar1, frontendID, publicGatewayACLName).Return(nil, client.ErrNoItemFound)
198+
i.FindLBACLByName(gomock.Any(), scw.ZoneFrPar1, frontendID, denyAllACLName).Return(nil, client.ErrNoItemFound)
199+
},
200+
asserts: func(g *WithT, c *scope.Cluster) {
201+
g.Expect(c.ScalewayCluster.Status.Network).ToNot(BeNil())
202+
g.Expect(c.ScalewayCluster.Status.Network.LoadBalancerIP).To(Equal(scw.StringPtr("42.42.42.42")))
203+
},
204+
},
124205
{
125206
name: "public LB, extra LBs, Private Network, ACL: up-to-date",
126207
fields: fields{
@@ -151,6 +232,12 @@ func TestService_Reconcile(t *testing.T) {
151232
},
152233
},
153234
},
235+
Cluster: &v1beta1.Cluster{
236+
ObjectMeta: v1.ObjectMeta{
237+
Name: "cluster",
238+
Namespace: "default",
239+
},
240+
},
154241
},
155242
},
156243
args: args{

templates/cluster-template-private-network.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ metadata:
44
name: ${CLUSTER_NAME}
55
spec:
66
clusterNetwork:
7+
apiServerPort: ${API_SERVER_PORT:=null}
78
pods:
89
cidrBlocks:
910
- 10.244.0.0/16

0 commit comments

Comments
 (0)