180 lines
4.5 KiB
Go
180 lines
4.5 KiB
Go
package node
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"reflect"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
/*
|
|
struct to hold the fields of GetFields
|
|
*/
|
|
type NodeFields struct {
|
|
Field string
|
|
Source string
|
|
Value string
|
|
}
|
|
|
|
func (f *NodeFields) Set(src, val string) {
|
|
if val == "" {
|
|
return
|
|
}
|
|
if f.Value == "" {
|
|
f.Value = val
|
|
f.Source = src
|
|
} else if f.Source != "" {
|
|
f.Value = val
|
|
if src == "" {
|
|
f.Source = "SUPERSEDED"
|
|
} else {
|
|
f.Source = src
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
type fieldMap map[string]*NodeFields
|
|
|
|
/*
|
|
Get all the info out of NodeConf. If emptyFields is set true, all fields are shown not only the ones with effective values
|
|
*/
|
|
func (nodeYml *NodeYaml) GetFields(node Node) (output []NodeFields) {
|
|
nodeMap := make(fieldMap)
|
|
for _, p := range node.Profiles {
|
|
if profile, ok := nodeYml.nodeProfiles[p]; ok {
|
|
nodeMap.importFields(profile, "", p)
|
|
}
|
|
}
|
|
rawNode, _ := nodeYml.GetNodeOnlyPtr(node.id)
|
|
nodeMap.importFields(rawNode, "", "")
|
|
for _, elem := range nodeMap {
|
|
if elem.Value != "" {
|
|
output = append(output, *elem)
|
|
}
|
|
}
|
|
sort.Slice(output, func(i, j int) bool {
|
|
return output[i].Field < output[j].Field
|
|
})
|
|
return output
|
|
}
|
|
|
|
/*
|
|
Get all the info out of ProfileConf. If emptyFields is set true, all fields are shown not only the ones with effective values
|
|
*/
|
|
func (nodeYml *NodeYaml) GetFieldsProfile(profile Profile) (output []NodeFields) {
|
|
profileMap := make(fieldMap)
|
|
profileMap.importFields(&profile, "", "")
|
|
for _, elem := range profileMap {
|
|
if elem.Value != "" {
|
|
output = append(output, *elem)
|
|
}
|
|
}
|
|
sort.Slice(output, func(i, j int) bool {
|
|
return output[i].Field < output[j].Field
|
|
})
|
|
return output
|
|
}
|
|
|
|
/*
|
|
Internal function which travels through all fields of a NodeConf and for this
|
|
reason needs to be called via interface{}
|
|
*/
|
|
func (fieldMap fieldMap) importFields(obj interface{}, prefix string, source string) {
|
|
objValue := reflect.ValueOf(obj)
|
|
objType := reflect.TypeOf(obj)
|
|
if objValue.IsNil() {
|
|
return
|
|
}
|
|
for i := 0; i < objType.Elem().NumField(); i++ {
|
|
fieldValue := objValue.Elem().Field(i)
|
|
field := objType.Elem().Field(i)
|
|
if !fieldValue.IsValid() || !field.IsExported() {
|
|
continue
|
|
}
|
|
switch field.Type.Kind() {
|
|
case reflect.Map:
|
|
mapIter := fieldValue.MapRange()
|
|
for mapIter.Next() {
|
|
if mapIter.Value().Kind() == reflect.String {
|
|
key := fmt.Sprintf("%s%s[%s]", prefix, field.Name, mapIter.Key().String())
|
|
fieldMap[key] = &NodeFields{
|
|
Field: key,
|
|
Source: source,
|
|
Value: mapIter.Value().String(),
|
|
}
|
|
} else {
|
|
newPrefix := fmt.Sprintf("%s%s[%s].", prefix, field.Name, mapIter.Key().String())
|
|
fieldMap.importFields(mapIter.Value().Interface(), newPrefix, source)
|
|
}
|
|
}
|
|
if fieldValue.Len() == 0 {
|
|
key := fmt.Sprintf("%s%s[]", prefix, field.Name)
|
|
fieldMap[key] = &NodeFields{
|
|
Field: key,
|
|
}
|
|
}
|
|
case reflect.Struct: // inherited fields from a sub-entity
|
|
fieldMap.importFields(fieldValue.Addr().Interface(), "", source)
|
|
case reflect.Ptr:
|
|
if fieldValue.Addr().IsValid() {
|
|
if field.Type.Elem().Kind() == reflect.Bool {
|
|
fieldMap.importField(field, fieldValue, prefix, source)
|
|
} else {
|
|
newPrefix := fmt.Sprintf("%s%s.", prefix, field.Name)
|
|
fieldMap.importFields(fieldValue.Interface(), newPrefix, source)
|
|
}
|
|
}
|
|
default:
|
|
fieldMap.importField(field, fieldValue, prefix, source)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (fieldMap fieldMap) importField(field reflect.StructField, fieldValue reflect.Value, prefix string, source string) {
|
|
key := prefix + field.Name
|
|
if _, ok := fieldMap[key]; !ok {
|
|
fieldMap[key] = &NodeFields{
|
|
Field: key,
|
|
Source: source,
|
|
}
|
|
}
|
|
|
|
if field.Type == reflect.TypeOf([]string{}) {
|
|
vals := (fieldValue.Interface()).([]string)
|
|
src_str := source
|
|
if oldVal, ok := fieldMap[key]; ok {
|
|
if oldVal.Value != "" {
|
|
if len(vals) > 0 {
|
|
src_str = oldVal.Source + "+"
|
|
} else {
|
|
src_str = oldVal.Source
|
|
}
|
|
vals = append(vals, oldVal.Value)
|
|
} else {
|
|
src_str = oldVal.Source
|
|
}
|
|
}
|
|
fieldMap[key] = &NodeFields{
|
|
Field: key,
|
|
Source: src_str,
|
|
Value: strings.Join(vals, ","),
|
|
}
|
|
} else if field.Type == reflect.TypeOf(net.IP{}) {
|
|
val := (fieldValue.Interface()).(net.IP)
|
|
if val != nil {
|
|
fieldMap[key].Set(source, val.String())
|
|
}
|
|
} else if field.Type.Kind() == reflect.Bool {
|
|
fieldMap[key].Set(source, strconv.FormatBool(fieldValue.Bool()))
|
|
} else if field.Type.Kind() == reflect.Pointer && field.Type.Elem().Kind() == reflect.Bool {
|
|
if fieldValue.Elem().IsValid() {
|
|
fieldMap[key].Set(source, strconv.FormatBool(fieldValue.Elem().Bool()))
|
|
}
|
|
} else {
|
|
fieldMap[key].Set(source, fieldValue.String())
|
|
}
|
|
}
|