-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathviper.go
117 lines (103 loc) · 3.55 KB
/
viper.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
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package config
import (
"fmt"
"os"
"strings"
"github.com/ava-labs/icm-services/utils"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
func NewConfig(v *viper.Viper) (Config, error) {
cfg, err := BuildConfig(v)
if err != nil {
return cfg, err
}
if err = cfg.Validate(); err != nil {
return Config{}, fmt.Errorf("failed to validate configuration: %w", err)
}
return cfg, nil
}
// Build the viper instance. The config file must be provided via the command line flag or environment variable.
// All config keys may be provided via config file or environment variable.
func BuildViper(fs *pflag.FlagSet) (*viper.Viper, error) {
v := viper.New()
v.AutomaticEnv()
// Map flag names to env var names. Flags are capitalized, and hyphens are replaced with underscores.
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
if err := v.BindPFlags(fs); err != nil {
return nil, err
}
// Verify that required flags are set
if !v.IsSet(ConfigFileKey) {
DisplayUsageText()
return nil, fmt.Errorf("config file not set")
}
filename := v.GetString(ConfigFileKey)
v.SetConfigFile(filename)
v.SetConfigType("json")
if err := v.ReadInConfig(); err != nil {
return nil, err
}
return v, nil
}
func SetDefaultConfigValues(v *viper.Viper) {
v.SetDefault(LogLevelKey, defaultLogLevel)
v.SetDefault(StorageLocationKey, defaultStorageLocation)
v.SetDefault(ProcessMissedBlocksKey, defaultProcessMissedBlocks)
v.SetDefault(APIPortKey, defaultAPIPort)
v.SetDefault(MetricsPortKey, defaultMetricsPort)
v.SetDefault(DBWriteIntervalSecondsKey, defaultIntervalSeconds)
v.SetDefault(
SignatureCacheSizeKey,
defaultSignatureCacheSize,
)
}
// BuildConfig constructs the relayer config using Viper.
// The following precedence order is used. Each item takes precedence over the item below it:
// 1. Flags
// 2. Environment variables
// a. Global account-private-key
// b. Chain-specific account-private-key
// 3. Config file
//
// Returns the Config
func BuildConfig(v *viper.Viper) (Config, error) {
// Set default values
SetDefaultConfigValues(v)
// Build the config from Viper
var cfg Config
if err := v.Unmarshal(&cfg); err != nil {
return cfg, fmt.Errorf("failed to unmarshal viper config: %w", err)
}
// Explicitly overwrite the configured account private key
// If account-private-key is set as a flag or environment variable,
// overwrite all destination subnet configurations to use that key
// In all cases, sanitize the key before setting it in the config
accountPrivateKey := v.GetString(AccountPrivateKeyKey)
for i, subnet := range cfg.DestinationBlockchains {
privateKey := subnet.AccountPrivateKey
if accountPrivateKey != "" {
privateKey = accountPrivateKey
cfg.overwrittenOptions = append(
cfg.overwrittenOptions,
fmt.Sprintf("destination-blockchain(%s).account-private-key", subnet.blockchainID),
)
// Otherwise, check for private keys suffixed with the chain ID and set it for that subnet
// Since the key is dynamic, this is only possible through environment variables
} else if privateKeyFromEnv := os.Getenv(fmt.Sprintf(
"%s_%s",
accountPrivateKeyEnvVarName,
subnet.BlockchainID,
)); privateKeyFromEnv != "" {
privateKey = privateKeyFromEnv
cfg.overwrittenOptions = append(cfg.overwrittenOptions, fmt.Sprintf(
"destination-blockchain(%s).account-private-key",
subnet.blockchainID),
)
}
cfg.DestinationBlockchains[i].AccountPrivateKey = utils.SanitizeHexString(privateKey)
}
return cfg, nil
}