cronsun/conf/conf.go

176 lines
3.2 KiB
Go
Raw Normal View History

2017-01-04 09:27:36 +00:00
package conf
import (
2017-02-16 06:36:25 +00:00
"flag"
2017-01-04 09:27:36 +00:00
"path"
"time"
client "github.com/coreos/etcd/clientv3"
"github.com/fsnotify/fsnotify"
2017-01-04 09:27:36 +00:00
"sunteng/commons/confutil"
"sunteng/commons/db/imgo"
2017-03-08 09:00:22 +00:00
"sunteng/commons/event"
2017-01-04 09:27:36 +00:00
"sunteng/commons/log"
)
var (
2017-02-16 06:36:25 +00:00
confFile = flag.String("conf",
"conf/files/base.json", "config file path")
2017-01-09 02:32:14 +00:00
Config = new(Conf)
initialized bool
watcher *fsnotify.Watcher
exitChan = make(chan struct{})
2017-01-04 09:27:36 +00:00
)
func Init() error {
2017-01-09 02:32:14 +00:00
if initialized {
return nil
}
2017-02-16 06:36:25 +00:00
flag.Parse()
if err := Config.parse(); err != nil {
2017-01-04 09:27:36 +00:00
return err
}
if err := Config.watch(); err != nil {
return err
2017-01-04 09:27:36 +00:00
}
2017-01-09 02:32:14 +00:00
initialized = true
2017-01-04 09:27:36 +00:00
return nil
}
type Conf struct {
Node string // node 进程路径
Proc string // 当前执行任务路径
2017-01-09 09:13:56 +00:00
Cmd string // cmd 路径
2017-03-09 09:43:08 +00:00
Once string // 马上执行任务路径
2017-01-09 09:13:56 +00:00
Group string // 节点分组
2017-01-05 02:37:48 +00:00
2017-01-06 08:59:31 +00:00
Ttl int64 // 节点超时时间,单位秒
ReqTimeout int // 请求超时时间,单位秒
2017-03-06 09:34:30 +00:00
// 执行任务信息过期时间,单位秒
// 0 为不过期
ProcTtl int64
2017-01-05 12:35:41 +00:00
2017-03-03 02:31:12 +00:00
Log *log.Config
2017-01-04 09:27:36 +00:00
Etcd client.Config
Mgo *imgo.Config
2017-01-09 02:32:14 +00:00
Web webConfig
2017-03-03 02:31:12 +00:00
Security *Security
2017-01-09 02:32:14 +00:00
}
type webConfig struct {
BindAddr string
UIDir string
2017-01-04 09:27:36 +00:00
}
2017-01-12 08:35:30 +00:00
2017-03-03 02:31:12 +00:00
type Security struct {
// 是不开启安全选项
// true 开启
// 所执行的命令只能是机器上的脚本,仅支持配置项里的扩展名
// 执行用户只能选择配置里的用户
// false 关闭,命令和用户可以用动填写
Open bool
// 配置执行用户
Users []string
// 支持的执行的脚本扩展名
Ext []string
}
2017-01-12 08:35:30 +00:00
// 返回前后包含斜杆的 /a/b/ 的前缀
func cleanKeyPrefix(p string) string {
p = path.Clean(p)
if p[0] != '/' {
p = "/" + p
}
p += "/"
return p
}
func (c *Conf) parse() error {
err := confutil.LoadExtendConf(*confFile, c)
if err != nil {
return err
}
if c.Etcd.DialTimeout > 0 {
c.Etcd.DialTimeout *= time.Second
}
log.InitConf(c.Log)
c.Cmd = cleanKeyPrefix(c.Cmd)
c.Node = cleanKeyPrefix(c.Node)
c.Proc = cleanKeyPrefix(c.Proc)
c.Group = cleanKeyPrefix(c.Group)
return nil
}
func (c *Conf) watch() error {
var err error
watcher, err = fsnotify.NewWatcher()
if err != nil {
return err
}
go func() {
duration := 3 * time.Second
timer, update := time.NewTimer(duration), false
for {
select {
case <-exitChan:
return
case event := <-watcher.Events:
// 保存文件时会产生多个事件
if event.Op&(fsnotify.Write|fsnotify.Chmod) > 0 {
update = true
}
timer.Reset(duration)
case <-timer.C:
if update {
c.reload()
2017-03-08 09:00:22 +00:00
event.Emit(event.WAIT, nil)
update = false
}
timer.Reset(duration)
case err := <-watcher.Errors:
log.Warnf("config watcher err: %v", err)
}
}
}()
return watcher.Add(*confFile)
}
// 重新加载配置项
// 注:与系统资源相关的选项不生效,需重启程序
// Etcd
// Mgo
// Web
func (c *Conf) reload() {
cf := new(Conf)
if err := cf.parse(); err != nil {
log.Warn("config file reload err:", err.Error())
return
}
2017-03-09 09:43:08 +00:00
// etcd key 选项需要重启
cf.Node, cf.Proc, cf.Cmd, cf.Once, cf.Group = c.Node, c.Proc, c.Cmd, c.Once, c.Group
*c = *cf
log.Noticef("config file[%s] reload success", *confFile)
return
}
func Exit(i interface{}) {
close(exitChan)
if watcher != nil {
watcher.Close()
}
}