github.com/govau/cf-common@v0.0.7/env/env.go (about)

     1  package env
     2  
     3  import (
     4  	"encoding/hex"
     5  	"fmt"
     6  	"strconv"
     7  )
     8  
     9  // Lookup must return the value for the environment variable with the given name
    10  // and whether or not it was found.
    11  type Lookup func(name string) (string, bool)
    12  
    13  // NoopLookup always returns false for the environment variable with the
    14  // given name. Useful as a fallback to return for an env lookup that may
    15  // not always be applicable, e.g. if not running in CloudFoundry, a user
    16  // provided service lookup won't be applicable.
    17  func NoopLookup(name string) (string, bool) {
    18  	return "", false
    19  }
    20  
    21  // VarSet provides methods to access environment variables from a list of Lookup
    22  // sources.
    23  type VarSet struct {
    24  	// sources are searched sequentially for a given environment variable.
    25  	sources []Lookup
    26  }
    27  
    28  // NewVarSet makes a new VarSet from opts.
    29  func NewVarSet(opts ...VarSetOpt) *VarSet {
    30  	v := &VarSet{sources: make([]Lookup, 0)}
    31  	for _, opt := range opts {
    32  		opt(v)
    33  	}
    34  	return v
    35  }
    36  
    37  // AppendSource adds s as another lookup source after all existing sources.
    38  func (v *VarSet) AppendSource(s Lookup) *VarSet {
    39  	v.sources = append(v.sources, s)
    40  	return v
    41  }
    42  
    43  // String gets the string environment variable with the given name, if set.
    44  // If not found, returns defaultVal.
    45  func (v *VarSet) String(name, defaultVal string) string {
    46  	rv, ok := v.Lookup(name)
    47  	if !ok {
    48  		return defaultVal
    49  	}
    50  	return rv
    51  }
    52  
    53  // MustString gets the string environment variable with the given name, if set.
    54  // It will panic with an error if it is not set.
    55  // If desired, callers can use IsVarNotFound when recovering from the panic in
    56  // order to check type of the error.
    57  func (v *VarSet) MustString(name string) string {
    58  	rv, ok := v.Lookup(name)
    59  	if !ok {
    60  		panic(&varNotFoundError{name: name})
    61  	}
    62  	return rv
    63  }
    64  
    65  // Bool gets the boolean environment variable with the given name, if set.
    66  // If not found, returns false.
    67  // If found and cannot parse, returns an error.
    68  func (v *VarSet) Bool(name string) (bool, error) {
    69  	val, ok := v.Lookup(name)
    70  	if !ok {
    71  		return false, nil
    72  	}
    73  	rv, err := strconv.ParseBool(val)
    74  	if err != nil {
    75  		return false, &varNotParsableError{name: name}
    76  	}
    77  	return rv, nil
    78  }
    79  
    80  // MustBool gets the boolean environment variable with the given name, if set.
    81  // If not set, false is returned. This matches behavior one would often see with
    82  // command line boolean arguments: if you don't set it, it defaults to false.
    83  // It will panic with an error if it is not a valid boolean.
    84  // If desired, callers can use IsVarNotParsable when recovering from the panic
    85  // in order to check type of the error.
    86  func (v *VarSet) MustBool(name string) bool {
    87  	val, ok := v.Lookup(name)
    88  	if !ok {
    89  		return false
    90  	}
    91  	rv, err := strconv.ParseBool(val)
    92  	if err != nil {
    93  		panic(&varNotParsableError{name: name})
    94  	}
    95  	return rv
    96  }
    97  
    98  // MustHexEncodedByteArray gets the hex-encoded environment variable with the
    99  // given name, if set.
   100  // It will panic with an error if it is not set if it is not a valid hex-encoded
   101  // string or if its length does not match decodedByteLength.
   102  // If desired, callers can use IsVarNotFound and IsVarNotParsable when
   103  // recovering from the panic in order to check type of the error.
   104  func (v *VarSet) MustHexEncodedByteArray(name string, decodedByteLength int) []byte {
   105  	rv, ok := v.Lookup(name)
   106  	if !ok {
   107  		panic(&varNotFoundError{name: name})
   108  	}
   109  	byteRv, err := hex.DecodeString(rv)
   110  	if err != nil {
   111  		panic(&varNotParsableError{name: name})
   112  	}
   113  	if len(byteRv) != decodedByteLength {
   114  		panic(&varNotParsableError{name: name})
   115  	}
   116  	return byteRv
   117  }
   118  
   119  // Lookup looks for a given name within all lookup sources in order.
   120  // If no variable is found, an empty string and false is returned.
   121  func (v *VarSet) Lookup(name string) (string, bool) {
   122  	for _, lookup := range v.sources {
   123  		rv, ok := lookup(name)
   124  		if ok {
   125  			return rv, true
   126  		}
   127  	}
   128  	return "", false
   129  }
   130  
   131  // IsSet looks for a given name within all lookup sources in order.
   132  // If found, true is returned, else false.
   133  func (v *VarSet) IsSet(name string) bool {
   134  	_, ok := v.Lookup(name)
   135  	return ok
   136  }
   137  
   138  // IsVarNotFound returns a boolean indicating whether the error is known to
   139  // report that an environment variable is not found.
   140  func IsVarNotFound(err error) bool {
   141  	_, ok := err.(*varNotFoundError)
   142  	return ok
   143  }
   144  
   145  // NewVarNotFoundErr makes a new error that indicates that an environment
   146  // variable is not found.
   147  func NewVarNotFoundErr(name string) error {
   148  	return &varNotFoundError{name: name}
   149  }
   150  
   151  // varNotFoundError is returned when a required environment variable cannot be
   152  // found.
   153  type varNotFoundError struct {
   154  	// name of the environment variable that was not found.
   155  	name string
   156  }
   157  
   158  // Error implements error.
   159  func (err *varNotFoundError) Error() string {
   160  	return fmt.Sprintf("environment variable with name %q not found", err.name)
   161  }
   162  
   163  // IsVarNotParsable returns a boolean indicating whether the error is known to
   164  // report that an environment variable is not parsable.
   165  func IsVarNotParsable(err error) bool {
   166  	_, ok := err.(*varNotParsableError)
   167  	return ok
   168  }
   169  
   170  // NewVarNotParsableErr makes a new error that indicates that an environment
   171  // variable is not parsable.
   172  func NewVarNotParsableErr(name string) error {
   173  	return &varNotParsableError{name: name}
   174  }
   175  
   176  // varNotParsableError is returned when a required environment variable cannot
   177  // be parsed.
   178  type varNotParsableError struct {
   179  	// name of the environment variable that was not parsable.
   180  	name string
   181  }
   182  
   183  // Error implements error.
   184  func (err *varNotParsableError) Error() string {
   185  	return fmt.Sprintf("environment variable with name %q could not be parsed", err.name)
   186  }