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