Skip to content
Merged
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
131 changes: 15 additions & 116 deletions configmap/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,152 +18,51 @@ package configmap

import (
"fmt"
"strconv"
"strings"
"time"

"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/configmap/parser"
)

// ParseFunc is a function taking ConfigMap data and applying a parse operation to it.
type ParseFunc func(map[string]string) error
type ParseFunc = parser.ParseFunc

// AsString passes the value at key through into the target, if it exists.
func AsString(key string, target *string) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
*target = raw
}
return nil
}
}
var AsString = parser.As[string]

// AsBool parses the value at key as a boolean into the target, if it exists.
func AsBool(key string, target *bool) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseBool(raw)
*target = val // If err != nil — this is always false.
return err
}
return nil
}
}
var AsBool = parser.As[bool]

// AsInt16 parses the value at key as an int16 into the target, if it exists.
func AsInt16(key string, target *int16) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseInt(raw, 10, 16)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = int16(val)
}
return nil
}
}
var AsInt16 = parser.As[int16]

// AsInt32 parses the value at key as an int32 into the target, if it exists.
func AsInt32(key string, target *int32) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseInt(raw, 10, 32)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = int32(val)
}
return nil
}
}
var AsInt32 = parser.As[int32]

// AsInt64 parses the value at key as an int64 into the target, if it exists.
func AsInt64(key string, target *int64) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseInt(raw, 10, 64)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = val
}
return nil
}
}
var AsInt64 = parser.As[int64]

// AsInt parses the value at key as an int into the target, if it exists.
func AsInt(key string, target *int) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.Atoi(raw)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = val
}
return nil
}
}
var AsInt = parser.As[int]

// AsUint16 parses the value at key as an uint16 into the target, if it exists.
func AsUint16(key string, target *uint16) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseUint(raw, 10, 16)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = uint16(val)
}
return nil
}
}
var AsUint16 = parser.As[uint16]

// AsUint32 parses the value at key as an uint32 into the target, if it exists.
func AsUint32(key string, target *uint32) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseUint(raw, 10, 32)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = uint32(val)
}
return nil
}
}
var AsUint32 = parser.As[uint32]

// AsUint64 parses the value at key as an uint32 into the target, if it exists.
var AsUint64 = parser.As[uint32]

// AsFloat64 parses the value at key as a float64 into the target, if it exists.
func AsFloat64(key string, target *float64) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := strconv.ParseFloat(raw, 64)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = val
}
return nil
}
}
var AsFloat64 = parser.As[float64]

// AsDuration parses the value at key as a time.Duration into the target, if it exists.
func AsDuration(key string, target *time.Duration) ParseFunc {
return func(data map[string]string) error {
if raw, ok := data[key]; ok {
val, err := time.ParseDuration(raw)
if err != nil {
return fmt.Errorf("failed to parse %q: %w", key, err)
}
*target = val
}
return nil
}
}
var AsDuration = parser.As[time.Duration]

// AsStringSet parses the value at key as a sets.Set[string] (split by ',') into the target, if it exists.
func AsStringSet(key string, target *sets.Set[string]) ParseFunc {
Expand Down
109 changes: 6 additions & 103 deletions configmap/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package configmap

import (
"testing"
"time"

"github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/api/resource"
Expand All @@ -27,18 +26,8 @@ import (
)

type testConfig struct {
str string
toggle bool
i16 int16
i32 int32
i64 int64
u16 uint16
u32 uint32
i int
f64 float64
dur time.Duration
set sets.Set[string]
qua *resource.Quantity
set sets.Set[string]
qua *resource.Quantity

nsn types.NamespacedName
onsn *types.NamespacedName
Expand All @@ -57,16 +46,6 @@ func TestParse(t *testing.T) {
}{{
name: "all good",
data: map[string]string{
"test-string": "foo.bar",
"test-bool": "true",
"test-int16": "6",
"test-int32": "1",
"test-int64": "2",
"test-uint16": "5",
"test-uint32": "3",
"test-int": "4",
"test-float64": "1.0",
"test-duration": "1m",
"test-set": "a,b,c, d",
"test-quantity": "500m",

Expand All @@ -77,18 +56,8 @@ func TestParse(t *testing.T) {
"test-dict.k1": "v1",
},
want: testConfig{
str: "foo.bar",
toggle: true,
i16: 6,
i32: 1,
i64: 2,
u16: 5,
u32: 3,
f64: 1.0,
i: 4,
dur: time.Minute,
set: sets.New[string]("a", "b", "c", "d"),
qua: &fiveHundredM,
set: sets.New("a", "b", "c", "d"),
qua: &fiveHundredM,
nsn: types.NamespacedName{
Name: "some-name",
Namespace: "some-namespace",
Expand All @@ -105,67 +74,11 @@ func TestParse(t *testing.T) {
}, {
name: "respect defaults",
conf: testConfig{
str: "foo.bar",
toggle: true,
i32: 1,
i64: 2,
f64: 1.0,
i: 4,
dur: time.Minute,
qua: &fiveHundredM,
qua: &fiveHundredM,
},
want: testConfig{
str: "foo.bar",
toggle: true,
i32: 1,
i64: 2,
f64: 1.0,
i: 4,
dur: time.Minute,
qua: &fiveHundredM,
qua: &fiveHundredM,
},
}, {
name: "junk bool fails",
data: map[string]string{
"test-bool": "foo",
},
expectErr: true,
}, {
name: "int32 error",
data: map[string]string{
"test-int32": "foo",
},
expectErr: true,
}, {
name: "int64 error",
data: map[string]string{
"test-int64": "foo",
},
expectErr: true,
}, {
name: "uint32 error",
data: map[string]string{
"test-uint32": "foo",
},
expectErr: true,
}, {
name: "int error",
data: map[string]string{
"test-int": "foo",
},
expectErr: true,
}, {
name: "float64 error",
data: map[string]string{
"test-float64": "foo",
},
expectErr: true,
}, {
name: "duration error",
data: map[string]string{
"test-duration": "foo",
},
expectErr: true,
}, {
name: "quantity error",
data: map[string]string{
Expand Down Expand Up @@ -201,16 +114,6 @@ func TestParse(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if err := Parse(test.data,
AsString("test-string", &test.conf.str),
AsBool("test-bool", &test.conf.toggle),
AsInt16("test-int16", &test.conf.i16),
AsInt32("test-int32", &test.conf.i32),
AsInt64("test-int64", &test.conf.i64),
AsUint16("test-uint16", &test.conf.u16),
AsUint32("test-uint32", &test.conf.u32),
AsInt("test-int", &test.conf.i),
AsFloat64("test-float64", &test.conf.f64),
AsDuration("test-duration", &test.conf.dur),
AsStringSet("test-set", &test.conf.set),
AsQuantity("test-quantity", &test.conf.qua),
AsNamespacedName("test-namespaced-name", &test.conf.nsn),
Expand Down
Loading
Loading