github.com/unirita/cuto@v0.9.8-0.20160830082821-aa6652f877b7/servant/config/config.go (about) 1 // Copyright 2015 unirita Inc. 2 // Created 2015/04/10 shanxia 3 4 package config 5 6 import ( 7 "fmt" 8 "io" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/BurntSushi/toml" 14 15 "github.com/unirita/cuto/console" 16 "github.com/unirita/cuto/util" 17 ) 18 19 const ( 20 defaultBindAddress = `0.0.0.0` 21 defaultBindPort = 2015 22 defaultHeartbeatSpanSec = 30 23 defaultMultiProc = 20 24 defaultDockerCommandPath = `` 25 defaultDisuseJoblog = 0 26 defaultJobDir = `jobscript` 27 defaultJoblogDir = `joblog` 28 defaultLogDir = `log` 29 defaultOutputLevel = `info` 30 defaultMaxSizeKB = 10240 31 defaultMaxGeneration = 2 32 defaultTimeoutSec = 1 33 ) 34 35 const dirName = "bin" 36 const fileName = "servant.ini" 37 const tag_CUTOROOT = "<CUTOROOT>" 38 39 // 設定情報のデフォルト値を設定する。 40 func DefaultServantConfig() *ServantConfig { 41 cfg := new(ServantConfig) 42 cfg.Sys.BindAddress = defaultBindAddress 43 cfg.Sys.BindPort = defaultBindPort 44 cfg.Job.HeartbeatSpanSec = defaultHeartbeatSpanSec 45 cfg.Job.MultiProc = defaultMultiProc 46 cfg.Job.DockerCommandPath = defaultDockerCommandPath 47 cfg.Job.DisuseJoblog = defaultDisuseJoblog 48 cfg.Dir.JobDir = defaultJobDir 49 cfg.Dir.JoblogDir = defaultJoblogDir 50 cfg.Dir.LogDir = defaultLogDir 51 cfg.Log.OutputLevel = defaultOutputLevel 52 cfg.Log.MaxSizeKB = defaultMaxSizeKB 53 cfg.Log.MaxGeneration = defaultMaxGeneration 54 cfg.Log.TimeoutSec = defaultTimeoutSec 55 56 return cfg 57 58 } 59 60 // サーバント設定情報 61 type ServantConfig struct { 62 Sys sysSection 63 Job jobSection 64 Dir dirSection 65 Log logSection 66 } 67 68 // サーバント設定のsysセクション 69 type sysSection struct { 70 BindAddress string `toml:"bind_address"` 71 BindPort int `toml:"bind_port"` 72 } 73 74 // サーバント設定のjobセクション 75 type jobSection struct { 76 MultiProc int `toml:"multi_proc"` 77 HeartbeatSpanSec int `toml:"heartbeat_span_sec"` 78 DockerCommandPath string `toml:"docker_command_path"` 79 DisuseJoblog int `toml:"disuse_joblog"` 80 } 81 82 // サーバント設定のdirセクション 83 type dirSection struct { 84 JoblogDir string `toml:"joblog_dir"` 85 JobDir string `toml:"job_dir"` 86 LogDir string `toml:"log_dir"` 87 } 88 89 // 設定ファイルのlogセクション 90 type logSection struct { 91 OutputLevel string `toml:"output_level"` 92 MaxSizeKB int `toml:"max_size_kb"` 93 MaxGeneration int `toml:"max_generation"` 94 TimeoutSec int `toml:"timeout_sec"` 95 } 96 97 var Servant *ServantConfig 98 var FilePath string 99 var RootPath string 100 101 func init() { 102 RootPath = util.GetRootPath() 103 FilePath = fileName 104 } 105 106 // 設定ファイルを読み込む 107 // 読み込みに失敗する場合はDefaultServantConfig関数でデフォルト値を設定する。 108 // 109 // 戻り値: 設定値を格納したServantConfig構造体オブジェクト 110 func ReadConfig(configPath string) *ServantConfig { 111 var err error 112 if len(configPath) > 0 { 113 FilePath = configPath 114 } 115 Servant, err = loadFile(FilePath) 116 if err != nil { 117 console.Display("CTS019E", err) 118 console.Display("CTS004W", FilePath) 119 Servant = DefaultServantConfig() 120 } 121 122 Servant.convertFullpath() 123 return Servant 124 } 125 126 // 設定をリロードする。 127 // 128 // 戻り値: 設定値を格納したServantConfig構造体オブジェクト 129 func ReloadConfig() *ServantConfig { 130 return ReadConfig(FilePath) 131 } 132 133 // 設定値のエラー検出を行う。 134 // 135 // 戻り値: エラー情報 136 func (c *ServantConfig) DetectError() error { 137 if c.Sys.BindPort < 0 || 65535 < c.Sys.BindPort { 138 return fmt.Errorf("sys.bind_port(%d) must be within the range 0 and 65535.", c.Sys.BindPort) 139 } 140 if c.Job.HeartbeatSpanSec <= 0 { 141 return fmt.Errorf("job.heartbeat_span_sec(%d) must not be 0 or less.", c.Job.HeartbeatSpanSec) 142 } 143 if c.Job.MultiProc <= 0 { 144 return fmt.Errorf("job.multi_proc(%d) must not be 0 or less.", c.Job.MultiProc) 145 } 146 if c.Log.MaxSizeKB <= 0 { 147 return fmt.Errorf("log.max_size_kb(%d) must not be 0 or less.", c.Log.MaxSizeKB) 148 } 149 if c.Log.MaxGeneration <= 0 { 150 return fmt.Errorf("log.max_generation(%d) must not be 0 or less.", c.Log.MaxGeneration) 151 } 152 153 return nil 154 } 155 156 func loadFile(filePath string) (*ServantConfig, error) { 157 f, err := os.Open(filePath) 158 if err != nil { 159 return nil, err 160 } 161 162 return loadReader(f) 163 } 164 165 func loadReader(reader io.Reader) (*ServantConfig, error) { 166 sc := new(ServantConfig) 167 if _, err := toml.DecodeReader(reader, sc); err != nil { 168 return nil, err 169 } 170 171 sc.replaceCutoroot() 172 173 return sc, nil 174 } 175 176 func (s *ServantConfig) replaceCutoroot() { 177 s.Dir.JoblogDir = strings.Replace(s.Dir.JoblogDir, tag_CUTOROOT, util.GetRootPath(), -1) 178 s.Dir.JobDir = strings.Replace(s.Dir.JobDir, tag_CUTOROOT, util.GetRootPath(), -1) 179 s.Dir.LogDir = strings.Replace(s.Dir.LogDir, tag_CUTOROOT, util.GetRootPath(), -1) 180 } 181 182 // 設定値の相対パスを絶対パスへ変換する。 183 func (s *ServantConfig) convertFullpath() { 184 if !filepath.IsAbs(s.Dir.JoblogDir) { 185 s.Dir.JoblogDir = filepath.Join(RootPath, s.Dir.JoblogDir) 186 } 187 if !filepath.IsAbs(s.Dir.JobDir) { 188 s.Dir.JobDir = filepath.Join(RootPath, s.Dir.JobDir) 189 } 190 if !filepath.IsAbs(s.Dir.LogDir) { 191 s.Dir.LogDir = filepath.Join(RootPath, s.Dir.LogDir) 192 } 193 }