-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.go
145 lines (122 loc) · 5.59 KB
/
validate.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package config
import (
"errors"
"fmt"
"net/url"
"strconv"
"strings"
"time"
)
var (
ValidLogLevels = [4]string{"TRACE", "DEBUG", "INFO", "ERROR"}
// restrict to max 1 month to guarantee constraint that
// metric partitioning routine never needs to create partitions
// spanning more than 2 calendar months
MaxMetricPartitioningPrefillPeriodDays = 28
)
// Validate validates the provided config
// returning a list of errors that can be unwrapped with `errors.Unwrap`
// or nil if the config is valid
func Validate(config Config) error {
var validLogLevel bool
var allErrs error
var err error
for _, validLevel := range ValidLogLevels {
if config.LogLevel == validLevel {
validLogLevel = true
break
}
}
if !validLogLevel {
allErrs = fmt.Errorf("invalid %s specified %s, supported values are %v", LOG_LEVEL_ENVIRONMENT_KEY, config.LogLevel, ValidLogLevels)
}
if err = validateHostURLMap(config.ProxyBackendHostURLMapRaw, false); err != nil {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s", PROXY_BACKEND_HOST_URL_MAP_ENVIRONMENT_KEY, config.ProxyBackendHostURLMapRaw), err)
}
if err = validateHostURLMap(config.ProxyPruningBackendHostURLMapRaw, true); err != nil {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s", PROXY_PRUNING_BACKEND_HOST_URL_MAP_ENVIRONMENT_KEY, config.ProxyPruningBackendHostURLMapRaw), err)
}
if err = validateShardRoutingBackendHostURLMap(config.ProxyShardBackendHostURLMapRaw); err != nil {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s", PROXY_SHARD_BACKEND_HOST_URL_MAP_ENVIRONMENT_KEY, config.ProxyShardBackendHostURLMapRaw), err)
}
if err = validateDefaultHostMapContainsHosts(
PROXY_PRUNING_BACKEND_HOST_URL_MAP_ENVIRONMENT_KEY,
config.ProxyBackendHostURLMapParsed,
config.ProxyPruningBackendHostURLMap,
); err != nil {
allErrs = errors.Join(allErrs, err)
}
_, err = strconv.Atoi(config.ProxyServicePort)
if err != nil {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s", PROXY_SERVICE_PORT_ENVIRONMENT_KEY, config.ProxyServicePort))
}
if config.MetricPartitioningPrefillPeriodDays > MaxMetricPartitioningPrefillPeriodDays || config.MetricPartitioningPrefillPeriodDays < 1 {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %d, must be non-zero and less than or equal to %d", METRIC_PARTITIONING_PREFILL_PERIOD_DAYS_ENVIRONMENT_KEY, config.MetricPartitioningPrefillPeriodDays, MaxMetricPartitioningPrefillPeriodDays))
}
if config.RedisEndpointURL == "" {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s, must not be empty", REDIS_ENDPOINT_URL_ENVIRONMENT_KEY, config.RedisEndpointURL))
}
if err := checkTTLConfig(config.CacheMethodHasBlockNumberParamTTL, CACHE_METHOD_HAS_BLOCK_NUMBER_PARAM_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}
if err := checkTTLConfig(config.CacheMethodHasBlockHashParamTTL, CACHE_METHOD_HAS_BLOCK_HASH_PARAM_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}
if err := checkTTLConfig(config.CacheStaticMethodTTL, CACHE_STATIC_METHOD_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}
if err := checkTTLConfig(config.CacheMethodHasTxHashParamTTL, CACHE_METHOD_HAS_TX_HASH_PARAM_TTL_ENVIRONMENT_KEY); err != nil {
allErrs = errors.Join(allErrs, err)
}
if strings.Contains(config.CachePrefix, ":") {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s, must not contain colon symbol", CACHE_PREFIX_ENVIRONMENT_KEY, config.CachePrefix))
}
if config.CachePrefix == "" {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s, must not be empty", CACHE_PREFIX_ENVIRONMENT_KEY, config.CachePrefix))
}
if err = validateHostnameToHeaderValueMap(config.HostnameToAccessControlAllowOriginValueMapRaw, true); err != nil {
allErrs = errors.Join(allErrs, fmt.Errorf("invalid %s specified %s", HOSTNAME_TO_ACCESS_CONTROL_ALLOW_ORIGIN_VALUE_MAP_ENVIRONMENT_KEY, config.HostnameToAccessControlAllowOriginValueMapRaw), err)
}
return allErrs
}
func checkTTLConfig(cacheTTL time.Duration, cacheTTLKey string) error {
if cacheTTL > 0 {
return nil
}
if cacheTTL == -1 {
return nil
}
return fmt.Errorf("invalid %s specified %s, must be greater than zero or -1", cacheTTLKey, cacheTTL)
}
// validateHostURLMap validates a raw backend host URL map, optionally allowing the map to be empty
func validateHostURLMap(raw string, allowEmpty bool) error {
_, err := ParseRawProxyBackendHostURLMap(raw)
if allowEmpty && errors.Is(err, ErrEmptyHostMap) {
err = nil
}
return err
}
// validateHostnameToHeaderValueMap validates a raw hostname to header value map, optionally allowing the map to be empty
func validateHostnameToHeaderValueMap(raw string, allowEmpty bool) error {
_, err := ParseRawHostnameToHeaderValueMap(raw)
if allowEmpty && errors.Is(err, ErrEmptyHostnameToHeaderValueMap) {
err = nil
}
return err
}
// validateShardRoutingBackendHostURLMap validates the host-backend url map for shard-based routing
func validateShardRoutingBackendHostURLMap(raw string) error {
_, err := ParseRawShardRoutingBackendHostURLMap(raw)
return err
}
// validateDefaultHostMapContainsHosts returns an error if there are hosts in hostMap that
// are not in defaultHostMap
// example: hosts in the pruning map should always have a default fallback backend
func validateDefaultHostMapContainsHosts(mapName string, defaultHostsMap, hostsMap map[string]url.URL) error {
for host := range hostsMap {
if _, found := defaultHostsMap[host]; !found {
return fmt.Errorf("host %s is in %s but not in default host map", host, mapName)
}
}
return nil
}