Skip to content

Commit

Permalink
Merge pull request #181 from conanca/master
Browse files Browse the repository at this point in the history
Support for Redis Sentinel
  • Loading branch information
cainlevy authored Aug 17, 2021
2 parents b050334 + 22927a2 commit 5913cfe
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## HEAD

### Added

* Support for Redis Sentinel

### Fixed

* Improved validation for AUTHN_URL and other ENV url values [#178]
Expand Down
7 changes: 6 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ func NewApp(cfg *Config, logger logrus.FieldLogger) (*App, error) {
}

var redis *redis.Client
if cfg.RedisURL != nil {
if cfg.RedisIsSentinelMode {
redis, err = dataRedis.NewSentinel(cfg.RedisSentinelMaster, cfg.RedisSentinelNodes, cfg.RedisSentinelPassword)
if err != nil {
return nil, errors.Wrap(err, "redis.NewSentinel")
}
} else if cfg.RedisURL != nil {
redis, err = dataRedis.New(cfg.RedisURL)
if err != nil {
return nil, errors.Wrap(err, "redis.New")
Expand Down
47 changes: 47 additions & 0 deletions app/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type Config struct {
PasswordChangeLogout bool
RefreshTokenTTL time.Duration
RedisURL *url.URL
RedisIsSentinelMode bool
RedisSentinelMaster string
RedisSentinelNodes string
RedisSentinelPassword string
DatabaseURL *url.URL
SessionCookieName string
OAuthCookieName string
Expand Down Expand Up @@ -229,6 +233,49 @@ var configurers = []configurer{
return err
},

// REDIS_IS_SENTINEL_MODE is a flag which indicates whether sentinel mode is used
// It could be setted to an empty string, so ignore err
// Example: "true" or "false"
func(c *Config) error {
val, err := requireEnv("REDIS_IS_SENTINEL_MODE")
if err == nil && val == "true" {
c.RedisIsSentinelMode = true
}
return nil
},

// REDIS_SENTINEL_MASTER is the master name of redis server in sentinel mode
// It could be setted to an empty string, so ignore err
func(c *Config) error {
val, err := requireEnv("REDIS_SENTINEL_MASTER")
if err == nil {
c.RedisSentinelMaster = val
}
return nil
},

// REDIS_SENTINEL_NODES is the address list of redis sentinel node in sentinel mode
// REDIS_SENTINEL_NODES contains some address splited by ","
// It could be setted to an empty string, so ignore err
// Example: "127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381"
func(c *Config) error {
val, err := requireEnv("REDIS_SENTINEL_NODES")
if err == nil {
c.RedisSentinelNodes = val
}
return nil
},

// REDIS_SENTINEL_PASSWORD is the password of master node in sentinel mode in redis
// It could be setted to an empty string, so ignore err
func(c *Config) error {
val, err := requireEnv("REDIS_SENTINEL_PASSWORD")
if err == nil {
c.RedisSentinelPassword = val
}
return nil
},

// USERNAME_IS_EMAIL is a truthy string ("t", "true", "yes") that enables the
// email validations for username fields. By default, usernames are just
// strings.
Expand Down
10 changes: 10 additions & 0 deletions app/data/redis/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"net/url"
"os"
"strings"

"github.com/go-redis/redis"
)
Expand All @@ -12,6 +13,15 @@ func New(url *url.URL) (*redis.Client, error) {
return newFromString(url.String())
}

func NewSentinel(redisSentinelMaster string, redisSentinelNodes string, redisSentinelPassword string) (*redis.Client, error) {
sentinelAddressSlice := strings.Split(redisSentinelNodes, ",")
return redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: redisSentinelMaster,
SentinelAddrs: sentinelAddressSlice,
Password: redisSentinelPassword,
}), nil
}

// TODO: move to _test
func TestDB() (*redis.Client, error) {
str, ok := os.LookupEnv("TEST_REDIS_URL")
Expand Down
2 changes: 1 addition & 1 deletion app/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func LookupURL(name string) (*url.URL, error) {
if val, ok := os.LookupEnv(name); ok {
url, err := url.ParseRequestURI(val)
if err == nil {
if url.Scheme != "http" && url.Scheme != "https" {
if url.Scheme != "http" && url.Scheme != "https" && url.Scheme != "mysql" && url.Scheme != "sqlite3" && url.Scheme != "postgres" && url.Scheme != "redis" {
return nil, fmt.Errorf("unsupported URL: %v", val)
}
return url, nil
Expand Down
39 changes: 38 additions & 1 deletion docs/config.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Server Configuration

* Core Settings: [`AUTHN_URL`](#authn_url)[`APP_DOMAINS`](#app_domains)[`HTTP_AUTH_USERNAME`](#http_auth_username)[`HTTP_AUTH_PASSWORD`](#http_auth_password)[`SECRET_KEY_BASE`](#secret_key_base)[`ENABLE_SIGNUP`](#enable_signup)
* Databases: [`DATABASE_URL`](#database_url)[`REDIS_URL`](#redis_url)
* Databases: [`DATABASE_URL`](#database_url)[`REDIS_URL`](#redis_url)[`REDIS_IS_SENTINEL_MODE`](#redis_is_sentinel_mode)[`REDIS_SENTINEL_MASTER`](#redis_sentinel_master)[`REDIS_SENTINEL_NODES`](#redis_sentinel_nodes)[`REDIS_SENTINEL_PASSWORD`](#redis_sentinel_password)
* Sessions:
[`ACCESS_TOKEN_TTL`](#access_token_ttl)[`REFRESH_TOKEN_TTL`](#refresh_token_ttl)[`SESSION_KEY_SALT`](#session_key_salt)[`DB_ENCRYPTION_KEY_SALT`](#db_encryption_key_salt)[`RSA_PRIVATE_KEY`](#rsa_private_key)[`SAME_SITE`](#same_site)
* OAuth Clients: [`FACEBOOK_OAUTH_CREDENTIALS`](#facebook_oauth_credentials)[`GITHUB_OAUTH_CREDENTIALS`](#github_oauth_credentials)[`GOOGLE_OAUTH_CREDENTIALS`](#google_oauth_credentials)[`DISCORD_OAUTH_CREDENTIALS`](#discord_oauth_credentials)[`MICROSOFT_OAUTH_CREDENTIALS`](#microsoft_oauth_credentials)
Expand Down Expand Up @@ -108,6 +108,43 @@ Format:

* `redis://username:password@host:port/database_number`

### `REDIS_IS_SENTINEL_MODE`

| | |
| --------- | --- |
| Required? | No |
| Value | boolean (`/^t|true|yes$/i`) |
| Default | `false` |

REDIS_IS_SENTINEL_MODE is a flag which indicates whether sentinel mode is used

### `REDIS_SENTINEL_MASTER`

| | |
| --------- | --- |
| Required? | No |
| Value | string |

REDIS_SENTINEL_MASTER is the master name of redis server in sentinel mode

### `REDIS_SENTINEL_NODES`

| | |
| --------- | --- |
| Required? | No |
| Value | string |

REDIS_SENTINEL_NODES is the node list of redis sentinel in sentinel mode. REDIS_SENTINEL_NODES contains some node splited by ",".

### `REDIS_SENTINEL_PASSWORD`

| | |
| --------- | --- |
| Required? | No |
| Value | string |

REDIS_SENTINEL_PASSWORD is the password of master node in sentinel mode in redis

## Sessions

### `ACCESS_TOKEN_TTL`
Expand Down

0 comments on commit 5913cfe

Please sign in to comment.