2023-06-27 15:53:29 +08:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
"sync"
|
2023-10-20 18:22:53 +08:00
|
|
|
"tinyrdm/backend/consts"
|
2023-06-27 15:53:29 +08:00
|
|
|
"tinyrdm/backend/types"
|
2023-07-02 22:25:23 +08:00
|
|
|
sliceutil "tinyrdm/backend/utils/slice"
|
2023-06-27 15:53:29 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type ConnectionsStorage struct {
|
|
|
|
storage *localStorage
|
|
|
|
mutex sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewConnections() *ConnectionsStorage {
|
|
|
|
return &ConnectionsStorage{
|
|
|
|
storage: NewLocalStore("connections.yaml"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) defaultConnections() types.Connections {
|
|
|
|
return types.Connections{}
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) defaultConnectionItem() types.ConnectionConfig {
|
|
|
|
return types.ConnectionConfig{
|
2023-06-27 15:53:29 +08:00
|
|
|
Name: "",
|
|
|
|
Addr: "127.0.0.1",
|
|
|
|
Port: 6379,
|
|
|
|
Username: "",
|
|
|
|
Password: "",
|
|
|
|
DefaultFilter: "*",
|
|
|
|
KeySeparator: ":",
|
|
|
|
ConnTimeout: 60,
|
|
|
|
ExecTimeout: 60,
|
2023-10-07 02:08:41 +08:00
|
|
|
DBFilterType: "none",
|
|
|
|
DBFilterList: []int{},
|
2023-10-20 18:22:53 +08:00
|
|
|
LoadSize: consts.DEFAULT_LOAD_SIZE,
|
2023-06-27 15:53:29 +08:00
|
|
|
MarkColor: "",
|
2023-10-08 01:31:54 +08:00
|
|
|
Sentinel: types.ConnectionSentinel{
|
|
|
|
Master: "mymaster",
|
|
|
|
},
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) getConnections() (ret types.Connections) {
|
2023-06-27 15:53:29 +08:00
|
|
|
b, err := c.storage.Load()
|
2023-12-05 12:03:00 +08:00
|
|
|
ret = c.defaultConnections()
|
2023-06-27 15:53:29 +08:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = yaml.Unmarshal(b, &ret); err != nil {
|
|
|
|
ret = c.defaultConnections()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(ret) <= 0 {
|
|
|
|
ret = c.defaultConnections()
|
|
|
|
}
|
|
|
|
//if !sliceutil.AnyMatch(ret, func(i int) bool {
|
|
|
|
// return ret[i].GroupName == ""
|
|
|
|
//}) {
|
|
|
|
// ret = append(ret, c.defaultConnections()...)
|
|
|
|
//}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetConnections get all store connections from local
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) GetConnections() (ret types.Connections) {
|
2023-06-27 15:53:29 +08:00
|
|
|
return c.getConnections()
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetConnectionsFlat get all store connections from local flat(exclude group level)
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) GetConnectionsFlat() (ret types.Connections) {
|
2023-07-02 03:25:57 +08:00
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
for _, conn := range conns {
|
|
|
|
if conn.Type == "group" {
|
|
|
|
ret = append(ret, conn.Connections...)
|
|
|
|
} else {
|
|
|
|
ret = append(ret, conn)
|
|
|
|
}
|
2023-07-02 03:25:57 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
|
2023-07-02 03:25:57 +08:00
|
|
|
// GetConnection get connection by name
|
|
|
|
func (c *ConnectionsStorage) GetConnection(name string) *types.Connection {
|
2023-06-27 15:53:29 +08:00
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
|
|
|
|
var findConn func(string, string, types.Connections) *types.Connection
|
|
|
|
findConn = func(name, groupName string, conns types.Connections) *types.Connection {
|
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type != "group" {
|
|
|
|
if conn.Name == name {
|
|
|
|
conns[i].Group = groupName
|
|
|
|
return &conns[i]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ret := findConn(name, conn.Name, conn.Connections); ret != nil {
|
|
|
|
return ret
|
|
|
|
}
|
2023-07-02 03:25:57 +08:00
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
2023-07-02 16:52:07 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return findConn(name, "", conns)
|
|
|
|
}
|
|
|
|
|
2023-07-16 01:50:01 +08:00
|
|
|
// GetGroup get one connection group by name
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) GetGroup(name string) *types.Connection {
|
|
|
|
conns := c.getConnections()
|
|
|
|
|
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type == "group" && conn.Name == name {
|
|
|
|
return &conns[i]
|
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
2023-07-02 03:25:57 +08:00
|
|
|
return nil
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) saveConnections(conns types.Connections) error {
|
2023-06-27 15:53:29 +08:00
|
|
|
b, err := yaml.Marshal(&conns)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err = c.storage.Store(b); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-07-02 03:25:57 +08:00
|
|
|
// CreateConnection create new connection
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) CreateConnection(param types.ConnectionConfig) error {
|
2023-07-02 03:25:57 +08:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conn := c.GetConnection(param.Name)
|
|
|
|
if conn != nil {
|
|
|
|
return errors.New("duplicated connection name")
|
|
|
|
}
|
|
|
|
|
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
var group *types.Connection
|
|
|
|
if len(param.Group) > 0 {
|
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type == "group" && conn.Name == param.Group {
|
|
|
|
group = &conns[i]
|
|
|
|
break
|
|
|
|
}
|
2023-07-02 03:25:57 +08:00
|
|
|
}
|
2023-07-02 16:52:07 +08:00
|
|
|
}
|
|
|
|
if group != nil {
|
|
|
|
group.Connections = append(group.Connections, types.Connection{
|
|
|
|
ConnectionConfig: param,
|
|
|
|
})
|
2023-07-02 03:25:57 +08:00
|
|
|
} else {
|
2023-07-02 16:52:07 +08:00
|
|
|
if len(param.Group) > 0 {
|
|
|
|
// no group matched, create new group
|
|
|
|
conns = append(conns, types.Connection{
|
|
|
|
Type: "group",
|
|
|
|
Connections: types.Connections{
|
|
|
|
types.Connection{
|
|
|
|
ConnectionConfig: param,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
conns = append(conns, types.Connection{
|
|
|
|
ConnectionConfig: param,
|
|
|
|
})
|
|
|
|
}
|
2023-07-02 03:25:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return c.saveConnections(conns)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateConnection update existing connection by name
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) UpdateConnection(name string, param types.ConnectionConfig) error {
|
2023-06-27 15:53:29 +08:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conns := c.getConnections()
|
2023-07-02 20:11:53 +08:00
|
|
|
var updated bool
|
|
|
|
var retrieve func(types.Connections, string, types.ConnectionConfig) error
|
|
|
|
retrieve = func(conns types.Connections, name string, param types.ConnectionConfig) error {
|
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type != "group" {
|
|
|
|
if name != param.Name && conn.Name == param.Name {
|
|
|
|
return errors.New("duplicated connection name")
|
|
|
|
} else if conn.Name == name && !updated {
|
|
|
|
conns[i] = types.Connection{
|
2023-07-02 16:52:07 +08:00
|
|
|
ConnectionConfig: param,
|
|
|
|
}
|
|
|
|
updated = true
|
2023-07-02 20:11:53 +08:00
|
|
|
}
|
|
|
|
} else {
|
2023-10-08 15:24:08 +08:00
|
|
|
if err := retrieve(conn.Connections, name, param); err != nil {
|
2023-07-02 20:11:53 +08:00
|
|
|
return err
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-07-02 20:11:53 +08:00
|
|
|
return nil
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
2023-07-02 16:52:07 +08:00
|
|
|
|
2023-07-02 20:11:53 +08:00
|
|
|
err := retrieve(conns, name, param)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if !updated {
|
|
|
|
return errors.New("connection not found")
|
2023-07-02 16:52:07 +08:00
|
|
|
}
|
|
|
|
|
2023-07-02 20:11:53 +08:00
|
|
|
return c.saveConnections(conns)
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
|
2023-07-06 01:22:14 +08:00
|
|
|
// DeleteConnection remove special connection
|
|
|
|
func (c *ConnectionsStorage) DeleteConnection(name string) error {
|
2023-06-27 15:53:29 +08:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
var updated bool
|
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type == "group" {
|
|
|
|
for j, subConn := range conn.Connections {
|
|
|
|
if subConn.Name == name {
|
|
|
|
conns[i].Connections = append(conns[i].Connections[:j], conns[i].Connections[j+1:]...)
|
|
|
|
updated = true
|
|
|
|
break
|
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
2023-07-02 16:52:07 +08:00
|
|
|
} else if conn.Name == name {
|
|
|
|
conns = append(conns[:i], conns[i+1:]...)
|
|
|
|
updated = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if updated {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !updated {
|
|
|
|
return errors.New("no match connection")
|
|
|
|
}
|
|
|
|
return c.saveConnections(conns)
|
|
|
|
}
|
|
|
|
|
2023-07-02 22:25:23 +08:00
|
|
|
// SaveSortedConnection save connection after sort
|
|
|
|
func (c *ConnectionsStorage) SaveSortedConnection(sortedConns types.Connections) error {
|
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conns := c.GetConnectionsFlat()
|
|
|
|
takeConn := func(name string) (types.Connection, bool) {
|
|
|
|
idx, ok := sliceutil.Find(conns, func(i int) bool {
|
|
|
|
return conns[i].Name == name
|
|
|
|
})
|
|
|
|
if ok {
|
|
|
|
ret := conns[idx]
|
|
|
|
conns = append(conns[:idx], conns[idx+1:]...)
|
|
|
|
return ret, true
|
|
|
|
}
|
|
|
|
return types.Connection{}, false
|
|
|
|
}
|
|
|
|
var replaceConn func(connections types.Connections) types.Connections
|
|
|
|
replaceConn = func(cons types.Connections) types.Connections {
|
|
|
|
var newConns types.Connections
|
|
|
|
for _, conn := range cons {
|
|
|
|
if conn.Type == "group" {
|
|
|
|
newConns = append(newConns, types.Connection{
|
|
|
|
ConnectionConfig: types.ConnectionConfig{
|
|
|
|
Name: conn.Name,
|
|
|
|
},
|
|
|
|
Type: "group",
|
|
|
|
Connections: replaceConn(conn.Connections),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
if foundConn, ok := takeConn(conn.Name); ok {
|
|
|
|
newConns = append(newConns, foundConn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newConns
|
|
|
|
}
|
|
|
|
conns = replaceConn(sortedConns)
|
|
|
|
return c.saveConnections(conns)
|
|
|
|
}
|
|
|
|
|
2023-10-08 15:24:08 +08:00
|
|
|
// CreateGroup create a new group
|
2023-07-02 16:52:07 +08:00
|
|
|
func (c *ConnectionsStorage) CreateGroup(name string) error {
|
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conns := c.getConnections()
|
|
|
|
for _, conn := range conns {
|
|
|
|
if conn.Type == "group" && conn.Name == name {
|
|
|
|
return errors.New("duplicated group name")
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
conns = append(conns, types.Connection{
|
|
|
|
ConnectionConfig: types.ConnectionConfig{
|
|
|
|
Name: name,
|
|
|
|
},
|
|
|
|
Type: "group",
|
|
|
|
})
|
|
|
|
return c.saveConnections(conns)
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
|
2023-07-02 16:52:07 +08:00
|
|
|
// RenameGroup rename group
|
|
|
|
func (c *ConnectionsStorage) RenameGroup(name, newName string) error {
|
2023-06-27 15:53:29 +08:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
2023-07-02 20:11:53 +08:00
|
|
|
groupIndex := -1
|
2023-06-27 15:53:29 +08:00
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
for i, conn := range conns {
|
2023-07-02 20:11:53 +08:00
|
|
|
if conn.Type == "group" {
|
|
|
|
if conn.Name == newName {
|
|
|
|
return errors.New("duplicated group name")
|
|
|
|
} else if conn.Name == name {
|
|
|
|
groupIndex = i
|
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-02 20:11:53 +08:00
|
|
|
if groupIndex == -1 {
|
|
|
|
return errors.New("group not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
conns[groupIndex].Name = newName
|
|
|
|
return c.saveConnections(conns)
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|
|
|
|
|
2023-10-08 15:24:08 +08:00
|
|
|
// DeleteGroup remove specified group, include all connections under it
|
2023-07-06 01:22:14 +08:00
|
|
|
func (c *ConnectionsStorage) DeleteGroup(group string, includeConnection bool) error {
|
2023-06-27 15:53:29 +08:00
|
|
|
c.mutex.Lock()
|
|
|
|
defer c.mutex.Unlock()
|
|
|
|
|
|
|
|
conns := c.getConnections()
|
2023-07-02 16:52:07 +08:00
|
|
|
for i, conn := range conns {
|
|
|
|
if conn.Type == "group" && conn.Name == group {
|
2023-06-27 15:53:29 +08:00
|
|
|
conns = append(conns[:i], conns[i+1:]...)
|
2023-07-02 16:52:07 +08:00
|
|
|
if includeConnection {
|
|
|
|
conns = append(conns, conn.Connections...)
|
|
|
|
}
|
2023-06-27 15:53:29 +08:00
|
|
|
return c.saveConnections(conns)
|
|
|
|
}
|
|
|
|
}
|
2023-07-02 16:52:07 +08:00
|
|
|
return errors.New("group not found")
|
2023-06-27 15:53:29 +08:00
|
|
|
}
|