Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
dedc0b4
backend: Sortby slice to string
wilhelmguo Nov 29, 2018
5fb93f0
backend: base api pageSize and pageNo must bigger than zero
wilhelmguo Nov 29, 2018
50ca792
backend: add kubernetes resource dataselector for backend paging
wilhelmguo Nov 29, 2018
5c26fcd
backend: add kubernetes deployment list
wilhelmguo Nov 29, 2018
2d9c02b
backend: abstraction base controller
wilhelmguo Nov 30, 2018
2f75143
Merge branch 'master' of github.com:Qihoo360/wayne into feature/add_k…
wilhelmguo Nov 30, 2018
7277e57
backend: remove deployment debug logs
wilhelmguo Nov 30, 2018
8da44cd
Merge branch 'master' of github.com:Qihoo360/wayne into feature/add_k…
wilhelmguo Nov 30, 2018
e9176a7
backend: update auditlog model Action size 255 to 256
wilhelmguo Dec 5, 2018
f33fe16
backend: update kubernetes deployment cluster & namespace param to path
wilhelmguo Dec 5, 2018
451ebe4
backend: add get kube deployment api
wilhelmguo Dec 5, 2018
d601685
backend: get kubernetes list return DeploymentList Object
wilhelmguo Dec 5, 2018
03cb40e
frontend: move tpl-detail to shared
wilhelmguo Dec 5, 2018
699621f
frontend: add kubernetes deployment management
wilhelmguo Dec 5, 2018
c847355
merge master
wilhelmguo Dec 5, 2018
a6db772
backend: update kubernetes deployment createOrUpdate strategy
wilhelmguo Dec 5, 2018
de1bfa4
frontend: update deployment tpl generate rules
wilhelmguo Dec 5, 2018
42e4b03
frontend: move tpl-detail to shared
wilhelmguo Dec 5, 2018
4fe613b
backend: deal with Resources already exist error.
wilhelmguo Dec 6, 2018
319f604
frontend: add kubernetes deployment migration
wilhelmguo Dec 6, 2018
b84aed2
frontend: update lib version
wilhelmguo Dec 6, 2018
95b5bb9
frontend: migration deployment showcolumns key to lower case
wilhelmguo Dec 6, 2018
453de6b
Merge branch 'master' of github.com:Qihoo360/wayne into feature/add_k…
wilhelmguo Dec 6, 2018
de6e641
Merge branch 'master' into feature/add_kubernetes_deployment_migration
Dec 6, 2018
42dedf4
backend: remove unused newline
wilhelmguo Dec 6, 2018
07c8c93
Merge branch 'feature/add_kubernetes_deployment_migration' of https:/…
wilhelmguo Dec 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/backend/common/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ type QueryParam struct {
PageNo int64 `json:"pageNo"`
PageSize int64 `json:"pageSize"`
Query map[string]interface{} `json:"query"`
Sortby []string `json:"sortby"`
Sortby string `json:"sortby"`
Groupby []string `json:"groupby"`
Relate string `json:"relate"`
}

func (q *QueryParam) Offset() int64 {
return (q.PageNo - 1) * q.PageSize
offset := (q.PageNo - 1) * q.PageSize
if offset < 0 {
offset = 0
}
return offset
}

func (q *QueryParam) Limit() int64 {
Expand Down
252 changes: 7 additions & 245 deletions src/backend/controllers/base/api.go
Original file line number Diff line number Diff line change
@@ -1,52 +1,15 @@
package base

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"

"github.com/Qihoo360/wayne/src/backend/common"
"github.com/Qihoo360/wayne/src/backend/models"
"github.com/Qihoo360/wayne/src/backend/util/hack"
"github.com/Qihoo360/wayne/src/backend/util/logs"
"github.com/Qihoo360/wayne/src/backend/util/slice"
"github.com/astaxie/beego/orm"
"github.com/go-sql-driver/mysql"
"k8s.io/apimachinery/pkg/api/errors"
)

const (
defaultPageNo = 1
defaultPageSize = 10
)

type Result struct {
Data interface{} `json:"data"`
}

type ErrorSubCode int

const (
ErrorSubCodeInsufficientResource = 403001
)

var _ error = &ErrorResult{}

// Error implements the Error interface.
func (e *ErrorResult) Error() string {
return fmt.Sprintf("code:%d,subCode:%d,msg:%s", e.Code, e.SubCode, e.Msg)
}

type ErrorResult struct {
// http code
Code int `json:"code"`
// The custom code
SubCode int `json:"subCode"`
Msg string `json:"msg"`
}

type APIController struct {
LoggedInController

Expand Down Expand Up @@ -117,239 +80,38 @@ func (c *APIController) CheckPermission(perType string, perAction string) {
func (c *APIController) Success(data interface{}) {
c.publishRequestMessage(http.StatusOK, data)

c.Ctx.Output.SetStatus(http.StatusOK)
c.Data["json"] = Result{Data: data}
c.ServeJSON()
c.ResultHandlerController.Success(data)
}

// Abort stops controller handler and show the error data, e.g. Prepare
func (c *APIController) AbortForbidden(msg string) {
c.publishRequestMessage(http.StatusForbidden, msg)

logs.Info("Abort Forbidden error. %s", msg)
c.CustomAbort(http.StatusForbidden, hack.String(c.ErrorResult(http.StatusForbidden, msg)))
c.ResultHandlerController.AbortForbidden(msg)
}

func (c *APIController) AbortInternalServerError(msg string) {
c.publishRequestMessage(http.StatusInternalServerError, msg)

logs.Error("Abort InternalServerError error. %s", msg)
c.CustomAbort(http.StatusInternalServerError, hack.String(c.ErrorResult(http.StatusInternalServerError, msg)))
c.ResultHandlerController.AbortInternalServerError(msg)
}

func (c *APIController) AbortBadRequest(msg string) {
c.publishRequestMessage(http.StatusBadRequest, msg)

logs.Info("Abort BadRequest error. %s", msg)
c.CustomAbort(http.StatusBadRequest, hack.String(c.ErrorResult(http.StatusBadRequest, msg)))
}

// format BadRequest with param name.
func (c *APIController) AbortBadRequestFormat(paramName string) {
msg := fmt.Sprintf("Invalid param %s !", paramName)
c.AbortBadRequest(msg)
c.ResultHandlerController.AbortBadRequest(msg)
}

func (c *APIController) AbortUnauthorized(msg string) {
c.publishRequestMessage(http.StatusUnauthorized, msg)

logs.Info("Abort Unauthorized error. %s", msg)
c.CustomAbort(http.StatusUnauthorized, hack.String(c.ErrorResult(http.StatusUnauthorized, msg)))

}
c.ResultHandlerController.AbortUnauthorized(msg)

func (c *APIController) ErrorResult(code int, msg string) []byte {
errorResult := ErrorResult{
Code: code,
Msg: msg,
}
body, err := json.Marshal(errorResult)
if err != nil {
logs.Error("Json Marshal error. %v", err)
c.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
return body
}

// Handle return http code and body normally, need return
func (c *APIController) HandleError(err error) {
errorResult := &ErrorResult{
Code: http.StatusInternalServerError,
}
switch e := err.(type) {
// deal with kubernetes errors
case errors.APIStatus:
errorResult.Code = int(e.Status().Code)
errorResult.SubCode = errorResult.Code
errorResult.Msg = e.Status().Message
case *mysql.MySQLError:
errorResult.Code = http.StatusBadRequest
errorResult.SubCode = int(e.Number)
errorResult.Msg = e.Message
case *ErrorResult:
errorResult = e
default:
if err == orm.ErrNoRows {
errorResult.Code = http.StatusNotFound
}
errorResult.SubCode = errorResult.Code
errorResult.Msg = http.StatusText(errorResult.Code)
}

if errorResult.Code >= http.StatusInternalServerError {
logs.Error("System error. %v", err)
} else {
logs.Info("Info error. %v", err)
}

c.Ctx.Output.SetStatus(errorResult.Code)

body, err := json.Marshal(errorResult)
if err != nil {
logs.Error("Json Marshal error. %v", err)
c.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

c.Ctx.Output.Body(body)

c.publishRequestMessage(errorResult.Code, err)
}

// TODO: 需要重构成独立的Controller,参考Django的generic views设计
func (c *APIController) BuildQueryParam() *common.QueryParam {
pageNo := c.Input().Get("pageNo")
pageSize := c.Input().Get("pageSize")
if pageNo == "" {
pageNo = strconv.Itoa(defaultPageNo)
}

if pageSize == "" {
pageSize = strconv.Itoa(defaultPageSize)
}

no, err := strconv.ParseInt(pageNo, 10, 64)
if err != nil {
c.AbortBadRequest("Invalid pageNo in query.")
}
size, err := strconv.ParseInt(pageSize, 10, 64)
if err != nil {
c.AbortBadRequest("Invalid pageSize in query.")
}

qmap := map[string]interface{}{}
deletedStr := c.Input().Get("deleted")
if deletedStr != "" {
deleted, err := strconv.ParseBool(deletedStr)
if err != nil {
c.AbortBadRequest("Invalid deleted in query.")
}
qmap["deleted"] = deleted
}

filter := c.Input().Get("filter")
if filter != "" {
filters := strings.Split(filter, ",")
for _, param := range filters {
params := strings.Split(param, "=")
if len(params) != 2 {
continue
}
key, value := params[0], params[1]
// 兼容在filter中使用deleted参数
if key == "deleted" {
deleted, err := strconv.ParseBool(value)
if err != nil {
continue
}
qmap[key] = deleted
continue
}
qmap[params[0]] = params[1]
}
}

relate := ""
if c.Input().Get("relate") != "" {
relate = c.Input().Get("relate")
}

var sortbys []string
sortby := c.Input().Get("sortby")
if sortby != "" {
sortbys = slice.CamelToSnake(strings.Split(sortby, ","))
}

return &common.QueryParam{PageNo: no, PageSize: size, Query: qmap, Sortby: sortbys, Relate: relate}
}

func (c *APIController) GetIDFromURL() int64 {
return c.GetIntParamFromURL(":id")
}

func (c *APIController) GetIntParamFromURL(param string) int64 {
paramStr := c.Ctx.Input.Param(param)
if len(paramStr) == 0 {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in URL", param))
}

paramInt, err := strconv.ParseInt(paramStr, 10, 64)
if err != nil || paramInt < 0 {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in URL", param))
}

return paramInt
}

func (c *APIController) GetIntParamFromQuery(param string) int64 {
paramStr := c.Input().Get(param)
if len(paramStr) == 0 {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in Query", param))
}

paramInt, err := strconv.ParseInt(paramStr, 10, 64)
if err != nil || paramInt < 0 {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in Query", param))
}

return paramInt
}

func (c *APIController) GetBoolParamFromQuery(param string) bool {
paramStr := c.Input().Get(param)
if len(paramStr) == 0 {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in Query", param))
}

paramBool, err := strconv.ParseBool(paramStr)
if err != nil {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in Query", param))
}

return paramBool
}

func (c *APIController) GetBoolParamFromQueryWithDefault(param string, defaultValue bool) bool {
paramStr := c.Input().Get(param)
if len(paramStr) == 0 {
return defaultValue
}

paramBool, err := strconv.ParseBool(paramStr)
if err != nil {
c.AbortBadRequest(fmt.Sprintf("Invalid %s in Query", param))
}

return paramBool
}

func (c *APIController) GetDeleteFromQuery() bool {
return c.GetBoolParamFromQueryWithDefault("deleted", false)
}

func (c *APIController) GetLogicalFromQuery() bool {
return c.GetBoolParamFromQueryWithDefault("logical", true)
}
code := c.ResultHandlerController.HandleError(err)

func (c *APIController) GetIsOnlineFromQuery() bool {
return c.GetBoolParamFromQueryWithDefault("isOnline", false)
c.publishRequestMessage(code, err)
}
12 changes: 12 additions & 0 deletions src/backend/controllers/base/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package base

const (
defaultPageNo = 1
defaultPageSize = 10
)

type ErrorSubCode int

const (
ErrorSubCodeInsufficientResource = 403001
)
3 changes: 1 addition & 2 deletions src/backend/controllers/base/logged.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/Qihoo360/wayne/src/backend/models"
"github.com/Qihoo360/wayne/src/backend/util/hack"
"github.com/Qihoo360/wayne/src/backend/util/logs"
"github.com/astaxie/beego"
"github.com/dgrijalva/jwt-go"
)

Expand All @@ -25,7 +24,7 @@ var (
)

type LoggedInController struct {
beego.Controller
ParamBuilderController

User *models.User
}
Expand Down
Loading