You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2020/06/11 07:03:04 UTC
[GitHub] [incubator-apisix-dashboard] moonming commented on a change in pull request #251: add manager & docker-compose
moonming commented on a change in pull request #251:
URL: https://github.com/apache/incubator-apisix-dashboard/pull/251#discussion_r438579694
##########
File path: api/conf/conf.go
##########
@@ -0,0 +1,91 @@
+package conf
+
+import (
+ "fmt"
+ "github.com/tidwall/gjson"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+const ServerPort = 8080
+const PROD = "prod"
+const BETA = "beta"
+const DEV = "dev"
+const LOCAL = "local"
+const TimeLayout = "2006-01-02 15:04:05"
+const TimeTLayout = "2006-01-02T15:04:05"
+const DateLayout = "2006-01-02"
+const confPath = "/root/api7-manager-api/conf.json"
+const RequestId = "requestId"
+
+var (
+ ENV string
+ basePath string
+ ApiKey = "edd1c9f034335f136f87ad84b625c8f1"
+ BaseUrl = "http://127.0.0.1:9080/apisix/admin"
Review comment:
should write in configure file. user can not change it if hard code in source code.
##########
File path: api/conf/conf.go
##########
@@ -0,0 +1,91 @@
+package conf
+
+import (
+ "fmt"
+ "github.com/tidwall/gjson"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+)
+
+const ServerPort = 8080
+const PROD = "prod"
+const BETA = "beta"
+const DEV = "dev"
+const LOCAL = "local"
+const TimeLayout = "2006-01-02 15:04:05"
+const TimeTLayout = "2006-01-02T15:04:05"
+const DateLayout = "2006-01-02"
Review comment:
why we need this lines?
##########
File path: api/conf/conf.json
##########
@@ -0,0 +1,19 @@
+{
+ "conf":{
+ "mysql":{
+ "address": "127.0.0.1:3306",
+ "user": "root",
+ "password": "123456",
+ "maxConns": 50,
+ "maxIdleConns": 25,
+ "maxLifeTime": 10
+ },
+ "syslog":{
+ "host": "localhost"
+ },
+ "apisix":{
+ "base_url": "http://127.0.0.1:9080/apisix/admin",
+ "api_key": "edd1c9f034335f136f87ad84b625c8f1"
+ }
Review comment:
the same as https://github.com/apache/incubator-apisix-dashboard/pull/251/files#diff-f6807e2091080c1b896cdde13f10f7b3R26-R27?
##########
File path: api/service/ssl.go
##########
@@ -0,0 +1,285 @@
+package service
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/json"
+ "encoding/pem"
+ "errors"
+ "fmt"
+
+ "github.com/satori/go.uuid"
+
+ "github.com/api7/api7-manager-api/conf"
+ "github.com/api7/api7-manager-api/errno"
+ "github.com/api7/api7-manager-api/utils"
+)
+
+type Ssl struct {
+ Base
+ ValidityStart uint64 `json:"validity_start"`
+ ValidityEnd uint64 `json:"validity_end"`
+ Snis string `json:"snis"`
+ Status uint64 `json:"status"`
+ PublicKey string `json:"public_key,omitempty"`
+}
+
+type SslDto struct {
+ Base
+ ValidityStart uint64 `json:"validity_start"`
+ ValidityEnd uint64 `json:"validity_end"`
+ Snis []string `json:"snis"`
+ Status uint64 `json:"status"`
+ PublicKey string `json:"public_key,omitempty"`
+}
+
+type SslRequest struct {
+ ID string `json:"id,omitempty"`
+ PublicKey string `json:"cert"`
+ PrivateKey string `json:"key"`
+ Snis []string `json:"snis"`
+}
+
+// ApisixSslResponse is response from apisix admin api
+type ApisixSslResponse struct {
+ Action string `json:"action"`
+ Node *SslNode `json:"node"`
+}
+
+type SslNode struct {
+ Value SslRequest `json:"value"`
+ ModifiedIndex uint64 `json:"modifiedIndex"`
+}
+
+func (req *SslRequest) Parse(body interface{}) {
+ if err := json.Unmarshal(body.([]byte), req); err != nil {
+ req = nil
+ logger.Error(errno.FromMessage(errno.RouteRequestError, err.Error()).Msg)
+ }
+}
+
+func (sslDto *SslDto) Parse(ssl *Ssl) error {
+ sslDto.ID = ssl.ID
+ sslDto.ValidityStart = ssl.ValidityStart
+ sslDto.ValidityEnd = ssl.ValidityEnd
+
+ var snis []string
+ _ = json.Unmarshal([]byte(ssl.Snis), &snis)
+ sslDto.Snis = snis
+
+ sslDto.Status = ssl.Status
+ sslDto.PublicKey = ssl.PublicKey
+ sslDto.CreateTime = ssl.CreateTime
+ sslDto.UpdateTime = ssl.UpdateTime
+
+ return nil
+}
+
+func SslList(page, size int) ([]byte, error) {
+ var count int
+ sslList := []Ssl{}
+ if err := conf.DB().Table("ssls").Offset((page - 1) * size).Limit(size).Find(&sslList).Count(&count).Error; err != nil {
+ return nil, err
+ }
+
+ sslDtoList := []SslDto{}
+
+ for _, ssl := range sslList {
+ sslDto := SslDto{}
+ sslDto.Parse(&ssl)
+
+ sslDtoList = append(sslDtoList, sslDto)
+ }
+
+ data := errno.FromMessage(errno.SystemSuccess).ListResponse(count, sslDtoList)
+
+ return json.Marshal(data)
+}
+
+func SslItem(id string) ([]byte, error) {
+ ssl := &Ssl{}
+ if err := conf.DB().Table("ssls").Where("id = ?", id).First(ssl).Error; err != nil {
+ return nil, err
+ }
+
+ sslDto := &SslDto{}
+ sslDto.Parse(ssl)
+
+ data := errno.FromMessage(errno.SystemSuccess).ItemResponse(sslDto)
+
+ return json.Marshal(data)
+}
+
+func SslCheck(param interface{}) ([]byte, error) {
+ sslReq := &SslRequest{}
+ sslReq.Parse(param)
+
+ ssl, err := ParseCert(sslReq.PublicKey, sslReq.PrivateKey)
+
+ if err != nil {
+ return nil, err
+ }
+
+ ssl.PublicKey = ""
+
+ sslDto := &SslDto{}
+ sslDto.Parse(ssl)
+
+ data := errno.FromMessage(errno.SystemSuccess).ItemResponse(sslDto)
+
+ return json.Marshal(data)
+}
+
+func SslCreate(param interface{}, id string) error {
+ sslReq := &SslRequest{}
+ sslReq.Parse(param)
+
+ ssl, err := ParseCert(sslReq.PublicKey, sslReq.PrivateKey)
+
+ if err != nil {
+ return err
+ }
+
+ //先请求admin api
+ var snis []string
+ _ = json.Unmarshal([]byte(ssl.Snis), &snis)
+ sslReq.Snis = snis
+
+ if _, err := sslReq.PutToApisix(id); err != nil {
+ return err
+ }
+ // 更新 mysql
+ ssl.ID = uuid.FromStringOrNil(id)
+ if err := conf.DB().Create(ssl).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func SslUpdate(param interface{}, id string) error {
+ sslReq := &SslRequest{}
+ sslReq.Parse(param)
+
+ ssl, err := ParseCert(sslReq.PublicKey, sslReq.PrivateKey)
+
+ if err != nil {
+ return err
+ }
+
+ //先请求admin api
+ var snis []string
+ _ = json.Unmarshal([]byte(ssl.Snis), &snis)
+ sslReq.Snis = snis
+
+ if _, err := sslReq.PutToApisix(id); err != nil {
+ return err
+ }
+
+ // 更新 mysql
+ ssl.ID = uuid.FromStringOrNil(id)
+ data := Ssl{PublicKey: ssl.PublicKey, Snis: ssl.Snis, ValidityStart: ssl.ValidityStart, ValidityEnd: ssl.ValidityEnd}
+ if err := conf.DB().Model(&ssl).Updates(data).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func SslDelete(id string) error {
+ // delete from apisix
+ request := &SslRequest{}
+ request.ID = id
+ if _, err := request.DeleteFromApisix(); err != nil {
+ return err
+ }
+ // delete from mysql
+ ssl := &Ssl{}
+ ssl.ID = uuid.FromStringOrNil(id)
+ if err := conf.DB().Delete(ssl).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (req *SslRequest) PutToApisix(rid string) (*ApisixSslResponse, error) {
+ url := fmt.Sprintf("%s/ssl/%s", conf.BaseUrl, rid)
+ if data, err := json.Marshal(req); err != nil {
+ return nil, err
+ } else {
+ if resp, err := utils.Put(url, data); err != nil {
+ logger.Error(url)
+ logger.Error(string(data))
+ logger.Error(err.Error())
+ return nil, err
+ } else {
+ var arresp ApisixSslResponse
+ if err := json.Unmarshal(resp, &arresp); err != nil {
+ logger.Error(err.Error())
+ return nil, err
+ } else {
+ return &arresp, nil
+ }
+ }
+ }
+}
+
+func (req *SslRequest) DeleteFromApisix() (*ApisixSslResponse, error) {
+ id := req.ID
+ url := fmt.Sprintf("%s/ssl/%s", conf.BaseUrl, id)
+
+ if resp, err := utils.Delete(url); err != nil {
+ logger.Error(err.Error())
+ return nil, err
+ } else {
+ var arresp ApisixSslResponse
+ if err := json.Unmarshal(resp, &arresp); err != nil {
+ logger.Error(err.Error())
+ return nil, err
+ } else {
+ return &arresp, nil
+ }
+ }
+}
+
+func ParseCert(crt, key string) (*Ssl, error) {
+ //打印出私钥类型
+ certDERBlock, _ := pem.Decode([]byte(crt))
+ if certDERBlock == nil {
+ return nil, errors.New("证书解析失败")
+ }
+
+ //校验配对
+ _, err := tls.X509KeyPair([]byte(crt), []byte(key))
+ if err != nil {
+ return nil, err
+ }
+
+ x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
+
+ if err != nil {
+ return nil, errors.New("证书解析失败")
Review comment:
English please
##########
File path: api/route/ssl.go
##########
@@ -0,0 +1,137 @@
+package route
+
+import (
+ "net/http"
+ "strconv"
+
+ "github.com/gin-gonic/gin"
+ "github.com/satori/go.uuid"
+
+ "github.com/api7/api7-manager-api/errno"
+ "github.com/api7/api7-manager-api/service"
+)
+
+const contentType = "application/json"
+
+func AppendSsl(r *gin.Engine) *gin.Engine {
+ r.POST("/apisix/admin/check_ssl_cert", sslCheck)
+ r.GET("/apisix/admin/ssls", sslList)
+ r.POST("/apisix/admin/ssls", sslCreate)
+ r.GET("/apisix/admin/ssls/:id", sslItem)
+ r.PUT("/apisix/admin/ssls/:id", sslUpdate)
+ r.DELETE("/apisix/admin/ssls/:id", sslDelete)
+ return r
+}
+
+func sslList(c *gin.Context) {
+ size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
+ page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
+ // todo 参数校验
Review comment:
ditto
##########
File path: compose/apisix_conf/config.yaml
##########
@@ -0,0 +1,137 @@
+apisix:
Review comment:
why we need this file?
##########
File path: api/route/route.go
##########
@@ -0,0 +1,226 @@
+package route
Review comment:
English please
##########
File path: api/errno/error.go
##########
@@ -0,0 +1,84 @@
+package errno
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Message struct {
+ Code string
+ Msg string
+}
+
+var (
+ //AA 01 表示api-manager-api
+ //BB 00 系统b部信息
+ SystemSuccess = Message{"010000", "success"}
+ SystemError = Message{"010001", "system error"}
+ BadRequestError = Message{Code: "010002", Msg: "请求格式错误"}
+ NotFoundError = Message{Code: "010003", Msg: "没有找到资源"}
+
+ //BB 01表示配置信息
+ ConfEnvError = Message{"010101", "找不到环境变量: %s"}
+ ConfFilePathError = Message{"010102", "加载配置文件出错: %s"}
+
+ // BB 02 路由模块
+ RouteRequestError = Message{"010201", "路由请求参数有异常: %s"}
+ ApisixRouteCreateError = Message{"010202", "创建APISIX路由失败: %s"}
+ DBRouteCreateError = Message{"010203", "路由入库失败: %s"}
+ ApisixRouteUpdateError = Message{"010204", "更新APISIX路由失败: %s"}
+ ApisixRouteDeleteError = Message{"010205", "删除APISIX路由失败: %s"}
+ DBRouteUpdateError = Message{"010206", "路由更新失败: %s"}
+ DBRouteDeleteError = Message{"010207", "路由删除失败: %s"}
+
+ // 03 插件模块
+ ApisixPluginListError = Message{"010301", "查询APISIX插件列表失败: %s"}
+ ApisixPluginSchemaError = Message{"010301", "查询APISIX插件schema失败: %s"}
+)
+
Review comment:
English please.
##########
File path: api/main.go
##########
@@ -0,0 +1,49 @@
+package main
+
+import (
+ "fmt"
+ "github.com/api7/api7-manager-api/conf"
+ "github.com/api7/api7-manager-api/filter"
+ "github.com/api7/api7-manager-api/log"
+ "github.com/api7/api7-manager-api/route"
+ "github.com/gin-contrib/pprof"
+ "github.com/gin-gonic/gin"
+ "net/http"
+ "time"
+)
+
+var logger = log.GetLogger()
+
+func setUpRouter() *gin.Engine {
+ if conf.ENV != conf.LOCAL && conf.ENV != conf.BETA {
+ gin.SetMode(gin.DebugMode)
+ } else {
+ gin.SetMode(gin.ReleaseMode)
+ }
+ r := gin.New()
+
+ r.Use(filter.CORS(), filter.RequestId(), filter.RequestLogHandler(), filter.RecoverHandler())
+ route.AppendHealthCheck(r)
+ route.AppendRoute(r)
+ route.AppendSsl(r)
+ route.AppendPlugin(r)
+
+ pprof.Register(r)
+
+ return r
+}
+
+func main() {
+ // init
+ conf.InitializeMysql()
+ // 路由
Review comment:
ditto
##########
File path: api/Dockerfile
##########
@@ -0,0 +1,34 @@
+FROM golang:1.13.8 AS build-env
Review comment:
need add ASF header in every source code files.
##########
File path: api/errno/error.go
##########
@@ -0,0 +1,84 @@
+package errno
+
+import (
+ "encoding/json"
+ "fmt"
+)
+
+type Message struct {
+ Code string
+ Msg string
+}
+
+var (
+ //AA 01 表示api-manager-api
+ //BB 00 系统b部信息
+ SystemSuccess = Message{"010000", "success"}
+ SystemError = Message{"010001", "system error"}
+ BadRequestError = Message{Code: "010002", Msg: "请求格式错误"}
+ NotFoundError = Message{Code: "010003", Msg: "没有找到资源"}
+
+ //BB 01表示配置信息
+ ConfEnvError = Message{"010101", "找不到环境变量: %s"}
+ ConfFilePathError = Message{"010102", "加载配置文件出错: %s"}
+
+ // BB 02 路由模块
+ RouteRequestError = Message{"010201", "路由请求参数有异常: %s"}
+ ApisixRouteCreateError = Message{"010202", "创建APISIX路由失败: %s"}
+ DBRouteCreateError = Message{"010203", "路由入库失败: %s"}
+ ApisixRouteUpdateError = Message{"010204", "更新APISIX路由失败: %s"}
+ ApisixRouteDeleteError = Message{"010205", "删除APISIX路由失败: %s"}
+ DBRouteUpdateError = Message{"010206", "路由更新失败: %s"}
+ DBRouteDeleteError = Message{"010207", "路由删除失败: %s"}
+
+ // 03 插件模块
+ ApisixPluginListError = Message{"010301", "查询APISIX插件列表失败: %s"}
+ ApisixPluginSchemaError = Message{"010301", "查询APISIX插件schema失败: %s"}
+)
+
+type Api7Error struct {
+ TraceId string
+ Code string
+ Msg string
+ Data interface{}
+}
+
+//toString 错误日志
Review comment:
ditto
##########
File path: compose/apisix_conf/config.yaml
##########
@@ -0,0 +1,137 @@
+apisix:
Review comment:
Is ti only for test? If yes, you can download from apisix repo when run test cases.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
users@infra.apache.org