/
env.go
128 lines (96 loc) · 2.72 KB
/
env.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Package env implements environment-related functionality.
package env
import (
"os"
"strings"
"time"
"github.com/azazeal/exit"
"github.com/gomodule/redigo/redis"
"go.uber.org/zap"
"github.com/soupedup/purgery/internal/common"
"github.com/soupedup/purgery/internal/safe"
)
// Config wraps
type Config struct {
// Addr holds the value of the ADDR environment variable.
Addr string
// APIKey holds the value of the API_KEY environment variable.
APIKey string
// PurgeryID holds the value of the PURGERY_ID environment value.
PurgeryID string
// Redis holds a reference to the Redis connection pool.
Redis *redis.Pool
// VarnishAddr holds the value of the VARNISH_ADDR environment value.
VarnishAddr string
}
var redisDialOpts = []redis.DialOption{
redis.DialConnectTimeout(5 * time.Second),
redis.DialReadTimeout(3 * time.Second),
redis.DialWriteTimeout(3 * time.Second),
}
func (cfg *Config) dialRedis(logger *zap.Logger, url string) bool {
logger.Info("dialing redis ...")
conn, err := redis.DialURL(url, redisDialOpts...)
if err != nil {
logger.Error("failed dialing redis.",
zap.Error(err))
return false
}
_ = conn.Close()
cfg.Redis = &redis.Pool{
MaxIdle: 5,
IdleTimeout: 10 * time.Minute,
Wait: true,
Dial: func() (redis.Conn, error) {
return redis.DialURL(url, redisDialOpts...)
},
}
logger.Debug("redis dialed.")
return true
}
func (cfg *Config) setAPIKey(logger *zap.Logger, key string) bool {
// we have to make sure that the length of the key doesn't exceed
if l := len(key); l > safe.MaxCompareLen {
logger.Error("the API key is too long.",
zap.Int("length", l),
zap.Int("max", safe.MaxCompareLen))
return false
}
cfg.APIKey = key
return true
}
var errLoadConfig = exit.Wrapf(common.ECLoadConfig,
"%/env: failed loading configuration",
common.AppName)
// LoadConfig returns a copy of the configuration it loads from the environment.
func LoadConfig(logger *zap.Logger) (*Config, error) {
logger.Info("loading configuration from the environment ...")
var (
cfg Config
redisURL string
apiKey string
)
ok := []bool{
fetch(logger, &cfg.Addr, "ADDR"),
fetch(logger, &apiKey, "API_KEY") &&
cfg.setAPIKey(logger, apiKey),
fetch(logger, &cfg.PurgeryID, "PURGERY_ID"),
fetch(logger, &redisURL, "REDIS_URL") &&
cfg.dialRedis(logger, redisURL),
fetch(logger, &cfg.VarnishAddr, "VARNISH_ADDR"),
}
for _, ok := range ok {
if !ok {
return nil, errLoadConfig
}
}
return &cfg, nil
}
func fetch(logger *zap.Logger, into *string, key string) (ok bool) {
*into = strings.TrimSpace(os.Getenv(key))
if ok = *into != ""; !ok {
logger.Error("a required environment variable is undefined or empty.",
zap.String("var", key))
}
return
}