Skip to content

Commit 28a0d9f

Browse files
committed
handle if node used old interface and/of uptime format
1 parent ac45189 commit 28a0d9f

File tree

1 file changed

+130
-6
lines changed

1 file changed

+130
-6
lines changed

node-registrar/pkg/server/handlers.go

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,19 @@ package server
22

33
import (
44
"encoding/base64"
5+
"encoding/json"
56
"errors"
67
"fmt"
8+
"io"
79
"net/http"
10+
"reflect"
811
"strconv"
912
"strings"
1013
"time"
1114

1215
"github.com/gin-gonic/gin"
1316
"github.com/lib/pq"
17+
"github.com/rs/zerolog/log"
1418
"github.com/threefoldtech/tfgrid4-sdk-go/node-registrar/pkg/db"
1519
)
1620

@@ -308,11 +312,37 @@ type NodeRegistrationRequest struct {
308312
func (s Server) registerNodeHandler(c *gin.Context) {
309313
var req NodeRegistrationRequest
310314

311-
if err := c.ShouldBindJSON(&req); err != nil {
315+
bodyBytes, err := io.ReadAll(c.Request.Body)
316+
if err != nil {
312317
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
313318
return
314319
}
315320

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+
316346
ensureOwner(c, req.TwinID)
317347
if c.IsAborted() {
318348
return
@@ -390,12 +420,33 @@ func (s *Server) updateNodeHandler(c *gin.Context) {
390420
return
391421
}
392422

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()})
396426
return
397427
}
398428

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+
399450
updatedNode := db.Node{
400451
FarmID: req.FarmID,
401452
Resources: req.Resources,
@@ -449,12 +500,30 @@ func (s *Server) uptimeReportHandler(c *gin.Context) {
449500
return
450501
}
451502

452-
var req UptimeReportRequest
453-
if err := c.ShouldBindJSON(&req); err != nil {
503+
bodyBytes, err := io.ReadAll(c.Request.Body)
504+
if err != nil {
454505
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
455506
return
456507
}
457508

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+
458527
// Get node
459528
node, err := s.db.GetNode(id)
460529
if err != nil {
@@ -826,3 +895,58 @@ func validateTimestampHint(timestampHint int64) error {
826895

827896
return nil
828897
}
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

Comments
 (0)