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  }