checkers/redis/redis.go
package redischk import ( "crypto/tls" "fmt" "time" "github.com/go-redis/redis") const ( // RedisDefaultSetValue will be used if the "Set" check method is enabled // and "RedisSetOptions.Value" is _not_ set. RedisDefaultSetValue = "go-health/redis-check") // RedisConfig is used for configuring the go-redis check.//// "Auth" is _required_; redis connection/auth config.//// "Ping" is optional; the most basic check method, performs a `.Ping()` on the client.//// "Get" is optional; perform a "GET" on a key; refer to the "RedisGetOptions" docs for details.//// "Set" is optional; perform a "SET" on a key; refer to the "RedisSetOptions" docs for details.//// Note: At least _one_ check method must be set/enabled; you can also enable// _all_ of the check methods (ie. perform a ping, set this key and now try to// retrieve that key).type RedisConfig struct { Auth *RedisAuthConfig Ping bool Set *RedisSetOptions Get *RedisGetOptions} // RedisAuthConfig defines how to connect to redis.type RedisAuthConfig struct { Addr string // `host:port` format Password string // leave blank if no password DB int // leave unset if no specific db TLS *tls.Config // TLS config in case we are using in-transit encryption} // RedisSetOptions contains attributes that can alter the behavior of the redis// "SET" check.//// "Key" is _required_; the name of the key we are attempting to "SET".//// "Value" is optional; what the value should hold; if not set, it will be set// to "RedisDefaultSetValue".//// "Expiration" is optional; if set, a TTL will be attached to the key.type RedisSetOptions struct { Key string Value string Expiration time.Duration} // RedisGetOptions contains attributes that can alter the behavior of the redis// "GET" check.//// "Key" is _required_; the name of the key that we are attempting to "GET".//// "Expect" is optional; optionally verify that the value for the key matches// the Expect value.//// "NoErrorMissingKey" is optional; by default, the "GET" check will error if// the key we are fetching does not exist; flip this bool if that is normal/expected/ok.type RedisGetOptions struct { Key string Expect string NoErrorMissingKey bool} // Redis implements the ICheckable interfacetype Redis struct { Config *RedisConfig client *redis.Client} // NewRedis creates a new "go-redis/redis" checker that can be used w/ "AddChecks()".func NewRedis(cfg *RedisConfig) (*Redis, error) { // validate settings if err := validateRedisConfig(cfg); err != nil { return nil, fmt.Errorf("Unable to validate redis config: %v", err) } // try to connect c := redis.NewClient(&redis.Options{ Addr: cfg.Auth.Addr, Password: cfg.Auth.Password, // no password set DB: cfg.Auth.DB, // use default DB TLSConfig: cfg.Auth.TLS, }) if _, err := c.Ping().Result(); err != nil { return nil, fmt.Errorf("Unable to establish initial connection to redis: %v", err) } return &Redis{ Config: cfg, client: c, }, nil} // Status is used for performing a redis check against a dependency; it satisfies// the "ICheckable" interface.Method `Redis.Status` has 6 return statements (exceeds 4 allowed).
Method `Redis.Status` has a Cognitive Complexity of 22 (exceeds 20 allowed). Consider refactoring.func (r *Redis) Status() (interface{}, error) { if r.Config.Ping { if _, err := r.client.Ping().Result(); err != nil { return nil, fmt.Errorf("Ping failed: %v", err) } } if r.Config.Set != nil { err := r.client.Set(r.Config.Set.Key, r.Config.Set.Value, r.Config.Set.Expiration).Err() if err != nil { return nil, fmt.Errorf("Unable to complete set: %v", err) } } if r.Config.Get != nil { val, err := r.client.Get(r.Config.Get.Key).Result() if err != nil { if err == redis.Nil { if !r.Config.Get.NoErrorMissingKey { return nil, fmt.Errorf("Unable to complete get: '%v' not found", r.Config.Get.Key) } } else { return nil, fmt.Errorf("Unable to complete get: %v", err) } } if r.Config.Get.Expect != "" { if r.Config.Get.Expect != val { return nil, fmt.Errorf("Unable to complete get: returned value '%v' does not match expected value '%v'", val, r.Config.Get.Expect) } } } return nil, nil} Function `validateRedisConfig` has 7 return statements (exceeds 4 allowed).func validateRedisConfig(cfg *RedisConfig) error { if cfg == nil { return fmt.Errorf("Main config cannot be nil") } if cfg.Auth == nil { return fmt.Errorf("Auth config cannot be nil") } if cfg.Auth.Addr == "" { return fmt.Errorf("Addr string must be set in auth config") } // At least one check method must be set if !cfg.Ping && cfg.Set == nil && cfg.Get == nil { return fmt.Errorf("At minimum, either cfg.Ping, cfg.Set or cfg.Get must be set") } // If .Set is set, verify that at minimum .Key is set if cfg.Set != nil { if cfg.Set.Key == "" { return fmt.Errorf("If cfg.Set is used, cfg.Set.Key must be set") } if cfg.Set.Value == "" { cfg.Set.Value = RedisDefaultSetValue } } // If .Get is set, verify that at minimum .Key is set if cfg.Get != nil { if cfg.Get.Key == "" { return fmt.Errorf("If cfg.Get is used, cfg.Get.Key must be set") } } return nil}