mirror of https://github.com/sunface/rust-course
resolved #4
parent
aca6193dec
commit
1e53668872
@ -0,0 +1,125 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/rpc"
|
||||
"tfgo/tfe/api/async"
|
||||
"time"
|
||||
|
||||
"github.com/mafanr/juz/api/filter"
|
||||
"github.com/mafanr/juz/api/manage"
|
||||
"github.com/mafanr/juz/api/stats"
|
||||
"github.com/mafanr/juz/misc"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/labstack/echo"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type ApiServer struct {
|
||||
manage *manage.Manage
|
||||
router *router
|
||||
}
|
||||
|
||||
func (p *ApiServer) Start() {
|
||||
g.L.Info("start tfe..")
|
||||
|
||||
// 初始化mysql连接
|
||||
misc.InitMysql()
|
||||
|
||||
// 从mysql中加载所有的api信息到内存中
|
||||
p.loadData()
|
||||
|
||||
p.manage = &manage.Manage{}
|
||||
go p.manage.Start()
|
||||
|
||||
p.router = &router{p, &filter.Filter{}}
|
||||
|
||||
// 连接到traffic rpc服务
|
||||
p.initTraffic()
|
||||
|
||||
// 启动proxy http服务
|
||||
go p.listen()
|
||||
|
||||
// 启动metrics收集
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
http.ListenAndServe(":6062", nil)
|
||||
}
|
||||
|
||||
func (o *ApiServer) Shutdown() {
|
||||
g.L.Info("shutdown tfe..")
|
||||
}
|
||||
|
||||
func (p *ApiServer) listen() {
|
||||
e := echo.New()
|
||||
|
||||
// 回调相关
|
||||
//同步回调接口
|
||||
e.Any("/*", p.router.route, timing)
|
||||
//异步回调接口
|
||||
e.POST("/notify", async.Notify)
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + misc.Conf.Api.Port))
|
||||
}
|
||||
|
||||
func timing(f echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
ts := time.Now()
|
||||
rid := (ts.UnixNano()/10)*10 + misc.Conf.Api.ServerID
|
||||
g.L.Info("New request accepted", zap.Int64("rid", rid), zap.String("ip", c.RealIP()))
|
||||
c.Set("rid", rid)
|
||||
defer func() {
|
||||
// 统计请求指标
|
||||
apiID := c.Get("api_id").(string)
|
||||
service := c.Get("service").(string)
|
||||
label := c.Get("label").(string)
|
||||
stats.Req.With(prometheus.Labels{
|
||||
"api_id": apiID,
|
||||
"service": service,
|
||||
"label": label,
|
||||
}).Observe(float64(time.Now().Sub(ts).Nanoseconds() / 1e6))
|
||||
|
||||
err := c.Get("error_msg")
|
||||
if err == nil {
|
||||
g.L.Info("Request success", zap.Int64("rid", rid))
|
||||
} else {
|
||||
g.L.Info("Request failed", zap.Int64("rid", rid), zap.Error(err.(error)))
|
||||
}
|
||||
}()
|
||||
|
||||
return f(c)
|
||||
}
|
||||
}
|
||||
|
||||
func (as *ApiServer) initTraffic() {
|
||||
r, err := rpc.Dial("tcp", misc.Conf.Traffic.Host+":"+misc.Conf.Traffic.Port)
|
||||
if err != nil {
|
||||
g.L.Fatal("connect to raffic error", zap.Error(err))
|
||||
}
|
||||
as.router.Filter.Rpc = r
|
||||
|
||||
// 定时检测rpc连接的存活性
|
||||
go func() {
|
||||
for {
|
||||
var res int
|
||||
err := as.router.Filter.Rpc.Call("RateLimiter.Ping", 1, &res)
|
||||
if err != nil || res != 1 {
|
||||
g.L.Warn("rpc ping failed", zap.Error(err))
|
||||
r, err := rpc.Dial("tcp", misc.Conf.Traffic.Host+":"+misc.Conf.Traffic.Port)
|
||||
if err != nil {
|
||||
g.L.Warn("re-connect to traffic error", zap.Error(err))
|
||||
time.Sleep(2 * time.Second)
|
||||
continue
|
||||
}
|
||||
as.router.Filter.Rpc = r
|
||||
g.L.Info("re-connect to traffic ok")
|
||||
}
|
||||
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
}()
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTfeStartStop(t *testing.T) {
|
||||
p := &Proxy{}
|
||||
g.InitConfig("../tfe.conf")
|
||||
g.InitLogger()
|
||||
|
||||
go func() {
|
||||
p.Start()
|
||||
}()
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
resp, err := http.Get("http://localhost:" + g.Conf.Common.Port + "/service/api?service_id=" + g.TEST_API_NAME)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 200, resp.StatusCode)
|
||||
|
||||
p.Shutdown()
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/mafanr/juz/api/req"
|
||||
"github.com/mafanr/juz/misc"
|
||||
)
|
||||
|
||||
/*
|
||||
对用户请求的参数进行验证
|
||||
*/
|
||||
|
||||
func (f *Filter) verifyParam(r *req.Request) error {
|
||||
if r.Api.VerifyOn == misc.PARAM_VERIFY_OFF {
|
||||
return nil
|
||||
}
|
||||
|
||||
for k, v := range r.Params {
|
||||
regI, ok := r.Api.ParamRules.Load(k)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
reg := regI.(*regexp.Regexp)
|
||||
if !reg.MatchString(v) { // 参数不合法
|
||||
return fmt.Errorf("param %s,value %s, verify failed", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/mafanr/juz/g"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLoadRow(t *testing.T) {
|
||||
g.InitConfig("../tfe.conf")
|
||||
g.InitLogger()
|
||||
|
||||
g.InitMysql()
|
||||
|
||||
p := &Proxy{}
|
||||
p.apis = &sync.Map{}
|
||||
p.loadAPIRow(g.TEST_API_NAME)
|
||||
_, ok := p.apis.Load(g.TEST_API_NAME)
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestLoadAll(t *testing.T) {
|
||||
g.InitConfig("../tfe.conf")
|
||||
g.InitLogger()
|
||||
|
||||
g.InitMysql()
|
||||
|
||||
p := &Proxy{}
|
||||
p.apis = &sync.Map{}
|
||||
p.loadAllAPIs()
|
||||
|
||||
_, ok := p.apis.Load(g.TEST_API_NAME)
|
||||
assert.True(t, ok)
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/sunface/talent"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const (
|
||||
TypeService = 1
|
||||
TypeApi = 2
|
||||
TypeStrategy = 3
|
||||
TypePrivilegy = 4
|
||||
TypeBatch = 5
|
||||
|
||||
OpCreate = 1
|
||||
OpEdit = 2
|
||||
OpRelease = 3
|
||||
OpOffline = 4
|
||||
OpDelete = 5
|
||||
)
|
||||
|
||||
func Log(userID string, service string, targetType int, targetID string, opType int, content string, desc string) {
|
||||
newc := g.B64.EncodeToString(talent.String2Bytes(content))
|
||||
query := fmt.Sprintf("insert into audit_log (user_id,service,target_type,target_id,op_type,content,description) values ('%s','%s','%d','%s','%d','%s','%s')",
|
||||
userID, service, targetType, targetID, opType, newc, desc)
|
||||
_, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("record audit log error", zap.Error(err), zap.String("query", query))
|
||||
}
|
||||
}
|
||||
|
||||
func Count(c echo.Context) error {
|
||||
tt := c.FormValue("target_type")
|
||||
tid := c.FormValue("target_id")
|
||||
if tt == "" || tid == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
var query string
|
||||
if tt == "0" {
|
||||
query = fmt.Sprintf("select count(1) from audit_log where service in (%s)", tid)
|
||||
} else {
|
||||
query = fmt.Sprintf("select count(1) from audit_log where target_id='%s' and target_type='%s'", tid, tt)
|
||||
}
|
||||
rows, err := g.DB.Query(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
var total int
|
||||
rows.Next()
|
||||
rows.Scan(&total)
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
Data: total,
|
||||
})
|
||||
}
|
||||
|
||||
type AuditLog struct {
|
||||
ID int `db:"id" json:"-"`
|
||||
UserID string `db:"user_id" json:"user_id"`
|
||||
Service string `db:"service" json:"service"`
|
||||
TargetType string `db:"target_type" json:"target_type"`
|
||||
TargetID string `db:"target_id" json:"target_id"`
|
||||
OpType string `db:"op_type" json:"op_type"`
|
||||
Content string `db:"content" json:"content"`
|
||||
Desc string `db:"description" json:"desc"`
|
||||
ModifyDate string `db:"modify_date" json:"modify_date"`
|
||||
}
|
||||
|
||||
func Load(c echo.Context) error {
|
||||
tt := c.FormValue("target_type")
|
||||
tid := c.FormValue("target_id")
|
||||
pageS := c.FormValue("page")
|
||||
|
||||
if tt == "" || tid == "" || pageS == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
page, _ := strconv.Atoi(pageS)
|
||||
if page <= 0 {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamInvalidC,
|
||||
Message: g.ParamInvalidE,
|
||||
})
|
||||
}
|
||||
|
||||
rs := make([]AuditLog, 0)
|
||||
var query string
|
||||
if tt == "0" {
|
||||
query = fmt.Sprintf("select * from audit_log where service in (%s) order by modify_date desc limit %d offset %d", tid, g.PER_PAGE, g.PER_PAGE*(page-1))
|
||||
} else {
|
||||
query = fmt.Sprintf("select * from audit_log where target_id='%s' and target_type='%s' order by modify_date desc limit %d offset %d", tid, tt, g.PER_PAGE, g.PER_PAGE*(page-1))
|
||||
}
|
||||
err := g.DB.Select(&rs, query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
for i, l := range rs {
|
||||
b, _ := g.B64.DecodeString(l.Content)
|
||||
rs[i].Content = talent.Bytes2String(b)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
Data: rs,
|
||||
})
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package manage
|
||||
|
||||
const (
|
||||
CodeInvalidUser = 10001
|
||||
ErrInvalidUser = "Username invalid"
|
||||
|
||||
InvalidVerifyTableC = 10002
|
||||
InvalidVerifyTableE = "Param verify rule is not a legal regexp"
|
||||
|
||||
InvalidVerifyRuleC = 10003
|
||||
InvalidVerifyRuleE = "The test data is not satisfying the verify rule"
|
||||
|
||||
ApiWithServicePrefixC = 10004
|
||||
ApiWithServicePrefixE = "API name must be prefix with service name"
|
||||
ApiWithServiceSuffixC = 10014
|
||||
ApiWithServiceSuffixE = "API ID must suffix with version"
|
||||
|
||||
ServiceEmptyC = 10005
|
||||
ServiceEmptyE = "Service name cant be empty"
|
||||
|
||||
ApiOnlyAlphaNumAndDotC = 10006
|
||||
ApiOnlyAlphaNumAndDotE = "API name can only be consisted of alphabet and numberic"
|
||||
|
||||
RouteAddrWithHTTPPrefixC = 10007
|
||||
RouteAddrWithHTTPPrefixE = "Backend url must prefix with http:// or https://"
|
||||
|
||||
RouteAddrEmptyC = 10008
|
||||
RouteAddrEmptyE = "Backend url cant be empty"
|
||||
|
||||
RouteProtoInvalidC = 10009
|
||||
RouteProtoInvalidE = "Backend type invalid"
|
||||
|
||||
ReqTimeoutInvalidC = 10010
|
||||
ReqTimeoutInvalidE = "Timeout must be in (0,60]"
|
||||
|
||||
RetryTimesInvalidC = 10011
|
||||
RetryTimesInvalidE = "Retry times must be in (0,5]"
|
||||
|
||||
RetryIntvInvalidC = 10012
|
||||
RetryIntvInvalidE = "Retry interval must be in (0,30]"
|
||||
|
||||
TrafficRatioInvalidC = 10013
|
||||
TrafficRatioInvalidE = "Traffic ratio must be in [0,100]"
|
||||
|
||||
ApiPathTypeInvalidC = 10014
|
||||
ApiPathTypeInvalidE = "API URL type must be 0 or 1"
|
||||
|
||||
ApiNotExistE = "Api not exist"
|
||||
ApiNotExistC = 10015
|
||||
|
||||
ApiOnlyAlphaNumAndUriC = 10016
|
||||
ApiOnlyAlphaNumAndUriE = "API name can only be consisted of alphabet,numberic and /"
|
||||
|
||||
ApiReservePathC = 10017
|
||||
ApiReservePathE = "You cant use the reserverd name"
|
||||
|
||||
APIOfflineE = "API not released"
|
||||
APIOfflineC = 1058
|
||||
|
||||
ApiStillReleasedE = "API still being released"
|
||||
ApiStillReleasedC = 1059
|
||||
|
||||
ApiInactiveNotLongEnoughE = "You cant delete api until 30 seconds after offline"
|
||||
ApiInactiveNotLongEnoughC = 1060
|
||||
|
||||
StrategyNameExistE = "Strategy name already exist"
|
||||
StrategyNameExistc = 1061
|
||||
)
|
@ -0,0 +1,80 @@
|
||||
package manage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (m *Manage) QueryLabels(c echo.Context) error {
|
||||
service := c.FormValue("service")
|
||||
if service == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("select name from labels where service='%s'", service)
|
||||
rows, err := g.DB.Query(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
labels := make([]string, 0)
|
||||
for rows.Next() {
|
||||
var l string
|
||||
rows.Scan(&l)
|
||||
labels = append(labels, l)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
Data: labels,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Manage) CreateLabel(c echo.Context) error {
|
||||
service := c.FormValue("service")
|
||||
name := c.FormValue("name")
|
||||
if service == "" || name == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("insert into labels (service,name) values ('%s','%s')", service, name)
|
||||
_, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), g.DUP_KEY_ERR) {
|
||||
return c.JSON(http.StatusConflict, g.Result{
|
||||
Status: http.StatusConflict,
|
||||
ErrCode: g.AlreadyExistC,
|
||||
Message: g.AlreadyExistE,
|
||||
})
|
||||
}
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
package manage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mafanr/juz/api/manage/audit"
|
||||
"github.com/mafanr/juz/api/manage/strategy"
|
||||
"github.com/mafanr/juz/misc"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/sunface/talent"
|
||||
)
|
||||
|
||||
type Manage struct{}
|
||||
|
||||
func (m *Manage) Start() {
|
||||
registerToEtcd()
|
||||
|
||||
e := echo.New()
|
||||
//api管理
|
||||
e.POST("/manage/api/query", m.QueryAPI, auth)
|
||||
e.POST("/manage/api/count", m.CountAPI, auth)
|
||||
e.POST("/manage/api/define", m.DefineAPI, auth)
|
||||
e.POST("/manage/api/delete", m.DeleteAPI, auth)
|
||||
e.POST("/manage/api/verifyParamRule", m.VerifyParamRule, auth)
|
||||
|
||||
e.POST("/manage/api/release", m.APIRelease, auth)
|
||||
e.POST("/manage/api/batchRelease", m.APIBatchRelease, auth)
|
||||
e.POST("/manage/api/offline", m.APIOffline, auth)
|
||||
|
||||
e.POST("/manage/api/batchStrategy", m.APIBatchStrategy, auth)
|
||||
e.POST("/manage/api/batchDelStrategy", m.APIBatchDelStrategy, auth)
|
||||
|
||||
//策略管理
|
||||
e.POST("/manage/strategy/create", strategy.Create, auth)
|
||||
e.POST("/manage/strategy/update", strategy.Update, auth)
|
||||
e.POST("/manage/strategy/load", strategy.Load, auth)
|
||||
e.POST("/manage/strategy/change", strategy.Change, auth)
|
||||
|
||||
e.POST("/manage/strategy/delete", strategy.Delete, auth)
|
||||
e.POST("/manage/strategy/query", strategy.Query, auth)
|
||||
// e.POST("/manage/strategy/api", strategy.Api, auth)
|
||||
|
||||
// 审计日志
|
||||
e.POST("/manage/auditLog/count", audit.Count, auth)
|
||||
e.POST("/manage/auditLog/load", audit.Load, auth)
|
||||
|
||||
// 标签分组
|
||||
e.POST("/manage/labels/query", m.QueryLabels, auth)
|
||||
e.POST("/manage/labels/create", m.CreateLabel, auth)
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + misc.Conf.Manage.Port))
|
||||
}
|
||||
|
||||
func auth(f echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
if c.FormValue("admin_token") != misc.Conf.Common.AdminToken {
|
||||
return c.JSON(http.StatusUnauthorized, g.Result{
|
||||
Status: http.StatusUnauthorized,
|
||||
ErrCode: g.ForbiddenC,
|
||||
Message: g.ForbiddenE,
|
||||
})
|
||||
}
|
||||
return f(c)
|
||||
}
|
||||
}
|
||||
|
||||
func registerToEtcd() {
|
||||
g.EtcdCli = g.InitEtcd(misc.Conf.Etcd.Addrs)
|
||||
|
||||
// 保存服务状态到etcd
|
||||
ip := talent.LocalIP()
|
||||
fmt.Println("local ip:", ip)
|
||||
|
||||
host := ip + ":" + misc.Conf.Manage.Port
|
||||
go func() {
|
||||
for {
|
||||
err := g.StoreServer(g.EtcdCli, &g.ServerInfo{g.TFEManage, host, 0})
|
||||
if err != nil {
|
||||
g.L.Error("Store to etcd error", zap.Error(err))
|
||||
}
|
||||
|
||||
time.Sleep(time.Second * g.ServiceStoreInterval)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func validUserID(s string) bool {
|
||||
i, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if i == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *Manage) serviceExist(service string) bool {
|
||||
// 验证service是否存在
|
||||
var temp interface{}
|
||||
query := fmt.Sprintf("select id from service where name ='%s'", service)
|
||||
err := g.DB.Get(&temp, query)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *Manage) canView(priv string) bool {
|
||||
if priv == g.PRIV_GUEST {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *Manage) canOperate(priv string) bool {
|
||||
if priv == g.PRIV_ADMIN || priv == g.PRIV_OWNER {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isServiceCreator(userID string, service string) bool {
|
||||
// 验证是否是service创建者
|
||||
var temp interface{}
|
||||
query := fmt.Sprintf("select id from service where name ='%s' and creator='%s'", service, userID)
|
||||
err := g.DB.Get(&temp, query)
|
||||
if err == nil {
|
||||
// 是创建者
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func getServiceByApiName(apiName string) string {
|
||||
return strings.Split(apiName, ".")[0]
|
||||
}
|
@ -0,0 +1,340 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mafanr/juz/api/manage/audit"
|
||||
"github.com/mafanr/juz/misc"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/sunface/talent"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func parse(c echo.Context) (*misc.Strategy, int, string) {
|
||||
str := c.FormValue("strategy")
|
||||
if str == "" {
|
||||
return nil, g.ParamEmptyC, g.ParamEmptyE
|
||||
}
|
||||
|
||||
st := &misc.Strategy{}
|
||||
err := json.Unmarshal([]byte(str), &st)
|
||||
if err != nil {
|
||||
return nil, g.ParamInvalidC, g.ParamInvalidE
|
||||
}
|
||||
|
||||
if st.Name == "" || st.Service == "" {
|
||||
return nil, g.ParamInvalidC, g.ParamInvalidE
|
||||
}
|
||||
return st, 0, ""
|
||||
}
|
||||
|
||||
func Create(c echo.Context) error {
|
||||
st, ecode, emsg := parse(c)
|
||||
if ecode != 0 {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: ecode,
|
||||
Message: emsg,
|
||||
})
|
||||
}
|
||||
|
||||
if !canOperate(c, st.Service) {
|
||||
return c.JSON(http.StatusForbidden, g.Result{
|
||||
Status: http.StatusForbidden,
|
||||
ErrCode: g.ForbiddenC,
|
||||
Message: g.ForbiddenE,
|
||||
})
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("insert into strategy (name,service,type,sub_type,content,create_date) values ('%s','%s','%d','%d','%s','%s')",
|
||||
st.Name, st.Service, st.Type, st.SubType, st.Content, talent.Time2StringSecond(time.Now()))
|
||||
res, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), g.DUP_KEY_ERR) {
|
||||
return c.JSON(http.StatusConflict, g.Result{
|
||||
Status: http.StatusConflict,
|
||||
ErrCode: g.AlreadyExistC,
|
||||
Message: "Strategy name already exist",
|
||||
})
|
||||
}
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
id, _ := res.LastInsertId()
|
||||
audit.Log(c.FormValue("username"), st.Service, audit.TypeStrategy, fmt.Sprintf("%d:%s", id, st.Name), audit.OpCreate, c.FormValue("strategy"), "")
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func Update(c echo.Context) error {
|
||||
st, ecode, emsg := parse(c)
|
||||
if ecode != 0 {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: ecode,
|
||||
Message: emsg,
|
||||
})
|
||||
}
|
||||
|
||||
if !canOperate(c, st.Service) {
|
||||
return c.JSON(http.StatusForbidden, g.Result{
|
||||
Status: http.StatusForbidden,
|
||||
ErrCode: g.ForbiddenC,
|
||||
Message: g.ForbiddenE,
|
||||
})
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("update strategy set name='%s',sub_type='%d',content='%s' where id ='%d'",
|
||||
st.Name, st.SubType, st.Content, st.ID)
|
||||
_, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
audit.Log(c.FormValue("username"), st.Service, audit.TypeStrategy, fmt.Sprintf("%d:%s", st.ID, st.Name), audit.OpEdit, c.FormValue("strategy"), "")
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func Load(c echo.Context) error {
|
||||
service := c.FormValue("service")
|
||||
tp := c.FormValue("type")
|
||||
if service == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
ss := make([]*misc.Strategy, 0)
|
||||
var query string
|
||||
if tp == "0" {
|
||||
query = fmt.Sprintf("select * from strategy where service ='%s' order by modify_date desc", service)
|
||||
} else {
|
||||
query = fmt.Sprintf("select * from strategy where service ='%s' and type='%s' order by modify_date desc", service, tp)
|
||||
}
|
||||
|
||||
err := g.DB.Select(&ss, query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
Data: ss,
|
||||
})
|
||||
}
|
||||
|
||||
func Delete(c echo.Context) error {
|
||||
service := c.FormValue("service")
|
||||
id := c.FormValue("id")
|
||||
name := c.FormValue("name")
|
||||
tp, _ := strconv.Atoi(c.FormValue("type"))
|
||||
if service == "" || id == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
if !canOperate(c, service) {
|
||||
return c.JSON(http.StatusForbidden, g.Result{
|
||||
Status: http.StatusForbidden,
|
||||
ErrCode: g.ForbiddenC,
|
||||
Message: g.ForbiddenE,
|
||||
})
|
||||
}
|
||||
|
||||
var query string
|
||||
switch tp {
|
||||
case misc.STRATEGY_BWLIST:
|
||||
query = fmt.Sprintf("update api_define set bw_strategy='%d' where bw_strategy='%s'", 0, id)
|
||||
case misc.STRATEGY_RETRY:
|
||||
query = fmt.Sprintf("update api_define set retry_strategy='%d' where retry_strategy='%s'", 0, id)
|
||||
case misc.STRATEGY_TRAFFIC:
|
||||
query = fmt.Sprintf("update api_define set traffic_strategy='%d' where traffic_strategy='%s'", 0, id)
|
||||
default:
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamInvalidC,
|
||||
Message: g.ParamInvalidE,
|
||||
})
|
||||
}
|
||||
_, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
switch tp {
|
||||
case misc.STRATEGY_BWLIST:
|
||||
query = fmt.Sprintf("update api_release set bw_strategy='%d' where bw_strategy='%s'", 0, id)
|
||||
case misc.STRATEGY_RETRY:
|
||||
query = fmt.Sprintf("update api_release set retry_strategy='%d' where retry_strategy='%s'", 0, id)
|
||||
case misc.STRATEGY_TRAFFIC:
|
||||
query = fmt.Sprintf("update api_release set traffic_strategy='%d' where traffic_strategy='%s'", 0, id)
|
||||
}
|
||||
_, err = g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
query = fmt.Sprintf("delete from strategy where id='%s'", id)
|
||||
_, err = g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
audit.Log(c.FormValue("username"), service, audit.TypeStrategy, fmt.Sprintf("%s:%s", id, name), audit.OpDelete, "", "")
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func Change(c echo.Context) error {
|
||||
status, _ := strconv.Atoi(c.FormValue("status"))
|
||||
id := c.FormValue("id")
|
||||
if id == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
newS := 0
|
||||
op := 0
|
||||
switch status {
|
||||
case misc.STRATEGY_ON:
|
||||
newS = misc.STRATEGY_OFF
|
||||
op = audit.OpOffline
|
||||
case misc.STRATEGY_OFF:
|
||||
newS = misc.STRATEGY_ON
|
||||
op = audit.OpRelease
|
||||
default:
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamInvalidC,
|
||||
Message: g.ParamInvalidE,
|
||||
})
|
||||
}
|
||||
|
||||
query := fmt.Sprintf("update strategy set status='%d' where id='%s'", newS, id)
|
||||
_, err := g.DB.Exec(query)
|
||||
if err != nil {
|
||||
g.L.Info("access database error", zap.Error(err), zap.String("query", query))
|
||||
return c.JSON(http.StatusInternalServerError, g.Result{
|
||||
Status: http.StatusInternalServerError,
|
||||
ErrCode: g.DatabaseC,
|
||||
Message: g.DatabaseE,
|
||||
})
|
||||
}
|
||||
|
||||
// 查询发布的strategy内容
|
||||
s := misc.Strategy{}
|
||||
g.DB.Get(&s, fmt.Sprintf("select * from strategy where id='%s'", id))
|
||||
d, _ := json.Marshal(s)
|
||||
audit.Log(c.FormValue("username"), s.Service, audit.TypeStrategy, fmt.Sprintf("%s:%s", id, s.Name), op, talent.Bytes2String(d), "")
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
})
|
||||
}
|
||||
|
||||
func Query(c echo.Context) error {
|
||||
id := c.FormValue("id")
|
||||
if id == "" {
|
||||
return c.JSON(http.StatusBadRequest, g.Result{
|
||||
Status: http.StatusBadRequest,
|
||||
ErrCode: g.ParamEmptyC,
|
||||
Message: g.ParamEmptyE,
|
||||
})
|
||||
}
|
||||
|
||||
s := misc.Strategy{}
|
||||
g.DB.Get(&s, fmt.Sprintf("select * from strategy where id='%s'", id))
|
||||
|
||||
return c.JSON(http.StatusOK, g.Result{
|
||||
Status: http.StatusOK,
|
||||
Data: s,
|
||||
})
|
||||
}
|
||||
|
||||
func canOperate(c echo.Context, service string) bool {
|
||||
role := c.FormValue("app_priv")
|
||||
userID := c.FormValue("username")
|
||||
|
||||
if role == g.ROLE_NORMAL {
|
||||
// 验证是否是service创建者
|
||||
var temp interface{}
|
||||
query := fmt.Sprintf("select id from service where name ='%s' and creator='%s'", service, userID)
|
||||
err := g.DB.Get(&temp, query)
|
||||
if err == nil {
|
||||
// 是创建者
|
||||
return true
|
||||
}
|
||||
|
||||
// 验证是否是管理员
|
||||
query = fmt.Sprintf("select privilege from privilege where user_id='%s' and service='%s'", userID, service)
|
||||
rows, err := g.DB.Query(query)
|
||||
if !rows.Next() {
|
||||
// 不存在该用户的权限
|
||||
return false
|
||||
}
|
||||
|
||||
var priv int
|
||||
rows.Scan(&priv)
|
||||
if priv == misc.PRIVILEGE_ADMIN {
|
||||
// 是管理员
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
} else { //是应用级别的管理员
|
||||
return true
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
# 集成测试
|
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"runtime"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(1)
|
||||
flag.Parse()
|
||||
|
||||
h := requestHandler
|
||||
|
||||
if err := fasthttp.ListenAndServe("localhost:10001", h); err != nil {
|
||||
log.Fatalf("Error in ListenAndServe: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func requestHandler(ctx *fasthttp.RequestCtx) {
|
||||
ctx.SetContentType("text/plain; charset=utf8")
|
||||
|
||||
// Set arbitrary headers
|
||||
ctx.Response.Header.Set("X-My-Header", "my-header-value")
|
||||
|
||||
// Set cookies
|
||||
var c fasthttp.Cookie
|
||||
c.SetKey("cookie-name")
|
||||
c.SetValue("cookie-value")
|
||||
ctx.Response.Header.SetCookie(&c)
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/mafanr/juz/misc"
|
||||
|
||||
"github.com/mafanr/juz/api"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// apiCmd represents the api command
|
||||
var apiCmd = &cobra.Command{
|
||||
Use: "api",
|
||||
Short: "api gateway",
|
||||
Long: ``,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
misc.InitConfig("juz.conf")
|
||||
misc.Conf.Common.LogLevel = strings.ToLower(misc.Conf.Common.LogLevel)
|
||||
g.InitLogger()
|
||||
g.L.Info("Application version", zap.String("version", misc.Conf.Common.Version))
|
||||
|
||||
p := &api.ApiServer{}
|
||||
p.Start()
|
||||
|
||||
// 等待服务器停止信号
|
||||
chSig := make(chan os.Signal)
|
||||
signal.Notify(chSig, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
sig := <-chSig
|
||||
g.L.Info("juz received signal", zap.Any("signal", sig))
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(apiCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// apiCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// apiCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "tfe",
|
||||
Short: "Api网关",
|
||||
Long: ``,
|
||||
// Uncomment the following line if your bare application
|
||||
// has an action associated with it:
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
},
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Here you will define your flags and configuration settings.
|
||||
// Cobra supports persistent flags, which, if defined here,
|
||||
// will be global for your application.
|
||||
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.tfe.yaml)")
|
||||
|
||||
// Cobra also supports local flags, which will only run
|
||||
// when this action is called directly.
|
||||
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/mafanr/juz/misc"
|
||||
"github.com/mafanr/juz/traffic"
|
||||
|
||||
"github.com/mafanr/g"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// trafficCmd represents the traffic command
|
||||
var trafficCmd = &cobra.Command{
|
||||
Use: "traffic",
|
||||
Short: "traffic control center",
|
||||
Long: ``,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
misc.InitConfig("juz.conf")
|
||||
misc.Conf.Common.LogLevel = strings.ToLower(misc.Conf.Common.LogLevel)
|
||||
g.InitLogger()
|
||||
g.L.Info("Application version", zap.String("version", misc.Conf.Common.Version))
|
||||
|
||||
p := &traffic.Traffic{}
|
||||
p.Start()
|
||||
|
||||
// 等待服务器停止信号
|
||||
chSig := make(chan os.Signal)
|
||||
signal.Notify(chSig, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
sig := <-chSig
|
||||
g.L.Info("juz received signal", zap.Any("signal", sig))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(trafficCmd)
|
||||
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// trafficCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// trafficCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
common:
|
||||
version: 0.0.1
|
||||
loglevel: warn
|
||||
admintoken: "juz.io"
|
||||
|
||||
api:
|
||||
port: "8081"
|
||||
serverid: 1
|
||||
|
||||
manage:
|
||||
port: "8089"
|
||||
|
||||
mysql:
|
||||
# addr: 10.7.13.48
|
||||
# port: 8066
|
||||
# database: tfe
|
||||
# acc: tfe
|
||||
# pw: EUnt7sbiRzYzpRLz8S21
|
||||
addr: localhost
|
||||
port: 3306
|
||||
database: mafanr_juz
|
||||
acc: root
|
||||
pw:
|
||||
|
||||
etcd:
|
||||
addrs:
|
||||
- "localhost:2379"
|
||||
# - "10.7.24.191:2379"
|
||||
# - "10.7.24.191:2379"
|
||||
|
||||
traffic:
|
||||
host: "127.0.0.1"
|
||||
port: "8088"
|
@ -0,0 +1,21 @@
|
||||
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/mafanr/juz/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
// Copyright © 2018 Sunface <CTO@188.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package misc
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Common struct {
|
||||
Version string
|
||||
LogLevel string
|
||||
AdminToken string
|
||||
}
|
||||
Api struct {
|
||||
Port string
|
||||
ServerID int64
|
||||
}
|
||||
Manage struct {
|
||||
Port string
|
||||
}
|
||||
Mysql struct {
|
||||
Addr string
|
||||
Port string
|
||||
Database string
|
||||
Acc string
|
||||
Pw string
|
||||
}
|
||||
Etcd struct {
|
||||
Addrs []string
|
||||
}
|
||||
|
||||
Traffic struct {
|
||||
Host string
|
||||
Port string
|
||||
}
|
||||
}
|
||||
|
||||
var Conf *Config
|
||||
|
||||
func InitConfig(path string) {
|
||||
conf := &Config{}
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatal("read config error :", err)
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(data, &conf)
|
||||
if err != nil {
|
||||
log.Fatal("yaml decode error :", err)
|
||||
}
|
||||
|
||||
Conf = conf
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package misc
|
||||
|
||||
const TEST_API_NAME = "devops.test.get.v1"
|
||||
|
||||
// 默认请求策略
|
||||
const (
|
||||
REQ_TIMEOUT = 15
|
||||
RETRY_TIMES = 0
|
||||
RETRY_INTERVAL = 5
|
||||
)
|
||||
|
||||
const (
|
||||
PRIVILEGE_SUPER_ADMIN = 0
|
||||
PRIVILEGE_ADMIN = 1
|
||||
PRIVILEGE_NORMAL = 2
|
||||
PRIVILEGE_VIEWER = 3
|
||||
)
|
||||
|
||||
// 通用的
|
||||
const (
|
||||
ON = 1
|
||||
OFF = 0
|
||||
)
|
||||
|
||||
// 以下值绝对不可更改,前端也在使用
|
||||
const (
|
||||
STRATEGY_NO_LIMIT = 0
|
||||
|
||||
BW_OFF = 0
|
||||
BLACK_LIST = 1
|
||||
WHITE_LIST = 2
|
||||
|
||||
IP_TYPE = 1
|
||||
PARAM_TYPE = 2
|
||||
|
||||
TRAFFIC_ON = 1
|
||||
TRAFFIC_OFF = 0
|
||||
|
||||
PARAM_VERIFY_ON = 1
|
||||
PARAM_VERIFY_OFF = 0
|
||||
|
||||
API_RELEASED = 1
|
||||
API_OFFLINE = 0
|
||||
|
||||
STRATEGY_ALL = -1
|
||||
STRATEGY_EMPTY = 0
|
||||
STRATEGY_BWLIST = 1
|
||||
STRATEGY_RETRY = 2
|
||||
STRATEGY_TRAFFIC = 3
|
||||
|
||||
STRATEGY_ON = 1
|
||||
STRATEGY_OFF = 0
|
||||
)
|
||||
|
||||
// redis后缀
|
||||
const (
|
||||
TRAFFIC_CONCURRENT = ".cr"
|
||||
)
|
Loading…
Reference in new issue