mirror of https://github.com/k3s-io/k3s
omitempty
parent
1085b6f730
commit
617b49858f
|
@ -120,7 +120,12 @@ func asArgs(fn, defaultFn func(*pflag.FlagSet)) []string {
|
||||||
defaultFn(defaults)
|
defaultFn(defaults)
|
||||||
var args []string
|
var args []string
|
||||||
fs.VisitAll(func(flag *pflag.Flag) {
|
fs.VisitAll(func(flag *pflag.Flag) {
|
||||||
|
// if the flag implements utilflag.OmitEmpty and the value is Empty, then just omit it from the command line
|
||||||
|
if omit, ok := flag.Value.(utilflag.OmitEmpty); ok && omit.Empty() {
|
||||||
|
return
|
||||||
|
}
|
||||||
s := flag.Value.String()
|
s := flag.Value.String()
|
||||||
|
// if the flag has the same value as the default, we can omit it without changing the meaning of the command line
|
||||||
var defaultValue string
|
var defaultValue string
|
||||||
if defaultFlag := defaults.Lookup(flag.Name); defaultFlag != nil {
|
if defaultFlag := defaults.Lookup(flag.Name); defaultFlag != nil {
|
||||||
defaultValue = defaultFlag.Value.String()
|
defaultValue = defaultFlag.Value.String()
|
||||||
|
@ -128,6 +133,7 @@ func asArgs(fn, defaultFn func(*pflag.FlagSet)) []string {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if the flag is a string slice, each element is specified with an independent flag invocation
|
||||||
if values, err := fs.GetStringSlice(flag.Name); err == nil {
|
if values, err := fs.GetStringSlice(flag.Name); err == nil {
|
||||||
for _, s := range values {
|
for _, s := range values {
|
||||||
args = append(args, fmt.Sprintf("--%s=%s", flag.Name, s))
|
args = append(args, fmt.Sprintf("--%s=%s", flag.Name, s))
|
||||||
|
|
|
@ -30,6 +30,7 @@ go_library(
|
||||||
"map_string_bool.go",
|
"map_string_bool.go",
|
||||||
"map_string_string.go",
|
"map_string_string.go",
|
||||||
"namedcertkey_flag.go",
|
"namedcertkey_flag.go",
|
||||||
|
"omitempty.go",
|
||||||
"string_flag.go",
|
"string_flag.go",
|
||||||
"tristate.go",
|
"tristate.go",
|
||||||
],
|
],
|
||||||
|
|
|
@ -38,10 +38,6 @@ func NewLangleSeparatedMapStringString(m *map[string]string) *LangleSeparatedMap
|
||||||
|
|
||||||
// String implements github.com/spf13/pflag.Value
|
// String implements github.com/spf13/pflag.Value
|
||||||
func (m *LangleSeparatedMapStringString) String() string {
|
func (m *LangleSeparatedMapStringString) String() string {
|
||||||
if *m.Map == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs := []string{}
|
pairs := []string{}
|
||||||
for k, v := range *m.Map {
|
for k, v := range *m.Map {
|
||||||
pairs = append(pairs, fmt.Sprintf("%s<%s", k, v))
|
pairs = append(pairs, fmt.Sprintf("%s<%s", k, v))
|
||||||
|
@ -55,12 +51,6 @@ func (m *LangleSeparatedMapStringString) Set(value string) error {
|
||||||
if m.Map == nil {
|
if m.Map == nil {
|
||||||
return fmt.Errorf("no target (nil pointer to map[string]string)")
|
return fmt.Errorf("no target (nil pointer to map[string]string)")
|
||||||
}
|
}
|
||||||
// allow explicit nil map
|
|
||||||
if value == "nil" {
|
|
||||||
*m.Map = nil
|
|
||||||
m.initialized = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if !m.initialized || *m.Map == nil {
|
if !m.initialized || *m.Map == nil {
|
||||||
// clear default values, or allocate if no existing map
|
// clear default values, or allocate if no existing map
|
||||||
*m.Map = make(map[string]string)
|
*m.Map = make(map[string]string)
|
||||||
|
@ -85,3 +75,8 @@ func (m *LangleSeparatedMapStringString) Set(value string) error {
|
||||||
func (*LangleSeparatedMapStringString) Type() string {
|
func (*LangleSeparatedMapStringString) Type() string {
|
||||||
return "mapStringString"
|
return "mapStringString"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Empty implements OmitEmpty
|
||||||
|
func (m *LangleSeparatedMapStringString) Empty() bool {
|
||||||
|
return len(*m.Map) == 0
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestStringLangleSeparatedMapStringString(t *testing.T) {
|
||||||
m *LangleSeparatedMapStringString
|
m *LangleSeparatedMapStringString
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
{"nil", NewLangleSeparatedMapStringString(&nilMap), "nil"},
|
{"nil", NewLangleSeparatedMapStringString(&nilMap), ""},
|
||||||
{"empty", NewLangleSeparatedMapStringString(&map[string]string{}), ""},
|
{"empty", NewLangleSeparatedMapStringString(&map[string]string{}), ""},
|
||||||
{"one key", NewLangleSeparatedMapStringString(&map[string]string{"one": "foo"}), "one<foo"},
|
{"one key", NewLangleSeparatedMapStringString(&map[string]string{"one": "foo"}), "one<foo"},
|
||||||
{"two keys", NewLangleSeparatedMapStringString(&map[string]string{"one": "foo", "two": "bar"}), "one<foo,two<bar"},
|
{"two keys", NewLangleSeparatedMapStringString(&map[string]string{"one": "foo", "two": "bar"}), "one<foo,two<bar"},
|
||||||
|
@ -59,12 +59,6 @@ func TestSetLangleSeparatedMapStringString(t *testing.T) {
|
||||||
initialized: true,
|
initialized: true,
|
||||||
Map: &map[string]string{},
|
Map: &map[string]string{},
|
||||||
}, ""},
|
}, ""},
|
||||||
{"explicitly nil", []string{"nil"},
|
|
||||||
NewLangleSeparatedMapStringString(&map[string]string{"default": ""}),
|
|
||||||
&LangleSeparatedMapStringString{
|
|
||||||
initialized: true,
|
|
||||||
Map: &nilMap,
|
|
||||||
}, ""},
|
|
||||||
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
||||||
{"allocates map if currently nil", []string{""},
|
{"allocates map if currently nil", []string{""},
|
||||||
&LangleSeparatedMapStringString{initialized: true, Map: &nilMap},
|
&LangleSeparatedMapStringString{initialized: true, Map: &nilMap},
|
||||||
|
@ -142,3 +136,24 @@ func TestSetLangleSeparatedMapStringString(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmptyLangleSeparatedMapStringString(t *testing.T) {
|
||||||
|
var nilMap map[string]string
|
||||||
|
cases := []struct {
|
||||||
|
desc string
|
||||||
|
val *LangleSeparatedMapStringString
|
||||||
|
expect bool
|
||||||
|
}{
|
||||||
|
{"nil", NewLangleSeparatedMapStringString(&nilMap), true},
|
||||||
|
{"empty", NewLangleSeparatedMapStringString(&map[string]string{}), true},
|
||||||
|
{"populated", NewLangleSeparatedMapStringString(&map[string]string{"foo": ""}), false},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
|
result := c.val.Empty()
|
||||||
|
if result != c.expect {
|
||||||
|
t.Fatalf("expect %t but got %t", c.expect, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,10 +39,6 @@ func NewMapStringBool(m *map[string]bool) *MapStringBool {
|
||||||
|
|
||||||
// String implements github.com/spf13/pflag.Value
|
// String implements github.com/spf13/pflag.Value
|
||||||
func (m *MapStringBool) String() string {
|
func (m *MapStringBool) String() string {
|
||||||
if *m.Map == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs := []string{}
|
pairs := []string{}
|
||||||
for k, v := range *m.Map {
|
for k, v := range *m.Map {
|
||||||
pairs = append(pairs, fmt.Sprintf("%s=%t", k, v))
|
pairs = append(pairs, fmt.Sprintf("%s=%t", k, v))
|
||||||
|
@ -56,12 +52,6 @@ func (m *MapStringBool) Set(value string) error {
|
||||||
if m.Map == nil {
|
if m.Map == nil {
|
||||||
return fmt.Errorf("no target (nil pointer to map[string]bool)")
|
return fmt.Errorf("no target (nil pointer to map[string]bool)")
|
||||||
}
|
}
|
||||||
// allow explicit nil map
|
|
||||||
if value == "nil" {
|
|
||||||
*m.Map = nil
|
|
||||||
m.initialized = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if !m.initialized || *m.Map == nil {
|
if !m.initialized || *m.Map == nil {
|
||||||
// clear default values, or allocate if no existing map
|
// clear default values, or allocate if no existing map
|
||||||
*m.Map = make(map[string]bool)
|
*m.Map = make(map[string]bool)
|
||||||
|
@ -90,3 +80,8 @@ func (m *MapStringBool) Set(value string) error {
|
||||||
func (*MapStringBool) Type() string {
|
func (*MapStringBool) Type() string {
|
||||||
return "mapStringBool"
|
return "mapStringBool"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Empty implements OmitEmpty
|
||||||
|
func (m *MapStringBool) Empty() bool {
|
||||||
|
return len(*m.Map) == 0
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestStringMapStringBool(t *testing.T) {
|
||||||
m *MapStringBool
|
m *MapStringBool
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
{"nil", NewMapStringBool(&nilMap), "nil"},
|
{"nil", NewMapStringBool(&nilMap), ""},
|
||||||
{"empty", NewMapStringBool(&map[string]bool{}), ""},
|
{"empty", NewMapStringBool(&map[string]bool{}), ""},
|
||||||
{"one key", NewMapStringBool(&map[string]bool{"one": true}), "one=true"},
|
{"one key", NewMapStringBool(&map[string]bool{"one": true}), "one=true"},
|
||||||
{"two keys", NewMapStringBool(&map[string]bool{"one": true, "two": false}), "one=true,two=false"},
|
{"two keys", NewMapStringBool(&map[string]bool{"one": true, "two": false}), "one=true,two=false"},
|
||||||
|
@ -59,12 +59,6 @@ func TestSetMapStringBool(t *testing.T) {
|
||||||
initialized: true,
|
initialized: true,
|
||||||
Map: &map[string]bool{},
|
Map: &map[string]bool{},
|
||||||
}, ""},
|
}, ""},
|
||||||
{"explicitly nil", []string{"nil"},
|
|
||||||
NewMapStringBool(&map[string]bool{"default": true}),
|
|
||||||
&MapStringBool{
|
|
||||||
initialized: true,
|
|
||||||
Map: &nilMap,
|
|
||||||
}, ""},
|
|
||||||
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
||||||
{"allocates map if currently nil", []string{""},
|
{"allocates map if currently nil", []string{""},
|
||||||
&MapStringBool{initialized: true, Map: &nilMap},
|
&MapStringBool{initialized: true, Map: &nilMap},
|
||||||
|
@ -146,3 +140,24 @@ func TestSetMapStringBool(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmptyMapStringBool(t *testing.T) {
|
||||||
|
var nilMap map[string]bool
|
||||||
|
cases := []struct {
|
||||||
|
desc string
|
||||||
|
val *MapStringBool
|
||||||
|
expect bool
|
||||||
|
}{
|
||||||
|
{"nil", NewMapStringBool(&nilMap), true},
|
||||||
|
{"empty", NewMapStringBool(&map[string]bool{}), true},
|
||||||
|
{"populated", NewMapStringBool(&map[string]bool{"foo": true}), false},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
|
result := c.val.Empty()
|
||||||
|
if result != c.expect {
|
||||||
|
t.Fatalf("expect %t but got %t", c.expect, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,10 +38,6 @@ func NewMapStringString(m *map[string]string) *MapStringString {
|
||||||
|
|
||||||
// String implements github.com/spf13/pflag.Value
|
// String implements github.com/spf13/pflag.Value
|
||||||
func (m *MapStringString) String() string {
|
func (m *MapStringString) String() string {
|
||||||
if *m.Map == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs := []string{}
|
pairs := []string{}
|
||||||
for k, v := range *m.Map {
|
for k, v := range *m.Map {
|
||||||
pairs = append(pairs, fmt.Sprintf("%s=%s", k, v))
|
pairs = append(pairs, fmt.Sprintf("%s=%s", k, v))
|
||||||
|
@ -55,12 +51,6 @@ func (m *MapStringString) Set(value string) error {
|
||||||
if m.Map == nil {
|
if m.Map == nil {
|
||||||
return fmt.Errorf("no target (nil pointer to map[string]string)")
|
return fmt.Errorf("no target (nil pointer to map[string]string)")
|
||||||
}
|
}
|
||||||
// allow explicit nil map
|
|
||||||
if value == "nil" {
|
|
||||||
*m.Map = nil
|
|
||||||
m.initialized = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if !m.initialized || *m.Map == nil {
|
if !m.initialized || *m.Map == nil {
|
||||||
// clear default values, or allocate if no existing map
|
// clear default values, or allocate if no existing map
|
||||||
*m.Map = make(map[string]string)
|
*m.Map = make(map[string]string)
|
||||||
|
@ -85,3 +75,8 @@ func (m *MapStringString) Set(value string) error {
|
||||||
func (*MapStringString) Type() string {
|
func (*MapStringString) Type() string {
|
||||||
return "mapStringString"
|
return "mapStringString"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Empty implements OmitEmpty
|
||||||
|
func (m *MapStringString) Empty() bool {
|
||||||
|
return len(*m.Map) == 0
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestStringMapStringString(t *testing.T) {
|
||||||
m *MapStringString
|
m *MapStringString
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
{"nil", NewMapStringString(&nilMap), "nil"},
|
{"nil", NewMapStringString(&nilMap), ""},
|
||||||
{"empty", NewMapStringString(&map[string]string{}), ""},
|
{"empty", NewMapStringString(&map[string]string{}), ""},
|
||||||
{"one key", NewMapStringString(&map[string]string{"one": "foo"}), "one=foo"},
|
{"one key", NewMapStringString(&map[string]string{"one": "foo"}), "one=foo"},
|
||||||
{"two keys", NewMapStringString(&map[string]string{"one": "foo", "two": "bar"}), "one=foo,two=bar"},
|
{"two keys", NewMapStringString(&map[string]string{"one": "foo", "two": "bar"}), "one=foo,two=bar"},
|
||||||
|
@ -59,12 +59,6 @@ func TestSetMapStringString(t *testing.T) {
|
||||||
initialized: true,
|
initialized: true,
|
||||||
Map: &map[string]string{},
|
Map: &map[string]string{},
|
||||||
}, ""},
|
}, ""},
|
||||||
{"explicitly nil", []string{"nil"},
|
|
||||||
NewMapStringString(&map[string]string{"default": ""}),
|
|
||||||
&MapStringString{
|
|
||||||
initialized: true,
|
|
||||||
Map: &nilMap,
|
|
||||||
}, ""},
|
|
||||||
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
// make sure we still allocate for "initialized" maps where Map was initially set to a nil map
|
||||||
{"allocates map if currently nil", []string{""},
|
{"allocates map if currently nil", []string{""},
|
||||||
&MapStringString{initialized: true, Map: &nilMap},
|
&MapStringString{initialized: true, Map: &nilMap},
|
||||||
|
@ -142,3 +136,24 @@ func TestSetMapStringString(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEmptyMapStringString(t *testing.T) {
|
||||||
|
var nilMap map[string]string
|
||||||
|
cases := []struct {
|
||||||
|
desc string
|
||||||
|
val *MapStringString
|
||||||
|
expect bool
|
||||||
|
}{
|
||||||
|
{"nil", NewMapStringString(&nilMap), true},
|
||||||
|
{"empty", NewMapStringString(&map[string]string{}), true},
|
||||||
|
{"populated", NewMapStringString(&map[string]string{"foo": ""}), false},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.desc, func(t *testing.T) {
|
||||||
|
result := c.val.Empty()
|
||||||
|
if result != c.expect {
|
||||||
|
t.Fatalf("expect %t but got %t", c.expect, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package flag
|
||||||
|
|
||||||
|
// OmitEmpty is an interface for flags to report whether their underlying value
|
||||||
|
// is "empty." If a flag implements OmitEmpty and returns true for a call to Empty(),
|
||||||
|
// it is assumed that flag may be omitted from the command line.
|
||||||
|
type OmitEmpty interface {
|
||||||
|
Empty() bool
|
||||||
|
}
|
Loading…
Reference in New Issue