feat: support sentinel mode #16 #42

This commit is contained in:
tiny-craft 2023-10-08 01:31:54 +08:00
parent 477ed19d20
commit ee68d699fa
7 changed files with 105 additions and 21 deletions

View File

@ -127,6 +127,21 @@ func (c *connectionService) createRedisClient(config types.ConnectionConfig) (*r
option.ReadTimeout = -2 option.ReadTimeout = -2
option.WriteTimeout = -2 option.WriteTimeout = -2
} }
if config.Sentinel.Enable {
sentinel := redis.NewSentinelClient(option)
addr, err := sentinel.GetMasterAddrByName(c.ctx, config.Sentinel.Master).Result()
if err != nil {
return nil, err
}
if len(addr) < 2 {
return nil, errors.New("cannot get master address")
}
option.Addr = fmt.Sprintf("%s:%s", addr[0], addr[1])
option.Username = config.Sentinel.Username
option.Password = config.Sentinel.Password
}
rdb := redis.NewClient(option) rdb := redis.NewClient(option)
return rdb, nil return rdb, nil
} }

View File

@ -37,6 +37,9 @@ func (c *ConnectionsStorage) defaultConnectionItem() types.ConnectionConfig {
DBFilterType: "none", DBFilterType: "none",
DBFilterList: []int{}, DBFilterList: []int{},
MarkColor: "", MarkColor: "",
Sentinel: types.ConnectionSentinel{
Master: "mymaster",
},
} }
} }

View File

@ -3,20 +3,21 @@ package types
type ConnectionCategory int type ConnectionCategory int
type ConnectionConfig struct { type ConnectionConfig struct {
Name string `json:"name" yaml:"name"` Name string `json:"name" yaml:"name"`
Group string `json:"group,omitempty" yaml:"-"` Group string `json:"group,omitempty" yaml:"-"`
Addr string `json:"addr,omitempty" yaml:"addr,omitempty"` Addr string `json:"addr,omitempty" yaml:"addr,omitempty"`
Port int `json:"port,omitempty" yaml:"port,omitempty"` Port int `json:"port,omitempty" yaml:"port,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"` Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"` Password string `json:"password,omitempty" yaml:"password,omitempty"`
DefaultFilter string `json:"defaultFilter,omitempty" yaml:"default_filter,omitempty"` DefaultFilter string `json:"defaultFilter,omitempty" yaml:"default_filter,omitempty"`
KeySeparator string `json:"keySeparator,omitempty" yaml:"key_separator,omitempty"` KeySeparator string `json:"keySeparator,omitempty" yaml:"key_separator,omitempty"`
ConnTimeout int `json:"connTimeout,omitempty" yaml:"conn_timeout,omitempty"` ConnTimeout int `json:"connTimeout,omitempty" yaml:"conn_timeout,omitempty"`
ExecTimeout int `json:"execTimeout,omitempty" yaml:"exec_timeout,omitempty"` ExecTimeout int `json:"execTimeout,omitempty" yaml:"exec_timeout,omitempty"`
DBFilterType string `json:"dbFilterType" yaml:"db_filter_type,omitempty"` DBFilterType string `json:"dbFilterType" yaml:"db_filter_type,omitempty"`
DBFilterList []int `json:"dbFilterList" yaml:"db_filter_list,omitempty"` DBFilterList []int `json:"dbFilterList" yaml:"db_filter_list,omitempty"`
MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"` MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"`
SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"` SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"`
Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"`
} }
type Connection struct { type Connection struct {
@ -49,3 +50,10 @@ type ConnectionSSH struct {
PKFile string `json:"pkFile,omitempty" yaml:"pk_file,omitempty"` PKFile string `json:"pkFile,omitempty" yaml:"pk_file,omitempty"`
Passphrase string `json:"passphrase,omitempty" yaml:"passphrase,omitempty"` Passphrase string `json:"passphrase,omitempty" yaml:"passphrase,omitempty"`
} }
type ConnectionSentinel struct {
Enable bool `json:"enable" yaml:"enable"`
Master string `json:"master" yaml:"master"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
}

View File

@ -198,6 +198,7 @@ const onClose = () => {
transform-origin="center"> transform-origin="center">
<n-spin :show="closingConnection"> <n-spin :show="closingConnection">
<n-tabs v-model:value="tab" animated type="line"> <n-tabs v-model:value="tab" animated type="line">
<!-- General pane -->
<n-tab-pane :tab="$t('dialogue.connection.general')" display-directive="show" name="general"> <n-tab-pane :tab="$t('dialogue.connection.general')" display-directive="show" name="general">
<n-form <n-form
ref="generalFormRef" ref="generalFormRef"
@ -239,7 +240,8 @@ const onClose = () => {
</n-form> </n-form>
</n-tab-pane> </n-tab-pane>
<n-tab-pane :tab="$t('dialogue.connection.advanced')" display-directive="show" name="advanced"> <!-- Advance pane -->
<n-tab-pane :tab="$t('dialogue.connection.advn.title')" display-directive="show" name="advanced">
<n-form <n-form
ref="advanceFormRef" ref="advanceFormRef"
:model="generalForm" :model="generalForm"
@ -327,14 +329,14 @@ const onClose = () => {
</n-form> </n-form>
</n-tab-pane> </n-tab-pane>
<n-tab-pane :tab="$t('dialogue.connection.ssh.tunnel')" display-directive="show" name="ssh"> <!-- SSH pane -->
<n-tab-pane :tab="$t('dialogue.connection.ssh.title')" display-directive="show" name="ssh">
<n-form-item label-placement="left"> <n-form-item label-placement="left">
<n-checkbox v-model:checked="generalForm.ssh.enable" size="medium"> <n-checkbox v-model:checked="generalForm.ssh.enable" size="medium">
{{ $t('dialogue.connection.ssh.enable') }} {{ $t('dialogue.connection.ssh.enable') }}
</n-checkbox> </n-checkbox>
</n-form-item> </n-form-item>
<n-form <n-form
ref="sshFormRef"
:model="generalForm.ssh" :model="generalForm.ssh"
:show-require-mark="false" :show-require-mark="false"
:disabled="!generalForm.ssh.enable" :disabled="!generalForm.ssh.enable"
@ -388,6 +390,38 @@ const onClose = () => {
</n-form> </n-form>
</n-tab-pane> </n-tab-pane>
<!-- Sentinel pane -->
<n-tab-pane :tab="$t('dialogue.connection.sentinel.title')" display-directive="show" name="sentinel">
<n-form-item label-placement="left">
<n-checkbox v-model:checked="generalForm.sentinel.enable" size="medium">
{{ $t('dialogue.connection.sentinel.enable') }}
</n-checkbox>
</n-form-item>
<n-form
:model="generalForm.sentinel"
:show-require-mark="false"
:disabled="!generalForm.sentinel.enable"
label-placement="top">
<n-form-item :label="$t('dialogue.connection.sentinel.master')">
<n-input
v-model:value="generalForm.sentinel.master"
:placeholder="$t('dialogue.connection.sentinel.master')" />
</n-form-item>
<n-form-item :label="$t('dialogue.connection.sentinel.password')">
<n-input
v-model:value="generalForm.sentinel.password"
:placeholder="$t('dialogue.connection.sentinel.pwd_tip')"
show-password-on="click"
type="password" />
</n-form-item>
<n-form-item :label="$t('dialogue.connection.sentinel.username')">
<n-input
v-model:value="generalForm.sentinel.username"
:placeholder="$t('dialogue.connection.sentinel.usr_tip')" />
</n-form-item>
</n-form>
</n-tab-pane>
<!-- TODO: SSL tab pane --> <!-- TODO: SSL tab pane -->
<!-- TODO: Sentinel tab pane --> <!-- TODO: Sentinel tab pane -->
<!-- TODO: Cluster tab pane --> <!-- TODO: Cluster tab pane -->

View File

@ -114,7 +114,6 @@
"new_title": "New Connection", "new_title": "New Connection",
"edit_title": "Edit Connection", "edit_title": "Edit Connection",
"general": "General", "general": "General",
"advanced": "Advanced",
"no_group": "No Group", "no_group": "No Group",
"group": "Group", "group": "Group",
"conn_name": "Name", "conn_name": "Name",
@ -129,6 +128,7 @@
"test_succ": "Successful connection to redis-server", "test_succ": "Successful connection to redis-server",
"test_fail": "Fail Connection", "test_fail": "Fail Connection",
"advn": { "advn": {
"title": "Advanced",
"filter": "Default Key Filter Pattern", "filter": "Default Key Filter Pattern",
"filter_tip": "Pattern which defines loaded keys from redis server", "filter_tip": "Pattern which defines loaded keys from redis server",
"separator": "Key Separator", "separator": "Key Separator",
@ -146,8 +146,8 @@
"mark_color": "Mark Color" "mark_color": "Mark Color"
}, },
"ssh": { "ssh": {
"title": "SSH Tunnel",
"enable": "Enable SSH Tuntel", "enable": "Enable SSH Tuntel",
"tunnel": "SSH Tunnel",
"login_type": "Login Type", "login_type": "Login Type",
"pkfile": "Private Key File", "pkfile": "Private Key File",
"passphrase": "Passphrase", "passphrase": "Passphrase",
@ -157,6 +157,15 @@
"pkfile_tip": "SSH Private Key File Path", "pkfile_tip": "SSH Private Key File Path",
"passphrase_tip": "(Optional) Passphrase for Private Key", "passphrase_tip": "(Optional) Passphrase for Private Key",
"pkfile_selection_title": "Please Select Private Key File" "pkfile_selection_title": "Please Select Private Key File"
},
"sentinel": {
"title": "Sentinel",
"enable": "Serve as Sentinel Node",
"master": "Name of Master Node",
"password": "Password for Master Node",
"username": "Username for Master Node",
"pwd_tip": "(Optional) username for master node",
"usr_tip": "(Optional) authentication password for master node (Redis > 6.0)"
} }
}, },
"group": { "group": {

View File

@ -114,7 +114,6 @@
"new_title": "新建连接", "new_title": "新建连接",
"edit_title": "编辑连接", "edit_title": "编辑连接",
"general": "常规配置", "general": "常规配置",
"advanced": "高级配置",
"no_group": "无分组", "no_group": "无分组",
"group": "分组", "group": "分组",
"conn_name": "连接名", "conn_name": "连接名",
@ -129,6 +128,7 @@
"test_succ": "成功连接到Redis服务器", "test_succ": "成功连接到Redis服务器",
"test_fail": "连接失败", "test_fail": "连接失败",
"advn": { "advn": {
"title": "高级配置",
"filter": "默认键过滤表达式", "filter": "默认键过滤表达式",
"filter_tip": "需要加载的键名表达式", "filter_tip": "需要加载的键名表达式",
"separator": "键分隔符", "separator": "键分隔符",
@ -147,7 +147,7 @@
}, },
"ssh": { "ssh": {
"enable": "启用SSH隧道", "enable": "启用SSH隧道",
"tunnel": "SSH隧道", "title": "SSH隧道",
"login_type": "登录类型", "login_type": "登录类型",
"pkfile": "私钥文件", "pkfile": "私钥文件",
"passphrase": "私钥密码", "passphrase": "私钥密码",
@ -157,6 +157,15 @@
"pkfile_tip": "SSH私钥文件路径", "pkfile_tip": "SSH私钥文件路径",
"passphrase_tip": "(可选)SSH私钥密码", "passphrase_tip": "(可选)SSH私钥密码",
"pkfile_selection_title": "请选择私钥文件" "pkfile_selection_title": "请选择私钥文件"
},
"sentinel": {
"title": "哨兵模式",
"enable": "当前为哨兵节点",
"master": "主实例名",
"password": "主节点密码",
"username": "主节点用户名",
"pwd_tip": "(可选)主节点服务授权用户名",
"usr_tip": "(可选)主节点服务授权密码 (Redis > 6.0)"
} }
}, },
"group": { "group": {

View File

@ -221,6 +221,12 @@ const useConnectionStore = defineStore('connections', {
pkFile: '', pkFile: '',
passphrase: '', passphrase: '',
}, },
sentinel: {
enable: false,
master: 'mymaster',
username: '',
password: '',
},
} }
}, },