diff --git a/go.work.sum b/go.work.sum index f8fbfef..e7d424d 100644 --- a/go.work.sum +++ b/go.work.sum @@ -2,6 +2,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -10,9 +12,10 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vedhavyas/go-subkey v1.0.3 h1:iKR33BB/akKmcR2PMlXPBeeODjWLM90EL98OrOGs8CA= github.com/vedhavyas/go-subkey v1.0.3/go.mod h1:CloUaFQSSTdWnINfBRFjVMkWXZANW+nd8+TI5jYcl6Y= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/node-registrar/client/node.go b/node-registrar/client/node.go index 5bb6854..8a67dbc 100644 --- a/node-registrar/client/node.go +++ b/node-registrar/client/node.go @@ -4,9 +4,11 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net/http" "net/url" "reflect" + "strings" "time" "github.com/pkg/errors" @@ -15,17 +17,8 @@ import ( var ErrorNodeNotFound = fmt.Errorf("failed to get requested node from node registrar") // RegisterNode register physical/virtual nodes with on TFGrid. -func (c *RegistrarClient) RegisterNode( - farmID uint64, - twinID uint64, - interfaces []Interface, - location Location, - resources Resources, - serialNumber string, - secureBoot, - virtualized bool, -) (nodeID uint64, err error) { - return c.registerNode(farmID, twinID, interfaces, location, resources, serialNumber, secureBoot, virtualized) +func (c *RegistrarClient) RegisterNode(node Node) (nodeID uint64, err error) { + return c.registerNode(node) } // UpdateNode update node configuration (farmID, interfaces, resources, location, secureBoot, virtualized). @@ -186,79 +179,78 @@ func UpdateNodeWithHealthy() UpdateNodeOpts { } } -func (c *RegistrarClient) registerNode( - farmID uint64, - twinID uint64, - interfaces []Interface, - location Location, - resources Resources, - serialNumber string, - secureBoot, - virtualized bool, -) (nodeID uint64, err error) { +func (c *RegistrarClient) registerNode(node Node) (nodeID uint64, err error) { err = c.ensureTwinID() if err != nil { return nodeID, errors.Wrap(err, "failed to ensure twin id") } + url, err := url.JoinPath(c.baseURL, "nodes") if err != nil { return nodeID, errors.Wrap(err, "failed to construct registrar url") } - data := Node{ - FarmID: farmID, - TwinID: twinID, - Location: location, - Resources: resources, - Interfaces: interfaces, - SecureBoot: secureBoot, - Virtualized: virtualized, - SerialNumber: serialNumber, - } + handler := func(body bytes.Buffer) (uint64, error) { + req, err := http.NewRequest("POST", url, &body) + if err != nil { + return nodeID, errors.Wrap(err, "failed to construct http request to the registrar") + } - var body bytes.Buffer - err = json.NewEncoder(&body).Encode(data) - if err != nil { - return nodeID, errors.Wrap(err, "failed to encode request body") - } + authHeader, err := c.signRequest(time.Now().Unix()) + if err != nil { + return nodeID, errors.Wrap(err, "failed to sign request") + } + req.Header.Set("X-Auth", authHeader) + req.Header.Set("Content-Type", "application/json") - req, err := http.NewRequest("POST", url, &body) - if err != nil { - return nodeID, errors.Wrap(err, "failed to construct http request to the registrar") - } + resp, err := c.httpClient.Do(req) + if err != nil { + return nodeID, errors.Wrap(err, "failed to send request to registrer the node") + } - authHeader, err := c.signRequest(time.Now().Unix()) - if err != nil { - return nodeID, errors.Wrap(err, "failed to sign request") - } - req.Header.Set("X-Auth", authHeader) - req.Header.Set("Content-Type", "application/json") + if resp == nil { + return 0, errors.New("no response received") + } + defer resp.Body.Close() - resp, err := c.httpClient.Do(req) - if err != nil { - return nodeID, errors.Wrap(err, "failed to send request to registrer the node") - } + if resp.StatusCode != http.StatusCreated { + err = parseResponseError(resp.Body) + return 0, errors.Wrapf(err, "failed to create node on the registrar with status code %s", resp.Status) + } - if resp == nil { - return 0, errors.New("no response received") - } - defer resp.Body.Close() + result := struct { + NodeID uint64 `json:"node_id"` + }{} - if resp.StatusCode != http.StatusCreated { - err = parseResponseError(resp.Body) - return 0, errors.Wrapf(err, "failed to create node on the registrar with status code %s", resp.Status) + err = json.NewDecoder(resp.Body).Decode(&result) + if err != nil { + return 0, errors.Wrap(err, "failed to decode response body") + } + + return result.NodeID, nil } - result := struct { - NodeID uint64 `json:"node_id"` - }{} + var body bytes.Buffer + if err = json.NewEncoder(&body).Encode(node); err != nil { + return 0, err + } - err = json.NewDecoder(resp.Body).Decode(&result) + nodeID, err = handler(body) if err != nil { - return 0, errors.Wrap(err, "failed to decode response body") + // try node with old interface format + body, err := createRequestBodyWithOldInterfaceFormat(node) + if err != nil { + return nodeID, err + } + + nodeID, err = handler(body) + if err != nil { + return nodeID, err + } } - c.nodeID = result.NodeID - return result.NodeID, err + + c.nodeID = nodeID + return nodeID, nil } func (c *RegistrarClient) updateNode(opts []UpdateNodeOpts) (err error) { @@ -279,37 +271,51 @@ func (c *RegistrarClient) updateNode(opts []UpdateNodeOpts) (err error) { node = c.parseUpdateNodeOpts(node, opts) - var body bytes.Buffer - err = json.NewEncoder(&body).Encode(node) - if err != nil { - return errors.Wrap(err, "failed to encode request body") - } - - req, err := http.NewRequest("PATCH", url, &body) - if err != nil { - return errors.Wrap(err, "failed to construct http request to the registrar") - } - - authHeader, err := c.signRequest(time.Now().Unix()) - if err != nil { - return errors.Wrap(err, "failed to sign request") + handler := func(body bytes.Buffer) error { + req, err := http.NewRequest("PATCH", url, &body) + if err != nil { + return errors.Wrap(err, "failed to construct http request to the registrar") + } + + authHeader, err := c.signRequest(time.Now().Unix()) + if err != nil { + return errors.Wrap(err, "failed to sign request") + } + req.Header.Set("X-Auth", authHeader) + req.Header.Set("Content-Type", "application/json") + + resp, err := c.httpClient.Do(req) + if err != nil { + return errors.Wrap(err, "failed to send request to update node") + } + + if resp == nil { + return errors.New("no response received") + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + err = parseResponseError(resp.Body) + return errors.Wrapf(err, "failed to update node with twin id %d with status code %s", c.twinID, resp.Status) + } + return nil } - req.Header.Set("X-Auth", authHeader) - req.Header.Set("Content-Type", "application/json") - resp, err := c.httpClient.Do(req) - if err != nil { - return errors.Wrap(err, "failed to send request to update node") + var body bytes.Buffer + if err = json.NewEncoder(&body).Encode(node); err != nil { + return err } - if resp == nil { - return errors.New("no response received") - } - defer resp.Body.Close() + if err := handler(body); err != nil { + // try update with old interface format + node, err := createRequestBodyWithOldInterfaceFormat(node) + if err != nil { + return err + } - if resp.StatusCode != http.StatusOK { - err = parseResponseError(resp.Body) - return errors.Wrapf(err, "failed to update node with twin id %d with status code %s", c.twinID, resp.Status) + if err := handler(node); err != nil { + return errors.Wrap(err, "failed here") + } } return @@ -326,38 +332,58 @@ func (c *RegistrarClient) reportUptime(report UptimeReport) (err error) { return errors.Wrap(err, "failed to construct registrar url") } - var body bytes.Buffer - - err = json.NewEncoder(&body).Encode(report) - if err != nil { - return errors.Wrap(err, "failed to encode request body") - } - - req, err := http.NewRequest("POST", url, &body) - if err != nil { - return errors.Wrap(err, "failed to construct http request to the registrar") - } - - authHeader, err := c.signRequest(time.Now().Unix()) - if err != nil { - return errors.Wrap(err, "failed to sign request") + handler := func(body bytes.Buffer) error { + req, err := http.NewRequest("POST", url, &body) + if err != nil { + return errors.Wrap(err, "failed to construct http request to the registrar") + } + + authHeader, err := c.signRequest(time.Now().Unix()) + if err != nil { + return errors.Wrap(err, "failed to sign request") + } + req.Header.Set("X-Auth", authHeader) + req.Header.Set("Content-Type", "application/json") + + resp, err := c.httpClient.Do(req) + if err != nil { + return errors.Wrap(err, "failed to send request to update uptime of the node") + } + + if resp == nil { + return errors.New("no response received") + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusCreated { + err = parseResponseError(resp.Body) + return errors.Wrapf(err, "failed to update node uptime for node with id %d with status code %s", c.nodeID, resp.Status) + } + return nil } - req.Header.Set("X-Auth", authHeader) - req.Header.Set("Content-Type", "application/json") - resp, err := c.httpClient.Do(req) - if err != nil { - return errors.Wrap(err, "failed to send request to update uptime of the node") + var body bytes.Buffer + if err = json.NewEncoder(&body).Encode(report); err != nil { + return errors.Wrap(err, "failed to encode request body") } - if resp == nil { - return errors.New("no response received") - } - defer resp.Body.Close() + if err = handler(body); err != nil { + // try old report format time.Duration and time.Time + old := struct { + Uptime time.Duration + Timestamp time.Time + }{ + Uptime: time.Duration(report.Uptime), + Timestamp: time.Now(), + } + var body bytes.Buffer + if err = json.NewEncoder(&body).Encode(old); err != nil { + return errors.Wrap(err, "failed to encode request body") + } - if resp.StatusCode != http.StatusCreated { - err = parseResponseError(resp.Body) - return errors.Wrapf(err, "failed to update node uptime for node with id %d with status code %s", c.nodeID, resp.Status) + if err = handler(body); err != nil { + return err + } } return @@ -388,12 +414,17 @@ func (c *RegistrarClient) getNode(id uint64) (node Node, err error) { return node, errors.Wrapf(err, "failed to get node with status code %s", resp.Status) } - err = json.NewDecoder(resp.Body).Decode(&node) + bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return } - return + err = json.Unmarshal(bodyBytes, &node) + if err == nil { + return + } + + return parseResponseBodyToNewInterfaceFormat(bodyBytes) } func (c *RegistrarClient) getNodeByTwinID(id uint64) (node Node, err error) { @@ -448,11 +479,37 @@ func (c *RegistrarClient) listNodes(opts []ListNodeOpts) (nodes []Node, err erro return nodes, errors.Wrapf(err, "failed to list nodes with with status code %s", resp.Status) } - err = json.NewDecoder(resp.Body).Decode(&nodes) + bodyBytes, err := io.ReadAll(resp.Body) if err != nil { return } + err = json.Unmarshal(bodyBytes, &nodes) + if err == nil { + return + } + + // try old interface format + var rawNodes []interface{} + err = json.Unmarshal(bodyBytes, &rawNodes) + if err != nil { + return + } + + for _, node := range rawNodes { + nodeBytes, err := json.Marshal(node) + if err != nil { + return nodes, err + } + + node, err := parseResponseBodyToNewInterfaceFormat(nodeBytes) + if err != nil { + return nodes, errors.Wrap(err, "failed to get nodes with old interface format") + } + + nodes = append(nodes, node) + } + return nodes, nil } @@ -561,3 +618,94 @@ func parseListNodeOpts(opts []ListNodeOpts) map[string]any { return data } + +type oldInterfaceFormat struct { + Name string `json:"name"` + Mac string `json:"mac"` + IPs string `json:"ips"` +} + +type oldFormatNodeType struct { + Interfaces []oldInterfaceFormat `json:"interfaces"` + + NodeID uint64 `json:"node_id"` + FarmID uint64 `json:"farm_id"` + TwinID uint64 `json:"twin_id"` + Location Location `json:"location"` + Resources Resources `json:"resources"` + SecureBoot bool `json:"secure_boot"` + Virtualized bool `json:"virtualized"` + SerialNumber string `json:"serial_number"` + LastSeen *time.Time `json:"last_seen"` + Online bool `json:"online"` + Approved bool +} + +func createRequestBodyWithOldInterfaceFormat(node Node) (body bytes.Buffer, err error) { + var oldInterfaces []oldInterfaceFormat + interfaces := node.Interfaces + for _, i := range interfaces { + old := oldInterfaceFormat{ + Name: i.Name, + Mac: i.Mac, + IPs: strings.Join(i.IPs, "/"), + } + oldInterfaces = append(oldInterfaces, old) + } + + oldFormatNode := oldFormatNodeType{ + Interfaces: oldInterfaces, + + NodeID: node.NodeID, + FarmID: node.FarmID, + TwinID: node.TwinID, + Location: node.Location, + Resources: node.Resources, + SecureBoot: node.SecureBoot, + Virtualized: node.Virtualized, + SerialNumber: node.SerialNumber, + LastSeen: node.LastSeen, + Online: node.Online, + Approved: node.Approved, + } + + err = json.NewEncoder(&body).Encode(oldFormatNode) + if err != nil { + return + } + + return +} + +func parseResponseBodyToNewInterfaceFormat(nodeBytes []byte) (Node, error) { + var oldFormatNode oldFormatNodeType + err := json.Unmarshal(nodeBytes, &oldFormatNode) + if err != nil { + return Node{}, err + } + + var newFormat []Interface + for _, i := range oldFormatNode.Interfaces { + ips := strings.Split(i.IPs, "/") + newFormat = append(newFormat, Interface{ + Name: i.Name, + Mac: i.Mac, + IPs: ips, + }) + } + return Node{ + Interfaces: newFormat, + + NodeID: oldFormatNode.NodeID, + FarmID: oldFormatNode.FarmID, + TwinID: oldFormatNode.TwinID, + Location: oldFormatNode.Location, + Resources: oldFormatNode.Resources, + SecureBoot: oldFormatNode.SecureBoot, + Virtualized: oldFormatNode.Virtualized, + SerialNumber: oldFormatNode.SerialNumber, + LastSeen: oldFormatNode.LastSeen, + Online: oldFormatNode.Online, + Approved: oldFormatNode.Approved, + }, nil +} diff --git a/node-registrar/client/node_test.go b/node-registrar/client/node_test.go index 4d539a2..bbac795 100644 --- a/node-registrar/client/node_test.go +++ b/node-registrar/client/node_test.go @@ -15,6 +15,11 @@ func TestRegistarNode(t *testing.T) { var count int require := require.New(t) + node := Node{ + TwinID: twinID, + FarmID: farmID, + } + testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { statusCode, body := serverHandler(r, request, count, require) w.WriteHeader(statusCode) @@ -33,7 +38,7 @@ func TestRegistarNode(t *testing.T) { require.NoError(err) request = registerNodeWithNoAccount - _, err = c.RegisterNode(farmID, twinID, []Interface{}, Location{}, Resources{}, "", false, false) + _, err = c.RegisterNode(node) require.Error(err) }) @@ -45,7 +50,7 @@ func TestRegistarNode(t *testing.T) { count = 0 request = registerNodeStatusConflict - _, err = c.RegisterNode(farmID, twinID, []Interface{}, Location{}, Resources{}, "", false, false) + _, err = c.RegisterNode(node) require.Error(err) }) @@ -57,7 +62,7 @@ func TestRegistarNode(t *testing.T) { count = 0 request = registerNodeStatusCreated - result, err := c.RegisterNode(farmID, twinID, []Interface{}, Location{}, Resources{}, "", false, false) + result, err := c.RegisterNode(node) require.NoError(err) require.Equal(nodeID, result) }) diff --git a/node-registrar/client/types.go b/node-registrar/client/types.go index 94e98e5..5c150d4 100644 --- a/node-registrar/client/types.go +++ b/node-registrar/client/types.go @@ -46,9 +46,9 @@ type ZosVersion struct { } type Interface struct { - Name string `json:"name"` - Mac string `json:"mac"` - IPs string `json:"ips"` + Name string `json:"name"` + Mac string `json:"mac"` + IPs []string `json:"ips"` } type Resources struct { diff --git a/node-registrar/cmds/main.go b/node-registrar/cmds/main.go index 63afe22..95b6644 100644 --- a/node-registrar/cmds/main.go +++ b/node-registrar/cmds/main.go @@ -40,15 +40,15 @@ func main() { func Run() error { f := flags{} var sqlLogLevel int - flag.StringVar(&f.PostgresHost, "postgres-host", "", "postgres host") + flag.StringVar(&f.Config.PostgresHost, "postgres-host", "", "postgres host") flag.Uint64Var(&f.Config.PostgresPort, "postgres-port", 5432, "postgres port") - flag.StringVar(&f.DBName, "postgres-db", "", "postgres database") - flag.StringVar(&f.PostgresUser, "postgres-user", "", "postgres username") - flag.StringVar(&f.PostgresPassword, "postgres-password", "", "postgres password") - flag.StringVar(&f.SSLMode, "ssl-mode", "disable", "postgres ssl mode[disable, require, verify-ca, verify-full]") + flag.StringVar(&f.Config.DBName, "postgres-db", "", "postgres database") + flag.StringVar(&f.Config.PostgresUser, "postgres-user", "", "postgres username") + flag.StringVar(&f.Config.PostgresPassword, "postgres-password", "", "postgres password") + flag.StringVar(&f.Config.SSLMode, "ssl-mode", "disable", "postgres ssl mode[disable, require, verify-ca, verify-full]") flag.IntVar(&sqlLogLevel, "sql-log-level", 2, "sql logger level") - flag.Uint64Var(&f.MaxOpenConns, "max-open-conn", 3, "max open sql connections") - flag.Uint64Var(&f.MaxIdleConns, "max-idle-conn", 3, "max idle sql connections") + flag.Uint64Var(&f.Config.MaxOpenConns, "max-open-conn", 3, "max open sql connections") + flag.Uint64Var(&f.Config.MaxIdleConns, "max-idle-conn", 3, "max idle sql connections") flag.BoolVar(&f.version, "v", false, "shows the package version") flag.BoolVar(&f.debug, "debug", false, "allow debug logs") @@ -58,7 +58,7 @@ func Run() error { flag.Uint64Var(&f.adminTwinID, "admin-twin-id", 1, "admin twin ID") flag.Parse() - f.SqlLogLevel = logger.LogLevel(sqlLogLevel) + f.Config.SqlLogLevel = logger.LogLevel(sqlLogLevel) if f.version { log.Info().Str("version", version).Str("commit", commit).Send() @@ -108,8 +108,8 @@ func (f flags) validate() error { return errors.New("invalid domain name, domain name should not be empty") } - if f.SqlLogLevel < 1 || f.SqlLogLevel > 4 { - return errors.Errorf("invalid sql log level %d, sql log level should be in the range 1-4", f.SqlLogLevel) + if f.Config.SqlLogLevel < 1 || f.Config.SqlLogLevel > 4 { + return errors.Errorf("invalid sql log level %d, sql log level should be in the range 1-4", f.Config.SqlLogLevel) } if f.adminTwinID == 0 { return errors.Errorf("invalid admin twin id %d, admin twin id should not be 0", f.adminTwinID) diff --git a/node-registrar/go.mod b/node-registrar/go.mod index 8989bac..2e0b1d2 100644 --- a/node-registrar/go.mod +++ b/node-registrar/go.mod @@ -4,15 +4,15 @@ go 1.21.0 require ( github.com/cosmos/go-bip39 v1.0.0 - github.com/gin-contrib/cors v1.7.3 - github.com/gin-gonic/gin v1.10.0 + github.com/gin-contrib/cors v1.5.0 + github.com/gin-gonic/gin v1.9.1 github.com/lib/pq v1.10.9 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/stretchr/testify v1.10.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 - github.com/swaggo/swag v1.16.4 + github.com/swaggo/swag v1.16.3 github.com/vedhavyas/go-subkey/v2 v2.0.0 gorm.io/driver/postgres v1.5.11 gorm.io/gorm v1.25.12 @@ -28,7 +28,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/base58 v1.0.4 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.7 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -36,7 +36,7 @@ require ( github.com/go-openapi/swag v0.22.3 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.23.0 // indirect + github.com/go-playground/validator/v10 v10.17.0 // indirect github.com/goccy/go-json v0.10.4 // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -62,12 +62,12 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect golang.org/x/arch v0.12.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.15.0 // indirect + golang.org/x/tools v0.16.1 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/node-registrar/go.sum b/node-registrar/go.sum index 3f35c5c..9025429 100644 --- a/node-registrar/go.sum +++ b/node-registrar/go.sum @@ -29,16 +29,16 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= -github.com/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA= -github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU= -github.com/gin-contrib/cors v1.7.3 h1:hV+a5xp8hwJoTw7OY+a70FsL8JkVVFTXw9EcfrYUdns= -github.com/gin-contrib/cors v1.7.3/go.mod h1:M3bcKZhxzsvI+rlRSkkxHyljJt1ESd93COUvemZ79j4= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= @@ -58,13 +58,13 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o= -github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= +github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= @@ -150,8 +150,8 @@ github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= -github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A= -github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -165,18 +165,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= @@ -191,8 +191,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -200,14 +200,16 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/node-registrar/pkg/db/migrate.go b/node-registrar/pkg/db/migrate.go index d3f7231..2a6382d 100644 --- a/node-registrar/pkg/db/migrate.go +++ b/node-registrar/pkg/db/migrate.go @@ -69,12 +69,18 @@ func (db Database) migrateNodes() error { interfaces = append(interfaces, newInterface) } - // Update only the interfaces field - if err := tx.Model(&Node{}). - Where("node_id = ?", node.NodeID). - Update("interfaces", interfaces).Error; err != nil { - return err // This will roll back the entire transaction + // skip the node if it has no interfaces + if len(interfaces) != 0 { + // Update only the interfaces field + if err := tx.Model(&Node{}). + Where("node_id = ?", node.NodeID). + Update("interfaces", interfaces).Error; err != nil { + return err // This will roll back the entire transaction + } + + log.Info().Uint64("node_id", node.NodeID).Msg("Migration: updating node") } + } return nil diff --git a/node-registrar/pkg/db/models.go b/node-registrar/pkg/db/models.go index 9e53edb..6eb1f86 100644 --- a/node-registrar/pkg/db/models.go +++ b/node-registrar/pkg/db/models.go @@ -1,9 +1,11 @@ package db import ( + "errors" "time" "github.com/lib/pq" + "gorm.io/gorm" ) type Account struct { @@ -55,6 +57,13 @@ type Node struct { Approved bool `json:"approved"` } +func (n *Node) BeforeCreate(tx *gorm.DB) (err error) { + if len(n.Interfaces) == 0 { + return errors.New("interfaces must not be empty") + } + return nil +} + type UptimeReport struct { ID uint64 `gorm:"primaryKey;autoIncrement"` NodeID uint64 `gorm:"index" json:"node_id"`