diff --git a/sqle/api/app.go b/sqle/api/app.go index 93b666f7d7..3cb530c045 100644 --- a/sqle/api/app.go +++ b/sqle/api/app.go @@ -99,6 +99,7 @@ func StartApi(net *gracenet.Net, exitChan chan struct{}, config config.SqleConfi // instance v1Router.POST("/instances", v1.CreateInstance, AdminUserAllowed()) + v1Router.GET("/instance_additional_metas", v1.GetInstanceAdditionalMetas, AdminUserAllowed()) v1Router.DELETE("/instances/:instance_name/", v1.DeleteInstance, AdminUserAllowed()) v1Router.PATCH("/instances/:instance_name/", v1.UpdateInstance, AdminUserAllowed()) diff --git a/sqle/api/controller/v1/instance.go b/sqle/api/controller/v1/instance.go index fc73f9096b..7520d4595c 100644 --- a/sqle/api/controller/v1/instance.go +++ b/sqle/api/controller/v1/instance.go @@ -10,6 +10,7 @@ import ( "github.com/actiontech/sqle/sqle/errors" "github.com/actiontech/sqle/sqle/log" "github.com/actiontech/sqle/sqle/model" + "github.com/actiontech/sqle/sqle/pkg/params" "github.com/actiontech/sqle/sqle/utils" "github.com/labstack/echo/v4" @@ -45,7 +46,33 @@ type InstanceAdditionalParamResV1 struct { // @Success 200 {object} v1.GetInstanceAdditionalMetasResV1 // @router /v1/instance_additional_metas [get] func GetInstanceAdditionalMetas(c echo.Context) error { - return nil + additionalParams := driver.AllAdditionalParams() + res := &GetInstanceAdditionalMetasResV1{ + BaseRes: controller.NewBaseReq(nil), + Metas: []*InstanceAdditionalMetaV1{}, + } + for name, params := range additionalParams { + meta := &InstanceAdditionalMetaV1{ + DBType: name, + Params: convertParamsToInstanceAdditionalParamRes(params), + } + + res.Metas = append(res.Metas, meta) + } + return c.JSON(http.StatusOK, res) +} + +func convertParamsToInstanceAdditionalParamRes(params params.Params) []*InstanceAdditionalParamResV1 { + res := make([]*InstanceAdditionalParamResV1, len(params)) + for i, param := range params { + res[i] = &InstanceAdditionalParamResV1{ + Name: param.Key, + Description: param.Desc, + Type: string(param.Type), + Value: param.Value, + } + } + return res } type CreateInstanceReqV1 struct { @@ -94,14 +121,24 @@ func CreateInstance(c echo.Context) error { if req.DBType == "" { req.DBType = driver.DriverTypeMySQL } + + additionalParams := driver.AllAdditionalParams()[req.DBType] + for _, additionalParam := range req.AdditionalParams { + err = additionalParams.SetParamValue(additionalParam.Name, additionalParam.Value) + if err != nil { + return controller.JSONBaseErrorReq(c, errors.New(errors.DataInvalid, err)) + } + } + instance := &model.Instance{ - DbType: req.DBType, - Name: req.Name, - User: req.User, - Host: req.Host, - Port: req.Port, - Password: req.Password, - Desc: req.Desc, + DbType: req.DBType, + Name: req.Name, + User: req.User, + Host: req.Host, + Port: req.Port, + Password: req.Password, + Desc: req.Desc, + AdditionalParams: additionalParams, } // set default workflow template if req.WorkflowTemplateName == "" { @@ -200,12 +237,13 @@ type GetInstanceResV1 struct { func convertInstanceToRes(instance *model.Instance) InstanceResV1 { instanceResV1 := InstanceResV1{ - Name: instance.Name, - Host: instance.Host, - Port: instance.Port, - User: instance.User, - Desc: instance.Desc, - DBType: instance.DbType, + Name: instance.Name, + Host: instance.Host, + Port: instance.Port, + User: instance.User, + Desc: instance.Desc, + DBType: instance.DbType, + AdditionalParams: []*InstanceAdditionalParamResV1{}, } if instance.WorkflowTemplate != nil { instanceResV1.WorkflowTemplateName = instance.WorkflowTemplate.Name @@ -224,6 +262,14 @@ func convertInstanceToRes(instance *model.Instance) InstanceResV1 { } instanceResV1.Roles = roleNames } + for _, param := range instance.AdditionalParams { + instanceResV1.AdditionalParams = append(instanceResV1.AdditionalParams, &InstanceAdditionalParamResV1{ + Name: param.Key, + Description: param.Desc, + Type: string(param.Type), + Value: fmt.Sprintf("%v", param.Value), + }) + } return instanceResV1 } @@ -413,6 +459,17 @@ func UpdateInstance(c echo.Context) error { } } + if req.AdditionalParams != nil { + additionalParams := driver.AllAdditionalParams()[instance.DbType] + for _, additionalParam := range req.AdditionalParams { + err = additionalParams.SetParamValue(additionalParam.Name, additionalParam.Value) + if err != nil { + return controller.JSONBaseErrorReq(c, errors.New(errors.DataInvalid, err)) + } + } + updateMap["additional_params"] = additionalParams + } + err = s.UpdateInstanceById(instance.ID, updateMap) if err != nil { return controller.JSONBaseErrorReq(c, err) @@ -608,12 +665,22 @@ func CheckInstanceIsConnectable(c echo.Context) error { if req.DBType == "" { req.DBType = driver.DriverTypeMySQL } + + additionalParams := driver.AllAdditionalParams()[req.DBType] + for _, additionalParam := range req.AdditionalParams { + err := additionalParams.SetParamValue(additionalParam.Name, additionalParam.Value) + if err != nil { + return controller.JSONBaseErrorReq(c, errors.New(errors.DataInvalid, err)) + } + } + instance := &model.Instance{ - DbType: req.DBType, - User: req.User, - Host: req.Host, - Port: req.Port, - Password: req.Password, + DbType: req.DBType, + User: req.User, + Host: req.Host, + Port: req.Port, + Password: req.Password, + AdditionalParams: additionalParams, } return checkInstanceIsConnectable(c, instance) } diff --git a/sqle/api/controller/v1/util.go b/sqle/api/controller/v1/util.go index 0498861565..ff02f1490c 100644 --- a/sqle/api/controller/v1/util.go +++ b/sqle/api/controller/v1/util.go @@ -13,10 +13,11 @@ func newDriverWithoutAudit(l *logrus.Entry, inst *model.Instance, database strin } dsn := &driver.DSN{ - Host: inst.Host, - Port: inst.Port, - User: inst.User, - Password: inst.Password, + Host: inst.Host, + Port: inst.Port, + User: inst.User, + Password: inst.Password, + AdditionalParams: inst.AdditionalParams, DatabaseName: database, } diff --git a/sqle/driver/driver.go b/sqle/driver/driver.go index 5cfa47057c..c2db578686 100644 --- a/sqle/driver/driver.go +++ b/sqle/driver/driver.go @@ -21,6 +21,10 @@ var ( // rules store audit rules for each driver. rules map[string][]*Rule rulesMu sync.RWMutex + + // additionalParams store driver additional params + additionalParams map[string]params.Params + additionalParamsMu sync.RWMutex ) const ( @@ -35,10 +39,11 @@ const ( // DSN provide necessary information to connect to database. type DSN struct { - Host string - Port string - User string - Password string + Host string + Port string + User string + Password string + AdditionalParams params.Params // DatabaseName is the default database to connect. DatabaseName string @@ -141,7 +146,7 @@ type handler func(log *logrus.Entry, c *Config) (Driver, error) // // Register makes a database driver available by the provided driver name. // Driver's initialize handler and audit rules register by Register. -func Register(name string, h handler, rs []*Rule) { +func Register(name string, h handler, rs []*Rule, ap params.Params) { _, exist := drivers[name] if exist { panic("duplicated driver name") @@ -157,6 +162,13 @@ func Register(name string, h handler, rs []*Rule) { } rules[name] = rs rulesMu.Unlock() + + additionalParamsMu.Lock() + if additionalParams == nil { + additionalParams = make(map[string]params.Params) + } + additionalParams[name] = ap + additionalParamsMu.Unlock() } type DriverNotSupportedError struct { @@ -197,6 +209,17 @@ func AllDrivers() []string { return driverNames } +func AllAdditionalParams() map[string] /*driver name*/ params.Params { + additionalParamsMu.RLock() + defer additionalParamsMu.RUnlock() + + newParams := map[string]params.Params{} + for k, v := range additionalParams { + newParams[k] = v.Copy() + } + return newParams +} + var ErrNodesCountExceedOne = errors.New("after parse, nodes count exceed one") // Driver is a interface that must be implemented by a database. @@ -244,6 +267,9 @@ type Registerer interface { // Rules returns all rules that plugin supported. Rules() []*Rule + + // AdditionalParams returns all additional params that plugin supported. + AdditionalParams() params.Params } // Node is a interface which unify SQL ast tree. It produce by Driver.Parse. diff --git a/sqle/driver/mysql/mysql.go b/sqle/driver/mysql/mysql.go index 4bdb667e32..cfdf798aea 100644 --- a/sqle/driver/mysql/mysql.go +++ b/sqle/driver/mysql/mysql.go @@ -7,14 +7,15 @@ import ( "fmt" "strings" - "github.com/actiontech/sqle/sqle/driver/mysql/optimizer/index" - "github.com/actiontech/sqle/sqle/driver" "github.com/actiontech/sqle/sqle/driver/mysql/executor" "github.com/actiontech/sqle/sqle/driver/mysql/onlineddl" + "github.com/actiontech/sqle/sqle/driver/mysql/optimizer/index" rulepkg "github.com/actiontech/sqle/sqle/driver/mysql/rule" "github.com/actiontech/sqle/sqle/driver/mysql/session" "github.com/actiontech/sqle/sqle/driver/mysql/util" + "github.com/actiontech/sqle/sqle/pkg/params" + "github.com/pingcap/parser/ast" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -26,7 +27,7 @@ func init() { allRules[i] = &rulepkg.RuleHandlers[i].Rule } - driver.Register(driver.DriverTypeMySQL, newInspect, allRules) + driver.Register(driver.DriverTypeMySQL, newInspect, allRules, params.Params{}) if err := LoadPtTemplateFromFile("./scripts/pt-online-schema-change.template"); err != nil { panic(err) diff --git a/sqle/driver/plugin.go b/sqle/driver/plugin.go index a4c5836419..c90a22eed3 100644 --- a/sqle/driver/plugin.go +++ b/sqle/driver/plugin.go @@ -142,10 +142,11 @@ func InitPlugins(pluginDir string) error { } if config.DSN != nil { initRequest.Dsn = &proto.DSN{ - Host: config.DSN.Host, - Port: config.DSN.Port, - User: config.DSN.User, - Password: config.DSN.Password, + Host: config.DSN.Host, + Port: config.DSN.Port, + User: config.DSN.User, + Password: config.DSN.Password, + AdditionalParams: proto.ConvertParamToProtoParam(config.DSN.AdditionalParams), // database is to open. Database: config.DSN.DatabaseName, @@ -160,7 +161,7 @@ func InitPlugins(pluginDir string) error { } - Register(pluginMeta.Name, handler, driverRules) + Register(pluginMeta.Name, handler, driverRules, proto.ConvertProtoParamToParam(pluginMeta.GetAdditionalParams())) log.Logger().WithFields(logrus.Fields{ "plugin_name": pluginMeta.Name, @@ -330,11 +331,12 @@ func (d *driverGRPCServer) Init(ctx context.Context, req *proto.InitRequest) (*p var dsn *DSN if req.GetDsn() != nil { dsn = &DSN{ - Host: req.GetDsn().GetHost(), - Port: req.GetDsn().GetPort(), - User: req.GetDsn().GetUser(), - Password: req.GetDsn().GetPassword(), - DatabaseName: req.GetDsn().GetDatabase(), + Host: req.GetDsn().GetHost(), + Port: req.GetDsn().GetPort(), + User: req.GetDsn().GetUser(), + Password: req.GetDsn().GetPassword(), + DatabaseName: req.GetDsn().GetDatabase(), + AdditionalParams: proto.ConvertProtoParamToParam(req.GetDsn().GetAdditionalParams()), } } @@ -455,8 +457,9 @@ func (d *driverGRPCServer) Metas(ctx context.Context, req *proto.Empty) (*proto. } return &proto.MetasResponse{ - Name: d.r.Name(), - Rules: protoRules, + Name: d.r.Name(), + Rules: protoRules, + AdditionalParams: proto.ConvertParamToProtoParam(d.r.AdditionalParams()), }, nil } diff --git a/sqle/driver/proto/driver.pb.go b/sqle/driver/proto/driver.pb.go index db17b5f033..f20172cc9b 100644 --- a/sqle/driver/proto/driver.pb.go +++ b/sqle/driver/proto/driver.pb.go @@ -51,11 +51,12 @@ var _ = math.Inf const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package type DSN struct { - Host string `protobuf:"bytes,1,opt,name=host" json:"host,omitempty"` - Port string `protobuf:"bytes,2,opt,name=port" json:"port,omitempty"` - User string `protobuf:"bytes,3,opt,name=user" json:"user,omitempty"` - Password string `protobuf:"bytes,4,opt,name=password" json:"password,omitempty"` - Database string `protobuf:"bytes,5,opt,name=database" json:"database,omitempty"` + Host string `protobuf:"bytes,1,opt,name=host" json:"host,omitempty"` + Port string `protobuf:"bytes,2,opt,name=port" json:"port,omitempty"` + User string `protobuf:"bytes,3,opt,name=user" json:"user,omitempty"` + Password string `protobuf:"bytes,4,opt,name=password" json:"password,omitempty"` + Database string `protobuf:"bytes,5,opt,name=database" json:"database,omitempty"` + AdditionalParams []*Param `protobuf:"bytes,6,rep,name=additionalParams" json:"additionalParams,omitempty"` } func (m *DSN) Reset() { *m = DSN{} } @@ -98,6 +99,13 @@ func (m *DSN) GetDatabase() string { return "" } +func (m *DSN) GetAdditionalParams() []*Param { + if m != nil { + return m.AdditionalParams + } + return nil +} + type Rule struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Desc string `protobuf:"bytes,2,opt,name=desc" json:"desc,omitempty"` @@ -491,8 +499,9 @@ func (m *GenRollbackSQLResponse) GetReason() string { } type MetasResponse struct { - Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Rules []*Rule `protobuf:"bytes,2,rep,name=rules" json:"rules,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Rules []*Rule `protobuf:"bytes,2,rep,name=rules" json:"rules,omitempty"` + AdditionalParams []*Param `protobuf:"bytes,3,rep,name=additionalParams" json:"additionalParams,omitempty"` } func (m *MetasResponse) Reset() { *m = MetasResponse{} } @@ -514,6 +523,13 @@ func (m *MetasResponse) GetRules() []*Rule { return nil } +func (m *MetasResponse) GetAdditionalParams() []*Param { + if m != nil { + return m.AdditionalParams + } + return nil +} + func init() { proto1.RegisterType((*DSN)(nil), "proto.DSN") proto1.RegisterType((*Rule)(nil), "proto.Rule") @@ -918,55 +934,57 @@ var _Driver_serviceDesc = grpc.ServiceDesc{ func init() { proto1.RegisterFile("driver.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 797 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xdd, 0x4e, 0xf3, 0x46, - 0x10, 0x55, 0x62, 0x3b, 0x7c, 0x19, 0x87, 0x0a, 0x16, 0x8a, 0xac, 0x88, 0x4a, 0x61, 0x69, 0xa5, - 0xa0, 0x52, 0x50, 0xc3, 0x25, 0xe2, 0x02, 0x1a, 0x5a, 0x21, 0x95, 0x28, 0x35, 0x48, 0x95, 0x7a, - 0x67, 0xe2, 0x21, 0x8d, 0x70, 0x6c, 0x67, 0x77, 0x0d, 0xc9, 0xdb, 0xf4, 0x19, 0xfa, 0x64, 0x7d, - 0x84, 0x6a, 0xff, 0x1c, 0x9b, 0xc0, 0x77, 0xe5, 0x99, 0x33, 0xb3, 0x33, 0x67, 0xd7, 0x67, 0x06, - 0x3a, 0x31, 0x9b, 0xbd, 0x22, 0x3b, 0xcb, 0x59, 0x26, 0x32, 0xe2, 0xa9, 0x0f, 0x5d, 0x81, 0x33, - 0x7c, 0x18, 0x11, 0x02, 0xee, 0xdf, 0x19, 0x17, 0x41, 0xa3, 0xd7, 0xe8, 0xb7, 0x43, 0x65, 0x4b, - 0x2c, 0xcf, 0x98, 0x08, 0x9a, 0x1a, 0x93, 0xb6, 0xc4, 0x0a, 0x8e, 0x2c, 0x70, 0x34, 0x26, 0x6d, - 0xd2, 0x85, 0x2f, 0x79, 0xc4, 0xf9, 0x5b, 0xc6, 0xe2, 0xc0, 0x55, 0x78, 0xe9, 0xcb, 0x58, 0x1c, - 0x89, 0xe8, 0x29, 0xe2, 0x18, 0x78, 0x3a, 0x66, 0x7d, 0xfa, 0x4f, 0x03, 0xdc, 0xb0, 0x48, 0x50, - 0x16, 0x4d, 0xa3, 0x39, 0xda, 0xe6, 0xd2, 0x96, 0x58, 0x8c, 0x7c, 0x62, 0x9b, 0x4b, 0x9b, 0x04, - 0xe0, 0xbd, 0x46, 0x49, 0x81, 0xba, 0xfb, 0x4d, 0x33, 0x68, 0x84, 0x1a, 0x20, 0xfb, 0xe0, 0x25, - 0xf8, 0x8a, 0x89, 0xe9, 0xaf, 0x1d, 0xd9, 0x7c, 0x12, 0x09, 0x9c, 0x66, 0x6c, 0x65, 0x9b, 0x5b, - 0x9f, 0x7c, 0x0f, 0xad, 0x3c, 0x62, 0xd1, 0x9c, 0x07, 0xad, 0x9e, 0xd3, 0xf7, 0x07, 0x1d, 0xfd, - 0x2c, 0x67, 0x63, 0x09, 0x86, 0x26, 0x46, 0xff, 0x04, 0x4f, 0x01, 0x64, 0x07, 0x9c, 0x17, 0x5c, - 0x19, 0x86, 0xd2, 0x94, 0x2d, 0x35, 0x19, 0xcd, 0xd0, 0x10, 0xb1, 0xb4, 0x9d, 0x0a, 0x6d, 0x02, - 0xae, 0x58, 0xe5, 0x68, 0xb8, 0x29, 0x9b, 0x8e, 0xc0, 0xbf, 0x4b, 0x67, 0x22, 0xc4, 0x45, 0x81, - 0x5c, 0x90, 0x43, 0x70, 0x62, 0x9e, 0xaa, 0xf2, 0xfe, 0x00, 0x0c, 0x95, 0xe1, 0xc3, 0x28, 0x94, - 0x30, 0x39, 0x02, 0x8f, 0x15, 0x09, 0xf2, 0xc0, 0x51, 0x54, 0x7d, 0x13, 0x97, 0x6f, 0x17, 0xea, - 0x08, 0xdd, 0x02, 0xef, 0x76, 0x9e, 0x8b, 0x15, 0x3d, 0x06, 0xff, 0x76, 0x89, 0x13, 0x5b, 0x78, - 0x1f, 0xbc, 0x45, 0x81, 0xcc, 0x32, 0xd7, 0x0e, 0xfd, 0xb7, 0x01, 0x1d, 0x9d, 0xc5, 0xf3, 0x2c, - 0xe5, 0x48, 0x28, 0x74, 0x92, 0x88, 0x8b, 0xbb, 0x94, 0x23, 0x13, 0x77, 0xb1, 0xca, 0x76, 0xc2, - 0x1a, 0x46, 0x4e, 0x61, 0xb7, 0xea, 0xdf, 0x32, 0x96, 0x31, 0x73, 0xf9, 0xcd, 0x80, 0xac, 0xc8, - 0xb2, 0x37, 0x7e, 0xfd, 0xfc, 0x8c, 0x13, 0x81, 0xb1, 0x7a, 0x10, 0x27, 0xac, 0x61, 0xb2, 0x62, - 0xd5, 0xd7, 0x15, 0xf5, 0x2b, 0x6d, 0x06, 0xe8, 0x0f, 0xd0, 0x7e, 0x5c, 0xda, 0x7b, 0x05, 0xb0, - 0x25, 0xaf, 0x32, 0x43, 0x1e, 0x34, 0x7a, 0x4e, 0xbf, 0x1d, 0x5a, 0x97, 0x5e, 0x02, 0xc8, 0x34, - 0x73, 0xb1, 0x9f, 0x60, 0x8b, 0x21, 0x4f, 0x0a, 0xa1, 0xf3, 0xfc, 0xc1, 0x9e, 0x79, 0xbc, 0xea, - 0xf5, 0x43, 0x9b, 0x43, 0x7f, 0x86, 0xdd, 0xa1, 0x91, 0x27, 0x2f, 0x6b, 0x1c, 0x42, 0xdb, 0x6a, - 0xd6, 0x76, 0x5b, 0x03, 0xb4, 0x0f, 0x9d, 0x71, 0xc4, 0x38, 0x56, 0x98, 0xf1, 0x45, 0xf2, 0x88, - 0x4b, 0x3b, 0x4c, 0xd6, 0xa5, 0x63, 0x70, 0x47, 0x59, 0xac, 0x34, 0x22, 0xd6, 0x61, 0x65, 0x97, - 0x1a, 0x69, 0xae, 0x35, 0x42, 0x7a, 0xe0, 0x3f, 0xcf, 0xd2, 0x29, 0xb2, 0x9c, 0xcd, 0x52, 0x61, - 0x24, 0x55, 0x85, 0xe8, 0x00, 0xb6, 0x4d, 0x6f, 0x43, 0xf5, 0x08, 0xbc, 0x34, 0x8b, 0xd1, 0x5e, - 0xd6, 0x2a, 0x45, 0xb6, 0x0d, 0x75, 0x84, 0xf6, 0xa0, 0x73, 0x5d, 0xc4, 0x6b, 0xe9, 0xed, 0x80, - 0xc3, 0x17, 0x89, 0x55, 0x36, 0x5f, 0x24, 0xf4, 0x0a, 0x7c, 0x93, 0xc1, 0x8b, 0x44, 0x5d, 0x68, - 0x8e, 0x9c, 0x47, 0x53, 0x3b, 0xa0, 0xd6, 0x5d, 0x4f, 0x5d, 0xb3, 0x32, 0x75, 0xf4, 0x0a, 0xb6, - 0xed, 0x71, 0x4d, 0xea, 0x54, 0xfd, 0x83, 0x22, 0x29, 0xff, 0x01, 0x31, 0xb4, 0x2a, 0x5d, 0x42, - 0x9b, 0x42, 0x4f, 0xe0, 0xdb, 0xdf, 0x30, 0x0d, 0xb3, 0x24, 0x79, 0x8a, 0x26, 0x2f, 0x0f, 0x7f, - 0xfc, 0xfe, 0x39, 0xd1, 0x1b, 0x38, 0x78, 0x9f, 0x6a, 0x5a, 0x6e, 0xe4, 0x92, 0x03, 0x68, 0x31, - 0x8c, 0x78, 0x96, 0x1a, 0xb2, 0xc6, 0xa3, 0xbf, 0xc2, 0xf6, 0x3d, 0x8a, 0x68, 0xfd, 0xb7, 0x3f, - 0x5a, 0x46, 0xe5, 0x00, 0x36, 0x3f, 0x1b, 0xc0, 0xc1, 0x7f, 0x0e, 0xb4, 0x86, 0x6a, 0xbf, 0x92, - 0x1f, 0xc1, 0x53, 0x25, 0x89, 0xdd, 0x29, 0x6a, 0x32, 0xbb, 0xfb, 0xc6, 0xab, 0xb7, 0xeb, 0x83, - 0x2b, 0x17, 0x01, 0xb1, 0x6f, 0x52, 0xd9, 0x0a, 0xdd, 0xda, 0x79, 0x72, 0x0c, 0xde, 0x2f, 0x49, - 0xc6, 0xf1, 0x5d, 0xd9, 0x7a, 0x12, 0x05, 0x77, 0x3c, 0x4b, 0xa7, 0x5f, 0xcd, 0x39, 0x07, 0x57, - 0xaa, 0xbf, 0x6c, 0x59, 0xd9, 0x17, 0xdd, 0x8f, 0xc6, 0x83, 0x9c, 0x40, 0xf3, 0x71, 0x49, 0x76, - 0x4c, 0xa8, 0x1c, 0xc2, 0xee, 0x6e, 0x05, 0x31, 0xa9, 0x17, 0xd0, 0x2e, 0x07, 0xe8, 0x1d, 0x89, - 0xc0, 0xae, 0xb5, 0x8d, 0x01, 0x1b, 0xa8, 0x2d, 0xcb, 0x91, 0xec, 0xad, 0x97, 0x70, 0x39, 0x50, - 0xe5, 0xbb, 0xd5, 0x95, 0x3e, 0x00, 0x4f, 0xc9, 0xa7, 0x3c, 0x53, 0x15, 0x75, 0x79, 0xa6, 0x2e, - 0xc4, 0x7b, 0xf8, 0xa6, 0xae, 0x17, 0x72, 0x68, 0xf2, 0x3e, 0x54, 0x5c, 0xf7, 0xbb, 0x4f, 0xa2, - 0xba, 0xdc, 0x0d, 0xfc, 0xf5, 0xe5, 0xec, 0xfc, 0x52, 0xa5, 0x3c, 0xb5, 0xd4, 0xe7, 0xe2, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x58, 0x6b, 0xde, 0xcc, 0x64, 0x07, 0x00, 0x00, + // 822 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xdb, 0x6a, 0xe4, 0x46, + 0x10, 0x45, 0x23, 0x69, 0xbc, 0x53, 0x1a, 0x07, 0xbb, 0xd7, 0x59, 0xc4, 0xe0, 0xc0, 0x6c, 0x6f, + 0x02, 0xb3, 0x64, 0xe3, 0x25, 0xb3, 0x2f, 0x81, 0x65, 0x1f, 0xd6, 0xb1, 0x09, 0x86, 0xac, 0x71, + 0x64, 0x43, 0x20, 0x6f, 0xed, 0x51, 0xd9, 0x11, 0x2b, 0x4b, 0x9a, 0xee, 0x96, 0x2f, 0x6f, 0xf9, + 0x94, 0x7c, 0x43, 0xf2, 0x63, 0xf9, 0x84, 0xd0, 0x37, 0x5d, 0xe6, 0x12, 0xf2, 0xa4, 0xaa, 0x53, + 0xd5, 0xd5, 0xa7, 0x4b, 0x75, 0x0a, 0xc6, 0x29, 0xcf, 0xee, 0x91, 0x1f, 0x55, 0xbc, 0x94, 0x25, + 0x09, 0xf5, 0x87, 0xfe, 0xed, 0x81, 0x7f, 0x72, 0x79, 0x4e, 0x08, 0x04, 0xbf, 0x97, 0x42, 0xc6, + 0xde, 0xd4, 0x9b, 0x8d, 0x12, 0x6d, 0x2b, 0xac, 0x2a, 0xb9, 0x8c, 0x07, 0x06, 0x53, 0xb6, 0xc2, + 0x6a, 0x81, 0x3c, 0xf6, 0x0d, 0xa6, 0x6c, 0x32, 0x81, 0x67, 0x15, 0x13, 0xe2, 0xa1, 0xe4, 0x69, + 0x1c, 0x68, 0xbc, 0xf1, 0x55, 0x2c, 0x65, 0x92, 0x5d, 0x33, 0x81, 0x71, 0x68, 0x62, 0xce, 0x27, + 0x3f, 0xc0, 0x1e, 0x4b, 0xd3, 0x4c, 0x66, 0x65, 0xc1, 0xf2, 0x0b, 0xc6, 0xd9, 0x9d, 0x88, 0x87, + 0x53, 0x7f, 0x16, 0xcd, 0xc7, 0x86, 0xe4, 0x91, 0x06, 0x93, 0xb5, 0x2c, 0xfa, 0xa7, 0x07, 0x41, + 0x52, 0xe7, 0xa8, 0xe8, 0x14, 0xec, 0x0e, 0x1d, 0x6d, 0x65, 0x2b, 0x2c, 0x45, 0xb1, 0x70, 0xb4, + 0x95, 0x4d, 0x62, 0x08, 0xef, 0x59, 0x5e, 0xa3, 0xe1, 0x7d, 0x3c, 0x88, 0xbd, 0xc4, 0x00, 0xe4, + 0x00, 0xc2, 0x1c, 0xef, 0x31, 0xb7, 0xcc, 0x8d, 0xa3, 0x68, 0x2f, 0x98, 0xc4, 0xdb, 0x92, 0x3f, + 0x39, 0xda, 0xce, 0x27, 0x5f, 0xc3, 0xb0, 0xda, 0x4e, 0xd6, 0xc6, 0xe8, 0xaf, 0x10, 0x6a, 0x80, + 0xec, 0x81, 0xff, 0x19, 0x9f, 0x2c, 0x43, 0x65, 0xaa, 0x2b, 0x0d, 0x19, 0xc3, 0xd0, 0x12, 0x71, + 0xb4, 0xfd, 0x0e, 0x6d, 0x02, 0x81, 0x7c, 0xaa, 0xd0, 0x72, 0xd3, 0x36, 0x3d, 0x87, 0xe8, 0xac, + 0xc8, 0x64, 0x82, 0xcb, 0x1a, 0x85, 0x24, 0x87, 0xe0, 0xa7, 0xa2, 0xd0, 0xe5, 0xa3, 0x39, 0x58, + 0x2a, 0x27, 0x97, 0xe7, 0x89, 0x82, 0xc9, 0x4b, 0x08, 0x79, 0x9d, 0xa3, 0x88, 0x7d, 0x4d, 0x35, + 0xb2, 0x71, 0xd5, 0xbb, 0xc4, 0x44, 0xe8, 0x0e, 0x84, 0xa7, 0x77, 0x95, 0x7c, 0xa2, 0xaf, 0x20, + 0x3a, 0x7d, 0xc4, 0x85, 0x2b, 0x7c, 0x00, 0xe1, 0xb2, 0x46, 0xee, 0x98, 0x1b, 0x87, 0xfe, 0xe5, + 0xc1, 0xd8, 0x64, 0x89, 0xaa, 0x2c, 0x04, 0x12, 0x0a, 0xe3, 0x9c, 0x09, 0x79, 0x56, 0x08, 0xe4, + 0xf2, 0x2c, 0xd5, 0xd9, 0x7e, 0xd2, 0xc3, 0xc8, 0x1b, 0xd8, 0xef, 0xfa, 0xa7, 0x9c, 0x97, 0xdc, + 0x3e, 0x7e, 0x3d, 0xa0, 0x2a, 0xf2, 0xf2, 0x41, 0x7c, 0xbc, 0xb9, 0xc1, 0x85, 0xc4, 0x54, 0x37, + 0xc4, 0x4f, 0x7a, 0x98, 0xaa, 0xd8, 0xf5, 0x4d, 0x45, 0xd3, 0xa5, 0xf5, 0x00, 0xfd, 0x06, 0x46, + 0x57, 0x8f, 0xee, 0x5d, 0x31, 0xec, 0xa8, 0xa7, 0x64, 0x28, 0x62, 0x6f, 0xea, 0xcf, 0x46, 0x89, + 0x73, 0xe9, 0x7b, 0x00, 0x95, 0x66, 0x1f, 0xf6, 0x1d, 0xec, 0x70, 0x14, 0x75, 0x2e, 0x4d, 0x5e, + 0x34, 0x7f, 0x6e, 0x9b, 0xd7, 0x7d, 0x7e, 0xe2, 0x72, 0xe8, 0xf7, 0xb0, 0x7f, 0x62, 0x07, 0x5b, + 0x34, 0x35, 0x0e, 0x61, 0xe4, 0xa6, 0xdd, 0xdd, 0xd6, 0x02, 0x74, 0x06, 0xe3, 0x0b, 0xc6, 0x05, + 0x76, 0x98, 0x89, 0x65, 0x7e, 0x85, 0x8f, 0x4e, 0x86, 0xce, 0xa5, 0x17, 0x10, 0x9c, 0x97, 0xa9, + 0x9e, 0x11, 0xd9, 0x86, 0xb5, 0xdd, 0xcc, 0xc8, 0xa0, 0x9d, 0x11, 0x32, 0x85, 0xe8, 0x26, 0x2b, + 0x6e, 0x91, 0x57, 0x3c, 0x2b, 0xa4, 0x1d, 0xa9, 0x2e, 0x44, 0xe7, 0xb0, 0x6b, 0xef, 0xb6, 0x54, + 0x5f, 0x42, 0x58, 0x94, 0x29, 0xba, 0xc7, 0xba, 0x49, 0x51, 0xd7, 0x26, 0x26, 0x42, 0xa7, 0x30, + 0xfe, 0x58, 0xa7, 0xed, 0xe8, 0xed, 0x81, 0x2f, 0x96, 0xb9, 0x9b, 0x6c, 0xb1, 0xcc, 0xe9, 0x07, + 0x88, 0x6c, 0x86, 0x6a, 0x8a, 0x7a, 0xd0, 0x1d, 0x0a, 0xc1, 0x6e, 0x9d, 0x40, 0x9d, 0xdb, 0xaa, + 0x6e, 0xd0, 0x51, 0x1d, 0xfd, 0x00, 0xbb, 0xee, 0xb8, 0x21, 0xf5, 0x66, 0xf5, 0x1f, 0x10, 0x4b, + 0xab, 0x73, 0x4b, 0xfb, 0x0b, 0x5e, 0xc3, 0x97, 0x3f, 0x61, 0x91, 0x94, 0x79, 0x7e, 0xcd, 0x16, + 0x9f, 0x2f, 0x7f, 0xf9, 0x79, 0x3b, 0xd1, 0x63, 0x78, 0xb1, 0x9a, 0x6a, 0xaf, 0x5c, 0xcb, 0x25, + 0x2f, 0x60, 0xc8, 0x91, 0x89, 0xb2, 0xb0, 0x64, 0xad, 0x47, 0xff, 0xf0, 0x60, 0xf7, 0x13, 0x4a, + 0xd6, 0xfe, 0xee, 0x4d, 0xdb, 0xa8, 0x51, 0xe0, 0x60, 0x9b, 0x02, 0x37, 0xee, 0x41, 0xff, 0xff, + 0xec, 0xc1, 0xf9, 0x3f, 0x3e, 0x0c, 0x4f, 0xf4, 0x56, 0x27, 0xdf, 0x42, 0xa8, 0xc9, 0x10, 0x77, + 0x46, 0x8b, 0x7a, 0x72, 0x60, 0xbd, 0x3e, 0xd1, 0x19, 0x04, 0x6a, 0x87, 0x10, 0xd7, 0xce, 0xce, + 0x42, 0x99, 0xf4, 0xce, 0x93, 0x57, 0x10, 0xfe, 0x98, 0x97, 0x02, 0x57, 0xca, 0xf6, 0x93, 0x28, + 0x04, 0x17, 0x59, 0x71, 0xfb, 0x9f, 0x39, 0x6f, 0x21, 0x50, 0xc2, 0x69, 0xae, 0xec, 0xac, 0x9a, + 0xc9, 0x26, 0x65, 0x91, 0xd7, 0x30, 0xb8, 0x7a, 0x24, 0x7b, 0x36, 0xd4, 0xe8, 0x77, 0xb2, 0xdf, + 0x41, 0x6c, 0xea, 0x3b, 0x18, 0x35, 0xda, 0x5b, 0x21, 0x11, 0xbb, 0x8d, 0xb8, 0xa6, 0xcd, 0xb9, + 0x5e, 0xd0, 0x02, 0xc9, 0xf3, 0xb6, 0xc9, 0x8d, 0x16, 0x9b, 0xbe, 0xf5, 0x45, 0x32, 0x87, 0x50, + 0x4f, 0x5e, 0x73, 0xa6, 0xab, 0x87, 0xe6, 0x4c, 0x7f, 0x86, 0x3f, 0xc1, 0x17, 0xfd, 0x51, 0x23, + 0x87, 0x36, 0x6f, 0xe3, 0xb0, 0x4e, 0xbe, 0xda, 0x12, 0x35, 0xe5, 0x8e, 0xe1, 0xb7, 0x67, 0x47, + 0x6f, 0xdf, 0xeb, 0x94, 0xeb, 0xa1, 0xfe, 0xbc, 0xfb, 0x37, 0x00, 0x00, 0xff, 0xff, 0x12, 0x6c, + 0xb3, 0x02, 0xda, 0x07, 0x00, 0x00, } diff --git a/sqle/driver/proto/driver.proto b/sqle/driver/proto/driver.proto index a764f72d29..e144bc3c86 100644 --- a/sqle/driver/proto/driver.proto +++ b/sqle/driver/proto/driver.proto @@ -27,12 +27,13 @@ message DSN { string user = 3; string password = 4; string database = 5; + repeated Param additionalParams = 6; } message Rule { string name = 1; string desc = 2; - string value = 3 [deprecated=true]; + string value = 3 [deprecated = true]; string level = 4; string category = 5; repeated Param params = 6; @@ -114,6 +115,7 @@ message GenRollbackSQLResponse { message MetasResponse { string name = 1; repeated Rule rules = 2; + repeated Param additionalParams = 3; } diff --git a/sqle/driver/proto/util.go b/sqle/driver/proto/util.go new file mode 100644 index 0000000000..0d91eff7b2 --- /dev/null +++ b/sqle/driver/proto/util.go @@ -0,0 +1,37 @@ +package proto + +import ( + "github.com/actiontech/sqle/sqle/pkg/params" +) + +func ConvertParamToProtoParam(p params.Params) []*Param { + pp := make([]*Param, len(p)) + for i, v := range p { + if v == nil { + continue + } + pp[i] = &Param{ + Key: v.Key, + Value: v.Value, + Desc: v.Desc, + Type: string(v.Type), + } + } + return pp +} + +func ConvertProtoParamToParam(p []*Param) params.Params { + pp := make(params.Params, len(p)) + for i, v := range p { + if v == nil { + continue + } + pp[i] = ¶ms.Param{ + Key: v.Key, + Value: v.Value, + Desc: v.Desc, + Type: params.ParamType(v.Type), + } + } + return pp +} diff --git a/sqle/model/instance.go b/sqle/model/instance.go index d4fed35d1a..1b2e002cb0 100644 --- a/sqle/model/instance.go +++ b/sqle/model/instance.go @@ -2,6 +2,7 @@ package model import ( "fmt" + "github.com/actiontech/sqle/sqle/pkg/params" "strings" "github.com/actiontech/sqle/sqle/errors" @@ -14,15 +15,16 @@ import ( type Instance struct { Model // has created composite index: [id, name] by gorm#AddIndex - Name string `json:"name" gorm:"not null;index" example:""` - DbType string `json:"db_type" gorm:"column:db_type; not null" example:"mysql"` - Host string `json:"host" gorm:"column:db_host; not null" example:"10.10.10.10"` - Port string `json:"port" gorm:"column:db_port; not null" example:"3306"` - User string `json:"user" gorm:"column:db_user; not null" example:"root"` - Password string `json:"-" gorm:"-"` - SecretPassword string `json:"secret_password" gorm:"column:db_password; not null"` - Desc string `json:"desc" example:"this is a instance"` - WorkflowTemplateId uint `json:"workflow_template_id"` + Name string `json:"name" gorm:"not null;index" example:""` + DbType string `json:"db_type" gorm:"column:db_type; not null" example:"mysql"` + Host string `json:"host" gorm:"column:db_host; not null" example:"10.10.10.10"` + Port string `json:"port" gorm:"column:db_port; not null" example:"3306"` + User string `json:"user" gorm:"column:db_user; not null" example:"root"` + Password string `json:"-" gorm:"-"` + SecretPassword string `json:"secret_password" gorm:"column:db_password; not null"` + Desc string `json:"desc" example:"this is a instance"` + WorkflowTemplateId uint `json:"workflow_template_id"` + AdditionalParams params.Params `json:"additional_params" gorm:"type:text"` // relation table Roles []*Role `json:"-" gorm:"many2many:instance_role;"` diff --git a/sqle/pkg/driver/adaptor.go b/sqle/pkg/driver/adaptor.go index 0f881b6ad0..6e7edfbf40 100644 --- a/sqle/pkg/driver/adaptor.go +++ b/sqle/pkg/driver/adaptor.go @@ -7,7 +7,9 @@ import ( "os" "github.com/actiontech/sqle/sqle/driver" + "github.com/actiontech/sqle/sqle/pkg/params" "github.com/actiontech/sqle/sqle/utils" + "github.com/hashicorp/go-hclog" "github.com/percona/go-mysql/query" "github.com/pkg/errors" @@ -27,6 +29,8 @@ type Adaptor struct { ruleToRawHandler map[string] /*rule name*/ rawSQLRuleHandler ruleToASTHandler map[string] /*rule name*/ astSQLRuleHandler + additionalParams params.Params + ao *adaptorOptions } @@ -50,6 +54,7 @@ func NewAdaptor(dt Dialector) *Adaptor { }), ruleToRawHandler: make(map[string]rawSQLRuleHandler), ruleToASTHandler: make(map[string]astSQLRuleHandler), + additionalParams: params.Params{}, } } @@ -58,6 +63,10 @@ func (a *Adaptor) AddRule(r *driver.Rule, h rawSQLRuleHandler) { a.ruleToRawHandler[r.Name] = h } +func (a *Adaptor) AddAdditionalParams(p *params.Param) { + a.additionalParams = append(a.additionalParams, p) +} + func (a *Adaptor) AddRuleWithSQLParser(r *driver.Rule, h astSQLRuleHandler) { a.rules = append(a.rules, r) a.ruleToASTHandler[r.Name] = h @@ -83,8 +92,9 @@ func (a *Adaptor) Serve(opts ...AdaptorOption) { } r := ®istererImpl{ - dt: a.dt, - rules: a.rules, + dt: a.dt, + rules: a.rules, + additionalParams: a.additionalParams, } newDriver := func(cfg *driver.Config) driver.Driver { @@ -151,8 +161,9 @@ var _ driver.Driver = (*driverImpl)(nil) var _ driver.Registerer = (*registererImpl)(nil) type registererImpl struct { - dt Dialector - rules []*driver.Rule + dt Dialector + rules []*driver.Rule + additionalParams params.Params } func (r *registererImpl) Name() string { @@ -163,6 +174,10 @@ func (r *registererImpl) Rules() []*driver.Rule { return r.rules } +func (r *registererImpl) AdditionalParams() params.Params { + return r.additionalParams +} + type driverImpl struct { a *Adaptor db *sql.DB diff --git a/sqle/server/auditplan/task.go b/sqle/server/auditplan/task.go index c30f4d14d8..e638c20516 100644 --- a/sqle/server/auditplan/task.go +++ b/sqle/server/auditplan/task.go @@ -8,15 +8,15 @@ import ( "sync" "time" - "github.com/actiontech/sqle/sqle/log" - "github.com/actiontech/sqle/sqle/utils" - "github.com/actiontech/sqle/sqle/driver" "github.com/actiontech/sqle/sqle/driver/mysql/executor" "github.com/actiontech/sqle/sqle/errors" + "github.com/actiontech/sqle/sqle/log" "github.com/actiontech/sqle/sqle/model" "github.com/actiontech/sqle/sqle/pkg/oracle" "github.com/actiontech/sqle/sqle/server" + "github.com/actiontech/sqle/sqle/utils" + "github.com/sirupsen/logrus" ) @@ -329,11 +329,13 @@ func (at *SchemaMetaTask) collectorDo() { return } db, err := executor.NewExecutor(at.logger, &driver.DSN{ - Host: instance.Host, - Port: instance.Port, - User: instance.User, - Password: instance.Password, - DatabaseName: at.ap.InstanceDatabase}, + Host: instance.Host, + Port: instance.Port, + User: instance.User, + Password: instance.Password, + AdditionalParams: instance.AdditionalParams, + DatabaseName: at.ap.InstanceDatabase, + }, at.ap.InstanceDatabase) if err != nil { at.logger.Errorf("connect to instance fail, error: %v", err) diff --git a/sqle/server/sqled.go b/sqle/server/sqled.go index 1640bd8ce6..5b3319b591 100644 --- a/sqle/server/sqled.go +++ b/sqle/server/sqled.go @@ -468,10 +468,11 @@ func newDriverWithAudit(l *logrus.Entry, inst *model.Instance, database string, modelRules, err = st.GetRulesFromRuleTemplateByName(templateName) } else { dsn = &driver.DSN{ - Host: inst.Host, - Port: inst.Port, - User: inst.User, - Password: inst.Password, + Host: inst.Host, + Port: inst.Port, + User: inst.User, + Password: inst.Password, + AdditionalParams: inst.AdditionalParams, DatabaseName: database, } diff --git a/sqle/server/workflow_schedule.go b/sqle/server/workflow_schedule.go index a4a8edba83..5fe9f47c79 100644 --- a/sqle/server/workflow_schedule.go +++ b/sqle/server/workflow_schedule.go @@ -86,11 +86,12 @@ func ExecuteWorkflow(workflow *model.Workflow, userId uint) error { // if instance is not connectable, exec sql must be failed; // commit action unable to retry, so don't to exec it. dsn := &driver.DSN{ - Host: task.Instance.Host, - Port: task.Instance.Port, - User: task.Instance.User, - Password: task.Instance.Password, - DatabaseName: task.Schema, + Host: task.Instance.Host, + Port: task.Instance.Port, + User: task.Instance.User, + Password: task.Instance.Password, + AdditionalParams: task.Instance.AdditionalParams, + DatabaseName: task.Schema, } cfg, err := driver.NewConfig(dsn, nil)