-
Notifications
You must be signed in to change notification settings - Fork 15
/
config.go
162 lines (141 loc) · 3.79 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
package config
import (
"encoding/json"
"errors"
"os"
"path/filepath"
"github.com/mitchellh/go-homedir"
)
// Config is used to load config files.
type Config struct {
Identity Identity
Datastore Datastore
Ingest Ingest
ProviderServer ProviderServer
AdminServer AdminServer
Bootstrap Bootstrap
DirectAnnounce DirectAnnounce
DelegatedRouting DelegatedRouting
}
const (
// DefaultPathName is the default config dir name.
DefaultPathName = ".index-provider"
// 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 = "PROVIDER_PATH"
)
var (
ErrInitialized = errors.New("configuration file already exists")
ErrNotInitialized = errors.New("not initialized")
)
// 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 = ErrNotInitialized
}
return nil, err
}
defer f.Close()
// Populate with initial values in case they are not present in config.
cfg := Config{
Bootstrap: NewBootstrap(),
Datastore: NewDatastore(),
Ingest: NewIngest(),
AdminServer: NewAdminServer(),
ProviderServer: NewProviderServer(),
DirectAnnounce: NewDirectAnnounce(),
DelegatedRouting: NewDelegatedRouting(),
}
if err = json.NewDecoder(f).Decode(&cfg); err != nil {
return nil, err
}
// Replace any zero-values with defaults.
cfg.PopulateDefaults()
return &cfg, 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) PopulateDefaults() {
c.AdminServer.PopulateDefaults()
c.Datastore.PopulateDefaults()
c.Ingest.PopulateDefaults()
c.ProviderServer.PopulateDefaults()
c.DelegatedRouting.PopulateDefaults()
}