Add db param to sentinel configurations
Signed-off-by: Shakar Bakr <5h4k4r.b4kr@gmail.com>
This commit is contained in:
		
							parent
							
								
									8afb047e01
								
							
						
					
					
						commit
						bded36d88f
					
				|  | @ -86,8 +86,7 @@ When using the redis store, specify `--session-store-type=redis` as well as the | ||||||
| `--redis-connection-url=redis://host[:port][/db-number]`. | `--redis-connection-url=redis://host[:port][/db-number]`. | ||||||
| 
 | 
 | ||||||
| You may also configure the store for Redis Sentinel. In this case, you will want to use the | You may also configure the store for Redis Sentinel. In this case, you will want to use the | ||||||
| `--redis-use-sentinel=true` flag, as well as configure the flags `--redis-sentinel-master-name` | `--redis-use-sentinel=true` flag, as well as configure the flags `--redis-sentinel-master-name`, `--redis-sentinel-db` and `--redis-sentinel-connection-urls` appropriately. | ||||||
| and `--redis-sentinel-connection-urls` appropriately. |  | ||||||
| 
 | 
 | ||||||
| Redis Cluster is available to be the backend store as well. To leverage it, you will need to set the | Redis Cluster is available to be the backend store as well. To leverage it, you will need to set the | ||||||
| `--redis-use-cluster=true` flag, and configure the flags `--redis-cluster-connection-urls` appropriately. | `--redis-use-cluster=true` flag, and configure the flags `--redis-cluster-connection-urls` appropriately. | ||||||
|  |  | ||||||
|  | @ -151,6 +151,7 @@ func NewFlagSet() *pflag.FlagSet { | ||||||
| 	flagSet.String("redis-username", "", "Redis username. Applicable for Redis configurations where ACL has been configured. Will override any username set in `--redis-connection-url`") | 	flagSet.String("redis-username", "", "Redis username. Applicable for Redis configurations where ACL has been configured. Will override any username set in `--redis-connection-url`") | ||||||
| 	flagSet.String("redis-password", "", "Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url`") | 	flagSet.String("redis-password", "", "Redis password. Applicable for all Redis configurations. Will override any password set in `--redis-connection-url`") | ||||||
| 	flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-connection-urls to use this feature") | 	flagSet.Bool("redis-use-sentinel", false, "Connect to redis via sentinels. Must set --redis-sentinel-master-name and --redis-sentinel-connection-urls to use this feature") | ||||||
|  | 	flagSet.Int("redis-sentinel-db", 0, "Redis sentinel database number. Used in conjunction with --redis-use-sentinel") | ||||||
| 	flagSet.String("redis-sentinel-password", "", "Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password`") | 	flagSet.String("redis-sentinel-password", "", "Redis sentinel password. Used only for sentinel connection; any redis node passwords need to use `--redis-password`") | ||||||
| 	flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjunction with --redis-use-sentinel") | 	flagSet.String("redis-sentinel-master-name", "", "Redis sentinel master name. Used in conjunction with --redis-use-sentinel") | ||||||
| 	flagSet.String("redis-ca-path", "", "Redis custom CA path") | 	flagSet.String("redis-ca-path", "", "Redis custom CA path") | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ type RedisStoreOptions struct { | ||||||
| 	Username               string   `flag:"redis-username" cfg:"redis_username"` | 	Username               string   `flag:"redis-username" cfg:"redis_username"` | ||||||
| 	Password               string   `flag:"redis-password" cfg:"redis_password"` | 	Password               string   `flag:"redis-password" cfg:"redis_password"` | ||||||
| 	UseSentinel            bool     `flag:"redis-use-sentinel" cfg:"redis_use_sentinel"` | 	UseSentinel            bool     `flag:"redis-use-sentinel" cfg:"redis_use_sentinel"` | ||||||
|  | 	SentinelDB             int      `flag:"redis-sentinel-db" cfg:"redis_sentinel_db"` | ||||||
| 	SentinelPassword       string   `flag:"redis-sentinel-password" cfg:"redis_sentinel_password"` | 	SentinelPassword       string   `flag:"redis-sentinel-password" cfg:"redis_sentinel_password"` | ||||||
| 	SentinelMasterName     string   `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name"` | 	SentinelMasterName     string   `flag:"redis-sentinel-master-name" cfg:"redis_sentinel_master_name"` | ||||||
| 	SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls"` | 	SentinelConnectionURLs []string `flag:"redis-sentinel-connection-urls" cfg:"redis_sentinel_connection_urls"` | ||||||
|  |  | ||||||
|  | @ -119,6 +119,7 @@ func buildSentinelClient(opts options.RedisStoreOptions) (Client, error) { | ||||||
| 		SentinelAddrs:    addrs, | 		SentinelAddrs:    addrs, | ||||||
| 		SentinelPassword: opts.SentinelPassword, | 		SentinelPassword: opts.SentinelPassword, | ||||||
| 		Username:         opts.Username, | 		Username:         opts.Username, | ||||||
|  | 		DB:               opts.SentinelDB, | ||||||
| 		Password:         opts.Password, | 		Password:         opts.Password, | ||||||
| 		TLSConfig:        opt.TLSConfig, | 		TLSConfig:        opt.TLSConfig, | ||||||
| 		ConnMaxIdleTime:  time.Duration(opts.IdleTimeout) * time.Second, | 		ConnMaxIdleTime:  time.Duration(opts.IdleTimeout) * time.Second, | ||||||
|  |  | ||||||
|  | @ -93,6 +93,29 @@ var _ = Describe("Redis SessionStore Tests", func() { | ||||||
| 					return nil | 					return nil | ||||||
| 				}, | 				}, | ||||||
| 			) | 			) | ||||||
|  | 
 | ||||||
|  | 			Context("with custom sentinel DB", func() { | ||||||
|  | 				tests.RunSessionStoreTests( | ||||||
|  | 					func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) { | ||||||
|  | 						// Set the sentinel connection URL with custom DB
 | ||||||
|  | 						sentinelAddr := redisProtocol + ms.Addr() | ||||||
|  | 						opts.Type = options.RedisSessionStoreType | ||||||
|  | 						opts.Redis.SentinelConnectionURLs = []string{sentinelAddr} | ||||||
|  | 						opts.Redis.UseSentinel = true | ||||||
|  | 						opts.Redis.SentinelMasterName = ms.MasterInfo().Name | ||||||
|  | 						opts.Redis.SentinelDB = 1 | ||||||
|  | 
 | ||||||
|  | 						// Capture the session store so that we can close the client
 | ||||||
|  | 						var err error | ||||||
|  | 						ss, err = NewRedisSessionStore(opts, cookieOpts) | ||||||
|  | 						return ss, err | ||||||
|  | 					}, | ||||||
|  | 					func(d time.Duration) error { | ||||||
|  | 						mr.FastForward(d) | ||||||
|  | 						return nil | ||||||
|  | 					}, | ||||||
|  | 				) | ||||||
|  | 			}) | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		Context("with cluster", func() { | 		Context("with cluster", func() { | ||||||
|  | @ -170,6 +193,30 @@ var _ = Describe("Redis SessionStore Tests", func() { | ||||||
| 						return nil | 						return nil | ||||||
| 					}, | 					}, | ||||||
| 				) | 				) | ||||||
|  | 
 | ||||||
|  | 				Context("with custom sentinel DB and password", func() { | ||||||
|  | 					tests.RunSessionStoreTests( | ||||||
|  | 						func(opts *options.SessionOptions, cookieOpts *options.Cookie) (sessionsapi.SessionStore, error) { | ||||||
|  | 							// Set the sentinel connection URL with custom DB and password
 | ||||||
|  | 							sentinelAddr := redisProtocol + ms.Addr() | ||||||
|  | 							opts.Type = options.RedisSessionStoreType | ||||||
|  | 							opts.Redis.SentinelConnectionURLs = []string{sentinelAddr} | ||||||
|  | 							opts.Redis.UseSentinel = true | ||||||
|  | 							opts.Redis.SentinelMasterName = ms.MasterInfo().Name | ||||||
|  | 							opts.Redis.Password = redisPassword | ||||||
|  | 							opts.Redis.SentinelDB = 2 | ||||||
|  | 
 | ||||||
|  | 							// Capture the session store so that we can close the client
 | ||||||
|  | 							var err error | ||||||
|  | 							ss, err = NewRedisSessionStore(opts, cookieOpts) | ||||||
|  | 							return ss, err | ||||||
|  | 						}, | ||||||
|  | 						func(d time.Duration) error { | ||||||
|  | 							mr.FastForward(d) | ||||||
|  | 							return nil | ||||||
|  | 						}, | ||||||
|  | 					) | ||||||
|  | 				}) | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			Context("with cluster", func() { | 			Context("with cluster", func() { | ||||||
|  | @ -271,4 +318,114 @@ var _ = Describe("Redis SessionStore Tests", func() { | ||||||
| 			Expect(opts).To(BeNil()) | 			Expect(opts).To(BeNil()) | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
|  | 
 | ||||||
|  | 	Describe("Sentinel DB Configuration", func() { | ||||||
|  | 		var mr *miniredis.Miniredis | ||||||
|  | 		var ms *minisentinel.Sentinel | ||||||
|  | 
 | ||||||
|  | 		BeforeEach(func() { | ||||||
|  | 			var err error | ||||||
|  | 			mr, err = miniredis.Run() | ||||||
|  | 			Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 			ms = minisentinel.NewSentinel(mr) | ||||||
|  | 			Expect(ms.Start()).To(Succeed()) | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		AfterEach(func() { | ||||||
|  | 			mr.Close() | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		It("should use default DB 0 when SentinelDB is not set", func() { | ||||||
|  | 			opts := options.RedisStoreOptions{ | ||||||
|  | 				SentinelConnectionURLs: []string{"redis://" + ms.Addr()}, | ||||||
|  | 				UseSentinel:            true, | ||||||
|  | 				SentinelMasterName:     ms.MasterInfo().Name, | ||||||
|  | 				SentinelDB:             0, // Default value
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			client, err := NewRedisClient(opts) | ||||||
|  | 			Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 			Expect(client).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Verify we can create a session store successfully
 | ||||||
|  | 			sessionStore := &SessionStore{Client: client} | ||||||
|  | 			Expect(sessionStore).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Clean up
 | ||||||
|  | 			if closer, ok := client.(interface{ Close() error }); ok { | ||||||
|  | 				Expect(closer.Close()).To(Succeed()) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		It("should use custom SentinelDB value when set", func() { | ||||||
|  | 			testDB := 5 | ||||||
|  | 			opts := options.RedisStoreOptions{ | ||||||
|  | 				SentinelConnectionURLs: []string{"redis://" + ms.Addr()}, | ||||||
|  | 				UseSentinel:            true, | ||||||
|  | 				SentinelMasterName:     ms.MasterInfo().Name, | ||||||
|  | 				SentinelDB:             testDB, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			client, err := NewRedisClient(opts) | ||||||
|  | 			Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 			Expect(client).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Verify we can create a session store successfully
 | ||||||
|  | 			sessionStore := &SessionStore{Client: client} | ||||||
|  | 			Expect(sessionStore).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Clean up
 | ||||||
|  | 			if closer, ok := client.(interface{ Close() error }); ok { | ||||||
|  | 				Expect(closer.Close()).To(Succeed()) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		It("should work with maximum valid DB number", func() { | ||||||
|  | 			maxDB := 15 // Redis supports DB 0-15 by default
 | ||||||
|  | 			opts := options.RedisStoreOptions{ | ||||||
|  | 				SentinelConnectionURLs: []string{"redis://" + ms.Addr()}, | ||||||
|  | 				UseSentinel:            true, | ||||||
|  | 				SentinelMasterName:     ms.MasterInfo().Name, | ||||||
|  | 				SentinelDB:             maxDB, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			client, err := NewRedisClient(opts) | ||||||
|  | 			Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 			Expect(client).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Verify we can create a session store successfully
 | ||||||
|  | 			sessionStore := &SessionStore{Client: client} | ||||||
|  | 			Expect(sessionStore).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Clean up
 | ||||||
|  | 			if closer, ok := client.(interface{ Close() error }); ok { | ||||||
|  | 				Expect(closer.Close()).To(Succeed()) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		It("should handle SentinelDB with authentication", func() { | ||||||
|  | 			testDB := 3 | ||||||
|  | 			testPassword := "test-password" | ||||||
|  | 			opts := options.RedisStoreOptions{ | ||||||
|  | 				SentinelConnectionURLs: []string{"redis://" + ms.Addr()}, | ||||||
|  | 				UseSentinel:            true, | ||||||
|  | 				SentinelMasterName:     ms.MasterInfo().Name, | ||||||
|  | 				SentinelDB:             testDB, | ||||||
|  | 				Password:               testPassword, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			client, err := NewRedisClient(opts) | ||||||
|  | 			Expect(err).ToNot(HaveOccurred()) | ||||||
|  | 			Expect(client).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Verify we can create a session store successfully
 | ||||||
|  | 			sessionStore := &SessionStore{Client: client} | ||||||
|  | 			Expect(sessionStore).ToNot(BeNil()) | ||||||
|  | 
 | ||||||
|  | 			// Clean up
 | ||||||
|  | 			if closer, ok := client.(interface{ Close() error }); ok { | ||||||
|  | 				Expect(closer.Close()).To(Succeed()) | ||||||
|  | 			} | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
| }) | }) | ||||||
|  |  | ||||||
|  | @ -346,6 +346,56 @@ var _ = Describe("Sessions", func() { | ||||||
| 			}, | 			}, | ||||||
| 			errStrings: []string{}, | 			errStrings: []string{}, | ||||||
| 		}), | 		}), | ||||||
|  | 		Entry("connect successfully to sentinel redis with custom DB", &redisStoreTableInput{ | ||||||
|  | 			useSentinel:     true, | ||||||
|  | 			setSentinelAddr: true, | ||||||
|  | 			setMasterName:   true, | ||||||
|  | 
 | ||||||
|  | 			opts: &options.Options{ | ||||||
|  | 				Session: options.SessionOptions{ | ||||||
|  | 					Type: options.RedisSessionStoreType, | ||||||
|  | 					Redis: options.RedisStoreOptions{ | ||||||
|  | 						UseSentinel: true, | ||||||
|  | 						SentinelDB:  1, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			errStrings: []string{}, | ||||||
|  | 		}), | ||||||
|  | 		Entry("connect successfully to sentinel redis with custom DB and password", &redisStoreTableInput{ | ||||||
|  | 			password:        "abcdef123", | ||||||
|  | 			useSentinel:     true, | ||||||
|  | 			setSentinelAddr: true, | ||||||
|  | 			setMasterName:   true, | ||||||
|  | 
 | ||||||
|  | 			opts: &options.Options{ | ||||||
|  | 				Session: options.SessionOptions{ | ||||||
|  | 					Type: options.RedisSessionStoreType, | ||||||
|  | 					Redis: options.RedisStoreOptions{ | ||||||
|  | 						Password:    "abcdef123", | ||||||
|  | 						UseSentinel: true, | ||||||
|  | 						SentinelDB:  5, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			errStrings: []string{}, | ||||||
|  | 		}), | ||||||
|  | 		Entry("connect successfully to sentinel redis with maximum DB number", &redisStoreTableInput{ | ||||||
|  | 			useSentinel:     true, | ||||||
|  | 			setSentinelAddr: true, | ||||||
|  | 			setMasterName:   true, | ||||||
|  | 
 | ||||||
|  | 			opts: &options.Options{ | ||||||
|  | 				Session: options.SessionOptions{ | ||||||
|  | 					Type: options.RedisSessionStoreType, | ||||||
|  | 					Redis: options.RedisStoreOptions{ | ||||||
|  | 						UseSentinel: true, | ||||||
|  | 						SentinelDB:  15, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			errStrings: []string{}, | ||||||
|  | 		}), | ||||||
| 		Entry("failed connection to sentinel redis with wrong password", &redisStoreTableInput{ | 		Entry("failed connection to sentinel redis with wrong password", &redisStoreTableInput{ | ||||||
| 			password:        "abcdef123", | 			password:        "abcdef123", | ||||||
| 			useSentinel:     true, | 			useSentinel:     true, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue