Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
//
// This allows you to Unmarshal JSON or YAML into:
//
// type myConfig struct {
// Server config.URL
// TLS config.TLS
// }
// type myConfig struct {
// Server config.URL
// TLS config.TLS
// }
//
// and have a net/url url.URL value available as cfg.Server.URL, and
// a TLS configuration as cfg.TLS.Config, with the config package taking
// care of parsing and validation.
//
package config
73 changes: 69 additions & 4 deletions env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
// Configuration can come from hardcoded defaults, environment, configuration
// files, and command line flags. To implement the usual precedence of:
//
// 1) built-in defaults (lowest)
// 2) environment parameters
// 3) configuration file parameters
// 4) command line parameters (highest)
// 1. built-in defaults (lowest)
// 2. environment parameters
// 3. configuration file parameters
// 4. command line parameters (highest)
//
// define defaults and command line bindings (with the flag package) first,
// followed by environment bindings with this package. Then load values from
Expand All @@ -30,6 +30,7 @@
package env

import (
"fmt"
"os"
"strconv"
"time"
Expand Down Expand Up @@ -155,3 +156,67 @@ func (d *durationValue) Set(s string) error {
func DurationVar(d *time.Duration, key string) error {
return Var((*durationValue)(d), key)
}

// ErrorHandling has advantage over bool as it can be extended
// to handle additional cases whereas bool cannot
type ErrorHandling int

const (
ContinueOnError ErrorHandling = 0
ExitOnError = 1
)

type envConfig struct {
errorHandling ErrorHandling
}

// NewConfig creates an envConfig object which allows handling of env variable parsing error
func NewConfig(errorHandling ErrorHandling) envConfig {
return envConfig{errorHandling: errorHandling}
}

// handleError handles envConfig on error behavior
func (e *envConfig) handleError(key string, err error) error {
if err != nil && e.errorHandling == ExitOnError {
fmt.Fprintf(os.Stderr, "%s encountered parsing error: %v\n", key, err)
os.Exit(1)
}

return err
}

func (e *envConfig) StringVar(v *string, key string) error {
return e.handleError(key, StringVar(v, key))
}

func (e *envConfig) BoolVar(v *bool, key string) error {
return e.handleError(key, BoolVar(v, key))
}

func (e *envConfig) IntVar(v *int, key string) error {
return e.handleError(key, IntVar(v, key))
}

func (e *envConfig) Int64Var(v *int64, key string) error {
return e.handleError(key, Int64Var(v, key))
}

func (e *envConfig) UintVar(v *uint, key string) error {
return e.handleError(key, UintVar(v, key))
}

func (e *envConfig) Uint64Var(v *uint64, key string) error {
return e.handleError(key, Uint64Var(v, key))
}

func (e *envConfig) Float64Var(v *float64, key string) error {
return e.handleError(key, Float64Var(v, key))
}

func (e *envConfig) DurationVar(v *time.Duration, key string) error {
return e.handleError(key, DurationVar(v, key))
}

func (e *envConfig) Var(v Value, key string) error {
return e.handleError(key, Var(v, key))
}
32 changes: 31 additions & 1 deletion env/env_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 Farsight Security, Inc.
* Copyright 2023 Farsight Security, Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
Expand All @@ -9,6 +9,7 @@
package env

import (
"github.com/farsightsec/go-config"
"os"
"testing"
"time"
Expand Down Expand Up @@ -59,3 +60,32 @@ func TestEnvMissing(t *testing.T) {
checkOK(t, IntVar(&i, "TEST_MISSING"), i == 10)
checkOK(t, BoolVar(&b, "TEST_MISSING"), b)
}

func TestEnvConfig(t *testing.T) {
var i int = 0
var i64 int64 = 0
var u uint = 0
var u64 uint64 = 0
var f64 float64 = 0
var s string = ""
var b bool = false
var d time.Duration = time.Second
var ss = config.String{}

ec := NewConfig(ContinueOnError)

checkOK(t, ec.IntVar(&i, "TEST_NUM"), i == 1048576)
checkOK(t, ec.Int64Var(&i64, "TEST_NUM"), i64 == 1048576)
checkOK(t, ec.UintVar(&u, "TEST_NUM"), u == 1048576)
checkOK(t, ec.Uint64Var(&u64, "TEST_NUM"), u64 == 1048576)
checkOK(t, ec.Float64Var(&f64, "TEST_NUM"), f64 == 1048576)
checkOK(t, ec.StringVar(&s, "TEST_NUM"), s == "1048576")
checkOK(t, ec.Var(&ss, "TEST_NUM"), ss.String() == "1048576")
checkOK(t, ec.DurationVar(&d, "TEST_DURATION"), d == 100*time.Millisecond)
checkOK(t, ec.BoolVar(&b, "TEST_BOOL_TRUE"), b)
checkOK(t, ec.BoolVar(&b, "TEST_BOOL_FALSE"), !b)

if ec.BoolVar(&b, "TEST_BOOL_INVALID") == nil {
t.Error("Expected parse error")
}
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/farsightsec/go-config

go 1.18

require gopkg.in/yaml.v2 v2.4.0
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
5 changes: 3 additions & 2 deletions tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
// conversion to and from string format.
//
// Supported string values are:
//
// "none": tls.NoClientCert (default)
// "request": tls.RequestClientCert
// "require": tls.RequireAnyClientCert
Expand Down Expand Up @@ -49,13 +50,13 @@ func (auth *TLSClientAuth) String() string {
type invalidClientAuthType string

func (i invalidClientAuthType) Error() string {
return fmt.Sprintf(`Invalid ClientAuthType "%s".`, i)
return fmt.Sprintf(`Invalid ClientAuthType "%s".`, string(i))
}

type invalidClientAuthTypeValue tls.ClientAuthType

func (i invalidClientAuthTypeValue) Error() string {
return fmt.Sprintf("Invalid ClientAuthType value %v", i)
return fmt.Sprintf("Invalid ClientAuthType value %v", int(i))
}

// Set satisfies the flag.Value interface.
Expand Down