rsync_provider.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package worker
  2. import (
  3. "errors"
  4. "strings"
  5. "time"
  6. )
  7. type rsyncConfig struct {
  8. name string
  9. rsyncCmd string
  10. upstreamURL, password, excludeFile string
  11. workingDir, logDir, logFile string
  12. useIPv6 bool
  13. interval time.Duration
  14. }
  15. // An RsyncProvider provides the implementation to rsync-based syncing jobs
  16. type rsyncProvider struct {
  17. baseProvider
  18. rsyncConfig
  19. options []string
  20. }
  21. func newRsyncProvider(c rsyncConfig) (*rsyncProvider, error) {
  22. // TODO: check config options
  23. if !strings.HasSuffix(c.upstreamURL, "/") {
  24. return nil, errors.New("rsync upstream URL should ends with /")
  25. }
  26. provider := &rsyncProvider{
  27. baseProvider: baseProvider{
  28. name: c.name,
  29. ctx: NewContext(),
  30. interval: c.interval,
  31. },
  32. rsyncConfig: c,
  33. }
  34. if c.rsyncCmd == "" {
  35. provider.rsyncCmd = "rsync"
  36. }
  37. options := []string{
  38. "-aHvh", "--no-o", "--no-g", "--stats",
  39. "--exclude", ".~tmp~/",
  40. "--delete", "--delete-after", "--delay-updates",
  41. "--safe-links", "--timeout=120", "--contimeout=120",
  42. }
  43. if c.useIPv6 {
  44. options = append(options, "-6")
  45. }
  46. if c.excludeFile != "" {
  47. options = append(options, "--exclude-from", c.excludeFile)
  48. }
  49. provider.options = options
  50. provider.ctx.Set(_WorkingDirKey, c.workingDir)
  51. provider.ctx.Set(_LogDirKey, c.logDir)
  52. provider.ctx.Set(_LogFileKey, c.logFile)
  53. return provider, nil
  54. }
  55. func (p *rsyncProvider) Upstream() string {
  56. return p.upstreamURL
  57. }
  58. func (p *rsyncProvider) Run() error {
  59. if err := p.Start(); err != nil {
  60. return err
  61. }
  62. return p.Wait()
  63. }
  64. func (p *rsyncProvider) Start() error {
  65. env := map[string]string{}
  66. if p.password != "" {
  67. env["RSYNC_PASSWORD"] = p.password
  68. }
  69. command := []string{p.rsyncCmd}
  70. command = append(command, p.options...)
  71. command = append(command, p.upstreamURL, p.WorkingDir())
  72. p.cmd = newCmdJob(command, p.WorkingDir(), env)
  73. if err := p.prepareLogFile(); err != nil {
  74. return err
  75. }
  76. if err := p.cmd.Start(); err != nil {
  77. return err
  78. }
  79. p.isRunning.Store(true)
  80. return nil
  81. }