Skip to content

Commit f5abda5

Browse files
authored
Merge pull request #3 from wy65701436/patch-sentinel
patch redis sentinel
2 parents d7dba95 + b675afe commit f5abda5

File tree

8 files changed

+776
-14
lines changed

8 files changed

+776
-14
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
password: ${{ secrets.DOCKERHUB_TOKEN }}
7373
-
7474
name: Build image
75-
uses: docker/bake-action@v3
75+
uses: docker/bake-action@v5
7676
with:
7777
files: |
7878
./docker-bake.hcl

configuration/configuration.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ type Configuration struct {
168168
// Addr specifies the the redis instance available to the application.
169169
Addr string `yaml:"addr,omitempty"`
170170

171+
// SentinelMasterSet specifies the the redis sentinel master set name.
172+
SentinelMasterSet string `yaml:"sentinelMasterSet,omitempty"`
173+
171174
// Password string to use when making a connection.
172175
Password string `yaml:"password,omitempty"`
173176

registry/handlers/app.go

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package handlers
33
import (
44
"context"
55
"crypto/rand"
6+
"errors"
67
"expvar"
78
"fmt"
89
"math"
@@ -16,6 +17,7 @@ import (
1617
"strings"
1718
"time"
1819

20+
"github.com/FZambia/sentinel"
1921
"github.com/distribution/reference"
2022
"github.com/docker/distribution"
2123
"github.com/docker/distribution/configuration"
@@ -499,6 +501,45 @@ func (app *App) configureRedis(configuration *configuration.Configuration) {
499501
return
500502
}
501503

504+
var getRedisAddr func() (string, error)
505+
var testOnBorrow func(c redis.Conn, t time.Time) error
506+
if configuration.Redis.SentinelMasterSet != "" {
507+
sntnl := &sentinel.Sentinel{
508+
Addrs: strings.Split(configuration.Redis.Addr, ","),
509+
MasterName: configuration.Redis.SentinelMasterSet,
510+
Dial: func(addr string) (redis.Conn, error) {
511+
c, err := redis.DialTimeout("tcp", addr,
512+
configuration.Redis.DialTimeout,
513+
configuration.Redis.ReadTimeout,
514+
configuration.Redis.WriteTimeout)
515+
if err != nil {
516+
return nil, err
517+
}
518+
return c, nil
519+
},
520+
}
521+
getRedisAddr = func() (string, error) {
522+
return sntnl.MasterAddr()
523+
}
524+
testOnBorrow = func(c redis.Conn, t time.Time) error {
525+
if !sentinel.TestRole(c, "master") {
526+
return errors.New("role check failed")
527+
}
528+
return nil
529+
}
530+
531+
} else {
532+
getRedisAddr = func() (string, error) {
533+
return configuration.Redis.Addr, nil
534+
}
535+
testOnBorrow = func(c redis.Conn, t time.Time) error {
536+
// TODO(stevvooe): We can probably do something more interesting
537+
// here with the health package.
538+
_, err := c.Do("PING")
539+
return err
540+
}
541+
}
542+
502543
pool := &redis.Pool{
503544
Dial: func() (redis.Conn, error) {
504545
// TODO(stevvooe): Yet another use case for contextual timing.
@@ -514,8 +555,11 @@ func (app *App) configureRedis(configuration *configuration.Configuration) {
514555
}
515556
}
516557

517-
conn, err := redis.DialTimeout("tcp",
518-
configuration.Redis.Addr,
558+
redisAddr, err := getRedisAddr()
559+
if err != nil {
560+
return nil, err
561+
}
562+
conn, err := redis.DialTimeout("tcp", redisAddr,
519563
configuration.Redis.DialTimeout,
520564
configuration.Redis.ReadTimeout,
521565
configuration.Redis.WriteTimeout)
@@ -547,16 +591,11 @@ func (app *App) configureRedis(configuration *configuration.Configuration) {
547591
done(nil)
548592
return conn, nil
549593
},
550-
MaxIdle: configuration.Redis.Pool.MaxIdle,
551-
MaxActive: configuration.Redis.Pool.MaxActive,
552-
IdleTimeout: configuration.Redis.Pool.IdleTimeout,
553-
TestOnBorrow: func(c redis.Conn, t time.Time) error {
554-
// TODO(stevvooe): We can probably do something more interesting
555-
// here with the health package.
556-
_, err := c.Do("PING")
557-
return err
558-
},
559-
Wait: false, // if a connection is not available, proceed without cache.
594+
MaxIdle: configuration.Redis.Pool.MaxIdle,
595+
MaxActive: configuration.Redis.Pool.MaxActive,
596+
IdleTimeout: configuration.Redis.Pool.IdleTimeout,
597+
TestOnBorrow: testOnBorrow,
598+
Wait: false, // if a connection is not available, proceed without cache.
560599
}
561600

562601
app.redis = pool

registry/handlers/app_test.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,29 @@ func TestAppDispatcher(t *testing.T) {
140140
// TestNewApp covers the creation of an application via NewApp with a
141141
// configuration.
142142
func TestNewApp(t *testing.T) {
143-
ctx := context.Background()
143+
144+
config := configuration.Configuration{
145+
Storage: configuration.Storage{
146+
"testdriver": nil,
147+
"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
148+
"enabled": false,
149+
}},
150+
},
151+
Auth: configuration.Auth{
152+
// For now, we simply test that new auth results in a viable
153+
// application.
154+
"silly": {
155+
"realm": "realm-test",
156+
"service": "service-test",
157+
},
158+
},
159+
}
160+
runAppWithConfig(t, config)
161+
}
162+
163+
// TestNewApp covers the creation of an application via NewApp with a
164+
// configuration(with redis).
165+
func TestNewAppWithRedis(t *testing.T) {
144166
config := configuration.Configuration{
145167
Storage: configuration.Storage{
146168
"testdriver": nil,
@@ -157,7 +179,38 @@ func TestNewApp(t *testing.T) {
157179
},
158180
},
159181
}
182+
config.Redis.Addr = "127.0.0.1:6379"
183+
config.Redis.DB = 0
184+
runAppWithConfig(t, config)
185+
}
160186

187+
// TestNewApp covers the creation of an application via NewApp with a
188+
// configuration(with redis sentinel cluster).
189+
func TestNewAppWithRedisSentinelCluster(t *testing.T) {
190+
config := configuration.Configuration{
191+
Storage: configuration.Storage{
192+
"testdriver": nil,
193+
"maintenance": configuration.Parameters{"uploadpurging": map[interface{}]interface{}{
194+
"enabled": false,
195+
}},
196+
},
197+
Auth: configuration.Auth{
198+
// For now, we simply test that new auth results in a viable
199+
// application.
200+
"silly": {
201+
"realm": "realm-test",
202+
"service": "service-test",
203+
},
204+
},
205+
}
206+
config.Redis.Addr = "192.168.0.11:26379,192.168.0.12:26379"
207+
config.Redis.DB = 0
208+
config.Redis.SentinelMasterSet = "mymaster"
209+
runAppWithConfig(t, config)
210+
}
211+
212+
func runAppWithConfig(t *testing.T, config configuration.Configuration) {
213+
ctx := context.Background()
161214
// Mostly, with this test, given a sane configuration, we are simply
162215
// ensuring that NewApp doesn't panic. We might want to tweak this
163216
// behavior.

vendor.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ gopkg.in/yaml.v2 v2.2.1
5151
rsc.io/letsencrypt e770c10b0f1a64775ae91d240407ce00d1a5bdeb https://github.com/dmcgowan/letsencrypt.git
5252
github.com/opencontainers/go-digest ea51bea511f75cfa3ef6098cc253c5c3609b037a # v1.0.0
5353
github.com/opencontainers/image-spec 67d2d5658fe0476ab9bf414cec164077ebff3920 # v1.0.2
54+
github.com/FZambia/sentinel 5585739eb4b6478aa30161866ccf9ce0ef5847c7 https://github.com/jeremyxu2010/sentinel.git

vendor/github.com/FZambia/sentinel/LICENSE

Lines changed: 201 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)