github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/pkg/discovery/file/file.go (about) 1 package file 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "strings" 7 "time" 8 9 "github.com/docker/docker/pkg/discovery" 10 ) 11 12 // Discovery is exported 13 type Discovery struct { 14 heartbeat time.Duration 15 path string 16 } 17 18 func init() { 19 Init() 20 } 21 22 // Init is exported 23 func Init() { 24 discovery.Register("file", &Discovery{}) 25 } 26 27 // Initialize is exported 28 func (s *Discovery) Initialize(path string, heartbeat time.Duration, ttl time.Duration, _ map[string]string) error { 29 s.path = path 30 s.heartbeat = heartbeat 31 return nil 32 } 33 34 func parseFileContent(content []byte) []string { 35 var result []string 36 for _, line := range strings.Split(strings.TrimSpace(string(content)), "\n") { 37 line = strings.TrimSpace(line) 38 // Ignoring line starts with # 39 if strings.HasPrefix(line, "#") { 40 continue 41 } 42 // Inlined # comment also ignored. 43 if strings.Contains(line, "#") { 44 line = line[0:strings.Index(line, "#")] 45 // Trim additional spaces caused by above stripping. 46 line = strings.TrimSpace(line) 47 } 48 for _, ip := range discovery.Generate(line) { 49 result = append(result, ip) 50 } 51 } 52 return result 53 } 54 55 func (s *Discovery) fetch() (discovery.Entries, error) { 56 fileContent, err := ioutil.ReadFile(s.path) 57 if err != nil { 58 return nil, fmt.Errorf("failed to read '%s': %v", s.path, err) 59 } 60 return discovery.CreateEntries(parseFileContent(fileContent)) 61 } 62 63 // Watch is exported 64 func (s *Discovery) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-chan error) { 65 ch := make(chan discovery.Entries) 66 errCh := make(chan error) 67 ticker := time.NewTicker(s.heartbeat) 68 69 go func() { 70 defer close(errCh) 71 defer close(ch) 72 73 // Send the initial entries if available. 74 currentEntries, err := s.fetch() 75 if err != nil { 76 errCh <- err 77 } else { 78 ch <- currentEntries 79 } 80 81 // Periodically send updates. 82 for { 83 select { 84 case <-ticker.C: 85 newEntries, err := s.fetch() 86 if err != nil { 87 errCh <- err 88 continue 89 } 90 91 // Check if the file has really changed. 92 if !newEntries.Equals(currentEntries) { 93 ch <- newEntries 94 } 95 currentEntries = newEntries 96 case <-stopCh: 97 ticker.Stop() 98 return 99 } 100 } 101 }() 102 103 return ch, errCh 104 } 105 106 // Register is exported 107 func (s *Discovery) Register(addr string) error { 108 return discovery.ErrNotImplemented 109 }