Skip to content

Commit 89096c0

Browse files
committed
Merge branch 'master' of https://github.com/metal-stack/metal-api into dualstack-support
2 parents 1b09d5d + d5e5fcf commit 89096c0

File tree

13 files changed

+169
-140
lines changed

13 files changed

+169
-140
lines changed

cmd/metal-api/internal/datastore/migrations/06_childprefixlength.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package migrations
22

33
import (
4+
"net/netip"
5+
46
r "gopkg.in/rethinkdb/rethinkdb-go.v6"
57

68
"github.com/metal-stack/metal-api/cmd/metal-api/internal/datastore"
@@ -9,6 +11,7 @@ import (
911

1012
func init() {
1113
type tmpPartition struct {
14+
// In theory this might be set in a partition, but in reality its not set anywhere
1215
PrivateNetworkPrefixLength uint8 `rethinkdb:"privatenetworkprefixlength"`
1316
}
1417
datastore.MustRegisterMigration(datastore.Migration{
@@ -31,24 +34,40 @@ func init() {
3134
return err
3235
}
3336

34-
// TODO: does not work somehow
3537
new := old
3638

37-
af, err := metal.GetAddressFamily(new.Prefixes)
39+
var (
40+
af metal.AddressFamily
41+
defaultChildPrefixLength = metal.ChildPrefixLength{}
42+
)
43+
parsed, err := netip.ParsePrefix(new.Prefixes[0].String())
3844
if err != nil {
3945
return err
4046
}
41-
if af != nil {
42-
if new.AddressFamilies == nil {
43-
new.AddressFamilies = make(map[metal.AddressFamily]bool)
44-
}
45-
new.AddressFamilies[*af] = true
47+
if parsed.Addr().Is4() {
48+
af = metal.IPv4AddressFamily
49+
defaultChildPrefixLength[af] = 22
50+
}
51+
if parsed.Addr().Is6() {
52+
af = metal.IPv6AddressFamily
53+
defaultChildPrefixLength[af] = 64
54+
}
55+
56+
if new.AddressFamilies == nil {
57+
new.AddressFamilies = make(map[metal.AddressFamily]bool)
4658
}
59+
new.AddressFamilies[af] = true
60+
4761
if new.PrivateSuper {
4862
if new.DefaultChildPrefixLength == nil {
4963
new.DefaultChildPrefixLength = make(map[metal.AddressFamily]uint8)
5064
}
51-
new.DefaultChildPrefixLength[*af] = partition.PrivateNetworkPrefixLength
65+
if partition.PrivateNetworkPrefixLength > 0 {
66+
new.DefaultChildPrefixLength[af] = partition.PrivateNetworkPrefixLength
67+
} else {
68+
new.DefaultChildPrefixLength = defaultChildPrefixLength
69+
}
70+
5271
}
5372
err = rs.UpdateNetwork(&old, &new)
5473
if err != nil {

cmd/metal-api/internal/datastore/migrations_integration/migrate_integration_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ func Test_MigrationChildPrefixLength(t *testing.T) {
163163
ID: "p2",
164164
PrivateNetworkPrefixLength: 24,
165165
}
166+
p3 = &tmpPartition{
167+
ID: "p3",
168+
}
166169
n1 = &metal.Network{
167170
Base: metal.Base{
168171
ID: "n1",
@@ -193,18 +196,32 @@ func Test_MigrationChildPrefixLength(t *testing.T) {
193196
PartitionID: "p2",
194197
PrivateSuper: false,
195198
}
199+
n4 = &metal.Network{
200+
Base: metal.Base{
201+
ID: "n4",
202+
},
203+
Prefixes: metal.Prefixes{
204+
{IP: "100.1.0.0", Length: "22"},
205+
},
206+
PartitionID: "p3",
207+
PrivateSuper: true,
208+
}
196209
)
197210
_, err = r.DB("metal").Table("partition").Insert(p1).RunWrite(rs.Session())
198211
require.NoError(t, err)
199212
_, err = r.DB("metal").Table("partition").Insert(p2).RunWrite(rs.Session())
200213
require.NoError(t, err)
214+
_, err = r.DB("metal").Table("partition").Insert(p3).RunWrite(rs.Session())
215+
require.NoError(t, err)
201216

202217
err = rs.CreateNetwork(n1)
203218
require.NoError(t, err)
204219
err = rs.CreateNetwork(n2)
205220
require.NoError(t, err)
206221
err = rs.CreateNetwork(n3)
207222
require.NoError(t, err)
223+
err = rs.CreateNetwork(n4)
224+
require.NoError(t, err)
208225

209226
err = rs.Migrate(nil, false)
210227
require.NoError(t, err)
@@ -233,4 +250,11 @@ func Test_MigrationChildPrefixLength(t *testing.T) {
233250
require.NotNil(t, n3fetched)
234251
require.Nil(t, n3fetched.DefaultChildPrefixLength)
235252
require.True(t, n3fetched.AddressFamilies[metal.IPv4AddressFamily])
253+
254+
n4fetched, err := rs.FindNetworkByID(n4.ID)
255+
require.NoError(t, err)
256+
require.NotNil(t, n4fetched)
257+
require.NotNil(t, n4fetched.DefaultChildPrefixLength)
258+
require.True(t, n4fetched.AddressFamilies[metal.IPv4AddressFamily])
259+
require.Equal(t, uint8(22), n4fetched.DefaultChildPrefixLength[metal.IPv4AddressFamily])
236260
}

cmd/metal-api/internal/ipam/ipam.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (i *ipam) AllocateChildPrefix(ctx context.Context, parentPrefix metal.Prefi
5252
Length: uint32(childLength),
5353
}))
5454
if err != nil {
55-
return nil, fmt.Errorf("error creating new prefix in ipam: %w", err)
55+
return nil, fmt.Errorf("error creating new prefix from:%s in ipam: %w", parentPrefix.String(), err)
5656
}
5757

5858
prefix, _, err := metal.NewPrefixFromCIDR(ipamPrefix.Msg.Prefix.Cidr)

cmd/metal-api/internal/metal/network.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package metal
22

33
import (
4-
"fmt"
54
"net"
65
"net/netip"
76
"strconv"
87

9-
"github.com/metal-stack/metal-lib/pkg/pointer"
108
"github.com/samber/lo"
119
)
1210

@@ -351,21 +349,3 @@ func (nics Nics) ByIdentifier() map[string]*Nic {
351349

352350
return res
353351
}
354-
355-
func GetAddressFamily(prefixes Prefixes) (*AddressFamily, error) {
356-
if len(prefixes) == 0 {
357-
return nil, nil
358-
}
359-
360-
parsed, err := netip.ParsePrefix(prefixes[0].String())
361-
if err != nil {
362-
return nil, err
363-
}
364-
if parsed.Addr().Is4() {
365-
return pointer.Pointer(IPv4AddressFamily), nil
366-
}
367-
if parsed.Addr().Is6() {
368-
return pointer.Pointer(IPv6AddressFamily), nil
369-
}
370-
return nil, fmt.Errorf("unable to detect addressfamily from prefixes:%v", prefixes)
371-
}

cmd/metal-api/internal/metal/network_test.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"fmt"
55
"reflect"
66
"testing"
7-
8-
"github.com/metal-stack/metal-lib/pkg/pointer"
97
)
108

119
func TestNics_ByIdentifier(t *testing.T) {
@@ -337,47 +335,3 @@ func TestNicState_SetState(t *testing.T) {
337335
})
338336
}
339337
}
340-
341-
func Test_getAddressFamily(t *testing.T) {
342-
tests := []struct {
343-
name string
344-
prefixes Prefixes
345-
want *AddressFamily
346-
wantErr bool
347-
}{
348-
{
349-
name: "ipv4",
350-
prefixes: Prefixes{{IP: "10.0.0.0", Length: "8"}},
351-
want: pointer.Pointer(IPv4AddressFamily),
352-
},
353-
{
354-
name: "ipv6",
355-
prefixes: Prefixes{{IP: "2001::", Length: "64"}},
356-
want: pointer.Pointer(IPv6AddressFamily),
357-
},
358-
{
359-
name: "empty prefixes",
360-
prefixes: Prefixes{},
361-
want: nil,
362-
wantErr: false,
363-
},
364-
{
365-
name: "malformed ipv4",
366-
prefixes: Prefixes{{IP: "10.0.0.0.0", Length: "6"}},
367-
want: nil,
368-
wantErr: true,
369-
},
370-
}
371-
for _, tt := range tests {
372-
t.Run(tt.name, func(t *testing.T) {
373-
got, err := GetAddressFamily(tt.prefixes)
374-
if (err != nil) != tt.wantErr {
375-
t.Errorf("getAddressFamily() error = %v, wantErr %v", err, tt.wantErr)
376-
return
377-
}
378-
if !reflect.DeepEqual(got, tt.want) {
379-
t.Errorf("getAddressFamily() = %v, want %v", got, tt.want)
380-
}
381-
})
382-
}
383-
}

cmd/metal-api/internal/service/async-actor.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66
"fmt"
77
"log/slog"
88

9+
"connectrpc.com/connect"
910
"github.com/metal-stack/metal-api/cmd/metal-api/internal/headscale"
1011

11-
ipamer "github.com/metal-stack/go-ipam"
1212
"github.com/metal-stack/metal-api/cmd/metal-api/internal/datastore"
1313
"github.com/metal-stack/metal-api/cmd/metal-api/internal/ipam"
1414
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
@@ -216,12 +216,15 @@ func (a *asyncActor) releaseIP(ip metal.IP) error {
216216

217217
// now the IP should not exist any more in our datastore
218218
// so cleanup the ipam
219-
219+
220220
ctx := context.Background()
221221
err = a.ReleaseIP(ctx, ip)
222222
if err != nil {
223-
if errors.Is(err, ipamer.ErrNotFound) {
224-
return nil
223+
var connectErr *connect.Error
224+
if errors.As(err, &connectErr) {
225+
if connectErr.Code() == connect.CodeNotFound {
226+
return nil
227+
}
225228
}
226229
return fmt.Errorf("cannot release IP %q: %w", ip, err)
227230
}

cmd/metal-api/internal/service/ip-service.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ import (
2323

2424
v1 "github.com/metal-stack/metal-api/cmd/metal-api/internal/service/v1"
2525

26-
goipam "github.com/metal-stack/go-ipam"
27-
2826
restfulspec "github.com/emicklei/go-restful-openapi/v2"
2927
restful "github.com/emicklei/go-restful/v3"
3028
"github.com/metal-stack/metal-lib/httperrors"
@@ -289,7 +287,7 @@ func (r *ipResource) allocateIP(request *restful.Request, response *restful.Resp
289287
ok := nw.AddressFamilies[metal.ToAddressFamily(string(*requestPayload.AddressFamily))]
290288
if !ok {
291289
r.sendError(request, response, httperrors.BadRequest(
292-
fmt.Errorf("there is no prefix for the given addressfamily:%s present in this network:%s", string(*requestPayload.AddressFamily), requestPayload.NetworkID)),
290+
fmt.Errorf("there is no prefix for the given addressfamily:%s present in network:%s", string(*requestPayload.AddressFamily), requestPayload.NetworkID)),
293291
)
294292
return
295293
}
@@ -471,10 +469,13 @@ func allocateRandomIP(ctx context.Context, parent *metal.Network, ipamer ipam.IP
471469
}
472470

473471
ipAddress, err = ipamer.AllocateIP(ctx, prefix)
474-
if err != nil && errors.Is(err, goipam.ErrNoIPAvailable) {
475-
continue
476-
}
477472
if err != nil {
473+
var connectErr *connect.Error
474+
if errors.As(err, &connectErr) {
475+
if connectErr.Code() == connect.CodeNotFound {
476+
continue
477+
}
478+
}
478479
return "", "", err
479480
}
480481

cmd/metal-api/internal/service/ip-service_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ func TestAllocateIP(t *testing.T) {
313313
AddressFamily: pointer.Pointer(metal.IPv6AddressFamily),
314314
},
315315
wantedStatus: http.StatusBadRequest,
316-
wantErr: errors.New("there is no prefix for the given addressfamily:IPv6 present in this network:4"),
316+
wantErr: errors.New("there is no prefix for the given addressfamily:IPv6 present in network:4"),
317317
},
318318
}
319319
for i := range tests {

cmd/metal-api/internal/service/machine-service.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,14 @@ func findWaitingMachine(ctx context.Context, ds *datastore.RethinkStore, allocat
13961396
// is enabled to clean up networks that were already created.
13971397
func makeNetworks(ctx context.Context, ds *datastore.RethinkStore, ipamer ipam.IPAMer, allocationSpec *machineAllocationSpec, networks allocationNetworkMap, alloc *metal.MachineAllocation) error {
13981398
for _, n := range networks {
1399+
if n == nil || n.network == nil {
1400+
continue
1401+
}
1402+
if len(n.network.AddressFamilies) == 0 {
1403+
n.network.AddressFamilies = metal.AddressFamilies{
1404+
metal.IPv4AddressFamily: true,
1405+
}
1406+
}
13991407
machineNetwork, err := makeMachineNetwork(ctx, ds, ipamer, allocationSpec, n)
14001408
if err != nil {
14011409
return err
@@ -1472,10 +1480,12 @@ func gatherNetworksFromSpec(ds *datastore.RethinkStore, allocationSpec *machineA
14721480
// - user specifies administrative networks, i.e. underlay or privatesuper networks
14731481
// - user's private network is specified with noauto but no specific IPs are given: this would yield a machine with no ip address
14741482

1475-
specNetworks := make(map[string]*allocationNetwork)
1476-
var primaryPrivateNetwork *allocationNetwork
1477-
var privateNetworks []*allocationNetwork
1478-
var privateSharedNetworks []*allocationNetwork
1483+
var (
1484+
specNetworks = make(map[string]*allocationNetwork)
1485+
primaryPrivateNetwork *allocationNetwork
1486+
privateNetworks []*allocationNetwork
1487+
privateSharedNetworks []*allocationNetwork
1488+
)
14791489

14801490
for _, networkSpec := range allocationSpec.Networks {
14811491
auto := true

0 commit comments

Comments
 (0)