Skip to content

Commit

Permalink
Add support for time.Duration. Fixes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
ppacher committed Jan 5, 2021
1 parent a552940 commit d325ed4
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 13 deletions.
16 changes: 16 additions & 0 deletions conf/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package conf_test

import (
"testing"
"time"

"github.com/ppacher/system-conf/conf"
"github.com/stretchr/testify/assert"
Expand All @@ -28,6 +29,10 @@ func TestFileSpecDecode(t *testing.T) {
Name: "Rotate",
Type: conf.BoolType,
},
{
Name: "MaxAge",
Type: conf.DurationType,
},
},
}

Expand All @@ -39,6 +44,7 @@ func TestFileSpecDecode(t *testing.T) {
type TestLogFile struct {
Path string
RotateFile bool `option:"Rotate"`
MaxAge time.Duration
}

type Test struct {
Expand Down Expand Up @@ -76,6 +82,10 @@ func TestFileSpecDecode(t *testing.T) {
Name: "Rotate",
Value: "yes",
},
{
Name: "MaxAge",
Value: "10h",
},
},
},
{
Expand All @@ -89,6 +99,10 @@ func TestFileSpecDecode(t *testing.T) {
Name: "Rotate",
Value: "no",
},
{
Name: "MaxAge",
Value: "24h",
},
},
},
},
Expand All @@ -107,10 +121,12 @@ func TestFileSpecDecode(t *testing.T) {
{
Path: "/var/log/path1",
RotateFile: true,
MaxAge: time.Hour * 10,
},
{
Path: "/var/log/path2",
RotateFile: false,
MaxAge: time.Hour * 24,
},
},
}, target)
Expand Down
5 changes: 5 additions & 0 deletions conf/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
)

// OptionSpec describes an option
Expand Down Expand Up @@ -351,6 +352,10 @@ func checkValue(val string, optType OptionType) error {
if _, err := strconv.ParseInt(val, 0, 64); err != nil {
return ErrInvalidNumber
}
case DurationType, DurationSliceType:
if _, err := time.ParseDuration(val); err != nil {
return ErrInvalidDuration
}
}

return nil
Expand Down
6 changes: 6 additions & 0 deletions conf/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ func TestCheckValue(t *testing.T) {
{FloatSliceType, "0.1e10", nil},
{FloatType, ".INVALID", ErrInvalidFloat},
{FloatSliceType, "0.1eINVALID", ErrInvalidFloat},
{DurationType, "5m", nil},
{DurationType, "10h6s", nil},
{DurationType, "asdf", ErrInvalidDuration},
{DurationSliceType, "5m", nil},
{DurationSliceType, "10h6s", nil},
{DurationSliceType, "asdf", ErrInvalidDuration},

{StringType, "", nil}, // empty strings ARE VALID
}
Expand Down
20 changes: 13 additions & 7 deletions conf/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ type OptionType interface {

// All supported option types.
var (
StringType = option("string ", false)
StringSliceType = option("[]string ", true)
BoolType = option("bool ", false)
IntType = option("int ", false)
IntSliceType = option("[]int ", true)
FloatType = option("float ", false)
FloatSliceType = option("[]float ", true)
StringType = option("string ", false)
StringSliceType = option("[]string ", true)
BoolType = option("bool ", false)
IntType = option("int ", false)
IntSliceType = option("[]int ", true)
FloatType = option("float ", false)
FloatSliceType = option("[]float ", true)
DurationType = option("duration", false)
DurationSliceType = option("[]duration", true)
)

type optionType struct {
Expand Down Expand Up @@ -68,6 +70,10 @@ func TypeFromString(str string) *OptionType {
return &FloatType
case "[]float":
return &FloatSliceType
case "duration":
return &DurationType
case "[]duration":
return &DurationSliceType
}

return nil
Expand Down
31 changes: 25 additions & 6 deletions conf/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
"unicode"
)

Expand Down Expand Up @@ -297,6 +298,10 @@ func decodeBasic(data []string, specType OptionType, outVal reflect.Value) error
decodeType = reflect.TypeOf([]float64{})
case BoolType:
decodeType = reflect.TypeOf(bool(true))
case DurationType:
decodeType = reflect.TypeOf(time.Duration(0))
case DurationSliceType:
decodeType = reflect.TypeOf([]time.Duration{})
default:
return fmt.Errorf("unsupported type: %s", specType.String())
}
Expand Down Expand Up @@ -327,13 +332,27 @@ func decodeBool(data string, specType OptionType, outVal reflect.Value) error {
}

func decodeInt(data string, specType OptionType, outVal reflect.Value) error {
if specType != IntType && specType != IntSliceType {
return errors.New("invalid type")
}
var (
val int64
err error
)

val, err := strconv.ParseInt(data, 0, 64)
if err != nil {
return err
switch specType {
case DurationType, DurationSliceType:
d, err := time.ParseDuration(data)
if err != nil {
return err
}
val = int64(d)

case IntType, IntSliceType:
val, err = strconv.ParseInt(data, 0, 64)
if err != nil {
return err
}

default:
return errors.New("invalid type")
}

outVal.SetInt(val)
Expand Down
10 changes: 10 additions & 0 deletions conf/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package conf_test

import (
"testing"
"time"

"github.com/ppacher/system-conf/conf"
"github.com/stretchr/testify/assert"
Expand All @@ -14,6 +15,10 @@ func TestDecode(t *testing.T) {
err := conf.DecodeValues([]string{"10"}, conf.IntType, &x)
assert.NoError(t, err)
assert.Equal(t, 10, x)

err = conf.DecodeValues([]string{"10m"}, conf.DurationType, &x)
assert.NoError(t, err)
assert.Equal(t, int(time.Minute*10), x)
})

t.Run("float", func(t *testing.T) {
Expand Down Expand Up @@ -48,5 +53,10 @@ func TestDecode(t *testing.T) {
err = conf.DecodeValues([]string{"1.0", "2.1", "3.2"}, conf.FloatSliceType, &x)
assert.NoError(t, err)
assert.Equal(t, []float64{1.0, 2.1, 3.2}, x)

x = nil
err = conf.DecodeValues([]string{"10m5s"}, conf.DurationType, &x)
assert.NoError(t, err)
assert.Equal(t, time.Minute*10+time.Second*5, x)
})
}
1 change: 1 addition & 0 deletions conf/validation_errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var (
ErrInvalidBoolean = errors.New("invalid boolean value")
ErrInvalidFloat = errors.New("invalid floating point number)")
ErrInvalidNumber = errors.New("invalid number")
ErrInvalidDuration = errors.New("invalid duration")
ErrNoSections = errors.New("task does not contain any sections")
ErrUnknownSection = errors.New("unknown section")
ErrDropInSectionNotExists = errors.New("section defined in drop-in does not exist")
Expand Down

0 comments on commit d325ed4

Please sign in to comment.