Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

set endpoint and port when registering #2505

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions auth/host_session.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these changes are required, all the changes should be only on client side for user to set IP and Port for a host

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mainly had to do this for the port check. Otherwise logic.CheckHostPorts(&result.Host) will automatically assign any free port even when user specifies one

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/exp/slices"
"golang.org/x/exp/slog"
)

// SessionHandler - called by the HTTP router when user
Expand All @@ -31,7 +33,7 @@ func SessionHandler(conn *websocket.Conn) {
return
}

var registerMessage models.RegisterMsg
var registerMessage models.HostRegisterNonTokenReqDto
if err = json.Unmarshal(message, &registerMessage); err != nil {
logger.Log(0, "Failed to unmarshall data err=", err.Error())
return
Expand Down Expand Up @@ -140,7 +142,22 @@ func SessionHandler(conn *websocket.Conn) {
return
}
}
logic.CheckHostPorts(&result.Host)
if slices.Contains(registerMessage.CustomParams, models.HostRegisterCustomParamListenPort) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this fields are already on host model, not required to extend the req to have custom params

slog.Info("checking custom host port", "port", result.Host.ListenPort)
isPortInUse, err := logic.CheckHostPorts(&result.Host, false)
if err != nil {
slog.Error("failed to check host port", "error", err)
handleHostRegErr(conn, err)
return
}
if isPortInUse {
slog.Error("port is already in use", "port", result.Host.ListenPort)
handleHostRegErr(conn, err)
return
}
} else {
logic.CheckHostPorts(&result.Host, true)
}
if err := logic.CreateHost(&result.Host); err != nil {
handleHostRegErr(conn, err)
return
Expand Down
27 changes: 23 additions & 4 deletions controllers/enrollmentkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/exp/slices"
"golang.org/x/exp/slog"
)

func enrollmentKeyHandlers(r *mux.Router) {
Expand Down Expand Up @@ -157,14 +159,15 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
// get the host
var newHost models.Host
if err = json.NewDecoder(r.Body).Decode(&newHost); err != nil {
reqBody := models.HostRegisterReqDto{}
if err = json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
// get the host
var newHost models.Host = reqBody.Host
hostExists := false
// re-register host with turn just in case.
if servercfg.IsUsingTurn() {
Expand Down Expand Up @@ -205,7 +208,23 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
hostPass := newHost.HostPass
if !hostExists {
// register host
logic.CheckHostPorts(&newHost)
if slices.Contains(reqBody.CustomParams, models.HostRegisterCustomParamListenPort) {
slog.Info("checking custom host port", "port", newHost.ListenPort)
isPortInUse, err := logic.CheckHostPorts(&newHost, false)
if err != nil {
slog.Error("failed to check host port", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
if isPortInUse {
slog.Error("port is already in use", "port", newHost.ListenPort)
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("port %d is already in use", newHost.ListenPort), "badrequest"))
return
}
} else {
slog.Info("no custom host port set. attempting to use", "port", newHost.ListenPort)
logic.CheckHostPorts(&newHost, true)
}
// create EMQX credentials and ACLs for host
if servercfg.GetBrokerType() == servercfg.EmqxBrokerType {
if err := mq.CreateEmqxUser(newHost.ID.String(), newHost.HostPass, false); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion controllers/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func migrate(w http.ResponseWriter, r *http.Request) {
return
}
if !logic.HostExists(&data.NewHost) {
logic.CheckHostPorts(&data.NewHost)
logic.CheckHostPorts(&data.NewHost, true)
if err = logic.CreateHost(&data.NewHost); err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
Expand Down
20 changes: 17 additions & 3 deletions logic/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,32 @@ func TestCheckPorts(t *testing.T) {
CreateHost(&h)
t.Run("no change", func(t *testing.T) {
is := is.New(t)
CheckHostPorts(&testHost)
CheckHostPorts(&testHost, true)
t.Log(testHost.ListenPort)
t.Log(h.ListenPort)
is.Equal(testHost.ListenPort, 51830)
})
t.Run("no change with assign=false", func(t *testing.T) {
is := is.New(t)
CheckHostPorts(&testHost, false)
t.Log(testHost.ListenPort)
t.Log(h.ListenPort)
is.Equal(testHost.ListenPort, 51830)
})
t.Run("same listen port", func(t *testing.T) {
is := is.New(t)
testHost.ListenPort = 51821
CheckHostPorts(&testHost)
CheckHostPorts(&testHost, true)
t.Log(testHost.ListenPort)
t.Log(h.ListenPort)
is.Equal(testHost.ListenPort, 51822)
})

t.Run("no change for same listen port with assign=false", func(t *testing.T) {
is := is.New(t)
testHost.ListenPort = 51821
CheckHostPorts(&testHost, false)
t.Log(testHost.ListenPort)
t.Log(h.ListenPort)
is.Equal(testHost.ListenPort, 51821)
})
}
9 changes: 6 additions & 3 deletions logic/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,11 @@ func GetRelatedHosts(hostID string) []models.Host {
// CheckHostPort checks host endpoints to ensures that hosts on the same server
// with the same endpoint have different listen ports
// in the case of 64535 hosts or more with same endpoint, ports will not be changed
func CheckHostPorts(h *models.Host) {
func CheckHostPorts(h *models.Host, assignPort bool) (bool, error) {
portsInUse := make(map[int]bool, 0)
hosts, err := GetAllHosts()
if err != nil {
return
return false, err
}
for _, host := range hosts {
if host.ID.String() == h.ID.String() {
Expand All @@ -496,14 +496,17 @@ func CheckHostPorts(h *models.Host) {
}
portsInUse[host.ListenPort] = true
}
if !assignPort {
return portsInUse[h.ListenPort], nil
}
// iterate until port is not found or max iteration is reached
for i := 0; portsInUse[h.ListenPort] && i < maxPort-minPort+1; i++ {
h.ListenPort++
if h.ListenPort > maxPort {
h.ListenPort = minPort
}
}

return false, nil
}

// HostExists - checks if given host already exists
Expand Down
28 changes: 21 additions & 7 deletions models/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,25 @@ type Signal struct {
TimeStamp int64 `json:"timestamp"`
}

// RegisterMsg - login message struct for hosts to join via SSO login
type RegisterMsg struct {
RegisterHost Host `json:"host"`
Network string `json:"network,omitempty"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
JoinAll bool `json:"join_all,omitempty"`
// HostRegisterNonTokenReqDto - login message struct for hosts to join via SSO login
type HostRegisterNonTokenReqDto struct {
RegisterHost Host `json:"host"`
Network string `json:"network,omitempty"`
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
JoinAll bool `json:"join_all,omitempty"`
CustomParams []HostRegisterCustomParams `json:"customParams"`
}

// HostRegisterCustomParams - enum for host registration custom params
type HostRegisterCustomParams int

const (
HostRegisterCustomParamEndpointIp HostRegisterCustomParams = iota // EnumIndex = 0
HostRegisterCustomParamListenPort
)

type HostRegisterReqDto struct {
Host Host `json:"host"`
CustomParams []HostRegisterCustomParams `json:"customParams"`
}
Loading