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