@@ -2,15 +2,19 @@ package server
2
2
3
3
import (
4
4
"encoding/base64"
5
+ "encoding/json"
5
6
"errors"
6
7
"fmt"
8
+ "io"
7
9
"net/http"
10
+ "reflect"
8
11
"strconv"
9
12
"strings"
10
13
"time"
11
14
12
15
"github.com/gin-gonic/gin"
13
16
"github.com/lib/pq"
17
+ "github.com/rs/zerolog/log"
14
18
"github.com/threefoldtech/tfgrid4-sdk-go/node-registrar/pkg/db"
15
19
)
16
20
@@ -308,11 +312,37 @@ type NodeRegistrationRequest struct {
308
312
func (s Server ) registerNodeHandler (c * gin.Context ) {
309
313
var req NodeRegistrationRequest
310
314
311
- if err := c .ShouldBindJSON (& req ); err != nil {
315
+ bodyBytes , err := io .ReadAll (c .Request .Body )
316
+ if err != nil {
312
317
c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
313
318
return
314
319
}
315
320
321
+ if err := json .Unmarshal (bodyBytes , & req ); err != nil {
322
+ // try old interfaces format
323
+ node := map [string ]any {}
324
+ if err := json .Unmarshal (bodyBytes , & node ); err != nil {
325
+ log .Info ().Msg ("failed to bind" )
326
+ c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
327
+ return
328
+ }
329
+
330
+ res , err := migrateInterfaces (node , NodeRegistrationRequest {})
331
+ if err != nil {
332
+ log .Info ().Msg ("failed to migrate" )
333
+ c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
334
+ return
335
+ }
336
+ var ok bool
337
+ req , ok = res .(NodeRegistrationRequest )
338
+ if ! ok {
339
+ log .Info ().Msg ("failed to parse" )
340
+ c .JSON (http .StatusInternalServerError , gin.H {"error" : "server failed to migrate node Interface in the request" })
341
+ return
342
+ }
343
+
344
+ }
345
+
316
346
ensureOwner (c , req .TwinID )
317
347
if c .IsAborted () {
318
348
return
@@ -390,12 +420,33 @@ func (s *Server) updateNodeHandler(c *gin.Context) {
390
420
return
391
421
}
392
422
393
- var req UpdateNodeRequest
394
- if err := c . ShouldBindJSON ( & req ); err != nil {
395
- c .AbortWithStatusJSON (http .StatusBadRequest , gin.H {"error" : "invalid request body" })
423
+ bodyBytes , err := io . ReadAll ( c . Request . Body )
424
+ if err != nil {
425
+ c .JSON (http .StatusBadRequest , gin.H {"error" : err . Error () })
396
426
return
397
427
}
398
428
429
+ var req UpdateNodeRequest
430
+ if err := json .Unmarshal (bodyBytes , & req ); err != nil {
431
+ // try old interfaces format
432
+ node := map [string ]any {}
433
+ if err := json .Unmarshal (bodyBytes , & node ); err != nil {
434
+ c .AbortWithStatusJSON (http .StatusBadRequest , gin.H {"error" : "invalid request body" })
435
+ return
436
+ }
437
+ res , err := migrateInterfaces (node , UpdateNodeRequest {})
438
+ if err != nil {
439
+ c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
440
+ return
441
+ }
442
+ var ok bool
443
+ req , ok = res .(UpdateNodeRequest )
444
+ if ! ok {
445
+ c .JSON (http .StatusInternalServerError , gin.H {"error" : "server failed to migrate node Interface in the request" })
446
+ return
447
+ }
448
+ }
449
+
399
450
updatedNode := db.Node {
400
451
FarmID : req .FarmID ,
401
452
Resources : req .Resources ,
@@ -449,12 +500,30 @@ func (s *Server) uptimeReportHandler(c *gin.Context) {
449
500
return
450
501
}
451
502
452
- var req UptimeReportRequest
453
- if err := c . ShouldBindJSON ( & req ); err != nil {
503
+ bodyBytes , err := io . ReadAll ( c . Request . Body )
504
+ if err != nil {
454
505
c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
455
506
return
456
507
}
457
508
509
+ var req UptimeReportRequest
510
+ if err := json .Unmarshal (bodyBytes , & req ); err != nil {
511
+ // try old format
512
+
513
+ type oldReport struct {
514
+ Uptime time.Duration `json:"uptime"`
515
+ Timestamp time.Time `json:"timestamp"`
516
+ }
517
+
518
+ var old oldReport
519
+ if err := json .Unmarshal (bodyBytes , & old ); err != nil {
520
+ c .JSON (http .StatusBadRequest , gin.H {"error" : err .Error ()})
521
+ return
522
+ }
523
+ req .Uptime = uint64 (old .Uptime )
524
+ req .Timestamp = old .Timestamp .Unix ()
525
+ }
526
+
458
527
// Get node
459
528
node , err := s .db .GetNode (id )
460
529
if err != nil {
@@ -826,3 +895,58 @@ func validateTimestampHint(timestampHint int64) error {
826
895
827
896
return nil
828
897
}
898
+
899
+ func migrateInterfaces (node map [string ]any , t interface {}) (any , error ) {
900
+ type oldInterface struct {
901
+ Name string `json:"name"`
902
+ Mac string `json:"mac"`
903
+ IPs string `json:"ips"`
904
+ }
905
+
906
+ var interfaces []db.Interface
907
+ rawInterfaces , ok := node ["interfaces" ].([]interface {})
908
+ if ! ok {
909
+ return nil , fmt .Errorf ("interfaces is not a list" )
910
+ }
911
+
912
+ // Convert []interface{} to []oldInterface safely
913
+ interfaceBytes , err := json .Marshal (rawInterfaces )
914
+ if err != nil {
915
+ return nil , fmt .Errorf ("failed to marshal interfaces: %w" , err )
916
+ }
917
+
918
+ var old []oldInterface
919
+ if err := json .Unmarshal (interfaceBytes , & old ); err != nil {
920
+ return nil , fmt .Errorf ("failed to unmarshal into oldInterface: %w" , err )
921
+ }
922
+
923
+ for _ , i := range old {
924
+ ips := strings .Split (i .IPs , "/" )
925
+ newInterface := db.Interface {
926
+ Name : i .Name ,
927
+ Mac : i .Mac ,
928
+ IPs : ips ,
929
+ }
930
+ interfaces = append (interfaces , newInterface )
931
+ }
932
+
933
+ node ["interfaces" ] = interfaces
934
+ nodeByets , err := json .Marshal (node )
935
+ if err != nil {
936
+ return nil , err
937
+ }
938
+
939
+ switch reflect .TypeOf (t ) {
940
+ case reflect .TypeOf (NodeRegistrationRequest {}):
941
+ var res NodeRegistrationRequest
942
+ err = json .Unmarshal (nodeByets , & res )
943
+ return res , err
944
+
945
+ case reflect .TypeOf (UpdateNodeRequest {}):
946
+ var res UpdateNodeRequest
947
+ err = json .Unmarshal (nodeByets , & res )
948
+ return res , err
949
+ }
950
+
951
+ return nil , errors .New ("unsupported t type" )
952
+ }
0 commit comments