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  }