config.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package worker
  2. import (
  3. "errors"
  4. "os"
  5. "path/filepath"
  6. "github.com/BurntSushi/toml"
  7. cgv1 "github.com/containerd/cgroups/v3/cgroup1"
  8. cgv2 "github.com/containerd/cgroups/v3/cgroup2"
  9. units "github.com/docker/go-units"
  10. "github.com/imdario/mergo"
  11. )
  12. type providerEnum uint8
  13. const (
  14. provRsync providerEnum = iota
  15. provTwoStageRsync
  16. provCommand
  17. )
  18. func (p *providerEnum) UnmarshalText(text []byte) error {
  19. s := string(text)
  20. switch s {
  21. case `command`:
  22. *p = provCommand
  23. case `rsync`:
  24. *p = provRsync
  25. case `two-stage-rsync`:
  26. *p = provTwoStageRsync
  27. default:
  28. return errors.New("Invalid value to provierEnum")
  29. }
  30. return nil
  31. }
  32. // Config represents worker config options
  33. type Config struct {
  34. Global globalConfig `toml:"global"`
  35. Manager managerConfig `toml:"manager"`
  36. Server serverConfig `toml:"server"`
  37. Cgroup cgroupConfig `toml:"cgroup"`
  38. ZFS zfsConfig `toml:"zfs"`
  39. BtrfsSnapshot btrfsSnapshotConfig `toml:"btrfs_snapshot"`
  40. Docker dockerConfig `toml:"docker"`
  41. Include includeConfig `toml:"include"`
  42. MirrorsConf []mirrorConfig `toml:"mirrors"`
  43. Mirrors []mirrorConfig
  44. }
  45. type globalConfig struct {
  46. Name string `toml:"name"`
  47. LogDir string `toml:"log_dir"`
  48. MirrorDir string `toml:"mirror_dir"`
  49. Concurrent int `toml:"concurrent"`
  50. Interval int `toml:"interval"`
  51. Retry int `toml:"retry"`
  52. Timeout int `toml:"timeout"`
  53. // appended to the options generated by rsync_provider, but before mirror-specific options
  54. RsyncOptions []string `toml:"rsync_options"`
  55. ExecOnSuccess []string `toml:"exec_on_success"`
  56. ExecOnFailure []string `toml:"exec_on_failure"`
  57. // merged with mirror-specific options. make sure you know what you are doing!
  58. SuccessExitCodes []int `toml:"dangerous_global_success_exit_codes"`
  59. }
  60. type managerConfig struct {
  61. APIBase string `toml:"api_base"`
  62. // this option overrides the APIBase
  63. APIList []string `toml:"api_base_list"`
  64. CACert string `toml:"ca_cert"`
  65. // Token string `toml:"token"`
  66. }
  67. func (mc managerConfig) APIBaseList() []string {
  68. if len(mc.APIList) > 0 {
  69. return mc.APIList
  70. }
  71. return []string{mc.APIBase}
  72. }
  73. type serverConfig struct {
  74. Hostname string `toml:"hostname"`
  75. Addr string `toml:"listen_addr"`
  76. Port int `toml:"listen_port"`
  77. SSLCert string `toml:"ssl_cert"`
  78. SSLKey string `toml:"ssl_key"`
  79. }
  80. type cgroupConfig struct {
  81. Enable bool `toml:"enable"`
  82. BasePath string `toml:"base_path"`
  83. Group string `toml:"group"`
  84. Subsystem string `toml:"subsystem"`
  85. isUnified bool
  86. cgMgrV1 cgv1.Cgroup
  87. cgMgrV2 *cgv2.Manager
  88. }
  89. type dockerConfig struct {
  90. Enable bool `toml:"enable"`
  91. Volumes []string `toml:"volumes"`
  92. Options []string `toml:"options"`
  93. }
  94. type zfsConfig struct {
  95. Enable bool `toml:"enable"`
  96. Zpool string `toml:"zpool"`
  97. }
  98. type btrfsSnapshotConfig struct {
  99. Enable bool `toml:"enable"`
  100. SnapshotPath string `toml:"snapshot_path"`
  101. }
  102. type includeConfig struct {
  103. IncludeMirrors string `toml:"include_mirrors"`
  104. }
  105. type includedMirrorConfig struct {
  106. Mirrors []mirrorConfig `toml:"mirrors"`
  107. }
  108. type MemBytes int64
  109. // Set sets the value of the MemBytes by passing a string
  110. func (m *MemBytes) Set(value string) error {
  111. val, err := units.RAMInBytes(value)
  112. *m = MemBytes(val)
  113. return err
  114. }
  115. // Type returns the type
  116. func (m *MemBytes) Type() string {
  117. return "bytes"
  118. }
  119. // Value returns the value in int64
  120. func (m *MemBytes) Value() int64 {
  121. return int64(*m)
  122. }
  123. // UnmarshalJSON is the customized unmarshaler for MemBytes
  124. func (m *MemBytes) UnmarshalText(s []byte) error {
  125. val, err := units.RAMInBytes(string(s))
  126. *m = MemBytes(val)
  127. return err
  128. }
  129. type mirrorConfig struct {
  130. Name string `toml:"name"`
  131. Provider providerEnum `toml:"provider"`
  132. Upstream string `toml:"upstream"`
  133. Interval int `toml:"interval"`
  134. Retry int `toml:"retry"`
  135. Timeout int `toml:"timeout"`
  136. MirrorDir string `toml:"mirror_dir"`
  137. MirrorSubDir string `toml:"mirror_subdir"`
  138. LogDir string `toml:"log_dir"`
  139. Env map[string]string `toml:"env"`
  140. Role string `toml:"role"`
  141. // These two options over-write the global options
  142. ExecOnSuccess []string `toml:"exec_on_success"`
  143. ExecOnFailure []string `toml:"exec_on_failure"`
  144. // These two options are appended to the global options
  145. ExecOnSuccessExtra []string `toml:"exec_on_success_extra"`
  146. ExecOnFailureExtra []string `toml:"exec_on_failure_extra"`
  147. // will be merged with global option
  148. SuccessExitCodes []int `toml:"success_exit_codes"`
  149. Command string `toml:"command"`
  150. FailOnMatch string `toml:"fail_on_match"`
  151. SizePattern string `toml:"size_pattern"`
  152. UseIPv6 bool `toml:"use_ipv6"`
  153. UseIPv4 bool `toml:"use_ipv4"`
  154. ExcludeFile string `toml:"exclude_file"`
  155. Username string `toml:"username"`
  156. Password string `toml:"password"`
  157. RsyncNoTimeo bool `toml:"rsync_no_timeout"`
  158. RsyncTimeout int `toml:"rsync_timeout"`
  159. RsyncOptions []string `toml:"rsync_options"`
  160. RsyncOverride []string `toml:"rsync_override"`
  161. RsyncOverrideOnly bool `toml:"rsync_override_only"` // only use provided overridden options if true
  162. Stage1Profile string `toml:"stage1_profile"`
  163. MemoryLimit MemBytes `toml:"memory_limit"`
  164. DockerImage string `toml:"docker_image"`
  165. DockerVolumes []string `toml:"docker_volumes"`
  166. DockerOptions []string `toml:"docker_options"`
  167. SnapshotPath string `toml:"snapshot_path"`
  168. ChildMirrors []mirrorConfig `toml:"mirrors"`
  169. }
  170. // LoadConfig loads configuration
  171. func LoadConfig(cfgFile string) (*Config, error) {
  172. if _, err := os.Stat(cfgFile); err != nil {
  173. return nil, err
  174. }
  175. cfg := new(Config)
  176. if _, err := toml.DecodeFile(cfgFile, cfg); err != nil {
  177. logger.Errorf(err.Error())
  178. return nil, err
  179. }
  180. if cfg.Include.IncludeMirrors != "" {
  181. includedFiles, err := filepath.Glob(cfg.Include.IncludeMirrors)
  182. if err != nil {
  183. logger.Errorf(err.Error())
  184. return nil, err
  185. }
  186. for _, f := range includedFiles {
  187. var incMirCfg includedMirrorConfig
  188. if _, err := toml.DecodeFile(f, &incMirCfg); err != nil {
  189. logger.Errorf(err.Error())
  190. return nil, err
  191. }
  192. cfg.MirrorsConf = append(cfg.MirrorsConf, incMirCfg.Mirrors...)
  193. }
  194. }
  195. for _, m := range cfg.MirrorsConf {
  196. if err := recursiveMirrors(cfg, nil, m); err != nil {
  197. return nil, err
  198. }
  199. }
  200. return cfg, nil
  201. }
  202. func recursiveMirrors(cfg *Config, parent *mirrorConfig, mirror mirrorConfig) error {
  203. var curMir mirrorConfig
  204. if parent != nil {
  205. curMir = *parent
  206. }
  207. curMir.ChildMirrors = nil
  208. if err := mergo.Merge(&curMir, mirror, mergo.WithOverride); err != nil {
  209. return err
  210. }
  211. if mirror.ChildMirrors == nil {
  212. cfg.Mirrors = append(cfg.Mirrors, curMir)
  213. } else {
  214. for _, m := range mirror.ChildMirrors {
  215. if err := recursiveMirrors(cfg, &curMir, m); err != nil {
  216. return err
  217. }
  218. }
  219. }
  220. return nil
  221. }