Merge pull request #1647 from anderbubble/enhanced-field-formatting
Enhancements for node.Field formatting
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -223,33 +223,51 @@ func listReflectedFields(t reflect.Type, v reflect.Value, prefix string) (fields
|
||||
return
|
||||
}
|
||||
|
||||
// valueStr converts a reflect.Value into a string. For slices, it joins all elements into a comma-separated
|
||||
// string. For pointers, it returns an empty string if the pointer is nil. For other kinds, it returns the
|
||||
// formatted string representation of the value.
|
||||
// valueStr converts a reflect.Value into a string.
|
||||
func valueStr(value reflect.Value) (output string) {
|
||||
if !value.IsValid() {
|
||||
return ""
|
||||
}
|
||||
|
||||
if value.Kind() == reflect.Pointer {
|
||||
if value.IsZero() {
|
||||
return ""
|
||||
}
|
||||
value = value.Elem()
|
||||
}
|
||||
if value.Type() == reflect.TypeOf(net.IP{}) {
|
||||
if !value.IsZero() {
|
||||
output = fmt.Sprintf("%s", value)
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.Ptr, reflect.Interface, reflect.Map, reflect.Slice:
|
||||
if value.IsNil() {
|
||||
return ""
|
||||
}
|
||||
} else if value.Kind() == reflect.Slice {
|
||||
}
|
||||
|
||||
stringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
||||
if value.Type().Implements(stringerType) {
|
||||
return fmt.Sprintf("%s", value)
|
||||
}
|
||||
|
||||
if value.Type() == reflect.TypeOf([]string{}) {
|
||||
var sliceStrs []string
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
sliceStrs = append(sliceStrs, fmt.Sprintf("%v", value.Index(i)))
|
||||
}
|
||||
output = strings.Join(sliceStrs, ",")
|
||||
} else {
|
||||
output = fmt.Sprintf("%s", value)
|
||||
return strings.Join(sliceStrs, ",")
|
||||
}
|
||||
return output
|
||||
|
||||
switch value.Kind() {
|
||||
case reflect.String, reflect.Int:
|
||||
return fmt.Sprintf("%s", value)
|
||||
case reflect.Bool:
|
||||
return fmt.Sprintf("%t", value.Bool())
|
||||
}
|
||||
|
||||
if jsonBytes, err := json.Marshal(value.Interface()); err == nil {
|
||||
return string(jsonBytes)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s", value)
|
||||
}
|
||||
|
||||
// sortValues sorts a slice of reflect.Values. Currently, it only supports sorting string values and
|
||||
|
||||
@@ -14,6 +14,7 @@ func Test_getNestedFieldString(t *testing.T) {
|
||||
node string
|
||||
field string
|
||||
value string
|
||||
jsonValue string
|
||||
}{
|
||||
"comment (simple)": {
|
||||
nodesConf: `
|
||||
@@ -67,6 +68,53 @@ nodes:
|
||||
field: "NetDevs[default].Tags[tag]",
|
||||
value: "n1 netdev tag",
|
||||
},
|
||||
"boolean value (true)": {
|
||||
nodesConf: `
|
||||
nodes:
|
||||
n1:
|
||||
discoverable: true`,
|
||||
node: "n1",
|
||||
field: "Discoverable",
|
||||
value: "true",
|
||||
},
|
||||
"boolean value (false)": {
|
||||
nodesConf: `
|
||||
nodes:
|
||||
n1:
|
||||
discoverable: false`,
|
||||
node: "n1",
|
||||
field: "Discoverable",
|
||||
value: "false",
|
||||
},
|
||||
"fstab resource": {
|
||||
nodesConf: `
|
||||
nodes:
|
||||
n1:
|
||||
resources:
|
||||
fstab:
|
||||
- file: /home
|
||||
freq: 0
|
||||
mntops: defaults
|
||||
passno: 0
|
||||
spec: warewulf:/home
|
||||
vfstype: nfs`,
|
||||
node: "n1",
|
||||
field: "Resources[fstab]",
|
||||
jsonValue: `[{"file":"/home","freq":0,"mntops":"defaults","passno":0,"spec":"warewulf:/home","vfstype":"nfs"}]`,
|
||||
},
|
||||
"disk partition": {
|
||||
nodesConf: `
|
||||
nodes:
|
||||
n1:
|
||||
disks:
|
||||
/dev/vda:
|
||||
partitions:
|
||||
rootfs:
|
||||
resize: false`,
|
||||
node: "n1",
|
||||
field: "Disks[/dev/vda].Partitions[rootfs].Resize",
|
||||
value: "false",
|
||||
},
|
||||
}
|
||||
|
||||
for name, tt := range tests {
|
||||
@@ -80,7 +128,12 @@ nodes:
|
||||
node := registry.Nodes[tt.node]
|
||||
value, err := getNestedFieldString(node, tt.field)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.value, value)
|
||||
if tt.value != "" {
|
||||
assert.Equal(t, tt.value, value)
|
||||
}
|
||||
if tt.jsonValue != "" {
|
||||
assert.JSONEq(t, tt.jsonValue, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,15 +194,16 @@ nodeprofiles:
|
||||
|
||||
func Test_MergeNode(t *testing.T) {
|
||||
var tests = map[string]struct {
|
||||
nodesConf string
|
||||
node string
|
||||
field string
|
||||
source string
|
||||
value string
|
||||
nodes []string
|
||||
fields []string
|
||||
sources []string
|
||||
values []string
|
||||
nodesConf string
|
||||
node string
|
||||
field string
|
||||
source string
|
||||
value string
|
||||
nodes []string
|
||||
fields []string
|
||||
sources []string
|
||||
values []string
|
||||
jsonValues []string
|
||||
}{
|
||||
"node comment": {
|
||||
nodesConf: `
|
||||
@@ -779,10 +780,10 @@ nodes:
|
||||
file: /opt
|
||||
vfstype: nfs
|
||||
`,
|
||||
nodes: []string{"n1"},
|
||||
fields: []string{"Resources[fstab]"},
|
||||
sources: []string{"p1,n1"},
|
||||
values: []string{"[map[file:/home spec:warewulf:/home vfstype:nfs] map[file:/opt spec:warewulf:/opt vfstype:nfs]]"},
|
||||
nodes: []string{"n1"},
|
||||
fields: []string{"Resources[fstab]"},
|
||||
sources: []string{"p1,n1"},
|
||||
jsonValues: []string{`[{"file":"/home","spec":"warewulf:/home","vfstype":"nfs"},{"file":"/opt","spec":"warewulf:/opt","vfstype":"nfs"}]`},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -817,8 +818,14 @@ nodes:
|
||||
_, fields, _ := registry.MergeNode(tt.nodes[i])
|
||||
value, valueErr := getNestedFieldString(nodes[i], tt.fields[i])
|
||||
assert.NoError(t, valueErr)
|
||||
assert.Equal(t, tt.values[i], value)
|
||||
assert.Equal(t, tt.values[i], fields.Value(tt.fields[i]))
|
||||
if len(tt.values) > i {
|
||||
assert.Equal(t, tt.values[i], value)
|
||||
assert.Equal(t, tt.values[i], fields.Value(tt.fields[i]))
|
||||
}
|
||||
if len(tt.jsonValues) > i {
|
||||
assert.JSONEq(t, tt.jsonValues[i], value)
|
||||
assert.Equal(t, tt.jsonValues[i], fields.Value(tt.fields[i]))
|
||||
}
|
||||
assert.Equal(t, tt.sources[i], fields.Source(tt.fields[i]))
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user