github.com/theliebeskind/genfig@v0.1.5-alpha/plugins/update_from_env.go (about)

     1  package plugins
     2  
     3  import (
     4  	"io"
     5  	"strings"
     6  	"text/template"
     7  
     8  	"github.com/theliebeskind/genfig/models"
     9  )
    10  
    11  type updateFromEnvPlugin struct {
    12  	s   models.SchemaMap
    13  	tpl *template.Template
    14  }
    15  
    16  var (
    17  	updateFromEnv = updateFromEnvPlugin{
    18  		s: models.SchemaMap{},
    19  		tpl: template.Must(template.
    20  			New("updateFromEnv").
    21  			Funcs(template.FuncMap{
    22  				"upper": strings.ToUpper,
    23  				"title": strings.Title,
    24  				// Remove root (usually "Config_") from env var name
    25  				"cleanPrefixEnv": func(s string) string {
    26  					return strings.Join(strings.Split(s, "_")[1:], "_")
    27  				},
    28  				// Converte an env var name to a Config path
    29  				"makePath": func(s string) string {
    30  					return strings.Join(strings.Split(s, "_")[1:], ".")
    31  				},
    32  				// Substitute []*type* with *type*Slice
    33  				"renameSlice": func(s string) string {
    34  					if strings.HasPrefix(s, "[]") {
    35  						return s[2:] + "Slice"
    36  					}
    37  					return s
    38  				},
    39  			}).
    40  			Parse(`import (
    41  	"encoding/json"
    42  	"fmt"
    43  	"os"
    44  	"strconv"
    45  )
    46  
    47  var (
    48  	_ = os.LookupEnv
    49  	_ = fmt.Sprintf
    50  	_ = json.Marshal
    51  )
    52  
    53  func (c *Config) UpdateFromEnv() []error {
    54  	var val string
    55  	_ = val
    56  	var exists bool
    57  	_ = exists
    58  	var errors = []error{}
    59  {{range $_, $v := .}}{{if not $v.IsStruct}}
    60  	if val, exists = os.LookupEnv("{{cleanPrefixEnv (upper $v.Path)}}"); exists { {{if eq $v.Content "string"}}
    61  		c.{{makePath $v.Path}} = val {{else}}
    62  		if v, err := parse{{title (renameSlice $v.Content)}}(val); err == nil {
    63  			c.{{makePath $v.Path}} = v
    64  		} else {
    65  			errors = append(errors, fmt.Errorf("Genfig: could not parse {{$v.Content}} from {{upper $v.Path}} ('%s')\n", val))
    66  		} {{end}}
    67  	}
    68  {{end}}{{end}}
    69  	if len(errors) == 0 {
    70  		return nil
    71  	} else {
    72  		return errors
    73  	}
    74  }
    75  
    76  // these are wrappers, so that they can
    77  // a) be referenced easily be the code generator and
    78  // b) be replaces easily by you (or me)
    79  func parseInt64(s string) (i int64, err error) {
    80  	i, err = strconv.ParseInt(s, 10, 0)
    81  	return
    82  }
    83  
    84  func parseFloat64(s string) (f float64, err error) {
    85  	f, err = strconv.ParseFloat(s, 0)
    86  	return
    87  }
    88  
    89  func parseBool(s string) (b bool, err error) {
    90  	b, err = strconv.ParseBool(s)
    91  	return
    92  }
    93  
    94  func parseStringSlice(s string) (a []string, err error) {
    95  	err = json.Unmarshal([]byte(s), &a)
    96  	return
    97  }
    98  
    99  func parseInt64Slice(s string) (a []int64, err error) {
   100  	err = json.Unmarshal([]byte(s), &a)
   101  	return
   102  }
   103  
   104  func parseFloat64Slice(s string) (a []float64, err error) {
   105  	err = json.Unmarshal([]byte(s), &a)
   106  	return
   107  }
   108  
   109  func parseInterfaceSlice(s string) (a []interface{}, err error) {
   110  	err = json.Unmarshal([]byte(s), &a)
   111  	return
   112  }
   113  `))}
   114  )
   115  
   116  func init() {
   117  	// "register" plugin
   118  	Plugins["update_from_env"] = &updateFromEnv
   119  }
   120  
   121  // GetInitCall returns the availibility and the string of the
   122  // function to be called on init
   123  func (p *updateFromEnvPlugin) GetInitCall() (string, bool) {
   124  	return "if errs := Current.UpdateFromEnv(); errs != nil {\n\tfmt.Println(errs)\n}", true
   125  }
   126  
   127  // SetSchemaMap sets the schema to be used when WriteTo is called
   128  func (p *updateFromEnvPlugin) SetSchemaMap(s models.SchemaMap) {
   129  	p.s = s
   130  }
   131  
   132  // WriteTo performs the acutal writing to a buffer (or io.Writer).
   133  // For this plugin, the template is simply "rendered" into the writer.
   134  func (p *updateFromEnvPlugin) WriteTo(w io.Writer) (l int64, err error) {
   135  	err = p.tpl.Execute(w, p.s)
   136  	return
   137  }