@@ -16,6 +16,7 @@ import (
16
16
type RedisMasterResolver struct {
17
17
masterName string
18
18
sentinelAddr * net.TCPAddr
19
+ sentinelPassword string
19
20
retryOnMasterResolveFail int
20
21
21
22
masterAddrLock * sync.RWMutex
@@ -24,10 +25,11 @@ type RedisMasterResolver struct {
24
25
masterAddr string
25
26
}
26
27
27
- func NewRedisMasterResolver (masterName string , sentinelAddr * net.TCPAddr , retryOnMasterResolveFail int ) * RedisMasterResolver {
28
+ func NewRedisMasterResolver (masterName string , sentinelAddr * net.TCPAddr , sentinelPassword string , retryOnMasterResolveFail int ) * RedisMasterResolver {
28
29
return & RedisMasterResolver {
29
30
masterName : masterName ,
30
31
sentinelAddr : sentinelAddr ,
32
+ sentinelPassword : sentinelPassword ,
31
33
retryOnMasterResolveFail : retryOnMasterResolveFail ,
32
34
masterAddrLock : & sync.RWMutex {},
33
35
initialMasterResolveLock : make (chan struct {}),
@@ -49,7 +51,7 @@ func (r *RedisMasterResolver) setMasterAddress(masterAddr *net.TCPAddr) {
49
51
}
50
52
51
53
func (r * RedisMasterResolver ) updateMasterAddress () error {
52
- masterAddr , err := redisMasterFromSentinelAddr (r .sentinelAddr , r .masterName )
54
+ masterAddr , err := redisMasterFromSentinelAddr (r .sentinelAddr , r .sentinelPassword , r . masterName )
53
55
if err != nil {
54
56
log .Println (err )
55
57
return err
@@ -59,7 +61,7 @@ func (r *RedisMasterResolver) updateMasterAddress() error {
59
61
}
60
62
61
63
func (r * RedisMasterResolver ) UpdateMasterAddressLoop (ctx context.Context ) error {
62
- if err := r .initialMasterAdressResolve (); err != nil {
64
+ if err := r .initialMasterAddressResolve (); err != nil {
63
65
return err
64
66
}
65
67
@@ -84,46 +86,70 @@ func (r *RedisMasterResolver) UpdateMasterAddressLoop(ctx context.Context) error
84
86
return err
85
87
}
86
88
87
- func (r * RedisMasterResolver ) initialMasterAdressResolve () error {
89
+ func (r * RedisMasterResolver ) initialMasterAddressResolve () error {
88
90
defer close (r .initialMasterResolveLock )
89
91
return r .updateMasterAddress ()
90
92
}
91
93
92
- func redisMasterFromSentinelAddr (sentinelAddress * net.TCPAddr , masterName string ) (* net.TCPAddr , error ) {
94
+ func redisMasterFromSentinelAddr (sentinelAddress * net.TCPAddr , sentinelPassword string , masterName string ) (* net.TCPAddr , error ) {
93
95
conn , err := utils .TCPConnectWithTimeout (sentinelAddress .String ())
94
- conn .SetDeadline (time .Now ().Add (time .Second ))
95
96
if err != nil {
96
97
return nil , fmt .Errorf ("error connecting to sentinel: %w" , err )
97
98
}
98
99
defer conn .Close ()
99
100
100
- getMasterCommand := fmt .Sprintf ("sentinel get-master-addr-by-name %s\n " , masterName )
101
+ conn .SetDeadline (time .Now ().Add (time .Second ))
102
+
103
+ // Authenticate with sentinel if password is provided
104
+ if sentinelPassword != "" {
105
+ authCommand := fmt .Sprintf ("AUTH %s\r \n " , sentinelPassword )
106
+ if _ , err := conn .Write ([]byte (authCommand )); err != nil {
107
+ return nil , fmt .Errorf ("error sending AUTH to sentinel: %w" , err )
108
+ }
109
+
110
+ // Read response from AUTH
111
+ b := make ([]byte , 256 )
112
+ n , err := conn .Read (b )
113
+ if err != nil {
114
+ return nil , fmt .Errorf ("error reading AUTH response: %w" , err )
115
+ }
116
+ response := string (b [:n ])
117
+ if ! strings .HasPrefix (response , "+OK" ) {
118
+ return nil , fmt .Errorf ("sentinel AUTH failed: %s" , response )
119
+ }
120
+ }
121
+
122
+ // Request master address
123
+ getMasterCommand := fmt .Sprintf ("SENTINEL get-master-addr-by-name %s\r \n " , masterName )
101
124
if _ , err := conn .Write ([]byte (getMasterCommand )); err != nil {
102
125
return nil , fmt .Errorf ("error writing to sentinel: %w" , err )
103
126
}
104
127
128
+ // Read response
105
129
b := make ([]byte , 256 )
106
- if _ , err := conn .Read (b ); err != nil {
130
+ n , err := conn .Read (b )
131
+ if err != nil {
107
132
return nil , fmt .Errorf ("error getting info from sentinel: %w" , err )
108
133
}
109
134
110
- parts := strings . Split ( string ( b ), " \r \n " )
111
-
135
+ // Extract master address parts
136
+ parts := strings . Split ( string ( b [: n ]), " \r \n " )
112
137
if len (parts ) < 5 {
113
138
return nil , errors .New ("couldn't get master address from sentinel" )
114
139
}
115
140
116
- // getting the string address for the master node
117
- stringaddr := fmt .Sprintf ("%s:%s" , parts [2 ], parts [4 ])
118
- addr , err := net .ResolveTCPAddr ("tcp" , stringaddr )
141
+ // Assemble master address
142
+ formattedMasterAddress := fmt .Sprintf ("%s:%s" , parts [2 ], parts [4 ])
143
+ addr , err := net .ResolveTCPAddr ("tcp" , formattedMasterAddress )
119
144
if err != nil {
120
145
return nil , fmt .Errorf ("error resolving redis master: %w" , err )
121
146
}
122
147
123
- // check that there's actually someone listening on that address
148
+ // Check if there is a Redis instance listening on the master address
124
149
if err := checkTCPConnect (addr ); err != nil {
125
150
return nil , fmt .Errorf ("error checking redis master: %w" , err )
126
151
}
152
+
127
153
return addr , nil
128
154
}
129
155
0 commit comments