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  }