SSH认证支持sudo

This commit is contained in:
刘祥超
2021-12-06 19:27:11 +08:00
parent 820779e614
commit 8fd29bd81c
14 changed files with 382 additions and 130 deletions

View File

@@ -73,7 +73,7 @@ func (this *NodeGrantDAO) FindNodeGrantName(tx *dbs.Tx, id uint32) (string, erro
}
// CreateGrant 创建认证信息
func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64) (grantId int64, err error) {
func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64, su bool) (grantId int64, err error) {
op := NewNodeGrantOperator()
op.AdminId = adminId
op.Name = name
@@ -83,12 +83,12 @@ func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, me
case "user":
op.Username = username
op.Password = password
op.Su = false // TODO 需要做到前端可以配置
case "privateKey":
op.Username = username
op.PrivateKey = privateKey
op.Passphrase = passphrase
}
op.Su = su
op.Description = description
op.NodeId = nodeId
op.State = NodeGrantStateEnabled
@@ -97,7 +97,7 @@ func (this *NodeGrantDAO) CreateGrant(tx *dbs.Tx, adminId int64, name string, me
}
// UpdateGrant 修改认证信息
func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64) error {
func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, method string, username string, password string, privateKey string, passphrase string, description string, nodeId int64, su bool) error {
if grantId <= 0 {
return errors.New("invalid grantId")
}
@@ -111,12 +111,12 @@ func (this *NodeGrantDAO) UpdateGrant(tx *dbs.Tx, grantId int64, name string, me
case "user":
op.Username = username
op.Password = password
op.Su = false // TODO 需要做到前端可以配置
case "privateKey":
op.Username = username
op.PrivateKey = privateKey
op.Passphrase = passphrase
}
op.Su = su
op.Description = description
op.NodeId = nodeId
err := this.Save(tx, op)

View File

@@ -8,4 +8,5 @@ type Credentials struct {
PrivateKey string
Passphrase string
Method string
Sudo bool
}

View File

@@ -94,7 +94,13 @@ func (this *BaseInstaller) Login(credentials *Credentials) error {
if err != nil {
return err
}
if credentials.Sudo {
client.Sudo(credentials.Password)
}
this.client = client
return nil
}
@@ -146,6 +152,10 @@ func (this *BaseInstaller) InstallHelper(targetDir string, role nodeconfigs.Node
return env, err
}
if len(uname) == 0 {
return nil, errors.New("unable to execute 'uname -a' on this system")
}
osName := ""
archName := ""
if strings.Contains(uname, "Darwin") {

View File

@@ -97,6 +97,12 @@ func (this *NodeInstaller) Install(dir string, params interface{}, installStatus
// 修改配置文件
{
configFile := dir + "/edge-node/configs/api.yaml"
// sudo之后我们需要修改配置目录才能写入文件
if this.client.sudo {
_, _, _ = this.client.Exec("chown " + this.client.User() + " " + filepath.Dir(configFile))
}
var data = []byte(`rpc:
endpoints: [ ${endpoints} ]
nodeId: "${nodeId}"
@@ -108,7 +114,7 @@ secret: "${nodeSecret}"`)
_, err = this.client.WriteFile(configFile, data)
if err != nil {
return errors.New("write 'configs/api.yaml': " + err.Error())
return errors.New("write '" + configFile + "': " + err.Error())
}
}

View File

@@ -97,6 +97,12 @@ func (this *NSNodeInstaller) Install(dir string, params interface{}, installStat
// 修改配置文件
{
configFile := dir + "/edge-dns/configs/api.yaml"
// sudo之后我们需要修改配置目录才能写入文件
if this.client.sudo {
_, _, _ = this.client.Exec("chown " + this.client.User() + " " + filepath.Dir(configFile))
}
var data = []byte(`rpc:
endpoints: [ ${endpoints} ]
nodeId: "${nodeId}"
@@ -108,7 +114,7 @@ secret: "${nodeSecret}"`)
_, err = this.client.WriteFile(configFile, data)
if err != nil {
return errors.New("write 'configs/api.yaml': " + err.Error())
return errors.New("write '" + configFile + "': " + err.Error())
}
}

View File

@@ -133,24 +133,6 @@ func (this *NodeQueue) InstallNode(nodeId int64, installStatus *models.NodeInsta
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-node
installDir = "/" + grant.Username + "/edge-node"
}
}
// API终端
apiNodes, err := models.SharedAPINodeDAO.FindAllEnabledAndOnAPINodes(nil)
if err != nil {
@@ -187,6 +169,7 @@ func (this *NodeQueue) InstallNode(nodeId int64, installStatus *models.NodeInsta
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
installStatus.ErrorCode = "SSH_LOGIN_FAILED"
@@ -196,6 +179,24 @@ func (this *NodeQueue) InstallNode(nodeId int64, installStatus *models.NodeInsta
_ = installer.Close()
}()
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-node
installDir = installer.client.UserHome() + "/edge-node"
}
}
err = installer.Install(installDir, params, installStatus)
return err
}
@@ -250,24 +251,6 @@ func (this *NodeQueue) StartNode(nodeId int64) error {
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-node
installDir = "/" + grant.Username + "/edge-node"
}
}
installer := &NodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
@@ -277,6 +260,7 @@ func (this *NodeQueue) StartNode(nodeId int64) error {
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
return err
@@ -286,16 +270,16 @@ func (this *NodeQueue) StartNode(nodeId int64) error {
}()
// 检查命令是否存在
exeFile := installDir + "/edge-node/bin/edge-node"
_, err = installer.client.Stat(exeFile)
exe, err := this.lookupNodeExe(node, installer.client)
if err != nil {
return errors.New("edge node is not installed correctly, can not find executable file: " + exeFile)
return errors.New("edge node was not installed correctly, can not find executable file")
}
// 我们先尝试Systemd启动
_, _, _ = installer.client.Exec("systemctl start edge-node")
_, stderr, err := installer.client.Exec(exeFile + " start")
// 执行start
_, stderr, err := installer.client.Exec("sudo " + exe + " start")
if err != nil {
return errors.New("start failed: " + err.Error())
}
@@ -356,24 +340,6 @@ func (this *NodeQueue) StopNode(nodeId int64) error {
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-node
installDir = "/" + grant.Username + "/edge-node"
}
}
installer := &NodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
@@ -383,6 +349,7 @@ func (this *NodeQueue) StopNode(nodeId int64) error {
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
return err
@@ -392,16 +359,16 @@ func (this *NodeQueue) StopNode(nodeId int64) error {
}()
// 检查命令是否存在
exeFile := installDir + "/edge-node/bin/edge-node"
_, err = installer.client.Stat(exeFile)
exe, err := this.lookupNodeExe(node, installer.client)
if err != nil {
return errors.New("edge node is not installed correctly, can not find executable file: " + exeFile)
return errors.New("edge node was not installed correctly, can not find executable file")
}
// 我们先尝试Systemd停止
_, _, _ = installer.client.Exec("systemctl stop edge-node")
_, stderr, err := installer.client.Exec(exeFile + " stop")
// 执行stop
_, stderr, err := installer.client.Exec(exe + " stop")
if err != nil {
return errors.New("stop failed: " + err.Error())
}
@@ -411,3 +378,38 @@ func (this *NodeQueue) StopNode(nodeId int64) error {
return nil
}
func (this *NodeQueue) lookupNodeExe(node *models.Node, client *SSHClient) (string, error) {
// 安装目录
var nodeDirs = []string{}
if len(node.InstallDir) > 0 {
nodeDirs = append(nodeDirs, node.InstallDir)
}
clusterId := node.ClusterId
cluster, err := models.SharedNodeClusterDAO.FindEnabledNodeCluster(nil, int64(clusterId))
if err != nil {
return "", err
}
if cluster == nil {
return "", errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
if len(cluster.InstallDir) > 0 {
nodeDirs = append(nodeDirs, cluster.InstallDir)
}
// 默认是 $登录用户/edge-node
nodeDirs = append(nodeDirs, client.UserHome()+"/edge-node")
// edge-boot安装目录
nodeDirs = append(nodeDirs, "/usr/local/goedge")
for _, dir := range nodeDirs {
var path = dir + "/edge-node/bin/edge-node"
_, err := client.sftp.Stat(path)
if err == nil {
return path, nil
}
}
return "", nil
}

View File

@@ -6,7 +6,7 @@ import (
)
func TestQueue_InstallNode(t *testing.T) {
queue := NewQueue()
queue := NewNodeQueue()
err := queue.InstallNodeProcess(16, false)
if err != nil {
t.Fatal(err)

View File

@@ -133,24 +133,6 @@ func (this *NSNodeQueue) InstallNode(nodeId int64, installStatus *models.NodeIns
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-dns
installDir = "/" + grant.Username + "/edge-dns"
}
}
// API终端
apiNodes, err := models.SharedAPINodeDAO.FindAllEnabledAndOnAPINodes(nil)
if err != nil {
@@ -187,6 +169,7 @@ func (this *NSNodeQueue) InstallNode(nodeId int64, installStatus *models.NodeIns
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
installStatus.ErrorCode = "SSH_LOGIN_FAILED"
@@ -196,6 +179,24 @@ func (this *NSNodeQueue) InstallNode(nodeId int64, installStatus *models.NodeIns
_ = installer.Close()
}()
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
clusterId := node.ClusterId
cluster, err := models.SharedNSClusterDAO.FindEnabledNSCluster(nil, int64(clusterId))
if err != nil {
return err
}
if cluster == nil {
return errors.New("can not find cluster, ID'" + fmt.Sprintf("%d", clusterId) + "'")
}
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-dns
installDir = installer.client.UserHome() + "/edge-dns"
}
}
err = installer.Install(installDir, params, installStatus)
return err
}
@@ -250,6 +251,24 @@ func (this *NSNodeQueue) StartNode(nodeId int64) error {
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
installer := &NSNodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
Port: loginParams.Port,
Username: grant.Username,
Password: grant.Password,
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
return err
}
defer func() {
_ = installer.Close()
}()
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
@@ -264,27 +283,10 @@ func (this *NSNodeQueue) StartNode(nodeId int64) error {
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-dns
installDir = "/" + grant.Username + "/edge-dns"
installDir = installer.client.UserHome() + "/edge-dns"
}
}
installer := &NSNodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
Port: loginParams.Port,
Username: grant.Username,
Password: grant.Password,
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
})
if err != nil {
return err
}
defer func() {
_ = installer.Close()
}()
// 检查命令是否存在
exeFile := installDir + "/edge-dns/bin/edge-dns"
_, err = installer.client.Stat(exeFile)
@@ -356,6 +358,24 @@ func (this *NSNodeQueue) StopNode(nodeId int64) error {
return errors.New("can not find user grant with id '" + numberutils.FormatInt64(loginParams.GrantId) + "'")
}
installer := &NSNodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
Port: loginParams.Port,
Username: grant.Username,
Password: grant.Password,
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
Sudo: grant.Su == 1,
})
if err != nil {
return err
}
defer func() {
_ = installer.Close()
}()
// 安装目录
installDir := node.InstallDir
if len(installDir) == 0 {
@@ -370,27 +390,10 @@ func (this *NSNodeQueue) StopNode(nodeId int64) error {
installDir = cluster.InstallDir
if len(installDir) == 0 {
// 默认是 $登录用户/edge-dns
installDir = "/" + grant.Username + "/edge-dns"
installDir = installer.client.UserHome() + "/edge-dns"
}
}
installer := &NSNodeInstaller{}
err = installer.Login(&Credentials{
Host: loginParams.Host,
Port: loginParams.Port,
Username: grant.Username,
Password: grant.Password,
PrivateKey: grant.PrivateKey,
Passphrase: grant.Passphrase,
Method: grant.Method,
})
if err != nil {
return err
}
defer func() {
_ = installer.Close()
}()
// 检查命令是否存在
exeFile := installDir + "/edge-dns/bin/edge-dns"
_, err = installer.client.Stat(exeFile)

View File

@@ -13,6 +13,9 @@ import (
type SSHClient struct {
raw *ssh.Client
sftp *sftp.Client
sudo bool
sudoPassword string
}
func NewSSHClient(raw *ssh.Client) (*SSHClient, error) {
@@ -30,8 +33,18 @@ func NewSSHClient(raw *ssh.Client) (*SSHClient, error) {
return c, nil
}
// Sudo 设置使用Sudo
func (this *SSHClient) Sudo(password string) {
this.sudo = true
this.sudoPassword = password
}
// Exec 执行shell命令
func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error) {
if this.raw.User() != "root" && this.sudo {
return this.execSudo(cmd, this.sudoPassword)
}
session, err := this.raw.NewSession()
if err != nil {
return "", "", err
@@ -40,8 +53,8 @@ func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error
_ = session.Close()
}()
stdoutBuf := bytes.NewBuffer([]byte{})
stderrBuf := bytes.NewBuffer([]byte{})
var stdoutBuf = &bytes.Buffer{}
var stderrBuf = &bytes.Buffer{}
session.Stdout = stdoutBuf
session.Stderr = stderrBuf
err = session.Run(cmd)
@@ -51,6 +64,79 @@ func (this *SSHClient) Exec(cmd string) (stdout string, stderr string, err error
return strings.TrimRight(stdoutBuf.String(), "\n"), stderrBuf.String(), nil
}
// execSudo 使用sudo执行shell命令
func (this *SSHClient) execSudo(cmd string, password string) (stdout string, stderr string, err error) {
session, err := this.raw.NewSession()
if err != nil {
return "", "", err
}
defer func() {
_ = session.Close()
}()
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echo
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}
err = session.RequestPty("xterm", 80, 40, modes)
if err != nil {
return "", "", err
}
var stderrBuf = &bytes.Buffer{}
session.Stderr = stderrBuf
pipeIn, err := session.StdinPipe()
if err != nil {
return "", "", err
}
pipeOut, err := session.StdoutPipe()
if err != nil {
return "", "", err
}
var resultErr error
var stdoutBuf = bytes.NewBuffer([]byte{})
go func() {
var buf = make([]byte, 512)
for {
n, err := pipeOut.Read(buf)
if n > 0 {
if strings.Contains(string(buf[:n]), "[sudo] password for") {
_, err = pipeIn.Write([]byte(password + "\n"))
if err != nil {
resultErr = err
return
}
continue
}
stdoutBuf.Write(buf[:n])
}
if err != nil {
return
}
}
}()
err = session.Run("sudo " + cmd)
stdout = strings.TrimSpace(stdoutBuf.String())
stderr = strings.TrimSpace(stderrBuf.String())
if err != nil {
return stdout, stderr, err
}
if resultErr != nil {
return stdout, stderr, resultErr
}
return stdout, stderr, nil
}
func (this *SSHClient) Listen(network string, addr string) (net.Listener, error) {
return this.raw.Listen(network, addr)
}
@@ -152,3 +238,31 @@ func (this *SSHClient) WriteFile(path string, data []byte) (n int, err error) {
func (this *SSHClient) Remove(path string) error {
return this.sftp.Remove(path)
}
// User 用户名
func (this *SSHClient) User() string {
return this.raw.User()
}
// UserHome 用户地址
func (this *SSHClient) UserHome() string {
homeStdout, _, err := this.Exec("echo $HOME")
if err != nil {
return this.defaultUserHome()
}
var home = strings.TrimSpace(homeStdout)
if len(home) > 0 {
return home
}
return this.defaultUserHome()
}
func (this *SSHClient) defaultUserHome() string {
var user = this.raw.User()
if user == "root" {
return "/root"
}
return "/home/" + user
}

View File

@@ -0,0 +1,82 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package installers
import (
"golang.org/x/crypto/ssh"
"net"
"testing"
"time"
)
func testSSHClient(t *testing.T, username string, password string) *SSHClient {
methods := []ssh.AuthMethod{}
{
authMethod := ssh.Password(password)
methods = append(methods, authMethod)
}
{
authMethod := ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
if len(questions) == 0 {
return []string{}, nil
}
return []string{password}, nil
})
methods = append(methods, authMethod)
}
config := &ssh.ClientConfig{
User: username,
Auth: methods,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
Timeout: 5 * time.Second,
}
sshClient, err := ssh.Dial("tcp", "192.168.2.31:22", config)
if err != nil {
t.Fatal(err)
}
client, err := NewSSHClient(sshClient)
if err != nil {
t.Fatal(err)
}
return client
}
func TestSSHClient_Home(t *testing.T) {
var client = testSSHClient(t, "root", "123456")
t.Log(client.UserHome())
}
func TestSSHClient_Exec(t *testing.T) {
var client = testSSHClient(t, "liuxiangchao", "123456")
stdout, stderr, err := client.Exec("echo 'Hello'")
if err != nil {
t.Fatal(err)
}
t.Log("stdout:", stdout, "stderr:", stderr)
}
func TestSSHClient_SudoExec(t *testing.T) {
var client = testSSHClient(t, "liuxiangchao", "123456")
client.Sudo("123456")
stdout, stderr, err := client.Exec("echo 'Hello'")
if err != nil {
t.Fatal(err)
}
t.Log("stdout:", stdout, "stderr:", stderr)
}
func TestSSHClient_SudoExec2(t *testing.T) {
var client = testSSHClient(t, "liuxiangchao", "123456")
client.Sudo("123456")
stdout, stderr, err := client.Exec("/home/liuxiangchao/edge-node/edge-node/bin/edge-node start")
if err != nil {
t.Fatal(err)
}
t.Log("stdout:", stdout, "stderr:", stderr)
}

View File

@@ -26,7 +26,7 @@ func (this *NodeGrantService) CreateNodeGrant(ctx context.Context, req *pb.Creat
tx := this.NullTx()
grantId, err := models.SharedNodeGrantDAO.CreateGrant(tx, adminId, req.Name, req.Method, req.Username, req.Password, req.PrivateKey, req.Passphrase, req.Description, req.NodeId)
grantId, err := models.SharedNodeGrantDAO.CreateGrant(tx, adminId, req.Name, req.Method, req.Username, req.Password, req.PrivateKey, req.Passphrase, req.Description, req.NodeId, req.Su)
if err != nil {
return nil, err
}
@@ -48,7 +48,7 @@ func (this *NodeGrantService) UpdateNodeGrant(ctx context.Context, req *pb.Updat
tx := this.NullTx()
err = models.SharedNodeGrantDAO.UpdateGrant(tx, req.NodeGrantId, req.Name, req.Method, req.Username, req.Password, req.PrivateKey, req.Passphrase, req.Description, req.NodeId)
err = models.SharedNodeGrantDAO.UpdateGrant(tx, req.NodeGrantId, req.Name, req.Method, req.Username, req.Password, req.PrivateKey, req.Passphrase, req.Description, req.NodeId, req.Su)
return this.Success()
}

File diff suppressed because one or more lines are too long

View File

@@ -59,6 +59,9 @@ var upgradeFuncs = []*upgradeVersion{
{
"0.3.3", upgradeV0_3_3,
},
{
"0.3.7", upgradeV0_3_7,
},
}
// UpgradeSQLData 升级SQL数据
@@ -532,3 +535,13 @@ func upgradeV0_3_3(db *dbs.DB) error {
return nil
}
// v0.3.7
func upgradeV0_3_7(db *dbs.DB) error {
// 修改所有edgeNodeGrants中的su为0
_, err := db.Exec("UPDATE edgeNodeGrants SET su=0 WHERE su=1")
if err != nil {
return err
}
return nil
}

View File

@@ -21,7 +21,6 @@ func TestUpgradeSQLData(t *testing.T) {
t.Log("ok")
}
func TestUpgradeSQLData_v0_3_1(t *testing.T) {
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
Driver: "mysql",
@@ -68,4 +67,20 @@ func TestUpgradeSQLData_v0_3_3(t *testing.T) {
t.Fatal(err)
}
t.Log("ok")
}
}
func TestUpgradeSQLData_v0_3_7(t *testing.T) {
db, err := dbs.NewInstanceFromConfig(&dbs.DBConfig{
Driver: "mysql",
Dsn: "root:123456@tcp(127.0.0.1:3306)/db_edge?charset=utf8mb4&timeout=30s",
Prefix: "edge",
})
if err != nil {
t.Fatal(err)
}
err = upgradeV0_3_7(db)
if err != nil {
t.Fatal(err)
}
t.Log("ok")
}