mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-29 18:27:58 +08:00
Merge pull request #1096 from barnettZQG/master
Structure adjustment #1083 #1084 #1085 #1086
This commit is contained in:
commit
c2f9930a5d
@ -1,8 +1,8 @@
|
||||
# Compile the project
|
||||
|
||||
```
|
||||
# you must have docker and golang environment
|
||||
if you have docker and golang environment
|
||||
|
||||
```
|
||||
# build all docker image
|
||||
make image
|
||||
|
||||
@ -12,11 +12,21 @@ make binary
|
||||
# build binary for different os
|
||||
GOOS=windows make binary
|
||||
|
||||
# if you what build one component
|
||||
# if you what build one module
|
||||
make binary WHAT=api
|
||||
make image WHAT=api
|
||||
```
|
||||
|
||||
in only golang environment
|
||||
|
||||
```
|
||||
# build all module
|
||||
./localbuild.sh all
|
||||
|
||||
# build one module
|
||||
./localbuild.sh api
|
||||
```
|
||||
|
||||
# How to contribute
|
||||
|
||||
Read [Contributing to Open Source on GitHub](https://guides.github.com/activities/contributing-to-open-source/) before contribute.
|
||||
|
1
Makefile
1
Makefile
@ -2,7 +2,6 @@ GO_LDFLAGS=-ldflags " -w"
|
||||
VERSION=$(shell git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3)
|
||||
WORK_DIR=/go/src/github.com/goodrain/rainbond
|
||||
BASE_NAME=rainbond
|
||||
BASE_DOCKER=./hack/contrib/docker
|
||||
|
||||
default: help
|
||||
all: image ## build linux binaries, build images for docker
|
||||
|
@ -1,36 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cloud
|
||||
|
||||
import (
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/goodrain/rainbond/api/controller"
|
||||
)
|
||||
|
||||
//Routes routes
|
||||
func Routes() chi.Router {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/show", controller.GetCloudRouterManager().Show)
|
||||
r.Post("/auth", controller.GetCloudRouterManager().CreateToken)
|
||||
r.Get("/auth/{eid}", controller.GetCloudRouterManager().GetTokenInfo)
|
||||
r.Put("/auth/{eid}", controller.GetCloudRouterManager().UpdateToken)
|
||||
r.Get("/api/manager", controller.GetCloudRouterManager().GetAPIManager)
|
||||
r.Post("/api/manager", controller.GetCloudRouterManager().DeleteAPIManager)
|
||||
return r
|
||||
}
|
@ -34,8 +34,6 @@ type V2 struct {
|
||||
//Routes routes
|
||||
func (v2 *V2) Routes() chi.Router {
|
||||
r := chi.NewRouter()
|
||||
license := middleware.NewLicense(v2.Cfg)
|
||||
r.Use(license.Verify)
|
||||
r.Get("/show", controller.GetManager().Show)
|
||||
r.Post("/show", controller.GetManager().Show)
|
||||
r.Mount("/tenants", v2.tenantRouter())
|
||||
|
@ -27,20 +27,15 @@ import (
|
||||
//Routes routes
|
||||
func Routes() chi.Router {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/docker_console", controller.GetDockerConsole().Get)
|
||||
r.Get("/docker_log", controller.GetDockerLog().Get)
|
||||
r.Get("/monitor_message", controller.GetMonitorMessage().Get)
|
||||
r.Get("/new_monitor_message", controller.GetMonitorMessage().Get)
|
||||
r.Get("/event_log", controller.GetEventLog().Get)
|
||||
r.Get("/services/{serviceID}/pubsub", controller.GetPubSubControll().Get)
|
||||
return r
|
||||
}
|
||||
|
||||
//LogRoutes 日志下载路由
|
||||
//LogRoutes componet log download
|
||||
func LogRoutes() chi.Router {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/{gid}/{filename}", controller.GetLogFile().Get)
|
||||
r.Get("/install_log/{filename}", controller.GetLogFile().GetInstallLog)
|
||||
return r
|
||||
}
|
||||
|
||||
|
@ -1,241 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
httputil "github.com/goodrain/rainbond/util/http"
|
||||
)
|
||||
|
||||
//CloudManager cloud manager
|
||||
type CloudManager struct{}
|
||||
|
||||
var defaultCloudManager *CloudManager
|
||||
|
||||
//GetCloudRouterManager get cloud Manager
|
||||
func GetCloudRouterManager() *CloudManager {
|
||||
if defaultCloudManager != nil {
|
||||
return defaultCloudManager
|
||||
}
|
||||
defaultCloudManager = &CloudManager{}
|
||||
return defaultCloudManager
|
||||
}
|
||||
|
||||
//Show Show
|
||||
func (c *CloudManager) Show(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("cloud urls"))
|
||||
}
|
||||
|
||||
//CreateToken CreateToken
|
||||
// swagger:operation POST /cloud/auth cloud createToken
|
||||
//
|
||||
// 产生token
|
||||
//
|
||||
// create token
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) CreateToken(w http.ResponseWriter, r *http.Request) {
|
||||
var gt api_model.GetUserToken
|
||||
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, >.Body, nil); !ok {
|
||||
return
|
||||
}
|
||||
ti, err := handler.GetCloudManager().TokenDispatcher(>)
|
||||
if err != nil {
|
||||
err.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, ti)
|
||||
}
|
||||
|
||||
//GetTokenInfo GetTokenInfo
|
||||
// swagger:operation GET /cloud/auth/{eid} cloud getTokenInfo
|
||||
//
|
||||
// 获取tokeninfo
|
||||
//
|
||||
// get token info
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) GetTokenInfo(w http.ResponseWriter, r *http.Request) {
|
||||
eid := chi.URLParam(r, "eid")
|
||||
ti, err := handler.GetCloudManager().GetTokenInfo(eid)
|
||||
if err != nil {
|
||||
err.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, ti)
|
||||
}
|
||||
|
||||
//UpdateToken UpdateToken
|
||||
// swagger:operation PUT /cloud/auth/{eid} cloud updateToken
|
||||
//
|
||||
// 更新token
|
||||
//
|
||||
// update token info
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) UpdateToken(w http.ResponseWriter, r *http.Request) {
|
||||
var ut api_model.UpdateToken
|
||||
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &ut.Body, nil); !ok {
|
||||
return
|
||||
}
|
||||
eid := chi.URLParam(r, "eid")
|
||||
err := handler.GetCloudManager().UpdateTokenTime(eid, ut.Body.ValidityPeriod)
|
||||
if err != nil {
|
||||
err.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, nil)
|
||||
}
|
||||
|
||||
//GetAPIManager GetAPIManager
|
||||
// swagger:operation GET /cloud/api/manager cloud GetAPIManager
|
||||
//
|
||||
// 获取api管理
|
||||
//
|
||||
// get api manager
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) GetAPIManager(w http.ResponseWriter, r *http.Request) {
|
||||
apiMap := handler.GetTokenIdenHandler().GetAPIManager()
|
||||
httputil.ReturnSuccess(r, w, apiMap)
|
||||
}
|
||||
|
||||
//AddAPIManager AddAPIManager
|
||||
// swagger:operation POST /cloud/api/manager cloud addAPIManager
|
||||
//
|
||||
// 添加api管理
|
||||
//
|
||||
// get api manager
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) AddAPIManager(w http.ResponseWriter, r *http.Request) {
|
||||
var am api_model.APIManager
|
||||
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &am.Body, nil); !ok {
|
||||
return
|
||||
}
|
||||
err := handler.GetTokenIdenHandler().AddAPIManager(&am)
|
||||
if err != nil {
|
||||
err.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, nil)
|
||||
}
|
||||
|
||||
//DeleteAPIManager DeleteAPIManager
|
||||
// swagger:operation DELETE /cloud/api/manager cloud deleteAPIManager
|
||||
//
|
||||
// 删除api管理
|
||||
//
|
||||
// delete api manager
|
||||
//
|
||||
// ---
|
||||
// consumes:
|
||||
// - application/json
|
||||
// - application/x-protobuf
|
||||
//
|
||||
// produces:
|
||||
// - application/json
|
||||
// - application/xml
|
||||
//
|
||||
// responses:
|
||||
// default:
|
||||
// schema:
|
||||
// "$ref": "#/responses/commandResponse"
|
||||
// description: 统一返回格式
|
||||
func (c *CloudManager) DeleteAPIManager(w http.ResponseWriter, r *http.Request) {
|
||||
var am api_model.APIManager
|
||||
if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &am.Body, nil); !ok {
|
||||
return
|
||||
}
|
||||
err := handler.GetTokenIdenHandler().DeleteAPIManager(&am)
|
||||
if err != nil {
|
||||
err.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, nil)
|
||||
}
|
@ -22,11 +22,9 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/goodrain/rainbond/api/api"
|
||||
"github.com/goodrain/rainbond/api/discover"
|
||||
"github.com/goodrain/rainbond/api/proxy"
|
||||
"github.com/goodrain/rainbond/cmd/api/option"
|
||||
mqclient "github.com/goodrain/rainbond/mq/client"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/goodrain/rainbond/worker/client"
|
||||
)
|
||||
|
||||
@ -66,13 +64,7 @@ func GetManager() V2Manager {
|
||||
|
||||
//NewManager new manager
|
||||
func NewManager(conf option.Config, statusCli *client.AppRuntimeSyncClient) (*V2Routes, error) {
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: conf.EtcdEndpoint,
|
||||
CaFile: conf.EtcdCaFile,
|
||||
CertFile: conf.EtcdCertFile,
|
||||
KeyFile: conf.EtcdKeyFile,
|
||||
}
|
||||
mqClient, err := mqclient.NewMqClient(etcdClientArgs, conf.MQAPI)
|
||||
mqClient, err := mqclient.NewMqClient(conf.MQAPI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -82,8 +74,7 @@ func NewManager(conf option.Config, statusCli *client.AppRuntimeSyncClient) (*V2
|
||||
v2r.GatewayStruct.MQClient = mqClient
|
||||
v2r.GatewayStruct.cfg = &conf
|
||||
v2r.LabelController.optconfig = &conf
|
||||
eventServerProxy := proxy.CreateProxy("eventlog", "http", []string{"local=>rbd-eventlog:6363"})
|
||||
discover.GetEndpointDiscover().AddProject("event_log_event_http", eventServerProxy)
|
||||
eventServerProxy := proxy.CreateProxy("eventlog", "http", []string{"rbd-eventlog:6363"})
|
||||
v2r.EventLogStruct.EventlogServerProxy = eventServerProxy
|
||||
return &v2r, nil
|
||||
}
|
||||
|
@ -19,13 +19,11 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/goodrain/rainbond/api/discover"
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
"github.com/goodrain/rainbond/api/proxy"
|
||||
ctxutil "github.com/goodrain/rainbond/api/util/ctx"
|
||||
@ -33,32 +31,7 @@ import (
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//DockerConsole docker console
|
||||
type DockerConsole struct {
|
||||
socketproxy proxy.Proxy
|
||||
}
|
||||
|
||||
var defaultDockerConsoleEndpoints = []string{"127.0.0.1:7171"}
|
||||
var defaultEventLogEndpoints = []string{"local=>rbd-eventlog:6363"}
|
||||
|
||||
var dockerConsole *DockerConsole
|
||||
|
||||
//GetDockerConsole get Docker console
|
||||
func GetDockerConsole() *DockerConsole {
|
||||
if dockerConsole != nil {
|
||||
return dockerConsole
|
||||
}
|
||||
dockerConsole = &DockerConsole{
|
||||
socketproxy: proxy.CreateProxy("dockerconsole", "websocket", defaultDockerConsoleEndpoints),
|
||||
}
|
||||
discover.GetEndpointDiscover().AddProject("acp_webcli", dockerConsole.socketproxy)
|
||||
return dockerConsole
|
||||
}
|
||||
|
||||
//Get get
|
||||
func (d DockerConsole) Get(w http.ResponseWriter, r *http.Request) {
|
||||
d.socketproxy.Proxy(w, r)
|
||||
}
|
||||
var defaultEventLogEndpoints = []string{"rbd-eventlog:6363"}
|
||||
|
||||
var dockerLog *DockerLog
|
||||
|
||||
@ -73,7 +46,6 @@ func GetDockerLog() *DockerLog {
|
||||
dockerLog = &DockerLog{
|
||||
socketproxy: proxy.CreateProxy("dockerlog", "websocket", defaultEventLogEndpoints),
|
||||
}
|
||||
discover.GetEndpointDiscover().AddProject("event_log_event_http", dockerLog.socketproxy)
|
||||
}
|
||||
return dockerLog
|
||||
}
|
||||
@ -96,7 +68,6 @@ func GetMonitorMessage() *MonitorMessage {
|
||||
monitorMessage = &MonitorMessage{
|
||||
socketproxy: proxy.CreateProxy("monitormessage", "websocket", defaultEventLogEndpoints),
|
||||
}
|
||||
discover.GetEndpointDiscover().AddProject("event_log_event_http", monitorMessage.socketproxy)
|
||||
}
|
||||
return monitorMessage
|
||||
}
|
||||
@ -119,7 +90,6 @@ func GetEventLog() *EventLog {
|
||||
eventLog = &EventLog{
|
||||
socketproxy: proxy.CreateProxy("eventlog", "websocket", defaultEventLogEndpoints),
|
||||
}
|
||||
discover.GetEndpointDiscover().AddProject("event_log_event_http", eventLog.socketproxy)
|
||||
}
|
||||
return eventLog
|
||||
}
|
||||
@ -167,17 +137,6 @@ func isExist(filename string) bool {
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
// GetInstallLog get
|
||||
func (d LogFile) GetInstallLog(w http.ResponseWriter, r *http.Request) {
|
||||
filename := chi.URLParam(r, "filename")
|
||||
filePath := d.Root + filename
|
||||
if isExist(filePath) {
|
||||
http.ServeFile(w, r, filePath)
|
||||
} else {
|
||||
w.WriteHeader(404)
|
||||
}
|
||||
}
|
||||
|
||||
var pubSubControll *PubSubControll
|
||||
|
||||
//PubSubControll service pub sub
|
||||
@ -191,7 +150,6 @@ func GetPubSubControll() *PubSubControll {
|
||||
pubSubControll = &PubSubControll{
|
||||
socketproxy: proxy.CreateProxy("dockerlog", "websocket", defaultEventLogEndpoints),
|
||||
}
|
||||
discover.GetEndpointDiscover().AddProject("event_log_event_http", pubSubControll.socketproxy)
|
||||
}
|
||||
return pubSubControll
|
||||
}
|
||||
@ -199,10 +157,11 @@ func GetPubSubControll() *PubSubControll {
|
||||
//Get pubsub controller
|
||||
func (d PubSubControll) Get(w http.ResponseWriter, r *http.Request) {
|
||||
serviceID := chi.URLParam(r, "serviceID")
|
||||
name, _ := handler.GetEventHandler().GetLogInstance(serviceID)
|
||||
if name != "" {
|
||||
r.URL.Query().Add("host_id", name)
|
||||
r = r.WithContext(context.WithValue(r.Context(), proxy.ContextKey("host_id"), name))
|
||||
address, _ := handler.GetEventHandler().GetLogInstance(serviceID)
|
||||
if address != "" {
|
||||
logrus.Infof("pubsub websocket req proxy to eventlog instance %s", address)
|
||||
proxy.CreateProxy("dockerlog", "websocket", []string{address}).Proxy(w, r)
|
||||
return
|
||||
}
|
||||
d.socketproxy.Proxy(w, r)
|
||||
}
|
||||
@ -210,10 +169,11 @@ func (d PubSubControll) Get(w http.ResponseWriter, r *http.Request) {
|
||||
//GetHistoryLog get service docker logs
|
||||
func (d PubSubControll) GetHistoryLog(w http.ResponseWriter, r *http.Request) {
|
||||
serviceID := r.Context().Value(ctxutil.ContextKey("service_id")).(string)
|
||||
name, _ := handler.GetEventHandler().GetLogInstance(serviceID)
|
||||
if name != "" {
|
||||
r.URL.Query().Add("host_id", name)
|
||||
r = r.WithContext(context.WithValue(r.Context(), proxy.ContextKey("host_id"), name))
|
||||
address, _ := handler.GetEventHandler().GetLogInstance(serviceID)
|
||||
if address != "" {
|
||||
logrus.Infof("get history container log req proxy to eventlog instance %s", address)
|
||||
proxy.CreateProxy("dockerlog", "websocket", []string{address}).Proxy(w, r)
|
||||
return
|
||||
}
|
||||
d.socketproxy.Proxy(w, r)
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//StartRegionAPI 启动
|
||||
func StartRegionAPI(ch chan os.Signal) {
|
||||
logrus.Info("old region api begin start..")
|
||||
arg := []string{"region_api.wsgi", "-b=127.0.0.1:8887", "--max-requests=5000", "--reload", "--debug", "--workers=4", "--log-file", "-", "--access-logfile", "-", "--error-logfile", "-"}
|
||||
cmd := exec.Command("gunicorn", arg...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
go func() {
|
||||
if err := cmd.Start(); err != nil {
|
||||
logrus.Error("start region old api error.", err.Error())
|
||||
}
|
||||
tick := time.NewTicker(time.Second * 5)
|
||||
select {
|
||||
case si := <-ch:
|
||||
cmd.Process.Signal(si)
|
||||
return
|
||||
case <-tick.C:
|
||||
monitor()
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
func monitor() {
|
||||
response, err := http.Get("http://127.0.0.1:8887/monitor")
|
||||
if err != nil {
|
||||
logrus.Error("monitor region old api error.", err.Error())
|
||||
return
|
||||
}
|
||||
defer util.CloseResponse(response)
|
||||
if response != nil && response.StatusCode/100 > 2 {
|
||||
logrus.Errorf("monitor region old api error. response code is %s", response.Status)
|
||||
}
|
||||
|
||||
}
|
13
api/db/db.go
13
api/db/db.go
@ -31,7 +31,6 @@ import (
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
"github.com/goodrain/rainbond/mq/client"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/goodrain/rainbond/worker/discover/model"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -65,17 +64,10 @@ func CreateDBManager(conf option.Config) error {
|
||||
func CreateEventManager(conf option.Config) error {
|
||||
var tryTime time.Duration
|
||||
var err error
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: conf.EtcdEndpoint,
|
||||
CaFile: conf.EtcdCaFile,
|
||||
CertFile: conf.EtcdCertFile,
|
||||
KeyFile: conf.EtcdKeyFile,
|
||||
}
|
||||
for tryTime < 4 {
|
||||
tryTime++
|
||||
if err = event.NewManager(event.EventConfig{
|
||||
EventLogServers: conf.EventLogServers,
|
||||
DiscoverArgs: etcdClientArgs,
|
||||
}); err != nil {
|
||||
logrus.Errorf("get event manager failed, try time is %v,%s", tryTime, err.Error())
|
||||
time.Sleep((5 + tryTime*10) * time.Second)
|
||||
@ -93,13 +85,12 @@ func CreateEventManager(conf option.Config) error {
|
||||
|
||||
//MQManager mq manager
|
||||
type MQManager struct {
|
||||
EtcdClientArgs *etcdutil.ClientArgs
|
||||
DefaultServer string
|
||||
DefaultServer string
|
||||
}
|
||||
|
||||
//NewMQManager new mq manager
|
||||
func (m *MQManager) NewMQManager() (client.MQClient, error) {
|
||||
client, err := client.NewMqClient(m.EtcdClientArgs, m.DefaultServer)
|
||||
client, err := client.NewMqClient(m.DefaultServer)
|
||||
if err != nil {
|
||||
logrus.Errorf("new mq manager error, %v", err)
|
||||
return client, err
|
||||
|
@ -1,125 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/goodrain/rainbond/api/proxy"
|
||||
corediscover "github.com/goodrain/rainbond/discover"
|
||||
corediscoverconfig "github.com/goodrain/rainbond/discover/config"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//EndpointDiscover 后端服务自动发现
|
||||
type EndpointDiscover interface {
|
||||
AddProject(name string, proxy proxy.Proxy)
|
||||
Remove(name string)
|
||||
Stop()
|
||||
}
|
||||
|
||||
var defaultEndpointDiscover EndpointDiscover
|
||||
|
||||
//CreateEndpointDiscover create endpoint discover
|
||||
func CreateEndpointDiscover(etcdClientArgs *etcdutil.ClientArgs) (EndpointDiscover, error) {
|
||||
if defaultEndpointDiscover == nil {
|
||||
if etcdClientArgs == nil {
|
||||
return nil, errors.New("etcd args is nil")
|
||||
}
|
||||
dis, err := corediscover.GetDiscover(corediscoverconfig.DiscoverConfig{EtcdClientArgs: etcdClientArgs})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defaultEndpointDiscover = &endpointDiscover{
|
||||
dis: dis,
|
||||
projects: make(map[string]*defalt),
|
||||
}
|
||||
}
|
||||
return defaultEndpointDiscover, nil
|
||||
}
|
||||
|
||||
//GetEndpointDiscover get endpoints discover
|
||||
func GetEndpointDiscover() EndpointDiscover {
|
||||
return defaultEndpointDiscover
|
||||
}
|
||||
|
||||
type endpointDiscover struct {
|
||||
projects map[string]*defalt
|
||||
lock sync.Mutex
|
||||
dis corediscover.Discover
|
||||
}
|
||||
|
||||
func (e *endpointDiscover) AddProject(name string, pro proxy.Proxy) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if def, ok := e.projects[name]; !ok {
|
||||
e.projects[name] = &defalt{name: name, proxys: []proxy.Proxy{pro}}
|
||||
e.dis.AddProject(name, e.projects[name])
|
||||
} else {
|
||||
def.proxys = append(def.proxys, pro)
|
||||
// add proxy after update endpoint first,must initialize endpoint by cache data
|
||||
if len(def.cacheEndpointURL) > 0 {
|
||||
pro.UpdateEndpoints(def.cacheEndpointURL...)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func (e *endpointDiscover) Remove(name string) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; ok {
|
||||
delete(e.projects, name)
|
||||
}
|
||||
}
|
||||
func (e *endpointDiscover) Stop() {
|
||||
e.dis.Stop()
|
||||
}
|
||||
|
||||
type defalt struct {
|
||||
name string
|
||||
proxys []proxy.Proxy
|
||||
cacheEndpointURL []string
|
||||
}
|
||||
|
||||
func (e *defalt) Error(err error) {
|
||||
logrus.Errorf("%s project auto discover occurred error.%s", e.name, err.Error())
|
||||
defaultEndpointDiscover.Remove(e.name)
|
||||
}
|
||||
|
||||
func (e *defalt) UpdateEndpoints(endpoints ...*corediscoverconfig.Endpoint) {
|
||||
var endStr []string
|
||||
for _, end := range endpoints {
|
||||
if end.URL != "" {
|
||||
endStr = append(endStr, end.Name+"=>"+end.URL)
|
||||
}
|
||||
}
|
||||
logrus.Debugf("endstr is %v, name is %v", endStr, e.name)
|
||||
for _, p := range e.proxys {
|
||||
p.UpdateEndpoints(endStr...)
|
||||
}
|
||||
e.cacheEndpointURL = endStr
|
||||
}
|
||||
|
||||
//when watch occurred error,will exec this method
|
||||
func (e *endpointDiscover) Error(err error) {
|
||||
logrus.Errorf("discover error %s", err.Error())
|
||||
}
|
@ -1,226 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
crand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"github.com/goodrain/rainbond/cmd/api/option"
|
||||
"github.com/goodrain/rainbond/db"
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
)
|
||||
|
||||
//CloudAction cloud action struct
|
||||
type CloudAction struct {
|
||||
RegionTag string
|
||||
APISSL bool
|
||||
CAPath string
|
||||
KeyPath string
|
||||
}
|
||||
|
||||
//CreateCloudManager get cloud manager
|
||||
func CreateCloudManager(conf option.Config) *CloudAction {
|
||||
return &CloudAction{
|
||||
APISSL: conf.APISSL,
|
||||
RegionTag: conf.RegionTag,
|
||||
CAPath: conf.APICertFile,
|
||||
KeyPath: conf.APIKeyFile,
|
||||
}
|
||||
}
|
||||
|
||||
//TokenDispatcher token
|
||||
func (c *CloudAction) TokenDispatcher(gt *api_model.GetUserToken) (*api_model.TokenInfo, *util.APIHandleError) {
|
||||
//TODO: product token, 启动api时需要添加该参数
|
||||
//token包含 eid,数据中心标识,可控范围,有效期
|
||||
ti := &api_model.TokenInfo{
|
||||
EID: gt.Body.EID,
|
||||
}
|
||||
token := c.createToken(gt)
|
||||
var oldToken string
|
||||
tokenInfos, err := db.GetManager().RegionUserInfoDao().GetTokenByEid(gt.Body.EID)
|
||||
if err != nil {
|
||||
if err.Error() == gorm.ErrRecordNotFound.Error() {
|
||||
goto CREATE
|
||||
}
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("get user token info", err)
|
||||
}
|
||||
ti.CA = tokenInfos.CA
|
||||
//ti.Key = tokenInfos.Key
|
||||
ti.Token = token
|
||||
oldToken = tokenInfos.Token
|
||||
tokenInfos.Token = token
|
||||
tokenInfos.ValidityPeriod = gt.Body.ValidityPeriod
|
||||
if err := db.GetManager().RegionUserInfoDao().UpdateModel(tokenInfos); err != nil {
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("recreate region user info", err)
|
||||
}
|
||||
tokenInfos.CA = ""
|
||||
tokenInfos.Key = ""
|
||||
GetTokenIdenHandler().DeleteTokenFromMap(oldToken, tokenInfos)
|
||||
return ti, nil
|
||||
CREATE:
|
||||
ti.Token = token
|
||||
logrus.Debugf("create token %v", token)
|
||||
rui := &dbmodel.RegionUserInfo{
|
||||
EID: gt.Body.EID,
|
||||
RegionTag: c.RegionTag,
|
||||
APIRange: gt.Body.Range,
|
||||
ValidityPeriod: gt.Body.ValidityPeriod,
|
||||
Token: token,
|
||||
}
|
||||
if c.APISSL {
|
||||
ca, key, err := c.CertDispatcher(gt)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(500, fmt.Errorf("create ca or key error"))
|
||||
}
|
||||
rui.CA = string(ca)
|
||||
rui.Key = string(key)
|
||||
ti.CA = string(ca)
|
||||
//ti.Key = string(key)
|
||||
}
|
||||
if gt.Body.Range == "" {
|
||||
rui.APIRange = dbmodel.SERVERSOURCE
|
||||
}
|
||||
GetTokenIdenHandler().AddTokenIntoMap(rui)
|
||||
if err := db.GetManager().RegionUserInfoDao().AddModel(rui); err != nil {
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("create region user info", err)
|
||||
}
|
||||
return ti, nil
|
||||
}
|
||||
|
||||
//GetTokenInfo GetTokenInfo
|
||||
func (c *CloudAction) GetTokenInfo(eid string) (*dbmodel.RegionUserInfo, *util.APIHandleError) {
|
||||
tokenInfos, err := db.GetManager().RegionUserInfoDao().GetTokenByEid(eid)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("get user token info", err)
|
||||
}
|
||||
return tokenInfos, nil
|
||||
}
|
||||
|
||||
//UpdateTokenTime UpdateTokenTime
|
||||
func (c *CloudAction) UpdateTokenTime(eid string, vd int) *util.APIHandleError {
|
||||
tokenInfos, err := db.GetManager().RegionUserInfoDao().GetTokenByEid(eid)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleErrorFromDBError("get user token info", err)
|
||||
}
|
||||
tokenInfos.ValidityPeriod = vd
|
||||
err = db.GetManager().RegionUserInfoDao().UpdateModel(tokenInfos)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleErrorFromDBError("update user token info", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//CertDispatcher Cert
|
||||
func (c *CloudAction) CertDispatcher(gt *api_model.GetUserToken) ([]byte, []byte, error) {
|
||||
cert, err := analystCaKey(c.CAPath, "ca")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
//解析私钥
|
||||
keyFile, err := analystCaKey(c.KeyPath, "key")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
//keyFile = keyFile.(rsa.PrivateKey)
|
||||
|
||||
validHourTime := (gt.Body.ValidityPeriod - gt.Body.BeforeTime)
|
||||
cer := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1), //证书序列号
|
||||
Subject: pkix.Name{
|
||||
CommonName: fmt.Sprintf("%s@%d", gt.Body.EID, time.Now().Unix()),
|
||||
Locality: []string{c.RegionTag},
|
||||
},
|
||||
NotBefore: time.Now(), //证书有效期开始时间
|
||||
NotAfter: time.Now().Add(time.Second * time.Duration(validHourTime)), //证书有效期结束时间
|
||||
BasicConstraintsValid: true, //基本的有效性约束
|
||||
IsCA: false, //是否是根证书
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, //证书用途(客户端认证,数据加密)
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment,
|
||||
//EmailAddresses: []string{"region@test.com"},
|
||||
//IPAddresses: []net.IP{net.ParseIP("192.168.1.59")},
|
||||
}
|
||||
priKey, err := rsa.GenerateKey(crand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ca, err := x509.CreateCertificate(crand.Reader, cer, cert.(*x509.Certificate), &priKey.PublicKey, keyFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
//编码证书文件和私钥文件
|
||||
caPem := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: ca,
|
||||
}
|
||||
ca = pem.EncodeToMemory(caPem)
|
||||
|
||||
buf := x509.MarshalPKCS1PrivateKey(priKey)
|
||||
keyPem := &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Bytes: buf,
|
||||
}
|
||||
key := pem.EncodeToMemory(keyPem)
|
||||
return ca, key, nil
|
||||
}
|
||||
|
||||
func analystCaKey(path, kind string) (interface{}, error) {
|
||||
fileInfo, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
fileBlock, _ := pem.Decode(fileInfo)
|
||||
switch kind {
|
||||
case "ca":
|
||||
cert, err := x509.ParseCertificate(fileBlock.Bytes)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return cert, nil
|
||||
case "key":
|
||||
praKey, err := x509.ParsePKCS1PrivateKey(fileBlock.Bytes)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return praKey, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (c *CloudAction) createToken(gt *api_model.GetUserToken) string {
|
||||
fullStr := fmt.Sprintf("%s-%s-%s-%d-%d", gt.Body.EID, c.RegionTag, gt.Body.Range, gt.Body.ValidityPeriod, int(time.Now().Unix()))
|
||||
h := md5.New()
|
||||
h.Write([]byte(fullStr))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
)
|
||||
|
||||
//CloudHandler define source handler
|
||||
type CloudHandler interface {
|
||||
TokenDispatcher(gt *api_model.GetUserToken) (*api_model.TokenInfo, *util.APIHandleError)
|
||||
GetTokenInfo(eid string) (*dbmodel.RegionUserInfo, *util.APIHandleError)
|
||||
UpdateTokenTime(eid string, vd int) *util.APIHandleError
|
||||
}
|
@ -21,32 +21,33 @@ package handler
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
"github.com/goodrain/rainbond/api/model"
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
"github.com/goodrain/rainbond/db"
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
eventdb "github.com/goodrain/rainbond/eventlog/db"
|
||||
"github.com/goodrain/rainbond/util/constants"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//LogAction log action struct
|
||||
type LogAction struct {
|
||||
EtcdCli *clientv3.Client
|
||||
eventdb *eventdb.EventFilePlugin
|
||||
eventdb *eventdb.EventFilePlugin
|
||||
eventLogServer string
|
||||
}
|
||||
|
||||
//CreateLogManager get log manager
|
||||
func CreateLogManager(cli *clientv3.Client) *LogAction {
|
||||
func CreateLogManager() *LogAction {
|
||||
return &LogAction{
|
||||
EtcdCli: cli,
|
||||
eventLogServer: "http://rbd-eventlog:6363",
|
||||
eventdb: &eventdb.EventFilePlugin{
|
||||
HomePath: "/grdata/logs/",
|
||||
},
|
||||
@ -97,15 +98,30 @@ func (l *LogAction) GetLogFile(serviceAlias, fileName string) (string, string, e
|
||||
|
||||
//GetLogInstance get log web socket instance
|
||||
func (l *LogAction) GetLogInstance(serviceID string) (string, error) {
|
||||
value, err := l.EtcdCli.Get(context.Background(), fmt.Sprintf("/event/dockerloginstacne/%s", serviceID))
|
||||
if err != nil {
|
||||
return "", err
|
||||
retry := 1
|
||||
for retry < 3 {
|
||||
address := fmt.Sprintf("%s/docker-instance?service_id=%s&mode=stream", l.eventLogServer, serviceID)
|
||||
res, err := http.DefaultClient.Get(address)
|
||||
if res != nil && res.Body != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
logrus.Warningf("Error get host info from %s. %s", address, err)
|
||||
retry++
|
||||
continue
|
||||
}
|
||||
var host = make(map[string]interface{})
|
||||
err = json.NewDecoder(res.Body).Decode(&host)
|
||||
if err != nil {
|
||||
logrus.Errorf("Error Decode BEST instance host info: %v", err)
|
||||
retry++
|
||||
continue
|
||||
}
|
||||
if status, ok := host["status"]; ok && status == "success" {
|
||||
return fmt.Sprintf("%s:%d", host["ip"], int(host["websocket_port"].(float64))), nil
|
||||
}
|
||||
}
|
||||
if len(value.Kvs) > 0 {
|
||||
return string(value.Kvs[0].Value), nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
return "", fmt.Errorf("can not select docker log instance")
|
||||
}
|
||||
|
||||
//GetLevelLog get event log
|
||||
|
@ -33,21 +33,6 @@ import (
|
||||
|
||||
var gm *GatewayAction
|
||||
|
||||
func init() {
|
||||
//conf := option.Config{
|
||||
// DBType: "mysql",
|
||||
// DBConnectionInfo: "pohF4b:EiW6Eipu@tcp(192.168.56.101:3306)/region",
|
||||
//}
|
||||
////创建db manager
|
||||
//if err := db.CreateDBManager(conf); err != nil {
|
||||
// fmt.Printf("create db manager error, %v", err)
|
||||
//}
|
||||
//cli, err := client.NewMqClient([]string{"http://192.168.56.101:2379"}, "192.168.56.101:6300")
|
||||
//if err != nil {
|
||||
// fmt.Printf("create mq client error, %v", err)
|
||||
//}
|
||||
//gm = CreateGatewayManager(cdb.GetManager(), cli, nil)
|
||||
}
|
||||
func TestSelectAvailablePort(t *testing.T) {
|
||||
t.Log(selectAvailablePort([]int{9000})) // less than minport
|
||||
t.Log(selectAvailablePort([]int{10000})) // equal to minport
|
||||
|
@ -44,8 +44,7 @@ func InitHandle(conf option.Config,
|
||||
k8sClient k8sclient.Client,
|
||||
) error {
|
||||
mq := api_db.MQManager{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
DefaultServer: conf.MQAPI,
|
||||
DefaultServer: conf.MQAPI,
|
||||
}
|
||||
mqClient, errMQ := mq.NewMQManager()
|
||||
if errMQ != nil {
|
||||
@ -65,9 +64,8 @@ func InitHandle(conf option.Config,
|
||||
defaultAppHandler = CreateAppManager(mqClient)
|
||||
defaultTenantHandler = CreateTenManager(mqClient, statusCli, &conf, kubeClient, prometheusCli, k8sClient)
|
||||
defaultNetRulesHandler = CreateNetRulesManager(etcdcli)
|
||||
defaultCloudHandler = CreateCloudManager(conf)
|
||||
defaultAPPBackupHandler = group.CreateBackupHandle(mqClient, statusCli, etcdcli)
|
||||
defaultEventHandler = CreateLogManager(etcdcli)
|
||||
defaultEventHandler = CreateLogManager()
|
||||
shareHandler = &share.ServiceShareHandle{MQClient: mqClient, EtcdCli: etcdcli}
|
||||
pluginShareHandler = &share.PluginShareHandle{MQClient: mqClient, EtcdCli: etcdcli}
|
||||
if err := CreateTokenIdenHandler(conf); err != nil {
|
||||
@ -135,13 +133,6 @@ func GetRulesManager() NetRulesHandler {
|
||||
return defaultNetRulesHandler
|
||||
}
|
||||
|
||||
var defaultCloudHandler CloudHandler
|
||||
|
||||
//GetCloudManager get manager
|
||||
func GetCloudManager() CloudHandler {
|
||||
return defaultCloudHandler
|
||||
}
|
||||
|
||||
var defaultEventHandler EventHandler
|
||||
|
||||
//GetEventHandler get event handler
|
||||
|
@ -19,43 +19,27 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/api/discover"
|
||||
"github.com/goodrain/rainbond/api/proxy"
|
||||
"github.com/goodrain/rainbond/cmd/api/option"
|
||||
)
|
||||
|
||||
var nodeProxy proxy.Proxy
|
||||
var builderProxy proxy.Proxy
|
||||
var prometheusProxy proxy.Proxy
|
||||
var monitorProxy proxy.Proxy
|
||||
var kubernetesDashboard proxy.Proxy
|
||||
|
||||
//InitProxy 初始化
|
||||
func InitProxy(conf option.Config) {
|
||||
if nodeProxy == nil {
|
||||
nodeProxy = proxy.CreateProxy("acp_node", "http", conf.NodeAPI)
|
||||
discover.GetEndpointDiscover().AddProject("acp_node", nodeProxy)
|
||||
}
|
||||
if builderProxy == nil {
|
||||
builderProxy = proxy.CreateProxy("builder", "http", conf.BuilderAPI)
|
||||
}
|
||||
if prometheusProxy == nil {
|
||||
prometheusProxy = proxy.CreateProxy("prometheus", "http", []string{conf.PrometheusEndpoint})
|
||||
}
|
||||
if monitorProxy == nil {
|
||||
monitorProxy = proxy.CreateProxy("monitor", "http", []string{"127.0.0.1:3329"})
|
||||
discover.GetEndpointDiscover().AddProject("monitor", monitorProxy)
|
||||
}
|
||||
if kubernetesDashboard == nil {
|
||||
kubernetesDashboard = proxy.CreateProxy("kubernetesdashboard", "http", []string{conf.KuberentesDashboardAPI})
|
||||
}
|
||||
}
|
||||
|
||||
//GetNodeProxy GetNodeProxy
|
||||
func GetNodeProxy() proxy.Proxy {
|
||||
return nodeProxy
|
||||
}
|
||||
|
||||
//GetBuilderProxy GetNodeProxy
|
||||
func GetBuilderProxy() proxy.Proxy {
|
||||
return builderProxy
|
||||
@ -66,11 +50,6 @@ func GetPrometheusProxy() proxy.Proxy {
|
||||
return prometheusProxy
|
||||
}
|
||||
|
||||
//GetMonitorProxy GetMonitorProxy
|
||||
func GetMonitorProxy() proxy.Proxy {
|
||||
return monitorProxy
|
||||
}
|
||||
|
||||
// GetKubernetesDashboardProxy returns the kubernetes dashboard proxy.
|
||||
func GetKubernetesDashboardProxy() proxy.Proxy {
|
||||
return kubernetesDashboard
|
||||
|
@ -2347,10 +2347,12 @@ func (s *ServiceAction) ListVersionInfo(serviceID string) (*api_model.BuildListR
|
||||
for idx := range bversions {
|
||||
bv := bversions[idx]
|
||||
if bv.Kind == "build_from_image" || bv.Kind == "build_from_market_image" {
|
||||
image := parser.ParseImageName(bv.RepoURL)
|
||||
bv.ImageDomain = image.GetDomain()
|
||||
bv.ImageRepo = image.GetRepostory()
|
||||
bv.ImageTag = image.GetTag()
|
||||
if bv.RepoURL != "" {
|
||||
image := parser.ParseImageName(bv.RepoURL)
|
||||
bv.ImageDomain = image.GetDomain()
|
||||
bv.ImageRepo = image.GetRepostory()
|
||||
bv.ImageTag = image.GetTag()
|
||||
}
|
||||
}
|
||||
}
|
||||
result := &api_model.BuildListRespVO{
|
||||
|
@ -60,6 +60,7 @@ func CreateOperationHandler(mqCli gclient.MQClient) *OperationHandler {
|
||||
func (o *OperationHandler) Build(batchOpReq model.ComponentOpReq) (*model.ComponentOpResult, error) {
|
||||
res := batchOpReq.BatchOpFailureItem()
|
||||
if err := o.build(batchOpReq); err != nil {
|
||||
logrus.Errorf("build component failure %s", err.Error())
|
||||
res.ErrMsg = err.Error()
|
||||
} else {
|
||||
res.Success()
|
||||
@ -279,7 +280,6 @@ func (o *OperationHandler) buildFromMarketSlug(r *model.ComponentBuildReq, servi
|
||||
return o.sendBuildTopic(service.ServiceID, "build_from_market_slug", body)
|
||||
}
|
||||
func (o *OperationHandler) sendBuildTopic(serviceID, taskType string, body map[string]interface{}) error {
|
||||
|
||||
topic := gclient.BuilderTopic
|
||||
if o.isWindowsService(serviceID) {
|
||||
topic = gclient.WindowsBuilderTopic
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
// Metric name parts.
|
||||
const (
|
||||
// Namespace for all metrics.
|
||||
namespace = "rbd_api"
|
||||
namespace = "region_api"
|
||||
// Subsystem(s).
|
||||
exporter = "exporter"
|
||||
)
|
||||
|
@ -1,37 +0,0 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/api/option"
|
||||
httputil "github.com/goodrain/rainbond/util/http"
|
||||
licutil "github.com/goodrain/rainbond/util/license"
|
||||
)
|
||||
|
||||
// License -
|
||||
type License struct {
|
||||
cfg *option.Config
|
||||
}
|
||||
|
||||
// NewLicense -
|
||||
func NewLicense(cfg *option.Config) *License {
|
||||
return &License{
|
||||
cfg: cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// Verify parses the license to make the content inside it take effect.
|
||||
func (l *License) Verify(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if !licutil.VerifyTime(l.cfg.LicensePath, l.cfg.LicSoPath) {
|
||||
httputil.Return(r, w, 401, httputil.ResponseBody{
|
||||
Bean: map[string]interface{}{
|
||||
"msg": "invalid license",
|
||||
"code": 10400,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
@ -162,38 +162,10 @@ func SetLog(next http.Handler) http.Handler {
|
||||
//Proxy 反向代理中间件
|
||||
func Proxy(next http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/nodes") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/cluster/service-health") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/builder") {
|
||||
handler.GetBuilderProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/tasks") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/tasktemps") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/taskgroups") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/configs") {
|
||||
handler.GetNodeProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/v2/rules") {
|
||||
handler.GetMonitorProxy().Proxy(w, r)
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(r.RequestURI, "/kubernetes/dashboard") {
|
||||
proxy := handler.GetKubernetesDashboardProxy()
|
||||
r.URL.Path = strings.Replace(r.URL.Path, "/kubernetes/dashboard", "", 1)
|
||||
|
@ -22,8 +22,6 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//ContextKey context key
|
||||
@ -147,50 +145,3 @@ func (rr RoundRobin) Select(r *http.Request, endpoints EndpointList) Endpoint {
|
||||
selec := int(atomic.AddUint64(rr.ops, 1) % l)
|
||||
return endpoints.Selec(selec)
|
||||
}
|
||||
|
||||
//SelectBalance 选择性负载均衡
|
||||
type SelectBalance struct {
|
||||
hostIDMap map[string]string
|
||||
}
|
||||
|
||||
//NewSelectBalance 创建选择性负载均衡
|
||||
func NewSelectBalance() *SelectBalance {
|
||||
return &SelectBalance{
|
||||
hostIDMap: map[string]string{"local": "rbd-eventlog:6363"},
|
||||
}
|
||||
}
|
||||
|
||||
//Select 负载
|
||||
func (s *SelectBalance) Select(r *http.Request, endpoints EndpointList) Endpoint {
|
||||
if r.URL == nil {
|
||||
return Endpoint(s.hostIDMap["local"])
|
||||
}
|
||||
|
||||
id2ip := map[string]string{"local": "rbd-eventlog:6363"}
|
||||
for _, end := range endpoints {
|
||||
if kv := strings.Split(string(end), "=>"); len(kv) > 1 {
|
||||
id2ip[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
|
||||
if r.URL != nil {
|
||||
hostID := r.URL.Query().Get("host_id")
|
||||
if hostID == "" {
|
||||
hostIDFromContext := r.Context().Value(ContextKey("host_id"))
|
||||
if hostIDFromContext != nil {
|
||||
hostID = hostIDFromContext.(string)
|
||||
}
|
||||
}
|
||||
if e, ok := id2ip[hostID]; ok {
|
||||
logrus.Infof("[lb selelct] find host %s from name %s success", e, hostID)
|
||||
return Endpoint(e)
|
||||
}
|
||||
}
|
||||
|
||||
if len(endpoints) > 0 {
|
||||
logrus.Infof("default endpoint is %s", endpoints[len(endpoints)-1])
|
||||
return endpoints[len(endpoints)-1]
|
||||
}
|
||||
|
||||
return Endpoint(s.hostIDMap["local"])
|
||||
}
|
||||
|
@ -23,11 +23,6 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewSelectBalance(t *testing.T) {
|
||||
sb := NewSelectBalance()
|
||||
t.Log(sb.hostIDMap)
|
||||
}
|
||||
|
||||
func TestURLParse(t *testing.T) {
|
||||
endURL, err := url.Parse("127.0.0.1:8080")
|
||||
if err != nil {
|
||||
|
@ -33,9 +33,6 @@ func CreateProxy(name string, mode string, endpoints []string) Proxy {
|
||||
case "websocket":
|
||||
return createWebSocketProxy(name, endpoints)
|
||||
case "http":
|
||||
if name == "eventlog" {
|
||||
return createHTTPProxy(name, endpoints, NewSelectBalance())
|
||||
}
|
||||
return createHTTPProxy(name, endpoints, nil)
|
||||
default:
|
||||
return createHTTPProxy(name, endpoints, nil)
|
||||
|
@ -162,17 +162,9 @@ func (h *WebSocketProxy) Do(r *http.Request) (*http.Response, error) {
|
||||
}
|
||||
|
||||
func createWebSocketProxy(name string, endpoints []string) *WebSocketProxy {
|
||||
if name != "dockerlog" {
|
||||
return &WebSocketProxy{
|
||||
name: name,
|
||||
endpoints: CreateEndpoints(endpoints),
|
||||
lb: NewRoundRobin(),
|
||||
}
|
||||
}
|
||||
return &WebSocketProxy{
|
||||
name: name,
|
||||
endpoints: CreateEndpoints(endpoints),
|
||||
lb: NewSelectBalance(),
|
||||
lb: NewRoundRobin(),
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,102 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package region
|
||||
|
||||
// //DefineCloudAuth DefineCloudAuth
|
||||
// func (t *tenant) DefineCloudAuth(gt *api_model.GetUserToken) DefineCloudAuthInterface {
|
||||
// return &DefineCloudAuth{
|
||||
// GT: gt,
|
||||
// }
|
||||
// }
|
||||
|
||||
// //DefineCloudAuth DefineCloudAuth
|
||||
// type DefineCloudAuth struct {
|
||||
// GT *api_model.GetUserToken
|
||||
// }
|
||||
|
||||
// //DefineCloudAuthInterface DefineCloudAuthInterface
|
||||
// type DefineCloudAuthInterface interface {
|
||||
// GetToken() ([]byte, error)
|
||||
// PostToken() ([]byte, error)
|
||||
// PutToken() error
|
||||
// }
|
||||
|
||||
// //GetToken GetToken
|
||||
// func (d *DefineCloudAuth) GetToken() ([]byte, error) {
|
||||
// resp, code, err := request(
|
||||
// fmt.Sprintf("/cloud/auth/%s", d.GT.Body.EID),
|
||||
// "GET",
|
||||
// nil,
|
||||
// )
|
||||
// if err != nil {
|
||||
// return nil, util.CreateAPIHandleError(code, err)
|
||||
// }
|
||||
// if code > 400 {
|
||||
// if code == 404 {
|
||||
// return nil, util.CreateAPIHandleError(code, fmt.Errorf("eid %s is not exist", d.GT.Body.EID))
|
||||
// }
|
||||
// return nil, util.CreateAPIHandleError(code, fmt.Errorf("get eid infos %s failed", d.GT.Body.EID))
|
||||
// }
|
||||
// //valJ, err := simplejson.NewJson(resp)
|
||||
// return resp, nil
|
||||
// }
|
||||
|
||||
// //PostToken PostToken
|
||||
// func (d *DefineCloudAuth) PostToken() ([]byte, error) {
|
||||
// data, err := ffjson.Marshal(d.GT.Body)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// resp, code, err := request(
|
||||
// "/cloud/auth",
|
||||
// "POST",
|
||||
// data,
|
||||
// )
|
||||
// if err != nil {
|
||||
// logrus.Errorf("create auth token error, %v", err)
|
||||
// return nil, util.CreateAPIHandleError(code, err)
|
||||
// }
|
||||
// if code > 400 {
|
||||
// logrus.Errorf("create auth token error")
|
||||
// return nil, util.CreateAPIHandleError(code, fmt.Errorf("cretae auth token failed"))
|
||||
// }
|
||||
// return resp, nil
|
||||
// }
|
||||
|
||||
// //PutToken PutToken
|
||||
// func (d *DefineCloudAuth) PutToken() error {
|
||||
// data, err := ffjson.Marshal(d.GT.Body)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// _, code, err := request(
|
||||
// fmt.Sprintf("/cloud/auth/%s", d.GT.Body.EID),
|
||||
// "PUT",
|
||||
// data,
|
||||
// )
|
||||
// if err != nil {
|
||||
// logrus.Errorf("create auth token error, %v", err)
|
||||
// return util.CreateAPIHandleError(code, err)
|
||||
// }
|
||||
// if code > 400 {
|
||||
// logrus.Errorf("create auth token error")
|
||||
// return util.CreateAPIHandleError(code, fmt.Errorf("cretae auth token failed"))
|
||||
// }
|
||||
// return nil
|
||||
// }
|
@ -20,13 +20,34 @@ package region
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"github.com/goodrain/rainbond/node/api/model"
|
||||
utilhttp "github.com/goodrain/rainbond/util/http"
|
||||
)
|
||||
|
||||
//ClusterResource cluster resource model
|
||||
type ClusterResource struct {
|
||||
AllNode int `json:"all_node"`
|
||||
NotReadyNode int `json:"notready_node"`
|
||||
ComputeNode int `json:"compute_node"`
|
||||
Tenant int `json:"tenant"`
|
||||
CapCPU int `json:"cap_cpu"` //可分配CPU总额
|
||||
CapMem int `json:"cap_mem"` //可分配Mem总额
|
||||
HealthCapCPU int `json:"health_cap_cpu"` //健康可分配CPU
|
||||
HealthCapMem int `json:"health_cap_mem"` //健康可分配Mem
|
||||
UnhealthCapCPU int `json:"unhealth_cap_cpu"` //不健康可分配CPU
|
||||
UnhealthCapMem int `json:"unhealth_cap_mem"` //不健康可分配Mem
|
||||
ReqCPU float32 `json:"req_cpu"` //已使用CPU总额
|
||||
ReqMem int `json:"req_mem"` //已使用Mem总额
|
||||
HealthReqCPU float32 `json:"health_req_cpu"` //健康已使用CPU
|
||||
HealthReqMem int `json:"health_req_mem"` //健康已使用Mem
|
||||
UnhealthReqCPU float32 `json:"unhealth_req_cpu"` //不健康已使用CPU
|
||||
UnhealthReqMem int `json:"unhealth_req_mem"` //不健康已使用Mem
|
||||
CapDisk uint64 `json:"cap_disk"`
|
||||
ReqDisk uint64 `json:"req_disk"`
|
||||
}
|
||||
|
||||
//ClusterInterface cluster api
|
||||
type ClusterInterface interface {
|
||||
GetClusterInfo() (*model.ClusterResource, *util.APIHandleError)
|
||||
GetClusterInfo() (*ClusterResource, *util.APIHandleError)
|
||||
GetClusterHealth() (*utilhttp.ResponseBody, *util.APIHandleError)
|
||||
}
|
||||
|
||||
@ -39,8 +60,8 @@ type cluster struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (c *cluster) GetClusterInfo() (*model.ClusterResource, *util.APIHandleError) {
|
||||
var cr model.ClusterResource
|
||||
func (c *cluster) GetClusterInfo() (*ClusterResource, *util.APIHandleError) {
|
||||
var cr ClusterResource
|
||||
var decode utilhttp.ResponseBody
|
||||
decode.Bean = &cr
|
||||
code, err := c.DoRequest(c.prefix, "GET", nil, &decode)
|
||||
|
@ -1,164 +0,0 @@
|
||||
// RAINBOND, Application Management Platform
|
||||
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package region
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"github.com/goodrain/rainbond/node/api/model"
|
||||
utilhttp "github.com/goodrain/rainbond/util/http"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// MonitorInterface cluster api
|
||||
type MonitorInterface interface {
|
||||
GetRule(name string) (*model.AlertingNameConfig, *util.APIHandleError)
|
||||
GetAllRule() (*model.AlertingRulesConfig, *util.APIHandleError)
|
||||
DelRule(name string) (*utilhttp.ResponseBody, *util.APIHandleError)
|
||||
AddRule(path string) (*utilhttp.ResponseBody, *util.APIHandleError)
|
||||
RegRule(ruleName string, path string) (*utilhttp.ResponseBody, *util.APIHandleError)
|
||||
}
|
||||
|
||||
func (r *regionImpl) Monitor() MonitorInterface {
|
||||
return &monitor{prefix: "/v2/rules", regionImpl: *r}
|
||||
}
|
||||
|
||||
type monitor struct {
|
||||
regionImpl
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (m *monitor) GetRule(name string) (*model.AlertingNameConfig, *util.APIHandleError) {
|
||||
var ac model.AlertingNameConfig
|
||||
var decode utilhttp.ResponseBody
|
||||
decode.Bean = &ac
|
||||
code, err := m.DoRequest(m.prefix+"/"+name, "GET", nil, &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Bean)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("get alerting rules error code %d", code))
|
||||
}
|
||||
return &ac, nil
|
||||
}
|
||||
|
||||
func (m *monitor) GetAllRule() (*model.AlertingRulesConfig, *util.APIHandleError) {
|
||||
var ac model.AlertingRulesConfig
|
||||
var decode utilhttp.ResponseBody
|
||||
decode.Bean = &ac
|
||||
code, err := m.DoRequest(m.prefix+"/all", "GET", nil, &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Bean)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("get alerting rules error code %d", code))
|
||||
}
|
||||
return &ac, nil
|
||||
}
|
||||
|
||||
func (m *monitor) DelRule(name string) (*utilhttp.ResponseBody, *util.APIHandleError) {
|
||||
var decode utilhttp.ResponseBody
|
||||
code, err := m.DoRequest(m.prefix+"/"+name, "DELETE", nil, &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Bean)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("del alerting rules error code %d", code))
|
||||
}
|
||||
return &decode, nil
|
||||
}
|
||||
|
||||
func (m *monitor) AddRule(path string) (*utilhttp.ResponseBody, *util.APIHandleError) {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return nil, util.CreateAPIHandleError(400, errors.New("file does not exist"))
|
||||
}
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
logrus.Error("Failed to read AlertingRules config file: ", err.Error())
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
var rulesConfig model.AlertingNameConfig
|
||||
if err := yaml.Unmarshal(content, &rulesConfig); err != nil {
|
||||
logrus.Error("Unmarshal AlertingRulesConfig config string to object error.", err.Error())
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
|
||||
}
|
||||
var decode utilhttp.ResponseBody
|
||||
body, err := json.Marshal(rulesConfig)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
code, err := m.DoRequest(m.prefix, "POST", bytes.NewBuffer(body), &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Bean)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("add alerting rules error code %d", code))
|
||||
}
|
||||
return &decode, nil
|
||||
}
|
||||
|
||||
func (m *monitor) RegRule(ruleName string, path string) (*utilhttp.ResponseBody, *util.APIHandleError) {
|
||||
_, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return nil, util.CreateAPIHandleError(400, errors.New("file does not exist"))
|
||||
}
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
logrus.Error("Failed to read AlertingRules config file: ", err.Error())
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
var rulesConfig model.AlertingNameConfig
|
||||
if err := yaml.Unmarshal(content, &rulesConfig); err != nil {
|
||||
logrus.Error("Unmarshal AlertingRulesConfig config string to object error.", err.Error())
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
|
||||
}
|
||||
var decode utilhttp.ResponseBody
|
||||
body, err := json.Marshal(rulesConfig)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
code, err := m.DoRequest(m.prefix+"/"+ruleName, "PUT", bytes.NewBuffer(body), &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Bean)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("add alerting rules error code %d", code))
|
||||
}
|
||||
return &decode, nil
|
||||
}
|
@ -1,369 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package region
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/goodrain/rainbond/node/api/model"
|
||||
"github.com/goodrain/rainbond/node/nodem/client"
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
|
||||
//"github.com/goodrain/rainbond/grctl/cmd"
|
||||
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
utilhttp "github.com/goodrain/rainbond/util/http"
|
||||
)
|
||||
|
||||
func (r *regionImpl) Nodes() NodeInterface {
|
||||
return &node{regionImpl: *r, prefix: "/v2/nodes"}
|
||||
}
|
||||
func (r *regionImpl) Configs() ConfigsInterface {
|
||||
return &configs{regionImpl: *r, prefix: "/v2/configs"}
|
||||
}
|
||||
|
||||
type task struct {
|
||||
regionImpl
|
||||
prefix string
|
||||
}
|
||||
type node struct {
|
||||
regionImpl
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (n *node) Get(node string) (*client.HostNode, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc client.HostNode
|
||||
res.Bean = &gc
|
||||
code, err := n.DoRequest(n.prefix+"/"+node, "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Get node detail code %d", code))
|
||||
}
|
||||
return &gc, nil
|
||||
}
|
||||
|
||||
func (n *node) GetNodeResource(node string) (*client.NodePodResource, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc client.NodePodResource
|
||||
res.Bean = &gc
|
||||
code, err := n.DoRequest(n.prefix+"/"+node+"/resource", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Get node resource code %d", code))
|
||||
}
|
||||
return &gc, nil
|
||||
}
|
||||
|
||||
func (n *node) GetNodeByRule(rule string) ([]*client.HostNode, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc []*client.HostNode
|
||||
res.List = &gc
|
||||
code, err := n.DoRequest(n.prefix+"/rule/"+rule, "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Get node rule code %d", code))
|
||||
}
|
||||
return gc, nil
|
||||
}
|
||||
func (n *node) UpdateNodeStatus(nid, status string) (*client.HostNode, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc client.HostNode
|
||||
res.Bean = &gc
|
||||
req := fmt.Sprintf(`{"status":"%s"}`, status)
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/status", "PUT", bytes.NewBuffer([]byte(req)), &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Update node status failure code %d", code))
|
||||
}
|
||||
return &gc, nil
|
||||
}
|
||||
func (n *node) List() ([]*client.HostNode, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc []*client.HostNode
|
||||
res.List = &gc
|
||||
code, err := n.DoRequest(n.prefix, "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Get node list code %d", code))
|
||||
}
|
||||
return gc, nil
|
||||
}
|
||||
|
||||
func (n *node) GetAllNodeHealth() (map[string][]map[string]string, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc map[string][]map[string]string
|
||||
res.Bean = &gc
|
||||
code, err := n.DoRequest(n.prefix+"/all_node_health", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if code != 200 {
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf("Get node health code %d", code))
|
||||
}
|
||||
return gc, nil
|
||||
}
|
||||
|
||||
func (n *node) Add(node *client.APIHostNode) (*client.HostNode, *util.APIHandleError) {
|
||||
body, err := json.Marshal(node)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
var res utilhttp.ResponseBody
|
||||
var renode client.HostNode
|
||||
res.Bean = &renode
|
||||
code, err := n.DoRequest(n.prefix, "POST", bytes.NewBuffer(body), &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return &renode, handleAPIResult(code, res)
|
||||
}
|
||||
func (n *node) Label(nid string) NodeLabelInterface {
|
||||
return &nodeLabelImpl{nodeImpl: n, NodeID: nid}
|
||||
}
|
||||
func (n *node) Condition(nid string) NodeConditionInterface {
|
||||
return &nodeConditionImpl{nodeImpl: n, NodeID: nid}
|
||||
}
|
||||
|
||||
type nodeLabelImpl struct {
|
||||
nodeImpl *node
|
||||
NodeID string
|
||||
}
|
||||
|
||||
func (nl *nodeLabelImpl) List() (map[string]string, *util.APIHandleError) {
|
||||
var decode map[string]string
|
||||
var res utilhttp.ResponseBody
|
||||
res.Bean = &decode
|
||||
code, err := nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/labels", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return decode, handleAPIResult(code, res)
|
||||
}
|
||||
func (nl *nodeLabelImpl) Delete(k string) *util.APIHandleError {
|
||||
var decode map[string]string
|
||||
var res utilhttp.ResponseBody
|
||||
res.Bean = &decode
|
||||
code, err := nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/labels", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if handleAPIResult(code, res) != nil {
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
delete(decode, k)
|
||||
body, err := json.Marshal(decode)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
code, err = nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/labels", "PUT", bytes.NewBuffer(body), &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
func (nl *nodeLabelImpl) Add(k, v string) *util.APIHandleError {
|
||||
var decode map[string]string
|
||||
var res utilhttp.ResponseBody
|
||||
res.Bean = &decode
|
||||
code, err := nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/labels", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
if handleAPIResult(code, res) != nil {
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
decode[k] = v
|
||||
body, err := json.Marshal(decode)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
code, err = nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/labels", "PUT", bytes.NewBuffer(body), &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
type nodeConditionImpl struct {
|
||||
nodeImpl *node
|
||||
NodeID string
|
||||
}
|
||||
|
||||
func (nl *nodeConditionImpl) List() ([]client.NodeCondition, *util.APIHandleError) {
|
||||
var decode []client.NodeCondition
|
||||
var res utilhttp.ResponseBody
|
||||
res.List = &decode
|
||||
code, err := nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/conditions", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return decode, handleAPIResult(code, res)
|
||||
}
|
||||
func (nl *nodeConditionImpl) Delete(k client.NodeConditionType) ([]client.NodeCondition, *util.APIHandleError) {
|
||||
var decode []client.NodeCondition
|
||||
var res utilhttp.ResponseBody
|
||||
res.List = &decode
|
||||
code, err := nl.nodeImpl.DoRequest(nl.nodeImpl.prefix+"/"+nl.NodeID+"/conditions/"+string(k), "DELETE", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return decode, handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
func (n *node) Delete(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid, "DELETE", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
func (n *node) Up(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/up", "POST", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
func (n *node) Down(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/down", "POST", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
func (n *node) UnSchedulable(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/unschedulable", "PUT", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
func (n *node) ReSchedulable(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/reschedulable", "PUT", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
func (n *node) Install(nid string) *util.APIHandleError {
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := n.DoRequest(n.prefix+"/"+nid+"/install", "POST", nil, &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
type configs struct {
|
||||
regionImpl
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (c *configs) Get() (*model.GlobalConfig, *util.APIHandleError) {
|
||||
var res utilhttp.ResponseBody
|
||||
var gc = model.GlobalConfig{
|
||||
Configs: make(map[string]*model.ConfigUnit),
|
||||
}
|
||||
res.Bean = &gc
|
||||
code, err := c.DoRequest(c.prefix+"/datacenter", "GET", nil, &res)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return &gc, handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
func (c *configs) Put(gc *model.GlobalConfig) *util.APIHandleError {
|
||||
rebody, err := ffjson.Marshal(gc)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(400, err)
|
||||
}
|
||||
var res utilhttp.ResponseBody
|
||||
code, err := c.DoRequest(c.prefix+"/datacenter", "PUT", bytes.NewBuffer(rebody), &res)
|
||||
if err != nil {
|
||||
return util.CreateAPIHandleError(code, err)
|
||||
}
|
||||
return handleAPIResult(code, res)
|
||||
}
|
||||
|
||||
//TaskInterface task api
|
||||
type TaskInterface interface {
|
||||
Get(name string) (*model.Task, *util.APIHandleError)
|
||||
GetTaskStatus(task string) (map[string]*model.TaskStatus, *util.APIHandleError)
|
||||
Add(task *model.Task) *util.APIHandleError
|
||||
AddGroup(group *model.TaskGroup) *util.APIHandleError
|
||||
Exec(name string, nodes []string) *util.APIHandleError
|
||||
List() ([]*model.Task, *util.APIHandleError)
|
||||
}
|
||||
|
||||
//NodeInterface node api
|
||||
type NodeInterface interface {
|
||||
GetNodeByRule(rule string) ([]*client.HostNode, *util.APIHandleError)
|
||||
Get(node string) (*client.HostNode, *util.APIHandleError)
|
||||
GetNodeResource(node string) (*client.NodePodResource, *util.APIHandleError)
|
||||
List() ([]*client.HostNode, *util.APIHandleError)
|
||||
GetAllNodeHealth() (map[string][]map[string]string, *util.APIHandleError)
|
||||
Add(node *client.APIHostNode) (*client.HostNode, *util.APIHandleError)
|
||||
Up(nid string) *util.APIHandleError
|
||||
Down(nid string) *util.APIHandleError
|
||||
UnSchedulable(nid string) *util.APIHandleError
|
||||
ReSchedulable(nid string) *util.APIHandleError
|
||||
Delete(nid string) *util.APIHandleError
|
||||
Label(nid string) NodeLabelInterface
|
||||
Condition(nid string) NodeConditionInterface
|
||||
Install(nid string) *util.APIHandleError
|
||||
UpdateNodeStatus(nid, status string) (*client.HostNode, *util.APIHandleError)
|
||||
}
|
||||
|
||||
//NodeLabelInterface node label interface
|
||||
type NodeLabelInterface interface {
|
||||
Add(k, v string) *util.APIHandleError
|
||||
Delete(k string) *util.APIHandleError
|
||||
List() (map[string]string, *util.APIHandleError)
|
||||
}
|
||||
|
||||
//NodeConditionInterface node condition manage api
|
||||
type NodeConditionInterface interface {
|
||||
List() ([]client.NodeCondition, *util.APIHandleError)
|
||||
Delete(conditionType client.NodeConditionType) ([]client.NodeCondition, *util.APIHandleError)
|
||||
}
|
||||
|
||||
//ConfigsInterface 数据中心配置API
|
||||
type ConfigsInterface interface {
|
||||
Get() (*model.GlobalConfig, *util.APIHandleError)
|
||||
Put(*model.GlobalConfig) *util.APIHandleError
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// RAINBOND, Application Management Platform
|
||||
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package region
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"github.com/goodrain/rainbond/node/api/model"
|
||||
utilhttp "github.com/goodrain/rainbond/util/http"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//NotificationInterface cluster api
|
||||
type NotificationInterface interface {
|
||||
GetNotification(start string, end string) ([]*model.NotificationEvent, *util.APIHandleError)
|
||||
HandleNotification(serviceName string, message string) ([]*model.NotificationEvent, *util.APIHandleError)
|
||||
}
|
||||
|
||||
func (r *regionImpl) Notification() NotificationInterface {
|
||||
return ¬ification{prefix: "/v2/notificationEvent", regionImpl: *r}
|
||||
}
|
||||
|
||||
type notification struct {
|
||||
regionImpl
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (n *notification) GetNotification(start string, end string) ([]*model.NotificationEvent, *util.APIHandleError) {
|
||||
var ne []*model.NotificationEvent
|
||||
var decode utilhttp.ResponseBody
|
||||
decode.List = &ne
|
||||
code, err := n.DoRequest(n.prefix+"?start="+start+"&"+"end="+end, "GET", nil, &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Msg)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf(decode.Msg))
|
||||
}
|
||||
return ne, nil
|
||||
}
|
||||
|
||||
func (n *notification) HandleNotification(serviceName string, message string) ([]*model.NotificationEvent, *util.APIHandleError) {
|
||||
var ne []*model.NotificationEvent
|
||||
var decode utilhttp.ResponseBody
|
||||
decode.List = &ne
|
||||
handleMessage, err := json.Marshal(map[string]string{"handle_message": message})
|
||||
body := bytes.NewBuffer(handleMessage)
|
||||
code, err := n.DoRequest(n.prefix+"/"+serviceName, "PUT", body, &decode)
|
||||
if err != nil {
|
||||
return nil, handleErrAndCode(err, code)
|
||||
}
|
||||
if code != 200 {
|
||||
logrus.Error("Return failure message ", decode.Msg)
|
||||
return nil, util.CreateAPIHandleError(code, fmt.Errorf(decode.Msg))
|
||||
}
|
||||
return ne, nil
|
||||
}
|
@ -48,12 +48,8 @@ var AllTenant string
|
||||
type Region interface {
|
||||
Tenants(name string) TenantInterface
|
||||
Resources() ResourcesInterface
|
||||
Nodes() NodeInterface
|
||||
Cluster() ClusterInterface
|
||||
Configs() ConfigsInterface
|
||||
Version() string
|
||||
Monitor() MonitorInterface
|
||||
Notification() NotificationInterface
|
||||
DoRequest(path, method string, body io.Reader, decode *utilhttp.ResponseBody) (int, error)
|
||||
}
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
// RAINBOND, Application Management Platform
|
||||
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package region
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
utilhttp "github.com/goodrain/rainbond/util/http"
|
||||
)
|
||||
|
||||
func TestListTenant(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"http://kubeapi.goodrain.me:8888"},
|
||||
})
|
||||
tenants, err := region.Tenants("").List()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%+v", tenants)
|
||||
}
|
||||
|
||||
func TestListServices(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"http://kubeapi.goodrain.me:8888"},
|
||||
})
|
||||
services, err := region.Tenants("n93lkp7t").Services("").List()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, s := range services {
|
||||
t.Logf("%+v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoRequest(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"http://kubeapi.goodrain.me:8888"},
|
||||
})
|
||||
var decode utilhttp.ResponseBody
|
||||
var tenants []*dbmodel.Tenants
|
||||
decode.List = &tenants
|
||||
code, err := region.DoRequest("/v2/tenants", "GET", nil, &decode)
|
||||
if err != nil {
|
||||
t.Fatal(err, code)
|
||||
}
|
||||
t.Logf("%+v", tenants)
|
||||
}
|
||||
|
||||
func TestListNodes(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"http://kubeapi.goodrain.me:8888"},
|
||||
})
|
||||
services, err := region.Nodes().List()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, s := range services {
|
||||
t.Logf("%+v", s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNodes(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"http://kubeapi.goodrain.me:8888"},
|
||||
})
|
||||
node, err := region.Nodes().Get("a134eab8-3d42-40f5-84a5-fcf2b7a44b31")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%+v", node)
|
||||
}
|
||||
|
||||
func TestGetTenantsBySSL(t *testing.T) {
|
||||
region, _ := NewRegion(APIConf{
|
||||
Endpoints: []string{"https://127.0.0.1:8443"},
|
||||
Cacert: "/Users/qingguo/gopath/src/github.com/goodrain/rainbond/test/ssl/ca.pem",
|
||||
Cert: "/Users/qingguo/gopath/src/github.com/goodrain/rainbond/test/ssl/client.pem",
|
||||
CertKey: "/Users/qingguo/gopath/src/github.com/goodrain/rainbond/test/ssl/client.key.pem",
|
||||
})
|
||||
tenants, err := region.Tenants("").List()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%+v", tenants)
|
||||
}
|
@ -22,6 +22,7 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -30,6 +31,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
"github.com/goodrain/rainbond/api/webcli/app"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prometheus/common/version"
|
||||
@ -42,9 +44,7 @@ import (
|
||||
"github.com/goodrain/rainbond/api/api_routers/doc"
|
||||
"github.com/goodrain/rainbond/api/api_routers/license"
|
||||
"github.com/goodrain/rainbond/api/metric"
|
||||
"github.com/goodrain/rainbond/api/proxy"
|
||||
|
||||
"github.com/goodrain/rainbond/api/api_routers/cloud"
|
||||
"github.com/goodrain/rainbond/api/api_routers/version2"
|
||||
"github.com/goodrain/rainbond/api/api_routers/websocket"
|
||||
|
||||
@ -62,20 +62,26 @@ type Manager struct {
|
||||
conf option.Config
|
||||
stopChan chan struct{}
|
||||
r *chi.Mux
|
||||
prometheusProxy proxy.Proxy
|
||||
etcdcli *clientv3.Client
|
||||
exporter *metric.Exporter
|
||||
websocketModuls map[string]CustomModule
|
||||
}
|
||||
|
||||
//CustomModule custom module set route for api
|
||||
type CustomModule interface {
|
||||
SetRoute(*chi.Mux) error
|
||||
}
|
||||
|
||||
//NewManager newManager
|
||||
func NewManager(c option.Config, etcdcli *clientv3.Client) *Manager {
|
||||
func NewManager(c option.Config, etcdcli *clientv3.Client, webapp *app.App) *Manager {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
manager := &Manager{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
conf: c,
|
||||
stopChan: make(chan struct{}),
|
||||
etcdcli: etcdcli,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
conf: c,
|
||||
stopChan: make(chan struct{}),
|
||||
etcdcli: etcdcli,
|
||||
websocketModuls: map[string]CustomModule{"webapp": webapp},
|
||||
}
|
||||
r := chi.NewRouter()
|
||||
manager.r = r
|
||||
@ -144,7 +150,7 @@ func (m *Manager) Stop() error {
|
||||
}
|
||||
|
||||
//Run run
|
||||
func (m *Manager) Run() {
|
||||
func (m *Manager) Run() error {
|
||||
v2R := &version2.V2{
|
||||
Cfg: &m.conf,
|
||||
}
|
||||
@ -156,22 +162,24 @@ func (m *Manager) Run() {
|
||||
res.Write([]byte("ok"))
|
||||
})
|
||||
m.r.Mount("/v2", v2R.Routes())
|
||||
m.r.Mount("/cloud", cloud.Routes())
|
||||
m.r.Mount("/", doc.Routes())
|
||||
m.r.Mount("/license", license.Routes())
|
||||
//兼容老版docker
|
||||
m.r.Get("/v1/etcd/event-log/instances", m.EventLogInstance)
|
||||
|
||||
m.r.Get("/kubernetes/dashboard", m.KuberntesDashboardAPI)
|
||||
//prometheus单节点代理
|
||||
m.r.Get("/api/v1/query", m.PrometheusAPI)
|
||||
m.r.Get("/api/v1/query_range", m.PrometheusAPI)
|
||||
//开启对浏览器的websocket服务和文件服务
|
||||
|
||||
//set websocket route
|
||||
websocketRouter := chi.NewRouter()
|
||||
websocketRouter.Mount("/", websocket.Routes())
|
||||
websocketRouter.Mount("/logs", websocket.LogRoutes())
|
||||
websocketRouter.Mount("/app", websocket.AppRoutes())
|
||||
for _, c := range m.websocketModuls {
|
||||
if err := c.SetRoute(websocketRouter); err != nil {
|
||||
return fmt.Errorf("set websocket custom route failire %s", err.Error())
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
websocketRouter := chi.NewRouter()
|
||||
websocketRouter.Mount("/", websocket.Routes())
|
||||
websocketRouter.Mount("/logs", websocket.LogRoutes())
|
||||
websocketRouter.Mount("/app", websocket.AppRoutes())
|
||||
if m.conf.WebsocketSSL {
|
||||
logrus.Infof("websocket listen on (HTTPs) %s", m.conf.WebsocketAddr)
|
||||
logrus.Fatal(http.ListenAndServeTLS(m.conf.WebsocketAddr, m.conf.WebsocketCertFile, m.conf.WebsocketKeyFile, websocketRouter))
|
||||
@ -203,30 +211,7 @@ func (m *Manager) Run() {
|
||||
}
|
||||
logrus.Infof("api listen on (HTTP) %s", m.conf.APIAddr)
|
||||
logrus.Fatal(http.ListenAndServe(m.conf.APIAddr, m.r))
|
||||
}
|
||||
|
||||
//EventLogInstance 查询event server instance
|
||||
func (m *Manager) EventLogInstance(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithCancel(m.ctx)
|
||||
defer cancel()
|
||||
|
||||
res, err := m.etcdcli.Get(ctx, "/event/instance", clientv3.WithPrefix())
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
if res.Kvs != nil && len(res.Kvs) > 0 {
|
||||
result := `{"data":{"instance":[`
|
||||
for _, kv := range res.Kvs {
|
||||
result += string(kv.Value) + ","
|
||||
}
|
||||
result = result[:len(result)-1] + `]},"ok":true}`
|
||||
w.Write([]byte(result))
|
||||
w.WriteHeader(200)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(404)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
//PrometheusAPI prometheus api 代理
|
||||
@ -254,7 +239,7 @@ func (m *Manager) RequestMetric(next http.Handler) http.Handler {
|
||||
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
||||
defer func() {
|
||||
path := r.RequestURI
|
||||
if strings.Index(r.RequestURI, "?") > -1 {
|
||||
if strings.Contains(r.RequestURI, "?") {
|
||||
path = r.RequestURI[:strings.Index(r.RequestURI, "?")]
|
||||
}
|
||||
m.exporter.RequestInc(ww.Status(), path)
|
||||
|
@ -23,31 +23,26 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"github.com/barnettZQG/gotty/server"
|
||||
"github.com/barnettZQG/gotty/webtty"
|
||||
httputil "github.com/goodrain/rainbond/util/http"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/yudai/umutex"
|
||||
api "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
//ExecuteCommandTotal metric
|
||||
@ -65,9 +60,9 @@ type App struct {
|
||||
titleTemplate *template.Template
|
||||
|
||||
onceMutex *umutex.UnblockingMutex
|
||||
restClient *restclient.RESTClient
|
||||
restClient *rest.RESTClient
|
||||
coreClient *kubernetes.Clientset
|
||||
config *restclient.Config
|
||||
config *rest.Config
|
||||
}
|
||||
|
||||
//Options options
|
||||
@ -92,11 +87,9 @@ var Version = "0.0.2"
|
||||
|
||||
//DefaultOptions -
|
||||
var DefaultOptions = Options{
|
||||
Address: "",
|
||||
Port: "8080",
|
||||
PermitWrite: true,
|
||||
IndexFile: "",
|
||||
TitleFormat: "GRTTY Command",
|
||||
TitleFormat: "GRTTY Command For Component Instance",
|
||||
EnableReconnect: true,
|
||||
ReconnectTime: 10,
|
||||
CloseSignal: 1, // syscall.SIGHUP
|
||||
@ -137,63 +130,17 @@ func New(options *Options) (*App, error) {
|
||||
return app, nil
|
||||
}
|
||||
|
||||
//Run Run
|
||||
func (app *App) Run() error {
|
||||
|
||||
endpoint := net.JoinHostPort(app.options.Address, app.options.Port)
|
||||
|
||||
wsHandler := http.HandlerFunc(app.handleWS)
|
||||
health := http.HandlerFunc(app.healthCheck)
|
||||
|
||||
var siteMux = http.NewServeMux()
|
||||
|
||||
siteHandler := http.Handler(siteMux)
|
||||
|
||||
siteHandler = wrapHeaders(siteHandler)
|
||||
|
||||
exporter := NewExporter()
|
||||
prometheus.MustRegister(exporter)
|
||||
|
||||
wsMux := http.NewServeMux()
|
||||
wsMux.Handle("/", siteHandler)
|
||||
wsMux.Handle("/docker_console", wsHandler)
|
||||
wsMux.Handle("/health", health)
|
||||
wsMux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
siteHandler = (http.Handler(wsMux))
|
||||
|
||||
siteHandler = wrapLogger(siteHandler)
|
||||
|
||||
server, err := app.makeServer(endpoint, &siteHandler)
|
||||
if err != nil {
|
||||
return errors.New("Failed to build server: " + err.Error())
|
||||
}
|
||||
go func() {
|
||||
logrus.Printf("webcli listen %s", endpoint)
|
||||
logrus.Fatal(server.ListenAndServe())
|
||||
logrus.Printf("Exiting...")
|
||||
}()
|
||||
//SetRoute -
|
||||
func (app *App) SetRoute(route *chi.Mux) error {
|
||||
route.Handle("/docker_console", http.HandlerFunc(app.handleWS))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) makeServer(addr string, handler *http.Handler) (*http.Server, error) {
|
||||
server := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: *handler,
|
||||
}
|
||||
|
||||
return server, nil
|
||||
}
|
||||
|
||||
func (app *App) healthCheck(w http.ResponseWriter, r *http.Request) {
|
||||
httputil.ReturnSuccess(r, w, map[string]string{"status": "health", "info": "webcli service health"})
|
||||
}
|
||||
|
||||
func (app *App) handleWS(w http.ResponseWriter, r *http.Request) {
|
||||
logrus.Printf("New client connected: %s", r.RemoteAddr)
|
||||
|
||||
if r.Method != "GET" {
|
||||
http.Error(w, "Method not allowed", 405)
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
@ -215,7 +162,7 @@ func (app *App) handleWS(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var init InitMessage
|
||||
|
||||
err = json.Unmarshal(stream, &init)
|
||||
_ = json.Unmarshal(stream, &init)
|
||||
|
||||
//todo auth
|
||||
if init.PodName == "" {
|
||||
@ -278,11 +225,6 @@ func (app *App) handleWS(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
//Exit -
|
||||
func (app *App) Exit() (firstCall bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
func (app *App) createKubeClient() error {
|
||||
config, err := k8sutil.NewRestConfig(app.options.K8SConfPath)
|
||||
if err != nil {
|
||||
@ -295,7 +237,7 @@ func (app *App) createKubeClient() error {
|
||||
}
|
||||
SetConfigDefaults(config)
|
||||
app.config = config
|
||||
restClient, err := restclient.RESTClientFor(config)
|
||||
restClient, err := rest.RESTClientFor(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -342,7 +284,7 @@ func (app *App) GetContainerArgs(namespace, podname, containerName string) (stri
|
||||
}
|
||||
|
||||
//NewRequest new exec request
|
||||
func (app *App) NewRequest(podName, namespace, containerName string, command []string) *restclient.Request {
|
||||
func (app *App) NewRequest(podName, namespace, containerName string, command []string) *rest.Request {
|
||||
// TODO: consider abstracting into a client invocation or client helper
|
||||
req := app.restClient.Post().
|
||||
Resource("pods").
|
||||
@ -360,21 +302,6 @@ func (app *App) NewRequest(podName, namespace, containerName string, command []s
|
||||
return req
|
||||
}
|
||||
|
||||
func wrapLogger(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
rw := &responseWrapper{w, 200}
|
||||
handler.ServeHTTP(rw, r)
|
||||
logrus.Printf("%s %d %s %s", r.RemoteAddr, rw.status, r.Method, r.URL.Path)
|
||||
})
|
||||
}
|
||||
|
||||
func wrapHeaders(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Server", "GoTTY/"+Version)
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func md5Func(str string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(str))
|
@ -7,7 +7,7 @@ import (
|
||||
// Metric name parts.
|
||||
const (
|
||||
// Namespace for all metrics.
|
||||
namespace = "webcli"
|
||||
namespace = "api"
|
||||
// Subsystem(s).
|
||||
exporter = "exporter"
|
||||
)
|
@ -22,7 +22,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/goodrain/rainbond/webcli/term"
|
||||
"github.com/goodrain/rainbond/api/webcli/term"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -16,10 +16,9 @@ import (
|
||||
jobc "github.com/goodrain/rainbond/builder/job"
|
||||
"github.com/goodrain/rainbond/builder/parser/code"
|
||||
"github.com/goodrain/rainbond/builder/sources"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@ -36,7 +35,6 @@ func TestCreateJob(t *testing.T) {
|
||||
}
|
||||
event.NewManager(event.EventConfig{
|
||||
EventLogServers: conf.EventLogServers,
|
||||
DiscoverArgs: &etcdutil.ClientArgs{Endpoints: conf.EtcdEndPoints},
|
||||
})
|
||||
restConfig, err := k8sutil.NewRestConfig("/Users/fanyangyang/Documents/company/goodrain/remote/192.168.2.206/admin.kubeconfig")
|
||||
if err != nil {
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/builder/exector"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
"github.com/goodrain/rainbond/mq/client"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -35,7 +35,7 @@ import (
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/goodrain/rainbond/builder/job"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/db"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
|
@ -30,12 +30,11 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/goodrain/rainbond/builder/parser/code"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
|
||||
mqclient "github.com/goodrain/rainbond/mq/client"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
)
|
||||
|
||||
@ -48,10 +47,8 @@ func Test_exectorManager_buildFromSourceCode(t *testing.T) {
|
||||
RbdNamespace: "rbd-system",
|
||||
MysqlConnectionInfo: "EeM2oc:lee7OhQu@tcp(192.168.2.203:3306)/region",
|
||||
}
|
||||
etcdArgs := etcdutil.ClientArgs{Endpoints: conf.EtcdEndPoints}
|
||||
event.NewManager(event.EventConfig{
|
||||
EventLogServers: conf.EventLogServers,
|
||||
DiscoverArgs: &etcdArgs,
|
||||
})
|
||||
restConfig, err := k8sutil.NewRestConfig("/Users/fanyangyang/Documents/company/goodrain/admin.kubeconfig")
|
||||
if err != nil {
|
||||
@ -72,7 +69,7 @@ func Test_exectorManager_buildFromSourceCode(t *testing.T) {
|
||||
} else {
|
||||
maxConcurrentTask = conf.MaxTasks
|
||||
}
|
||||
mqClient, err := mqclient.NewMqClient(&etcdArgs, conf.MQAPI)
|
||||
mqClient, err := mqclient.NewMqClient(conf.MQAPI)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
eventutil "github.com/goodrain/rainbond/eventlog/util"
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -1,54 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Discoverier blablabla
|
||||
type Discoverier interface {
|
||||
Connect() error
|
||||
Fetch() ([]*Endpoint, error)
|
||||
Close() error
|
||||
}
|
||||
|
||||
// NewDiscoverier creates a new Discoverier
|
||||
func NewDiscoverier(info *Info) Discoverier {
|
||||
switch strings.ToUpper(info.Type) {
|
||||
case "ETCD":
|
||||
return NewEtcd(info)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Info holds service discovery center information.
|
||||
type Info struct {
|
||||
Type string `json:"type"`
|
||||
Servers []string `json:"servers"`
|
||||
Key string `json:"key"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// Endpoint holds endpoint and endpoint status(online or offline).
|
||||
type Endpoint struct {
|
||||
Ep string `json:"endpoint"`
|
||||
IsOnline bool `json:"is_online"`
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discovery
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
c "github.com/coreos/etcd/clientv3"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Etcd implements Discoverier
|
||||
type etcd struct {
|
||||
cli *c.Client
|
||||
endpoints []string
|
||||
key string
|
||||
username string
|
||||
password string
|
||||
}
|
||||
|
||||
// NewEtcd creates a new Discorvery which implemeted by etcd.
|
||||
func NewEtcd(info *Info) Discoverier {
|
||||
// TODO: validate endpoints
|
||||
return &etcd{
|
||||
endpoints: info.Servers,
|
||||
key: info.Key,
|
||||
username: info.Username,
|
||||
password: info.Password,
|
||||
}
|
||||
}
|
||||
|
||||
// Connect connects a etcdv3 client with a given configuration.
|
||||
func (e *etcd) Connect() error {
|
||||
cli, err := c.New(c.Config{
|
||||
Endpoints: e.endpoints,
|
||||
DialTimeout: 10 * time.Second,
|
||||
Username: e.username,
|
||||
Password: e.password,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("Endpoints: %s; error connecting etcd: %v", strings.Join(e.endpoints, ","), err)
|
||||
return err
|
||||
}
|
||||
e.cli = cli
|
||||
return nil
|
||||
}
|
||||
|
||||
// Fetch fetches data from Etcd.
|
||||
func (e *etcd) Fetch() ([]*Endpoint, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if e.cli == nil {
|
||||
return nil, fmt.Errorf("can't fetching data from etcd without etcdv3 client")
|
||||
}
|
||||
|
||||
resp, err := e.cli.Get(ctx, e.key, c.WithPrefix())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching endpoints form etcd: %v", err)
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, fmt.Errorf("error fetching endpoints form etcd: empty GetResponse")
|
||||
}
|
||||
|
||||
var res []*Endpoint
|
||||
for _, kv := range resp.Kvs {
|
||||
var ep Endpoint
|
||||
if err := json.Unmarshal(kv.Value, &ep); err != nil {
|
||||
return nil, fmt.Errorf("error parsing the data from etcd: %v", err)
|
||||
}
|
||||
ep.Ep = strings.Replace(string(kv.Key), e.key+"/", "", -1)
|
||||
res = append(res, &ep)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Close shuts down the client's etcd connections.
|
||||
func (e *etcd) Close() error {
|
||||
if e.cli != nil {
|
||||
return nil
|
||||
}
|
||||
return e.cli.Close()
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discovery
|
@ -26,7 +26,6 @@ import (
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/goodrain/rainbond/builder/parser/code"
|
||||
"github.com/goodrain/rainbond/builder/parser/discovery"
|
||||
"github.com/goodrain/rainbond/builder/parser/types"
|
||||
"github.com/goodrain/rainbond/builder/sources"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -184,8 +183,6 @@ type ServiceInfo struct {
|
||||
Memory int `json:"memory,omitempty"`
|
||||
Lang code.Lang `json:"language,omitempty"`
|
||||
ImageAlias string `json:"image_alias,omitempty"`
|
||||
//For third party services
|
||||
Endpoints []*discovery.Endpoint `json:"endpoints,omitempty"`
|
||||
//os type,default linux
|
||||
OS string `json:"os"`
|
||||
Name string `json:"name,omitempty"` // module name
|
||||
|
@ -19,22 +19,16 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/goodrain/rainbond/builder/parser/discovery"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ThirdPartyServiceParse is one of the implematation of parser.Parser
|
||||
type ThirdPartyServiceParse struct {
|
||||
sourceBody string
|
||||
|
||||
endpoints []*discovery.Endpoint
|
||||
|
||||
errors []ParseError
|
||||
logger event.Logger
|
||||
errors []ParseError
|
||||
logger event.Logger
|
||||
}
|
||||
|
||||
// CreateThirdPartyServiceParse creates a new ThirdPartyServiceParse.
|
||||
@ -53,41 +47,13 @@ func (t *ThirdPartyServiceParse) Parse() ParseErrorList {
|
||||
return nil
|
||||
}
|
||||
|
||||
var info discovery.Info
|
||||
if err := json.Unmarshal([]byte(t.sourceBody), &info); err != nil {
|
||||
logrus.Errorf("wrong source_body: %v, source_body: %s", err, t.sourceBody)
|
||||
t.logger.Error("第三方检查输入参数错误", map[string]string{"step": "parse"})
|
||||
t.errors = append(t.errors, ParseError{FatalError, "wrong input data", ""})
|
||||
return t.errors
|
||||
}
|
||||
// TODO: validate data
|
||||
|
||||
d := discovery.NewDiscoverier(&info)
|
||||
err := d.Connect()
|
||||
if err != nil {
|
||||
t.logger.Error("error connecting discovery center", map[string]string{"step": "parse"})
|
||||
t.errors = append(t.errors, ParseError{FatalError, "error connecting discovery center", "please make sure " +
|
||||
"the configuration is right and the discovery center is working."})
|
||||
return t.errors
|
||||
}
|
||||
defer d.Close()
|
||||
eps, err := d.Fetch()
|
||||
if err != nil {
|
||||
t.logger.Error("error fetching endpints", map[string]string{"step": "parse"})
|
||||
t.errors = append(t.errors, ParseError{FatalError, "error fetching endpints", "please check the given key."})
|
||||
return t.errors
|
||||
}
|
||||
t.endpoints = eps
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetServiceInfo returns information of third-party service from
|
||||
// the receiver *ThirdPartyServiceParse.
|
||||
func (t *ThirdPartyServiceParse) GetServiceInfo() []ServiceInfo {
|
||||
serviceInfo := ServiceInfo{
|
||||
Endpoints: t.endpoints,
|
||||
}
|
||||
serviceInfo := ServiceInfo{}
|
||||
return []ServiceInfo{serviceInfo}
|
||||
}
|
||||
|
||||
|
9
check.sh
9
check.sh
@ -1,5 +1,8 @@
|
||||
#!/bin/sh
|
||||
pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z $pull_number ]; then
|
||||
pull_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
|
||||
fi
|
||||
|
||||
URL="https://api.github.com/repos/goodrain/rainbond/pulls/${pull_number}/files"
|
||||
|
||||
@ -11,4 +14,4 @@ for file in ${CHANGED_MARKDOWN_FILES}; do
|
||||
golint -set_exit_status=true ${file} || exit 1
|
||||
done
|
||||
|
||||
echo "code golint check success"
|
||||
echo "code golint check success"
|
||||
|
@ -32,9 +32,7 @@ type Config struct {
|
||||
APIAddrSSL string
|
||||
DBConnectionInfo string
|
||||
EventLogServers []string
|
||||
NodeAPI []string
|
||||
BuilderAPI []string
|
||||
V1API string
|
||||
MQAPI string
|
||||
EtcdEndpoint []string
|
||||
EtcdCaFile string
|
||||
@ -48,20 +46,17 @@ type Config struct {
|
||||
WebsocketCertFile string
|
||||
WebsocketKeyFile string
|
||||
WebsocketAddr string
|
||||
Opentsdb string
|
||||
RegionTag string
|
||||
LoggerFile string
|
||||
EnableFeature []string
|
||||
Debug bool
|
||||
MinExtPort int // minimum external port
|
||||
LicensePath string
|
||||
LicSoPath string
|
||||
LogPath string
|
||||
KuberentesDashboardAPI string
|
||||
KubeConfigPath string
|
||||
PrometheusEndpoint string
|
||||
RbdNamespace string
|
||||
ShowSQL bool
|
||||
WorkerAddress string
|
||||
}
|
||||
|
||||
//APIServer apiserver server
|
||||
@ -91,29 +86,24 @@ func (a *APIServer) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&a.WebsocketSSL, "ws-ssl-enable", false, "whether to enable websocket SSL")
|
||||
fs.StringVar(&a.WebsocketCertFile, "ws-ssl-certfile", "/etc/ssl/goodrain.com/goodrain.com.crt", "websocket and fileserver ssl cert file")
|
||||
fs.StringVar(&a.WebsocketKeyFile, "ws-ssl-keyfile", "/etc/ssl/goodrain.com/goodrain.com.key", "websocket and fileserver ssl key file")
|
||||
fs.StringVar(&a.V1API, "v1-api", "127.0.0.1:8887", "the region v1 api")
|
||||
fs.StringSliceVar(&a.NodeAPI, "node-api", []string{"127.0.0.1:6100"}, "the node server api")
|
||||
fs.StringSliceVar(&a.BuilderAPI, "builder-api", []string{"rbd-chaos:3228"}, "the builder api")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"127.0.0.1:6366"}, "event log server address. simple lb")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "127.0.0.1:6300", "acp_mq api")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"rbd-eventlog:6366"}, "event log server address.")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "rbd-mq:6300", "acp_mq api")
|
||||
fs.BoolVar(&a.StartRegionAPI, "start", false, "Whether to start region old api")
|
||||
fs.StringSliceVar(&a.EtcdEndpoint, "etcd", []string{"http://127.0.0.1:2379"}, "etcd server or proxy address")
|
||||
fs.StringVar(&a.EtcdCaFile, "etcd-ca", "", "verify etcd certificates of TLS-enabled secure servers using this CA bundle")
|
||||
fs.StringVar(&a.EtcdCertFile, "etcd-cert", "", "identify secure etcd client using this TLS certificate file")
|
||||
fs.StringVar(&a.EtcdKeyFile, "etcd-key", "", "identify secure etcd client using this TLS key file")
|
||||
fs.StringVar(&a.Opentsdb, "opentsdb", "127.0.0.1:4242", "opentsdb server config")
|
||||
fs.StringVar(&a.RegionTag, "region-tag", "test-ali", "region tag setting")
|
||||
fs.StringVar(&a.LoggerFile, "logger-file", "/logs/request.log", "request log file path")
|
||||
fs.BoolVar(&a.Debug, "debug", false, "open debug will enable pprof")
|
||||
fs.IntVar(&a.MinExtPort, "min-ext-port", 0, "minimum external port")
|
||||
fs.StringArrayVar(&a.EnableFeature, "enable-feature", []string{}, "List of special features supported, such as `windows`")
|
||||
fs.StringVar(&a.LicensePath, "license-path", "/opt/rainbond/etc/license/license.yb", "the license path of the enterprise version.")
|
||||
fs.StringVar(&a.LicSoPath, "license-so-path", "/opt/rainbond/etc/license/license.so", "Dynamic library file path for parsing the license.")
|
||||
fs.StringVar(&a.LogPath, "log-path", "/grdata/logs", "Where Docker log files and event log files are stored.")
|
||||
fs.StringVar(&a.KubeConfigPath, "kube-config", "", "kube config file path, No setup is required to run in a cluster.")
|
||||
fs.StringVar(&a.KuberentesDashboardAPI, "k8s-dashboard-api", "kubernetes-dashboard.rbd-system:443", "The service DNS name of Kubernetes dashboard. Default to kubernetes-dashboard.kubernetes-dashboard")
|
||||
fs.StringVar(&a.PrometheusEndpoint, "prom-api", "rbd-monitor:9999", "The service DNS name of Prometheus api. Default to rbd-monitor:9999")
|
||||
fs.StringVar(&a.RbdNamespace, "rbd-namespace", "rbd-system", "rbd component namespace")
|
||||
fs.StringVar(&a.WorkerAddress, "worker-address", "rbd-worker:6535", "the address of worker runtime server")
|
||||
fs.BoolVar(&a.ShowSQL, "show-sql", false, "The trigger for showing sql.")
|
||||
}
|
||||
|
||||
|
@ -23,17 +23,16 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
|
||||
rainbondscheme "github.com/goodrain/rainbond/pkg/generated/clientset/versioned/scheme"
|
||||
|
||||
"github.com/goodrain/rainbond/api/controller"
|
||||
"github.com/goodrain/rainbond/api/db"
|
||||
"github.com/goodrain/rainbond/api/discover"
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
"github.com/goodrain/rainbond/api/server"
|
||||
"github.com/goodrain/rainbond/api/webcli/app"
|
||||
"github.com/goodrain/rainbond/cmd/api/option"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/pkg/generated/clientset/versioned"
|
||||
rainbondscheme "github.com/goodrain/rainbond/pkg/generated/clientset/versioned/scheme"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
"github.com/goodrain/rainbond/worker/client"
|
||||
@ -57,10 +56,6 @@ func Run(s *option.APIServer) error {
|
||||
CertFile: s.Config.EtcdCertFile,
|
||||
KeyFile: s.Config.EtcdKeyFile,
|
||||
}
|
||||
//启动服务发现
|
||||
if _, err := discover.CreateEndpointDiscover(etcdClientArgs); err != nil {
|
||||
return err
|
||||
}
|
||||
//创建db manager
|
||||
if err := db.CreateDBManager(s.Config); err != nil {
|
||||
logrus.Debugf("create db manager error, %v", err)
|
||||
@ -94,18 +89,14 @@ func Run(s *option.APIServer) error {
|
||||
|
||||
if err := event.NewManager(event.EventConfig{
|
||||
EventLogServers: s.Config.EventLogServers,
|
||||
DiscoverArgs: etcdClientArgs,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
defer event.CloseManager()
|
||||
//create app status client
|
||||
cli, err := client.NewClient(ctx, client.AppRuntimeSyncClientConf{
|
||||
EtcdEndpoints: s.Config.EtcdEndpoint,
|
||||
EtcdCaFile: s.Config.EtcdCaFile,
|
||||
EtcdCertFile: s.Config.EtcdCertFile,
|
||||
EtcdKeyFile: s.Config.EtcdKeyFile,
|
||||
NonBlock: s.Config.Debug,
|
||||
DefaultServerAddress: s.Config.WorkerAddress,
|
||||
NonBlock: s.Config.Debug,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("create app status client error, %v", err)
|
||||
@ -118,19 +109,30 @@ func Run(s *option.APIServer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
//初始化 middleware
|
||||
//init middleware
|
||||
handler.InitProxy(s.Config)
|
||||
//创建handle
|
||||
|
||||
//create handle
|
||||
if err := handler.InitHandle(s.Config, etcdClientArgs, cli, etcdcli, clientset, rainbondClient, k8sClient); err != nil {
|
||||
logrus.Errorf("init all handle error, %v", err)
|
||||
return err
|
||||
}
|
||||
//创建v2Router manager
|
||||
|
||||
// webcli modul
|
||||
option := app.DefaultOptions
|
||||
option.K8SConfPath = s.Config.KubeConfigPath
|
||||
cliapp, err := app.New(&option)
|
||||
if err != nil {
|
||||
logrus.Errorf("new webcli app failure %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// create v2Router manager
|
||||
if err := controller.CreateV2RouterManager(s.Config, cli); err != nil {
|
||||
logrus.Errorf("create v2 route manager error, %v", err)
|
||||
}
|
||||
// 启动api
|
||||
apiManager := server.NewManager(s.Config, etcdcli)
|
||||
// start server listen
|
||||
apiManager := server.NewManager(s.Config, etcdcli, cliapp)
|
||||
if err := apiManager.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -138,7 +140,7 @@ func Run(s *option.APIServer) error {
|
||||
logrus.Info("api router is running...")
|
||||
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case s := <-term:
|
||||
|
@ -23,8 +23,8 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/builder/server"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/server"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
@ -81,11 +81,11 @@ func (a *Builder) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&a.PrometheusMetricPath, "metric", "/metrics", "prometheus metrics path")
|
||||
fs.StringVar(&a.DBType, "db-type", "mysql", "db type mysql or etcd")
|
||||
fs.StringVar(&a.MysqlConnectionInfo, "mysql", "root:admin@tcp(127.0.0.1:3306)/region", "mysql db connection info")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"127.0.0.1:6366"}, "event log server address. simple lb")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"rbd-eventlog:6366"}, "event log server address. simple lb")
|
||||
fs.StringVar(&a.KubeConfig, "kube-config", "", "kubernetes api server config file")
|
||||
fs.IntVar(&a.MaxTasks, "max-tasks", 50, "Maximum number of simultaneous build tasks")
|
||||
fs.IntVar(&a.APIPort, "api-port", 3228, "the port for api server")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "127.0.0.1:6300", "acp_mq api")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "rbd-mq:6300", "acp_mq api")
|
||||
fs.StringVar(&a.RunMode, "run", "sync", "sync data when worker start")
|
||||
fs.StringVar(&a.DockerEndpoint, "dockerd", "127.0.0.1:2376", "dockerd endpoint")
|
||||
fs.StringVar(&a.HostIP, "hostIP", "", "Current node Intranet IP")
|
@ -26,7 +26,7 @@ import (
|
||||
"github.com/goodrain/rainbond/builder/discover"
|
||||
"github.com/goodrain/rainbond/builder/exector"
|
||||
"github.com/goodrain/rainbond/builder/monitor"
|
||||
"github.com/goodrain/rainbond/cmd/builder/option"
|
||||
"github.com/goodrain/rainbond/cmd/chaos/option"
|
||||
"github.com/goodrain/rainbond/db"
|
||||
"github.com/goodrain/rainbond/db/config"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
@ -36,8 +36,6 @@ import (
|
||||
|
||||
"github.com/goodrain/rainbond/builder/api"
|
||||
"github.com/goodrain/rainbond/builder/clean"
|
||||
discoverv2 "github.com/goodrain/rainbond/discover.v2"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -50,26 +48,17 @@ func Run(s *option.Builder) error {
|
||||
dbconfig := config.Config{
|
||||
DBType: s.Config.DBType,
|
||||
MysqlConnectionInfo: s.Config.MysqlConnectionInfo,
|
||||
EtcdEndPoints: s.Config.EtcdEndPoints,
|
||||
EtcdTimeout: s.Config.EtcdTimeout,
|
||||
}
|
||||
if err := db.CreateManager(dbconfig); err != nil {
|
||||
return err
|
||||
}
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: s.Config.EtcdEndPoints,
|
||||
CaFile: s.Config.EtcdCaFile,
|
||||
CertFile: s.Config.EtcdCertFile,
|
||||
KeyFile: s.Config.EtcdKeyFile,
|
||||
}
|
||||
if err := event.NewManager(event.EventConfig{
|
||||
EventLogServers: s.Config.EventLogServers,
|
||||
DiscoverArgs: etcdClientArgs,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
defer event.CloseManager()
|
||||
client, err := client.NewMqClient(etcdClientArgs, s.Config.MQAPI)
|
||||
client, err := client.NewMqClient(s.Config.MQAPI)
|
||||
if err != nil {
|
||||
logrus.Errorf("new Mq client error, %v", err)
|
||||
return err
|
||||
@ -98,15 +87,6 @@ func Run(s *option.Builder) error {
|
||||
}
|
||||
defer cle.Stop()
|
||||
}
|
||||
keepalive, err := discoverv2.CreateKeepAlive(etcdClientArgs, "builder",
|
||||
"", s.Config.HostIP, s.Config.APIPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := keepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer keepalive.Stop()
|
||||
|
||||
exporter := monitor.NewExporter(exec)
|
||||
prometheus.MustRegister(exporter)
|
||||
@ -117,7 +97,7 @@ func Run(s *option.Builder) error {
|
||||
|
||||
logrus.Info("builder begin running...")
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-term:
|
@ -27,16 +27,16 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/discover"
|
||||
"github.com/goodrain/rainbond/eventlog/cluster"
|
||||
"github.com/goodrain/rainbond/eventlog/conf"
|
||||
"github.com/goodrain/rainbond/eventlog/db"
|
||||
"github.com/goodrain/rainbond/eventlog/entry"
|
||||
"github.com/goodrain/rainbond/eventlog/exit/web"
|
||||
"github.com/goodrain/rainbond/eventlog/store"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// LogServer -
|
||||
@ -69,17 +69,10 @@ func (s *LogServer) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.IntVar(&s.Conf.Entry.MonitorMessageServer.CacheMessageSize, "monitor.cache", 200, "the monitor sub server cache the receive message size")
|
||||
fs.StringVar(&s.Conf.Entry.MonitorMessageServer.SubSubscribe, "monitor.subscribe", "ceptop", "the monitor message sub server subscribe info")
|
||||
fs.BoolVar(&s.Conf.ClusterMode, "cluster", true, "Whether open cluster mode")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.InstanceIP, "cluster.instance.ip", "", "The current instance IP in the cluster can be communications.")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.Type, "discover.type", "etcd", "the instance in cluster auto discover way.")
|
||||
fs.StringSliceVar(&s.Conf.Cluster.Discover.EtcdAddr, "discover.etcd.addr", []string{"http://127.0.0.1:2379"}, "set all etcd server addr in cluster for message instence auto discover.")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.EtcdCaFile, "discover.etcd.ca", "", "verify etcd certificates of TLS-enabled secure servers using this CA bundle")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.EtcdCertFile, "discover.etcd.cert", "", "identify secure etcd client using this TLS certificate file")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.EtcdKeyFile, "discover.etcd.key", "", "identify secure etcd client using this TLS key file")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.HomePath, "discover.etcd.homepath", "/event", "etcd home key")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.EtcdUser, "discover.etcd.user", "", "etcd server user info")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.EtcdPass, "discover.etcd.pass", "", "etcd server user password")
|
||||
fs.StringVar(&s.Conf.Cluster.HostIP, "cluster.instance.ip", "", "The current instance IP in the cluster can be communications.")
|
||||
fs.StringVar(&s.Conf.Cluster.PubSub.PubBindIP, "cluster.bind.ip", "0.0.0.0", "Cluster communication to listen the IP")
|
||||
fs.IntVar(&s.Conf.Cluster.PubSub.PubBindPort, "cluster.bind.port", 6365, "Cluster communication to listen the Port")
|
||||
fs.IntVar(&s.Conf.Cluster.ClusterPort, "cluster.leader.port", 6367, "leader server bind port")
|
||||
fs.StringVar(&s.Conf.EventStore.MessageType, "message.type", "json", "Receive and transmit the log message type.")
|
||||
fs.StringVar(&s.Conf.EventStore.GarbageMessageSaveType, "message.garbage.save", "file", "garbage message way of storage")
|
||||
fs.StringVar(&s.Conf.EventStore.GarbageMessageFile, "message.garbage.file", "/var/log/envent_garbage_message.log", "save garbage message file path when save type is file")
|
||||
@ -111,8 +104,9 @@ func (s *LogServer) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&s.Conf.EventStore.DB.HomePath, "docker.log.homepath", "/grdata/logs/", "container log persistent home path")
|
||||
fs.StringVar(&s.Conf.Entry.NewMonitorMessageServerConf.ListenerHost, "monitor.udp.host", "0.0.0.0", "receive new monitor udp server host")
|
||||
fs.IntVar(&s.Conf.Entry.NewMonitorMessageServerConf.ListenerPort, "monitor.udp.port", 6166, "receive new monitor udp server port")
|
||||
fs.StringVar(&s.Conf.Cluster.Discover.NodeID, "node-id", "", "the unique ID for this node.")
|
||||
fs.DurationVar(&s.Conf.Cluster.PubSub.PollingTimeout, "zmq4-polling-timeout", 200*time.Millisecond, "The timeout determines the time-out on the polling of sockets")
|
||||
fs.StringVar(&s.Conf.KubeConfigPath, "kubeconfig", "", "path to kubeconfig file with authorization and master location information.")
|
||||
fs.StringVar(&s.Conf.Cluster.LeaderElectionNamespace, "leader-election-namespace", "rbd-system", "Namespace where this attacher runs.")
|
||||
}
|
||||
|
||||
//InitLog 初始化log
|
||||
@ -157,11 +151,9 @@ func (s *LogServer) InitLog() {
|
||||
|
||||
//InitConf 初始化配置
|
||||
func (s *LogServer) InitConf() {
|
||||
s.Conf.Cluster.Discover.ClusterMode = s.Conf.ClusterMode
|
||||
s.Conf.Cluster.PubSub.ClusterMode = s.Conf.ClusterMode
|
||||
s.Conf.EventStore.ClusterMode = s.Conf.ClusterMode
|
||||
s.Conf.Cluster.Discover.DockerLogPort = s.Conf.Entry.DockerLogServer.BindPort
|
||||
s.Conf.Cluster.Discover.WebPort = s.Conf.WebSocket.BindPort
|
||||
s.Conf.Cluster.DockerLogPort = s.Conf.Entry.DockerLogServer.BindPort
|
||||
s.Conf.Cluster.WebsocketPort = s.Conf.WebSocket.BindPort
|
||||
if os.Getenv("MYSQL_HOST") != "" && os.Getenv("MYSQL_USER") != "" && os.Getenv("MYSQL_PASSWORD") != "" {
|
||||
s.Conf.EventStore.DB.URL = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"),
|
||||
os.Getenv("MYSQL_HOST"), os.Getenv("MYSQL_PORT"), os.Getenv("MYSQL_DATABASE"))
|
||||
@ -176,27 +168,23 @@ func (s *LogServer) Run() error {
|
||||
s.Logger.Debug("Start run server.")
|
||||
log := s.Logger
|
||||
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: s.Conf.Cluster.Discover.EtcdAddr,
|
||||
CaFile: s.Conf.Cluster.Discover.EtcdCaFile,
|
||||
CertFile: s.Conf.Cluster.Discover.EtcdCertFile,
|
||||
KeyFile: s.Conf.Cluster.Discover.EtcdKeyFile,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
etcdClient, err := etcdutil.NewClient(ctx, etcdClientArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//init new db
|
||||
if err := db.CreateDBManager(s.Conf.EventStore.DB); err != nil {
|
||||
logrus.Infof("create db manager error, %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
config, err := k8sutil.NewRestConfig(s.Conf.KubeConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storeManager, err := store.NewManager(s.Conf.EventStore, log.WithField("module", "MessageStore"))
|
||||
if err != nil {
|
||||
return err
|
||||
@ -206,15 +194,12 @@ func (s *LogServer) Run() error {
|
||||
return err
|
||||
}
|
||||
defer storeManager.Stop()
|
||||
if s.Conf.ClusterMode {
|
||||
s.Cluster = cluster.NewCluster(etcdClient, s.Conf.Cluster, log.WithField("module", "Cluster"), storeManager)
|
||||
if err := s.Cluster.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Cluster.Stop()
|
||||
s.Cluster = cluster.NewCluster(ctx, s.Conf.Cluster, clientset, log.WithField("module", "Cluster"), storeManager)
|
||||
if err := s.Cluster.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.SocketServer = web.NewSocket(s.Conf.WebSocket, s.Conf.Cluster.Discover, etcdClient,
|
||||
log.WithField("module", "SocketServer"), storeManager, s.Cluster, healthInfo)
|
||||
defer s.Cluster.Stop()
|
||||
s.SocketServer = web.NewSocket(s.Conf.WebSocket, log.WithField("module", "SocketServer"), storeManager, s.Cluster, healthInfo)
|
||||
if err := s.SocketServer.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -226,38 +211,7 @@ func (s *LogServer) Run() error {
|
||||
}
|
||||
defer s.Entry.Stop()
|
||||
|
||||
//服务注册
|
||||
grpckeepalive, err := discover.CreateKeepAlive(etcdClientArgs, "event_log_event_grpc",
|
||||
s.Conf.Cluster.Discover.NodeID, s.Conf.Cluster.Discover.InstanceIP, s.Conf.Entry.EventLogServer.BindPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := grpckeepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer grpckeepalive.Stop()
|
||||
|
||||
udpkeepalive, err := discover.CreateKeepAlive(etcdClientArgs, "event_log_event_udp",
|
||||
s.Conf.Cluster.Discover.NodeID, s.Conf.Cluster.Discover.InstanceIP, s.Conf.Entry.NewMonitorMessageServerConf.ListenerPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := udpkeepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer udpkeepalive.Stop()
|
||||
|
||||
httpkeepalive, err := discover.CreateKeepAlive(etcdClientArgs, "event_log_event_http",
|
||||
s.Conf.Cluster.Discover.NodeID, s.Conf.Cluster.Discover.InstanceIP, s.Conf.WebSocket.BindPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := httpkeepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer httpkeepalive.Stop()
|
||||
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-term:
|
||||
|
@ -36,7 +36,6 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/gateway/option"
|
||||
"github.com/goodrain/rainbond/discover"
|
||||
"github.com/goodrain/rainbond/gateway/cluster"
|
||||
"github.com/goodrain/rainbond/gateway/controller"
|
||||
"github.com/goodrain/rainbond/gateway/metric"
|
||||
@ -118,17 +117,6 @@ func Run(s *option.GWServer) error {
|
||||
}
|
||||
go startHTTPServer(s.ListenPorts.Health, mux)
|
||||
|
||||
keepalive, err := discover.CreateKeepAlive(etcdClientArgs, "gateway", s.Config.NodeName,
|
||||
s.Config.HostIP, s.ListenPorts.Health)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Debug("start keepalive")
|
||||
if err := keepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer keepalive.Stop()
|
||||
|
||||
logrus.Info("RBD app gateway start success!")
|
||||
|
||||
term := make(chan os.Signal)
|
||||
|
@ -19,21 +19,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd"
|
||||
|
||||
"github.com/goodrain/rainbond/monitor/custom"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/monitor/option"
|
||||
"github.com/goodrain/rainbond/monitor"
|
||||
"github.com/goodrain/rainbond/monitor/api"
|
||||
"github.com/goodrain/rainbond/monitor/api/controller"
|
||||
"github.com/goodrain/rainbond/monitor/prometheus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
@ -51,33 +44,23 @@ func main() {
|
||||
c.CompleteConfig()
|
||||
|
||||
// start prometheus daemon and watching tis status in all time, exit monitor process if start failed
|
||||
a := prometheus.NewRulesManager(c)
|
||||
p := prometheus.NewManager(c, a)
|
||||
controllerManager := controller.NewControllerManager(a, p)
|
||||
p := prometheus.NewManager(c)
|
||||
|
||||
monitorMysql(c, p)
|
||||
monitorKSM(c, p)
|
||||
// start watching prometheus config from kube api, and update modify to prometheus config
|
||||
m, err := monitor.NewMonitor(c, p)
|
||||
if err != nil {
|
||||
logrus.Fatalf("new monitor module failure %s", err.Error())
|
||||
}
|
||||
m.Start()
|
||||
defer m.Stop()
|
||||
|
||||
errChan := make(chan error, 1)
|
||||
defer close(errChan)
|
||||
p.StartDaemon(errChan)
|
||||
defer p.StopDaemon()
|
||||
|
||||
// register prometheus address to etcd cluster
|
||||
p.Registry.Start()
|
||||
defer p.Registry.Stop()
|
||||
|
||||
// start watching components from etcd, and update modify to prometheus config
|
||||
m := monitor.NewMonitor(c, p)
|
||||
m.Start()
|
||||
defer m.Stop()
|
||||
|
||||
r := api.Server(controllerManager)
|
||||
logrus.Info("monitor api listen port 3329")
|
||||
go http.ListenAndServe(":3329", r)
|
||||
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
defer close(term)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
@ -91,29 +74,3 @@ func main() {
|
||||
}
|
||||
logrus.Info("See you next time!")
|
||||
}
|
||||
|
||||
func monitorMysql(c *option.Config, p *prometheus.Manager) {
|
||||
if strings.TrimSpace(c.MysqldExporter) != "" {
|
||||
metrics := strings.TrimSpace(c.MysqldExporter)
|
||||
logrus.Infof("add mysql metrics[%s] into prometheus", metrics)
|
||||
custom.AddMetrics(p, custom.Metrics{Name: "mysql", Path: "/metrics", Metrics: []string{metrics}, Interval: 30 * time.Second, Timeout: 15 * time.Second})
|
||||
}
|
||||
}
|
||||
|
||||
func monitorKSM(c *option.Config, p *prometheus.Manager) {
|
||||
if strings.TrimSpace(c.KSMExporter) != "" {
|
||||
metrics := strings.TrimSpace(c.KSMExporter)
|
||||
logrus.Infof("add kube-state-metrics[%s] into prometheus", metrics)
|
||||
custom.AddMetrics(p, custom.Metrics{
|
||||
Name: "kubernetes",
|
||||
Path: "/metrics",
|
||||
Scheme: func() string {
|
||||
if strings.HasSuffix(metrics, "443") {
|
||||
return "https"
|
||||
}
|
||||
return "http"
|
||||
}(),
|
||||
Metrics: []string{metrics}, Interval: 30 * time.Second, Timeout: 10 * time.Second},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ package option
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -31,18 +30,13 @@ import (
|
||||
|
||||
// Config config
|
||||
type Config struct {
|
||||
EtcdEndpointsLine string
|
||||
EtcdEndpoints []string
|
||||
EtcdCaFile string
|
||||
EtcdCertFile string
|
||||
EtcdKeyFile string
|
||||
LogLevel string
|
||||
AdvertiseAddr string
|
||||
BindIP string
|
||||
Port int
|
||||
MetricPort int
|
||||
StartArgs []string
|
||||
ConfigFile string
|
||||
AlertingRulesFile string
|
||||
AlertingRulesFileDir string
|
||||
AlertManagerURL []string
|
||||
LocalStoragePath string
|
||||
Web Web
|
||||
@ -54,9 +48,6 @@ type Config struct {
|
||||
QueryLookbackDelta string
|
||||
QueryTimeout string
|
||||
QueryMaxConcurrency string
|
||||
CadvisorListenPort int
|
||||
MysqldExporter string
|
||||
KSMExporter string
|
||||
KubeConfig string
|
||||
}
|
||||
|
||||
@ -99,15 +90,13 @@ func NewConfig() *Config {
|
||||
host, _ := os.Hostname()
|
||||
|
||||
config := &Config{
|
||||
EtcdEndpointsLine: "http://127.0.0.1:2379",
|
||||
EtcdEndpoints: []string{},
|
||||
AdvertiseAddr: host + ":9999",
|
||||
BindIP: host,
|
||||
Port: 9999,
|
||||
MetricPort: 3329,
|
||||
LogLevel: "info",
|
||||
KubeConfig: "",
|
||||
ConfigFile: "/etc/prometheus/prometheus.yml",
|
||||
AlertingRulesFile: "/etc/prometheus/rules.yml",
|
||||
AlertingRulesFileDir: "/etc/prometheus/rules",
|
||||
AlertManagerURL: []string{},
|
||||
LocalStoragePath: "/prometheusdata",
|
||||
WebTimeout: "5m",
|
||||
@ -128,7 +117,6 @@ func NewConfig() *Config {
|
||||
MinBlockDuration: "2h",
|
||||
Retention: "7d",
|
||||
},
|
||||
CadvisorListenPort: 10250,
|
||||
}
|
||||
|
||||
return config
|
||||
@ -136,15 +124,7 @@ func NewConfig() *Config {
|
||||
|
||||
//AddFlag monitor flag
|
||||
func (c *Config) AddFlag(cmd *pflag.FlagSet) {
|
||||
cmd.StringVar(&c.EtcdEndpointsLine, "etcd-endpoints", c.EtcdEndpointsLine, "etcd endpoints list.")
|
||||
cmd.StringVar(&c.EtcdCaFile, "etcd-ca", "", "etcd tls ca file ")
|
||||
cmd.StringVar(&c.EtcdCertFile, "etcd-cert", "", "etcd tls cert file")
|
||||
cmd.StringVar(&c.EtcdKeyFile, "etcd-key", "", "etcd http tls cert key file")
|
||||
cmd.StringVar(&c.AdvertiseAddr, "advertise-addr", c.AdvertiseAddr, "advertise address, and registry into etcd.")
|
||||
cmd.IntVar(&c.CadvisorListenPort, "cadvisor-listen-port", c.CadvisorListenPort, "kubelet cadvisor listen port in all node")
|
||||
cmd.StringSliceVar(&c.AlertManagerURL, "alertmanager-address", c.AlertManagerURL, "AlertManager url.")
|
||||
cmd.StringVar(&c.MysqldExporter, "mysqld-exporter", c.MysqldExporter, "mysqld exporter address. eg: 127.0.0.1:9104")
|
||||
cmd.StringVar(&c.KSMExporter, "kube-state-metrics", c.KSMExporter, "kube-state-metrics, current server's kube-state-metrics address")
|
||||
cmd.StringVar(&c.KubeConfig, "kube-config", "", "kubernetes api server config file")
|
||||
}
|
||||
|
||||
@ -152,7 +132,7 @@ func (c *Config) AddFlag(cmd *pflag.FlagSet) {
|
||||
func (c *Config) AddPrometheusFlag(cmd *pflag.FlagSet) {
|
||||
cmd.StringVar(&c.ConfigFile, "config.file", c.ConfigFile, "Prometheus configuration file path.")
|
||||
|
||||
cmd.StringVar(&c.AlertingRulesFile, "rules-config.file", c.AlertingRulesFile, "Prometheus alerting rules config file path.")
|
||||
cmd.StringVar(&c.AlertingRulesFileDir, "rules-config.dir", c.AlertingRulesFileDir, "Prometheus alerting rules config file path.")
|
||||
|
||||
cmd.StringVar(&c.Web.ListenAddress, "web.listen-address", c.Web.ListenAddress, "Address to listen on for UI, API, and telemetry.")
|
||||
|
||||
@ -202,25 +182,6 @@ func (c *Config) AddPrometheusFlag(cmd *pflag.FlagSet) {
|
||||
|
||||
// CompleteConfig complete config
|
||||
func (c *Config) CompleteConfig() {
|
||||
// parse etcd urls line to array
|
||||
for _, url := range strings.Split(c.EtcdEndpointsLine, ",") {
|
||||
c.EtcdEndpoints = append(c.EtcdEndpoints, url)
|
||||
}
|
||||
|
||||
if len(c.EtcdEndpoints) < 1 {
|
||||
logrus.Error("Must define the etcd endpoints by --etcd-endpoints")
|
||||
os.Exit(17)
|
||||
}
|
||||
|
||||
// parse values from prometheus options to config
|
||||
ipPort := strings.TrimLeft(c.AdvertiseAddr, "shttp://")
|
||||
ipPortArr := strings.Split(ipPort, ":")
|
||||
c.BindIP = ipPortArr[0]
|
||||
port, err := strconv.Atoi(ipPortArr[1])
|
||||
if err == nil {
|
||||
c.Port = port
|
||||
}
|
||||
|
||||
defaultOptions := "--log.level=%s --web.listen-address=%s --config.file=%s --storage.tsdb.path=%s --storage.tsdb.retention.time=%s"
|
||||
defaultOptions = fmt.Sprintf(defaultOptions, c.LogLevel, c.Web.ListenAddress, c.ConfigFile, c.LocalStoragePath, c.Tsdb.Retention)
|
||||
if c.Tsdb.NoLockfile {
|
||||
|
@ -24,10 +24,8 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/mq/option"
|
||||
discover "github.com/goodrain/rainbond/discover.v2"
|
||||
"github.com/goodrain/rainbond/mq/api"
|
||||
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -43,35 +41,8 @@ func Run(s *option.MQServer) error {
|
||||
apiManager.Start(errChan)
|
||||
defer apiManager.Stop()
|
||||
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: s.Config.EtcdEndPoints,
|
||||
CaFile: s.Config.EtcdCaFile,
|
||||
CertFile: s.Config.EtcdCertFile,
|
||||
KeyFile: s.Config.EtcdKeyFile,
|
||||
}
|
||||
|
||||
//step 2:regist mq endpoint
|
||||
keepalive, err := discover.CreateKeepAlive(etcdClientArgs, "rainbond_mq", s.Config.HostName, s.Config.HostIP, s.Config.APIPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := keepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer keepalive.Stop()
|
||||
|
||||
//step 3:regist prometheus export endpoint
|
||||
exportKeepalive, err := discover.CreateKeepAlive(etcdClientArgs, "mq", s.Config.HostName, s.Config.HostIP, 6301)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := exportKeepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer exportKeepalive.Stop()
|
||||
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-term:
|
||||
|
@ -42,7 +42,7 @@ var mode string
|
||||
func main() {
|
||||
AddFlags(pflag.CommandLine)
|
||||
pflag.Parse()
|
||||
c, err := client.NewMqClient(nil, server)
|
||||
c, err := client.NewMqClient(server)
|
||||
if err != nil {
|
||||
logrus.Error("new mq client error.", err.Error())
|
||||
os.Exit(1)
|
||||
|
@ -26,15 +26,14 @@ import (
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/cmd/node/server"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/server"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "version" {
|
||||
cmd.ShowVersion("node")
|
||||
}
|
||||
server.ParseClientCommnad(os.Args)
|
||||
option.Config.AddFlags(pflag.CommandLine)
|
||||
server.InstallServiceFlags(pflag.CommandLine)
|
||||
if err := option.Init(); err != nil {
|
144
cmd/node-proxy/option/conf.go
Normal file
144
cmd/node-proxy/option/conf.go
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright (C) 2014-2021 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
dockercli "github.com/docker/docker/client"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
//Config config
|
||||
Config = new(Conf)
|
||||
initialized bool
|
||||
)
|
||||
|
||||
//Init init config
|
||||
func Init() error {
|
||||
if initialized {
|
||||
return nil
|
||||
}
|
||||
pflag.Parse()
|
||||
Config.SetLog()
|
||||
if err := Config.parse(); err != nil {
|
||||
return err
|
||||
}
|
||||
initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
//Conf Conf
|
||||
type Conf struct {
|
||||
APIAddr string //api server listen port
|
||||
GrpcAPIAddr string //grpc api server listen port
|
||||
LogLevel string
|
||||
LogFile string
|
||||
StatsdConfig StatsdConfig
|
||||
UDPMonitorConfig UDPMonitorConfig
|
||||
//enable collect docker container log
|
||||
EnableCollectLog bool
|
||||
DockerCli *dockercli.Client
|
||||
// Namespace for Rainbond application.
|
||||
RbdNamespace string
|
||||
ImageRepositoryHost string
|
||||
GatewayVIP string
|
||||
HostsFile string
|
||||
KubeConfigPath string
|
||||
}
|
||||
|
||||
//StatsdConfig StatsdConfig
|
||||
type StatsdConfig struct {
|
||||
StatsdListenAddress string
|
||||
StatsdListenUDP string
|
||||
StatsdListenTCP string
|
||||
MappingConfig string
|
||||
ReadBuffer int
|
||||
}
|
||||
|
||||
//UDPMonitorConfig UDPMonitorConfig
|
||||
type UDPMonitorConfig struct {
|
||||
ListenHost string
|
||||
ListenPort string
|
||||
}
|
||||
|
||||
//AddFlags AddFlags
|
||||
func (a *Conf) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&a.LogLevel, "log-level", "info", "the log level")
|
||||
fs.StringVar(&a.LogFile, "log-file", "", "the log file path that log output")
|
||||
fs.StringVar(&a.GrpcAPIAddr, "grpc-api-addr", ":6101", "The node grpc api server listen address")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenAddress, "statsd.listen-address", "", "The UDP address on which to receive statsd metric lines. DEPRECATED, use statsd.listen-udp instead.")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenUDP, "statsd.listen-udp", ":9125", "The UDP address on which to receive statsd metric lines. \"\" disables it.")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenTCP, "statsd.listen-tcp", ":9125", "The TCP address on which to receive statsd metric lines. \"\" disables it.")
|
||||
fs.StringVar(&a.StatsdConfig.MappingConfig, "statsd.mapping-config", "", "Metric mapping configuration file name.")
|
||||
fs.IntVar(&a.StatsdConfig.ReadBuffer, "statsd.read-buffer", 0, "Size (in bytes) of the operating system's transmit read buffer associated with the UDP connection. Please make sure the kernel parameters net.core.rmem_max is set to a value greater than the value specified.")
|
||||
fs.BoolVar(&a.EnableCollectLog, "enabel-collect-log", true, "Whether to collect container logs")
|
||||
fs.StringVar(&a.RbdNamespace, "rbd-ns", "rbd-system", "The namespace of rainbond applications.")
|
||||
fs.StringVar(&a.ImageRepositoryHost, "image-repo-host", "goodrain.me", "The host of image repository")
|
||||
fs.StringVar(&a.GatewayVIP, "gateway-vip", "", "The vip of gateway")
|
||||
fs.StringVar(&a.HostsFile, "hostsfile", "/newetc/hosts", "/etc/hosts mapped path in the container. eg. /etc/hosts:/tmp/hosts. Do not set hostsfile to /etc/hosts")
|
||||
fs.StringVar(&a.KubeConfigPath, "kubeconfig", "", "path to kubeconfig file with authorization and master location information.")
|
||||
}
|
||||
|
||||
//SetLog 设置log
|
||||
func (a *Conf) SetLog() {
|
||||
level, err := logrus.ParseLevel(a.LogLevel)
|
||||
if err != nil {
|
||||
fmt.Println("set log level error." + err.Error())
|
||||
return
|
||||
}
|
||||
logrus.SetLevel(level)
|
||||
if a.LogFile != "" {
|
||||
if err := util.CheckAndCreateDir(path.Dir(a.LogFile)); err != nil {
|
||||
logrus.Errorf("create node log file dir failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
logfile, err := os.OpenFile(a.LogFile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
logrus.Errorf("create and open node log file failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
logrus.SetOutput(logfile)
|
||||
}
|
||||
}
|
||||
|
||||
//ParseClient handle config and create some api
|
||||
func (a *Conf) ParseClient(ctx context.Context) (err error) {
|
||||
a.DockerCli, err = dockercli.NewClientWithOpts(dockercli.FromEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//parse parse
|
||||
func (a *Conf) parse() error {
|
||||
//init api listen port, can not custom
|
||||
if a.APIAddr == "" {
|
||||
a.APIAddr = ":6100"
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// Copyright (C) 2014-2021 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
@ -25,20 +25,14 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
"github.com/goodrain/rainbond/discover.v2"
|
||||
eventLog "github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/node/api"
|
||||
"github.com/goodrain/rainbond/node/api/controller"
|
||||
"github.com/goodrain/rainbond/node/core/store"
|
||||
"github.com/goodrain/rainbond/node/initiate"
|
||||
"github.com/goodrain/rainbond/node/kubecache"
|
||||
"github.com/goodrain/rainbond/node/masterserver"
|
||||
"github.com/goodrain/rainbond/node/nodem"
|
||||
"github.com/goodrain/rainbond/node/nodem/docker"
|
||||
"github.com/goodrain/rainbond/node/nodem/envoy"
|
||||
"github.com/goodrain/rainbond/util/constants"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@ -55,18 +49,11 @@ func Run(cfg *option.Conf) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: cfg.EtcdEndpoints,
|
||||
CaFile: cfg.EtcdCaFile,
|
||||
CertFile: cfg.EtcdCertFile,
|
||||
KeyFile: cfg.EtcdKeyFile,
|
||||
DialTimeout: cfg.EtcdDialTimeout,
|
||||
}
|
||||
if err := cfg.ParseClient(ctx, etcdClientArgs); err != nil {
|
||||
if err := cfg.ParseClient(ctx); err != nil {
|
||||
return fmt.Errorf("config parse error:%s", err.Error())
|
||||
}
|
||||
|
||||
config, err := k8sutil.NewRestConfig(cfg.K8SConfPath)
|
||||
config, err := k8sutil.NewRestConfig(cfg.KubeConfigPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -75,35 +62,13 @@ func Run(cfg *option.Conf) error {
|
||||
return err
|
||||
}
|
||||
|
||||
k8sDiscover := discover.NewK8sDiscover(ctx, clientset, cfg)
|
||||
defer k8sDiscover.Stop()
|
||||
|
||||
nodemanager, err := nodem.NewNodeManager(ctx, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create node manager failed: %s", err)
|
||||
}
|
||||
if err := nodemanager.InitStart(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = eventLog.NewManager(eventLog.EventConfig{
|
||||
EventLogServers: cfg.EventLogServer,
|
||||
DiscoverArgs: etcdClientArgs,
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Errorf("error creating eventlog manager")
|
||||
return nil
|
||||
}
|
||||
defer eventLog.CloseManager()
|
||||
logrus.Debug("create and start event log client success")
|
||||
|
||||
kubecli, err := kubecache.NewKubeClient(cfg, clientset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer kubecli.Stop()
|
||||
|
||||
if cfg.ImageRepositoryHost == constants.DefImageRepository {
|
||||
k8sDiscover := discover.NewK8sDiscover(ctx, clientset, cfg)
|
||||
defer k8sDiscover.Stop()
|
||||
hostManager, err := initiate.NewHostManager(cfg, k8sDiscover)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create new host manager: %v", err)
|
||||
@ -117,10 +82,6 @@ func Run(cfg *option.Conf) error {
|
||||
return fmt.Errorf("sync docker cert from secret error: %s", err.Error())
|
||||
}
|
||||
|
||||
// init etcd client
|
||||
if err = store.NewClient(ctx, cfg, etcdClientArgs); err != nil {
|
||||
return fmt.Errorf("Connect to ETCD %s failed: %s", cfg.EtcdEndpoints, err)
|
||||
}
|
||||
errChan := make(chan error, 3)
|
||||
if err := nodemanager.Start(errChan); err != nil {
|
||||
return fmt.Errorf("start node manager failed: %s", err)
|
||||
@ -128,24 +89,8 @@ func Run(cfg *option.Conf) error {
|
||||
defer nodemanager.Stop()
|
||||
logrus.Debug("create and start node manager moudle success")
|
||||
|
||||
//master服务在node服务之后启动
|
||||
var ms *masterserver.MasterServer
|
||||
if cfg.RunMode == "master" {
|
||||
ms, err = masterserver.NewMasterServer(nodemanager.GetCurrentNode(), kubecli)
|
||||
if err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
return err
|
||||
}
|
||||
ms.Cluster.UpdateNode(nodemanager.GetCurrentNode())
|
||||
if err := ms.Start(errChan); err != nil {
|
||||
logrus.Errorf(err.Error())
|
||||
return err
|
||||
}
|
||||
defer ms.Stop(nil)
|
||||
logrus.Debug("create and start master server moudle success")
|
||||
}
|
||||
//create api manager
|
||||
apiManager := api.NewManager(*cfg, nodemanager.GetCurrentNode(), ms, kubecli)
|
||||
apiManager := api.NewManager(*cfg, clientset)
|
||||
if err := apiManager.Start(errChan); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -165,10 +110,8 @@ func Run(cfg *option.Conf) error {
|
||||
defer grpcserver.Stop()
|
||||
|
||||
logrus.Debug("create and start api server moudle success")
|
||||
|
||||
defer controller.Exist(nil)
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
term := make(chan os.Signal, 1)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-stoped:
|
@ -1,5 +1,5 @@
|
||||
// RAINBOND, Application Management Platform
|
||||
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
||||
// Copyright (C) 2014-2021 Goodrain Co., Ltd.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -21,7 +21,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
@ -25,7 +25,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
utilwindows "github.com/goodrain/rainbond/util/windows"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/sys/windows"
|
@ -1,260 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
client "github.com/coreos/etcd/clientv3"
|
||||
dockercli "github.com/docker/docker/client"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
confFile = flag.String("conf",
|
||||
"conf/files/base.json", "config file path")
|
||||
//Config config
|
||||
Config = new(Conf)
|
||||
initialized bool
|
||||
|
||||
watcher *fsnotify.Watcher
|
||||
exitChan = make(chan struct{})
|
||||
)
|
||||
|
||||
//Init init config
|
||||
func Init() error {
|
||||
if initialized {
|
||||
return nil
|
||||
}
|
||||
pflag.Parse()
|
||||
Config.SetLog()
|
||||
if err := Config.parse(); err != nil {
|
||||
return err
|
||||
}
|
||||
initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
//Conf Conf
|
||||
type Conf struct {
|
||||
APIAddr string //api server listen port
|
||||
GrpcAPIAddr string //grpc api server listen port
|
||||
PrometheusAPI string //Prometheus server listen port
|
||||
K8SConfPath string //absolute path to the kubeconfig file
|
||||
LogLevel string
|
||||
LogFile string
|
||||
HostID string
|
||||
HostIP string
|
||||
PodIP string
|
||||
RunMode string //ACP_NODE 运行模式:master,node
|
||||
NodeRule string //节点属性 compute manage storage
|
||||
Service string //服务注册与发现
|
||||
InitStatus string
|
||||
NodePath string //Rainbond node model basic information storage path in etcd
|
||||
EventLogServer []string //event server address list
|
||||
ConfigStoragePath string //config storage path in etcd
|
||||
LockPath string
|
||||
TTL int64 // node heartbeat to master TTL
|
||||
PodCIDR string //pod cidr, when master not set cidr,this parameter can take effect
|
||||
EtcdEndpoints []string // etcd endpoints
|
||||
EtcdDialTimeout time.Duration // etcd dial timeout
|
||||
EtcdCaFile string // etcd ca file
|
||||
EtcdCertFile string // etcd cert file
|
||||
EtcdKeyFile string // etcd key file
|
||||
StatsdConfig StatsdConfig
|
||||
UDPMonitorConfig UDPMonitorConfig
|
||||
MinResyncPeriod time.Duration
|
||||
AutoUnschedulerUnHealthDuration time.Duration
|
||||
AutoScheduler bool
|
||||
ReqTimeout int
|
||||
|
||||
// for node controller
|
||||
ServiceListFile string
|
||||
ServiceManager string
|
||||
EnableInitStart bool
|
||||
AutoRegistNode bool
|
||||
//enable collect docker container log
|
||||
EnableCollectLog bool
|
||||
DockerCli *dockercli.Client
|
||||
EtcdCli *client.Client
|
||||
|
||||
LicPath string
|
||||
LicSoPath string
|
||||
|
||||
// EnableImageGC is the trigger of image garbage collection.
|
||||
EnableImageGC bool
|
||||
// imageMinimumGCAge is the minimum age for an unused image before it is
|
||||
// garbage collected.
|
||||
ImageMinimumGCAge time.Duration
|
||||
// imageGCHighThresholdPercent is the percent of disk usage after which
|
||||
// image garbage collection is always run. The percent is calculated as
|
||||
// this field value out of 100.
|
||||
ImageGCHighThresholdPercent int32
|
||||
// imageGCLowThresholdPercent is the percent of disk usage before which
|
||||
// image garbage collection is never run. Lowest disk usage to garbage
|
||||
// collect to. The percent is calculated as this field value out of 100.
|
||||
ImageGCLowThresholdPercent int32
|
||||
// ImageGCPeriod is the period for performing image garbage collection.
|
||||
ImageGCPeriod time.Duration
|
||||
|
||||
// Namespace for Rainbond application.
|
||||
RbdNamespace string
|
||||
ImageRepositoryHost string
|
||||
GatewayVIP string
|
||||
HostsFile string
|
||||
}
|
||||
|
||||
//StatsdConfig StatsdConfig
|
||||
type StatsdConfig struct {
|
||||
StatsdListenAddress string
|
||||
StatsdListenUDP string
|
||||
StatsdListenTCP string
|
||||
MappingConfig string
|
||||
ReadBuffer int
|
||||
}
|
||||
|
||||
//UDPMonitorConfig UDPMonitorConfig
|
||||
type UDPMonitorConfig struct {
|
||||
ListenHost string
|
||||
ListenPort string
|
||||
}
|
||||
|
||||
//AddFlags AddFlags
|
||||
func (a *Conf) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&a.LogLevel, "log-level", "info", "the log level")
|
||||
fs.StringVar(&a.LogFile, "log-file", "", "the log file path that log output")
|
||||
fs.StringVar(&a.PrometheusAPI, "prometheus", "http://rbd-monitor:9999", "the prometheus server address")
|
||||
fs.StringVar(&a.NodePath, "nodePath", "/rainbond/nodes", "the path of node in etcd")
|
||||
fs.StringVar(&a.HostID, "nodeid", "", "the unique ID for this node. Just specify, don't modify")
|
||||
fs.StringVar(&a.HostIP, "hostIP", "", "the host ip you can define. default get ip from eth0")
|
||||
fs.StringVar(&a.PodIP, "podIP", "", "The pod ip of node.")
|
||||
fs.StringSliceVar(&a.EventLogServer, "event-log-server", []string{"127.0.0.1:6366"}, "host:port slice of event log server")
|
||||
fs.StringVar(&a.ConfigStoragePath, "config-path", "/rainbond/acp_configs", "the path of config to store(new)")
|
||||
fs.StringVar(&a.Service, "servicePath", "/traefik/backends", "the path of service info to store")
|
||||
fs.StringSliceVar(&a.EtcdEndpoints, "etcd", []string{"http://127.0.0.1:2379"}, "the path of node in etcd")
|
||||
fs.StringVar(&a.EtcdCaFile, "etcd-ca", "", "verify etcd certificates of TLS-enabled secure servers using this CA bundle")
|
||||
fs.StringVar(&a.EtcdCertFile, "etcd-cert", "", "identify secure etcd client using this TLS certificate file")
|
||||
fs.StringVar(&a.EtcdKeyFile, "etcd-key", "", "identify secure etcd client using this TLS key file")
|
||||
fs.DurationVar(&a.EtcdDialTimeout, "etcd-dialTimeOut", 3, "etcd cluster dialTimeOut In seconds")
|
||||
fs.IntVar(&a.ReqTimeout, "reqTimeOut", 2, "req TimeOut.")
|
||||
fs.Int64Var(&a.TTL, "ttl", 10, "Frequency of node status reporting to master")
|
||||
//fs.StringVar(&a.APIAddr, "api-addr", ":6100", "The node api server listen address")
|
||||
fs.StringVar(&a.GrpcAPIAddr, "grpc-api-addr", ":6101", "The node grpc api server listen address")
|
||||
fs.StringVar(&a.K8SConfPath, "kube-conf", "", "absolute path to the kubeconfig file ./kubeconfig")
|
||||
fs.StringVar(&a.RunMode, "run-mode", "worker", "the acp_node run mode,could be 'worker' or 'master'")
|
||||
fs.StringVar(&a.NodeRule, "noderule", "compute", "current node rule,maybe is `compute` `manage` `storage` ")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenAddress, "statsd.listen-address", "", "The UDP address on which to receive statsd metric lines. DEPRECATED, use statsd.listen-udp instead.")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenUDP, "statsd.listen-udp", ":9125", "The UDP address on which to receive statsd metric lines. \"\" disables it.")
|
||||
fs.StringVar(&a.StatsdConfig.StatsdListenTCP, "statsd.listen-tcp", ":9125", "The TCP address on which to receive statsd metric lines. \"\" disables it.")
|
||||
fs.StringVar(&a.StatsdConfig.MappingConfig, "statsd.mapping-config", "", "Metric mapping configuration file name.")
|
||||
fs.IntVar(&a.StatsdConfig.ReadBuffer, "statsd.read-buffer", 0, "Size (in bytes) of the operating system's transmit read buffer associated with the UDP connection. Please make sure the kernel parameters net.core.rmem_max is set to a value greater than the value specified.")
|
||||
fs.DurationVar(&a.MinResyncPeriod, "min-resync-period", time.Second*15, "The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod")
|
||||
fs.StringVar(&a.ServiceListFile, "service-list-file", "/opt/rainbond/conf/", "Specifies the configuration file, which can be a directory, that configures the service running on the current node")
|
||||
fs.BoolVar(&a.EnableInitStart, "enable-init-start", false, "Enable dependency - free initialization starts for services that support initialization starts")
|
||||
fs.BoolVar(&a.AutoRegistNode, "auto-registnode", true, "Whether auto regist node info to cluster where node is not found")
|
||||
fs.BoolVar(&a.AutoScheduler, "auto-scheduler", true, "Whether auto set node unscheduler where current node is unhealth")
|
||||
fs.BoolVar(&a.EnableCollectLog, "enabel-collect-log", true, "Whether to collect container logs")
|
||||
fs.DurationVar(&a.AutoUnschedulerUnHealthDuration, "autounscheduler-unhealthy-dura", 5*time.Minute, "Node unhealthy duration, after the automatic offline,if set 0,disable auto handle unscheduler.default is 5 Minute")
|
||||
fs.StringVar(&a.LicPath, "lic-path", "/opt/rainbond/etc/license/license.yb", "the license path of the enterprise version.")
|
||||
fs.StringVar(&a.LicSoPath, "lic-so-path", "/opt/rainbond/etc/license/license.so", "Dynamic library file path for parsing the license.")
|
||||
fs.BoolVar(&a.EnableImageGC, "enable-image-gc", true, "The trigger of image garbage collection.")
|
||||
fs.DurationVar(&a.ImageMinimumGCAge, "minimum-image-ttl-duration", 2*time.Hour, "Minimum age for an unused image before it is garbage collected. Examples: '300ms', '10s' or '2h45m'.")
|
||||
fs.DurationVar(&a.ImageGCPeriod, "image-gc-period", 5*time.Minute, "ImageGCPeriod is the period for performing image garbage collection. Examples: '10s', '5m' or '2h45m'.")
|
||||
fs.Int32Var(&a.ImageGCHighThresholdPercent, "image-gc-high-threshold", 90, "The percent of disk usage after which image garbage collection is always run. Values must be within the range [0, 100], To disable image garbage collection, set to 100. ")
|
||||
fs.Int32Var(&a.ImageGCLowThresholdPercent, "image-gc-low-threshold", 75, "The percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to. Values must be within the range [0, 100] and should not be larger than that of --image-gc-high-threshold.")
|
||||
fs.StringVar(&a.RbdNamespace, "rbd-ns", "rbd-system", "The namespace of rainbond applications.")
|
||||
fs.StringVar(&a.ImageRepositoryHost, "image-repo-host", "goodrain.me", "The host of image repository")
|
||||
fs.StringVar(&a.GatewayVIP, "gateway-vip", "", "The vip of gateway")
|
||||
fs.StringVar(&a.HostsFile, "hostsfile", "/newetc/hosts", "/etc/hosts mapped path in the container. eg. /etc/hosts:/tmp/hosts. Do not set hostsfile to /etc/hosts")
|
||||
}
|
||||
|
||||
//SetLog 设置log
|
||||
func (a *Conf) SetLog() {
|
||||
level, err := logrus.ParseLevel(a.LogLevel)
|
||||
if err != nil {
|
||||
fmt.Println("set log level error." + err.Error())
|
||||
return
|
||||
}
|
||||
logrus.SetLevel(level)
|
||||
if a.LogFile != "" {
|
||||
if err := util.CheckAndCreateDir(path.Dir(a.LogFile)); err != nil {
|
||||
logrus.Errorf("create node log file dir failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
logfile, err := os.OpenFile(a.LogFile, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0755)
|
||||
if err != nil {
|
||||
logrus.Errorf("create and open node log file failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
logrus.SetOutput(logfile)
|
||||
}
|
||||
}
|
||||
|
||||
//ParseClient handle config and create some api
|
||||
func (a *Conf) ParseClient(ctx context.Context, etcdClientArgs *etcdutil.ClientArgs) (err error) {
|
||||
a.DockerCli, err = dockercli.NewEnvClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("begin create etcd client: %s", a.EtcdEndpoints)
|
||||
for {
|
||||
a.EtcdCli, err = etcdutil.NewClient(ctx, etcdClientArgs)
|
||||
if err != nil {
|
||||
logrus.Errorf("create etcd client failure %s, will retry after 3 second", err.Error())
|
||||
}
|
||||
if err == nil && a.EtcdCli != nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
}
|
||||
logrus.Infof("create etcd client success")
|
||||
return nil
|
||||
}
|
||||
|
||||
//parse parse
|
||||
func (a *Conf) parse() error {
|
||||
if a.TTL <= 0 {
|
||||
a.TTL = 10
|
||||
}
|
||||
a.LockPath = "/rainbond/lock"
|
||||
if a.HostIP == "" || !util.CheckIP(a.HostIP) {
|
||||
localIP, err := util.LocalIP()
|
||||
if localIP == nil || err != nil {
|
||||
return fmt.Errorf("can not find ip of this node")
|
||||
}
|
||||
a.HostIP = localIP.String()
|
||||
}
|
||||
//init api listen port, can not custom
|
||||
if a.APIAddr == "" {
|
||||
a.APIAddr = ":6100"
|
||||
}
|
||||
if a.HostID == "" {
|
||||
return fmt.Errorf("kubernetes node id can't empty")
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
// RAINBOND, Application Management Platform
|
||||
// Copyright (C) 2014-2017 Goodrain Co., Ltd.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/goodrain/rainbond/util"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/goodrain/rainbond/event"
|
||||
|
||||
"github.com/goodrain/rainbond/builder/parser"
|
||||
|
||||
"github.com/goodrain/rainbond/node/nodem/service"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd"
|
||||
|
||||
httputil "github.com/goodrain/rainbond/util/http"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
//ParseClientCommnad parse client command
|
||||
// node service xxx :Operation of the guard component
|
||||
// node reg : Register the daemon configuration for node
|
||||
// node run: daemon start node server
|
||||
func ParseClientCommnad(args []string) {
|
||||
|
||||
if len(args) > 1 {
|
||||
switch args[1] {
|
||||
case "version":
|
||||
cmd.ShowVersion("node")
|
||||
case "service":
|
||||
controller := controllerServiceClient{}
|
||||
if len(args) > 2 {
|
||||
switch args[2] {
|
||||
case "start":
|
||||
if len(args) < 4 {
|
||||
fmt.Printf("Parameter error")
|
||||
}
|
||||
//enable a service
|
||||
serviceName := args[3]
|
||||
if err := controller.startService(serviceName); err != nil {
|
||||
fmt.Printf("start service %s failure %s", serviceName, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("start service %s success", serviceName)
|
||||
os.Exit(0)
|
||||
case "stop":
|
||||
if len(args) < 4 {
|
||||
fmt.Printf("Parameter error")
|
||||
}
|
||||
//disable a service
|
||||
serviceName := args[3]
|
||||
if err := controller.stopService(serviceName); err != nil {
|
||||
fmt.Printf("stop service %s failure %s", serviceName, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("stop service %s success", serviceName)
|
||||
os.Exit(0)
|
||||
case "update":
|
||||
if err := controller.updateConfig(); err != nil {
|
||||
fmt.Printf("update service config failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("update service config success")
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
case "upgrade":
|
||||
App := cli.NewApp()
|
||||
App.Version = "0.1"
|
||||
App.Commands = []cli.Command{
|
||||
{
|
||||
Name: "upgrade",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "config-dir,c",
|
||||
Value: "/opt/rainbond/conf",
|
||||
Usage: "service config file dir",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "new-version,v",
|
||||
Value: "",
|
||||
Usage: "upgrade target version",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "image-prefix,p",
|
||||
Value: "goodrain.me",
|
||||
Usage: "",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "services,s",
|
||||
Value: &cli.StringSlice{"rbd-gateway", "rbd-api", "rbd-chaos", "rbd-mq", "rbd-webcli", "rbd-worker", "rbd-eventlog", "rbd-monitor", "rbd-app-ui"},
|
||||
Usage: "Enable supported services",
|
||||
},
|
||||
},
|
||||
Action: upgradeImages,
|
||||
},
|
||||
}
|
||||
sort.Sort(cli.FlagsByName(App.Flags))
|
||||
sort.Sort(cli.CommandsByName(App.Commands))
|
||||
if err := App.Run(os.Args); err != nil {
|
||||
logrus.Errorf("upgrade failure %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
logrus.Info("upgrade success")
|
||||
os.Exit(0)
|
||||
case "run":
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//upgrade image name
|
||||
func upgradeImages(ctx *cli.Context) error {
|
||||
services := service.LoadServicesWithFileFromLocal(ctx.String("c"))
|
||||
for i, serviceList := range services {
|
||||
for j, service := range serviceList.Services {
|
||||
if util.StringArrayContains(ctx.StringSlice("s"), service.Name) &&
|
||||
service.Start != "" && !service.OnlyHealthCheck {
|
||||
par := parser.CreateDockerRunOrImageParse("", "", service.Start, nil, event.GetTestLogger())
|
||||
par.ParseDockerun(service.Start)
|
||||
image := par.GetImage()
|
||||
if image.Name == "" {
|
||||
continue
|
||||
}
|
||||
newImage := ctx.String("p") + "/" + service.Name + ":" + ctx.String("v")
|
||||
oldImage := func() string {
|
||||
if image.IsOfficial() {
|
||||
return image.GetRepostory() + ":" + image.GetTag()
|
||||
}
|
||||
return image.String()
|
||||
}()
|
||||
services[i].Services[j].Start = strings.Replace(services[i].Services[j].Start, oldImage, newImage, 1)
|
||||
logrus.Infof("upgrade %s image from %s to %s", service.Name, oldImage, newImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
return service.WriteServicesWithFile(services...)
|
||||
}
|
||||
|
||||
type controllerServiceClient struct {
|
||||
}
|
||||
|
||||
func (c *controllerServiceClient) request(url string) error {
|
||||
res, err := http.Post(url, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if res.StatusCode == 200 {
|
||||
return nil
|
||||
}
|
||||
resbody, err := httputil.ParseResponseBody(res.Body, "application/json")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf(resbody.Msg)
|
||||
}
|
||||
func (c *controllerServiceClient) startService(serviceName string) error {
|
||||
return c.request(fmt.Sprintf("http://127.0.0.1:6100/services/%s/start", serviceName))
|
||||
}
|
||||
func (c *controllerServiceClient) stopService(serviceName string) error {
|
||||
return c.request(fmt.Sprintf("http://127.0.0.1:6100/services/%s/stop", serviceName))
|
||||
}
|
||||
func (c *controllerServiceClient) updateConfig() error {
|
||||
return c.request(fmt.Sprintf("http://127.0.0.1:6100/services/update"))
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
//Config config server
|
||||
type Config struct {
|
||||
EtcdEndPoints []string
|
||||
EtcdCaFile string
|
||||
EtcdCertFile string
|
||||
EtcdKeyFile string
|
||||
Address string
|
||||
HostIP string
|
||||
HostName string
|
||||
Port int
|
||||
SessionKey string
|
||||
PrometheusMetricPath string
|
||||
K8SConfPath string
|
||||
}
|
||||
|
||||
//WebCliServer container webcli server
|
||||
type WebCliServer struct {
|
||||
Config
|
||||
LogLevel string
|
||||
}
|
||||
|
||||
//NewWebCliServer new server
|
||||
func NewWebCliServer() *WebCliServer {
|
||||
return &WebCliServer{}
|
||||
}
|
||||
|
||||
//AddFlags config
|
||||
func (a *WebCliServer) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&a.LogLevel, "log-level", "info", "the webcli log level")
|
||||
fs.StringSliceVar(&a.EtcdEndPoints, "etcd-endpoints", []string{"http://127.0.0.1:2379"}, "etcd v3 cluster endpoints.")
|
||||
fs.StringVar(&a.EtcdCaFile, "etcd-ca", "", "etcd tls ca file ")
|
||||
fs.StringVar(&a.EtcdCertFile, "etcd-cert", "", "etcd tls cert file")
|
||||
fs.StringVar(&a.EtcdKeyFile, "etcd-key", "", "etcd http tls cert key file")
|
||||
fs.StringVar(&a.Address, "address", "0.0.0.0", "server listen address")
|
||||
fs.StringVar(&a.HostIP, "hostIP", "", "Current node Intranet IP")
|
||||
fs.StringVar(&a.HostName, "hostName", "", "Current node host name")
|
||||
fs.StringVar(&a.K8SConfPath, "kube-conf", "", "absolute path to the kubeconfig file")
|
||||
fs.IntVar(&a.Port, "port", 7171, "server listen port")
|
||||
fs.StringVar(&a.PrometheusMetricPath, "metric", "/metrics", "prometheus metrics path")
|
||||
}
|
||||
|
||||
//SetLog 设置log
|
||||
func (a *WebCliServer) SetLog() {
|
||||
level, err := logrus.ParseLevel(a.LogLevel)
|
||||
if err != nil {
|
||||
fmt.Println("set log level error." + err.Error())
|
||||
return
|
||||
}
|
||||
logrus.SetLevel(level)
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/webcli/option"
|
||||
"github.com/goodrain/rainbond/discover"
|
||||
"github.com/goodrain/rainbond/webcli/app"
|
||||
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//Run start run
|
||||
func Run(s *option.WebCliServer) error {
|
||||
errChan := make(chan error)
|
||||
option := app.DefaultOptions
|
||||
option.Address = s.Address
|
||||
option.Port = strconv.Itoa(s.Port)
|
||||
option.SessionKey = s.SessionKey
|
||||
option.K8SConfPath = s.K8SConfPath
|
||||
ap, err := app.New(&option)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ap.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ap.Exit()
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: s.EtcdEndPoints,
|
||||
CaFile: s.EtcdCaFile,
|
||||
CertFile: s.EtcdCertFile,
|
||||
KeyFile: s.EtcdKeyFile,
|
||||
}
|
||||
keepalive, err := discover.CreateKeepAlive(etcdClientArgs, "acp_webcli", s.HostName, s.HostIP, s.Port)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := keepalive.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer keepalive.Stop()
|
||||
//step finally: listen Signal
|
||||
term := make(chan os.Signal)
|
||||
signal.Notify(term, os.Interrupt, syscall.SIGTERM)
|
||||
select {
|
||||
case <-term:
|
||||
logrus.Warn("Received SIGTERM, exiting gracefully...")
|
||||
case err := <-errChan:
|
||||
logrus.Errorf("Received a error %s, exiting gracefully...", err.Error())
|
||||
}
|
||||
logrus.Info("See you next time!")
|
||||
return nil
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd"
|
||||
"github.com/goodrain/rainbond/cmd/webcli/option"
|
||||
"github.com/goodrain/rainbond/cmd/webcli/server"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) > 1 && os.Args[1] == "version" {
|
||||
cmd.ShowVersion("webcli")
|
||||
}
|
||||
s := option.NewWebCliServer()
|
||||
s.AddFlags(pflag.CommandLine)
|
||||
pflag.Parse()
|
||||
s.SetLog()
|
||||
if err := server.Run(s); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build windows
|
||||
|
||||
package option
|
||||
|
||||
import (
|
||||
|
@ -16,6 +16,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -30,12 +30,6 @@ import (
|
||||
|
||||
//Config config server
|
||||
type Config struct {
|
||||
EtcdEndPoints []string
|
||||
EtcdCaFile string
|
||||
EtcdCertFile string
|
||||
EtcdKeyFile string
|
||||
EtcdTimeout int
|
||||
EtcdPrefix string
|
||||
ClusterName string
|
||||
MysqlConnectionInfo string
|
||||
DBType string
|
||||
@ -81,32 +75,25 @@ func NewWorker() *Worker {
|
||||
//AddFlags config
|
||||
func (a *Worker) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&a.LogLevel, "log-level", "info", "the worker log level")
|
||||
fs.StringSliceVar(&a.EtcdEndPoints, "etcd-endpoints", []string{"http://127.0.0.1:2379"}, "etcd v3 cluster endpoints.")
|
||||
fs.StringVar(&a.EtcdCaFile, "etcd-ca", "", "")
|
||||
fs.StringVar(&a.EtcdCertFile, "etcd-cert", "", "")
|
||||
fs.StringVar(&a.EtcdKeyFile, "etcd-key", "", "")
|
||||
fs.IntVar(&a.EtcdTimeout, "etcd-timeout", 5, "etcd http timeout seconds")
|
||||
fs.StringVar(&a.EtcdPrefix, "etcd-prefix", "/store", "the etcd data save key prefix ")
|
||||
fs.StringVar(&a.PrometheusMetricPath, "metric", "/metrics", "prometheus metrics path")
|
||||
fs.StringVar(&a.Listen, "listen", ":6369", "prometheus listen host and port")
|
||||
fs.StringVar(&a.DBType, "db-type", "mysql", "db type mysql or etcd")
|
||||
fs.StringVar(&a.MysqlConnectionInfo, "mysql", "root:admin@tcp(127.0.0.1:3306)/region", "mysql db connection info")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"127.0.0.1:6366"}, "event log server address. simple lb")
|
||||
fs.StringSliceVar(&a.EventLogServers, "event-servers", []string{"rbd-eventlog:6366"}, "event log server address. simple lb")
|
||||
fs.StringVar(&a.KubeConfig, "kube-config", "", "kubernetes api server config file")
|
||||
fs.IntVar(&a.KubeAPIQPS, "kube-api-qps", 50, "kube client qps")
|
||||
fs.IntVar(&a.KubeAPIBurst, "kube-api-burst", 10, "kube clint burst")
|
||||
fs.IntVar(&a.MaxTasks, "max-tasks", 50, "the max tasks for per node")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "127.0.0.1:6300", "acp_mq api")
|
||||
fs.StringVar(&a.MQAPI, "mq-api", "rbd-mq:6300", "acp_mq api")
|
||||
fs.StringVar(&a.RunMode, "run", "sync", "sync data when worker start")
|
||||
fs.StringVar(&a.NodeName, "node-name", "", "the name of this worker,it must be global unique name")
|
||||
fs.StringVar(&a.HostIP, "host-ip", "", "the ip of this worker,it must be global connected ip")
|
||||
fs.IntVar(&a.ServerPort, "server-port", 6535, "the listen port that app runtime server")
|
||||
fs.StringVar(&a.LeaderElectionNamespace, "leader-election-namespace", "rainbond", "Namespace where this attacher runs.")
|
||||
fs.StringVar(&a.LeaderElectionNamespace, "leader-election-namespace", "rbd-system", "Namespace where this attacher runs.")
|
||||
fs.StringVar(&a.LeaderElectionIdentity, "leader-election-identity", "", "Unique idenity of this attcher. Typically name of the pod where the attacher runs.")
|
||||
fs.StringVar(&a.RBDNamespace, "rbd-system-namespace", "rbd-system", "rbd components kubernetes namespace")
|
||||
fs.StringVar(&a.GrdataPVCName, "grdata-pvc-name", "rbd-cpt-grdata", "The name of grdata persistent volume claim")
|
||||
fs.StringVar(&a.Helm.DataDir, "helm-data-dir", "helm-data-dir", "The data directory of Helm.")
|
||||
|
||||
if a.Helm.DataDir == "" {
|
||||
a.Helm.DataDir = "/grdata/helm"
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import (
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/pkg/common"
|
||||
"github.com/goodrain/rainbond/pkg/generated/clientset/versioned"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
k8sutil "github.com/goodrain/rainbond/util/k8s"
|
||||
"github.com/goodrain/rainbond/worker/appm/componentdefinition"
|
||||
"github.com/goodrain/rainbond/worker/appm/controller"
|
||||
@ -52,23 +51,14 @@ func Run(s *option.Worker) error {
|
||||
dbconfig := config.Config{
|
||||
DBType: s.Config.DBType,
|
||||
MysqlConnectionInfo: s.Config.MysqlConnectionInfo,
|
||||
EtcdEndPoints: s.Config.EtcdEndPoints,
|
||||
EtcdTimeout: s.Config.EtcdTimeout,
|
||||
}
|
||||
//step 1:db manager init ,event log client init
|
||||
if err := db.CreateManager(dbconfig); err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.CloseManager()
|
||||
etcdClientArgs := &etcdutil.ClientArgs{
|
||||
Endpoints: s.Config.EtcdEndPoints,
|
||||
CaFile: s.Config.EtcdCaFile,
|
||||
CertFile: s.Config.EtcdCertFile,
|
||||
KeyFile: s.Config.EtcdKeyFile,
|
||||
}
|
||||
if err := event.NewManager(event.EventConfig{
|
||||
EventLogServers: s.Config.EventLogServers,
|
||||
DiscoverArgs: etcdClientArgs,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
dbconfig "github.com/goodrain/rainbond/db/config"
|
||||
"github.com/goodrain/rainbond/db/model"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestEndpointDaoImpl_UpdateModel(t *testing.T) {
|
||||
dbname := "region"
|
||||
rootpw := "rainbond"
|
||||
|
||||
ctx := context.Background()
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "mariadb",
|
||||
ExposedPorts: []string{"3306/tcp"},
|
||||
Env: map[string]string{
|
||||
"MYSQL_ROOT_PASSWORD": rootpw,
|
||||
"MYSQL_DATABASE": dbname,
|
||||
},
|
||||
Cmd: []string{"character-set-server=utf8mb4", "collation-server=utf8mb4_unicode_ci"},
|
||||
}
|
||||
mariadb, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mariadb.Terminate(ctx)
|
||||
|
||||
host, err := mariadb.Host(ctx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
port, err := mariadb.MappedPort(ctx, "3306")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
connInfo := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", "root",
|
||||
rootpw, host, port.Int(), dbname)
|
||||
tryTimes := 3
|
||||
for {
|
||||
if err := CreateManager(dbconfig.Config{
|
||||
DBType: "mysql",
|
||||
MysqlConnectionInfo: connInfo,
|
||||
}); err != nil {
|
||||
if tryTimes == 0 {
|
||||
t.Fatalf("Connect info: %s; error creating db manager: %v", connInfo, err)
|
||||
} else {
|
||||
tryTimes = tryTimes - 1
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
trueVal := true
|
||||
falseVal := false
|
||||
ep := &model.Endpoint{
|
||||
UUID: util.NewUUID(),
|
||||
ServiceID: util.NewUUID(),
|
||||
IP: "10.10.10.10",
|
||||
IsOnline: &trueVal,
|
||||
}
|
||||
err = GetManager().EndpointsDao().AddModel(ep)
|
||||
if err != nil {
|
||||
t.Fatalf("error adding endpoint: %v", err)
|
||||
}
|
||||
ep.IsOnline = &falseVal
|
||||
err = GetManager().EndpointsDao().UpdateModel(ep)
|
||||
if err != nil {
|
||||
t.Fatalf("error updating endpoint: %v", err)
|
||||
}
|
||||
e, err := GetManager().EndpointsDao().GetByUUID(ep.UUID)
|
||||
if err != nil {
|
||||
t.Fatalf("error getting endpoint: %v", err)
|
||||
}
|
||||
if *e.IsOnline != false {
|
||||
t.Errorf("Expected %v for e.IsOnline, but returned %v", false, e.IsOnline)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEndpointDaoImpl_AddModel(t *testing.T) {
|
||||
dbname := "region"
|
||||
rootpw := "rainbond"
|
||||
|
||||
ctx := context.Background()
|
||||
req := testcontainers.ContainerRequest{
|
||||
Image: "mariadb",
|
||||
ExposedPorts: []string{"3306/tcp"},
|
||||
Env: map[string]string{
|
||||
"MYSQL_ROOT_PASSWORD": rootpw,
|
||||
"MYSQL_DATABASE": dbname,
|
||||
},
|
||||
Cmd: []string{"character-set-server=utf8mb4", "collation-server=utf8mb4_unicode_ci"},
|
||||
}
|
||||
mariadb, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: req,
|
||||
Started: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer mariadb.Terminate(ctx)
|
||||
|
||||
host, err := mariadb.Host(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
port, err := mariadb.MappedPort(ctx, "3306")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
connInfo := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", "root",
|
||||
rootpw, host, port.Int(), dbname)
|
||||
tryTimes := 3
|
||||
for {
|
||||
if err := CreateManager(dbconfig.Config{
|
||||
DBType: "mysql",
|
||||
MysqlConnectionInfo: connInfo,
|
||||
}); err != nil {
|
||||
if tryTimes == 0 {
|
||||
t.Fatalf("Connect info: %s; error creating db manager: %v", connInfo, err)
|
||||
} else {
|
||||
tryTimes = tryTimes - 1
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
falseVal := false
|
||||
ep := &model.Endpoint{
|
||||
UUID: util.NewUUID(),
|
||||
ServiceID: util.NewUUID(),
|
||||
IP: "10.10.10.10",
|
||||
IsOnline: &falseVal,
|
||||
}
|
||||
err = GetManager().EndpointsDao().AddModel(ep)
|
||||
if err != nil {
|
||||
t.Fatalf("error adding endpoint: %v", err)
|
||||
}
|
||||
e, err := GetManager().EndpointsDao().GetByUUID(ep.UUID)
|
||||
if err != nil {
|
||||
t.Fatalf("error getting endpoint: %v", err)
|
||||
}
|
||||
if *e.IsOnline != false {
|
||||
t.Errorf("Expected %v for e.IsOnline, but returned %v", false, e.IsOnline)
|
||||
}
|
||||
}
|
@ -19,19 +19,9 @@
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
"github.com/coreos/etcd/mvcc/mvccpb"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/goodrain/rainbond/discover.v2/config"
|
||||
)
|
||||
|
||||
//CallbackUpdate 每次返还变化
|
||||
@ -58,36 +48,6 @@ type Discover interface {
|
||||
AddUpdateProject(name string, callback CallbackUpdate)
|
||||
Stop()
|
||||
}
|
||||
|
||||
//GetDiscover 获取服务发现管理器
|
||||
func GetDiscover(opt config.DiscoverConfig) (Discover, error) {
|
||||
if opt.Ctx == nil {
|
||||
opt.Ctx = context.Background()
|
||||
}
|
||||
ctx, cancel := context.WithCancel(opt.Ctx)
|
||||
client, err := etcdutil.NewClient(ctx, opt.EtcdClientArgs)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
etcdD := &etcdDiscover{
|
||||
projects: make(map[string]CallbackUpdate),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
client: client,
|
||||
prefix: "/rainbond/discover",
|
||||
}
|
||||
return etcdD, nil
|
||||
}
|
||||
|
||||
type etcdDiscover struct {
|
||||
projects map[string]CallbackUpdate
|
||||
lock sync.Mutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
client *clientv3.Client
|
||||
prefix string
|
||||
}
|
||||
type defaultCallBackUpdate struct {
|
||||
endpoints map[string]*config.Endpoint
|
||||
callback Callback
|
||||
@ -182,125 +142,3 @@ func (d *defaultCallBackUpdate) UpdateEndpoints(operation config.Operation, endp
|
||||
func (d *defaultCallBackUpdate) Error(err error) {
|
||||
d.callback.Error(err)
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) AddProject(name string, callback Callback) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; !ok {
|
||||
cal := &defaultCallBackUpdate{
|
||||
callback: callback,
|
||||
endpoints: make(map[string]*config.Endpoint),
|
||||
}
|
||||
e.projects[name] = cal
|
||||
go e.discover(name, cal)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) AddUpdateProject(name string, callback CallbackUpdate) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; !ok {
|
||||
e.projects[name] = callback
|
||||
go e.discover(name, callback)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) Stop() {
|
||||
e.cancel()
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) removeProject(name string) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; ok {
|
||||
delete(e.projects, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) discover(name string, callback CallbackUpdate) {
|
||||
ctx, cancel := context.WithCancel(e.ctx)
|
||||
defer cancel()
|
||||
endpoints := e.list(name)
|
||||
if endpoints != nil && len(endpoints) > 0 {
|
||||
callback.UpdateEndpoints(config.SYNC, endpoints...)
|
||||
}
|
||||
watch := e.client.Watch(ctx, fmt.Sprintf("%s/%s", e.prefix, name), clientv3.WithPrefix())
|
||||
timer := time.NewTimer(time.Second * 20)
|
||||
defer timer.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-e.ctx.Done():
|
||||
return
|
||||
case <-timer.C:
|
||||
go e.discover(name, callback)
|
||||
return
|
||||
case res := <-watch:
|
||||
if err := res.Err(); err != nil {
|
||||
callback.Error(err)
|
||||
logrus.Debugf("monitor discover get watch error: %s, remove this watch target first, and then sleep 10 sec, we will re-watch it", err.Error())
|
||||
e.removeProject(name)
|
||||
time.Sleep(10 * time.Second)
|
||||
e.AddUpdateProject(name, callback)
|
||||
return
|
||||
}
|
||||
for _, event := range res.Events {
|
||||
if event.Kv != nil {
|
||||
var end *config.Endpoint
|
||||
kstep := strings.Split(string(event.Kv.Key), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-1]
|
||||
serverURL := string(event.Kv.Value)
|
||||
end = &config.Endpoint{Name: serverName, URL: serverURL, Mode: 0}
|
||||
}
|
||||
if end != nil { //获取服务地址
|
||||
switch event.Type {
|
||||
case mvccpb.DELETE:
|
||||
callback.UpdateEndpoints(config.DELETE, end)
|
||||
case mvccpb.PUT:
|
||||
if event.Kv.Version == 1 {
|
||||
callback.UpdateEndpoints(config.ADD, end)
|
||||
} else {
|
||||
callback.UpdateEndpoints(config.UPDATE, end)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timer.Reset(time.Second * 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
func (e *etcdDiscover) list(name string) []*config.Endpoint {
|
||||
ctx, cancel := context.WithTimeout(e.ctx, time.Second*10)
|
||||
defer cancel()
|
||||
res, err := e.client.Get(ctx, fmt.Sprintf("%s/%s", e.prefix, name), clientv3.WithPrefix())
|
||||
if err != nil {
|
||||
logrus.Errorf("list all servers of %s error.%s", name, err.Error())
|
||||
return nil
|
||||
}
|
||||
if res.Count == 0 {
|
||||
return nil
|
||||
}
|
||||
return makeEndpointForKvs(res.Kvs)
|
||||
}
|
||||
|
||||
func makeEndpointForKvs(kvs []*mvccpb.KeyValue) (res []*config.Endpoint) {
|
||||
var ends = make(map[string]*config.Endpoint)
|
||||
for _, kv := range kvs {
|
||||
//获取服务地址
|
||||
kstep := strings.Split(string(kv.Key), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-1]
|
||||
serverURL := string(kv.Value)
|
||||
if en, ok := ends[serverName]; ok {
|
||||
en.URL = serverURL
|
||||
} else {
|
||||
ends[serverName] = &config.Endpoint{Name: serverName, URL: serverURL}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range ends {
|
||||
res = append(res, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
"testing"
|
||||
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestAddUpdateProject(t *testing.T) {
|
||||
etcdClientArgs := &etcdutil.ClientArgs{Endpoints: []string{"127.0.0.1:2379"}}
|
||||
discover, err := GetDiscover(config.DiscoverConfig{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer discover.Stop()
|
||||
discover.AddUpdateProject("test", callbackupdate{})
|
||||
}
|
||||
func TestAddProject(t *testing.T) {
|
||||
etcdClientArgs := &etcdutil.ClientArgs{Endpoints: []string{"127.0.0.1:2379"}}
|
||||
discover, err := GetDiscover(config.DiscoverConfig{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer discover.Stop()
|
||||
discover.AddProject("test", callback{})
|
||||
}
|
||||
|
||||
type callbackupdate struct {
|
||||
callback
|
||||
}
|
||||
|
||||
func (c callbackupdate) UpdateEndpoints(operation config.Operation, endpoints ...*config.Endpoint) {
|
||||
logrus.Info(operation, "////", endpoints)
|
||||
}
|
||||
|
||||
type callback struct {
|
||||
}
|
||||
|
||||
func (c callback) UpdateEndpoints(endpoints ...*config.Endpoint) {
|
||||
for _, en := range endpoints {
|
||||
logrus.Infof("%+v", en)
|
||||
}
|
||||
}
|
||||
|
||||
//when watch occurred error,will exec this method
|
||||
func (c callback) Error(err error) {
|
||||
logrus.Error(err.Error())
|
||||
}
|
@ -14,8 +14,8 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
"github.com/goodrain/rainbond/discover.v2/config"
|
||||
)
|
||||
|
||||
type k8sDiscover struct {
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/cmd/node/option"
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
"github.com/goodrain/rainbond/cmd/node-proxy/option"
|
||||
"github.com/goodrain/rainbond/discover.v2/config"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
|
@ -1,162 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
client "github.com/coreos/etcd/clientv3"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
grpcutil "github.com/goodrain/rainbond/util/grpc"
|
||||
"github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc/naming"
|
||||
)
|
||||
|
||||
//KeepAlive 服务注册
|
||||
type KeepAlive struct {
|
||||
cancel context.CancelFunc
|
||||
EtcdClientArgs *etcdutil.ClientArgs
|
||||
ServerName string
|
||||
HostName string
|
||||
Endpoint string
|
||||
TTL int64
|
||||
LID clientv3.LeaseID
|
||||
Done chan struct{}
|
||||
etcdClient *client.Client
|
||||
gRPCResolver *grpcutil.GRPCResolver
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
//CreateKeepAlive create keepalive for server
|
||||
func CreateKeepAlive(etcdClientArgs *etcdutil.ClientArgs, ServerName string, Protocol string, HostIP string, Port int) (*KeepAlive, error) {
|
||||
if ServerName == "" || Port == 0 {
|
||||
return nil, fmt.Errorf("servername or serverport can not be empty")
|
||||
}
|
||||
if HostIP == "" {
|
||||
ip, err := util.LocalIP()
|
||||
if err != nil {
|
||||
logrus.Errorf("get ip failed,details %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
HostIP = ip.String()
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
etcdclient, err := etcdutil.NewClient(ctx, etcdClientArgs)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k := &KeepAlive{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
ServerName: ServerName,
|
||||
Endpoint: fmt.Sprintf("%s:%d", HostIP, Port),
|
||||
TTL: 5,
|
||||
Done: make(chan struct{}),
|
||||
etcdClient: etcdclient,
|
||||
cancel: cancel,
|
||||
}
|
||||
if Protocol == "" {
|
||||
k.Endpoint = fmt.Sprintf("%s:%d", HostIP, Port)
|
||||
} else {
|
||||
k.Endpoint = fmt.Sprintf("%s://%s:%d", Protocol, HostIP, Port)
|
||||
}
|
||||
return k, nil
|
||||
}
|
||||
|
||||
//Start 开始
|
||||
func (k *KeepAlive) Start() error {
|
||||
duration := time.Duration(k.TTL) * time.Second
|
||||
timer := time.NewTimer(duration)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-k.Done:
|
||||
return
|
||||
case <-timer.C:
|
||||
if k.LID > 0 {
|
||||
func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
defer timer.Reset(duration)
|
||||
_, err := k.etcdClient.KeepAliveOnce(ctx, k.LID)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
logrus.Warnf("%s lid[%x] keepAlive err: %s, try to reset...", k.Endpoint, k.LID, err.Error())
|
||||
k.LID = 0
|
||||
}()
|
||||
} else {
|
||||
if err := k.reg(); err != nil {
|
||||
logrus.Warnf("%s set lid err: %s, try to reset after %d seconds...", k.Endpoint, err.Error(), k.TTL)
|
||||
} else {
|
||||
logrus.Infof("%s set lid[%x] success", k.Endpoint, k.LID)
|
||||
}
|
||||
timer.Reset(duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *KeepAlive) etcdKey() string {
|
||||
return fmt.Sprintf("/rainbond/discover/%s", k.ServerName)
|
||||
}
|
||||
|
||||
func (k *KeepAlive) reg() error {
|
||||
k.gRPCResolver = &grpcutil.GRPCResolver{Client: k.etcdClient}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
resp, err := k.etcdClient.Grant(ctx, k.TTL+3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.gRPCResolver.Update(ctx, k.etcdKey(), naming.Update{Op: naming.Add, Addr: k.Endpoint}, clientv3.WithLease(resp.ID)); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("Register a %s server endpoint %s to cluster", k.ServerName, k.Endpoint)
|
||||
k.LID = resp.ID
|
||||
return nil
|
||||
}
|
||||
|
||||
//Stop 结束
|
||||
func (k *KeepAlive) Stop() {
|
||||
k.once.Do(func() {
|
||||
close(k.Done)
|
||||
k.cancel()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
if k.gRPCResolver != nil {
|
||||
if err := k.gRPCResolver.Update(ctx, k.etcdKey(), naming.Update{Op: naming.Delete, Addr: k.Endpoint}); err != nil {
|
||||
logrus.Errorf("cancel %s server endpoint %s from etcd error %s", k.ServerName, k.Endpoint, err.Error())
|
||||
} else {
|
||||
logrus.Infof("cancel %s server endpoint %s from etcd", k.ServerName, k.Endpoint)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
## 数据中心内部服务发现包
|
||||
基于ETCD实现
|
@ -1,50 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package config
|
||||
|
||||
import "context"
|
||||
import etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
|
||||
//Operation 实例操作类型
|
||||
type Operation int
|
||||
|
||||
const (
|
||||
// ADD add operation
|
||||
ADD Operation = iota
|
||||
// DELETE delete operation
|
||||
DELETE
|
||||
// UPDATE update operation
|
||||
UPDATE
|
||||
// SYNC sync operation
|
||||
SYNC
|
||||
)
|
||||
|
||||
//DiscoverConfig discover config
|
||||
type DiscoverConfig struct {
|
||||
Ctx context.Context
|
||||
EtcdClientArgs *etcdutil.ClientArgs
|
||||
}
|
||||
|
||||
// Endpoint endpoint
|
||||
type Endpoint struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Weight int `json:"weight"`
|
||||
Mode int `json:"-"` //0 表示URL变化,1表示Weight变化 ,2表示全变化
|
||||
}
|
@ -1,315 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/goodrain/rainbond/util/watch"
|
||||
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/coreos/etcd/mvcc/mvccpb"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//CallbackUpdate 每次返还变化
|
||||
type CallbackUpdate interface {
|
||||
//TODO:
|
||||
//weight自动发现更改实现暂时不 Ready
|
||||
UpdateEndpoints(operation config.Operation, endpoints ...*config.Endpoint)
|
||||
//when watch occurred error,will exec this method
|
||||
Error(error)
|
||||
}
|
||||
|
||||
//Callback 每次返回全部节点
|
||||
type Callback interface {
|
||||
UpdateEndpoints(endpoints ...*config.Endpoint)
|
||||
//when watch occurred error,will exec this method
|
||||
Error(error)
|
||||
}
|
||||
|
||||
//Discover 后端服务自动发现
|
||||
type Discover interface {
|
||||
AddProject(name string, callback Callback)
|
||||
AddUpdateProject(name string, callback CallbackUpdate)
|
||||
Stop()
|
||||
}
|
||||
|
||||
//GetDiscover 获取服务发现管理器
|
||||
func GetDiscover(opt config.DiscoverConfig) (Discover, error) {
|
||||
if opt.Ctx == nil {
|
||||
opt.Ctx = context.Background()
|
||||
}
|
||||
ctx, cancel := context.WithCancel(opt.Ctx)
|
||||
client, err := etcdutil.NewClient(ctx, opt.EtcdClientArgs)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
watcher := watch.New(client, "")
|
||||
etcdD := &etcdDiscover{
|
||||
projects: make(map[string]CallbackUpdate),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
watcher: watcher,
|
||||
prefix: "/traefik",
|
||||
}
|
||||
return etcdD, nil
|
||||
}
|
||||
|
||||
type etcdDiscover struct {
|
||||
projects map[string]CallbackUpdate
|
||||
lock sync.Mutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
watcher watch.Watch
|
||||
prefix string
|
||||
}
|
||||
type defaultCallBackUpdate struct {
|
||||
endpoints map[string]*config.Endpoint
|
||||
callback Callback
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (d *defaultCallBackUpdate) UpdateEndpoints(operation config.Operation, endpoints ...*config.Endpoint) {
|
||||
d.lock.Lock()
|
||||
defer d.lock.Unlock()
|
||||
switch operation {
|
||||
case config.ADD:
|
||||
for _, e := range endpoints {
|
||||
if old, ok := d.endpoints[e.Name]; !ok {
|
||||
d.endpoints[e.Name] = e
|
||||
} else {
|
||||
if e.Mode == 0 {
|
||||
old.URL = e.URL
|
||||
}
|
||||
if e.Mode == 1 {
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
if e.Mode == 2 {
|
||||
old.URL = e.URL
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
}
|
||||
}
|
||||
case config.SYNC:
|
||||
for _, e := range endpoints {
|
||||
if old, ok := d.endpoints[e.Name]; !ok {
|
||||
d.endpoints[e.Name] = e
|
||||
} else {
|
||||
if e.Mode == 0 {
|
||||
old.URL = e.URL
|
||||
}
|
||||
if e.Mode == 1 {
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
if e.Mode == 2 {
|
||||
old.URL = e.URL
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
}
|
||||
}
|
||||
case config.DELETE:
|
||||
for _, e := range endpoints {
|
||||
if e.Mode == 0 {
|
||||
if old, ok := d.endpoints[e.Name]; ok {
|
||||
old.URL = ""
|
||||
}
|
||||
}
|
||||
if e.Mode == 1 {
|
||||
if old, ok := d.endpoints[e.Name]; ok {
|
||||
old.Weight = 0
|
||||
}
|
||||
}
|
||||
if e.Mode == 2 {
|
||||
if _, ok := d.endpoints[e.Name]; ok {
|
||||
delete(d.endpoints, e.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
case config.UPDATE:
|
||||
for _, e := range endpoints {
|
||||
if e.Mode == 0 {
|
||||
if old, ok := d.endpoints[e.Name]; ok {
|
||||
old.URL = e.URL
|
||||
}
|
||||
}
|
||||
if e.Mode == 1 {
|
||||
if old, ok := d.endpoints[e.Name]; ok {
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
}
|
||||
if e.Mode == 2 {
|
||||
if old, ok := d.endpoints[e.Name]; ok {
|
||||
old.URL = e.URL
|
||||
old.Weight = e.Weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var re []*config.Endpoint
|
||||
for _, v := range d.endpoints {
|
||||
if v.URL != "" {
|
||||
re = append(re, v)
|
||||
}
|
||||
}
|
||||
d.callback.UpdateEndpoints(re...)
|
||||
}
|
||||
|
||||
func (d *defaultCallBackUpdate) Error(err error) {
|
||||
d.callback.Error(err)
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) AddProject(name string, callback Callback) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; !ok {
|
||||
cal := &defaultCallBackUpdate{
|
||||
callback: callback,
|
||||
endpoints: make(map[string]*config.Endpoint),
|
||||
}
|
||||
e.projects[name] = cal
|
||||
go e.discover(name, cal)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) AddUpdateProject(name string, callback CallbackUpdate) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; !ok {
|
||||
e.projects[name] = callback
|
||||
go e.discover(name, callback)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) Stop() {
|
||||
e.cancel()
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) removeProject(name string) {
|
||||
e.lock.Lock()
|
||||
defer e.lock.Unlock()
|
||||
if _, ok := e.projects[name]; ok {
|
||||
delete(e.projects, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *etcdDiscover) discover(name string, callback CallbackUpdate) {
|
||||
watchChan, err := e.watcher.WatchList(e.ctx, fmt.Sprintf("%s/backends/%s/servers", e.prefix, name), "")
|
||||
if err != nil {
|
||||
callback.Error(err)
|
||||
e.removeProject(name)
|
||||
return
|
||||
}
|
||||
defer watchChan.Stop()
|
||||
for event := range watchChan.ResultChan() {
|
||||
if event.Source == nil {
|
||||
continue
|
||||
}
|
||||
var end *config.Endpoint
|
||||
if strings.HasSuffix(event.GetKey(), "/url") { //服务地址变化
|
||||
kstep := strings.Split(event.GetKey(), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-2]
|
||||
serverURL := event.GetValueString()
|
||||
end = &config.Endpoint{Name: serverName, URL: serverURL, Mode: 0}
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(event.GetKey(), "/weight") { //获取服务地址
|
||||
kstep := strings.Split(event.GetKey(), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-2]
|
||||
serverWeight := event.GetValueString()
|
||||
weight, _ := strconv.Atoi(serverWeight)
|
||||
end = &config.Endpoint{Name: serverName, Weight: weight, Mode: 1}
|
||||
}
|
||||
}
|
||||
switch event.Type {
|
||||
case watch.Added:
|
||||
if end != nil {
|
||||
callback.UpdateEndpoints(config.ADD, end)
|
||||
}
|
||||
case watch.Modified:
|
||||
if end != nil {
|
||||
callback.UpdateEndpoints(config.UPDATE, end)
|
||||
}
|
||||
case watch.Deleted:
|
||||
if end != nil {
|
||||
callback.UpdateEndpoints(config.DELETE, end)
|
||||
}
|
||||
case watch.Error:
|
||||
callback.Error(event.Error)
|
||||
logrus.Errorf("monitor discover get watch error: %s, remove this watch target first, and then sleep 10 sec, we will re-watch it", event.Error.Error())
|
||||
e.removeProject(name)
|
||||
time.Sleep(10 * time.Second)
|
||||
e.AddUpdateProject(name, callback)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeEndpointForKvs(kvs []*mvccpb.KeyValue) (res []*config.Endpoint) {
|
||||
var ends = make(map[string]*config.Endpoint)
|
||||
for _, kv := range kvs {
|
||||
if strings.HasSuffix(string(kv.Key), "/url") { //获取服务地址
|
||||
kstep := strings.Split(string(kv.Key), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-2]
|
||||
serverURL := string(kv.Value)
|
||||
if en, ok := ends[serverName]; ok {
|
||||
en.URL = serverURL
|
||||
} else {
|
||||
ends[serverName] = &config.Endpoint{Name: serverName, URL: serverURL}
|
||||
}
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(string(kv.Key), "/weight") { //获取服务权重
|
||||
kstep := strings.Split(string(kv.Key), "/")
|
||||
if len(kstep) > 2 {
|
||||
serverName := kstep[len(kstep)-2]
|
||||
serverWeight := string(kv.Value)
|
||||
if en, ok := ends[serverName]; ok {
|
||||
var err error
|
||||
en.Weight, err = strconv.Atoi(serverWeight)
|
||||
if err != nil {
|
||||
logrus.Error("get server weight error.", err.Error())
|
||||
}
|
||||
} else {
|
||||
weight, err := strconv.Atoi(serverWeight)
|
||||
if err != nil {
|
||||
logrus.Error("get server weight error.", err.Error())
|
||||
}
|
||||
ends[serverName] = &config.Endpoint{Name: serverName, Weight: weight}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range ends {
|
||||
res = append(res, v)
|
||||
}
|
||||
return
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goodrain/rainbond/discover/config"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestAddUpdateProject(t *testing.T) {
|
||||
etcdClientArgs := &etcdutil.ClientArgs{Endpoints: []string{"127.0.0.1:2379"}}
|
||||
discover, err := GetDiscover(config.DiscoverConfig{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer discover.Stop()
|
||||
discover.AddUpdateProject("test", callbackupdate{})
|
||||
}
|
||||
func TestAddProject(t *testing.T) {
|
||||
etcdClientArgs := &etcdutil.ClientArgs{Endpoints: []string{"127.0.0.1:2379"}}
|
||||
discover, err := GetDiscover(config.DiscoverConfig{
|
||||
EtcdClientArgs: etcdClientArgs,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer discover.Stop()
|
||||
discover.AddProject("test", callback{})
|
||||
}
|
||||
|
||||
type callbackupdate struct {
|
||||
callback
|
||||
}
|
||||
|
||||
func (c callbackupdate) UpdateEndpoints(operation config.Operation, endpoints ...*config.Endpoint) {
|
||||
logrus.Info(operation, "////", endpoints)
|
||||
}
|
||||
|
||||
type callback struct {
|
||||
}
|
||||
|
||||
func (c callback) UpdateEndpoints(endpoints ...*config.Endpoint) {
|
||||
for _, en := range endpoints {
|
||||
logrus.Infof("%+v", en)
|
||||
}
|
||||
}
|
||||
|
||||
//when watch occurred error,will exec this method
|
||||
func (c callback) Error(err error) {
|
||||
logrus.Error(err.Error())
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package discover
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
client "github.com/coreos/etcd/clientv3"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
etcdutil "github.com/goodrain/rainbond/util/etcd"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
//KeepAlive 服务注册
|
||||
type KeepAlive struct {
|
||||
cancel context.CancelFunc
|
||||
EtcdClentArgs *etcdutil.ClientArgs
|
||||
ServerName string
|
||||
HostName string
|
||||
Endpoint string
|
||||
TTL int64
|
||||
LID clientv3.LeaseID
|
||||
Done chan struct{}
|
||||
etcdClient *client.Client
|
||||
}
|
||||
|
||||
//CreateKeepAlive create keepalive for server
|
||||
func CreateKeepAlive(etcdClientArgs *etcdutil.ClientArgs, serverName string, hostName string, HostIP string, Port int) (*KeepAlive, error) {
|
||||
if serverName == "" || Port == 0 {
|
||||
return nil, fmt.Errorf("servername or serverport can not be empty")
|
||||
}
|
||||
if hostName == "" {
|
||||
var err error
|
||||
hostName, err = os.Hostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if HostIP == "" {
|
||||
ip, err := util.LocalIP()
|
||||
if err != nil {
|
||||
logrus.Errorf("get ip failed,details %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
HostIP = ip.String()
|
||||
}
|
||||
return &KeepAlive{
|
||||
EtcdClentArgs: etcdClientArgs,
|
||||
ServerName: serverName,
|
||||
HostName: hostName,
|
||||
Endpoint: fmt.Sprintf("%s:%d", HostIP, Port),
|
||||
TTL: 10,
|
||||
Done: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
//Start 开始
|
||||
func (k *KeepAlive) Start() error {
|
||||
duration := time.Duration(k.TTL) * time.Second
|
||||
timer := time.NewTimer(duration)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
etcdclient, err := etcdutil.NewClient(ctx, k.EtcdClentArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
k.etcdClient = etcdclient
|
||||
k.cancel = cancel
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-k.Done:
|
||||
return
|
||||
case <-timer.C:
|
||||
if k.LID > 0 {
|
||||
func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
_, err := k.etcdClient.KeepAliveOnce(ctx, k.LID)
|
||||
if err == nil {
|
||||
timer.Reset(duration)
|
||||
return
|
||||
}
|
||||
logrus.Warnf("%s lid[%x] keepAlive err: %s, try to reset...", k.Endpoint, k.LID, err.Error())
|
||||
k.LID = 0
|
||||
timer.Reset(duration)
|
||||
}()
|
||||
} else {
|
||||
if err := k.reg(); err != nil {
|
||||
logrus.Warnf("%s set lid err: %s, try to reset after %d seconds...", k.Endpoint, err.Error(), k.TTL)
|
||||
} else {
|
||||
logrus.Infof("%s set lid[%x] success", k.Endpoint, k.LID)
|
||||
}
|
||||
timer.Reset(duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *KeepAlive) etcdKey() string {
|
||||
return fmt.Sprintf("/traefik/backends/%s/servers/%s/url", k.ServerName, k.HostName)
|
||||
}
|
||||
|
||||
func (k *KeepAlive) reg() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
resp, err := k.etcdClient.Grant(ctx, k.TTL+3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := k.etcdClient.Put(ctx,
|
||||
k.etcdKey(),
|
||||
k.Endpoint,
|
||||
clientv3.WithLease(resp.ID)); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("Register a %s server endpoint %s to cluster", k.ServerName, k.Endpoint)
|
||||
k.LID = resp.ID
|
||||
return nil
|
||||
}
|
||||
|
||||
//Stop 结束
|
||||
func (k *KeepAlive) Stop() error {
|
||||
close(k.Done)
|
||||
defer k.cancel()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
if _, err := k.etcdClient.Delete(ctx, k.etcdKey()); err != nil {
|
||||
return err
|
||||
}
|
||||
logrus.Infof("cancel %s server endpoint %s from etcd", k.ServerName, k.Endpoint)
|
||||
return nil
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
<svg version="1.1" width="36" height="36" viewBox="0 0 36 36" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>bell-outline-badged</title>
|
||||
<path class="clr-i-outline--badged clr-i-outline-path-1--badged" d="M18,34.28A2.67,2.67,0,0,0,20.58,32H15.32A2.67,2.67,0,0,0,18,34.28Z"></path><path class="clr-i-outline--badged clr-i-outline-path-2--badged" d="M32.51,27.83A14.4,14.4,0,0,1,30,24.9a12.63,12.63,0,0,1-1.35-4.81V15.15a10.92,10.92,0,0,0-.16-1.79,7.44,7.44,0,0,1-2.24-.84,8.89,8.89,0,0,1,.4,2.64v4.94a14.24,14.24,0,0,0,1.65,5.85,16.17,16.17,0,0,0,2.44,3H5.13a16.17,16.17,0,0,0,2.44-3,14.24,14.24,0,0,0,1.65-5.85V15.15A8.8,8.8,0,0,1,18,6.31a8.61,8.61,0,0,1,4.76,1.44A7.49,7.49,0,0,1,22.5,6c0-.21,0-.42,0-.63a10.58,10.58,0,0,0-3.32-1V3.11a1.33,1.33,0,1,0-2.67,0V4.42A10.81,10.81,0,0,0,7.21,15.15v4.94A12.63,12.63,0,0,1,5.86,24.9a14.4,14.4,0,0,1-2.47,2.93,1,1,0,0,0-.34.75v1.36a1,1,0,0,0,1,1h27.8a1,1,0,0,0,1-1V28.58A1,1,0,0,0,32.51,27.83Z"></path><circle class="clr-i-outline--badged clr-i-outline-path-1--badged clr-i-badge" cx="30" cy="6" r="5"></circle>
|
||||
<rect x="0" y="0" width="36" height="36" fill-opacity="0"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 MiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user