[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 (
"encoding/json"
"github.com/Sirupsen/logrus"
"net/http"
"strings"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/api/controller/validation"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/middleware"
"github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db/errors"
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) {
return
}
values := make(map[string][]string)
if strings.Contains(data.IP, "127.0.0.1") {
values["ip"] = []string{"The ip field is can't contains '127.0.0.1'"}
}
if len(values) != 0 {
ipAddress := strings.Split(data.Address, ":")[0]
if err := validation.ValidateEndpointIP(ipAddress); len(err) > 0 {
values := make(map[string][]string, 1)
values["ip"] = err
httputil.ReturnValidationError(r, w, values)
return
}
sid := r.Context().Value(middleware.ContextKey("service_id")).(string)
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())
return
}
@ -73,14 +79,16 @@ func (t *ThirdPartyServiceController) updEndpoints(w http.ResponseWriter, r *htt
if !httputil.ValidatorRequestStructAndErrorResponse(r, w, &data, nil) {
return
}
values := make(map[string][]string)
if strings.Contains(data.IP, "127.0.0.1") {
values["ip"] = []string{"The ip field is can't contains '127.0.0.1'"}
}
if len(values) != 0 {
httputil.ReturnValidationError(r, w, values)
return
if data.Address != "" {
ipAddress := strings.Split(data.Address, ":")[0]
if err := validation.ValidateEndpointIP(ipAddress); len(err) > 0 {
values := make(map[string][]string, 1)
values["address"] = err
httputil.ReturnValidationError(r, w, values)
return
}
}
if err := handler.Get3rdPartySvcHandler().UpdEndpoints(&data); err != nil {
httputil.ReturnError(r, w, 500, err.Error())
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 (
"fmt"
"strconv"
"strings"
"github.com/Sirupsen/logrus"
"github.com/goodrain/rainbond/api/model"
"github.com/goodrain/rainbond/db"
@ -44,11 +47,12 @@ func Create3rdPartySvcHandler(dbmanager db.Manager, statusCli *client.AppRuntime
// AddEndpoints adds endpoints for third-party service.
func (t *ThirdPartyServiceHanlder) AddEndpoints(sid string, d *model.AddEndpiontsReq) error {
address, port := convertAddressPort(d.Address)
ep := &dbmodel.Endpoint{
UUID: util.NewUUID(),
ServiceID: sid,
IP: d.IP,
Port: 0,
IP: address,
Port: port,
IsOnline: &d.IsOnline,
}
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)
return err
}
if d.IP != "" {
ep.IP = d.IP
if d.Address != "" {
address, port := convertAddressPort(d.Address)
ep.IP = address
ep.Port = port
}
ep.IsOnline = &d.IsOnline
if err := t.dbmanager.EndpointsDao().UpdateModel(ep); err != nil {
@ -79,6 +85,22 @@ func (t *ThirdPartyServiceHanlder) UpdEndpoints(d *model.UpdEndpiontsReq) error
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.
func (t *ThirdPartyServiceHanlder) DelEndpoints(epid, sid string) error {
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 {
m[item.UUID] = &model.EndpointResp{
EpID: item.UUID,
IP: func(ip string, p int) string {
Address: func(ip string, p int) string {
if p != 0 {
return fmt.Sprintf("%s:%d", ip, p)
}
@ -127,7 +149,7 @@ func (t *ThirdPartyServiceHanlder) ListEndpoints(sid string) ([]*model.EndpointR
}
m[item.Uuid] = &model.EndpointResp{
EpID: item.Uuid,
IP: item.Ip,
Address: item.Ip,
Status: item.Status,
IsOnline: true,
IsStatic: false,

View File

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

View File

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