github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/mdbd/generators.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "errors" 6 "io" 7 "net/http" 8 "os" 9 "strings" 10 11 "github.com/Cloud-Foundations/Dominator/lib/log" 12 "github.com/Cloud-Foundations/Dominator/lib/mdb" 13 ) 14 15 type makeGeneratorFunc func([]string, log.DebugLogger) (generator, error) 16 17 type sourceDriverFunc func(reader io.Reader, datacentre string, 18 logger log.Logger) (*mdb.Mdb, error) 19 20 // The generator interface generates an mdb from some source. 21 type generator interface { 22 Generate(datacentre string, logger log.Logger) (*mdb.Mdb, error) 23 } 24 25 // The eventGenerator interface generates an mdb from a source which has update 26 // events. 27 type eventGenerator interface { 28 generator 29 RegisterEventChannel(events chan<- struct{}) 30 } 31 32 func setupGenerators(reader io.Reader, drivers []driver, 33 logger log.DebugLogger) ([]generator, error) { 34 var generators []generator 35 scanner := bufio.NewScanner(reader) 36 for scanner.Scan() { 37 fields := strings.Fields(scanner.Text()) 38 if len(fields) < 1 || len(fields[0]) < 1 || fields[0][0] == '#' { 39 continue 40 } 41 driverName := fields[0] 42 args := fields[1:] 43 var drv *driver 44 for _, d := range drivers { 45 if d.name == driverName { 46 drv = &d 47 break 48 } 49 } 50 if drv == nil { 51 return nil, errors.New("unknown driver: " + driverName) 52 } 53 if len(args) < drv.minArgs { 54 return nil, errors.New("insufficient arguments for: " + driverName) 55 } 56 if drv.maxArgs >= 0 && len(args) > drv.maxArgs { 57 return nil, errors.New("too mant arguments for: " + driverName) 58 } 59 gen, err := drv.setupFunc(args, logger) 60 if err != nil { 61 return nil, err 62 } 63 generators = append(generators, gen) 64 } 65 if err := scanner.Err(); err != nil { 66 return nil, err 67 } 68 return generators, nil 69 } 70 71 // sourceGenerator implements the generator interface and generates an *mdb.Mdb 72 // from either a flat file or a URL. 73 type sourceGenerator struct { 74 driverFunc sourceDriverFunc // Parses the data from URL or flat file. 75 url string // The URL or path of the flat file. 76 } 77 78 func (s sourceGenerator) Generate(datacentre string, logger log.Logger) ( 79 *mdb.Mdb, error) { 80 return loadMdb(s.driverFunc, s.url, datacentre, logger) 81 } 82 83 func loadMdb(driverFunc sourceDriverFunc, url string, datacentre string, 84 logger log.Logger) (*mdb.Mdb, error) { 85 if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { 86 return loadHttpMdb(driverFunc, url, datacentre, logger) 87 } 88 file, err := os.Open(url) 89 if err != nil { 90 return nil, errors.New(("Error opening file " + err.Error())) 91 } 92 defer file.Close() 93 return driverFunc(bufio.NewReader(file), datacentre, logger) 94 } 95 96 func loadHttpMdb(driverFunc sourceDriverFunc, url string, datacentre string, 97 logger log.Logger) (*mdb.Mdb, error) { 98 response, err := http.Get(url) 99 if err != nil { 100 return nil, err 101 } 102 defer response.Body.Close() 103 if response.StatusCode != http.StatusOK { 104 return nil, errors.New("HTTP get failed") 105 } 106 return driverFunc(response.Body, datacentre, logger) 107 }