/
config.go
172 lines (150 loc) · 4.13 KB
/
config.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package config
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
sticfg "github.com/ipni/storetheindex/config"
"github.com/mitchellh/go-homedir"
)
// Config is used to load config files.
type Config struct {
Version int // config version.
Identity sticfg.Identity // peer identity.
Assignment Assignment // Indexer assignment settings.
Bootstrap sticfg.Bootstrap // Peers to connect to for gossip,
Daemon Daemon // daemon settings.
Logging Logging // logging configuration.,
Peering sticfg.Peering // peering service configuration.
}
const (
// DefaultPathName is the default config dir name.
DefaultPathName = ".assigner"
// DefaultPathRoot is the path to the default config dir location.
DefaultPathRoot = "~/" + DefaultPathName
// DefaultConfigFile is the filename of the configuration file.
DefaultConfigFile = "config"
// EnvDir is the environment variable used to change the path root.
EnvDir = "ASSIGNER_PATH"
Version = 1
)
// Filename returns the configuration file path given a configuration root
// directory. If the configuration root directory is empty, use the default.
func Filename(configRoot string) (string, error) {
return Path(configRoot, DefaultConfigFile)
}
// Marshal configuration with JSON.
func Marshal(value interface{}) ([]byte, error) {
// need to prettyprint, hence MarshalIndent, instead of Encoder.
return json.MarshalIndent(value, "", " ")
}
// Path returns the config file path relative to the configuration root. If an
// empty string is provided for `configRoot`, the default root is used. If
// configFile is an absolute path, then configRoot is ignored.
func Path(configRoot, configFile string) (string, error) {
if filepath.IsAbs(configFile) {
return filepath.Clean(configFile), nil
}
if configRoot == "" {
var err error
configRoot, err = PathRoot()
if err != nil {
return "", err
}
}
return filepath.Join(configRoot, configFile), nil
}
// PathRoot returns the default configuration root directory.
func PathRoot() (string, error) {
dir := os.Getenv(EnvDir)
if dir != "" {
return dir, nil
}
return homedir.Expand(DefaultPathRoot)
}
// Load reads the json-serialized config at the specified path.
func Load(filePath string) (*Config, error) {
var err error
if filePath == "" {
filePath, err = Filename("")
if err != nil {
return nil, err
}
}
f, err := os.Open(filePath)
if err != nil {
if os.IsNotExist(err) {
err = sticfg.ErrNotInitialized
}
return nil, err
}
defer f.Close()
// Populate with initial values in case they are not present in config.
cfg := Config{
Assignment: NewAssignment(),
Bootstrap: sticfg.NewBootstrap(),
Daemon: NewDaemon(),
Logging: NewLogging(),
Peering: sticfg.NewPeering(),
}
if err = json.NewDecoder(f).Decode(&cfg); err != nil {
return nil, err
}
cfg.populateUnset()
return &cfg, nil
}
// UpgradeConfig upgrades (or downgrades) the config file to the current
// version. If the config file is at the current version a backup is still
// created and the config rewritten with any unconfigured values set to their
// defaults.
func (c *Config) UpgradeConfig(filePath string) error {
prevName := fmt.Sprintf("%s.v%d", filePath, c.Version)
err := os.Rename(filePath, prevName)
if err != nil {
return err
}
c.Version = Version
err = c.Save(filePath)
if err != nil {
return err
}
return nil
}
// Save writes the json-serialized config to the specified path.
func (c *Config) Save(filePath string) error {
var err error
if filePath == "" {
filePath, err = Filename("")
if err != nil {
return err
}
}
err = os.MkdirAll(filepath.Dir(filePath), 0755)
if err != nil {
return err
}
f, err := os.Create(filePath)
if err != nil {
return err
}
defer f.Close()
buf, err := Marshal(c)
if err != nil {
return err
}
_, err = f.Write(buf)
return err
}
// String returns a pretty-printed json config.
func (c *Config) String() string {
b, err := json.MarshalIndent(c, "", " ")
if err != nil {
panic(err)
}
return string(b)
}
func (c *Config) populateUnset() {
c.Assignment.populateUnset()
c.Daemon.populateUnset()
c.Logging.populateUnset()
}