@@ -17,10 +17,19 @@ limitations under the License.
17
17
package util
18
18
19
19
import (
20
+ "context"
20
21
"fmt"
22
+ "net"
21
23
"net/netip"
22
24
"slices"
23
25
"sync"
26
+
27
+ "k8s.io/apimachinery/pkg/labels"
28
+ "k8s.io/apimachinery/pkg/selection"
29
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
30
+ "sigs.k8s.io/controller-runtime/pkg/client"
31
+
32
+ "github.com/linode/cluster-api-provider-linode/api/v1alpha2"
24
33
)
25
34
26
35
var (
@@ -35,16 +44,52 @@ type ClusterIPs struct {
35
44
ips []string
36
45
}
37
46
38
- func getClusterIPs (key string ) * ClusterIPs {
47
+ func getExistingIPsForCluster (ctx context.Context , clusterName , namespace string , kubeclient client.Client ) ([]string , error ) {
48
+ clusterReq , err := labels .NewRequirement ("cluster.x-k8s.io/cluster-name" , selection .Equals , []string {clusterName })
49
+ if err != nil {
50
+ return nil , fmt .Errorf ("building label selector: %w" , err )
51
+ }
52
+
53
+ selector := labels .NewSelector ()
54
+ selector = selector .Add (* clusterReq )
55
+ var linodeMachineList v1alpha2.LinodeMachineList
56
+ err = kubeclient .List (ctx , & linodeMachineList , & client.ListOptions {Namespace : namespace , LabelSelector : selector })
57
+ if err != nil {
58
+ return nil , fmt .Errorf ("listing all linodeMachines %w" , err )
59
+ }
60
+
61
+ _ , ipnet , err := net .ParseCIDR (vlanIPRange )
62
+ if err != nil {
63
+ return nil , fmt .Errorf ("parsing vlanIPRange: %w" , err )
64
+ }
65
+
66
+ existingIPs := []string {}
67
+ for _ , lm := range linodeMachineList .Items {
68
+ for _ , addr := range lm .Status .Addresses {
69
+ if addr .Type == clusterv1 .MachineInternalIP && ipnet .Contains (net .ParseIP (addr .Address )) {
70
+ existingIPs = append (existingIPs , addr .Address )
71
+ }
72
+ }
73
+ }
74
+ return existingIPs , nil
75
+ }
76
+
77
+ func getClusterIPs (ctx context.Context , clusterName , namespace string , kubeclient client.Client ) (* ClusterIPs , error ) {
78
+ key := fmt .Sprintf ("%s.%s" , namespace , clusterName )
39
79
vlanIPsMu .Lock ()
40
80
defer vlanIPsMu .Unlock ()
41
- ips , exists := vlanIPsMap [key ]
81
+ clusterIps , exists := vlanIPsMap [key ]
42
82
if ! exists {
43
- ips = & ClusterIPs {
44
- ips : []string {},
83
+ ips , err := getExistingIPsForCluster (ctx , clusterName , namespace , kubeclient )
84
+ if err != nil {
85
+ return nil , fmt .Errorf ("getting existingIPs for a cluster: %w" , err )
86
+ }
87
+ clusterIps = & ClusterIPs {
88
+ ips : ips ,
45
89
}
90
+ vlanIPsMap [key ] = clusterIps
46
91
}
47
- return ips
92
+ return clusterIps , nil
48
93
}
49
94
50
95
func (c * ClusterIPs ) getNextIP () string {
@@ -66,10 +111,12 @@ func (c *ClusterIPs) getNextIP() string {
66
111
}
67
112
68
113
// GetNextVlanIP returns the next available IP for a cluster
69
- func GetNextVlanIP (clusterName , namespace string ) string {
70
- key := fmt .Sprintf ("%s.%s" , namespace , clusterName )
71
- clusterIPs := getClusterIPs (key )
72
- return clusterIPs .getNextIP ()
114
+ func GetNextVlanIP (ctx context.Context , clusterName , namespace string , kubeclient client.Client ) (string , error ) {
115
+ clusterIPs , err := getClusterIPs (ctx , clusterName , namespace , kubeclient )
116
+ if err != nil {
117
+ return "" , err
118
+ }
119
+ return clusterIPs .getNextIP (), nil
73
120
}
74
121
75
122
func DeleteClusterIPs (clusterName , namespace string ) {
0 commit comments