forked from jpillora/webproc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.go
152 lines (135 loc) · 3.93 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
package agent
import (
"fmt"
"io/ioutil"
"os"
"time"
"github.com/naoina/toml"
)
type (
Log string
OnExit string
OnSave string
Duration time.Duration
)
const (
LogBoth Log = "both"
LogWebUI Log = "webui"
LogProxy Log = "proxy"
OnExitRestart OnExit = "restart"
OnExitIgnore OnExit = "ignore"
OnExitProxy OnExit = "proxy"
OnSaveRestart OnSave = "restart"
OnSaveContinue OnSave = "continue"
)
//Config is shared for both toml unmarshalling and opts CLI generation.
//Defaults are applied on ValidateConfig.
type Config struct {
Host string `opts:"help=listening interface, default=0.0.0.0"`
Port int `opts:"help=listening port, default=8080, env=PORT"`
User string `opts:"help=basic auth username, env=HTTP_USER"`
Pass string `opts:"help=basic auth password, env=HTTP_PASS"`
AllowedIPs []string `opts:"name=allow-ip, help=allow ip or cidr block"`
AllowedCountries []string `opts:"name=allow-country, short=y, help=allow ip range by 2-letter ISO country code"`
TrustProxy bool `opts:"help=trust proxy HTTP headers to provide remote ip address"`
ProgramArgs []string `opts:"mode=arg, name=arg, help=args can be either a command with arguments or a webproc file, min=1"`
Log Log `opts:"help=log mode (must be 'webui' or 'proxy' or 'both' defaults to 'both')"`
OnExit OnExit `opts:"help=process exit action, short=o, default=ignore"`
OnSave OnSave `opts:"help=config save action, short=s, default=restart"`
ConfigurationFiles []string `opts:"mode=flag, help=writable configuration file"`
RestartTimeout Duration `opts:"help=restart timeout controls when to perform a force kill, default=30s"`
MaxLines int `opts:"help=maximum number of log lines to show in webui, default=5000"`
}
func LoadConfig(path string, c *Config) error {
if info, err := os.Stat(path); os.IsNotExist(err) {
return fmt.Errorf("file not found")
} else if err != nil {
return fmt.Errorf("file error: %s", err)
} else if info.IsDir() {
return fmt.Errorf("file not specified")
}
cbuff, err := ioutil.ReadFile(path)
if err != nil {
return fmt.Errorf("file read error: %s", err)
}
//toml reader
if err := toml.Unmarshal(cbuff, c); err != nil {
return fmt.Errorf("toml syntax error: %s", err)
}
return nil
}
func ValidateConfig(c *Config) error {
if len(c.ProgramArgs) == 0 {
return fmt.Errorf("required property ProgramArgs is missing")
}
//apply defaults
if c.Host == "" {
c.Host = "0.0.0.0"
}
if c.Port == 0 {
c.Port = 8080
}
if c.MaxLines == 0 {
c.MaxLines = 5000
}
switch c.Log {
case LogBoth, LogProxy, LogWebUI:
//valid
case "":
c.Log = LogBoth
default:
return fmt.Errorf("log option must be 'both' 'proxy' or 'webui'")
}
switch c.OnExit {
case OnExitProxy, OnExitIgnore, OnExitRestart:
//valid
case "":
c.OnExit = OnExitIgnore
default:
return fmt.Errorf("on-exit option must be 'proxy' 'ignore' or 'restart'")
}
switch c.OnSave {
case OnSaveContinue, OnSaveRestart:
//valid
case "":
c.OnSave = OnSaveRestart
default:
return fmt.Errorf("on-restart option must be 'continue' or 'restart'")
}
if c.RestartTimeout <= 0 {
c.RestartTimeout = Duration(30 * time.Second)
}
return nil
}
// helper types
func (o *OnSave) UnmarshalTOML(data []byte) error {
*o = OnSave(quoted(data))
return nil
}
func (o *OnExit) UnmarshalTOML(data []byte) error {
*o = OnExit(quoted(data))
return nil
}
func (o *OnExit) Set(s string) error {
*o = OnExit(s)
return nil
}
func (o *OnExit) String() string {
return string(*o)
}
func (o *Log) UnmarshalTOML(data []byte) error {
*o = Log(quoted(data))
return nil
}
func (d *Duration) UnmarshalTOML(data []byte) error {
str := quoted(data)
d2, err := time.ParseDuration(str)
*d = Duration(d2)
return err
}
func quoted(data []byte) string {
if l := len(data); l >= 2 {
return string(data[1 : l-1])
}
return string(data)
}