Skip to content

Commit ccf0ae2

Browse files
committed
Add subnet allocation logic to client tests
Signed-off-by: Denis Arslanbekov <denis@arslanbekov.com>
1 parent 7962b29 commit ccf0ae2

File tree

1 file changed

+89
-2
lines changed

1 file changed

+89
-2
lines changed

e2e/client_test.go

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package client
22

33
import (
44
"fmt"
5+
"net"
56
"os"
67
"testing"
78
"time"
@@ -49,6 +50,88 @@ func setUpClient(t *testing.T) *cloudconnexa.Client {
4950
return client
5051
}
5152

53+
// cidrOverlaps returns true if two IPv4 networks overlap
54+
func cidrOverlaps(a *net.IPNet, b *net.IPNet) bool {
55+
return a.Contains(b.IP) || b.Contains(a.IP)
56+
}
57+
58+
// parseCIDROrNil parses CIDR string and returns *net.IPNet or nil on error
59+
func parseCIDROrNil(cidr string) *net.IPNet {
60+
_, ipnet, err := net.ParseCIDR(cidr)
61+
if err != nil {
62+
return nil
63+
}
64+
return ipnet
65+
}
66+
67+
// findAvailableIPv4Subnet scans existing networks' routes and system subnets
68+
// and returns an available 10.a.b.0/24 subnet that does not overlap
69+
func findAvailableIPv4Subnet(c *cloudconnexa.Client) (string, error) {
70+
networks, err := c.Networks.List()
71+
if err != nil {
72+
return "", err
73+
}
74+
75+
var used []*net.IPNet
76+
for _, n := range networks {
77+
for _, r := range n.Routes {
78+
if r.Subnet == "" {
79+
continue
80+
}
81+
if ipn := parseCIDROrNil(r.Subnet); ipn != nil {
82+
used = append(used, ipn)
83+
}
84+
}
85+
for _, s := range n.SystemSubnets {
86+
if ipn := parseCIDROrNil(s); ipn != nil {
87+
used = append(used, ipn)
88+
}
89+
}
90+
}
91+
92+
// Prefer high 10.200.0.0/16 space, then sweep remaining 10.0.0.0/8
93+
for a := 200; a <= 254; a++ {
94+
for b := 0; b <= 255; b++ {
95+
candidate := fmt.Sprintf("10.%d.%d.0/24", a, b)
96+
_, ipn, err := net.ParseCIDR(candidate)
97+
if err != nil {
98+
continue
99+
}
100+
overlap := false
101+
for _, u := range used {
102+
if cidrOverlaps(ipn, u) {
103+
overlap = true
104+
break
105+
}
106+
}
107+
if !overlap {
108+
return candidate, nil
109+
}
110+
}
111+
}
112+
for a := 0; a <= 199; a++ {
113+
for b := 0; b <= 255; b++ {
114+
candidate := fmt.Sprintf("10.%d.%d.0/24", a, b)
115+
_, ipn, err := net.ParseCIDR(candidate)
116+
if err != nil {
117+
continue
118+
}
119+
overlap := false
120+
for _, u := range used {
121+
if cidrOverlaps(ipn, u) {
122+
overlap = true
123+
break
124+
}
125+
}
126+
if !overlap {
127+
return candidate, nil
128+
}
129+
}
130+
}
131+
132+
return "", fmt.Errorf("no available /24 subnet found in 10.0.0.0/8")
133+
}
134+
52135
// TestListNetworks tests the retrieval of networks using pagination
53136
// It verifies that networks can be retrieved successfully
54137
func TestListNetworks(t *testing.T) {
@@ -115,10 +198,12 @@ func TestCreateNetwork(t *testing.T) {
115198
Name: testName,
116199
VpnRegionID: "it-mxp",
117200
}
201+
subnet, err := findAvailableIPv4Subnet(c)
202+
require.NoError(t, err)
118203
route := cloudconnexa.Route{
119204
Description: "test",
120205
Type: "IP_V4",
121-
Subnet: fmt.Sprintf("10.%d.%d.0/24", timestamp%256, (timestamp/256)%256),
206+
Subnet: subnet,
122207
}
123208
network := cloudconnexa.Network{
124209
Description: "test",
@@ -131,6 +216,8 @@ func TestCreateNetwork(t *testing.T) {
131216
response, err := c.Networks.Create(network)
132217
require.NoError(t, err)
133218
fmt.Printf("created %s network\n", response.ID)
219+
// Ensure cleanup even if subsequent steps fail
220+
defer func() { _ = c.Networks.Delete(response.ID) }()
134221
test, err := c.Routes.Create(response.ID, route)
135222
require.NoError(t, err)
136223
fmt.Printf("created %s route\n", test.ID)
@@ -139,7 +226,7 @@ func TestCreateNetwork(t *testing.T) {
139226
}
140227
ipServiceRoute := cloudconnexa.IPServiceRoute{
141228
Description: "test",
142-
Value: fmt.Sprintf("10.%d.%d.0/24", timestamp%256, (timestamp/256)%256),
229+
Value: subnet,
143230
}
144231
service := cloudconnexa.IPService{
145232
Name: testName,

0 commit comments

Comments
 (0)