[FIX] failed to add endpoint with port

This commit is contained in:
GLYASAI 2019-05-17 10:40:46 +08:00
parent 6d7690a51b
commit 103ad550ee
5 changed files with 113 additions and 23 deletions

View File

@ -20,13 +20,15 @@ package controller
import ( import (
"encoding/json" "encoding/json"
"github.com/Sirupsen/logrus"
"net/http" "net/http"
"strings" "strings"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/api/controller/validation"
"github.com/goodrain/rainbond/api/handler" "github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/middleware" "github.com/goodrain/rainbond/api/middleware"
"github.com/goodrain/rainbond/api/model" "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db/errors"
httputil "github.com/goodrain/rainbond/util/http" httputil "github.com/goodrain/rainbond/util/http"
) )
@ -52,16 +54,20 @@ func (t *ThirdPartyServiceController) addEndpoints(w http.ResponseWriter, r *htt
if !httputil.ValidatorRequestStructAndErrorResponse(r, w, &data, nil) { if !httputil.ValidatorRequestStructAndErrorResponse(r, w, &data, nil) {
return return
} }
values := make(map[string][]string) ipAddress := strings.Split(data.Address, ":")[0]
if strings.Contains(data.IP, "127.0.0.1") { if err := validation.ValidateEndpointIP(ipAddress); len(err) > 0 {
values["ip"] = []string{"The ip field is can't contains '127.0.0.1'"} values := make(map[string][]string, 1)
} values["ip"] = err
if len(values) != 0 {
httputil.ReturnValidationError(r, w, values) httputil.ReturnValidationError(r, w, values)
return return
} }
sid := r.Context().Value(middleware.ContextKey("service_id")).(string) sid := r.Context().Value(middleware.ContextKey("service_id")).(string)
if err := handler.Get3rdPartySvcHandler().AddEndpoints(sid, &data); err != nil { if err := handler.Get3rdPartySvcHandler().AddEndpoints(sid, &data); err != nil {
if err == errors.ErrRecordAlreadyExist {
httputil.ReturnError(r, w, 400, err.Error())
return
}
httputil.ReturnError(r, w, 500, err.Error()) httputil.ReturnError(r, w, 500, err.Error())
return return
} }
@ -73,14 +79,16 @@ func (t *ThirdPartyServiceController) updEndpoints(w http.ResponseWriter, r *htt
if !httputil.ValidatorRequestStructAndErrorResponse(r, w, &data, nil) { if !httputil.ValidatorRequestStructAndErrorResponse(r, w, &data, nil) {
return return
} }
values := make(map[string][]string) if data.Address != "" {
if strings.Contains(data.IP, "127.0.0.1") { ipAddress := strings.Split(data.Address, ":")[0]
values["ip"] = []string{"The ip field is can't contains '127.0.0.1'"} if err := validation.ValidateEndpointIP(ipAddress); len(err) > 0 {
} values := make(map[string][]string, 1)
if len(values) != 0 { values["address"] = err
httputil.ReturnValidationError(r, w, values) httputil.ReturnValidationError(r, w, values)
return return
}
} }
if err := handler.Get3rdPartySvcHandler().UpdEndpoints(&data); err != nil { if err := handler.Get3rdPartySvcHandler().UpdEndpoints(&data); err != nil {
httputil.ReturnError(r, w, 500, err.Error()) httputil.ReturnError(r, w, 500, err.Error())
return return

View File

@ -0,0 +1,59 @@
package validation
import (
"fmt"
"net"
"strings"
k8svalidation "k8s.io/apimachinery/pkg/util/validation"
)
// ValidateDomain tests that the argument is a valid domain.
func ValidateDomain(domain string) []string {
if strings.TrimSpace(domain) == "" {
return nil
}
var errs []string
if strings.Contains(domain, "*") {
errs = k8svalidation.IsWildcardDNS1123Subdomain(domain)
} else {
errs = k8svalidation.IsDNS1123Subdomain(domain)
}
return errs
}
// ValidateEndpointAddress tests that the argument is a valid endpoint address.
func ValidateEndpointAddress(address string) []string {
ip := net.ParseIP(address)
if ip == nil {
return ValidateDomain(address)
}
return ValidateEndpointIP(address)
}
// ValidateEndpointIP tests that the argument is a valid IP address.
func ValidateEndpointIP(ipAddress string) []string {
// We disallow some IPs as endpoints or external-ips. Specifically,
// unspecified and loopback addresses are nonsensical and link-local
// addresses tend to be used for node-centric purposes (e.g. metadata
// service).
err := []string{}
ip := net.ParseIP(ipAddress)
if ip == nil {
err = append(err, fmt.Sprintf("%s must be a valid IP address", ipAddress))
return err
}
if ip.IsUnspecified() {
err = append(err, fmt.Sprintf("%s may not be unspecified (0.0.0.0)", ipAddress))
}
if ip.IsLoopback() {
err = append(err, fmt.Sprintf("%s may not be in the loopback range (127.0.0.0/8)", ipAddress))
}
if ip.IsLinkLocalUnicast() {
err = append(err, fmt.Sprintf("%s may not be in the link-local range (169.254.0.0/16)", ipAddress))
}
if ip.IsLinkLocalMulticast() {
err = append(err, fmt.Sprintf("%s may not be in the link-local multicast range (224.0.0.0/24)", ipAddress))
}
return err
}

View File

@ -20,6 +20,9 @@ package handler
import ( import (
"fmt" "fmt"
"strconv"
"strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/api/model" "github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db" "github.com/goodrain/rainbond/db"
@ -44,11 +47,12 @@ func Create3rdPartySvcHandler(dbmanager db.Manager, statusCli *client.AppRuntime
// AddEndpoints adds endpoints for third-party service. // AddEndpoints adds endpoints for third-party service.
func (t *ThirdPartyServiceHanlder) AddEndpoints(sid string, d *model.AddEndpiontsReq) error { func (t *ThirdPartyServiceHanlder) AddEndpoints(sid string, d *model.AddEndpiontsReq) error {
address, port := convertAddressPort(d.Address)
ep := &dbmodel.Endpoint{ ep := &dbmodel.Endpoint{
UUID: util.NewUUID(), UUID: util.NewUUID(),
ServiceID: sid, ServiceID: sid,
IP: d.IP, IP: address,
Port: 0, Port: port,
IsOnline: &d.IsOnline, IsOnline: &d.IsOnline,
} }
if err := t.dbmanager.EndpointsDao().AddModel(ep); err != nil { if err := t.dbmanager.EndpointsDao().AddModel(ep); err != nil {
@ -66,8 +70,10 @@ func (t *ThirdPartyServiceHanlder) UpdEndpoints(d *model.UpdEndpiontsReq) error
logrus.Warningf("EpID: %s; error getting endpoints: %v", d.EpID, err) logrus.Warningf("EpID: %s; error getting endpoints: %v", d.EpID, err)
return err return err
} }
if d.IP != "" { if d.Address != "" {
ep.IP = d.IP address, port := convertAddressPort(d.Address)
ep.IP = address
ep.Port = port
} }
ep.IsOnline = &d.IsOnline ep.IsOnline = &d.IsOnline
if err := t.dbmanager.EndpointsDao().UpdateModel(ep); err != nil { if err := t.dbmanager.EndpointsDao().UpdateModel(ep); err != nil {
@ -79,6 +85,22 @@ func (t *ThirdPartyServiceHanlder) UpdEndpoints(d *model.UpdEndpiontsReq) error
return nil return nil
} }
func convertAddressPort(s string) (address string, port int) {
addressport := strings.Split(s, ":")
// compatible with ipv6
addressSli := addressport[:func() int {
if len(addressport) == 2 {
return len(addressport) - 1
}
return len(addressport)
}()]
address = strings.Join(addressSli, ":")
if len(addressport) == 2 {
port, _ = strconv.Atoi(addressport[1])
}
return address, port
}
// DelEndpoints deletes endpoints for third-party service. // DelEndpoints deletes endpoints for third-party service.
func (t *ThirdPartyServiceHanlder) DelEndpoints(epid, sid string) error { func (t *ThirdPartyServiceHanlder) DelEndpoints(epid, sid string) error {
if err := t.dbmanager.EndpointsDao().DelByUUID(epid); err != nil { if err := t.dbmanager.EndpointsDao().DelByUUID(epid); err != nil {
@ -100,7 +122,7 @@ func (t *ThirdPartyServiceHanlder) ListEndpoints(sid string) ([]*model.EndpointR
for _, item := range endpoints { for _, item := range endpoints {
m[item.UUID] = &model.EndpointResp{ m[item.UUID] = &model.EndpointResp{
EpID: item.UUID, EpID: item.UUID,
IP: func(ip string, p int) string { Address: func(ip string, p int) string {
if p != 0 { if p != 0 {
return fmt.Sprintf("%s:%d", ip, p) return fmt.Sprintf("%s:%d", ip, p)
} }
@ -127,7 +149,7 @@ func (t *ThirdPartyServiceHanlder) ListEndpoints(sid string) ([]*model.EndpointR
} }
m[item.Uuid] = &model.EndpointResp{ m[item.Uuid] = &model.EndpointResp{
EpID: item.Uuid, EpID: item.Uuid,
IP: item.Ip, Address: item.Ip,
Status: item.Status, Status: item.Status,
IsOnline: true, IsOnline: true,
IsStatic: false, IsStatic: false,

View File

@ -20,14 +20,14 @@ package model
// AddEndpiontsReq is one of the Endpoints in the request to add the endpints. // AddEndpiontsReq is one of the Endpoints in the request to add the endpints.
type AddEndpiontsReq struct { type AddEndpiontsReq struct {
IP string `json:"ip" validate:"required|ip_v4"` Address string `json:"address" validate:"address|required"`
IsOnline bool `json:"is_online" validate:"required"` IsOnline bool `json:"is_online" validate:"required"`
} }
// UpdEndpiontsReq is one of the Endpoints in the request to update the endpints. // UpdEndpiontsReq is one of the Endpoints in the request to update the endpints.
type UpdEndpiontsReq struct { type UpdEndpiontsReq struct {
EpID string `json:"ep_id" validate:"required|len:32"` EpID string `json:"ep_id" validate:"required|len:32"`
IP string `json:"ip" validate:"ip_v4"` Address string `json:"address"`
IsOnline bool `json:"is_online" validate:"required"` IsOnline bool `json:"is_online" validate:"required"`
} }
@ -40,7 +40,7 @@ type DelEndpiontsReq struct {
// update or delete the endpints. // update or delete the endpints.
type EndpointResp struct { type EndpointResp struct {
EpID string `json:"ep_id"` EpID string `json:"ep_id"`
IP string `json:"ip"` Address string `json:"address"`
Status string `json:"status"` Status string `json:"status"`
IsOnline bool `json:"is_online"` IsOnline bool `json:"is_online"`
IsStatic bool `json:"is_static"` IsStatic bool `json:"is_static"`

View File

@ -24,6 +24,7 @@ import (
"strings" "strings"
"github.com/goodrain/rainbond/db/model" "github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/db/errors"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
) )
@ -44,7 +45,7 @@ func (e *EndpointDaoImpl) AddModel(mo model.Interface) error {
return err return err
} }
} else { } else {
return fmt.Errorf("Endpoint exists based on servicd_id(%s) and ip(%s)", ep.ServiceID, ep.IP) return errors.ErrRecordAlreadyExist
} }
return nil return nil
} }