From 91c2b12205dd8ad35d9d754e364c7b2f01a19aba Mon Sep 17 00:00:00 2001 From: Alex Stockinger Date: Thu, 27 Jan 2022 21:13:45 +0100 Subject: Make default options for newly created networks configurable Signed-off-by: Alex Stockinger Co-authored-by: Sergei Egorov Co-authored-by: Cory Snider --- opts/opts.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ opts/opts_test.go | 31 ++++++++++++++++++++++ 2 files changed, 108 insertions(+) (limited to 'opts') diff --git a/opts/opts.go b/opts/opts.go index aacd30af08..dbcd028525 100644 --- a/opts/opts.go +++ b/opts/opts.go @@ -146,6 +146,83 @@ func (o *NamedListOpts) Name() string { return o.name } +// NamedMapMapOpts is a MapMapOpts with a configuration name. +// This struct is useful to keep reference to the assigned +// field name in the internal configuration struct. +type NamedMapMapOpts struct { + name string + MapMapOpts +} + +// NewNamedMapMapOpts creates a reference to a new NamedMapOpts struct. +func NewNamedMapMapOpts(name string, values map[string]map[string]string, validator ValidatorFctType) *NamedMapMapOpts { + return &NamedMapMapOpts{ + name: name, + MapMapOpts: *NewMapMapOpts(values, validator), + } +} + +// Name returns the name of the NamedListOpts in the configuration. +func (o *NamedMapMapOpts) Name() string { + return o.name +} + +// MapMapOpts holds a map of maps of values and a validation function. +type MapMapOpts struct { + values map[string]map[string]string + validator ValidatorFctType +} + +// Set validates if needed the input value and add it to the +// internal map, by splitting on '='. +func (opts *MapMapOpts) Set(value string) error { + if opts.validator != nil { + v, err := opts.validator(value) + if err != nil { + return err + } + value = v + } + rk, rv, found := strings.Cut(value, "=") + if !found { + return fmt.Errorf("invalid value %q for map option, should be root-key=key=value", value) + } + k, v, found := strings.Cut(rv, "=") + if !found { + return fmt.Errorf("invalid value %q for map option, should be root-key=key=value", value) + } + if _, ok := opts.values[rk]; !ok { + opts.values[rk] = make(map[string]string) + } + opts.values[rk][k] = v + return nil +} + +// GetAll returns the values of MapOpts as a map. +func (opts *MapMapOpts) GetAll() map[string]map[string]string { + return opts.values +} + +func (opts *MapMapOpts) String() string { + return fmt.Sprintf("%v", opts.values) +} + +// Type returns a string name for this Option type +func (opts *MapMapOpts) Type() string { + return "mapmap" +} + +// NewMapMapOpts creates a new MapMapOpts with the specified map of values and a validator. +func NewMapMapOpts(values map[string]map[string]string, validator ValidatorFctType) *MapMapOpts { + if values == nil { + values = make(map[string]map[string]string) + } + return &MapMapOpts{ + values: values, + validator: validator, + } +} + // MapOpts holds a map of values and a validation function. type MapOpts struct { values map[string]string diff --git a/opts/opts_test.go b/opts/opts_test.go index 850618e320..fe4b7f5ce5 100644 --- a/opts/opts_test.go +++ b/opts/opts_test.go @@ -334,3 +334,34 @@ func TestParseLink(t *testing.T) { assert.Check(t, is.Equal(alias, "bar")) }) } + +func TestMapMapOpts(t *testing.T) { + tmpMap := make(map[string]map[string]string) + validator := func(val string) (string, error) { + if strings.HasPrefix(val, "invalid-key=") { + return "", fmt.Errorf("invalid key %s", val) + } + return val, nil + } + o := NewMapMapOpts(tmpMap, validator) + o.Set("r1=k11=v11") + assert.Check(t, is.DeepEqual(tmpMap, map[string]map[string]string{"r1": {"k11": "v11"}})) + + o.Set("r2=k21=v21") + assert.Check(t, is.Len(tmpMap, 2)) + + if err := o.Set("invalid-syntax"); err == nil { + t.Error("invalid mapping syntax is not being caught") + } + + if err := o.Set("k=invalid-syntax"); err == nil { + t.Error("invalid value syntax is not being caught") + } + + o.Set("r1=k12=v12") + assert.Check(t, is.DeepEqual(tmpMap["r1"], map[string]string{"k11": "v11", "k12": "v12"})) + + if o.Set("invalid-key={\"k\":\"v\"}") == nil { + t.Error("validator is not being called") + } +} -- cgit v1.2.1