From 5a39a168f70a2300eabb100037b2e27d96fe832a Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Thu, 17 Mar 2016 14:08:29 +0100 Subject: [PATCH] pkg/types: add IgnoreUnknown arg and logic This commit adds a struct type CommonArgs that is to be embedded in every plugin's argument struct. It contains a field named "IgnoreUnknown" which will be parsed as a boolean and can be provided to ignore unknown arguments passed to the plugin. --- pkg/types/args.go | 45 +++++++++++++++++++++++++++++-- plugins/ipam/host-local/config.go | 1 + 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pkg/types/args.go b/pkg/types/args.go index 3c0fd88e..c4e3c55b 100644 --- a/pkg/types/args.go +++ b/pkg/types/args.go @@ -21,6 +21,39 @@ import ( "strings" ) +// UnmarshallableBool typedef for builtin bool +// because builtin type's methods can't be declared +type UnmarshallableBool bool + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// Returns boolean true if the string is "1" or "[Tt]rue" +// Returns boolean false if the string is "0" or "[Ff]alse" +func (b *UnmarshallableBool) UnmarshalText(data []byte) error { + s := strings.ToLower(string(data)) + switch s { + case "1", "true": + *b = true + case "0", "false": + *b = false + default: + return fmt.Errorf("Boolean unmarshal error: invalid input %s", s) + } + return nil +} + +// CommonArgs contains the IgnoreUnknown argument +// and must be embedded by all Arg structs +type CommonArgs struct { + IgnoreUnknown UnmarshallableBool `json:"ignoreunknown,omitempty"` +} + +// getKeyField is a helper function to receive Values +// Values that represent a pointer to a struct +func getKeyField(keyString string, v reflect.Value) reflect.Value { + return v.Elem().FieldByName(keyString) +} + +// LoadArgs parses args from a string in the form "K=V;K2=V2;..." func LoadArgs(args string, container interface{}) error { if args == "" { return nil @@ -29,6 +62,7 @@ func LoadArgs(args string, container interface{}) error { containerValue := reflect.ValueOf(container) pairs := strings.Split(args, ";") + unknownArgs := []string{} for _, pair := range pairs { kv := strings.Split(pair, "=") if len(kv) != 2 { @@ -36,15 +70,22 @@ func LoadArgs(args string, container interface{}) error { } keyString := kv[0] valueString := kv[1] - keyField := containerValue.Elem().FieldByName(keyString) + keyField := GetKeyField(keyString, containerValue) if !keyField.IsValid() { - return fmt.Errorf("ARGS: invalid key %q", keyString) + unknownArgs = append(unknownArgs, pair) + continue } + u := keyField.Addr().Interface().(encoding.TextUnmarshaler) err := u.UnmarshalText([]byte(valueString)) if err != nil { return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err) } } + + isIgnoreUnknown := GetKeyField("IgnoreUnknown", containerValue).Bool() + if len(unknownArgs) > 0 && !isIgnoreUnknown { + return fmt.Errorf("ARGS: unknown args %q", unknownArgs) + } return nil } diff --git a/plugins/ipam/host-local/config.go b/plugins/ipam/host-local/config.go index c33c33c7..08ca07e3 100644 --- a/plugins/ipam/host-local/config.go +++ b/plugins/ipam/host-local/config.go @@ -35,6 +35,7 @@ type IPAMConfig struct { } type IPAMArgs struct { + types.CommonArgs IP net.IP `json:"ip,omitempty"` }