From bd2543d484f2fc85cfd2ef16852fb65c3a671cad Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 30 Jun 2022 11:22:38 +0200 Subject: [PATCH 01/38] relection test for comment --- internal/app/wwctl/node/set/root.go | 31 ++++++++++++++++++++++++++++- internal/pkg/node/datastructure.go | 2 +- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 0174d55e..976f28d9 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -2,6 +2,7 @@ package set import ( "log" + "reflect" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/kernel" @@ -74,10 +75,38 @@ var ( SetAssetKey string SetNetTags []string SetNetDelTags []string + OptionStrMap map[string]*string ) func init() { - baseCmd.PersistentFlags().StringVar(&SetComment, "comment", "", "Set a comment for this node") + OptionStrMap = make(map[string]*string) + var emptyNodeConf node.NodeConf + nodeStruct := reflect.ValueOf(emptyNodeConf) + nodeType := nodeStruct.Type() + for i := 0; i < nodeStruct.NumField(); i++ { + field := nodeType.Field(i) + if field.Tag.Get("comment") != "" { + kind := field.Type.Kind() + if kind == reflect.String { + var optionVal string + OptionStrMap[field.Name] = &optionVal + if field.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringVarP(&optionVal, + field.Tag.Get("lopt"), + field.Tag.Get("sopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().StringVar(&optionVal, + field.Tag.Get("lopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + + } + } + } + } + //baseCmd.PersistentFlags().StringVar(&SetComment, "comment", "", "Set a comment for this node") baseCmd.PersistentFlags().StringVarP(&SetContainer, "container", "C", "", "Set the container (VNFS) for this node") if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 4e818b8f..91818c1e 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -19,7 +19,7 @@ type NodeYaml struct { NodeConf is the datastructure which is stored on disk. */ type NodeConf struct { - Comment string `yaml:"comment,omitempty"` + Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set Comment"` ClusterName string `yaml:"cluster name,omitempty"` ContainerName string `yaml:"container name,omitempty"` Ipxe string `yaml:"ipxe template,omitempty"` From f5b6287486e1c4525766396e260c64b080a6dd4f Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 1 Jul 2022 09:26:06 +0200 Subject: [PATCH 02/38] Explicit setter func at complie time --- internal/pkg/node/methods.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 1ec5d6ad..b4e05a42 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -2,6 +2,7 @@ package node import ( "fmt" + "reflect" "regexp" "strings" @@ -299,3 +300,29 @@ func (ent *Entry) Defined() bool { } return false } + +/* +Set the Entry trough an interface by trying to cast the interface +*/ +func SetEntry(entryPrt interface{}, val string) { + fmt.Printf("entryPtr: %v\n", reflect.TypeOf(entryPrt)) + if entry, ok := entryPrt.(*Entry); ok { + entry.Set(val) + } else { + panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPrt))) + } + +} + +/* +Call SetEntry for given field +*/ +func (node *NodeInfo) SetField(fieldName string, val interface{}) { + field := reflect.ValueOf(node).Elem().FieldByName(fieldName) + if field.IsValid() { + SetEntry(field.Addr().Interface(), val.(string)) + } else { + panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) + } + +} From 84d3b72f63d8c515d5a497e167e31d48f2e2aa74 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 1 Jul 2022 13:57:36 +0200 Subject: [PATCH 03/38] added more abstrac setter for nested structs --- internal/app/wwctl/node/set/root.go | 48 ++-------- internal/pkg/node/datastructure.go | 12 +-- internal/pkg/node/methods.go | 144 ++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 52 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 976f28d9..e63048ef 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -1,8 +1,8 @@ package set import ( + "fmt" "log" - "reflect" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/kernel" @@ -33,10 +33,7 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } - SetComment string - SetContainer string SetKernelOverride string - SetKernelArgs string SetNetName string SetNetDev string SetIpaddr string @@ -66,48 +63,27 @@ var ( SetAddProfile []string SetDelProfile []string SetForce bool - SetInit string SetDiscoverable bool SetUndiscoverable bool - SetRoot string SetTags []string SetDelTags []string - SetAssetKey string SetNetTags []string SetNetDelTags []string OptionStrMap map[string]*string + KernelStrMapmap map[string]*string ) func init() { - OptionStrMap = make(map[string]*string) + //var emptyNodeConf node.NodeConf + //var emptyKernelE node.KernelEntry + myBase := node.CobraCommand{baseCmd} var emptyNodeConf node.NodeConf - nodeStruct := reflect.ValueOf(emptyNodeConf) - nodeType := nodeStruct.Type() - for i := 0; i < nodeStruct.NumField(); i++ { - field := nodeType.Field(i) - if field.Tag.Get("comment") != "" { - kind := field.Type.Kind() - if kind == reflect.String { - var optionVal string - OptionStrMap[field.Name] = &optionVal - if field.Tag.Get("sopt") != "" { - baseCmd.PersistentFlags().StringVarP(&optionVal, - field.Tag.Get("lopt"), - field.Tag.Get("sopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) - } else { - baseCmd.PersistentFlags().StringVar(&optionVal, - field.Tag.Get("lopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) + emptyNodeConf.Kernel = new(node.KernelConf) + emptyNodeConf.Ipmi = new(node.IpmiConf) + //emptyNodeConf.NetDevs = make(map[string]*node.NetDevs) + OptionStrMap = myBase.CreateFlags(emptyNodeConf) - } - } - } - } - //baseCmd.PersistentFlags().StringVar(&SetComment, "comment", "", "Set a comment for this node") - baseCmd.PersistentFlags().StringVarP(&SetContainer, "container", "C", "", "Set the container (VNFS) for this node") + fmt.Printf("OptionStrMap: %v\n", OptionStrMap) if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() return list, cobra.ShellCompDirectiveNoFileComp @@ -121,12 +97,8 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name") - baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container") - baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs") - baseCmd.PersistentFlags().StringVar(&SetAssetKey, "assetkey", "", "Set the node's Asset tag (key)") baseCmd.PersistentFlags().StringVarP(&SetInitOverlay, "wwinit", "O", "", "Set the node's initialization overlay") baseCmd.PersistentFlags().StringSliceVarP(&SetRuntimeOverlay, "runtime", "R", []string{}, "Set the node's runtime overlay") if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 91818c1e..f5745a6a 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -19,9 +19,9 @@ type NodeYaml struct { NodeConf is the datastructure which is stored on disk. */ type NodeConf struct { - Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set Comment"` + Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set arbitrary string comment"` ClusterName string `yaml:"cluster name,omitempty"` - ContainerName string `yaml:"container name,omitempty"` + ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"` Ipxe string `yaml:"ipxe template,omitempty"` KernelVersion string `yaml:"kernel version,omitempty"` KernelOverride string `yaml:"kernel override,omitempty"` @@ -38,9 +38,9 @@ type NodeConf struct { SystemOverlay []string `yaml:"system overlay,omitempty"` Kernel *KernelConf `yaml:"kernel,omitempty"` Ipmi *IpmiConf `yaml:"ipmi,omitempty"` - Init string `yaml:"init,omitempty"` - Root string `yaml:"root,omitempty"` - AssetKey string `yaml:"asset key,omitempty"` + Init string `yaml:"init,omitempty" lopt:"init" sopt:"i" comment:"Define the init process to boot the container"` + Root string `yaml:"root,omitempty" lopt:"root" comment:"Define the rootfs" ` + AssetKey string `yaml:"asset key,omitempty" lopt:"asset" comment:"Set the node's Asset tag (key)"` Discoverable string `yaml:"discoverable,omitempty"` Profiles []string `yaml:"profiles,omitempty"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` @@ -61,7 +61,7 @@ type IpmiConf struct { type KernelConf struct { Version string `yaml:"version,omitempty"` Override string `yaml:"override,omitempty"` - Args string `yaml:"args,omitempty"` + Args string `yaml:"args,omitempty" lopt:"kernelargs" sopt:"A" comment:"Set Kernel argument"` } type NetDevs struct { diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index b4e05a42..d6d62262 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/spf13/cobra" ) /********** @@ -304,25 +305,152 @@ func (ent *Entry) Defined() bool { /* Set the Entry trough an interface by trying to cast the interface */ -func SetEntry(entryPrt interface{}, val string) { - fmt.Printf("entryPtr: %v\n", reflect.TypeOf(entryPrt)) - if entry, ok := entryPrt.(*Entry); ok { - entry.Set(val) +func SetEntry(entryPtr interface{}, val interface{}) { + if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) { + entry := entryPtr.(*Entry) + valKind := reflect.TypeOf(val) + if valKind.Kind() == reflect.String { + entry.Set(val.(string)) + } else if valKind.Kind() == reflect.Slice { + if valKind.Elem().Kind() == reflect.String { + entry.SetSlice(val.([]string)) + } else { + panic("Got unknown slice type") + } + } } else { - panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPrt))) + panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPtr))) } } /* -Call SetEntry for given field +Call SetEntry for given field (NodeInfo) */ func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) if field.IsValid() { - SetEntry(field.Addr().Interface(), val.(string)) + //fmt.Println(reflect.TypeOf(field.Addr().Interface())) + SetEntry(field.Addr().Interface(), val) } else { - panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) + fieldNames := strings.Split(fieldName, ".") + if len(fieldNames) == 2 { + nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) + if nestedField.IsValid() { + switch nestedField.Addr().Type() { + case reflect.TypeOf((**KernelEntry)(nil)): + entry := nestedField.Addr().Interface().(**KernelEntry) + (*entry).SetField(fieldNames[1], val) + case reflect.TypeOf((**IpmiEntry)(nil)): + entry := nestedField.Addr().Interface().(**IpmiEntry) + (*entry).SetField(fieldNames[1], val) + default: + panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) + } + } else { + panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) + } + } else { + panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) + } } } + +/* +Call SetEntry for given field (KernelEntry) +*/ +func (node *KernelEntry) SetField(fieldName string, val interface{}) { + field := reflect.ValueOf(node).Elem().FieldByName(fieldName) + if field.IsValid() { + SetEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + } +} + +/* +Call SetEntry for given field (ImpiEntry) +*/ +func (node *IpmiEntry) SetField(fieldName string, val interface{}) { + field := reflect.ValueOf(node).Elem().FieldByName(fieldName) + if field.IsValid() { + SetEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + } +} + +/* +Get all names of the fields in the given struct (recursive) +and create a map[name of struct field]*string if the the field +of the struct bears the comment tag. +*/ +func GetOptionsMap(theStruct interface{}) map[string]*string { + optionsMap := make(map[string]*string) + structVal := reflect.ValueOf(theStruct) + structTyp := structVal.Type() + for i := 0; i < structVal.NumField(); i++ { + field := structTyp.Field(i) + if field.Type.Kind() == reflect.Struct { + subStruct := GetOptionsMap(field) + for key, val := range subStruct { + optionsMap[key] = val + } + } else if field.Tag.Get("comment") != "" { + var newStr string + optionsMap[field.Name] = &newStr + } + + } + return optionsMap +} + +type CobraCommand struct { + *cobra.Command +} + +/* +Get all names of the fields in the given struct (recursive) +and create a map[name of struct field]*string if the the field +of the struct bears the comment tag. +*/ +func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*string { + optionsMap := make(map[string]*string) + structVal := reflect.ValueOf(theStruct) + structTyp := structVal.Type() + for i := 0; i < structVal.NumField(); i++ { + field := structTyp.Field(i) + fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) + if field.Type.Kind() == reflect.Ptr { + a := structVal.Field(i).Elem().Interface() + subStruct := baseCmd.CreateFlags(a) + for key, val := range subStruct { + optionsMap[field.Name+"."+key] = val + } + + } else if field.Type.Kind() == reflect.Map { + // Just check for network map + fmt.Println(reflect.TypeOf(structVal.Field(i).Elem())) + + } else if field.Tag.Get("comment") != "" { + var newStr string + optionsMap[field.Name] = &newStr + if field.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringVarP(&newStr, + field.Tag.Get("lopt"), + field.Tag.Get("sopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + } else { + baseCmd.PersistentFlags().StringVar(&newStr, + field.Tag.Get("lopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + + } + } + + } + return optionsMap +} From 8902f08c8748e0518f31f6f0da3522f2990e12a1 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 4 Jul 2022 19:59:03 +0200 Subject: [PATCH 04/38] added hangling of map[string]*struct --- internal/app/wwctl/node/set/root.go | 2 -- internal/pkg/node/datastructure.go | 2 +- internal/pkg/node/methods.go | 14 ++++++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index e63048ef..50904cbd 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -36,7 +36,6 @@ var ( SetKernelOverride string SetNetName string SetNetDev string - SetIpaddr string SetNetmask string SetGateway string SetHwaddr string @@ -138,7 +137,6 @@ func init() { } baseCmd.PersistentFlags().StringVarP(&SetNetName, "netname", "n", "default", "Define the network name to configure") baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Set the node's network device") - baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address") baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask") baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway") baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address") diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index f5745a6a..54f51e3b 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -69,7 +69,7 @@ type NetDevs struct { OnBoot string `yaml:"onboot,omitempty"` Device string `yaml:"device,omitempty"` Hwaddr string `yaml:"hwaddr,omitempty"` - Ipaddr string `yaml:"ipaddr,omitempty"` + Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address" sopt:"I" lopt:"ipaddr"` IpCIDR string `yaml:"ipcidr,omitempty"` Ipaddr6 string `yaml:"ip6addr,omitempty"` Prefix string `yaml:"prefix,omitempty"` diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index d6d62262..3039ac28 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -424,14 +424,24 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) if field.Type.Kind() == reflect.Ptr { a := structVal.Field(i).Elem().Interface() + fmt.Println(structVal.Field(i).Elem()) subStruct := baseCmd.CreateFlags(a) for key, val := range subStruct { optionsMap[field.Name+"."+key] = val } } else if field.Type.Kind() == reflect.Map { - // Just check for network map - fmt.Println(reflect.TypeOf(structVal.Field(i).Elem())) + // check the type of map + mapType := field.Type.Elem() + if mapType.Kind() == reflect.Ptr { + //a := reflect.ValueOf((mapType.Elem())) node.NetDevs + subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface()) + for key, val := range subMap { + optionsMap[field.Name+"."+key] = val + } + } else { + fmt.Println(mapType) + } } else if field.Tag.Get("comment") != "" { var newStr string From a37fa71de088f914e773fe453e3f5d8ec4ad7309 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 5 Jul 2022 09:28:13 +0200 Subject: [PATCH 05/38] add explicit set of netname --- internal/app/wwctl/node/set/root.go | 3 -- internal/pkg/node/methods.go | 70 ++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 50904cbd..30f5ddbc 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -1,7 +1,6 @@ package set import ( - "fmt" "log" "github.com/hpcng/warewulf/internal/pkg/container" @@ -82,7 +81,6 @@ func init() { //emptyNodeConf.NetDevs = make(map[string]*node.NetDevs) OptionStrMap = myBase.CreateFlags(emptyNodeConf) - fmt.Printf("OptionStrMap: %v\n", OptionStrMap) if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() return list, cobra.ShellCompDirectiveNoFileComp @@ -135,7 +133,6 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetNetName, "netname", "n", "default", "Define the network name to configure") baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Set the node's network device") baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask") baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway") diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 3039ac28..a9b25f23 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -319,7 +319,7 @@ func SetEntry(entryPtr interface{}, val interface{}) { } } } else { - panic(fmt.Sprintf("Can't convert %s to *node.Entry\n", reflect.TypeOf(entryPtr))) + panic(fmt.Sprintf("Can't convert %s to *node.Entry to call Set\n", reflect.TypeOf(entryPtr))) } } @@ -330,11 +330,15 @@ Call SetEntry for given field (NodeInfo) func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) if field.IsValid() { - //fmt.Println(reflect.TypeOf(field.Addr().Interface())) - SetEntry(field.Addr().Interface(), val) + if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { + //fmt.Println(reflect.TypeOf(field.Addr().Interface())) + SetEntry(field.Addr().Interface(), val) + } else { + // is most likely NetDevEntry, ignore it + } } else { fieldNames := strings.Split(fieldName, ".") - if len(fieldNames) == 2 { + if len(fieldNames) >= 2 { nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) if nestedField.IsValid() { switch nestedField.Addr().Type() { @@ -344,6 +348,17 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { case reflect.TypeOf((**IpmiEntry)(nil)): entry := nestedField.Addr().Interface().(**IpmiEntry) (*entry).SetField(fieldNames[1], val) + case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): + if len(fieldNames) == 3 { + entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) + if myVal, ok := (*entryMap)[fieldNames[1]]; ok { + myVal.SetField(fieldNames[2], val) + } else { + var newEntry NetDevEntry + (*entryMap)[fieldNames[1]] = &newEntry + newEntry.SetField(fieldNames[2], val) + } + } default: panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) } @@ -381,6 +396,18 @@ func (node *IpmiEntry) SetField(fieldName string, val interface{}) { } } +/* +Call SetEntry for given field (NetDevEntry) +*/ +func (node *NetDevEntry) SetField(fieldName string, val interface{}) { + field := reflect.ValueOf(node).Elem().FieldByName(fieldName) + if field.IsValid() { + SetEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + } +} + /* Get all names of the fields in the given struct (recursive) and create a map[name of struct field]*string if the the field @@ -421,7 +448,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri structTyp := structVal.Type() for i := 0; i < structVal.NumField(); i++ { field := structTyp.Field(i) - fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) + //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) if field.Type.Kind() == reflect.Ptr { a := structVal.Field(i).Elem().Interface() fmt.Println(structVal.Field(i).Elem()) @@ -439,8 +466,16 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri for key, val := range subMap { optionsMap[field.Name+"."+key] = val } + if mapType == reflect.TypeOf((*NetDevs)(nil)) { + // set the option for the network name here + var netName string + optionsMap[field.Name] = &netName + baseCmd.PersistentFlags().StringVarP(&netName, + "netname", "n", "", "Define the network name to configure") + } } else { - fmt.Println(mapType) + // TODO: implement handling of string maps + wwlog.Warn("handling of %v not implemented\n", field.Type) } } else if field.Tag.Get("comment") != "" { @@ -464,3 +499,26 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri } return optionsMap } + +/* Add the netname to the options map, as its only known after the map +command line options have been read out. +*/ +func AddNetname(theMap *map[string]*string) { + foundNetname := false + netname := "" + for key, val := range *theMap { + if key == "NetDevs" { + foundNetname = true + netname = *val + } + } + if foundNetname { + for key, val := range *theMap { + keys := strings.Split(key, ".") + if len(keys) == 2 && keys[0] == "NetDevs" { + (*theMap)[keys[0]+"."+netname+"."+keys[1]] = val + delete(*theMap, key) + } + } + } +} From 29573e26ad4a4b044604e5b16e978969e7a47658 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 5 Jul 2022 22:03:08 +0200 Subject: [PATCH 06/38] added more values --- internal/app/wwctl/node/set/root.go | 78 ++++++--------------------- internal/pkg/node/constructors.go | 6 +-- internal/pkg/node/datastructure.go | 76 +++++++++++++------------- internal/pkg/node/modifiers.go | 4 +- internal/pkg/overlay/datastructure.go | 2 +- 5 files changed, 61 insertions(+), 105 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 30f5ddbc..40ae09ce 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -32,43 +32,16 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } - SetKernelOverride string - SetNetName string - SetNetDev string - SetNetmask string - SetGateway string - SetHwaddr string - SetType string - SetNetOnBoot string - SetNetPrimary string - SetNetDevDel bool - SetClusterName string - SetIpxe string - SetInitOverlay string - SetRuntimeOverlay []string - SetSystemOverlay []string - SetIpmiIpaddr string - SetIpmiNetmask string - SetIpmiPort string - SetIpmiGateway string - SetIpmiUsername string - SetIpmiPassword string - SetIpmiInterface string - SetIpmiWrite string - SetNodeAll bool - SetYes bool - SetProfile string - SetAddProfile []string - SetDelProfile []string - SetForce bool - SetDiscoverable bool - SetUndiscoverable bool - SetTags []string - SetDelTags []string - SetNetTags []string - SetNetDelTags []string - OptionStrMap map[string]*string - KernelStrMapmap map[string]*string + SetNetDevDel bool + SetNodeAll bool + SetYes bool + SetForce bool + SetTags []string + SetDelTags []string + SetNetTags []string + SetNetDelTags []string + OptionStrMap map[string]*string + KernelStrMap map[string]*string ) func init() { @@ -87,41 +60,28 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernelOverride, "kerneloverride", "K", "", "Set kernel override version for nodes") if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := kernel.ListKernels() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") - baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name") - baseCmd.PersistentFlags().StringVarP(&SetInitOverlay, "wwinit", "O", "", "Set the node's initialization overlay") - baseCmd.PersistentFlags().StringSliceVarP(&SetRuntimeOverlay, "runtime", "R", []string{}, "Set the node's runtime overlay") if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := overlay.FindOverlays() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringSliceVarP(&SetSystemOverlay, "system", "S", []string{}, "Set the node's system overlay") if err := baseCmd.RegisterFlagCompletionFunc("system", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := overlay.FindOverlays() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVar(&SetIpmiIpaddr, "ipmiaddr", "", "Set the node's IPMI IP address") - baseCmd.PersistentFlags().StringVar(&SetIpmiNetmask, "ipminetmask", "", "Set the node's IPMI netmask") - baseCmd.PersistentFlags().StringVar(&SetIpmiPort, "ipmiport", "", "Set the node's IPMI port") - baseCmd.PersistentFlags().StringVar(&SetIpmiGateway, "ipmigateway", "", "Set the node's IPMI gateway") - baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") - baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") - baseCmd.PersistentFlags().StringVar(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults: 'lan')") - baseCmd.PersistentFlags().StringVar(&SetIpmiWrite, "ipmiwrite", "", "Enable/disable the write of impi configuration (yes/no)") - baseCmd.PersistentFlags().StringSliceVar(&SetAddProfile, "addprofile", []string{}, "Add Profile(s) to node") - baseCmd.PersistentFlags().StringSliceVar(&SetDelProfile, "delprofile", []string{}, "Remove Profile(s) to node") - baseCmd.PersistentFlags().StringVarP(&SetProfile, "profile", "P", "", "Set the node's profile members (comma separated)") + /* + baseCmd.PersistentFlags().StringSliceVar(&SetAddProfile, "addprofile", []string{}, "Add Profile(s) to node") + baseCmd.PersistentFlags().StringSliceVar(&SetDelProfile, "delprofile", []string{}, "Remove Profile(s) to node") + */ if err := baseCmd.RegisterFlagCompletionFunc("profile", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { var list []string nodeDB, _ := node.New() @@ -133,13 +93,6 @@ func init() { }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Set the node's network device") - baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask") - baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway") - baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address") - baseCmd.PersistentFlags().StringVarP(&SetType, "type", "T", "", "Set the node's network device type") - baseCmd.PersistentFlags().StringVar(&SetNetOnBoot, "onboot", "", "Enable/disable device (yes/no)") - baseCmd.PersistentFlags().StringVar(&SetNetPrimary, "primary", "", "Enable/disable device as primary (yes/no)") baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") baseCmd.PersistentFlags().StringSliceVar(&SetNetTags, "nettag", []string{}, "Define custom tag to network device (key=value)") @@ -152,8 +105,7 @@ func init() { baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") - baseCmd.PersistentFlags().BoolVar(&SetDiscoverable, "discoverable", false, "Make this node discoverable") - baseCmd.PersistentFlags().BoolVar(&SetUndiscoverable, "undiscoverable", false, "Remove the discoverable flag") + //baseCmd.PersistentFlags().BoolVar(&SetUndiscoverable, "undiscoverable", false, "Remove the discoverable flag") } diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 4c4fde56..958cc0de 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -114,7 +114,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Ipmi.UserName.Set(node.Ipmi.UserName) n.Ipmi.Password.Set(node.Ipmi.Password) n.Ipmi.Interface.Set(node.Ipmi.Interface) - n.Ipmi.Write.Set(node.Ipmi.Write) + n.Ipmi.Write.SetB(node.Ipmi.Write) } n.SystemOverlay.SetSlice(node.SystemOverlay) n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) @@ -231,7 +231,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Ipmi.UserName.SetAlt(config.NodeProfiles[p].Ipmi.UserName, p) n.Ipmi.Password.SetAlt(config.NodeProfiles[p].Ipmi.Password, p) n.Ipmi.Interface.SetAlt(config.NodeProfiles[p].Ipmi.Interface, p) - n.Ipmi.Write.SetAlt(config.NodeProfiles[p].Ipmi.Write, p) + n.Ipmi.Write.SetAltB(config.NodeProfiles[p].Ipmi.Write, p) } n.SystemOverlay.SetAltSlice(config.NodeProfiles[p].SystemOverlay, p) n.RuntimeOverlay.SetAltSlice(config.NodeProfiles[p].RuntimeOverlay, p) @@ -366,7 +366,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.Ipmi.UserName.Set(profile.Ipmi.UserName) p.Ipmi.Password.Set(profile.Ipmi.Password) p.Ipmi.Interface.Set(profile.Ipmi.Interface) - p.Ipmi.Write.Set(profile.Ipmi.Write) + p.Ipmi.Write.SetB(profile.Ipmi.Write) } p.RuntimeOverlay.SetSlice(profile.RuntimeOverlay) p.SystemOverlay.SetSlice(profile.SystemOverlay) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 54f51e3b..b7923e85 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -19,63 +19,67 @@ type NodeYaml struct { NodeConf is the datastructure which is stored on disk. */ type NodeConf struct { - Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set arbitrary string comment"` - ClusterName string `yaml:"cluster name,omitempty"` - ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"` - Ipxe string `yaml:"ipxe template,omitempty"` - KernelVersion string `yaml:"kernel version,omitempty"` - KernelOverride string `yaml:"kernel override,omitempty"` - KernelArgs string `yaml:"kernel args,omitempty"` - IpmiUserName string `yaml:"ipmi username,omitempty"` - IpmiPassword string `yaml:"ipmi password,omitempty"` - IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"` - IpmiNetmask string `yaml:"ipmi netmask,omitempty"` - IpmiPort string `yaml:"ipmi port,omitempty"` - IpmiGateway string `yaml:"ipmi gateway,omitempty"` - IpmiInterface string `yaml:"ipmi interface,omitempty"` - IpmiWrite string `yaml:"ipmi write,omitempty"` - RuntimeOverlay []string `yaml:"runtime overlay,omitempty"` - SystemOverlay []string `yaml:"system overlay,omitempty"` + Comment string `yaml:"comment,omitempty" lopt:"comment" comment:"Set arbitrary string comment"` + ClusterName string `yaml:"cluster name,omitempty" lopt:"cluster" sopt:"c" comment:"Set cluster group"` + ContainerName string `yaml:"container name,omitempty" lopt:"container" sopt:"C" comment:"Set container name"` + Ipxe string `yaml:"ipxe template,omitempty" lopt:"ipxe" comment:"Set the iPXE template name"` + // Deprecated start + // Kernel settings here are deprecated and here for backward comptability + KernelVersion string `yaml:"kernel version,omitempty"` + KernelOverride string `yaml:"kernel override,omitempty"` + KernelArgs string `yaml:"kernel args,omitempty"` + // Ipmi settings herer are deprecated and here for backward comptability + IpmiUserName string `yaml:"ipmi username,omitempty"` + IpmiPassword string `yaml:"ipmi password,omitempty"` + IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"` + IpmiNetmask string `yaml:"ipmi netmask,omitempty"` + IpmiPort string `yaml:"ipmi port,omitempty"` + IpmiGateway string `yaml:"ipmi gateway,omitempty"` + IpmiInterface string `yaml:"ipmi interface,omitempty"` + IpmiWrite string `yaml:"ipmi write,omitempty"` + // Deprecated end + RuntimeOverlay []string `yaml:"runtime overlay,omitempty" lopt:"runtime" sopt:"R" comment:"Set the runtime overlay"` + SystemOverlay []string `yaml:"system overlay,omitempty" lopt:"wwinit" sopt:"O" comment:"Set the system overlay"` Kernel *KernelConf `yaml:"kernel,omitempty"` Ipmi *IpmiConf `yaml:"ipmi,omitempty"` Init string `yaml:"init,omitempty" lopt:"init" sopt:"i" comment:"Define the init process to boot the container"` Root string `yaml:"root,omitempty" lopt:"root" comment:"Define the rootfs" ` AssetKey string `yaml:"asset key,omitempty" lopt:"asset" comment:"Set the node's Asset tag (key)"` - Discoverable string `yaml:"discoverable,omitempty"` - Profiles []string `yaml:"profiles,omitempty"` + Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" comment:"Make discoverable in given network (yes/no)"` + Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` Tags map[string]string `yaml:"tags,omitempty"` Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility } type IpmiConf struct { - UserName string `yaml:"username,omitempty"` - Password string `yaml:"password,omitempty"` - Ipaddr string `yaml:"ipaddr,omitempty"` - Netmask string `yaml:"netmask,omitempty"` - Port string `yaml:"port,omitempty"` - Gateway string `yaml:"gateway,omitempty"` - Interface string `yaml:"interface,omitempty"` - Write string `yaml:"write,omitempty"` + UserName string `yaml:"username,omitempty" lopt:"ipmiuser" comment:"Set the IPMI username"` + Password string `yaml:"password,omitempty" lopt:"ipmipass" comment:"Set the IPMI password"` + Ipaddr string `yaml:"ipaddr,omitempty" lopt:"ipmiaddr" comment:"Set the IPMI IP address"` + Netmask string `yaml:"netmask,omitempty" lopt:"ipminetmask" comment:"Set the IPMI netmask"` + Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` + Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` + Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` + Write bool `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` } type KernelConf struct { - Version string `yaml:"version,omitempty"` + Version string `yaml:"version,omitempty lopt:"kerneloverride" sopt:"K" comment:"Set kernel override version` Override string `yaml:"override,omitempty"` Args string `yaml:"args,omitempty" lopt:"kernelargs" sopt:"A" comment:"Set Kernel argument"` } type NetDevs struct { - Type string `yaml:"type,omitempty"` - OnBoot string `yaml:"onboot,omitempty"` - Device string `yaml:"device,omitempty"` - Hwaddr string `yaml:"hwaddr,omitempty"` - Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address" sopt:"I" lopt:"ipaddr"` + Type string `yaml:"type,omitempty" lopt:"type" sopt:"T" comment:"Set device type of given network"` + OnBoot string `yaml:"onboot,omitempty" lopt:"onboot" comment:"Enable/disable network device (yes/no)")` + Device string `yaml:"device,omitempty" lopt:"netdev" sopt:"N" comment:"Set the device for given network"` + Hwaddr string `yaml:"hwaddr,omitempty" lopt:"hwaddr" sopt:"H" comment:"Set the device's HW address for given network` + Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address in given network" sopt:"I" lopt:"ipaddr"` IpCIDR string `yaml:"ipcidr,omitempty"` Ipaddr6 string `yaml:"ip6addr,omitempty"` Prefix string `yaml:"prefix,omitempty"` - Netmask string `yaml:"netmask,omitempty"` - Gateway string `yaml:"gateway,omitempty"` - Primary string `yaml:"primary,omitempty"` + Netmask string `yaml:"netmask,omitempty" lopt:"netmask" sopt:"M" comment:"Set the networks netmask"` + Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway"` + Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)")` Default string `yaml:"default,omitempty"` /* backward compatibility */ Tags map[string]string `yaml:"tags,omitempty"` } diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 7e95c193..44c3b10c 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -79,7 +79,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].Ipmi.UserName = node.Ipmi.UserName.GetReal() config.Nodes[nodeID].Ipmi.Password = node.Ipmi.Password.GetReal() config.Nodes[nodeID].Ipmi.Interface = node.Ipmi.Interface.GetReal() - config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.GetReal() + config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.GetB() } config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetRealSlice() config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetRealSlice() @@ -185,7 +185,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipmi.UserName = profile.Ipmi.UserName.GetReal() config.NodeProfiles[profileID].Ipmi.Password = profile.Ipmi.Password.GetReal() config.NodeProfiles[profileID].Ipmi.Interface = profile.Ipmi.Interface.GetReal() - config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.GetReal() + config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.GetB() } config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetRealSlice() config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetRealSlice() diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 4a0575af..8d5dd534 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -86,7 +86,7 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get() tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get() tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get() - tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get() + tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.GetB() tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print() tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print() tstruct.NetDevs = make(map[string]*node.NetDevs) From c8d70e23ad6e2a8c43509258bdd1e4e0a5adc1c4 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 8 Jul 2022 11:38:10 +0200 Subject: [PATCH 07/38] rebased on new API --- Makefile | 1 + go.mod | 1 + internal/app/wwctl/node/set/main.go | 51 +- internal/app/wwctl/node/set/root.go | 24 +- internal/pkg/api/node/node.go | 326 ++------- internal/pkg/api/routes/v1/routes.proto | 34 +- internal/pkg/api/routes/wwapiv1/routes.pb.go | 642 +++++------------- .../pkg/api/routes/wwapiv1/routes.pb.gw.go | 120 ++-- .../pkg/api/routes/wwapiv1/routes_grpc.pb.go | 48 +- internal/pkg/node/datastructure.go | 34 +- internal/pkg/node/methods.go | 115 +++- 11 files changed, 412 insertions(+), 984 deletions(-) diff --git a/Makefile b/Makefile index 60ec87c6..1197496d 100644 --- a/Makefile +++ b/Makefile @@ -260,6 +260,7 @@ dist: vendor config ## sudo ldconfig # refresh shared library cache. ## To setup protoc-gen-grpc-gateway, see https://github.com/grpc-ecosystem/grpc-gateway proto: + rm -r internal/pkg/api/routes/wwapiv1/ protoc -I internal/pkg/api/routes/v1 -I=. \ --grpc-gateway_out=. \ --grpc-gateway_opt logtostderr=true \ diff --git a/go.mod b/go.mod index b921bcfc..6159de0c 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/creasty/defaults v1.5.2 github.com/fatih/color v1.13.0 github.com/golang/glog v1.0.0 + github.com/golang/protobuf v1.5.2 github.com/google/uuid v1.1.2 github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0 github.com/manifoldco/promptui v0.8.0 diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 42f4bb48..1aa58013 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -10,49 +10,16 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { + realMap := make(map[string]string) + for key, val := range OptionStrMap { + realMap[key] = *val + } set := wwapiv1.NodeSetParameter{ - Comment: SetComment, - Container: SetContainer, - KernelOverride: SetKernelOverride, - KernelArgs: SetKernelArgs, - Netname: SetNetName, - Netdev: SetNetDev, - Ipaddr: SetIpaddr, - Netmask: SetNetmask, - Gateway: SetGateway, - Hwaddr: SetHwaddr, - Type: SetType, - Onboot: SetNetOnBoot, - NetDefault: SetNetPrimary, - NetdevDelete: SetNetDevDel, - Cluster: SetClusterName, - Ipxe: SetIpxe, - InitOverlay: SetInitOverlay, - RuntimeOverlay: SetRuntimeOverlay, - SystemOverlay: SetSystemOverlay, - IpmiIpaddr: SetIpmiIpaddr, - IpmiNetmask: SetIpmiNetmask, - IpmiPort: SetIpmiPort, - IpmiGateway: SetIpmiGateway, - IpmiUsername: SetIpmiUsername, - IpmiPassword: SetIpmiPassword, - IpmiInterface: SetIpmiInterface, - IpmiWrite: SetIpmiWrite, - AllNodes: SetNodeAll, - Profile: SetProfile, - ProfileAdd: SetAddProfile, - ProfileDelete: SetDelProfile, - Force: SetForce, - Init: SetInit, - Discoverable: SetDiscoverable, - Undiscoverable: SetUndiscoverable, - Root: SetRoot, - Tags: SetTags, - TagsDelete: SetDelTags, - AssetKey: SetAssetKey, - NodeNames: args, - NetTags: SetNetTags, - NetDeleteTags: SetNetDelTags, + OptionsStrMap: realMap, + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, } if !SetYes { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 40ae09ce..658d5e79 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -32,16 +32,12 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } - SetNetDevDel bool - SetNodeAll bool - SetYes bool - SetForce bool - SetTags []string - SetDelTags []string - SetNetTags []string - SetNetDelTags []string - OptionStrMap map[string]*string - KernelStrMap map[string]*string + SetNetDevDel bool + SetNodeAll bool + SetYes bool + SetForce bool + OptionStrMap map[string]*string + KernelStrMap map[string]*string ) func init() { @@ -53,7 +49,6 @@ func init() { emptyNodeConf.Ipmi = new(node.IpmiConf) //emptyNodeConf.NetDevs = make(map[string]*node.NetDevs) OptionStrMap = myBase.CreateFlags(emptyNodeConf) - if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() return list, cobra.ShellCompDirectiveNoFileComp @@ -72,7 +67,7 @@ func init() { }); err != nil { log.Println(err) } - if err := baseCmd.RegisterFlagCompletionFunc("system", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if err := baseCmd.RegisterFlagCompletionFunc("wwinit", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := overlay.FindOverlays() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { @@ -95,11 +90,6 @@ func init() { } baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") - baseCmd.PersistentFlags().StringSliceVar(&SetNetTags, "nettag", []string{}, "Define custom tag to network device (key=value)") - baseCmd.PersistentFlags().StringSliceVar(&SetNetDelTags, "netdeltag", []string{}, "Delete tag for network device") - - baseCmd.PersistentFlags().StringSliceVarP(&SetTags, "tag", "t", []string{}, "Define custom tag (key=value)") - baseCmd.PersistentFlags().StringSliceVar(&SetDelTags, "tagdel", []string{}, "Delete tag") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index cf1faaaa..997f7241 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -533,10 +533,11 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB for _, n := range nodes { wwlog.Printf(wwlog.VERBOSE, "Evaluating node: %s\n", n.Id.Get()) - - if set.Comment != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting comment to: %s\n", n.Id.Get(), set.Comment) - n.Comment.Set(set.Comment) + for key, val := range set.OptionsStrMap { + if val != "" { + wwlog.Verbose("node:%s setting %s to %s\n", n.Id.Get(), key, val) + n.SetField(key, val) + } } if set.Container != "" { @@ -544,266 +545,23 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB n.ContainerName.Set(set.Container) } - if set.Init != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting init command to: %s\n", n.Id.Get(), set.Init) - n.Init.Set(set.Init) - } - - if set.Root != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting root to: %s\n", n.Id.Get(), set.Root) - n.Root.Set(set.Root) - } - - if set.AssetKey != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting asset key to: %s\n", n.Id.Get(), set.AssetKey) - n.AssetKey.Set(set.AssetKey) - } - - if set.KernelOverride != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel override to: %s\n", n.Id.Get(), set.KernelOverride) - n.Kernel.Override.Set(set.KernelOverride) - } - - if set.KernelArgs != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel args to: %s\n", n.Id.Get(), set.KernelArgs) - n.Kernel.Args.Set(set.KernelArgs) - } - - if set.Cluster != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting cluster name to: %s\n", n.Id.Get(), set.Cluster) - n.ClusterName.Set(set.Cluster) - } - - if set.Ipxe != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting iPXE template to: %s\n", n.Id.Get(), set.Ipxe) - n.Ipxe.Set(set.Ipxe) - } - - if len(set.RuntimeOverlay) != 0 { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting runtime overlay to: %s\n", n.Id.Get(), set.RuntimeOverlay) - n.RuntimeOverlay.SetSlice(set.RuntimeOverlay) - } - - if len(set.SystemOverlay) != 0 { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting system overlay to: %s\n", n.Id.Get(), set.SystemOverlay) - n.SystemOverlay.SetSlice(set.SystemOverlay) - } - - if set.IpmiIpaddr != "" { - newIpaddr := util.IncrementIPv4(set.IpmiIpaddr, nodeCount) - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP address to: %s\n", n.Id.Get(), newIpaddr) - n.Ipmi.Ipaddr.Set(newIpaddr) - } - - if set.IpmiNetmask != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI netmask to: %s\n", n.Id.Get(), set.IpmiNetmask) - n.Ipmi.Netmask.Set(set.IpmiNetmask) - } - - if set.IpmiPort != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI port to: %s\n", n.Id.Get(), set.IpmiPort) - n.Ipmi.Port.Set(set.IpmiPort) - } - - if set.IpmiGateway != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI gateway to: %s\n", n.Id.Get(), set.IpmiGateway) - n.Ipmi.Gateway.Set(set.IpmiGateway) - } - - if set.IpmiUsername != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP username to: %s\n", n.Id.Get(), set.IpmiUsername) - n.Ipmi.UserName.Set(set.IpmiUsername) - } - - if set.IpmiPassword != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP password to: %s\n", n.Id.Get(), set.IpmiPassword) - n.Ipmi.Password.Set(set.IpmiPassword) - } - - if set.IpmiInterface != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting IPMI IP interface to: %s\n", n.Id.Get(), set.IpmiInterface) - n.Ipmi.Interface.Set(set.IpmiInterface) - } - - if set.IpmiWrite == "yes" || set.Onboot == "y" || set.Onboot == "1" || set.Onboot == "true" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting Ipmiwrite to %s\n", n.Id.Get(), set.IpmiWrite) - n.Ipmi.Write.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting Ipmiwrite to %s\n", n.Id.Get(), set.IpmiWrite) - n.Ipmi.Write.SetB(false) - } - - if set.Discoverable { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting node to discoverable\n", n.Id.Get()) - n.Discoverable.SetB(true) - } - - if set.Undiscoverable { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting node to undiscoverable\n", n.Id.Get()) - n.Discoverable.SetB(false) - } - - if set.Profile != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting profiles to: %s\n", n.Id.Get(), set.Profile) - n.Profiles = []string{set.Profile} - } - - if len(set.ProfileAdd) > 0 { - for _, p := range set.ProfileAdd { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, adding profile '%s'\n", n.Id.Get(), p) - n.Profiles = util.SliceAddUniqueElement(n.Profiles, p) - } - } - - if len(set.ProfileDelete) > 0 { - for _, p := range set.ProfileDelete { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, deleting profile '%s'\n", n.Id.Get(), p) - n.Profiles = util.SliceRemoveElement(n.Profiles, p) - } - } - - if set.Netname != "" { - if _, ok := n.NetDevs[set.Netname]; !ok { - var nd node.NetDevEntry - nd.Tags = make(map[string]*node.Entry) - - n.NetDevs[set.Netname] = &nd - - if set.Netdev == "" { - n.NetDevs[set.Netname].Device.Set(set.Netname) - } - } - var def bool = true - - // NOTE: This is overriding parameters passed in by the caller. - set.Onboot = "yes" - - for _, n := range n.NetDevs { - if n.Primary.GetB() { - def = false - } - } - - if def { - set.NetDefault = "yes" - } - } - - if set.Netdev != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting net Device to: %s\n", n.Id.Get(), set.Netname, set.Netdev) - n.NetDevs[set.Netname].Device.Set(set.Netdev) - } - - if set.Ipaddr != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - newIpaddr := util.IncrementIPv4(set.Ipaddr, nodeCount) - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), set.Netname, newIpaddr) - n.NetDevs[set.Netname].Ipaddr.Set(newIpaddr) - } - - if set.Netmask != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting netmask to: %s\n", n.Id.Get(), set.Netname, set.Netmask) - n.NetDevs[set.Netname].Netmask.Set(set.Netmask) - } - - if set.Gateway != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting gateway to: %s\n", n.Id.Get(), set.Netname, set.Gateway) - n.NetDevs[set.Netname].Gateway.Set(set.Gateway) - } - - if set.Hwaddr != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Id.Get(), set.Netname, set.Hwaddr) - n.NetDevs[set.Netname].Hwaddr.Set(strings.ToLower(set.Hwaddr)) - } - - if set.Type != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Type %s\n", n.Id.Get(), set.Netname, set.Type) - n.NetDevs[set.Netname].Type.Set(set.Type) - } - - if set.Onboot != "" { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - if set.Onboot == "yes" || set.Onboot == "y" || set.Onboot == "1" || set.Onboot == "true" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting ONBOOT\n", n.Id.Get(), set.Netname) - n.NetDevs[set.Netname].OnBoot.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Unsetting ONBOOT\n", n.Id.Get(), set.Netname) - n.NetDevs[set.Netname].OnBoot.SetB(false) - } - } - - if set.NetDefault != "" { - if set.Netname == "" { - err = fmt.Errorf("You must include the '--netname' option") - wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) - return - } - - if set.NetDefault == "yes" || set.NetDefault == "y" || set.NetDefault == "1" || set.NetDefault == "true" { - - // Set all other devices to non-default - for _, n := range n.NetDevs { - n.Primary.SetB(false) + /* + if set.NetdevDelete { + err = checkNetNameRequired(set.Netname) + if err != nil { + return } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting PRIMARY\n", n.Id.Get(), set.Netname) - n.NetDevs[set.Netname].Primary.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Unsetting PRIMARY\n", n.Id.Get(), set.Netname) - n.NetDevs[set.Netname].Primary.SetB(false) + if _, ok := n.NetDevs[set.Netname]; !ok { + err = fmt.Errorf("Network device name doesn't exist: %s", set.Netname) + wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + return + } + + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.Netname) + delete(n.NetDevs, set.Netname) } - } - - if set.NetdevDelete { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - if _, ok := n.NetDevs[set.Netname]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.Netname) - wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.Netname) - delete(n.NetDevs, set.Netname) - } - + */ if len(set.Tags) > 0 { for _, t := range set.Tags { keyval := strings.SplitN(t, "=", 2) @@ -833,36 +591,36 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB delete(n.Tags, key) } } + /* + if len(set.NetTags) > 0 { + for _, t := range set.NetTags { + keyval := strings.SplitN(t, "=", 2) + key := keyval[0] + val := keyval[1] + if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { + var nd node.Entry + n.NetDevs[set.Netname].Tags[key] = &nd + } - if len(set.NetTags) > 0 { - for _, t := range set.NetTags { - keyval := strings.SplitN(t, "=", 2) - key := keyval[0] - val := keyval[1] - if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { - var nd node.Entry - n.NetDevs[set.Netname].Tags[key] = &nd + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting NETTAG '%s'='%s'\n", n.Id.Get(), set.Netname, key, val) + n.NetDevs[set.Netname].Tags[key].Set(val) } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting NETTAG '%s'='%s'\n", n.Id.Get(), set.Netname, key, val) - n.NetDevs[set.Netname].Tags[key].Set(val) } + if len(set.NetDeleteTags) > 0 { + for _, t := range set.NetDeleteTags { + keyval := strings.SplitN(t, "=", 1) + key := keyval[0] + if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { + wwlog.Printf(wwlog.WARN, "Node: %s:%s Key %s does not exist\n", n.Id.Get(), set.Netname, key) + os.Exit(1) + } - } - if len(set.NetDeleteTags) > 0 { - for _, t := range set.NetDeleteTags { - keyval := strings.SplitN(t, "=", 1) - key := keyval[0] - if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { - wwlog.Printf(wwlog.WARN, "Node: %s:%s Key %s does not exist\n", n.Id.Get(), set.Netname, key) - os.Exit(1) + wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Deleting Tag %s\n", n.Id.Get(), set.Netname, key) + delete(n.NetDevs[set.Netname].Tags, key) } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Deleting Tag %s\n", n.Id.Get(), set.Netname, key) - delete(n.NetDevs[set.Netname].Tags, key) } - } - + */ err := nodeDB.NodeUpdate(n) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) diff --git a/internal/pkg/api/routes/v1/routes.proto b/internal/pkg/api/routes/v1/routes.proto index 33998534..0ec910c9 100644 --- a/internal/pkg/api/routes/v1/routes.proto +++ b/internal/pkg/api/routes/v1/routes.proto @@ -157,46 +157,14 @@ message NodeDeleteParameter { // NodeSetParameter contains all fields for updating aspects of nodes managed // by Warewulf. message NodeSetParameter { - string comment = 1; + map optionsStrMap = 1; string container = 2; - string kernelOverride = 3; - string kernelArgs = 4; - string netname = 5; - string netdev = 6; - string ipaddr = 7; - string netmask = 8; - string gateway = 9; - string hwaddr = 10; - string type = 11; - string onboot = 12; - string netDefault = 13; bool netdevDelete = 14; - string cluster = 15; - string ipxe = 16; - string initOverlay = 17; - repeated string runtimeOverlay = 18; - repeated string systemOverlay = 19; - string ipmiIpaddr = 20; - string ipmiNetmask = 21; - string ipmiPort = 22; - string ipmiGateway = 23; - string ipmiUsername = 24; - string ipmiPassword = 25; - string ipmiInterface = 26; bool allNodes = 27; - string profile = 28; - repeated string profileAdd = 29; - repeated string profileDelete = 30; bool force = 31; - string init = 32; - bool discoverable = 33; - bool undiscoverable = 34; - string root = 35; repeated string tags = 36; repeated string tagsDelete = 37; - string assetKey = 38; repeated string nodeNames = 39; - string ipmiWrite = 40; repeated string NetTags = 41; repeated string NetDeleteTags = 42; } diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.go b/internal/pkg/api/routes/wwapiv1/routes.pb.go index fcfc7adb..83a8be7a 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.go @@ -3,17 +3,17 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.21.1 +// protoc-gen-go v1.28.0 +// protoc v3.9.2 // source: routes.proto package wwapiv1 import ( + empty "github.com/golang/protobuf/ptypes/empty" _ "google.golang.org/genproto/googleapis/api/annotations" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) @@ -1228,48 +1228,16 @@ type NodeSetParameter struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Comment string `protobuf:"bytes,1,opt,name=comment,proto3" json:"comment,omitempty"` - Container string `protobuf:"bytes,2,opt,name=container,proto3" json:"container,omitempty"` - KernelOverride string `protobuf:"bytes,3,opt,name=kernelOverride,proto3" json:"kernelOverride,omitempty"` - KernelArgs string `protobuf:"bytes,4,opt,name=kernelArgs,proto3" json:"kernelArgs,omitempty"` - Netname string `protobuf:"bytes,5,opt,name=netname,proto3" json:"netname,omitempty"` - Netdev string `protobuf:"bytes,6,opt,name=netdev,proto3" json:"netdev,omitempty"` - Ipaddr string `protobuf:"bytes,7,opt,name=ipaddr,proto3" json:"ipaddr,omitempty"` - Netmask string `protobuf:"bytes,8,opt,name=netmask,proto3" json:"netmask,omitempty"` - Gateway string `protobuf:"bytes,9,opt,name=gateway,proto3" json:"gateway,omitempty"` - Hwaddr string `protobuf:"bytes,10,opt,name=hwaddr,proto3" json:"hwaddr,omitempty"` - Type string `protobuf:"bytes,11,opt,name=type,proto3" json:"type,omitempty"` - Onboot string `protobuf:"bytes,12,opt,name=onboot,proto3" json:"onboot,omitempty"` - NetDefault string `protobuf:"bytes,13,opt,name=netDefault,proto3" json:"netDefault,omitempty"` - NetdevDelete bool `protobuf:"varint,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` - Cluster string `protobuf:"bytes,15,opt,name=cluster,proto3" json:"cluster,omitempty"` - Ipxe string `protobuf:"bytes,16,opt,name=ipxe,proto3" json:"ipxe,omitempty"` - InitOverlay string `protobuf:"bytes,17,opt,name=initOverlay,proto3" json:"initOverlay,omitempty"` - RuntimeOverlay []string `protobuf:"bytes,18,rep,name=runtimeOverlay,proto3" json:"runtimeOverlay,omitempty"` - SystemOverlay []string `protobuf:"bytes,19,rep,name=systemOverlay,proto3" json:"systemOverlay,omitempty"` - IpmiIpaddr string `protobuf:"bytes,20,opt,name=ipmiIpaddr,proto3" json:"ipmiIpaddr,omitempty"` - IpmiNetmask string `protobuf:"bytes,21,opt,name=ipmiNetmask,proto3" json:"ipmiNetmask,omitempty"` - IpmiPort string `protobuf:"bytes,22,opt,name=ipmiPort,proto3" json:"ipmiPort,omitempty"` - IpmiGateway string `protobuf:"bytes,23,opt,name=ipmiGateway,proto3" json:"ipmiGateway,omitempty"` - IpmiUsername string `protobuf:"bytes,24,opt,name=ipmiUsername,proto3" json:"ipmiUsername,omitempty"` - IpmiPassword string `protobuf:"bytes,25,opt,name=ipmiPassword,proto3" json:"ipmiPassword,omitempty"` - IpmiInterface string `protobuf:"bytes,26,opt,name=ipmiInterface,proto3" json:"ipmiInterface,omitempty"` - AllNodes bool `protobuf:"varint,27,opt,name=allNodes,proto3" json:"allNodes,omitempty"` - Profile string `protobuf:"bytes,28,opt,name=profile,proto3" json:"profile,omitempty"` - ProfileAdd []string `protobuf:"bytes,29,rep,name=profileAdd,proto3" json:"profileAdd,omitempty"` - ProfileDelete []string `protobuf:"bytes,30,rep,name=profileDelete,proto3" json:"profileDelete,omitempty"` - Force bool `protobuf:"varint,31,opt,name=force,proto3" json:"force,omitempty"` - Init string `protobuf:"bytes,32,opt,name=init,proto3" json:"init,omitempty"` - Discoverable bool `protobuf:"varint,33,opt,name=discoverable,proto3" json:"discoverable,omitempty"` - Undiscoverable bool `protobuf:"varint,34,opt,name=undiscoverable,proto3" json:"undiscoverable,omitempty"` - Root string `protobuf:"bytes,35,opt,name=root,proto3" json:"root,omitempty"` - Tags []string `protobuf:"bytes,36,rep,name=tags,proto3" json:"tags,omitempty"` - TagsDelete []string `protobuf:"bytes,37,rep,name=tagsDelete,proto3" json:"tagsDelete,omitempty"` - AssetKey string `protobuf:"bytes,38,opt,name=assetKey,proto3" json:"assetKey,omitempty"` - NodeNames []string `protobuf:"bytes,39,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` - IpmiWrite string `protobuf:"bytes,40,opt,name=ipmiWrite,proto3" json:"ipmiWrite,omitempty"` - NetTags []string `protobuf:"bytes,41,rep,name=NetTags,proto3" json:"NetTags,omitempty"` - NetDeleteTags []string `protobuf:"bytes,42,rep,name=NetDeleteTags,proto3" json:"NetDeleteTags,omitempty"` + OptionsStrMap map[string]string `protobuf:"bytes,1,rep,name=optionsStrMap,proto3" json:"optionsStrMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Container string `protobuf:"bytes,2,opt,name=container,proto3" json:"container,omitempty"` + NetdevDelete bool `protobuf:"varint,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` + AllNodes bool `protobuf:"varint,27,opt,name=allNodes,proto3" json:"allNodes,omitempty"` + Force bool `protobuf:"varint,31,opt,name=force,proto3" json:"force,omitempty"` + Tags []string `protobuf:"bytes,36,rep,name=tags,proto3" json:"tags,omitempty"` + TagsDelete []string `protobuf:"bytes,37,rep,name=tagsDelete,proto3" json:"tagsDelete,omitempty"` + NodeNames []string `protobuf:"bytes,39,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` + NetTags []string `protobuf:"bytes,41,rep,name=NetTags,proto3" json:"NetTags,omitempty"` + NetDeleteTags []string `protobuf:"bytes,42,rep,name=NetDeleteTags,proto3" json:"NetDeleteTags,omitempty"` } func (x *NodeSetParameter) Reset() { @@ -1304,11 +1272,11 @@ func (*NodeSetParameter) Descriptor() ([]byte, []int) { return file_routes_proto_rawDescGZIP(), []int{15} } -func (x *NodeSetParameter) GetComment() string { +func (x *NodeSetParameter) GetOptionsStrMap() map[string]string { if x != nil { - return x.Comment + return x.OptionsStrMap } - return "" + return nil } func (x *NodeSetParameter) GetContainer() string { @@ -1318,83 +1286,6 @@ func (x *NodeSetParameter) GetContainer() string { return "" } -func (x *NodeSetParameter) GetKernelOverride() string { - if x != nil { - return x.KernelOverride - } - return "" -} - -func (x *NodeSetParameter) GetKernelArgs() string { - if x != nil { - return x.KernelArgs - } - return "" -} - -func (x *NodeSetParameter) GetNetname() string { - if x != nil { - return x.Netname - } - return "" -} - -func (x *NodeSetParameter) GetNetdev() string { - if x != nil { - return x.Netdev - } - return "" -} - -func (x *NodeSetParameter) GetIpaddr() string { - if x != nil { - return x.Ipaddr - } - return "" -} - -func (x *NodeSetParameter) GetNetmask() string { - if x != nil { - return x.Netmask - } - return "" -} - -func (x *NodeSetParameter) GetGateway() string { - if x != nil { - return x.Gateway - } - return "" -} - -func (x *NodeSetParameter) GetHwaddr() string { - if x != nil { - return x.Hwaddr - } - return "" -} - -func (x *NodeSetParameter) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *NodeSetParameter) GetOnboot() string { - if x != nil { - return x.Onboot - } - return "" -} - -func (x *NodeSetParameter) GetNetDefault() string { - if x != nil { - return x.NetDefault - } - return "" -} - func (x *NodeSetParameter) GetNetdevDelete() bool { if x != nil { return x.NetdevDelete @@ -1402,90 +1293,6 @@ func (x *NodeSetParameter) GetNetdevDelete() bool { return false } -func (x *NodeSetParameter) GetCluster() string { - if x != nil { - return x.Cluster - } - return "" -} - -func (x *NodeSetParameter) GetIpxe() string { - if x != nil { - return x.Ipxe - } - return "" -} - -func (x *NodeSetParameter) GetInitOverlay() string { - if x != nil { - return x.InitOverlay - } - return "" -} - -func (x *NodeSetParameter) GetRuntimeOverlay() []string { - if x != nil { - return x.RuntimeOverlay - } - return nil -} - -func (x *NodeSetParameter) GetSystemOverlay() []string { - if x != nil { - return x.SystemOverlay - } - return nil -} - -func (x *NodeSetParameter) GetIpmiIpaddr() string { - if x != nil { - return x.IpmiIpaddr - } - return "" -} - -func (x *NodeSetParameter) GetIpmiNetmask() string { - if x != nil { - return x.IpmiNetmask - } - return "" -} - -func (x *NodeSetParameter) GetIpmiPort() string { - if x != nil { - return x.IpmiPort - } - return "" -} - -func (x *NodeSetParameter) GetIpmiGateway() string { - if x != nil { - return x.IpmiGateway - } - return "" -} - -func (x *NodeSetParameter) GetIpmiUsername() string { - if x != nil { - return x.IpmiUsername - } - return "" -} - -func (x *NodeSetParameter) GetIpmiPassword() string { - if x != nil { - return x.IpmiPassword - } - return "" -} - -func (x *NodeSetParameter) GetIpmiInterface() string { - if x != nil { - return x.IpmiInterface - } - return "" -} - func (x *NodeSetParameter) GetAllNodes() bool { if x != nil { return x.AllNodes @@ -1493,27 +1300,6 @@ func (x *NodeSetParameter) GetAllNodes() bool { return false } -func (x *NodeSetParameter) GetProfile() string { - if x != nil { - return x.Profile - } - return "" -} - -func (x *NodeSetParameter) GetProfileAdd() []string { - if x != nil { - return x.ProfileAdd - } - return nil -} - -func (x *NodeSetParameter) GetProfileDelete() []string { - if x != nil { - return x.ProfileDelete - } - return nil -} - func (x *NodeSetParameter) GetForce() bool { if x != nil { return x.Force @@ -1521,34 +1307,6 @@ func (x *NodeSetParameter) GetForce() bool { return false } -func (x *NodeSetParameter) GetInit() string { - if x != nil { - return x.Init - } - return "" -} - -func (x *NodeSetParameter) GetDiscoverable() bool { - if x != nil { - return x.Discoverable - } - return false -} - -func (x *NodeSetParameter) GetUndiscoverable() bool { - if x != nil { - return x.Undiscoverable - } - return false -} - -func (x *NodeSetParameter) GetRoot() string { - if x != nil { - return x.Root - } - return "" -} - func (x *NodeSetParameter) GetTags() []string { if x != nil { return x.Tags @@ -1563,13 +1321,6 @@ func (x *NodeSetParameter) GetTagsDelete() []string { return nil } -func (x *NodeSetParameter) GetAssetKey() string { - if x != nil { - return x.AssetKey - } - return "" -} - func (x *NodeSetParameter) GetNodeNames() []string { if x != nil { return x.NodeNames @@ -1577,13 +1328,6 @@ func (x *NodeSetParameter) GetNodeNames() []string { return nil } -func (x *NodeSetParameter) GetIpmiWrite() string { - if x != nil { - return x.IpmiWrite - } - return "" -} - func (x *NodeSetParameter) GetNetTags() []string { if x != nil { return x.NetTags @@ -2011,177 +1755,125 @@ var file_routes_proto_rawDesc = []byte{ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xf6, 0x09, 0x0a, 0x10, + 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xaf, 0x03, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x26, 0x0a, 0x0e, 0x6b, 0x65, 0x72, 0x6e, - 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, - 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x65, - 0x74, 0x64, 0x65, 0x76, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x65, 0x74, 0x64, - 0x65, 0x76, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, - 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, - 0x6d, 0x61, 0x73, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x68, 0x77, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x68, 0x77, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x6e, - 0x62, 0x6f, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x6e, 0x62, 0x6f, - 0x6f, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x69, 0x70, 0x78, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x69, 0x70, 0x78, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x4f, 0x76, 0x65, 0x72, - 0x6c, 0x61, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x4f, - 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x18, 0x12, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x24, - 0x0a, 0x0d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x18, - 0x13, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4f, 0x76, 0x65, - 0x72, 0x6c, 0x61, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x70, 0x6d, 0x69, 0x49, 0x70, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x70, 0x6d, 0x69, 0x49, 0x70, - 0x61, 0x64, 0x64, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x73, 0x6b, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x4e, - 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x70, 0x6d, 0x69, 0x50, 0x6f, - 0x72, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x6d, 0x69, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x70, 0x6d, 0x69, 0x55, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x70, 0x6d, 0x69, - 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x70, 0x6d, 0x69, - 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x69, 0x70, 0x6d, 0x69, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x24, 0x0a, 0x0d, - 0x69, 0x70, 0x6d, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x1a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x69, 0x70, 0x6d, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x1b, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x41, 0x64, 0x64, 0x18, 0x1d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x41, 0x64, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0d, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, - 0x6f, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x20, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0e, - 0x75, 0x6e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x22, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x6e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x23, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x18, 0x24, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, - 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x25, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0a, 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x26, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x70, 0x6d, 0x69, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x70, 0x6d, 0x69, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x18, - 0x29, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x24, - 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x18, - 0x2a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x54, 0x61, 0x67, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, - 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, - 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, - 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, - 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, - 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, - 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, - 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, + 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, + 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, + 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, + 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, + 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, + 0x73, 0x18, 0x24, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x25, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4e, + 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x18, 0x29, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4e, 0x65, + 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x18, 0x2a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x65, + 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, + 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, + 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, + 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, + 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, + 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, + 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, + 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, + 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, + 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, + 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, - 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, - 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, - 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, - 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, - 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, + 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, + 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, + 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, + 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, - 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, - 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, - 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, - 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, - 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, - 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, - 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, + 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, + 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, + 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, + 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, + 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, + 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, + 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, + 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2196,7 +1888,7 @@ func file_routes_proto_rawDescGZIP() []byte { return file_routes_proto_rawDescData } -var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_routes_proto_goTypes = []interface{}{ (*ContainerBuildParameter)(nil), // 0: wwapi.v1.ContainerBuildParameter (*ContainerDeleteParameter)(nil), // 1: wwapi.v1.ContainerDeleteParameter @@ -2221,7 +1913,8 @@ var file_routes_proto_goTypes = []interface{}{ nil, // 20: wwapi.v1.NodeInfo.NetDevsEntry nil, // 21: wwapi.v1.NodeInfo.TagsEntry nil, // 22: wwapi.v1.NodeInfo.KeysEntry - (*emptypb.Empty)(nil), // 23: google.protobuf.Empty + nil, // 23: wwapi.v1.NodeSetParameter.OptionsStrMapEntry + (*empty.Empty)(nil), // 24: google.protobuf.Empty } var file_routes_proto_depIdxs = []int32{ 3, // 0: wwapi.v1.ContainerListResponse.containers:type_name -> wwapi.v1.ContainerInfo @@ -2258,38 +1951,39 @@ var file_routes_proto_depIdxs = []int32{ 21, // 31: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry 22, // 32: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry 11, // 33: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo - 16, // 34: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus - 9, // 35: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField - 10, // 36: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev - 9, // 37: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField - 9, // 38: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField - 0, // 39: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter - 1, // 40: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter - 2, // 41: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter - 23, // 42: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty - 5, // 43: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter - 13, // 44: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter - 14, // 45: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter - 8, // 46: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames - 15, // 47: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter - 8, // 48: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames - 23, // 49: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty - 4, // 50: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse - 23, // 51: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty - 4, // 52: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse - 4, // 53: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse - 6, // 54: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse - 12, // 55: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse - 23, // 56: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty - 12, // 57: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse - 12, // 58: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse - 17, // 59: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse - 18, // 60: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse - 50, // [50:61] is the sub-list for method output_type - 39, // [39:50] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 23, // 34: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry + 16, // 35: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus + 9, // 36: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField + 10, // 37: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev + 9, // 38: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField + 9, // 39: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField + 0, // 40: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter + 1, // 41: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter + 2, // 42: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter + 24, // 43: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty + 5, // 44: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter + 13, // 45: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter + 14, // 46: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter + 8, // 47: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames + 15, // 48: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter + 8, // 49: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames + 24, // 50: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty + 4, // 51: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse + 24, // 52: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty + 4, // 53: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse + 4, // 54: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse + 6, // 55: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse + 12, // 56: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse + 24, // 57: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty + 12, // 58: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse + 12, // 59: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse + 17, // 60: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse + 18, // 61: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse + 51, // [51:62] is the sub-list for method output_type + 40, // [40:51] is the sub-list for method input_type + 40, // [40:40] is the sub-list for extension type_name + 40, // [40:40] is the sub-list for extension extendee + 0, // [0:40] is the sub-list for field type_name } func init() { file_routes_proto_init() } @@ -2533,7 +2227,7 @@ func file_routes_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_routes_proto_rawDesc, NumEnums: 0, - NumMessages: 23, + NumMessages: 24, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.gw.go b/internal/pkg/api/routes/wwapiv1/routes.pb.gw.go index 167091fb..b7591bea 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.gw.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/ptypes/empty" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" @@ -21,7 +22,6 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/emptypb" ) // Suppress "imported and not used" errors @@ -137,7 +137,7 @@ func local_request_WWApi_ContainerImport_0(ctx context.Context, marshaler runtim } func request_WWApi_ContainerList_0(ctx context.Context, marshaler runtime.Marshaler, client WWApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty + var protoReq empty.Empty var metadata runtime.ServerMetadata msg, err := client.ContainerList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -146,7 +146,7 @@ func request_WWApi_ContainerList_0(ctx context.Context, marshaler runtime.Marsha } func local_request_WWApi_ContainerList_0(ctx context.Context, marshaler runtime.Marshaler, server WWApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty + var protoReq empty.Empty var metadata runtime.ServerMetadata msg, err := server.ContainerList(ctx, &protoReq) @@ -367,7 +367,7 @@ func local_request_WWApi_NodeStatus_0(ctx context.Context, marshaler runtime.Mar } func request_WWApi_Version_0(ctx context.Context, marshaler runtime.Marshaler, client WWApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty + var protoReq empty.Empty var metadata runtime.ServerMetadata msg, err := client.Version(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -376,7 +376,7 @@ func request_WWApi_Version_0(ctx context.Context, marshaler runtime.Marshaler, c } func local_request_WWApi_Version_0(ctx context.Context, marshaler runtime.Marshaler, server WWApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq emptypb.Empty + var protoReq empty.Empty var metadata runtime.ServerMetadata msg, err := server.Version(ctx, &protoReq) @@ -396,13 +396,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerBuild", runtime.WithHTTPPathPattern("/v1/containerbuild")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerBuild", runtime.WithHTTPPathPattern("/v1/containerbuild")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_ContainerBuild_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_ContainerBuild_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -420,13 +419,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerDelete", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerDelete", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_ContainerDelete_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_ContainerDelete_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -444,13 +442,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerImport", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerImport", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_ContainerImport_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_ContainerImport_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -468,13 +465,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerList", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerList", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_ContainerList_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_ContainerList_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -492,13 +488,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerShow", runtime.WithHTTPPathPattern("/v1/containershow")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerShow", runtime.WithHTTPPathPattern("/v1/containershow")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_ContainerShow_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_ContainerShow_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -516,13 +511,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeAdd", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeAdd", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_NodeAdd_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_NodeAdd_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -540,13 +534,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeDelete", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeDelete", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_NodeDelete_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_NodeDelete_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -564,13 +557,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeList", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeList", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_NodeList_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_NodeList_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -588,13 +580,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeSet", runtime.WithHTTPPathPattern("/v1/nodeset")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeSet", runtime.WithHTTPPathPattern("/v1/nodeset")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_NodeSet_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_NodeSet_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -612,13 +603,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeStatus", runtime.WithHTTPPathPattern("/v1/nodestatus")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeStatus", runtime.WithHTTPPathPattern("/v1/nodestatus")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_NodeStatus_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_NodeStatus_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -636,13 +626,12 @@ func RegisterWWApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/Version", runtime.WithHTTPPathPattern("/version")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/wwapi.v1.WWApi/Version", runtime.WithHTTPPathPattern("/version")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_WWApi_Version_0(ctx, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_WWApi_Version_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { @@ -699,13 +688,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerBuild", runtime.WithHTTPPathPattern("/v1/containerbuild")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerBuild", runtime.WithHTTPPathPattern("/v1/containerbuild")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_ContainerBuild_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_ContainerBuild_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -720,13 +708,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerDelete", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerDelete", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_ContainerDelete_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_ContainerDelete_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -741,13 +728,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerImport", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerImport", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_ContainerImport_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_ContainerImport_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -762,13 +748,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerList", runtime.WithHTTPPathPattern("/v1/container")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerList", runtime.WithHTTPPathPattern("/v1/container")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_ContainerList_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_ContainerList_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -783,13 +768,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerShow", runtime.WithHTTPPathPattern("/v1/containershow")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/ContainerShow", runtime.WithHTTPPathPattern("/v1/containershow")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_ContainerShow_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_ContainerShow_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -804,13 +788,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeAdd", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeAdd", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_NodeAdd_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_NodeAdd_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -825,13 +808,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeDelete", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeDelete", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_NodeDelete_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_NodeDelete_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -846,13 +828,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeList", runtime.WithHTTPPathPattern("/v1/node")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeList", runtime.WithHTTPPathPattern("/v1/node")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_NodeList_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_NodeList_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -867,13 +848,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeSet", runtime.WithHTTPPathPattern("/v1/nodeset")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeSet", runtime.WithHTTPPathPattern("/v1/nodeset")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_NodeSet_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_NodeSet_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -888,13 +868,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeStatus", runtime.WithHTTPPathPattern("/v1/nodestatus")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/NodeStatus", runtime.WithHTTPPathPattern("/v1/nodestatus")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_NodeStatus_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_NodeStatus_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -909,13 +888,12 @@ func RegisterWWApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - ctx, err = runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/Version", runtime.WithHTTPPathPattern("/version")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/wwapi.v1.WWApi/Version", runtime.WithHTTPPathPattern("/version")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_WWApi_Version_0(ctx, inboundMarshaler, client, req, pathParams) + resp, md, err := request_WWApi_Version_0(rctx, inboundMarshaler, client, req, pathParams) ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) diff --git a/internal/pkg/api/routes/wwapiv1/routes_grpc.pb.go b/internal/pkg/api/routes/wwapiv1/routes_grpc.pb.go index 4c5096b5..d31185f6 100644 --- a/internal/pkg/api/routes/wwapiv1/routes_grpc.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes_grpc.pb.go @@ -1,17 +1,17 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.1 +// - protoc v3.9.2 // source: routes.proto package wwapiv1 import ( context "context" + empty "github.com/golang/protobuf/ptypes/empty" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file @@ -26,18 +26,18 @@ type WWApiClient interface { // ContainerBuild builds zero or more containers. ContainerBuild(ctx context.Context, in *ContainerBuildParameter, opts ...grpc.CallOption) (*ContainerListResponse, error) // ContainerDelete removes one or more container from Warewulf management. - ContainerDelete(ctx context.Context, in *ContainerDeleteParameter, opts ...grpc.CallOption) (*emptypb.Empty, error) + ContainerDelete(ctx context.Context, in *ContainerDeleteParameter, opts ...grpc.CallOption) (*empty.Empty, error) // ContainerImport imports a container to Warewulf. ContainerImport(ctx context.Context, in *ContainerImportParameter, opts ...grpc.CallOption) (*ContainerListResponse, error) // ContainerList lists ContainerInfo for each container. - ContainerList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ContainerListResponse, error) + ContainerList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ContainerListResponse, error) // ContainerShow lists ContainerShow for each container. ContainerShow(ctx context.Context, in *ContainerShowParameter, opts ...grpc.CallOption) (*ContainerShowResponse, error) // NodeAdd adds one or more nodes for management by Warewulf and returns // the added nodes. Node fields may be shimmed in per profiles. NodeAdd(ctx context.Context, in *NodeAddParameter, opts ...grpc.CallOption) (*NodeListResponse, error) // NodeDelete removes one or more nodes from Warewulf management. - NodeDelete(ctx context.Context, in *NodeDeleteParameter, opts ...grpc.CallOption) (*emptypb.Empty, error) + NodeDelete(ctx context.Context, in *NodeDeleteParameter, opts ...grpc.CallOption) (*empty.Empty, error) // NodeList lists some or all nodes managed by Warewulf. NodeList(ctx context.Context, in *NodeNames, opts ...grpc.CallOption) (*NodeListResponse, error) // NodeSet updates node fields for one or more nodes. @@ -47,7 +47,7 @@ type WWApiClient interface { NodeStatus(ctx context.Context, in *NodeNames, opts ...grpc.CallOption) (*NodeStatusResponse, error) // Version returns the wwapi version, the api prefix, and the Warewulf // version. This is also useful for testing if the service is up. - Version(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*VersionResponse, error) + Version(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*VersionResponse, error) } type wWApiClient struct { @@ -67,8 +67,8 @@ func (c *wWApiClient) ContainerBuild(ctx context.Context, in *ContainerBuildPara return out, nil } -func (c *wWApiClient) ContainerDelete(ctx context.Context, in *ContainerDeleteParameter, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) +func (c *wWApiClient) ContainerDelete(ctx context.Context, in *ContainerDeleteParameter, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) err := c.cc.Invoke(ctx, "/wwapi.v1.WWApi/ContainerDelete", in, out, opts...) if err != nil { return nil, err @@ -85,7 +85,7 @@ func (c *wWApiClient) ContainerImport(ctx context.Context, in *ContainerImportPa return out, nil } -func (c *wWApiClient) ContainerList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ContainerListResponse, error) { +func (c *wWApiClient) ContainerList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ContainerListResponse, error) { out := new(ContainerListResponse) err := c.cc.Invoke(ctx, "/wwapi.v1.WWApi/ContainerList", in, out, opts...) if err != nil { @@ -112,8 +112,8 @@ func (c *wWApiClient) NodeAdd(ctx context.Context, in *NodeAddParameter, opts .. return out, nil } -func (c *wWApiClient) NodeDelete(ctx context.Context, in *NodeDeleteParameter, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) +func (c *wWApiClient) NodeDelete(ctx context.Context, in *NodeDeleteParameter, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) err := c.cc.Invoke(ctx, "/wwapi.v1.WWApi/NodeDelete", in, out, opts...) if err != nil { return nil, err @@ -148,7 +148,7 @@ func (c *wWApiClient) NodeStatus(ctx context.Context, in *NodeNames, opts ...grp return out, nil } -func (c *wWApiClient) Version(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*VersionResponse, error) { +func (c *wWApiClient) Version(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*VersionResponse, error) { out := new(VersionResponse) err := c.cc.Invoke(ctx, "/wwapi.v1.WWApi/Version", in, out, opts...) if err != nil { @@ -164,18 +164,18 @@ type WWApiServer interface { // ContainerBuild builds zero or more containers. ContainerBuild(context.Context, *ContainerBuildParameter) (*ContainerListResponse, error) // ContainerDelete removes one or more container from Warewulf management. - ContainerDelete(context.Context, *ContainerDeleteParameter) (*emptypb.Empty, error) + ContainerDelete(context.Context, *ContainerDeleteParameter) (*empty.Empty, error) // ContainerImport imports a container to Warewulf. ContainerImport(context.Context, *ContainerImportParameter) (*ContainerListResponse, error) // ContainerList lists ContainerInfo for each container. - ContainerList(context.Context, *emptypb.Empty) (*ContainerListResponse, error) + ContainerList(context.Context, *empty.Empty) (*ContainerListResponse, error) // ContainerShow lists ContainerShow for each container. ContainerShow(context.Context, *ContainerShowParameter) (*ContainerShowResponse, error) // NodeAdd adds one or more nodes for management by Warewulf and returns // the added nodes. Node fields may be shimmed in per profiles. NodeAdd(context.Context, *NodeAddParameter) (*NodeListResponse, error) // NodeDelete removes one or more nodes from Warewulf management. - NodeDelete(context.Context, *NodeDeleteParameter) (*emptypb.Empty, error) + NodeDelete(context.Context, *NodeDeleteParameter) (*empty.Empty, error) // NodeList lists some or all nodes managed by Warewulf. NodeList(context.Context, *NodeNames) (*NodeListResponse, error) // NodeSet updates node fields for one or more nodes. @@ -185,7 +185,7 @@ type WWApiServer interface { NodeStatus(context.Context, *NodeNames) (*NodeStatusResponse, error) // Version returns the wwapi version, the api prefix, and the Warewulf // version. This is also useful for testing if the service is up. - Version(context.Context, *emptypb.Empty) (*VersionResponse, error) + Version(context.Context, *empty.Empty) (*VersionResponse, error) mustEmbedUnimplementedWWApiServer() } @@ -196,13 +196,13 @@ type UnimplementedWWApiServer struct { func (UnimplementedWWApiServer) ContainerBuild(context.Context, *ContainerBuildParameter) (*ContainerListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ContainerBuild not implemented") } -func (UnimplementedWWApiServer) ContainerDelete(context.Context, *ContainerDeleteParameter) (*emptypb.Empty, error) { +func (UnimplementedWWApiServer) ContainerDelete(context.Context, *ContainerDeleteParameter) (*empty.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method ContainerDelete not implemented") } func (UnimplementedWWApiServer) ContainerImport(context.Context, *ContainerImportParameter) (*ContainerListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ContainerImport not implemented") } -func (UnimplementedWWApiServer) ContainerList(context.Context, *emptypb.Empty) (*ContainerListResponse, error) { +func (UnimplementedWWApiServer) ContainerList(context.Context, *empty.Empty) (*ContainerListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ContainerList not implemented") } func (UnimplementedWWApiServer) ContainerShow(context.Context, *ContainerShowParameter) (*ContainerShowResponse, error) { @@ -211,7 +211,7 @@ func (UnimplementedWWApiServer) ContainerShow(context.Context, *ContainerShowPar func (UnimplementedWWApiServer) NodeAdd(context.Context, *NodeAddParameter) (*NodeListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NodeAdd not implemented") } -func (UnimplementedWWApiServer) NodeDelete(context.Context, *NodeDeleteParameter) (*emptypb.Empty, error) { +func (UnimplementedWWApiServer) NodeDelete(context.Context, *NodeDeleteParameter) (*empty.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method NodeDelete not implemented") } func (UnimplementedWWApiServer) NodeList(context.Context, *NodeNames) (*NodeListResponse, error) { @@ -223,7 +223,7 @@ func (UnimplementedWWApiServer) NodeSet(context.Context, *NodeSetParameter) (*No func (UnimplementedWWApiServer) NodeStatus(context.Context, *NodeNames) (*NodeStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method NodeStatus not implemented") } -func (UnimplementedWWApiServer) Version(context.Context, *emptypb.Empty) (*VersionResponse, error) { +func (UnimplementedWWApiServer) Version(context.Context, *empty.Empty) (*VersionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Version not implemented") } func (UnimplementedWWApiServer) mustEmbedUnimplementedWWApiServer() {} @@ -294,7 +294,7 @@ func _WWApi_ContainerImport_Handler(srv interface{}, ctx context.Context, dec fu } func _WWApi_ContainerList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) + in := new(empty.Empty) if err := dec(in); err != nil { return nil, err } @@ -306,7 +306,7 @@ func _WWApi_ContainerList_Handler(srv interface{}, ctx context.Context, dec func FullMethod: "/wwapi.v1.WWApi/ContainerList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WWApiServer).ContainerList(ctx, req.(*emptypb.Empty)) + return srv.(WWApiServer).ContainerList(ctx, req.(*empty.Empty)) } return interceptor(ctx, in, info, handler) } @@ -420,7 +420,7 @@ func _WWApi_NodeStatus_Handler(srv interface{}, ctx context.Context, dec func(in } func _WWApi_Version_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) + in := new(empty.Empty) if err := dec(in); err != nil { return nil, err } @@ -432,7 +432,7 @@ func _WWApi_Version_Handler(srv interface{}, ctx context.Context, dec func(inter FullMethod: "/wwapi.v1.WWApi/Version", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WWApiServer).Version(ctx, req.(*emptypb.Empty)) + return srv.(WWApiServer).Version(ctx, req.(*empty.Empty)) } return interceptor(ctx, in, info, handler) } diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index b7923e85..d33d74c3 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -48,40 +48,41 @@ type NodeConf struct { Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" comment:"Make discoverable in given network (yes/no)"` Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` - Tags map[string]string `yaml:"tags,omitempty"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"keys" comment:"base key"` Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility } type IpmiConf struct { - UserName string `yaml:"username,omitempty" lopt:"ipmiuser" comment:"Set the IPMI username"` - Password string `yaml:"password,omitempty" lopt:"ipmipass" comment:"Set the IPMI password"` - Ipaddr string `yaml:"ipaddr,omitempty" lopt:"ipmiaddr" comment:"Set the IPMI IP address"` - Netmask string `yaml:"netmask,omitempty" lopt:"ipminetmask" comment:"Set the IPMI netmask"` - Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` - Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` - Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` - Write bool `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` + UserName string `yaml:"username,omitempty" lopt:"ipmiuser" comment:"Set the IPMI username"` + Password string `yaml:"password,omitempty" lopt:"ipmipass" comment:"Set the IPMI password"` + Ipaddr string `yaml:"ipaddr,omitempty" lopt:"ipmiaddr" comment:"Set the IPMI IP address"` + Netmask string `yaml:"netmask,omitempty" lopt:"ipminetmask" comment:"Set the IPMI netmask"` + Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` + Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` + Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` + Write bool `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"impitag" comment:"ipmi keys"` } type KernelConf struct { - Version string `yaml:"version,omitempty lopt:"kerneloverride" sopt:"K" comment:"Set kernel override version` - Override string `yaml:"override,omitempty"` + Version string `yaml:"version,omitempty"` + Override string `yaml:"override,omitempty" lopt:"kerneloverride" sopt:"K" comment:"Set kernel override version"` Args string `yaml:"args,omitempty" lopt:"kernelargs" sopt:"A" comment:"Set Kernel argument"` } type NetDevs struct { Type string `yaml:"type,omitempty" lopt:"type" sopt:"T" comment:"Set device type of given network"` - OnBoot string `yaml:"onboot,omitempty" lopt:"onboot" comment:"Enable/disable network device (yes/no)")` + OnBoot string `yaml:"onboot,omitempty" lopt:"onboot" comment:"Enable/disable network device (yes/no)"` Device string `yaml:"device,omitempty" lopt:"netdev" sopt:"N" comment:"Set the device for given network"` - Hwaddr string `yaml:"hwaddr,omitempty" lopt:"hwaddr" sopt:"H" comment:"Set the device's HW address for given network` + Hwaddr string `yaml:"hwaddr,omitempty" lopt:"hwaddr" sopt:"H" comment:"Set the device's HW address for given network"` Ipaddr string `yaml:"ipaddr,omitempty" comment:"IPv4 address in given network" sopt:"I" lopt:"ipaddr"` IpCIDR string `yaml:"ipcidr,omitempty"` - Ipaddr6 string `yaml:"ip6addr,omitempty"` + Ipaddr6 string `yaml:"ip6addr,omitempty" lopt:"ipaddr6" comment:"IPv6 address"` Prefix string `yaml:"prefix,omitempty"` Netmask string `yaml:"netmask,omitempty" lopt:"netmask" sopt:"M" comment:"Set the networks netmask"` Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway"` - Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)")` + Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)"` Default string `yaml:"default,omitempty"` /* backward compatibility */ - Tags map[string]string `yaml:"tags,omitempty"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"nettag" comment:"network keys"` } /****** @@ -135,6 +136,7 @@ type IpmiEntry struct { Password Entry Interface Entry Write Entry + Tags map[string]*Entry } type KernelEntry struct { diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index a9b25f23..5c13900c 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -324,46 +324,104 @@ func SetEntry(entryPtr interface{}, val interface{}) { } +/* +Add an entry in a map +*/ +func AddEntry(entryMapInt interface{}, val interface{}) { + if reflect.TypeOf(entryMapInt) == reflect.TypeOf((map[string]*Entry)(nil)) { + entryMap := entryMapInt.(map[string]*Entry) + str, ok := (val).(string) + if !ok { + panic("AddEntry must be called with string value") + } + for _, token := range strings.Split(str, ",") { + keyVal := strings.Split(token, "=") + if len(keyVal) == 2 { + _, mapOk := entryMap[keyVal[0]] + if !mapOk { + var entr Entry + entryMap[keyVal[0]] = &entr + } + entryMap[keyVal[0]].Set(keyVal[1]) + } + } + } +} + +/* +Del an entry in a map +*/ +func DelEntry(entryMapInt interface{}, val interface{}) { + if reflect.TypeOf(entryMapInt) == reflect.TypeOf((map[string]*Entry)(nil)) { + entryMap := entryMapInt.(map[string]*Entry) + str, ok := (val).(string) + if !ok { + panic("DelEntry must be called with string value") + } + for _, token := range strings.Split(str, ",") { + delete(entryMap, token) + } + } + +} + /* Call SetEntry for given field (NodeInfo) */ func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) + fmt.Println("On field:", fieldName) if field.IsValid() { if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { //fmt.Println(reflect.TypeOf(field.Addr().Interface())) SetEntry(field.Addr().Interface(), val) + } else if field.Addr().Kind() == reflect.Map { + fmt.Println(field.Addr()) } else { + fmt.Println("Not working field.Addr().Kind():", field.Addr().Kind()) // is most likely NetDevEntry, ignore it } } else { fieldNames := strings.Split(fieldName, ".") if len(fieldNames) >= 2 { - nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) - if nestedField.IsValid() { - switch nestedField.Addr().Type() { - case reflect.TypeOf((**KernelEntry)(nil)): - entry := nestedField.Addr().Interface().(**KernelEntry) - (*entry).SetField(fieldNames[1], val) - case reflect.TypeOf((**IpmiEntry)(nil)): - entry := nestedField.Addr().Interface().(**IpmiEntry) - (*entry).SetField(fieldNames[1], val) - case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): - if len(fieldNames) == 3 { - entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) - if myVal, ok := (*entryMap)[fieldNames[1]]; ok { - myVal.SetField(fieldNames[2], val) - } else { - var newEntry NetDevEntry - (*entryMap)[fieldNames[1]] = &newEntry - newEntry.SetField(fieldNames[2], val) - } + if fieldNames[0] == "del" || fieldNames[0] == "add" { + fieldMap := reflect.ValueOf(node).Elem().FieldByName(fieldNames[1]) + if fieldMap.IsValid() { + if fieldNames[0] == "del" { + DelEntry(fieldMap.Addr().Elem().Interface(), val) + } else if fieldNames[0] == "add" { + AddEntry(fieldMap.Addr().Elem().Interface(), val) } - default: - panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) + } else { + panic(fmt.Sprintf("invalid del/add operation with name %s called, field %s does not exists\n", fieldName, fieldNames[0])) } } else { - panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) + nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) + if nestedField.IsValid() { + switch nestedField.Addr().Type() { + case reflect.TypeOf((**KernelEntry)(nil)): + entry := nestedField.Addr().Interface().(**KernelEntry) + (*entry).SetField(fieldNames[1], val) + case reflect.TypeOf((**IpmiEntry)(nil)): + entry := nestedField.Addr().Interface().(**IpmiEntry) + (*entry).SetField(fieldNames[1], val) + case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): + if len(fieldNames) == 3 { + entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) + if myVal, ok := (*entryMap)[fieldNames[1]]; ok { + myVal.SetField(fieldNames[2], val) + } else { + var newEntry NetDevEntry + (*entryMap)[fieldNames[1]] = &newEntry + newEntry.SetField(fieldNames[2], val) + } + } + default: + panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) + } + } else { + panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) + } } } else { panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) @@ -451,7 +509,6 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) if field.Type.Kind() == reflect.Ptr { a := structVal.Field(i).Elem().Interface() - fmt.Println(structVal.Field(i).Elem()) subStruct := baseCmd.CreateFlags(a) for key, val := range subStruct { optionsMap[field.Name+"."+key] = val @@ -473,6 +530,17 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri baseCmd.PersistentFlags().StringVarP(&netName, "netname", "n", "", "Define the network name to configure") } + } else if mapType.Kind() == reflect.String { + if field.Tag.Get("lopt") != "" { + var addPair string + optionsMap["add"+"."+field.Name] = &addPair + baseCmd.PersistentFlags().StringVarP(&addPair, + field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) + var delPair string + optionsMap["del"+"."+field.Name] = &delPair + baseCmd.PersistentFlags().StringVarP(&delPair, + field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) + } } else { // TODO: implement handling of string maps wwlog.Warn("handling of %v not implemented\n", field.Type) @@ -497,6 +565,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri } } + fmt.Println(optionsMap) return optionsMap } From 59141a6dacfaec65319e60eb765fec36b80a334d Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 12 Jul 2022 10:42:05 +0200 Subject: [PATCH 08/38] change network hadnling --- internal/app/wwctl/node/set/main.go | 7 + internal/app/wwctl/node/set/root.go | 20 +- internal/pkg/api/node/node.go | 121 +++------- internal/pkg/api/routes/v1/routes.proto | 6 +- internal/pkg/api/routes/wwapiv1/routes.pb.go | 241 ++++++++----------- internal/pkg/node/methods.go | 80 +++--- 6 files changed, 190 insertions(+), 285 deletions(-) diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 1aa58013..1f2d8c21 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -1,6 +1,7 @@ package set import ( + "errors" "fmt" "github.com/hpcng/warewulf/internal/pkg/api/node" @@ -10,10 +11,16 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { + OptionStrMap, haveNetname := node.AddNetname(OptionStrMap) + if !haveNetname { + return errors.New("A netname must be given for any network related configuration\n") + } realMap := make(map[string]string) + for key, val := range OptionStrMap { realMap[key] = *val } + set := wwapiv1.NodeSetParameter{ OptionsStrMap: realMap, NetdevDelete: SetNetDevDel, diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 658d5e79..db906077 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -32,7 +32,7 @@ var ( return node_names, cobra.ShellCompDirectiveNoFileComp }, } - SetNetDevDel bool + SetNetDevDel string SetNodeAll bool SetYes bool SetForce bool @@ -49,6 +49,12 @@ func init() { emptyNodeConf.Ipmi = new(node.IpmiConf) //emptyNodeConf.NetDevs = make(map[string]*node.NetDevs) OptionStrMap = myBase.CreateFlags(emptyNodeConf) + + baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") + baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") + baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") + baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") + // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() return list, cobra.ShellCompDirectiveNoFileComp @@ -73,10 +79,6 @@ func init() { }); err != nil { log.Println(err) } - /* - baseCmd.PersistentFlags().StringSliceVar(&SetAddProfile, "addprofile", []string{}, "Add Profile(s) to node") - baseCmd.PersistentFlags().StringSliceVar(&SetDelProfile, "delprofile", []string{}, "Remove Profile(s) to node") - */ if err := baseCmd.RegisterFlagCompletionFunc("profile", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { var list []string nodeDB, _ := node.New() @@ -89,14 +91,6 @@ func init() { log.Println(err) } - baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") - - baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") - - baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") - baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") - //baseCmd.PersistentFlags().BoolVar(&SetUndiscoverable, "undiscoverable", false, "Remove the discoverable flag") - } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index 997f7241..aed8224e 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -407,13 +407,13 @@ func NodeList(nodeNames []string) (nodeInfo []*wwapiv1.NodeInfo, err error) { Value: node.Ipmi.Interface.Get(), Print: node.Ipmi.Interface.Print(), } - + ni.Tags = map[string]*wwapiv1.NodeField{} for keyname, keyvalue := range node.Tags { + ni.Tags[keyname] = new(wwapiv1.NodeField) ni.Tags[keyname].Source = keyvalue.Source() ni.Tags[keyname].Value = keyvalue.Get() ni.Tags[keyname].Print = keyvalue.Print() } - ni.NetDevs = map[string]*wwapiv1.NetDev{} for name, netdev := range node.NetDevs { @@ -540,87 +540,18 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB } } - if set.Container != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting container name to: %s\n", n.Id.Get(), set.Container) - n.ContainerName.Set(set.Container) + if set.NetdevDelete != "" { + + if _, ok := n.NetDevs[set.NetdevDelete]; !ok { + err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + return + } + + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.NetdevDelete) + delete(n.NetDevs, set.NetdevDelete) } - /* - if set.NetdevDelete { - err = checkNetNameRequired(set.Netname) - if err != nil { - return - } - - if _, ok := n.NetDevs[set.Netname]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.Netname) - wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) - return - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.Netname) - delete(n.NetDevs, set.Netname) - } - */ - if len(set.Tags) > 0 { - for _, t := range set.Tags { - keyval := strings.SplitN(t, "=", 2) - key := keyval[0] - val := keyval[1] - - if _, ok := n.Tags[key]; !ok { - var nd node.Entry - n.Tags[key] = &nd - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting Tag '%s'='%s'\n", n.Id.Get(), key, val) - n.Tags[key].Set(val) - } - } - if len(set.TagsDelete) > 0 { - for _, t := range set.TagsDelete { - keyval := strings.SplitN(t, "=", 1) - key := keyval[0] - - if _, ok := n.Tags[key]; !ok { - wwlog.Printf(wwlog.WARN, "Key does not exist: %s\n", key) - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting tag: %s\n", n.Id.Get(), key) - delete(n.Tags, key) - } - } - /* - if len(set.NetTags) > 0 { - for _, t := range set.NetTags { - keyval := strings.SplitN(t, "=", 2) - key := keyval[0] - val := keyval[1] - if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { - var nd node.Entry - n.NetDevs[set.Netname].Tags[key] = &nd - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting NETTAG '%s'='%s'\n", n.Id.Get(), set.Netname, key, val) - n.NetDevs[set.Netname].Tags[key].Set(val) - } - - } - if len(set.NetDeleteTags) > 0 { - for _, t := range set.NetDeleteTags { - keyval := strings.SplitN(t, "=", 1) - key := keyval[0] - if _, ok := n.NetDevs[set.Netname].Tags[key]; !ok { - wwlog.Printf(wwlog.WARN, "Node: %s:%s Key %s does not exist\n", n.Id.Get(), set.Netname, key) - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Deleting Tag %s\n", n.Id.Get(), set.Netname, key) - delete(n.NetDevs[set.Netname].Tags, key) - } - } - */ err := nodeDB.NodeUpdate(n) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) @@ -744,3 +675,31 @@ func nodeDbSave(nodeDB *node.NodeYaml) (err error) { } return } + +/* +Add the netname to the options map, as its only known after the map +command line options have been read out. +*/ +func AddNetname(theMap map[string]*string) (map[string]*string, bool) { + foundNetname := false + netname := "" + retMap := make(map[string]*string) + for key, val := range theMap { + if key == "NetDevs" { + foundNetname = true + netname = *val + } + } + if foundNetname { + for key, val := range theMap { + keys := strings.Split(key, ".") + myVal := *val + if len(keys) >= 2 && keys[0] == "NetDevs" { + retMap[keys[0]+"."+netname+"."+strings.Join(keys[1:], ".")] = &myVal + } else { + retMap[key] = &myVal + } + } + } + return retMap, foundNetname +} diff --git a/internal/pkg/api/routes/v1/routes.proto b/internal/pkg/api/routes/v1/routes.proto index 0ec910c9..6d653dfa 100644 --- a/internal/pkg/api/routes/v1/routes.proto +++ b/internal/pkg/api/routes/v1/routes.proto @@ -159,14 +159,10 @@ message NodeDeleteParameter { message NodeSetParameter { map optionsStrMap = 1; string container = 2; - bool netdevDelete = 14; + string netdevDelete = 14; bool allNodes = 27; bool force = 31; - repeated string tags = 36; - repeated string tagsDelete = 37; repeated string nodeNames = 39; - repeated string NetTags = 41; - repeated string NetDeleteTags = 42; } // NodeStatus contains information about the imaging status per node. diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.go b/internal/pkg/api/routes/wwapiv1/routes.pb.go index 83a8be7a..4e653252 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.go @@ -1230,14 +1230,10 @@ type NodeSetParameter struct { OptionsStrMap map[string]string `protobuf:"bytes,1,rep,name=optionsStrMap,proto3" json:"optionsStrMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Container string `protobuf:"bytes,2,opt,name=container,proto3" json:"container,omitempty"` - NetdevDelete bool `protobuf:"varint,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` + NetdevDelete string `protobuf:"bytes,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` AllNodes bool `protobuf:"varint,27,opt,name=allNodes,proto3" json:"allNodes,omitempty"` Force bool `protobuf:"varint,31,opt,name=force,proto3" json:"force,omitempty"` - Tags []string `protobuf:"bytes,36,rep,name=tags,proto3" json:"tags,omitempty"` - TagsDelete []string `protobuf:"bytes,37,rep,name=tagsDelete,proto3" json:"tagsDelete,omitempty"` NodeNames []string `protobuf:"bytes,39,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` - NetTags []string `protobuf:"bytes,41,rep,name=NetTags,proto3" json:"NetTags,omitempty"` - NetDeleteTags []string `protobuf:"bytes,42,rep,name=NetDeleteTags,proto3" json:"NetDeleteTags,omitempty"` } func (x *NodeSetParameter) Reset() { @@ -1286,11 +1282,11 @@ func (x *NodeSetParameter) GetContainer() string { return "" } -func (x *NodeSetParameter) GetNetdevDelete() bool { +func (x *NodeSetParameter) GetNetdevDelete() string { if x != nil { return x.NetdevDelete } - return false + return "" } func (x *NodeSetParameter) GetAllNodes() bool { @@ -1307,20 +1303,6 @@ func (x *NodeSetParameter) GetForce() bool { return false } -func (x *NodeSetParameter) GetTags() []string { - if x != nil { - return x.Tags - } - return nil -} - -func (x *NodeSetParameter) GetTagsDelete() []string { - if x != nil { - return x.TagsDelete - } - return nil -} - func (x *NodeSetParameter) GetNodeNames() []string { if x != nil { return x.NodeNames @@ -1328,20 +1310,6 @@ func (x *NodeSetParameter) GetNodeNames() []string { return nil } -func (x *NodeSetParameter) GetNetTags() []string { - if x != nil { - return x.NetTags - } - return nil -} - -func (x *NodeSetParameter) GetNetDeleteTags() []string { - if x != nil { - return x.NetDeleteTags - } - return nil -} - // NodeStatus contains information about the imaging status per node. type NodeStatus struct { state protoimpl.MessageState @@ -1755,7 +1723,7 @@ var file_routes_proto_rawDesc = []byte{ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xaf, 0x03, 0x0a, 0x10, + 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, @@ -1765,115 +1733,108 @@ var file_routes_proto_rawDesc = []byte{ 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, + 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, - 0x73, 0x18, 0x24, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x25, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0a, 0x74, 0x61, 0x67, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1c, 0x0a, - 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x4e, - 0x65, 0x74, 0x54, 0x61, 0x67, 0x73, 0x18, 0x29, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4e, 0x65, - 0x74, 0x54, 0x61, 0x67, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x18, 0x2a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x4e, 0x65, - 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, - 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, - 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, - 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, - 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, - 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, - 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, - 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, - 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, - 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, - 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, - 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, + 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, + 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, + 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, + 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, + 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, + 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, + 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, + 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, + 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, - 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, - 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, - 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, - 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, - 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, - 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, - 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, - 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, - 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, - 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, + 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, + 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, + 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, + 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, + 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, + 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, + 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, + 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, + 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, + 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, + 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 5c13900c..9f24be94 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -328,8 +328,8 @@ func SetEntry(entryPtr interface{}, val interface{}) { Add an entry in a map */ func AddEntry(entryMapInt interface{}, val interface{}) { - if reflect.TypeOf(entryMapInt) == reflect.TypeOf((map[string]*Entry)(nil)) { - entryMap := entryMapInt.(map[string]*Entry) + if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { + entryMap := entryMapInt.(*map[string]*Entry) str, ok := (val).(string) if !ok { panic("AddEntry must be called with string value") @@ -337,14 +337,15 @@ func AddEntry(entryMapInt interface{}, val interface{}) { for _, token := range strings.Split(str, ",") { keyVal := strings.Split(token, "=") if len(keyVal) == 2 { - _, mapOk := entryMap[keyVal[0]] + _, mapOk := (*entryMap)[keyVal[0]] if !mapOk { - var entr Entry - entryMap[keyVal[0]] = &entr + (*entryMap)[keyVal[0]] = new(Entry) } - entryMap[keyVal[0]].Set(keyVal[1]) + (*entryMap)[keyVal[0]].Set(keyVal[1]) } } + } else { + panic(fmt.Sprintf("Do not know how to add %v to %v\n", val, entryMapInt)) } } @@ -352,15 +353,17 @@ func AddEntry(entryMapInt interface{}, val interface{}) { Del an entry in a map */ func DelEntry(entryMapInt interface{}, val interface{}) { - if reflect.TypeOf(entryMapInt) == reflect.TypeOf((map[string]*Entry)(nil)) { - entryMap := entryMapInt.(map[string]*Entry) + if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { + entryMap := entryMapInt.(*map[string]*Entry) str, ok := (val).(string) if !ok { panic("DelEntry must be called with string value") } for _, token := range strings.Split(str, ",") { - delete(entryMap, token) + delete(*entryMap, token) } + } else { + panic(fmt.Sprintf("Do not know how to del %v to %v\n", val, entryMapInt)) } } @@ -370,17 +373,19 @@ Call SetEntry for given field (NodeInfo) */ func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) - fmt.Println("On field:", fieldName) if field.IsValid() { if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { //fmt.Println(reflect.TypeOf(field.Addr().Interface())) SetEntry(field.Addr().Interface(), val) - } else if field.Addr().Kind() == reflect.Map { - fmt.Println(field.Addr()) - } else { - fmt.Println("Not working field.Addr().Kind():", field.Addr().Kind()) - // is most likely NetDevEntry, ignore it } + /* + else if field.Addr().Kind() == reflect.Map { + fmt.Println(field.Addr()) + } else { + //fmt.Println("Not working field.Addr().Kind():", field.Addr().Type()) + // is most likely NetDevEntry, ignore it + } + */ } else { fieldNames := strings.Split(fieldName, ".") if len(fieldNames) >= 2 { @@ -406,14 +411,14 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { entry := nestedField.Addr().Interface().(**IpmiEntry) (*entry).SetField(fieldNames[1], val) case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): - if len(fieldNames) == 3 { + if len(fieldNames) >= 3 { entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) if myVal, ok := (*entryMap)[fieldNames[1]]; ok { - myVal.SetField(fieldNames[2], val) + myVal.SetField(strings.Join(fieldNames[2:], "."), val) } else { var newEntry NetDevEntry (*entryMap)[fieldNames[1]] = &newEntry - newEntry.SetField(fieldNames[2], val) + newEntry.SetField(strings.Join(fieldNames[2:], "."), val) } } default: @@ -450,7 +455,7 @@ func (node *IpmiEntry) SetField(fieldName string, val interface{}) { if field.IsValid() { SetEntry(field.Addr().Interface(), val) } else { - panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + panic(fmt.Sprintf("field %s does not exists in node.ImpiEntry\n", fieldName)) } } @@ -462,7 +467,15 @@ func (node *NetDevEntry) SetField(fieldName string, val interface{}) { if field.IsValid() { SetEntry(field.Addr().Interface(), val) } else { - panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + valFields := strings.Split(fieldName, ".") + field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) + if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { + AddEntry(field.Addr().Interface(), val) + } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { + DelEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) + } } } @@ -483,8 +496,7 @@ func GetOptionsMap(theStruct interface{}) map[string]*string { optionsMap[key] = val } } else if field.Tag.Get("comment") != "" { - var newStr string - optionsMap[field.Name] = &newStr + optionsMap[field.Name] = new(string) } } @@ -565,29 +577,5 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri } } - fmt.Println(optionsMap) return optionsMap } - -/* Add the netname to the options map, as its only known after the map -command line options have been read out. -*/ -func AddNetname(theMap *map[string]*string) { - foundNetname := false - netname := "" - for key, val := range *theMap { - if key == "NetDevs" { - foundNetname = true - netname = *val - } - } - if foundNetname { - for key, val := range *theMap { - keys := strings.Split(key, ".") - if len(keys) == 2 && keys[0] == "NetDevs" { - (*theMap)[keys[0]+"."+netname+"."+keys[1]] = val - delete(*theMap, key) - } - } - } -} From f0eb3f85040c2125361471e6b2faf72fd88ace8d Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 13 Jul 2022 14:43:02 +0200 Subject: [PATCH 09/38] fixed embeded init for linitng --- internal/app/wwctl/node/set/main.go | 2 +- internal/app/wwctl/node/set/root.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 1f2d8c21..24cb5dda 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -13,7 +13,7 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) (err error) { OptionStrMap, haveNetname := node.AddNetname(OptionStrMap) if !haveNetname { - return errors.New("A netname must be given for any network related configuration\n") + return errors.New("a netname must be given for any network related configuration") } realMap := make(map[string]string) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index db906077..f827b605 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -43,7 +43,7 @@ var ( func init() { //var emptyNodeConf node.NodeConf //var emptyKernelE node.KernelEntry - myBase := node.CobraCommand{baseCmd} + myBase := node.CobraCommand{Command: baseCmd} var emptyNodeConf node.NodeConf emptyNodeConf.Kernel = new(node.KernelConf) emptyNodeConf.Ipmi = new(node.IpmiConf) From 14b86a5e8e5fbd670070f6c333c6fa5252283209 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 13 Jul 2022 15:56:04 +0200 Subject: [PATCH 10/38] added profile set over API --- internal/app/wwctl/node/set/main.go | 8 +- internal/app/wwctl/node/set/root.go | 5 +- internal/app/wwctl/profile/set/main.go | 364 ++----------------------- internal/app/wwctl/profile/set/root.go | 95 ++----- internal/pkg/api/node/node.go | 22 +- internal/pkg/api/node/utils.go | 25 ++ internal/pkg/api/profile/profile.go | 109 ++++++++ 7 files changed, 188 insertions(+), 440 deletions(-) create mode 100644 internal/pkg/api/node/utils.go create mode 100644 internal/pkg/api/profile/profile.go diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 24cb5dda..877c9c57 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -4,14 +4,14 @@ import ( "errors" "fmt" - "github.com/hpcng/warewulf/internal/pkg/api/node" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/api/util" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, haveNetname := node.AddNetname(OptionStrMap) + OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) if !haveNetname { return errors.New("a netname must be given for any network related configuration") } @@ -33,7 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { var nodeCount uint // The checks run twice in the prompt case. // Avoiding putting in a blocking prompt in an API. - _, nodeCount, err = node.NodeSetParameterCheck(&set, false) + _, nodeCount, err = apinode.NodeSetParameterCheck(&set, false) if err != nil { return } @@ -42,5 +42,5 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { return } } - return node.NodeSet(&set) + return apinode.NodeSet(&set) } diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index f827b605..36a24063 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -37,17 +37,14 @@ var ( SetYes bool SetForce bool OptionStrMap map[string]*string - KernelStrMap map[string]*string ) func init() { - //var emptyNodeConf node.NodeConf - //var emptyKernelE node.KernelEntry + // init empty helper structs, so that we know what's inside myBase := node.CobraCommand{Command: baseCmd} var emptyNodeConf node.NodeConf emptyNodeConf.Kernel = new(node.KernelConf) emptyNodeConf.Ipmi = new(node.IpmiConf) - //emptyNodeConf.NetDevs = make(map[string]*node.NetDevs) OptionStrMap = myBase.CreateFlags(emptyNodeConf) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 6fec3326..e206c13f 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -2,352 +2,46 @@ package set import ( "fmt" - "os" - "strings" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/warewulfd" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/manifoldco/promptui" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" + apiprofile "github.com/hpcng/warewulf/internal/pkg/api/profile" + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/api/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - var err error +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) + if !haveNetname { + return errors.New("a netname must be given for any network related configuration") + } + realMap := make(map[string]string) - nodeDB, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) - os.Exit(1) + for key, val := range OptionStrMap { + realMap[key] = *val } - profiles, err := nodeDB.FindAllProfiles() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) + set := wwapiv1.NodeSetParameter{ + OptionsStrMap: realMap, + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, } - if SetAll { - fmt.Printf("\n*** WARNING: This command will modify all profiles! ***\n\n") - } else if len(args) > 0 { - profiles = node.FilterByName(profiles, args) - } else { - wwlog.Printf(wwlog.INFO, "No profile specified, selecting the 'default' profile\n") - profiles = node.FilterByName(profiles, []string{"default"}) - } - - if len(profiles) == 0 { - fmt.Printf("No profiles found\n") - os.Exit(1) - } - - for _, p := range profiles { - wwlog.Printf(wwlog.VERBOSE, "Modifying profile: %s\n", p.Id.Get()) - - if SetComment != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting comment to: %s\n", p.Id.Get(), SetComment) - p.Comment.Set(SetComment) - } - - if SetClusterName != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting cluster name to: %s\n", p.Id.Get(), SetClusterName) - p.ClusterName.Set(SetClusterName) - } - - if SetContainer != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Container name to: %s\n", p.Id.Get(), SetContainer) - p.ContainerName.Set(SetContainer) - } - - if SetInit != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting init command to: %s\n", p.Id.Get(), SetInit) - p.Init.Set(SetInit) - } - - if SetRoot != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting root to: %s\n", p.Id.Get(), SetRoot) - p.Root.Set(SetRoot) - } - - if SetAssetKey != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting asset key to: %s\n", p.Id.Get(), SetAssetKey) - p.AssetKey.Set(SetAssetKey) - } - - if SetKernelOverride != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel override version to: %s\n", p.Id.Get(), SetKernelOverride) - p.Kernel.Override.Set(SetKernelOverride) - } - - if SetKernelArgs != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel args to: %s\n", p.Id.Get(), SetKernelArgs) - p.Kernel.Args.Set(SetKernelArgs) - } - - if SetIpxe != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting iPXE template to: %s\n", p.Id.Get(), SetIpxe) - p.Ipxe.Set(SetIpxe) - } - - if len(SetRuntimeOverlay) != 0 { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting runtime overlay to: %s\n", p.Id.Get(), SetRuntimeOverlay) - p.RuntimeOverlay.SetSlice(SetRuntimeOverlay) - } - - if len(SetSystemOverlay) != 0 { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting system overlay to: %s\n", p.Id.Get(), SetSystemOverlay) - p.SystemOverlay.SetSlice(SetSystemOverlay) - } - - if SetIpmiNetmask != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI netmask to: %s\n", p.Id.Get(), SetIpmiNetmask) - p.Ipmi.Netmask.Set(SetIpmiNetmask) - } - - if SetIpmiPort != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI port to: %s\n", p.Id.Get(), SetIpmiPort) - p.Ipmi.Port.Set(SetIpmiPort) - } - - if SetIpmiGateway != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI gateway to: %s\n", p.Id.Get(), SetIpmiGateway) - p.Ipmi.Gateway.Set(SetIpmiGateway) - } - - if SetIpmiUsername != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI username to: %s\n", p.Id.Get(), SetIpmiUsername) - p.Ipmi.UserName.Set(SetIpmiUsername) - } - - if SetIpmiPassword != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI password to: %s\n", p.Id.Get(), SetIpmiPassword) - p.Ipmi.Password.Set(SetIpmiPassword) - } - - if SetIpmiInterface != "" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting IPMI interface to: %s\n", p.Id.Get(), SetIpmiInterface) - p.Ipmi.Interface.Set(SetIpmiInterface) - } - - if SetIpmiWrite == "yes" || SetNetOnBoot == "y" || SetNetOnBoot == "1" || SetNetOnBoot == "true" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting Ipmiwrite to %s\n", p.Id.Get(), SetIpmiWrite) - p.Ipmi.Write.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting Ipmiwrite to %s\n", p.Id.Get(), SetIpmiWrite) - p.Ipmi.Write.SetB(false) - } - - if SetDiscoverable { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting all nodes to discoverable\n", p.Id.Get()) - p.Discoverable.SetB(true) - } - - if SetUndiscoverable { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting all nodes to undiscoverable\n", p.Id.Get()) - p.Discoverable.SetB(false) - } - - if SetNetName != "" { - if _, ok := p.NetDevs[SetNetName]; !ok { - var nd node.NetDevEntry - nd.Tags = make(map[string]*node.Entry) - p.NetDevs[SetNetName] = &nd - } - } - - if SetNetDev != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting net Device to: %s\n", p.Id.Get(), SetNetName, SetNetDev) - p.NetDevs[SetNetName].Device.Set(SetNetDev) - } - - if SetNetmask != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile '%s': Setting netmask to: %s\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].Netmask.Set(SetNetmask) - } - - if SetGateway != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile '%s': Setting gateway to: %s\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].Gateway.Set(SetGateway) - } - - if SetType != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile '%s': Setting HW address to: %s:%s\n", p.Id.Get(), SetNetName, SetType) - p.NetDevs[SetNetName].Type.Set(SetType) - } - - if SetNetOnBoot != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - if SetNetOnBoot == "yes" || SetNetOnBoot == "y" || SetNetOnBoot == "1" || SetNetOnBoot == "true" { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Setting ONBOOT\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].OnBoot.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Unsetting ONBOOT\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].OnBoot.SetB(false) - } - } - - if SetNetPrimary != "" { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - if SetNetPrimary == "yes" || SetNetPrimary == "y" || SetNetPrimary == "1" || SetNetPrimary == "true" { - - // Set all other networks to non-default - for _, n := range p.NetDevs { - n.Primary.SetB(false) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Setting PRIMARY\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].Primary.SetB(true) - } else { - wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Unsetting PRIMARY\n", p.Id.Get(), SetNetName) - p.NetDevs[SetNetName].Primary.SetB(false) - } - } - - if SetNetDevDel { - if SetNetName == "" { - wwlog.Printf(wwlog.ERROR, "You must include the '--netname' option\n") - os.Exit(1) - } - - if _, ok := p.NetDevs[SetNetName]; !ok { - wwlog.Printf(wwlog.ERROR, "Profile '%s': network name doesn't exist: %s\n", p.Id.Get(), SetNetName) - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile %s: Deleting network: %s\n", p.Id.Get(), SetNetName) - delete(p.NetDevs, SetNetName) - } - - if len(SetTags) > 0 { - for _, t := range SetTags { - keyval := strings.SplitN(t, "=", 2) - key := keyval[0] - val := keyval[1] - - if _, ok := p.Tags[key]; !ok { - var nd node.Entry - p.Tags[key] = &nd - } - - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Tag '%s'='%s'\n", p.Id.Get(), key, val) - p.Tags[key].Set(val) - } - } - if len(SetDelTags) > 0 { - for _, t := range SetDelTags { - keyval := strings.SplitN(t, "=", 1) - key := keyval[0] - - if _, ok := p.Tags[key]; !ok { - wwlog.Printf(wwlog.WARN, "Key does not exist: %s\n", key) - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting tag: %s\n", p.Id.Get(), key) - delete(p.Tags, key) - } - } - if len(SetNetTags) > 0 { - for _, t := range SetNetTags { - keyval := strings.SplitN(t, "=", 2) - key := keyval[0] - val := keyval[1] - if _, ok := p.NetDevs[SetNetName].Tags[key]; !ok { - var nd node.Entry - p.NetDevs[SetNetName].Tags[key] = &nd - } - - wwlog.Printf(wwlog.VERBOSE, "Profile: %s:%s, Setting NETTAG '%s'='%s'\n", p.Id.Get(), SetNetName, key, val) - p.NetDevs[SetNetName].Tags[key].Set(val) - } - - } - if len(SetNetDelTags) > 0 { - for _, t := range SetNetDelTags { - keyval := strings.SplitN(t, "=", 1) - key := keyval[0] - if _, ok := p.NetDevs[SetNetName].Tags[key]; !ok { - wwlog.Printf(wwlog.WARN, "Profile: %s,%s, Key %s does not exist\n", p.Id.Get(), SetNetName, key) - os.Exit(1) - } - - wwlog.Printf(wwlog.VERBOSE, "Profile: %s,%s Deleting NETTAG: %s\n", p.Id.Get(), SetNetName, key) - delete(p.NetDevs[SetNetName].Tags, key) - } - } - - err := nodeDB.ProfileUpdate(p) + if !SetYes { + var nodeCount uint + // The checks run twice in the prompt case. + // Avoiding putting in a blocking prompt in an API. + _, nodeCount, err = apiprofile.ProfileSetParameterCheck(&set, false) if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) + return + } + yes := util.ConfirmationPrompt(fmt.Sprintf("Are you sure you want to modify %d nodes(s)", nodeCount)) + if !yes { + return } } - - if len(profiles) > 0 { - if SetYes { - err := nodeDB.Persist() - if err != nil { - return errors.Wrap(err, "failed to persist nodedb") - } - - err = warewulfd.DaemonReload() - if err != nil { - return errors.Wrap(err, "failed to reload warewulf daemon") - } - } else { - q := fmt.Sprintf("Are you sure you want to modify %d profile(s)", len(profiles)) - - prompt := promptui.Prompt{ - Label: q, - IsConfirm: true, - } - - result, _ := prompt.Run() - - if result == "y" || result == "yes" { - err := nodeDB.Persist() - if err != nil { - return errors.Wrap(err, "failed to persist nodedb") - } - - err = warewulfd.DaemonReload() - if err != nil { - return errors.Wrap(err, "failed to reload daemon") - } - } - } - } else { - fmt.Printf("No profiles found\n") - } - - return nil + return apiprofile.ProfileSet(&set) } diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index e15d28d5..b1a62fd4 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -32,110 +32,51 @@ var ( return p_names, cobra.ShellCompDirectiveNoFileComp }, } - SetAll bool - SetYes bool - SetForce bool - SetComment string - SetContainer string - SetKernelOverride string - SetKernelArgs string - SetClusterName string - SetIpxe string - SetInitOverlay string - SetRuntimeOverlay []string - SetSystemOverlay []string - SetIpmiNetmask string - SetIpmiPort string - SetIpmiGateway string - SetIpmiUsername string - SetIpmiPassword string - SetIpmiInterface string - SetIpmiWrite string - SetNetName string - SetNetDev string - SetNetmask string - SetGateway string - SetType string - SetNetOnBoot string - SetNetPrimary string - SetNetDevDel bool - SetDiscoverable bool - SetUndiscoverable bool - SetInit string - SetRoot string - SetKey string - SetTags []string - SetDelTags []string - SetAssetKey string - SetNetTags []string - SetNetDelTags []string + SetNetDevDel string + SetNodeAll bool + SetYes bool + SetForce bool + OptionStrMap map[string]*string ) func init() { - baseCmd.PersistentFlags().StringVar(&SetComment, "comment", "", "Set a comment for this node") - baseCmd.PersistentFlags().StringVarP(&SetContainer, "container", "C", "", "Set the container (VNFS) for this node") + // init empty helper structs, so that we know what's inside + myBase := node.CobraCommand{Command: baseCmd} + var emptyNodeConf node.NodeConf + emptyNodeConf.Kernel = new(node.KernelConf) + emptyNodeConf.Ipmi = new(node.IpmiConf) + OptionStrMap = myBase.CreateFlags(emptyNodeConf) + + baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") + baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") + baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") + baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") + // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernelOverride, "kerneloverride", "K", "", "Set kernel override version for nodes") if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := kernel.ListKernels() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVarP(&SetKernelArgs, "kernelargs", "A", "", "Set Kernel argument for nodes") - baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster group") - baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name") - baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container") - baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs") - baseCmd.PersistentFlags().StringVar(&SetAssetKey, "assetkey", "", "Set the node's Asset tag (key)") - baseCmd.PersistentFlags().StringSliceVarP(&SetRuntimeOverlay, "runtime", "R", []string{}, "Set the node's runtime overlay") if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := overlay.FindOverlays() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) - } - baseCmd.PersistentFlags().StringSliceVarP(&SetSystemOverlay, "system", "S", []string{}, "Set the node's system overlay") - if err := baseCmd.RegisterFlagCompletionFunc("system", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if err := baseCmd.RegisterFlagCompletionFunc("wwinit", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := overlay.FindOverlays() return list, cobra.ShellCompDirectiveNoFileComp }); err != nil { log.Println(err) } - baseCmd.PersistentFlags().StringVar(&SetIpmiNetmask, "ipminetmask", "", "Set the node's IPMI netmask") - baseCmd.PersistentFlags().StringVar(&SetIpmiPort, "ipmiport", "", "Set the node's IPMI port") - baseCmd.PersistentFlags().StringVar(&SetIpmiGateway, "ipmigateway", "", "Set the node's IPMI gateway") - baseCmd.PersistentFlags().StringVar(&SetIpmiUsername, "ipmiuser", "", "Set the node's IPMI username") - baseCmd.PersistentFlags().StringVar(&SetIpmiPassword, "ipmipass", "", "Set the node's IPMI password") - baseCmd.PersistentFlags().StringVar(&SetIpmiInterface, "ipmiinterface", "", "Set the node's IPMI interface (defaults to 'lan')") - baseCmd.PersistentFlags().StringVar(&SetIpmiWrite, "ipmiwrite", "", "Enable/disable the write of impi configuration (yes/no)") - baseCmd.PersistentFlags().StringVarP(&SetNetName, "netname", "n", "default", "Define the network name to configure") - baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Set the node's network device") - baseCmd.PersistentFlags().StringVar(&SetNetPrimary, "primary", "", "Enable/disable device as primary (yes/no)") - baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask") - baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway") - baseCmd.PersistentFlags().StringVarP(&SetType, "type", "T", "", "Set the node's network device type") - baseCmd.PersistentFlags().StringVar(&SetNetOnBoot, "onboot", "", "Enable/disable device (yes/no)") - - baseCmd.PersistentFlags().BoolVar(&SetNetDevDel, "netdel", false, "Delete the node's network device") - baseCmd.PersistentFlags().StringSliceVar(&SetNetTags, "nettag", []string{}, "Define custom tag to network device (key=value)") - baseCmd.PersistentFlags().StringSliceVar(&SetNetDelTags, "netdeltag", []string{}, "Delete tag for network device") - - baseCmd.PersistentFlags().StringSliceVarP(&SetTags, "tag", "t", []string{}, "Define custom tag (key=value)") - baseCmd.PersistentFlags().StringSliceVar(&SetDelTags, "tagdel", []string{}, "Delete tag") - - baseCmd.PersistentFlags().BoolVarP(&SetAll, "all", "a", false, "Set all profiles") - baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") - baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") - baseCmd.PersistentFlags().BoolVar(&SetDiscoverable, "discoverable", false, "Make this node discoverable") - baseCmd.PersistentFlags().BoolVar(&SetUndiscoverable, "undiscoverable", false, "Remove the discoverable flag") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index aed8224e..5121528f 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -1,4 +1,4 @@ -package node +package apinode import ( "encoding/json" @@ -477,7 +477,7 @@ func NodeSet(set *wwapiv1.NodeSetParameter) (err error) { if err != nil { return } - return nodeDbSave(&nodeDB) + return DbSave(&nodeDB) } // NodeSetParameterCheck does error checking on NodeSetParameter. @@ -658,24 +658,6 @@ func checkNetNameRequired(netname string) (err error) { return } -// nodeDbSave persists the nodeDB to disk and restarts warewulfd. -// TODO: We will likely need locking around anything changing nodeDB -// or restarting warewulfd. Determine if the reason for restart is -// just to reinitialize warewulfd with the new nodeDB or if there is -// something more to it. -func nodeDbSave(nodeDB *node.NodeYaml) (err error) { - err = nodeDB.Persist() - if err != nil { - return errors.Wrap(err, "failed to persist nodedb") - } - - err = warewulfd.DaemonReload() - if err != nil { - return errors.Wrap(err, "failed to reload warewulf daemon") - } - return -} - /* Add the netname to the options map, as its only known after the map command line options have been read out. diff --git a/internal/pkg/api/node/utils.go b/internal/pkg/api/node/utils.go new file mode 100644 index 00000000..e2643f77 --- /dev/null +++ b/internal/pkg/api/node/utils.go @@ -0,0 +1,25 @@ +package apinode + +import ( + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/warewulfd" + "github.com/pkg/errors" +) + +// nodeDbSave persists the nodeDB to disk and restarts warewulfd. +// TODO: We will likely need locking around anything changing nodeDB +// or restarting warewulfd. Determine if the reason for restart is +// just to reinitialize warewulfd with the new nodeDB or if there is +// something more to it. +func DbSave(nodeDB *node.NodeYaml) (err error) { + err = nodeDB.Persist() + if err != nil { + return errors.Wrap(err, "failed to persist nodedb") + } + + err = warewulfd.DaemonReload() + if err != nil { + return errors.Wrap(err, "failed to reload warewulf daemon") + } + return +} diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go new file mode 100644 index 00000000..ef4916a7 --- /dev/null +++ b/internal/pkg/api/profile/profile.go @@ -0,0 +1,109 @@ +package apiprofile + +import ( + "fmt" + "os" + + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +// NodeSet is the wwapiv1 implmentation for updating node fields. +func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { + + if set == nil { + return fmt.Errorf("NodeAddParameter is nil") + } + + var nodeDB node.NodeYaml + nodeDB, _, err = ProfileSetParameterCheck(set, false) + if err != nil { + return + } + return apinode.DbSave(&nodeDB) +} + +// NodeSetParameterCheck does error checking on NodeSetParameter. +// Output to the console if console is true. +// TODO: Determine if the console switch does wwlog or not. +// - console may end up being textOutput? +func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, profileCount uint, err error) { + + if set == nil { + err = fmt.Errorf("Profile set parameter is nil") + if console { + fmt.Printf("%v\n", err) + return + } + } + + if set.NodeNames == nil { + err = fmt.Errorf("Profile set parameter: ProfileNames is nil") + if console { + fmt.Printf("%v\n", err) + return + } + } + + nodeDB, err = node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open configuration: %s\n", err) + return + } + + profiles, err := nodeDB.FindAllProfiles() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not get profile list: %s\n", err) + return + } + + // Note: This does not do expansion on the nodes. + + if set.AllNodes || (len(set.NodeNames) == 0 && len(profiles) > 0) { + if console { + fmt.Printf("\n*** WARNING: This command will modify all profiles! ***\n\n") + } + } else { + profiles = node.FilterByName(profiles, set.NodeNames) + } + + if len(profiles) == 0 { + if console { + fmt.Printf("No profiles found\n") + } + return + } + + for _, p := range profiles { + wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) + for key, val := range set.OptionsStrMap { + if val != "" { + wwlog.Verbose("profile:%s setting %s to %s\n", p.Id.Get(), key, val) + p.SetField(key, val) + } + } + + if set.NetdevDelete != "" { + + if _, ok := p.NetDevs[set.NetdevDelete]; !ok { + err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + return + } + + wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) + delete(p.NetDevs, set.NetdevDelete) + } + + err := nodeDB.NodeUpdate(p) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + profileCount++ + } + return +} From d10b4c352fc8550eb66e03788cb6d8ce178b1126 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 13 Jul 2022 16:05:16 +0200 Subject: [PATCH 11/38] new apinode namespace in wwapid --- internal/app/api/wwapid/wwapid.go | 12 ++++++------ internal/app/wwctl/node/add/main.go | 4 ++-- internal/app/wwctl/node/list/main.go | 4 ++-- internal/app/wwctl/node/status/main.go | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/app/api/wwapid/wwapid.go b/internal/app/api/wwapid/wwapid.go index 3ae7bf8c..0d19e29d 100644 --- a/internal/app/api/wwapid/wwapid.go +++ b/internal/app/api/wwapid/wwapid.go @@ -14,7 +14,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/api/apiconfig" "github.com/hpcng/warewulf/internal/pkg/api/container" - "github.com/hpcng/warewulf/internal/pkg/api/node" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/version" @@ -241,7 +241,7 @@ func (s *apiServer) NodeAdd(ctx context.Context, request *wwapiv1.NodeAddParamet } // Add the node(s). - err = node.NodeAdd(request) + err = apinode.NodeAdd(request) if err != nil { return } @@ -264,7 +264,7 @@ func (s *apiServer) NodeDelete(ctx context.Context, request *wwapiv1.NodeDeleteP return response, status.Errorf(codes.InvalidArgument, "nil request.NodeNames") } - err = node.NodeDelete(request) + err = apinode.NodeDelete(request) return } @@ -293,7 +293,7 @@ func (s *apiServer) NodeSet(ctx context.Context, request *wwapiv1.NodeSetParamet } // Perform the NodeSet. - err = node.NodeSet(request) + err = apinode.NodeSet(request) if err != nil { return } @@ -309,7 +309,7 @@ func (s *apiServer) NodeStatus(ctx context.Context, request *wwapiv1.NodeNames) return response, status.Errorf(codes.InvalidArgument, "nil request") } - return node.NodeStatus(request.NodeNames) + return apinode.NodeStatus(request.NodeNames) } // Version returns the versions of the wwapiv1 and warewulf as well as the api @@ -331,7 +331,7 @@ func (s *apiServer) Version(ctx context.Context, request *emptypb.Empty) (respon func (s *apiServer) nodeListInternal(nodeNames []string) (response *wwapiv1.NodeListResponse, err error) { var nodes []*wwapiv1.NodeInfo - nodes, err = node.NodeList(nodeNames) + nodes, err = apinode.NodeList(nodeNames) if err != nil { return } diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 0101729c..5e92ccf6 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -1,7 +1,7 @@ package add import ( - "github.com/hpcng/warewulf/internal/pkg/api/node" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/spf13/cobra" ) @@ -20,5 +20,5 @@ func CobraRunE(cmd *cobra.Command, args []string) error { Type: SetType, NodeNames: args, } - return node.NodeAdd(&nap) + return apinode.NodeAdd(&nap) } diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 354dfae1..6580b61d 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -5,14 +5,14 @@ import ( "sort" "strings" - "github.com/hpcng/warewulf/internal/pkg/api/node" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - nodeInfo, err := node.NodeList(args) + nodeInfo, err := apinode.NodeList(args) if err != nil { wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) return diff --git a/internal/app/wwctl/node/status/main.go b/internal/app/wwctl/node/status/main.go index 771157a9..fabc338f 100644 --- a/internal/app/wwctl/node/status/main.go +++ b/internal/app/wwctl/node/status/main.go @@ -8,7 +8,7 @@ import ( "time" "github.com/fatih/color" - "github.com/hpcng/warewulf/internal/pkg/api/node" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -37,7 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { rightnow := time.Now().Unix() var nodeStatusResponse *wwapiv1.NodeStatusResponse - nodeStatusResponse, err = node.NodeStatus([]string{}) + nodeStatusResponse, err = apinode.NodeStatus([]string{}) if err != nil { return err } From e0c62a81a464b5cd0738d5856ab48b441e0c3f7a Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 13 Jul 2022 16:15:35 +0200 Subject: [PATCH 12/38] testing profile set --- internal/app/wwctl/node/set/root.go | 2 +- internal/app/wwctl/profile/set/root.go | 12 ++++++++++-- internal/pkg/api/profile/profile.go | 18 ++++++++---------- internal/pkg/node/methods.go | 11 ++++++----- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 36a24063..32c58292 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -45,7 +45,7 @@ func init() { var emptyNodeConf node.NodeConf emptyNodeConf.Kernel = new(node.KernelConf) emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf) + OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index b1a62fd4..543ee81d 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -1,6 +1,7 @@ package set import ( + "fmt" "log" "github.com/hpcng/warewulf/internal/pkg/container" @@ -45,8 +46,15 @@ func init() { var emptyNodeConf node.NodeConf emptyNodeConf.Kernel = new(node.KernelConf) emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf) - + OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) + fmt.Println(baseCmd.Flags().Args()) + flag := baseCmd.Flag("ipaddr") + if flag != nil { + flag.Name = "donotuse" + flag.Usage = "FooBaar" + } else { + fmt.Println("Flag not found") + } baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index ef4916a7..c3a04188 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -10,7 +10,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/wwlog" ) -// NodeSet is the wwapiv1 implmentation for updating node fields. +// NodeSet is the wwapiv1 implmentation for updating nodeinfo fields. func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { if set == nil { @@ -25,7 +25,7 @@ func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { return apinode.DbSave(&nodeDB) } -// NodeSetParameterCheck does error checking on NodeSetParameter. +// ProfileSetParameterCheck does error checking on ProfileSetParameter. // Output to the console if console is true. // TODO: Determine if the console switch does wwlog or not. // - console may end up being textOutput? @@ -49,13 +49,13 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node nodeDB, err = node.New() if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open configuration: %s\n", err) + wwlog.Error("Could not open configuration: %s\n", err) return } profiles, err := nodeDB.FindAllProfiles() if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not get profile list: %s\n", err) + wwlog.Error("Could not get profile list: %s\n", err) return } @@ -65,8 +65,6 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node if console { fmt.Printf("\n*** WARNING: This command will modify all profiles! ***\n\n") } - } else { - profiles = node.FilterByName(profiles, set.NodeNames) } if len(profiles) == 0 { @@ -89,17 +87,17 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node if _, ok := p.NetDevs[set.NetdevDelete]; !ok { err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) - wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + wwlog.Error(fmt.Sprintf("%v\n", err.Error())) return } - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) delete(p.NetDevs, set.NetdevDelete) } - err := nodeDB.NodeUpdate(p) + err := nodeDB.ProfileUpdate(p) if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) + wwlog.Error("%s\n", err) os.Exit(1) } diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 9f24be94..1efea092 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -6,6 +6,7 @@ import ( "regexp" "strings" + "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) @@ -512,7 +513,7 @@ Get all names of the fields in the given struct (recursive) and create a map[name of struct field]*string if the the field of the struct bears the comment tag. */ -func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*string { +func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []string) map[string]*string { optionsMap := make(map[string]*string) structVal := reflect.ValueOf(theStruct) structTyp := structVal.Type() @@ -521,7 +522,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) if field.Type.Kind() == reflect.Ptr { a := structVal.Field(i).Elem().Interface() - subStruct := baseCmd.CreateFlags(a) + subStruct := baseCmd.CreateFlags(a, excludeList) for key, val := range subStruct { optionsMap[field.Name+"."+key] = val } @@ -531,7 +532,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri mapType := field.Type.Elem() if mapType.Kind() == reflect.Ptr { //a := reflect.ValueOf((mapType.Elem())) node.NetDevs - subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface()) + subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) for key, val := range subMap { optionsMap[field.Name+"."+key] = val } @@ -558,7 +559,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri wwlog.Warn("handling of %v not implemented\n", field.Type) } - } else if field.Tag.Get("comment") != "" { + } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Name) { var newStr string optionsMap[field.Name] = &newStr if field.Tag.Get("sopt") != "" { @@ -567,7 +568,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}) map[string]*stri field.Tag.Get("sopt"), field.Tag.Get("default"), field.Tag.Get("comment")) - } else { + } else if !util.InSlice(excludeList, field.Name) { baseCmd.PersistentFlags().StringVar(&newStr, field.Tag.Get("lopt"), field.Tag.Get("default"), From 510f6a60a98a628c2b5badeaf5739cd32eecf8ce Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 14 Jul 2022 10:40:46 +0200 Subject: [PATCH 13/38] added excludellist to CreateFlags --- internal/app/wwctl/profile/set/root.go | 13 +++---------- internal/pkg/node/methods.go | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 543ee81d..9bb96d6f 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -1,7 +1,6 @@ package set import ( - "fmt" "log" "github.com/hpcng/warewulf/internal/pkg/container" @@ -46,15 +45,9 @@ func init() { var emptyNodeConf node.NodeConf emptyNodeConf.Kernel = new(node.KernelConf) emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) - fmt.Println(baseCmd.Flags().Args()) - flag := baseCmd.Flag("ipaddr") - if flag != nil { - flag.Name = "donotuse" - flag.Usage = "FooBaar" - } else { - fmt.Println("Flag not found") - } + OptionStrMap = myBase.CreateFlags(emptyNodeConf, + []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) + baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 1efea092..d3df4270 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -559,7 +559,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []st wwlog.Warn("handling of %v not implemented\n", field.Type) } - } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Name) { + } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Tag.Get("lopt")) { var newStr string optionsMap[field.Name] = &newStr if field.Tag.Get("sopt") != "" { @@ -568,7 +568,7 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []st field.Tag.Get("sopt"), field.Tag.Get("default"), field.Tag.Get("comment")) - } else if !util.InSlice(excludeList, field.Name) { + } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { baseCmd.PersistentFlags().StringVar(&newStr, field.Tag.Get("lopt"), field.Tag.Get("default"), From e6ef30ed53b38ec7a0f0585333ff6436a8a4d5c6 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 14 Jul 2022 17:22:49 +0200 Subject: [PATCH 14/38] porfile add has now all otions of set --- internal/app/wwctl/profile/add/main.go | 52 ++++++++++++----- internal/app/wwctl/profile/add/root.go | 58 +++++++++++++++++-- internal/pkg/api/profile/profile.go | 77 +++++++++++++++++--------- internal/pkg/node/constructors.go | 15 ++++- 4 files changed, 156 insertions(+), 46 deletions(-) diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index 6e5ef57a..8a219a95 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -1,28 +1,52 @@ package add import ( - "os" + "fmt" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/wwlog" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" + apiprofile "github.com/hpcng/warewulf/internal/pkg/api/profile" + + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/api/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - nodeDB, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Failed opening node database: %s\n", err) - os.Exit(1) +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) + if !haveNetname { + return errors.New("a netname must be given for any network related configuration") + } + realMap := make(map[string]string) + + for key, val := range OptionStrMap { + realMap[key] = *val } - for _, p := range args { - _, err := nodeDB.AddProfile(p) + set := wwapiv1.NodeSetParameter{ + OptionsStrMap: realMap, + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, + } + + if !SetYes { + // The checks run twice in the prompt case. + // Avoiding putting in a blocking prompt in an API. + apiprofile.AddProfile(&set, false) if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) + return + } + _, _, err = apiprofile.ProfileSetParameterCheck(&set, false) + if err != nil { + return + } + + yes := util.ConfirmationPrompt(fmt.Sprintf("Are you sure you add the profile %s", args)) + if !yes { + return } } - - return errors.Wrap(nodeDB.Persist(), "failed to persist nodedb") + return apiprofile.ProfileSet(&set) } diff --git a/internal/app/wwctl/profile/add/root.go b/internal/app/wwctl/profile/add/root.go index 9e95d8d2..7380dec4 100644 --- a/internal/app/wwctl/profile/add/root.go +++ b/internal/app/wwctl/profile/add/root.go @@ -1,19 +1,65 @@ package add -import "github.com/spf13/cobra" +import ( + "log" + + "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/overlay" + "github.com/spf13/cobra" +) var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "add PROFILE", - Short: "Add a new node profile", - Long: "This command adds a new named PROFILE.", - RunE: CobraRunE, - Args: cobra.MinimumNArgs(1), + Use: "add PROFILE", + Short: "Add a new node profile", + Long: "This command adds a new named PROFILE.", + RunE: CobraRunE, + Args: cobra.ExactArgs(1), } + SetNetDevDel string + SetNodeAll bool + SetYes bool + SetForce bool + OptionStrMap map[string]*string ) // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { + // init empty helper structs, so that we know what's inside + myBase := node.CobraCommand{Command: baseCmd} + var emptyNodeConf node.NodeConf + emptyNodeConf.Kernel = new(node.KernelConf) + emptyNodeConf.Ipmi = new(node.IpmiConf) + OptionStrMap = myBase.CreateFlags(emptyNodeConf, + []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) + // register the command line completions + if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := container.ListSources() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := kernel.ListKernels() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := overlay.FindOverlays() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("wwinit", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := overlay.FindOverlays() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + return baseCmd } diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index c3a04188..24ebff8f 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -7,7 +7,9 @@ import ( apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/pkg/errors" ) // NodeSet is the wwapiv1 implmentation for updating nodeinfo fields. @@ -20,7 +22,7 @@ func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { var nodeDB node.NodeYaml nodeDB, _, err = ProfileSetParameterCheck(set, false) if err != nil { - return + return errors.Wrap(err, "Could not open database") } return apinode.DbSave(&nodeDB) } @@ -61,7 +63,7 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node // Note: This does not do expansion on the nodes. - if set.AllNodes || (len(set.NodeNames) == 0 && len(profiles) > 0) { + if set.AllNodes || (len(set.NodeNames) == 0) { if console { fmt.Printf("\n*** WARNING: This command will modify all profiles! ***\n\n") } @@ -75,33 +77,58 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node } for _, p := range profiles { - wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) - for key, val := range set.OptionsStrMap { - if val != "" { - wwlog.Verbose("profile:%s setting %s to %s\n", p.Id.Get(), key, val) - p.SetField(key, val) - } - } - - if set.NetdevDelete != "" { - - if _, ok := p.NetDevs[set.NetdevDelete]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) - wwlog.Error(fmt.Sprintf("%v\n", err.Error())) - return + if util.InSlice(set.NodeNames, p.Id.Get()) { + wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) + for key, val := range set.OptionsStrMap { + if val != "" { + wwlog.Verbose("profile:%s setting %s to %s\n", p.Id.Get(), key, val) + p.SetField(key, val) + } } - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) - delete(p.NetDevs, set.NetdevDelete) - } + if set.NetdevDelete != "" { - err := nodeDB.ProfileUpdate(p) - if err != nil { - wwlog.Error("%s\n", err) - os.Exit(1) - } + if _, ok := p.NetDevs[set.NetdevDelete]; !ok { + err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + wwlog.Error(fmt.Sprintf("%v\n", err.Error())) + return + } - profileCount++ + wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) + delete(p.NetDevs, set.NetdevDelete) + } + + err := nodeDB.ProfileUpdate(p) + if err != nil { + wwlog.Error("%s\n", err) + os.Exit(1) + } + + profileCount++ + } } return } + +/* +Adds a new profile with the given name +*/ +func AddProfile(set *wwapiv1.NodeSetParameter, console bool) error { + nodeDB, err := node.New() + if err != nil { + return errors.Wrap(err, "Could not open database") + } + + if util.InSlice(nodeDB.ListAllProfiles(), set.NodeNames[0]) { + return errors.New(fmt.Sprintf("profile with name %s allready exists", set.NodeNames[0])) + } + _, err = nodeDB.AddProfile(set.NodeNames[0]) + if err != nil { + return errors.Wrap(err, "Could not create new profile") + } + err = apinode.DbSave(&nodeDB) + if err != nil { + return errors.Wrap(err, "Could not persist new profile") + } + return nil +} diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 958cc0de..3e56fb98 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -312,6 +312,9 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { return ret, nil } +/* +Return all profiles as NodeInfo +*/ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { var ret []NodeInfo @@ -429,7 +432,6 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { ret = append(ret, p) } - sort.Slice(ret, func(i, j int) bool { if ret[i].ClusterName.Get() < ret[j].ClusterName.Get() { return true @@ -444,6 +446,17 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { return ret, nil } +/* +Return the names of all available profiles +*/ +func (config *NodeYaml) ListAllProfiles() []string { + var ret []string + for name, _ := range config.NodeProfiles { + ret = append(ret, name) + } + return ret +} + func (config *NodeYaml) FindDiscoverableNode() (NodeInfo, string, error) { var ret NodeInfo From 26fff308970124701ca8033a85d39fc56da40e11 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 18 Jul 2022 14:42:00 +0200 Subject: [PATCH 15/38] node add with all options now --- internal/app/wwctl/node/add/main.go | 29 +- internal/app/wwctl/node/add/root.go | 74 +++- internal/pkg/api/node/node.go | 131 +----- internal/pkg/api/routes/v1/routes.proto | 11 +- internal/pkg/api/routes/wwapiv1/routes.pb.go | 411 ++++++++----------- 5 files changed, 253 insertions(+), 403 deletions(-) diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 5e92ccf6..571783e3 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -1,24 +1,27 @@ package add import ( + "errors" + apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { - - nap := wwapiv1.NodeAddParameter{ - Cluster: SetClusterName, - Discoverable: SetDiscoverable, - Gateway: SetGateway, - Hwaddr: SetHwaddr, - Ipaddr: SetIpaddr, - Netdev: SetNetDev, - Netmask: SetNetmask, - Netname: SetNetName, - Type: SetType, - NodeNames: args, + OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) + if !haveNetname { + return errors.New("a netname must be given for any network related configuration") } - return apinode.NodeAdd(&nap) + realMap := make(map[string]string) + + for key, val := range OptionStrMap { + realMap[key] = *val + } + set := wwapiv1.NodeAddParameter{ + OptionsStrMap: realMap, + NodeNames: args, + } + + return apinode.NodeAdd(&set) } diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index a08caaf8..b0e6af19 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -1,6 +1,14 @@ package add -import "github.com/spf13/cobra" +import ( + "log" + + "github.com/hpcng/warewulf/internal/pkg/container" + "github.com/hpcng/warewulf/internal/pkg/kernel" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/overlay" + "github.com/spf13/cobra" +) var ( baseCmd = &cobra.Command{ @@ -11,29 +19,53 @@ var ( RunE: CobraRunE, Args: cobra.MinimumNArgs(1), } - SetClusterName string - SetNetName string - SetNetDev string - SetIpaddr string - SetIpaddr6 string - SetNetmask string - SetGateway string - SetHwaddr string - SetType string - SetDiscoverable bool + OptionStrMap map[string]*string ) func init() { - baseCmd.PersistentFlags().StringVarP(&SetClusterName, "cluster", "c", "", "Set the node's cluster name") - baseCmd.PersistentFlags().StringVarP(&SetNetName, "netname", "n", "default", "Define the network name to configure") - baseCmd.PersistentFlags().StringVarP(&SetNetDev, "netdev", "N", "", "Define the network device to configure") - baseCmd.PersistentFlags().StringVarP(&SetIpaddr, "ipaddr", "I", "", "Set the node's network device IP address") - baseCmd.PersistentFlags().StringVarP(&SetIpaddr6, "ipaddr6", "6", "", "Set the node's network device IPv6 address") - baseCmd.PersistentFlags().StringVarP(&SetNetmask, "netmask", "M", "", "Set the node's network device netmask") - baseCmd.PersistentFlags().StringVarP(&SetGateway, "gateway", "G", "", "Set the node's network device gateway") - baseCmd.PersistentFlags().StringVarP(&SetHwaddr, "hwaddr", "H", "", "Set the node's network device HW address") - baseCmd.PersistentFlags().StringVarP(&SetType, "type", "T", "", "Set the node's network device type") - baseCmd.PersistentFlags().BoolVar(&SetDiscoverable, "discoverable", false, "Make this node discoverable") + // init empty helper structs, so that we know what's inside + myBase := node.CobraCommand{Command: baseCmd} + var emptyNodeConf node.NodeConf + emptyNodeConf.Kernel = new(node.KernelConf) + emptyNodeConf.Ipmi = new(node.IpmiConf) + OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) + // register the command line completions + if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := container.ListSources() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("kerneloverride", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := kernel.ListKernels() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := overlay.FindOverlays() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("wwinit", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + list, _ := overlay.FindOverlays() + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + if err := baseCmd.RegisterFlagCompletionFunc("profile", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + var list []string + nodeDB, _ := node.New() + profiles, _ := nodeDB.FindAllProfiles() + for _, profile := range profiles { + list = append(list, profile.Id.Get()) + } + return list, cobra.ShellCompDirectiveNoFileComp + }); err != nil { + log.Println(err) + } + } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index 5121528f..a0f1d4a6 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -3,7 +3,6 @@ package apinode import ( "encoding/json" "fmt" - "net" "net/http" "os" "strconv" @@ -42,124 +41,26 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { return errors.Wrap(err, "failed to add node") } wwlog.Printf(wwlog.INFO, "Added node: %s\n", a) + if nap.OptionsStrMap["ipaddr"] != "" { + // if more nodes are added increment IPv4 address + nap.OptionsStrMap["ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["ipaddr"], count) - if nap.Cluster != "" { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting cluster name to: %s\n", n.Id.Get(), nap.Cluster) - n.ClusterName.Set(nap.Cluster) - err = nodeDB.NodeUpdate(n) - if err != nil { - return errors.Wrap(err, "failed to update node") - } + wwlog.Verbose("Node: %s:%s, Setting Ipaddr to: %s\n", + n.Id.Get(), nap.OptionsStrMap["netname"], nap.OptionsStrMap["ipaddr"]) } + if nap.OptionsStrMap["ipmiaddr"] != "" { + // if more nodes are added increment IPv4 address + nap.OptionsStrMap["ipmiaddr"] = util.IncrementIPv4(nap.OptionsStrMap["ipmiaddr"], count) - if nap.Netdev != "" { - err = checkNetNameRequired(nap.Netname) - if err != nil { - return - } - - if _, ok := n.NetDevs[nap.Netname]; !ok { - var netdev node.NetDevEntry - n.NetDevs[nap.Netname] = &netdev - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Device to: %s\n", n.Id.Get(), nap.Netname, nap.Netdev) - - n.NetDevs[nap.Netname].Device.Set(nap.Netdev) - n.NetDevs[nap.Netname].OnBoot.SetB(true) + wwlog.Verbose("Node: %s:, Setting IPMIIpaddr to: %s\n", + n.Id.Get(), nap.OptionsStrMap["ipmiaddr"]) } - - if nap.Ipaddr != "" { - err = checkNetNameRequired(nap.Netname) - if err != nil { - return + // Now set all the rest + for key, val := range nap.OptionsStrMap { + if val != "" { + wwlog.Verbose("node:%s setting %s to %s\n", n.Id.Get(), key, val) + n.SetField(key, val) } - - NewIpaddr := util.IncrementIPv4(nap.Ipaddr, count) - - if _, ok := n.NetDevs[nap.Netname]; !ok { - var netdev node.NetDevEntry - n.NetDevs[nap.Netname] = &netdev - } - - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Ipaddr to: %s\n", n.Id.Get(), nap.Netname, NewIpaddr) - - n.NetDevs[nap.Netname].Ipaddr.Set(NewIpaddr) - n.NetDevs[nap.Netname].OnBoot.SetB(true) - } - - if nap.Netmask != "" { - err = checkNetNameRequired(nap.Netname) - if err != nil { - return - } - - if _, ok := n.NetDevs[nap.Netname]; !ok { - return errors.New("network device does not exist: " + nap.Netname) - } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting netmask to: %s\n", n.Id.Get(), nap.Netname, nap.Netmask) - - n.NetDevs[nap.Netname].Netmask.Set(nap.Netmask) - } - - if nap.Gateway != "" { - err = checkNetNameRequired(nap.Netname) - if err != nil { - return - } - - if _, ok := n.NetDevs[nap.Netname]; !ok { - return errors.New("network device does not exist: " + nap.Netname) - } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting gateway to: %s\n", n.Id.Get(), nap.Netname, nap.Gateway) - - n.NetDevs[nap.Netname].Gateway.Set(nap.Gateway) - } - - if nap.Hwaddr != "" { - if nap.Netname == "" { - return errors.New("you must include the '--netname' option") - } - - if _, ok := n.NetDevs[nap.Netname]; !ok { - return errors.New("network device does not exist: " + nap.Netname) - } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Id.Get(), nap.Netname, nap.Hwaddr) - - n.NetDevs[nap.Netname].Hwaddr.Set(nap.Hwaddr) - n.NetDevs[nap.Netname].OnBoot.SetB(true) - } - - if nap.Type != "" { - if nap.Netname == "" { - return errors.New("you must include the '--netname' option") - } - - if _, ok := n.NetDevs[nap.Netname]; !ok { - return errors.New("network device does not exist: " + nap.Netname) - } - wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting Type to: %s\n", n.Id.Get(), nap.Netname, nap.Type) - - n.NetDevs[nap.Netname].Type.Set(nap.Type) - } - - if nap.Ipaddr6 != "" { - if nap.Netname == "" { - return errors.New("you must include the '--netname' option") - } - if _, ok := n.NetDevs[nap.Netname]; !ok { - return errors.New("network device does not exist: " + nap.Netname) - } - // just check if address is a valid ipv6 CIDR address - if _, _, err := net.ParseCIDR(nap.Ipaddr6); err != nil { - return errors.Errorf("%s is not a valid ipv6 address in CIDR notation", nap.Ipaddr6) - } - } - - if nap.Discoverable { - wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting node to discoverable\n", n.Id.Get()) - - n.Discoverable.SetB(true) } err = nodeDB.NodeUpdate(n) @@ -168,7 +69,7 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { } count++ - } // end for + } err = nodeDB.Persist() if err != nil { diff --git a/internal/pkg/api/routes/v1/routes.proto b/internal/pkg/api/routes/v1/routes.proto index 6d653dfa..ee381009 100644 --- a/internal/pkg/api/routes/v1/routes.proto +++ b/internal/pkg/api/routes/v1/routes.proto @@ -134,17 +134,8 @@ message NodeListResponse { // NodeAddParameter contains all input for adding a node to be managed by // Warewulf. message NodeAddParameter { - string cluster = 1; - bool discoverable = 2; - string gateway = 3; - string hwaddr = 4; - string ipaddr = 5; - string netdev = 6; - string netmask = 7; - string netname = 8; - string type = 9; + map optionsStrMap = 1; repeated string nodeNames = 10; - string ipaddr6 = 11; } // NodeDeleteParameter contains input for removing nodes from Warewulf diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.go b/internal/pkg/api/routes/wwapiv1/routes.pb.go index 4e653252..02417e11 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.go @@ -1042,17 +1042,8 @@ type NodeAddParameter struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Cluster string `protobuf:"bytes,1,opt,name=cluster,proto3" json:"cluster,omitempty"` - Discoverable bool `protobuf:"varint,2,opt,name=discoverable,proto3" json:"discoverable,omitempty"` - Gateway string `protobuf:"bytes,3,opt,name=gateway,proto3" json:"gateway,omitempty"` - Hwaddr string `protobuf:"bytes,4,opt,name=hwaddr,proto3" json:"hwaddr,omitempty"` - Ipaddr string `protobuf:"bytes,5,opt,name=ipaddr,proto3" json:"ipaddr,omitempty"` - Netdev string `protobuf:"bytes,6,opt,name=netdev,proto3" json:"netdev,omitempty"` - Netmask string `protobuf:"bytes,7,opt,name=netmask,proto3" json:"netmask,omitempty"` - Netname string `protobuf:"bytes,8,opt,name=netname,proto3" json:"netname,omitempty"` - Type string `protobuf:"bytes,9,opt,name=type,proto3" json:"type,omitempty"` - NodeNames []string `protobuf:"bytes,10,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` - Ipaddr6 string `protobuf:"bytes,11,opt,name=ipaddr6,proto3" json:"ipaddr6,omitempty"` + OptionsStrMap map[string]string `protobuf:"bytes,1,rep,name=optionsStrMap,proto3" json:"optionsStrMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + NodeNames []string `protobuf:"bytes,10,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` } func (x *NodeAddParameter) Reset() { @@ -1087,67 +1078,11 @@ func (*NodeAddParameter) Descriptor() ([]byte, []int) { return file_routes_proto_rawDescGZIP(), []int{13} } -func (x *NodeAddParameter) GetCluster() string { +func (x *NodeAddParameter) GetOptionsStrMap() map[string]string { if x != nil { - return x.Cluster + return x.OptionsStrMap } - return "" -} - -func (x *NodeAddParameter) GetDiscoverable() bool { - if x != nil { - return x.Discoverable - } - return false -} - -func (x *NodeAddParameter) GetGateway() string { - if x != nil { - return x.Gateway - } - return "" -} - -func (x *NodeAddParameter) GetHwaddr() string { - if x != nil { - return x.Hwaddr - } - return "" -} - -func (x *NodeAddParameter) GetIpaddr() string { - if x != nil { - return x.Ipaddr - } - return "" -} - -func (x *NodeAddParameter) GetNetdev() string { - if x != nil { - return x.Netdev - } - return "" -} - -func (x *NodeAddParameter) GetNetmask() string { - if x != nil { - return x.Netmask - } - return "" -} - -func (x *NodeAddParameter) GetNetname() string { - if x != nil { - return x.Netname - } - return "" -} - -func (x *NodeAddParameter) GetType() string { - if x != nil { - return x.Type - } - return "" + return nil } func (x *NodeAddParameter) GetNodeNames() []string { @@ -1157,13 +1092,6 @@ func (x *NodeAddParameter) GetNodeNames() []string { return nil } -func (x *NodeAddParameter) GetIpaddr6() string { - if x != nil { - return x.Ipaddr6 - } - return "" -} - // NodeDeleteParameter contains input for removing nodes from Warewulf // management. type NodeDeleteParameter struct { @@ -1699,142 +1627,135 @@ var file_routes_proto_rawDesc = []byte{ 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xb2, 0x02, 0x0a, 0x10, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0c, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x77, 0x61, 0x64, - 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x77, 0x61, 0x64, 0x64, 0x72, - 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x65, 0x74, 0x64, - 0x65, 0x76, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, - 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, - 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, - 0x36, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x36, - 0x22, 0x49, 0x0a, 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, - 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xbb, 0x02, 0x0a, 0x10, - 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, - 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, - 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, - 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, - 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, - 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, - 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, - 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, - 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, - 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, - 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, - 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, - 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, - 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, - 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, - 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, - 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, - 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, - 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, - 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, - 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, - 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, + 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, + 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, + 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, + 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, + 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, + 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, + 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, + 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, + 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, + 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, + 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, + 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, + 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, + 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, + 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, + 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, + 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, + 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, + 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, + 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, + 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, - 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, - 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, + 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, + 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, + 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, + 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, + 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, + 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1849,7 +1770,7 @@ func file_routes_proto_rawDescGZIP() []byte { return file_routes_proto_rawDescData } -var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 24) +var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_routes_proto_goTypes = []interface{}{ (*ContainerBuildParameter)(nil), // 0: wwapi.v1.ContainerBuildParameter (*ContainerDeleteParameter)(nil), // 1: wwapi.v1.ContainerDeleteParameter @@ -1874,8 +1795,9 @@ var file_routes_proto_goTypes = []interface{}{ nil, // 20: wwapi.v1.NodeInfo.NetDevsEntry nil, // 21: wwapi.v1.NodeInfo.TagsEntry nil, // 22: wwapi.v1.NodeInfo.KeysEntry - nil, // 23: wwapi.v1.NodeSetParameter.OptionsStrMapEntry - (*empty.Empty)(nil), // 24: google.protobuf.Empty + nil, // 23: wwapi.v1.NodeAddParameter.OptionsStrMapEntry + nil, // 24: wwapi.v1.NodeSetParameter.OptionsStrMapEntry + (*empty.Empty)(nil), // 25: google.protobuf.Empty } var file_routes_proto_depIdxs = []int32{ 3, // 0: wwapi.v1.ContainerListResponse.containers:type_name -> wwapi.v1.ContainerInfo @@ -1912,39 +1834,40 @@ var file_routes_proto_depIdxs = []int32{ 21, // 31: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry 22, // 32: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry 11, // 33: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo - 23, // 34: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry - 16, // 35: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus - 9, // 36: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField - 10, // 37: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev - 9, // 38: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField - 9, // 39: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField - 0, // 40: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter - 1, // 41: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter - 2, // 42: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter - 24, // 43: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty - 5, // 44: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter - 13, // 45: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter - 14, // 46: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter - 8, // 47: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames - 15, // 48: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter - 8, // 49: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames - 24, // 50: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty - 4, // 51: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse - 24, // 52: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty - 4, // 53: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse - 4, // 54: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse - 6, // 55: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse - 12, // 56: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse - 24, // 57: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty - 12, // 58: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse - 12, // 59: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse - 17, // 60: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse - 18, // 61: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse - 51, // [51:62] is the sub-list for method output_type - 40, // [40:51] is the sub-list for method input_type - 40, // [40:40] is the sub-list for extension type_name - 40, // [40:40] is the sub-list for extension extendee - 0, // [0:40] is the sub-list for field type_name + 23, // 34: wwapi.v1.NodeAddParameter.optionsStrMap:type_name -> wwapi.v1.NodeAddParameter.OptionsStrMapEntry + 24, // 35: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry + 16, // 36: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus + 9, // 37: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField + 10, // 38: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev + 9, // 39: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField + 9, // 40: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField + 0, // 41: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter + 1, // 42: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter + 2, // 43: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter + 25, // 44: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty + 5, // 45: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter + 13, // 46: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter + 14, // 47: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter + 8, // 48: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames + 15, // 49: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter + 8, // 50: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames + 25, // 51: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty + 4, // 52: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse + 25, // 53: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty + 4, // 54: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse + 4, // 55: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse + 6, // 56: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse + 12, // 57: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse + 25, // 58: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty + 12, // 59: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse + 12, // 60: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse + 17, // 61: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse + 18, // 62: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse + 52, // [52:63] is the sub-list for method output_type + 41, // [41:52] is the sub-list for method input_type + 41, // [41:41] is the sub-list for extension type_name + 41, // [41:41] is the sub-list for extension extendee + 0, // [0:41] is the sub-list for field type_name } func init() { file_routes_proto_init() } @@ -2188,7 +2111,7 @@ func file_routes_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_routes_proto_rawDesc, NumEnums: 0, - NumMessages: 24, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, From 1dd519a7e6a2f8ae9ed564d3e20b0f3a2af0eb65 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 18 Jul 2022 15:04:32 +0200 Subject: [PATCH 16/38] clean up and linting fix --- internal/app/wwctl/profile/add/main.go | 2 +- internal/pkg/api/node/node.go | 10 ---------- internal/pkg/node/constructors.go | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index 8a219a95..fb502fd3 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -34,7 +34,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if !SetYes { // The checks run twice in the prompt case. // Avoiding putting in a blocking prompt in an API. - apiprofile.AddProfile(&set, false) + err = apiprofile.AddProfile(&set, false) if err != nil { return } diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index a0f1d4a6..ea16ba69 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -549,16 +549,6 @@ func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusRespo return } -// checkNetNameRequired is a helper for determining if netname is set. -// Certain settings require it. -func checkNetNameRequired(netname string) (err error) { - if netname == "" { - err = fmt.Errorf("You must include the '--netname' option") - wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) - } - return -} - /* Add the netname to the options map, as its only known after the map command line options have been read out. diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 3e56fb98..5002a32a 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -451,7 +451,7 @@ Return the names of all available profiles */ func (config *NodeYaml) ListAllProfiles() []string { var ret []string - for name, _ := range config.NodeProfiles { + for name := range config.NodeProfiles { ret = append(ret, name) } return ret From e23f7941664518a356c1cacff40e36776b0e2955 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 18 Jul 2022 19:27:57 +0200 Subject: [PATCH 17/38] simplified node list command --- Makefile | 2 +- internal/app/wwctl/node/list/main.go | 181 +++-- internal/pkg/api/node/methods.go | 79 ++ internal/pkg/api/node/node.go | 180 +---- internal/pkg/api/routes/v1/routes.proto | 33 +- internal/pkg/api/routes/wwapiv1/routes.pb.go | 810 ++++++------------- internal/pkg/node/datastructure.go | 6 +- internal/pkg/node/methods.go | 17 + 8 files changed, 442 insertions(+), 866 deletions(-) create mode 100644 internal/pkg/api/node/methods.go diff --git a/Makefile b/Makefile index 1197496d..24ed1f58 100644 --- a/Makefile +++ b/Makefile @@ -260,7 +260,7 @@ dist: vendor config ## sudo ldconfig # refresh shared library cache. ## To setup protoc-gen-grpc-gateway, see https://github.com/grpc-ecosystem/grpc-gateway proto: - rm -r internal/pkg/api/routes/wwapiv1/ + rm -rf internal/pkg/api/routes/wwapiv1/ protoc -I internal/pkg/api/routes/v1 -I=. \ --grpc-gateway_out=. \ --grpc-gateway_opt logtostderr=true \ diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 6580b61d..60cccffc 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -2,8 +2,6 @@ package list import ( "fmt" - "sort" - "strings" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -21,107 +19,114 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if ShowAll { for i := 0; i < len(nodeInfo); i++ { ni := nodeInfo[i] - nodeName := ni.Id.Value + nodeName := `UNKNOWN` + if _, ok := ni.Fields["Id"]; ok { + nodeName = ni.Fields["Id"].Print + } fmt.Printf("################################################################################\n") fmt.Printf("%-20s %-18s %-12s %s\n", "NODE", "FIELD", "PROFILE", "VALUE") - - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Id", ni.Id.Source, ni.Id.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Comment", ni.Comment.Source, ni.Comment.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Cluster", ni.Cluster.Source, ni.Cluster.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Profiles", "--", strings.Join(ni.Profiles, ",'")) - - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Discoverable", ni.Discoverable.Source, ni.Discoverable.Print) - - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Container", ni.Container.Source, ni.Container.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelOverride", ni.KernelOverride.Source, ni.KernelOverride.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelArgs", ni.KernelArgs.Source, ni.KernelArgs.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "SystemOverlay", ni.SystemOverlay.Source, ni.SystemOverlay.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "RuntimeOverlay", ni.RuntimeOverlay.Source, ni.RuntimeOverlay.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Ipxe", ni.Ipxe.Source, ni.Ipxe.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Init", ni.Init.Source, ni.Init.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Root", ni.Root.Source, ni.Root.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "AssetKey", ni.AssetKey.Source, ni.AssetKey.Print) - - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiIpaddr", ni.IpmiIpaddr.Source, ni.IpmiIpaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiNetmask", ni.IpmiNetmask.Source, ni.IpmiNetmask.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiPort", ni.IpmiPort.Source, ni.IpmiPort.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiGateway", ni.IpmiGateway.Source, ni.IpmiGateway.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiUserName", ni.IpmiUserName.Source, ni.IpmiUserName.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiInterface", ni.IpmiInterface.Source, ni.IpmiInterface.Print) - - for keyname, key := range ni.Tags { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Tag["+keyname+"]", key.Source, key.Print) + for key, val := range ni.Fields { + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, key, val.Source, val.Print) } + /* + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Comment", ni.Comment.Source, ni.Comment.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Cluster", ni.Cluster.Source, ni.Cluster.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Profiles", "--", strings.Join(ni.Profiles, ",'")) - for name, netdev := range ni.NetDevs { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEVICE", netdev.Device.Source, netdev.Device.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":HWADDR", netdev.Hwaddr.Source, netdev.Hwaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":IPADDR", netdev.Ipaddr.Source, netdev.Ipaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":NETMASK", netdev.Netmask.Source, netdev.Netmask.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":GATEWAY", netdev.Gateway.Source, netdev.Gateway.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TYPE", netdev.Type.Source, netdev.Type.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":ONBOOT", netdev.Onboot.Source, netdev.Onboot.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEFAULT", netdev.Primary.Source, netdev.Primary.Print) - for keyname, key := range netdev.Tags { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TAG["+keyname+"]", key.Source, key.Print) - } - } - } - } else if ShowNet { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY") - fmt.Println(strings.Repeat("=", 80)) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Discoverable", ni.Discoverable.Source, ni.Discoverable.Print) - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Container", ni.Container.Source, ni.Container.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelOverride", ni.KernelOverride.Source, ni.KernelOverride.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelArgs", ni.KernelArgs.Source, ni.KernelArgs.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "SystemOverlay", ni.SystemOverlay.Source, ni.SystemOverlay.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "RuntimeOverlay", ni.RuntimeOverlay.Source, ni.RuntimeOverlay.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Ipxe", ni.Ipxe.Source, ni.Ipxe.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Init", ni.Init.Source, ni.Init.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Root", ni.Root.Source, ni.Root.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "AssetKey", ni.AssetKey.Source, ni.AssetKey.Print) - if len(ni.NetDevs) > 0 { - for name, dev := range ni.NetDevs { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, name, dev.Hwaddr.Print, dev.Ipaddr.Print, dev.Gateway.Print) - } - } else { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, "--", "--", "--", "--") - } - } - } else if ShowIpmi { - fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI PASSWORD", "IPMI INTERFACE") - fmt.Println(strings.Repeat("=", 108)) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiIpaddr", ni.IpmiIpaddr.Source, ni.IpmiIpaddr.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiNetmask", ni.IpmiNetmask.Source, ni.IpmiNetmask.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiPort", ni.IpmiPort.Source, ni.IpmiPort.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiGateway", ni.IpmiGateway.Source, ni.IpmiGateway.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiUserName", ni.IpmiUserName.Source, ni.IpmiUserName.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiInterface", ni.IpmiInterface.Source, ni.IpmiInterface.Print) - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value + for keyname, key := range ni.Tags { + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Tag["+keyname+"]", key.Source, key.Print) + } - fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", nodeName, ni.IpmiIpaddr.Print, ni.IpmiPort.Print, ni.IpmiUserName.Print, ni.IpmiPassword.Print, ni.IpmiInterface.Print) - } + for name, netdev := range ni.NetDevs { + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEVICE", netdev.Device.Source, netdev.Device.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":HWADDR", netdev.Hwaddr.Source, netdev.Hwaddr.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":IPADDR", netdev.Ipaddr.Source, netdev.Ipaddr.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":NETMASK", netdev.Netmask.Source, netdev.Netmask.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":GATEWAY", netdev.Gateway.Source, netdev.Gateway.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TYPE", netdev.Type.Source, netdev.Type.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":ONBOOT", netdev.Onboot.Source, netdev.Onboot.Print) + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEFAULT", netdev.Primary.Source, netdev.Primary.Print) + for keyname, key := range netdev.Tags { + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TAG["+keyname+"]", key.Source, key.Print) + } + } + } + } else if ShowNet { + fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY") + fmt.Println(strings.Repeat("=", 80)) - } else if ShowLong { - fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") - fmt.Println(strings.Repeat("=", 120)) + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := ni.Id.Value - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value + if len(ni.NetDevs) > 0 { + for name, dev := range ni.NetDevs { + fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, name, dev.Hwaddr.Print, dev.Ipaddr.Print, dev.Gateway.Print) + } + } else { + fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, "--", "--", "--", "--") + } + } + } else if ShowIpmi { + fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI PASSWORD", "IPMI INTERFACE") + fmt.Println(strings.Repeat("=", 108)) - fmt.Printf("%-22s %-26s %-35s %s\n", nodeName, ni.KernelOverride.Print, ni.Container.Print, ni.SystemOverlay.Print+"/"+ni.RuntimeOverlay.Print) - } + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := ni.Id.Value - } else { - fmt.Printf("%-22s %-26s %s\n", "NODE NAME", "PROFILES", "NETWORK") - fmt.Println(strings.Repeat("=", 80)) + fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", nodeName, ni.IpmiIpaddr.Print, ni.IpmiPort.Print, ni.IpmiUserName.Print, ni.IpmiPassword.Print, ni.IpmiInterface.Print) + } - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value + } else if ShowLong { + fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") + fmt.Println(strings.Repeat("=", 120)) - var netdevs []string - if len(ni.NetDevs) > 0 { - for name, dev := range ni.NetDevs { - netdevs = append(netdevs, fmt.Sprintf("%s:%s", name, dev.Ipaddr.Print)) - } - } - sort.Strings(netdevs) - fmt.Printf("%-22s %-26s %s\n", nodeName, strings.Join(ni.Profiles, ","), strings.Join(netdevs, ", ")) + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := ni.Id.Value + + fmt.Printf("%-22s %-26s %-35s %s\n", nodeName, ni.KernelOverride.Print, ni.Container.Print, ni.SystemOverlay.Print+"/"+ni.RuntimeOverlay.Print) + } + + } else { + fmt.Printf("%-22s %-26s %s\n", "NODE NAME", "PROFILES", "NETWORK") + fmt.Println(strings.Repeat("=", 80)) + + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := ni.Id.Value + + var netdevs []string + if len(ni.NetDevs) > 0 { + for name, dev := range ni.NetDevs { + netdevs = append(netdevs, fmt.Sprintf("%s:%s", name, dev.Ipaddr.Print)) + } + } + sort.Strings(netdevs) + fmt.Printf("%-22s %-26s %s\n", nodeName, strings.Join(ni.Profiles, ","), strings.Join(netdevs, ", ")) + } + */ } } return diff --git a/internal/pkg/api/node/methods.go b/internal/pkg/api/node/methods.go new file mode 100644 index 00000000..dc561238 --- /dev/null +++ b/internal/pkg/api/node/methods.go @@ -0,0 +1,79 @@ +package apinode + +import ( + "fmt" + "reflect" + "strings" + + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/node" +) + +/* +Get the all the fields of a NodeInfo, keys are the lopt of NodeConf. +func GetFields(n interface{}) map[string]*wwapiv1.NodeField { + return getFieldsOf(n, node.NodeConf{}) +} +*/ + +func GetFields(n interface{}) map[string]*wwapiv1.NodeField { + nodeType := reflect.TypeOf(n) + nodeVal := reflect.ValueOf(n) + fieldMap := make(map[string]*wwapiv1.NodeField) + for i := 0; i < nodeType.NumField(); i++ { + switch nodeType.Field(i).Type { + case reflect.TypeOf(node.Entry{}): + var myField wwapiv1.NodeField + entry := nodeVal.Field(i).Interface().(node.Entry) + myField.Source = entry.Source() + myField.Value = entry.Get() + myField.Print = entry.Print() + fieldMap[nodeType.Field(i).Name] = &myField + case reflect.TypeOf([]string{}): + var myField wwapiv1.NodeField + entry := nodeVal.Field(i).Interface().([]string) + if len(entry) == 0 { + myField.Value = node.NoValue + myField.Print = node.NoValue + myField.Source = node.NoValue + } else { + myField.Value = strings.Join(entry, ",") + myField.Print = strings.Join(entry, ",") + myField.Source = node.NoValue + fieldMap[nodeType.Field(i).Name] = &myField + } + case reflect.TypeOf((*node.KernelEntry)(nil)): + entry := nodeVal.Field(i).Elem().Interface().(node.KernelEntry) + kernelMap := GetFields(entry) + for key, val := range kernelMap { + fieldMap["kernel:"+key] = val + } + case reflect.TypeOf((*node.IpmiEntry)(nil)): + entry := nodeVal.Field(i).Elem().Interface().(node.IpmiEntry) + kernelMap := GetFields(entry) + for key, val := range kernelMap { + fieldMap["ipmi:"+key] = val + } + case reflect.TypeOf(map[string]*node.Entry(nil)): + keyMap := nodeVal.Field(i).Interface().(map[string]*node.Entry) + for key, entr := range keyMap { + var myField wwapiv1.NodeField + myField.Source = entr.Source() + myField.Value = entr.Get() + myField.Print = entr.Print() + fieldMap["key:"+key] = &myField + } + case reflect.TypeOf(map[string]*node.NetDevEntry(nil)): + netMap := nodeVal.Field(i).Interface().(map[string]*node.NetDevEntry) + for net, netdev := range netMap { + netMapEntr := GetFields(*netdev) + for key, val := range netMapEntr { + fieldMap[net+":"+key] = val + } + } + default: + fmt.Println(nodeType.Field(i).Type) + } + } + return fieldMap +} diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index ea16ba69..5e7e902a 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "os" - "strconv" "strings" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" @@ -183,184 +182,9 @@ func NodeList(nodeNames []string) (nodeInfo []*wwapiv1.NodeInfo, err error) { // Translate to the protobuf structure so wwapiv1 can use this across the wire. // This is the same logic as was in wwctl. - for _, node := range node.FilterByName(nodes, nodeNames) { - + for _, n := range node.FilterByName(nodes, nodeNames) { var ni wwapiv1.NodeInfo - - ni.Id = &wwapiv1.NodeField{ - Source: node.Id.Source(), - Value: node.Id.Get(), - Print: node.Id.Print(), - } - - ni.Comment = &wwapiv1.NodeField{ - Source: node.Comment.Source(), - Value: node.Comment.Get(), - Print: node.Comment.Print(), - } - - ni.Cluster = &wwapiv1.NodeField{ - Source: node.ClusterName.Source(), - Value: node.ClusterName.Get(), - Print: node.ClusterName.Print(), - } - - ni.Profiles = node.Profiles - - ni.Discoverable = &wwapiv1.NodeField{ - Source: node.Discoverable.Source(), - Value: strconv.FormatBool(node.Discoverable.GetB()), - Print: node.Discoverable.PrintB(), - } - - ni.Container = &wwapiv1.NodeField{ - Source: node.ContainerName.Source(), - Value: node.ContainerName.Get(), - Print: node.ContainerName.Print(), - } - - ni.KernelOverride = &wwapiv1.NodeField{ - Source: node.Kernel.Override.Source(), - Value: node.Kernel.Override.Get(), - Print: node.Kernel.Override.Print(), - } - - ni.KernelArgs = &wwapiv1.NodeField{ - Source: node.Kernel.Args.Source(), - Value: node.Kernel.Args.Get(), - Print: node.Kernel.Args.Print(), - } - - ni.SystemOverlay = &wwapiv1.NodeField{ - Source: node.SystemOverlay.Source(), - Value: node.SystemOverlay.Get(), - Print: node.SystemOverlay.Print(), - } - - ni.RuntimeOverlay = &wwapiv1.NodeField{ - Source: node.RuntimeOverlay.Source(), - Value: node.RuntimeOverlay.Get(), - Print: node.RuntimeOverlay.Print(), - } - - ni.Ipxe = &wwapiv1.NodeField{ - Source: node.Ipxe.Source(), - Value: node.Ipxe.Get(), - Print: node.Ipxe.Print(), - } - - ni.Init = &wwapiv1.NodeField{ - Source: node.Init.Source(), - Value: node.Init.Get(), - Print: node.Init.Print(), - } - - ni.Root = &wwapiv1.NodeField{ - Source: node.Root.Source(), - Value: node.Root.Get(), - Print: node.Root.Print(), - } - - ni.AssetKey = &wwapiv1.NodeField{ - Source: node.AssetKey.Source(), - Value: node.AssetKey.Get(), - Print: node.AssetKey.Print(), - } - - ni.IpmiIpaddr = &wwapiv1.NodeField{ - Source: node.Ipmi.Ipaddr.Source(), - Value: node.Ipmi.Ipaddr.Get(), - Print: node.Ipmi.Ipaddr.Print(), - } - - ni.IpmiNetmask = &wwapiv1.NodeField{ - Source: node.Ipmi.Netmask.Source(), - Value: node.Ipmi.Netmask.Get(), - Print: node.Ipmi.Netmask.Print(), - } - - ni.IpmiPort = &wwapiv1.NodeField{ - Source: node.Ipmi.Port.Source(), - Value: node.Ipmi.Port.Get(), - Print: node.Ipmi.Port.Print(), - } - - ni.IpmiGateway = &wwapiv1.NodeField{ - Source: node.Ipmi.Gateway.Source(), - Value: node.Ipmi.Gateway.Get(), - Print: node.Ipmi.Gateway.Print(), - } - - ni.IpmiUserName = &wwapiv1.NodeField{ - Source: node.Ipmi.UserName.Source(), - Value: node.Ipmi.UserName.Get(), - Print: node.Ipmi.UserName.Print(), - } - - ni.IpmiPassword = &wwapiv1.NodeField{ - Source: node.Ipmi.Password.Source(), - Value: node.Ipmi.Password.Get(), - Print: node.Ipmi.Password.Print(), // TODO: Password was removed from pprinted output, at least in some places. - } - - ni.IpmiInterface = &wwapiv1.NodeField{ - Source: node.Ipmi.Interface.Source(), - Value: node.Ipmi.Interface.Get(), - Print: node.Ipmi.Interface.Print(), - } - ni.Tags = map[string]*wwapiv1.NodeField{} - for keyname, keyvalue := range node.Tags { - ni.Tags[keyname] = new(wwapiv1.NodeField) - ni.Tags[keyname].Source = keyvalue.Source() - ni.Tags[keyname].Value = keyvalue.Get() - ni.Tags[keyname].Print = keyvalue.Print() - } - ni.NetDevs = map[string]*wwapiv1.NetDev{} - for name, netdev := range node.NetDevs { - - ni.NetDevs[name] = &wwapiv1.NetDev{ - Device: &wwapiv1.NodeField{ - Source: netdev.Device.Source(), - Value: netdev.Device.Get(), - Print: netdev.Device.Print(), - }, - Hwaddr: &wwapiv1.NodeField{ - Source: netdev.Hwaddr.Source(), - Value: netdev.Hwaddr.Get(), - Print: netdev.Hwaddr.Print(), - }, - Ipaddr: &wwapiv1.NodeField{ - Source: netdev.Ipaddr.Source(), - Value: netdev.Ipaddr.Get(), - Print: netdev.Ipaddr.Print(), - }, - Netmask: &wwapiv1.NodeField{ - Source: netdev.Netmask.Source(), - Value: netdev.Netmask.Get(), - Print: netdev.Netmask.Print(), - }, - Gateway: &wwapiv1.NodeField{ - Source: netdev.Gateway.Source(), - Value: netdev.Gateway.Get(), - Print: netdev.Gateway.Print(), - }, - Type: &wwapiv1.NodeField{ - Source: netdev.Type.Source(), - Value: netdev.Type.Get(), - Print: netdev.Type.Print(), - }, - Onboot: &wwapiv1.NodeField{ - Source: netdev.OnBoot.Source(), - Value: strconv.FormatBool(netdev.OnBoot.GetB()), - Print: netdev.OnBoot.PrintB(), - }, - Primary: &wwapiv1.NodeField{ - Source: netdev.Primary.Source(), - Value: strconv.FormatBool(netdev.Primary.GetB()), - Print: netdev.Primary.PrintB(), - }, - } - } + ni.Fields = GetFields(n) nodeInfo = append(nodeInfo, &ni) } return diff --git a/internal/pkg/api/routes/v1/routes.proto b/internal/pkg/api/routes/v1/routes.proto index ee381009..d3b3de2f 100644 --- a/internal/pkg/api/routes/v1/routes.proto +++ b/internal/pkg/api/routes/v1/routes.proto @@ -84,42 +84,13 @@ message NodeField { // NetDev is network devices (NICs) on a node. message NetDev { - NodeField type = 1; - NodeField onboot = 2; - NodeField device = 3; - NodeField hwaddr = 4; - NodeField ipaddr = 5; - NodeField netmask = 6; - NodeField gateway = 7; - NodeField primary = 8; + map Field = 1; map Tags = 9; } // NodeInfo contains details about a node managed by Warewulf/ message NodeInfo { - NodeField id = 1; - NodeField comment = 2; - NodeField cluster = 3; - NodeField discoverable = 4; - NodeField container = 5; - NodeField kernelOverride = 6; - NodeField kernelArgs = 7; - NodeField systemOverlay = 8; - NodeField runtimeOverlay = 9; - NodeField ipxe = 10; - NodeField init = 11; - NodeField root = 12; - NodeField assetKey = 13; - NodeField ipmiIpaddr = 14; - NodeField ipmiNetmask = 15; - NodeField ipmiPort = 16; - NodeField ipmiGateway = 17; - NodeField ipmiUserName = 18; - NodeField ipmiInterface = 19; - NodeField ipmiPassword = 20; - - repeated string profiles = 21; - repeated string groupProfiles = 22; + map Fields = 1; map NetDevs = 23; map Tags = 24; diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.go b/internal/pkg/api/routes/wwapiv1/routes.pb.go index 02417e11..30d23083 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.go @@ -641,15 +641,8 @@ type NetDev struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Type *NodeField `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - Onboot *NodeField `protobuf:"bytes,2,opt,name=onboot,proto3" json:"onboot,omitempty"` - Device *NodeField `protobuf:"bytes,3,opt,name=device,proto3" json:"device,omitempty"` - Hwaddr *NodeField `protobuf:"bytes,4,opt,name=hwaddr,proto3" json:"hwaddr,omitempty"` - Ipaddr *NodeField `protobuf:"bytes,5,opt,name=ipaddr,proto3" json:"ipaddr,omitempty"` - Netmask *NodeField `protobuf:"bytes,6,opt,name=netmask,proto3" json:"netmask,omitempty"` - Gateway *NodeField `protobuf:"bytes,7,opt,name=gateway,proto3" json:"gateway,omitempty"` - Primary *NodeField `protobuf:"bytes,8,opt,name=primary,proto3" json:"primary,omitempty"` - Tags map[string]*NodeField `protobuf:"bytes,9,rep,name=Tags,proto3" json:"Tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Field map[string]*NodeField `protobuf:"bytes,1,rep,name=Field,proto3" json:"Field,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Tags map[string]*NodeField `protobuf:"bytes,9,rep,name=Tags,proto3" json:"Tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *NetDev) Reset() { @@ -684,58 +677,9 @@ func (*NetDev) Descriptor() ([]byte, []int) { return file_routes_proto_rawDescGZIP(), []int{10} } -func (x *NetDev) GetType() *NodeField { +func (x *NetDev) GetField() map[string]*NodeField { if x != nil { - return x.Type - } - return nil -} - -func (x *NetDev) GetOnboot() *NodeField { - if x != nil { - return x.Onboot - } - return nil -} - -func (x *NetDev) GetDevice() *NodeField { - if x != nil { - return x.Device - } - return nil -} - -func (x *NetDev) GetHwaddr() *NodeField { - if x != nil { - return x.Hwaddr - } - return nil -} - -func (x *NetDev) GetIpaddr() *NodeField { - if x != nil { - return x.Ipaddr - } - return nil -} - -func (x *NetDev) GetNetmask() *NodeField { - if x != nil { - return x.Netmask - } - return nil -} - -func (x *NetDev) GetGateway() *NodeField { - if x != nil { - return x.Gateway - } - return nil -} - -func (x *NetDev) GetPrimary() *NodeField { - if x != nil { - return x.Primary + return x.Field } return nil } @@ -753,31 +697,10 @@ type NodeInfo struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id *NodeField `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Comment *NodeField `protobuf:"bytes,2,opt,name=comment,proto3" json:"comment,omitempty"` - Cluster *NodeField `protobuf:"bytes,3,opt,name=cluster,proto3" json:"cluster,omitempty"` - Discoverable *NodeField `protobuf:"bytes,4,opt,name=discoverable,proto3" json:"discoverable,omitempty"` - Container *NodeField `protobuf:"bytes,5,opt,name=container,proto3" json:"container,omitempty"` - KernelOverride *NodeField `protobuf:"bytes,6,opt,name=kernelOverride,proto3" json:"kernelOverride,omitempty"` - KernelArgs *NodeField `protobuf:"bytes,7,opt,name=kernelArgs,proto3" json:"kernelArgs,omitempty"` - SystemOverlay *NodeField `protobuf:"bytes,8,opt,name=systemOverlay,proto3" json:"systemOverlay,omitempty"` - RuntimeOverlay *NodeField `protobuf:"bytes,9,opt,name=runtimeOverlay,proto3" json:"runtimeOverlay,omitempty"` - Ipxe *NodeField `protobuf:"bytes,10,opt,name=ipxe,proto3" json:"ipxe,omitempty"` - Init *NodeField `protobuf:"bytes,11,opt,name=init,proto3" json:"init,omitempty"` - Root *NodeField `protobuf:"bytes,12,opt,name=root,proto3" json:"root,omitempty"` - AssetKey *NodeField `protobuf:"bytes,13,opt,name=assetKey,proto3" json:"assetKey,omitempty"` - IpmiIpaddr *NodeField `protobuf:"bytes,14,opt,name=ipmiIpaddr,proto3" json:"ipmiIpaddr,omitempty"` - IpmiNetmask *NodeField `protobuf:"bytes,15,opt,name=ipmiNetmask,proto3" json:"ipmiNetmask,omitempty"` - IpmiPort *NodeField `protobuf:"bytes,16,opt,name=ipmiPort,proto3" json:"ipmiPort,omitempty"` - IpmiGateway *NodeField `protobuf:"bytes,17,opt,name=ipmiGateway,proto3" json:"ipmiGateway,omitempty"` - IpmiUserName *NodeField `protobuf:"bytes,18,opt,name=ipmiUserName,proto3" json:"ipmiUserName,omitempty"` - IpmiInterface *NodeField `protobuf:"bytes,19,opt,name=ipmiInterface,proto3" json:"ipmiInterface,omitempty"` - IpmiPassword *NodeField `protobuf:"bytes,20,opt,name=ipmiPassword,proto3" json:"ipmiPassword,omitempty"` - Profiles []string `protobuf:"bytes,21,rep,name=profiles,proto3" json:"profiles,omitempty"` - GroupProfiles []string `protobuf:"bytes,22,rep,name=groupProfiles,proto3" json:"groupProfiles,omitempty"` - NetDevs map[string]*NetDev `protobuf:"bytes,23,rep,name=NetDevs,proto3" json:"NetDevs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Tags map[string]*NodeField `protobuf:"bytes,24,rep,name=Tags,proto3" json:"Tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Keys map[string]*NodeField `protobuf:"bytes,25,rep,name=Keys,proto3" json:"Keys,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // TODO: We may not need this. Tags may be it. Ask Greg. + Fields map[string]*NodeField `protobuf:"bytes,1,rep,name=Fields,proto3" json:"Fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + NetDevs map[string]*NetDev `protobuf:"bytes,23,rep,name=NetDevs,proto3" json:"NetDevs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Tags map[string]*NodeField `protobuf:"bytes,24,rep,name=Tags,proto3" json:"Tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Keys map[string]*NodeField `protobuf:"bytes,25,rep,name=Keys,proto3" json:"Keys,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // TODO: We may not need this. Tags may be it. Ask Greg. } func (x *NodeInfo) Reset() { @@ -812,156 +735,9 @@ func (*NodeInfo) Descriptor() ([]byte, []int) { return file_routes_proto_rawDescGZIP(), []int{11} } -func (x *NodeInfo) GetId() *NodeField { +func (x *NodeInfo) GetFields() map[string]*NodeField { if x != nil { - return x.Id - } - return nil -} - -func (x *NodeInfo) GetComment() *NodeField { - if x != nil { - return x.Comment - } - return nil -} - -func (x *NodeInfo) GetCluster() *NodeField { - if x != nil { - return x.Cluster - } - return nil -} - -func (x *NodeInfo) GetDiscoverable() *NodeField { - if x != nil { - return x.Discoverable - } - return nil -} - -func (x *NodeInfo) GetContainer() *NodeField { - if x != nil { - return x.Container - } - return nil -} - -func (x *NodeInfo) GetKernelOverride() *NodeField { - if x != nil { - return x.KernelOverride - } - return nil -} - -func (x *NodeInfo) GetKernelArgs() *NodeField { - if x != nil { - return x.KernelArgs - } - return nil -} - -func (x *NodeInfo) GetSystemOverlay() *NodeField { - if x != nil { - return x.SystemOverlay - } - return nil -} - -func (x *NodeInfo) GetRuntimeOverlay() *NodeField { - if x != nil { - return x.RuntimeOverlay - } - return nil -} - -func (x *NodeInfo) GetIpxe() *NodeField { - if x != nil { - return x.Ipxe - } - return nil -} - -func (x *NodeInfo) GetInit() *NodeField { - if x != nil { - return x.Init - } - return nil -} - -func (x *NodeInfo) GetRoot() *NodeField { - if x != nil { - return x.Root - } - return nil -} - -func (x *NodeInfo) GetAssetKey() *NodeField { - if x != nil { - return x.AssetKey - } - return nil -} - -func (x *NodeInfo) GetIpmiIpaddr() *NodeField { - if x != nil { - return x.IpmiIpaddr - } - return nil -} - -func (x *NodeInfo) GetIpmiNetmask() *NodeField { - if x != nil { - return x.IpmiNetmask - } - return nil -} - -func (x *NodeInfo) GetIpmiPort() *NodeField { - if x != nil { - return x.IpmiPort - } - return nil -} - -func (x *NodeInfo) GetIpmiGateway() *NodeField { - if x != nil { - return x.IpmiGateway - } - return nil -} - -func (x *NodeInfo) GetIpmiUserName() *NodeField { - if x != nil { - return x.IpmiUserName - } - return nil -} - -func (x *NodeInfo) GetIpmiInterface() *NodeField { - if x != nil { - return x.IpmiInterface - } - return nil -} - -func (x *NodeInfo) GetIpmiPassword() *NodeField { - if x != nil { - return x.IpmiPassword - } - return nil -} - -func (x *NodeInfo) GetProfiles() []string { - if x != nil { - return x.Profiles - } - return nil -} - -func (x *NodeInfo) GetGroupProfiles() []string { - if x != nil { - return x.GroupProfiles + return x.Fields } return nil } @@ -1498,264 +1274,190 @@ var file_routes_proto_rawDesc = []byte{ 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0xf0, 0x03, 0x0a, - 0x06, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x12, 0x27, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x2b, 0x0a, 0x06, 0x6f, 0x6e, 0x62, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x6f, 0x6e, 0x62, 0x6f, 0x6f, 0x74, 0x12, 0x2b, 0x0a, - 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x68, 0x77, - 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, - 0x06, 0x68, 0x77, 0x61, 0x64, 0x64, 0x72, 0x12, 0x2b, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, - 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x69, 0x70, - 0x61, 0x64, 0x64, 0x72, 0x12, 0x2d, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x6d, - 0x61, 0x73, 0x6b, 0x12, 0x2d, 0x0a, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x67, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, - 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, - 0x76, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x54, 0x61, 0x67, - 0x73, 0x1a, 0x4c, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0xdb, 0x0b, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x23, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x2d, 0x0a, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, - 0x37, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x31, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x0e, 0x6b, - 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x33, 0x0a, 0x0a, 0x6b, 0x65, 0x72, 0x6e, - 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x52, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x41, 0x72, 0x67, 0x73, 0x12, 0x39, 0x0a, - 0x0d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0d, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x3b, 0x0a, 0x0e, 0x72, 0x75, 0x6e, 0x74, - 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0e, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4f, 0x76, - 0x65, 0x72, 0x6c, 0x61, 0x79, 0x12, 0x27, 0x0a, 0x04, 0x69, 0x70, 0x78, 0x65, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, 0x69, 0x70, 0x78, 0x65, 0x12, 0x27, - 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x27, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x74, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x74, - 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4b, 0x65, - 0x79, 0x12, 0x33, 0x0a, 0x0a, 0x69, 0x70, 0x6d, 0x69, 0x49, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, - 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0a, 0x69, 0x70, 0x6d, 0x69, - 0x49, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x35, 0x0a, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x4e, 0x65, - 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x52, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x12, 0x2f, 0x0a, - 0x08, 0x69, 0x70, 0x6d, 0x69, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x08, 0x69, 0x70, 0x6d, 0x69, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x35, - 0x0a, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0b, 0x69, 0x70, 0x6d, 0x69, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x37, 0x0a, 0x0c, 0x69, 0x70, 0x6d, 0x69, 0x55, 0x73, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x52, 0x0c, 0x69, 0x70, 0x6d, 0x69, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, - 0x0a, 0x0d, 0x69, 0x70, 0x6d, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, - 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0d, 0x69, 0x70, 0x6d, 0x69, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x0c, 0x69, 0x70, 0x6d, - 0x69, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x0c, 0x69, 0x70, 0x6d, 0x69, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x15, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x24, - 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, - 0x16, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x18, - 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x12, - 0x30, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x88, 0x02, 0x0a, + 0x06, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x12, 0x31, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x54, 0x61, + 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x1a, 0x4d, 0x0a, 0x0a, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x09, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9b, 0x04, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x36, 0x0a, 0x06, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12, 0x39, 0x0a, 0x07, + 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x18, 0x17, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x54, 0x61, 0x67, - 0x73, 0x12, 0x30, 0x0a, 0x04, 0x4b, 0x65, 0x79, 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4b, - 0x65, 0x79, 0x73, 0x1a, 0x4c, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x4c, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, - 0x4c, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, - 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3c, 0x0a, - 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x10, - 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, - 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, - 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, - 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, - 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, - 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, - 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, - 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, - 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, - 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, - 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, - 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, - 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, - 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, - 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, - 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, - 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, - 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, - 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, - 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, + 0x6f, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, + 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, + 0x18, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x04, 0x4b, 0x65, 0x79, + 0x73, 0x18, 0x19, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4b, 0x65, 0x79, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x4e, 0x0a, 0x0b, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x0c, 0x4e, + 0x65, 0x74, 0x44, 0x65, 0x76, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x44, 0x65, 0x76, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x09, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x4c, 0x0a, 0x09, 0x4b, 0x65, 0x79, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3c, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, + 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, + 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, + 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, + 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, + 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, + 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x4e, 0x6f, 0x64, + 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, + 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, + 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, + 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, + 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, + 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, + 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, + 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, + 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, + 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, + 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, + 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, - 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, - 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, - 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, - 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, + 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, + 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, + 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, + 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, + 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, + 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, + 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, + 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, + 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, + 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, - 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, - 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, - 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, - 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, - 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, - 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, - 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, + 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1770,7 +1472,7 @@ func file_routes_proto_rawDescGZIP() []byte { return file_routes_proto_rawDescData } -var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_routes_proto_goTypes = []interface{}{ (*ContainerBuildParameter)(nil), // 0: wwapi.v1.ContainerBuildParameter (*ContainerDeleteParameter)(nil), // 1: wwapi.v1.ContainerDeleteParameter @@ -1791,83 +1493,61 @@ var file_routes_proto_goTypes = []interface{}{ (*NodeStatus)(nil), // 16: wwapi.v1.NodeStatus (*NodeStatusResponse)(nil), // 17: wwapi.v1.NodeStatusResponse (*VersionResponse)(nil), // 18: wwapi.v1.VersionResponse - nil, // 19: wwapi.v1.NetDev.TagsEntry - nil, // 20: wwapi.v1.NodeInfo.NetDevsEntry - nil, // 21: wwapi.v1.NodeInfo.TagsEntry - nil, // 22: wwapi.v1.NodeInfo.KeysEntry - nil, // 23: wwapi.v1.NodeAddParameter.OptionsStrMapEntry - nil, // 24: wwapi.v1.NodeSetParameter.OptionsStrMapEntry - (*empty.Empty)(nil), // 25: google.protobuf.Empty + nil, // 19: wwapi.v1.NetDev.FieldEntry + nil, // 20: wwapi.v1.NetDev.TagsEntry + nil, // 21: wwapi.v1.NodeInfo.FieldsEntry + nil, // 22: wwapi.v1.NodeInfo.NetDevsEntry + nil, // 23: wwapi.v1.NodeInfo.TagsEntry + nil, // 24: wwapi.v1.NodeInfo.KeysEntry + nil, // 25: wwapi.v1.NodeAddParameter.OptionsStrMapEntry + nil, // 26: wwapi.v1.NodeSetParameter.OptionsStrMapEntry + (*empty.Empty)(nil), // 27: google.protobuf.Empty } var file_routes_proto_depIdxs = []int32{ 3, // 0: wwapi.v1.ContainerListResponse.containers:type_name -> wwapi.v1.ContainerInfo - 9, // 1: wwapi.v1.NetDev.type:type_name -> wwapi.v1.NodeField - 9, // 2: wwapi.v1.NetDev.onboot:type_name -> wwapi.v1.NodeField - 9, // 3: wwapi.v1.NetDev.device:type_name -> wwapi.v1.NodeField - 9, // 4: wwapi.v1.NetDev.hwaddr:type_name -> wwapi.v1.NodeField - 9, // 5: wwapi.v1.NetDev.ipaddr:type_name -> wwapi.v1.NodeField - 9, // 6: wwapi.v1.NetDev.netmask:type_name -> wwapi.v1.NodeField - 9, // 7: wwapi.v1.NetDev.gateway:type_name -> wwapi.v1.NodeField - 9, // 8: wwapi.v1.NetDev.primary:type_name -> wwapi.v1.NodeField - 19, // 9: wwapi.v1.NetDev.Tags:type_name -> wwapi.v1.NetDev.TagsEntry - 9, // 10: wwapi.v1.NodeInfo.id:type_name -> wwapi.v1.NodeField - 9, // 11: wwapi.v1.NodeInfo.comment:type_name -> wwapi.v1.NodeField - 9, // 12: wwapi.v1.NodeInfo.cluster:type_name -> wwapi.v1.NodeField - 9, // 13: wwapi.v1.NodeInfo.discoverable:type_name -> wwapi.v1.NodeField - 9, // 14: wwapi.v1.NodeInfo.container:type_name -> wwapi.v1.NodeField - 9, // 15: wwapi.v1.NodeInfo.kernelOverride:type_name -> wwapi.v1.NodeField - 9, // 16: wwapi.v1.NodeInfo.kernelArgs:type_name -> wwapi.v1.NodeField - 9, // 17: wwapi.v1.NodeInfo.systemOverlay:type_name -> wwapi.v1.NodeField - 9, // 18: wwapi.v1.NodeInfo.runtimeOverlay:type_name -> wwapi.v1.NodeField - 9, // 19: wwapi.v1.NodeInfo.ipxe:type_name -> wwapi.v1.NodeField - 9, // 20: wwapi.v1.NodeInfo.init:type_name -> wwapi.v1.NodeField - 9, // 21: wwapi.v1.NodeInfo.root:type_name -> wwapi.v1.NodeField - 9, // 22: wwapi.v1.NodeInfo.assetKey:type_name -> wwapi.v1.NodeField - 9, // 23: wwapi.v1.NodeInfo.ipmiIpaddr:type_name -> wwapi.v1.NodeField - 9, // 24: wwapi.v1.NodeInfo.ipmiNetmask:type_name -> wwapi.v1.NodeField - 9, // 25: wwapi.v1.NodeInfo.ipmiPort:type_name -> wwapi.v1.NodeField - 9, // 26: wwapi.v1.NodeInfo.ipmiGateway:type_name -> wwapi.v1.NodeField - 9, // 27: wwapi.v1.NodeInfo.ipmiUserName:type_name -> wwapi.v1.NodeField - 9, // 28: wwapi.v1.NodeInfo.ipmiInterface:type_name -> wwapi.v1.NodeField - 9, // 29: wwapi.v1.NodeInfo.ipmiPassword:type_name -> wwapi.v1.NodeField - 20, // 30: wwapi.v1.NodeInfo.NetDevs:type_name -> wwapi.v1.NodeInfo.NetDevsEntry - 21, // 31: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry - 22, // 32: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry - 11, // 33: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo - 23, // 34: wwapi.v1.NodeAddParameter.optionsStrMap:type_name -> wwapi.v1.NodeAddParameter.OptionsStrMapEntry - 24, // 35: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry - 16, // 36: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus - 9, // 37: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField - 10, // 38: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev - 9, // 39: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField - 9, // 40: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField - 0, // 41: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter - 1, // 42: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter - 2, // 43: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter - 25, // 44: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty - 5, // 45: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter - 13, // 46: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter - 14, // 47: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter - 8, // 48: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames - 15, // 49: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter - 8, // 50: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames - 25, // 51: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty - 4, // 52: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse - 25, // 53: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty - 4, // 54: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse - 4, // 55: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse - 6, // 56: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse - 12, // 57: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse - 25, // 58: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty - 12, // 59: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse - 12, // 60: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse - 17, // 61: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse - 18, // 62: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse - 52, // [52:63] is the sub-list for method output_type - 41, // [41:52] is the sub-list for method input_type - 41, // [41:41] is the sub-list for extension type_name - 41, // [41:41] is the sub-list for extension extendee - 0, // [0:41] is the sub-list for field type_name + 19, // 1: wwapi.v1.NetDev.Field:type_name -> wwapi.v1.NetDev.FieldEntry + 20, // 2: wwapi.v1.NetDev.Tags:type_name -> wwapi.v1.NetDev.TagsEntry + 21, // 3: wwapi.v1.NodeInfo.Fields:type_name -> wwapi.v1.NodeInfo.FieldsEntry + 22, // 4: wwapi.v1.NodeInfo.NetDevs:type_name -> wwapi.v1.NodeInfo.NetDevsEntry + 23, // 5: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry + 24, // 6: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry + 11, // 7: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo + 25, // 8: wwapi.v1.NodeAddParameter.optionsStrMap:type_name -> wwapi.v1.NodeAddParameter.OptionsStrMapEntry + 26, // 9: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry + 16, // 10: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus + 9, // 11: wwapi.v1.NetDev.FieldEntry.value:type_name -> wwapi.v1.NodeField + 9, // 12: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField + 9, // 13: wwapi.v1.NodeInfo.FieldsEntry.value:type_name -> wwapi.v1.NodeField + 10, // 14: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev + 9, // 15: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField + 9, // 16: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField + 0, // 17: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter + 1, // 18: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter + 2, // 19: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter + 27, // 20: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty + 5, // 21: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter + 13, // 22: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter + 14, // 23: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter + 8, // 24: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames + 15, // 25: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter + 8, // 26: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames + 27, // 27: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty + 4, // 28: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse + 27, // 29: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty + 4, // 30: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse + 4, // 31: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse + 6, // 32: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse + 12, // 33: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse + 27, // 34: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty + 12, // 35: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse + 12, // 36: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse + 17, // 37: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse + 18, // 38: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse + 28, // [28:39] is the sub-list for method output_type + 17, // [17:28] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_routes_proto_init() } @@ -2111,7 +1791,7 @@ func file_routes_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_routes_proto_rawDesc, NumEnums: 0, - NumMessages: 25, + NumMessages: 27, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index d33d74c3..b8ffed07 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -108,7 +108,6 @@ node itself, for all values of type Entry. */ type NodeInfo struct { Id Entry - Cid Entry Comment Entry ClusterName Entry ContainerName Entry @@ -122,7 +121,6 @@ type NodeInfo struct { Kernel *KernelEntry Ipmi *IpmiEntry Profiles []string - GroupProfiles []string NetDevs map[string]*NetDevEntry Tags map[string]*Entry } @@ -140,7 +138,6 @@ type IpmiEntry struct { } type KernelEntry struct { - Version Entry Override Entry Args Entry } @@ -160,6 +157,9 @@ type NetDevEntry struct { Tags map[string]*Entry } +// string which is printed if no value is set +const NoValue = "--" + func init() { // Check that nodes.conf is found if !util.IsFile(ConfigFile) { diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index d3df4270..b84d8182 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -580,3 +580,20 @@ func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []st } return optionsMap } + +/* +Helper function which gets the lopt of a given interface +*/ +func GetLoptOf(myStruct interface{}, name string) string { + retStr := "" + if reflect.TypeOf(myStruct).Kind() != reflect.Struct { + return retStr + } + myType := reflect.TypeOf(myStruct) + field, ok := myType.FieldByName(name) + if ok { + retStr = field.Tag.Get("lopt") + } + return retStr + +} From 99e9316011406c7a03243e6af302d74ac5e8ac92 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 19 Jul 2022 17:36:49 +0200 Subject: [PATCH 18/38] restore old node list --- internal/app/wwctl/node/list/main.go | 229 +++++++++++++++------------ internal/pkg/api/node/methods.go | 6 +- internal/pkg/node/methods.go | 19 +++ 3 files changed, 154 insertions(+), 100 deletions(-) diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 60cccffc..52dd0b30 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -2,8 +2,11 @@ package list import ( "fmt" + "sort" + "strings" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" + "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) @@ -15,7 +18,10 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) return } - + nodeLopt := node.GetloptMap(node.NodeConf{}) + ipmiLopt := node.GetloptMap(node.IpmiConf{}) + kernelLopt := node.GetloptMap(node.KernelConf{}) + netdevLopt := node.GetloptMap(node.NetDevs{}) if ShowAll { for i := 0; i < len(nodeInfo); i++ { ni := nodeInfo[i] @@ -23,110 +29,139 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if _, ok := ni.Fields["Id"]; ok { nodeName = ni.Fields["Id"].Print } - + var nodeconfkeys, ipmiconfkeys, kernelconfkeys, netdevkys []string + for k := range ni.Fields { + subkeys := strings.Split(k, ":") + if len(subkeys) == 1 { + nodeconfkeys = append(nodeconfkeys, k) + } + if len(subkeys) >= 2 { + switch subkeys[0] { + case "IpmiEntry": + ipmiconfkeys = append(ipmiconfkeys, k) + case "KernelEntry": + kernelconfkeys = append(kernelconfkeys, k) + case "NetDevEntry": + netdevkys = append(netdevkys, k) + } + } + } + sort.Strings(nodeconfkeys) + sort.Strings(ipmiconfkeys) + sort.Strings(kernelconfkeys) + sort.Strings(netdevkys) + keyssorted := append(nodeconfkeys, kernelconfkeys...) + keyssorted = append(keyssorted, ipmiconfkeys...) + keyssorted = append(keyssorted, netdevkys...) fmt.Printf("################################################################################\n") fmt.Printf("%-20s %-18s %-12s %s\n", "NODE", "FIELD", "PROFILE", "VALUE") - for key, val := range ni.Fields { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, key, val.Source, val.Print) + for _, keys := range keyssorted { + fieldName := keys + subkeys := strings.Split(keys, ":") + if len(subkeys) == 1 { + if subkeys[0] == "Id" { + continue + } + fieldName = nodeLopt[subkeys[0]] + } + if len(subkeys) >= 2 { + switch subkeys[0] { + case "IpmiEntry": + fieldName = ipmiLopt[subkeys[1]] + case "KernelEntry": + fieldName = kernelLopt[subkeys[1]] + case "NetDevEntry": + if len(subkeys) == 3 { + fieldName = subkeys[1] + ":" + netdevLopt[subkeys[2]] + } else if len(subkeys) == 4 { + fieldName = subkeys[1] + ":keys:" + subkeys[3] + } + } + } + fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, fieldName, ni.Fields[keys].Source, ni.Fields[keys].Print) } - /* - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Comment", ni.Comment.Source, ni.Comment.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Cluster", ni.Cluster.Source, ni.Cluster.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Profiles", "--", strings.Join(ni.Profiles, ",'")) + } + } else if ShowNet { + fmt.Printf("%-22s %-8s %-18s %-15s %-15s %-15s\n", "NODE NAME", "NAME", "HWADDR", "IPADDR", "GATEWAY", "DEVICE") + fmt.Println(strings.Repeat("=", 90)) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Discoverable", ni.Discoverable.Source, ni.Discoverable.Print) + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := `UNKNOWN` + if _, ok := ni.Fields["Id"]; ok { + nodeName = ni.Fields["Id"].Print + } + netNames := make(map[string]bool) + for k := range ni.Fields { + subkeys := strings.Split(k, ":") + if len(subkeys) == 3 && subkeys[0] == "NetDevEntry" { + netNames[subkeys[1]] = true + } + } + if len(netNames) > 0 { + for name := range netNames { + fmt.Printf("%-22s %-8s %-18s %-15s %-15s %-15s\n", nodeName, name, + ni.Fields["NetDevEntry:"+name+":Hwaddr"].Print, + ni.Fields["NetDevEntry:"+name+":Ipaddr"].Print, + ni.Fields["NetDevEntry:"+name+":Gateway"].Print, + ni.Fields["NetDevEntry:"+name+":Device"].Print) + } + } else { + fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, "--", "--", "--", "--") + } + } + } else if ShowIpmi { + fmt.Printf("%-22s %-16s %-10s %-20s %-14s\n", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI INTERFACE") + fmt.Println(strings.Repeat("=", 98)) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Container", ni.Container.Source, ni.Container.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelOverride", ni.KernelOverride.Source, ni.KernelOverride.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "KernelArgs", ni.KernelArgs.Source, ni.KernelArgs.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "SystemOverlay", ni.SystemOverlay.Source, ni.SystemOverlay.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "RuntimeOverlay", ni.RuntimeOverlay.Source, ni.RuntimeOverlay.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Ipxe", ni.Ipxe.Source, ni.Ipxe.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Init", ni.Init.Source, ni.Init.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Root", ni.Root.Source, ni.Root.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "AssetKey", ni.AssetKey.Source, ni.AssetKey.Print) + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := `UNKNOWN` + if _, ok := ni.Fields["Id"]; ok { + nodeName = ni.Fields["Id"].Print + } + fmt.Printf("%-22s %-16s %-10s %-20s %-14s\n", nodeName, + ni.Fields["IpmiEntry:Ipaddr"].Print, + ni.Fields["IpmiEntry:Port"].Print, + ni.Fields["IpmiEntry:UserName"].Print, + ni.Fields["IpmiEntry:Interface"].Print) + } - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiIpaddr", ni.IpmiIpaddr.Source, ni.IpmiIpaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiNetmask", ni.IpmiNetmask.Source, ni.IpmiNetmask.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiPort", ni.IpmiPort.Source, ni.IpmiPort.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiGateway", ni.IpmiGateway.Source, ni.IpmiGateway.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiUserName", ni.IpmiUserName.Source, ni.IpmiUserName.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "IpmiInterface", ni.IpmiInterface.Source, ni.IpmiInterface.Print) + } else if ShowLong { + fmt.Printf("%-22s %-16s %-16s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") + fmt.Println(strings.Repeat("=", 85)) - for keyname, key := range ni.Tags { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, "Tag["+keyname+"]", key.Source, key.Print) - } + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := `UNKNOWN` + if _, ok := ni.Fields["Id"]; ok { + nodeName = ni.Fields["Id"].Print + } + fmt.Printf("%-22s %-16s %-16s %s\n", nodeName, + ni.Fields["KernelEntry:Override"].Print, + ni.Fields["ContainerName"].Print, + ni.Fields["SystemOverlay"].Print+"/"+ni.Fields["RuntimeOverlay"].Print) + } - for name, netdev := range ni.NetDevs { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEVICE", netdev.Device.Source, netdev.Device.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":HWADDR", netdev.Hwaddr.Source, netdev.Hwaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":IPADDR", netdev.Ipaddr.Source, netdev.Ipaddr.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":NETMASK", netdev.Netmask.Source, netdev.Netmask.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":GATEWAY", netdev.Gateway.Source, netdev.Gateway.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TYPE", netdev.Type.Source, netdev.Type.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":ONBOOT", netdev.Onboot.Source, netdev.Onboot.Print) - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":DEFAULT", netdev.Primary.Source, netdev.Primary.Print) - for keyname, key := range netdev.Tags { - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, name+":TAG["+keyname+"]", key.Source, key.Print) - } - } - } - } else if ShowNet { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", "NODE NAME", "DEVICE", "HWADDR", "IPADDR", "GATEWAY") - fmt.Println(strings.Repeat("=", 80)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value - - if len(ni.NetDevs) > 0 { - for name, dev := range ni.NetDevs { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, name, dev.Hwaddr.Print, dev.Ipaddr.Print, dev.Gateway.Print) - } - } else { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, "--", "--", "--", "--") - } - } - } else if ShowIpmi { - fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI PASSWORD", "IPMI INTERFACE") - fmt.Println(strings.Repeat("=", 108)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value - - fmt.Printf("%-22s %-16s %-10s %-20s %-20s %-14s\n", nodeName, ni.IpmiIpaddr.Print, ni.IpmiPort.Print, ni.IpmiUserName.Print, ni.IpmiPassword.Print, ni.IpmiInterface.Print) - } - - } else if ShowLong { - fmt.Printf("%-22s %-26s %-35s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") - fmt.Println(strings.Repeat("=", 120)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value - - fmt.Printf("%-22s %-26s %-35s %s\n", nodeName, ni.KernelOverride.Print, ni.Container.Print, ni.SystemOverlay.Print+"/"+ni.RuntimeOverlay.Print) - } - - } else { - fmt.Printf("%-22s %-26s %s\n", "NODE NAME", "PROFILES", "NETWORK") - fmt.Println(strings.Repeat("=", 80)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := ni.Id.Value - - var netdevs []string - if len(ni.NetDevs) > 0 { - for name, dev := range ni.NetDevs { - netdevs = append(netdevs, fmt.Sprintf("%s:%s", name, dev.Ipaddr.Print)) - } - } - sort.Strings(netdevs) - fmt.Printf("%-22s %-26s %s\n", nodeName, strings.Join(ni.Profiles, ","), strings.Join(netdevs, ", ")) - } - */ + } else { + fmt.Printf("%-22s %-26s %s\n", "NODE NAME", "PROFILES", "NETWORK") + fmt.Println(strings.Repeat("=", 80)) + for i := 0; i < len(nodeInfo); i++ { + ni := nodeInfo[i] + nodeName := `UNKNOWN` + if _, ok := ni.Fields["Id"]; ok { + nodeName = ni.Fields["Id"].Print + } + netNameMap := make(map[string]bool) + var netNames []string + for k := range ni.Fields { + subkeys := strings.Split(k, ":") + if len(subkeys) == 3 && subkeys[0] == "NetDevEntry" && !netNameMap[subkeys[1]] { + netNameMap[subkeys[1]] = true + netNames = append(netNames, subkeys[1]) + } + } + fmt.Printf("%-22s %-26s %s\n", nodeName, ni.Fields["Profiles"].Print, strings.Join(netNames, ", ")) } } return diff --git a/internal/pkg/api/node/methods.go b/internal/pkg/api/node/methods.go index dc561238..57428170 100644 --- a/internal/pkg/api/node/methods.go +++ b/internal/pkg/api/node/methods.go @@ -46,13 +46,13 @@ func GetFields(n interface{}) map[string]*wwapiv1.NodeField { entry := nodeVal.Field(i).Elem().Interface().(node.KernelEntry) kernelMap := GetFields(entry) for key, val := range kernelMap { - fieldMap["kernel:"+key] = val + fieldMap["KernelEntry:"+key] = val } case reflect.TypeOf((*node.IpmiEntry)(nil)): entry := nodeVal.Field(i).Elem().Interface().(node.IpmiEntry) kernelMap := GetFields(entry) for key, val := range kernelMap { - fieldMap["ipmi:"+key] = val + fieldMap["IpmiEntry:"+key] = val } case reflect.TypeOf(map[string]*node.Entry(nil)): keyMap := nodeVal.Field(i).Interface().(map[string]*node.Entry) @@ -68,7 +68,7 @@ func GetFields(n interface{}) map[string]*wwapiv1.NodeField { for net, netdev := range netMap { netMapEntr := GetFields(*netdev) for key, val := range netMapEntr { - fieldMap[net+":"+key] = val + fieldMap["NetDevEntry:"+net+":"+key] = val } } default: diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index b84d8182..cf805546 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -597,3 +597,22 @@ func GetLoptOf(myStruct interface{}, name string) string { return retStr } + +/* +Returns a translation map of field name and its associated lopt. +*/ +func GetloptMap(myStruct interface{}) map[string]string { + retMap := make(map[string]string) + if reflect.TypeOf(myStruct).Kind() != reflect.Struct { + return retMap + } + structType := reflect.TypeOf(myStruct) + for i := 0; i < structType.NumField(); i++ { + retMap[structType.Field(i).Name] = structType.Field(i).Name + lopt := structType.Field(i).Tag.Get("lopt") + if lopt != "" { + retMap[structType.Field(i).Name] = lopt + } + } + return retMap +} From d252b974bfea8c2d645e50489364537afa163f24 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 20 Jul 2022 15:14:30 +0200 Subject: [PATCH 19/38] Fix Nodeadd with ipaddr count --- internal/app/wwctl/node/add/main.go | 4 +-- internal/app/wwctl/profile/add/main.go | 4 +-- internal/app/wwctl/profile/set/main.go | 4 +-- internal/pkg/api/node/node.go | 44 ++++---------------------- internal/pkg/api/node/utils.go | 36 +++++++++++++++++++++ 5 files changed, 49 insertions(+), 43 deletions(-) diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 571783e3..2b63ad94 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -9,8 +9,8 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) - if !haveNetname { + OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + if netWithoutName { return errors.New("a netname must be given for any network related configuration") } realMap := make(map[string]string) diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index fb502fd3..6871520b 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -13,8 +13,8 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) - if !haveNetname { + OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + if netWithoutName { return errors.New("a netname must be given for any network related configuration") } realMap := make(map[string]string) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index e206c13f..b177a6b5 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -12,8 +12,8 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) - if !haveNetname { + OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + if netWithoutName { return errors.New("a netname must be given for any network related configuration") } realMap := make(map[string]string) diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index 5e7e902a..14263082 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "os" - "strings" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/node" @@ -25,7 +24,6 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { return fmt.Errorf("NodeAddParameter is nil") } - var count uint nodeDB, err := node.New() if err != nil { return errors.Wrap(err, "failed to open node database") @@ -40,19 +38,20 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { return errors.Wrap(err, "failed to add node") } wwlog.Printf(wwlog.INFO, "Added node: %s\n", a) - if nap.OptionsStrMap["ipaddr"] != "" { + netName := nap.OptionsStrMap["NetDevs"] + if nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"] != "" { // if more nodes are added increment IPv4 address - nap.OptionsStrMap["ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["ipaddr"], count) + nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"], 1) wwlog.Verbose("Node: %s:%s, Setting Ipaddr to: %s\n", - n.Id.Get(), nap.OptionsStrMap["netname"], nap.OptionsStrMap["ipaddr"]) + n.Id.Get(), nap.OptionsStrMap["NetDevs"], nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"]) } - if nap.OptionsStrMap["ipmiaddr"] != "" { + if nap.OptionsStrMap["Ipmi.Ipaddr"] != "" { // if more nodes are added increment IPv4 address - nap.OptionsStrMap["ipmiaddr"] = util.IncrementIPv4(nap.OptionsStrMap["ipmiaddr"], count) + nap.OptionsStrMap["Ipmi.Ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["Ipmi.Ipaddr"], 1) wwlog.Verbose("Node: %s:, Setting IPMIIpaddr to: %s\n", - n.Id.Get(), nap.OptionsStrMap["ipmiaddr"]) + n.Id.Get(), nap.OptionsStrMap["Ipmi.Ipaddr"]) } // Now set all the rest for key, val := range nap.OptionsStrMap { @@ -67,7 +66,6 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { return errors.Wrap(err, "failed to update nodedb") } - count++ } err = nodeDB.Persist() @@ -372,31 +370,3 @@ func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusRespo } return } - -/* -Add the netname to the options map, as its only known after the map -command line options have been read out. -*/ -func AddNetname(theMap map[string]*string) (map[string]*string, bool) { - foundNetname := false - netname := "" - retMap := make(map[string]*string) - for key, val := range theMap { - if key == "NetDevs" { - foundNetname = true - netname = *val - } - } - if foundNetname { - for key, val := range theMap { - keys := strings.Split(key, ".") - myVal := *val - if len(keys) >= 2 && keys[0] == "NetDevs" { - retMap[keys[0]+"."+netname+"."+strings.Join(keys[1:], ".")] = &myVal - } else { - retMap[key] = &myVal - } - } - } - return retMap, foundNetname -} diff --git a/internal/pkg/api/node/utils.go b/internal/pkg/api/node/utils.go index e2643f77..cf46d4bb 100644 --- a/internal/pkg/api/node/utils.go +++ b/internal/pkg/api/node/utils.go @@ -1,6 +1,8 @@ package apinode import ( + "strings" + "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/warewulfd" "github.com/pkg/errors" @@ -23,3 +25,37 @@ func DbSave(nodeDB *node.NodeYaml) (err error) { } return } + +/* +Add the netname to the options map, as its only known after the +command line options have been read out, but its needing for setting +the values. Returns the manipulated map and a bool which is true if +networks specific values were set, but no netname was given. +*/ +func AddNetname(theMap map[string]*string) (map[string]*string, bool) { + netname := "" + netvalues := false + retMap := make(map[string]*string) + for key, val := range theMap { + if key == "NetDevs" && *val != "" { + netname = *val + } + } + for key, val := range theMap { + keys := strings.Split(key, ".") + myVal := *val + if len(keys) >= 2 && keys[0] == "NetDevs" { + if *val != "" { + netvalues = true + } + if netname != "" { + retMap[keys[0]+"."+netname+"."+strings.Join(keys[1:], ".")] = &myVal + } + } else { + retMap[key] = &myVal + } + + } + + return retMap, netvalues && netname == "" +} From 925a5a215539461d5d47eb6ab26177037e704fc2 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 26 Jul 2022 10:48:16 +0200 Subject: [PATCH 20/38] Fix node set --- internal/app/wwctl/node/set/main.go | 4 ++-- internal/pkg/node/methods.go | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 877c9c57..83187b24 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -11,8 +11,8 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, haveNetname := apinode.AddNetname(OptionStrMap) - if !haveNetname { + OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + if netWithoutName { return errors.New("a netname must be given for any network related configuration") } realMap := make(map[string]string) diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index cf805546..7627465f 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -307,9 +307,9 @@ func (ent *Entry) Defined() bool { Set the Entry trough an interface by trying to cast the interface */ func SetEntry(entryPtr interface{}, val interface{}) { + valKind := reflect.TypeOf(val) if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) { entry := entryPtr.(*Entry) - valKind := reflect.TypeOf(val) if valKind.Kind() == reflect.String { entry.Set(val.(string)) } else if valKind.Kind() == reflect.Slice { @@ -319,6 +319,18 @@ func SetEntry(entryPtr interface{}, val interface{}) { panic("Got unknown slice type") } } + } else if reflect.TypeOf(entryPtr) == reflect.TypeOf((*[]string)(nil)) { + entry := entryPtr.(*[]string) + if valKind.Kind() == reflect.String { + // most likely we got a comma seperated string slice + *entry = strings.Split(val.(string), ",") + } else if valKind.Kind() == reflect.Slice { + if valKind.Elem().Kind() == reflect.String { + *entry = val.([]string) + } else { + panic("Got unknown slice type") + } + } } else { panic(fmt.Sprintf("Can't convert %s to *node.Entry to call Set\n", reflect.TypeOf(entryPtr))) } @@ -370,7 +382,7 @@ func DelEntry(entryMapInt interface{}, val interface{}) { } /* -Call SetEntry for given field (NodeInfo) +Call SetEntry for given field (NodeInfo). */ func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) @@ -378,6 +390,8 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { //fmt.Println(reflect.TypeOf(field.Addr().Interface())) SetEntry(field.Addr().Interface(), val) + } else if field.Addr().Type() == reflect.TypeOf((*[]string)(nil)) { + SetEntry(field.Addr().Interface(), val) } /* else if field.Addr().Kind() == reflect.Map { From b548d8583d5ecc9777be22e645f572a441d376a4 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 29 Jul 2022 14:55:51 +0200 Subject: [PATCH 21/38] reflection on constructor --- internal/pkg/node/constructors.go | 270 ++++++++++++++++---------- internal/pkg/node/datastructure.go | 2 +- internal/pkg/node/modifiers.go | 4 +- internal/pkg/overlay/datastructure.go | 2 +- 4 files changed, 174 insertions(+), 104 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 5002a32a..fb3d17ce 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -4,13 +4,12 @@ import ( "errors" "fmt" "io/ioutil" - "net" "path" + "reflect" "sort" "strings" "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" "gopkg.in/yaml.v2" @@ -51,10 +50,12 @@ for every node */ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { var ret []NodeInfo - wwconfig, err := warewulfconf.New() - if err != nil { - return ret, err - } + /* + wwconfig, err := warewulfconf.New() + if err != nil { + return ret, err + } + */ wwlog.Printf(wwlog.DEBUG, "Finding all nodes...\n") for nodename, node := range config.Nodes { var n NodeInfo @@ -75,29 +76,98 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { if len(fullname) > 1 { n.ClusterName.SetDefault(fullname[1]) } - + // special handling for profile to get the default one if len(node.Profiles) == 0 { n.Profiles = []string{"default"} } else { n.Profiles = node.Profiles } - + // node explciti nodename field in NodeConf n.Id.Set(nodename) - n.Comment.Set(node.Comment) - n.ContainerName.Set(node.ContainerName) - n.ClusterName.Set(node.ClusterName) - n.Ipxe.Set(node.Ipxe) - n.Init.Set(node.Init) - // backward compatibility for old Ipmi config - n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) - n.Ipmi.Netmask.Set(node.IpmiNetmask) - n.Ipmi.Port.Set(node.IpmiPort) - n.Ipmi.Gateway.Set(node.IpmiGateway) - n.Ipmi.UserName.Set(node.IpmiUserName) - n.Ipmi.Password.Set(node.IpmiPassword) - n.Ipmi.Interface.Set(node.IpmiInterface) - n.Ipmi.Write.Set(node.IpmiWrite) - // delete deprectated structures so that they do not get unmarshalled + /* + n.Comment.Set(node.Comment) + n.ContainerName.Set(node.ContainerName) + n.ClusterName.Set(node.ClusterName) + n.Ipxe.Set(node.Ipxe) + n.Init.Set(node.Init) + // backward compatibility for old Ipmi config + n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) + n.Ipmi.Netmask.Set(node.IpmiNetmask) + n.Ipmi.Port.Set(node.IpmiPort) + n.Ipmi.Gateway.Set(node.IpmiGateway) + n.Ipmi.UserName.Set(node.IpmiUserName) + n.Ipmi.Password.Set(node.IpmiPassword) + n.Ipmi.Interface.Set(node.IpmiInterface) + n.Ipmi.Write.Set(node.IpmiWrite) + */ + nodeInfoType := reflect.TypeOf(&n) + nodeInfoVal := reflect.ValueOf(&n) + nodeConfVal := reflect.ValueOf(node) + // now iterate of every field + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + fmt.Println("Found map") + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.Set(val) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { + nestedMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range nestedMap { + netValsType := reflect.ValueOf(netVals) + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + // This should be done a bit down, but didn'tknow how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) + if netInfoType.Field(j).Name == "Netmask" { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") + } + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.Set(val) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } + } + } + } + } + // delete deprecated structures so that they do not get unmarshalled node.IpmiIpaddr = "" node.IpmiNetmask = "" node.IpmiGateway = "" @@ -105,22 +175,23 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.IpmiPassword = "" node.IpmiInterface = "" node.IpmiWrite = "" - - if node.Ipmi != nil { - n.Ipmi.Ipaddr.Set(node.Ipmi.Ipaddr) - n.Ipmi.Netmask.Set(node.Ipmi.Netmask) - n.Ipmi.Port.Set(node.Ipmi.Port) - n.Ipmi.Gateway.Set(node.Ipmi.Gateway) - n.Ipmi.UserName.Set(node.Ipmi.UserName) - n.Ipmi.Password.Set(node.Ipmi.Password) - n.Ipmi.Interface.Set(node.Ipmi.Interface) - n.Ipmi.Write.SetB(node.Ipmi.Write) - } - n.SystemOverlay.SetSlice(node.SystemOverlay) - n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) - n.Root.Set(node.Root) - n.AssetKey.Set(node.AssetKey) - n.Discoverable.Set(node.Discoverable) + /* + if node.Ipmi != nil { + n.Ipmi.Ipaddr.Set(node.Ipmi.Ipaddr) + n.Ipmi.Netmask.Set(node.Ipmi.Netmask) + n.Ipmi.Port.Set(node.Ipmi.Port) + n.Ipmi.Gateway.Set(node.Ipmi.Gateway) + n.Ipmi.UserName.Set(node.Ipmi.UserName) + n.Ipmi.Password.Set(node.Ipmi.Password) + n.Ipmi.Interface.Set(node.Ipmi.Interface) + n.Ipmi.Write.SetB(node.Ipmi.Write) + } + n.SystemOverlay.SetSlice(node.SystemOverlay) + n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) + n.Root.Set(node.Root) + n.AssetKey.Set(node.AssetKey) + n.Discoverable.Set(node.Discoverable) + */ // backward compatibility n.Kernel.Args.Set(node.KernelArgs) n.Kernel.Override.Set(node.KernelOverride) @@ -128,68 +199,67 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.KernelArgs = "" node.KernelOverride = "" node.KernelVersion = "" - - if node.Kernel != nil { - n.Kernel.Args.Set(node.Kernel.Args) - if node.Kernel.Override != "" { - n.Kernel.Override.Set(node.Kernel.Override) - } else if node.Kernel.Version != "" { - n.Kernel.Override.Set(node.Kernel.Version) - } - } - - for devname, netdev := range node.NetDevs { - if _, ok := n.NetDevs[devname]; !ok { - var netdev NetDevEntry - n.NetDevs[devname] = &netdev - } - n.NetDevs[devname].Device.Set(netdev.Device) - n.NetDevs[devname].Ipaddr.Set(netdev.Ipaddr) - n.NetDevs[devname].Ipaddr6.Set(netdev.Ipaddr6) - - // Derive value of ipv6 address from ipv4 if not explicitly set - if wwconfig.Ipaddr6 != "" && netdev.Ipaddr != "" { - ipv4Arr := strings.Split(netdev.Ipaddr, ".") - // error can be ignored as check was done at init - _, ipv6Net, _ := net.ParseCIDR(wwconfig.Ipaddr6) - mSize, _ := ipv6Net.Mask.Size() - ipv6str := fmt.Sprintf("%s%s:%s:%s:%s/%v", - ipv6Net.IP.String(), ipv4Arr[0], ipv4Arr[1], ipv4Arr[2], ipv4Arr[3], mSize) - if strings.Count(ipv6Net.IP.String(), ":") == 5 { - ipv6str = strings.Replace(ipv6str, "::", ":", -1) + /* + if node.Kernel != nil { + n.Kernel.Args.Set(node.Kernel.Args) + if node.Kernel.Override != "" { + n.Kernel.Override.Set(node.Kernel.Override) + } else if node.Kernel.Version != "" { + n.Kernel.Override.Set(node.Kernel.Version) + } } - n.NetDevs[devname].Ipaddr6.SetDefault(ipv6str) - } - n.NetDevs[devname].Netmask.Set(netdev.Netmask) - n.NetDevs[devname].Netmask.SetDefault("255.255.255.0") - n.NetDevs[devname].Hwaddr.Set(strings.ToLower(netdev.Hwaddr)) - n.NetDevs[devname].Gateway.Set(netdev.Gateway) - n.NetDevs[devname].Type.Set(netdev.Type) - n.NetDevs[devname].OnBoot.Set(netdev.OnBoot) - n.NetDevs[devname].Primary.Set(netdev.Primary) - n.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility - // for just one netdev, it is always the primary - if len(node.NetDevs) == 1 { - n.NetDevs[devname].Primary.Set("true") - } - n.NetDevs[devname].Tags = make(map[string]*Entry) - for keyname, key := range netdev.Tags { - if _, ok := n.Tags[keyname]; !ok { - var keyVar Entry - n.NetDevs[devname].Tags[keyname] = &keyVar + for devname, netdev := range node.NetDevs { + if _, ok := n.NetDevs[devname]; !ok { + var netdev NetDevEntry + n.NetDevs[devname] = &netdev } - n.NetDevs[devname].Tags[keyname].Set(key) - } - n.NetDevs[devname].Tags = make(map[string]*Entry) - for keyname, key := range netdev.Tags { - if _, ok := n.Tags[keyname]; !ok { - var keyVar Entry - n.NetDevs[devname].Tags[keyname] = &keyVar - } - n.NetDevs[devname].Tags[keyname].Set(key) - } - } + n.NetDevs[devname].Device.Set(netdev.Device) + n.NetDevs[devname].Ipaddr.Set(netdev.Ipaddr) + n.NetDevs[devname].Ipaddr6.Set(netdev.Ipaddr6) + // Derive value of ipv6 address from ipv4 if not explicitly set + if wwconfig.Ipaddr6 != "" && netdev.Ipaddr != "" { + ipv4Arr := strings.Split(netdev.Ipaddr, ".") + // error can be ignored as check was done at init + _, ipv6Net, _ := net.ParseCIDR(wwconfig.Ipaddr6) + mSize, _ := ipv6Net.Mask.Size() + ipv6str := fmt.Sprintf("%s%s:%s:%s:%s/%v", + ipv6Net.IP.String(), ipv4Arr[0], ipv4Arr[1], ipv4Arr[2], ipv4Arr[3], mSize) + if strings.Count(ipv6Net.IP.String(), ":") == 5 { + ipv6str = strings.Replace(ipv6str, "::", ":", -1) + } + n.NetDevs[devname].Ipaddr6.SetDefault(ipv6str) + } + n.NetDevs[devname].Netmask.Set(netdev.Netmask) + n.NetDevs[devname].Netmask.SetDefault("255.255.255.0") + n.NetDevs[devname].Hwaddr.Set(strings.ToLower(netdev.Hwaddr)) + n.NetDevs[devname].Gateway.Set(netdev.Gateway) + n.NetDevs[devname].Type.Set(netdev.Type) + n.NetDevs[devname].OnBoot.Set(netdev.OnBoot) + n.NetDevs[devname].Primary.Set(netdev.Primary) + n.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility + // for just one netdev, it is always the primary + if len(node.NetDevs) == 1 { + n.NetDevs[devname].Primary.Set("true") + } + n.NetDevs[devname].Tags = make(map[string]*Entry) + for keyname, key := range netdev.Tags { + if _, ok := n.Tags[keyname]; !ok { + var keyVar Entry + n.NetDevs[devname].Tags[keyname] = &keyVar + } + n.NetDevs[devname].Tags[keyname].Set(key) + } + n.NetDevs[devname].Tags = make(map[string]*Entry) + for keyname, key := range netdev.Tags { + if _, ok := n.Tags[keyname]; !ok { + var keyVar Entry + n.NetDevs[devname].Tags[keyname] = &keyVar + } + n.NetDevs[devname].Tags[keyname].Set(key) + } + } + */ // Merge Keys into Tags for backwards compatibility if len(node.Tags) == 0 { node.Tags = make(map[string]string) @@ -231,7 +301,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Ipmi.UserName.SetAlt(config.NodeProfiles[p].Ipmi.UserName, p) n.Ipmi.Password.SetAlt(config.NodeProfiles[p].Ipmi.Password, p) n.Ipmi.Interface.SetAlt(config.NodeProfiles[p].Ipmi.Interface, p) - n.Ipmi.Write.SetAltB(config.NodeProfiles[p].Ipmi.Write, p) + n.Ipmi.Write.SetAlt(config.NodeProfiles[p].Ipmi.Write, p) } n.SystemOverlay.SetAltSlice(config.NodeProfiles[p].SystemOverlay, p) n.RuntimeOverlay.SetAltSlice(config.NodeProfiles[p].RuntimeOverlay, p) @@ -369,7 +439,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.Ipmi.UserName.Set(profile.Ipmi.UserName) p.Ipmi.Password.Set(profile.Ipmi.Password) p.Ipmi.Interface.Set(profile.Ipmi.Interface) - p.Ipmi.Write.SetB(profile.Ipmi.Write) + p.Ipmi.Write.Set(profile.Ipmi.Write) } p.RuntimeOverlay.SetSlice(profile.RuntimeOverlay) p.SystemOverlay.SetSlice(profile.SystemOverlay) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index b8ffed07..8521122a 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -60,7 +60,7 @@ type IpmiConf struct { Port string `yaml:"port,omitempty" lopt:"ipmiport" comment:"Set the IPMI port"` Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` - Write bool `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` + Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` Tags map[string]string `yaml:"tags,omitempty" lopt:"impitag" comment:"ipmi keys"` } type KernelConf struct { diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 44c3b10c..4d094dc6 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -79,7 +79,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error { config.Nodes[nodeID].Ipmi.UserName = node.Ipmi.UserName.GetReal() config.Nodes[nodeID].Ipmi.Password = node.Ipmi.Password.GetReal() config.Nodes[nodeID].Ipmi.Interface = node.Ipmi.Interface.GetReal() - config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.GetB() + config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.Get() } config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetRealSlice() config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetRealSlice() @@ -185,7 +185,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { config.NodeProfiles[profileID].Ipmi.UserName = profile.Ipmi.UserName.GetReal() config.NodeProfiles[profileID].Ipmi.Password = profile.Ipmi.Password.GetReal() config.NodeProfiles[profileID].Ipmi.Interface = profile.Ipmi.Interface.GetReal() - config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.GetB() + config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.Get() } config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetRealSlice() config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetRealSlice() diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 8d5dd534..4a0575af 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -86,7 +86,7 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get() tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get() tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get() - tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.GetB() + tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get() tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print() tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print() tstruct.NetDevs = make(map[string]*node.NetDevs) From 96731a4b87570cefe1f1d4f5195af4c4acc1a86f Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 3 Aug 2022 11:32:40 +0200 Subject: [PATCH 22/38] node list imporvement --- internal/app/wwctl/node/list/main.go | 4 ++ internal/pkg/node/constructors.go | 98 +--------------------------- 2 files changed, 5 insertions(+), 97 deletions(-) diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 52dd0b30..16a9cc07 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -43,6 +43,8 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { kernelconfkeys = append(kernelconfkeys, k) case "NetDevEntry": netdevkys = append(netdevkys, k) + case "key": + nodeconfkeys = append(nodeconfkeys, k) } } } @@ -66,6 +68,8 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { } if len(subkeys) >= 2 { switch subkeys[0] { + case "key": + fieldName = "key:" + subkeys[1] case "IpmiEntry": fieldName = ipmiLopt[subkeys[1]] case "KernelEntry": diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index fb3d17ce..e3bc7fa8 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -2,7 +2,6 @@ package node import ( "errors" - "fmt" "io/ioutil" "path" "reflect" @@ -84,22 +83,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // node explciti nodename field in NodeConf n.Id.Set(nodename) - /* - n.Comment.Set(node.Comment) - n.ContainerName.Set(node.ContainerName) - n.ClusterName.Set(node.ClusterName) - n.Ipxe.Set(node.Ipxe) - n.Init.Set(node.Init) - // backward compatibility for old Ipmi config - n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) - n.Ipmi.Netmask.Set(node.IpmiNetmask) - n.Ipmi.Port.Set(node.IpmiPort) - n.Ipmi.Gateway.Set(node.IpmiGateway) - n.Ipmi.UserName.Set(node.IpmiUserName) - n.Ipmi.Password.Set(node.IpmiPassword) - n.Ipmi.Interface.Set(node.IpmiInterface) - n.Ipmi.Write.Set(node.IpmiWrite) - */ nodeInfoType := reflect.TypeOf(&n) nodeInfoVal := reflect.ValueOf(&n) nodeConfVal := reflect.ValueOf(node) @@ -107,7 +90,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { for i := 0; i < nodeInfoType.Elem().NumField(); i++ { valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) if valField.IsValid() { - // found field with same name + // found field with same name for Conf and Info if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { if valField.Type().Kind() == reflect.String { (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) @@ -127,7 +110,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } } } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { - fmt.Println("Found map") confMap := valField.Interface().(map[string]string) for key, val := range confMap { var entr Entry @@ -175,23 +157,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.IpmiPassword = "" node.IpmiInterface = "" node.IpmiWrite = "" - /* - if node.Ipmi != nil { - n.Ipmi.Ipaddr.Set(node.Ipmi.Ipaddr) - n.Ipmi.Netmask.Set(node.Ipmi.Netmask) - n.Ipmi.Port.Set(node.Ipmi.Port) - n.Ipmi.Gateway.Set(node.Ipmi.Gateway) - n.Ipmi.UserName.Set(node.Ipmi.UserName) - n.Ipmi.Password.Set(node.Ipmi.Password) - n.Ipmi.Interface.Set(node.Ipmi.Interface) - n.Ipmi.Write.SetB(node.Ipmi.Write) - } - n.SystemOverlay.SetSlice(node.SystemOverlay) - n.RuntimeOverlay.SetSlice(node.RuntimeOverlay) - n.Root.Set(node.Root) - n.AssetKey.Set(node.AssetKey) - n.Discoverable.Set(node.Discoverable) - */ // backward compatibility n.Kernel.Args.Set(node.KernelArgs) n.Kernel.Override.Set(node.KernelOverride) @@ -199,67 +164,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.KernelArgs = "" node.KernelOverride = "" node.KernelVersion = "" - /* - if node.Kernel != nil { - n.Kernel.Args.Set(node.Kernel.Args) - if node.Kernel.Override != "" { - n.Kernel.Override.Set(node.Kernel.Override) - } else if node.Kernel.Version != "" { - n.Kernel.Override.Set(node.Kernel.Version) - } - } - for devname, netdev := range node.NetDevs { - if _, ok := n.NetDevs[devname]; !ok { - var netdev NetDevEntry - n.NetDevs[devname] = &netdev - } - n.NetDevs[devname].Device.Set(netdev.Device) - n.NetDevs[devname].Ipaddr.Set(netdev.Ipaddr) - n.NetDevs[devname].Ipaddr6.Set(netdev.Ipaddr6) - - // Derive value of ipv6 address from ipv4 if not explicitly set - if wwconfig.Ipaddr6 != "" && netdev.Ipaddr != "" { - ipv4Arr := strings.Split(netdev.Ipaddr, ".") - // error can be ignored as check was done at init - _, ipv6Net, _ := net.ParseCIDR(wwconfig.Ipaddr6) - mSize, _ := ipv6Net.Mask.Size() - ipv6str := fmt.Sprintf("%s%s:%s:%s:%s/%v", - ipv6Net.IP.String(), ipv4Arr[0], ipv4Arr[1], ipv4Arr[2], ipv4Arr[3], mSize) - if strings.Count(ipv6Net.IP.String(), ":") == 5 { - ipv6str = strings.Replace(ipv6str, "::", ":", -1) - } - n.NetDevs[devname].Ipaddr6.SetDefault(ipv6str) - } - n.NetDevs[devname].Netmask.Set(netdev.Netmask) - n.NetDevs[devname].Netmask.SetDefault("255.255.255.0") - n.NetDevs[devname].Hwaddr.Set(strings.ToLower(netdev.Hwaddr)) - n.NetDevs[devname].Gateway.Set(netdev.Gateway) - n.NetDevs[devname].Type.Set(netdev.Type) - n.NetDevs[devname].OnBoot.Set(netdev.OnBoot) - n.NetDevs[devname].Primary.Set(netdev.Primary) - n.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility - // for just one netdev, it is always the primary - if len(node.NetDevs) == 1 { - n.NetDevs[devname].Primary.Set("true") - } - n.NetDevs[devname].Tags = make(map[string]*Entry) - for keyname, key := range netdev.Tags { - if _, ok := n.Tags[keyname]; !ok { - var keyVar Entry - n.NetDevs[devname].Tags[keyname] = &keyVar - } - n.NetDevs[devname].Tags[keyname].Set(key) - } - n.NetDevs[devname].Tags = make(map[string]*Entry) - for keyname, key := range netdev.Tags { - if _, ok := n.Tags[keyname]; !ok { - var keyVar Entry - n.NetDevs[devname].Tags[keyname] = &keyVar - } - n.NetDevs[devname].Tags[keyname].Set(key) - } - } - */ // Merge Keys into Tags for backwards compatibility if len(node.Tags) == 0 { node.Tags = make(map[string]string) From ed5b2bbf358e0f9edfa9c853ab8f00080364c9b7 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 3 Aug 2022 11:56:51 +0200 Subject: [PATCH 23/38] using tag instead of key --- internal/app/wwctl/node/list/main.go | 2 +- internal/pkg/node/constructors.go | 17 +++++------------ internal/pkg/node/datastructure.go | 4 ++-- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 16a9cc07..602687eb 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -69,7 +69,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { if len(subkeys) >= 2 { switch subkeys[0] { case "key": - fieldName = "key:" + subkeys[1] + fieldName = "tag:" + subkeys[1] case "IpmiEntry": fieldName = ipmiLopt[subkeys[1]] case "KernelEntry": diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index e3bc7fa8..3fa8024d 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -85,6 +85,11 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { n.Id.Set(nodename) nodeInfoType := reflect.TypeOf(&n) nodeInfoVal := reflect.ValueOf(&n) + // backward compatibilty + for keyname, key := range node.Keys { + node.Tags[keyname] = key + delete(node.Keys, keyname) + } nodeConfVal := reflect.ValueOf(node) // now iterate of every field for i := 0; i < nodeInfoType.Elem().NumField(); i++ { @@ -168,18 +173,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { if len(node.Tags) == 0 { node.Tags = make(map[string]string) } - for keyname, key := range node.Keys { - node.Tags[keyname] = key - delete(node.Keys, keyname) - } - - for keyname, key := range node.Tags { - if _, ok := n.Tags[keyname]; !ok { - var key Entry - n.Tags[keyname] = &key - } - n.Tags[keyname].Set(key) - } for _, p := range n.Profiles { if _, ok := config.NodeProfiles[p]; !ok { diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 8521122a..5f2d0e82 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -48,7 +48,7 @@ type NodeConf struct { Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" comment:"Make discoverable in given network (yes/no)"` Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` - Tags map[string]string `yaml:"tags,omitempty" lopt:"keys" comment:"base key"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"tag" comment:"base key"` Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility } @@ -61,7 +61,7 @@ type IpmiConf struct { Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` - Tags map[string]string `yaml:"tags,omitempty" lopt:"impitag" comment:"ipmi keys"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"ipmitag" comment:"ipmi keys"` } type KernelConf struct { Version string `yaml:"version,omitempty"` From ba46e34a4d75480cce942d656cd230243c922e36 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 3 Aug 2022 14:11:09 +0200 Subject: [PATCH 24/38] merging profile update --- internal/pkg/node/constructors.go | 148 +++++++++++++----------------- 1 file changed, 65 insertions(+), 83 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 3fa8024d..d6a37abc 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -83,13 +83,13 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // node explciti nodename field in NodeConf n.Id.Set(nodename) - nodeInfoType := reflect.TypeOf(&n) - nodeInfoVal := reflect.ValueOf(&n) // backward compatibilty for keyname, key := range node.Keys { node.Tags[keyname] = key delete(node.Keys, keyname) } + nodeInfoVal := reflect.ValueOf(&n) + nodeInfoType := reflect.TypeOf(&n) nodeConfVal := reflect.ValueOf(node) // now iterate of every field for i := 0; i < nodeInfoType.Elem().NumField(); i++ { @@ -102,7 +102,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } else if valField.Type() == reflect.TypeOf([]string{}) { (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) } - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) nestedConfVal := reflect.ValueOf(valField.Interface()) @@ -174,95 +174,77 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags = make(map[string]string) } - for _, p := range n.Profiles { - if _, ok := config.NodeProfiles[p]; !ok { - wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, p) + for _, profileName := range n.Profiles { + if _, ok := config.NodeProfiles[profileName]; !ok { + wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, profileName) continue } - wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, p) - - n.Comment.SetAlt(config.NodeProfiles[p].Comment, p) - n.ClusterName.SetAlt(config.NodeProfiles[p].ClusterName, p) - n.ContainerName.SetAlt(config.NodeProfiles[p].ContainerName, p) - if config.NodeProfiles[p].Kernel != nil { - n.Kernel.Args.SetAlt(config.NodeProfiles[p].Kernel.Args, p) - } - n.Ipxe.SetAlt(config.NodeProfiles[p].Ipxe, p) - n.Init.SetAlt(config.NodeProfiles[p].Init, p) - if config.NodeProfiles[p].Ipmi != nil { - n.Ipmi.Ipaddr.SetAlt(config.NodeProfiles[p].Ipmi.Ipaddr, p) - n.Ipmi.Netmask.SetAlt(config.NodeProfiles[p].Ipmi.Netmask, p) - n.Ipmi.Port.SetAlt(config.NodeProfiles[p].Ipmi.Port, p) - n.Ipmi.Gateway.SetAlt(config.NodeProfiles[p].Ipmi.Gateway, p) - n.Ipmi.UserName.SetAlt(config.NodeProfiles[p].Ipmi.UserName, p) - n.Ipmi.Password.SetAlt(config.NodeProfiles[p].Ipmi.Password, p) - n.Ipmi.Interface.SetAlt(config.NodeProfiles[p].Ipmi.Interface, p) - n.Ipmi.Write.SetAlt(config.NodeProfiles[p].Ipmi.Write, p) - } - n.SystemOverlay.SetAltSlice(config.NodeProfiles[p].SystemOverlay, p) - n.RuntimeOverlay.SetAltSlice(config.NodeProfiles[p].RuntimeOverlay, p) - n.Root.SetAlt(config.NodeProfiles[p].Root, p) - n.AssetKey.SetAlt(config.NodeProfiles[p].AssetKey, p) - n.Discoverable.SetAlt(config.NodeProfiles[p].Discoverable, p) - - if config.NodeProfiles[p].Kernel != nil { - if config.NodeProfiles[p].Kernel.Override != "" { - n.Kernel.Override.SetAlt(config.NodeProfiles[p].Kernel.Override, p) - } else if config.NodeProfiles[p].Kernel.Version != "" { - n.Kernel.Override.SetAlt(config.NodeProfiles[p].Kernel.Version, p) - } - } - - for devname, netdev := range config.NodeProfiles[p].NetDevs { - if _, ok := n.NetDevs[devname]; !ok { - var netdev NetDevEntry - n.NetDevs[devname] = &netdev - } - wwlog.Printf(wwlog.DEBUG, "Updating profile (%s) netdev: %s\n", p, devname) - - n.NetDevs[devname].Device.SetAlt(netdev.Device, p) - n.NetDevs[devname].Ipaddr.SetAlt(netdev.Ipaddr, p) //FIXME? <- Ipaddr must be uniq - n.NetDevs[devname].Netmask.SetAlt(netdev.Netmask, p) - n.NetDevs[devname].Hwaddr.SetAlt(strings.ToLower(netdev.Hwaddr), p) - n.NetDevs[devname].Gateway.SetAlt(netdev.Gateway, p) - n.NetDevs[devname].Type.SetAlt(netdev.Type, p) - n.NetDevs[devname].OnBoot.SetAlt(netdev.OnBoot, p) - n.NetDevs[devname].Primary.SetAlt(netdev.Primary, p) - if len(netdev.Tags) != 0 { - if len(n.NetDevs[devname].Tags) == 0 { - n.NetDevs[devname].Tags = make(map[string]*Entry) - } - for keyname, key := range netdev.Tags { - if _, ok := n.NetDevs[devname].Tags[keyname]; !ok { - var keyVar Entry - n.NetDevs[devname].Tags[keyname] = &keyVar + wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) + nodeInfoVal := reflect.ValueOf(&n) + nodeInfoType := reflect.TypeOf(&n) + profileConfVal := reflect.ValueOf(config.NodeProfiles[profileName]) + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := profileConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name for Conf and Info + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAlt(valField.String(), profileName) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAltSlice(valField.Interface().([]string), profileName) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).SetAlt(nestedVal.String(), profileName) + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.SetAlt(val, profileName) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { + nestedMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range nestedMap { + netValsType := reflect.ValueOf(netVals) + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + // This should be done a bit down, but didn'tknow how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.SetAlt(val, profileName) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } } - n.NetDevs[devname].Tags[keyname].SetAlt(key, p) } } } - - // Merge Keys into Tags for backwards compatibility - if len(config.NodeProfiles[p].Tags) == 0 { - config.NodeProfiles[p].Tags = make(map[string]string) - } - for keyname, key := range config.NodeProfiles[p].Keys { - config.NodeProfiles[p].Tags[keyname] = key - delete(config.NodeProfiles[p].Keys, keyname) - } - - for keyname, key := range config.NodeProfiles[p].Tags { - if _, ok := n.Tags[keyname]; !ok { - var key Entry - n.Tags[keyname] = &key - } - n.Tags[keyname].SetAlt(key, p) - } } - ret = append(ret, n) - } sort.Slice(ret, func(i, j int) bool { From d819eef7926289084acd75e9e0ec2f187f559457 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 3 Aug 2022 17:58:01 +0200 Subject: [PATCH 25/38] tags for ipmi and kernel --- internal/pkg/node/constructors.go | 261 +++++++++++------------------- internal/pkg/node/methods.go | 31 +++- 2 files changed, 122 insertions(+), 170 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index d6a37abc..b3f03a2f 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -42,6 +42,76 @@ func New() (NodeYaml, error) { return ret, nil } +func (node *NodeInfo) initFrom(n *NodeConf) { + nodeInfoVal := reflect.ValueOf(node) + nodeInfoType := reflect.TypeOf(node) + nodeConfVal := reflect.ValueOf(n) + // now iterate of every field + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name for Conf and Info + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.Set(val) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { + nestedMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range nestedMap { + netValsType := reflect.ValueOf(netVals) + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + // This should be done a bit down, but didn'tknow how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) + if netInfoType.Field(j).Name == "Netmask" { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") + } + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.Set(val) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } + } + } + } + } + +} + /* Get all the nodes of a configuration. This function also merges the nodes with the given profiles and set the default values @@ -88,72 +158,19 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags[keyname] = key delete(node.Keys, keyname) } - nodeInfoVal := reflect.ValueOf(&n) - nodeInfoType := reflect.TypeOf(&n) - nodeConfVal := reflect.ValueOf(node) - // now iterate of every field - for i := 0; i < nodeInfoType.Elem().NumField(); i++ { - valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) - if valField.IsValid() { - // found field with same name for Conf and Info - if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { - if valField.Type().Kind() == reflect.String { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) - } else if valField.Type() == reflect.TypeOf([]string{}) { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) - } - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { - nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) - netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) - nestedConfVal := reflect.ValueOf(valField.Interface()) - for j := 0; j < nestedInfoType.Elem().NumField(); j++ { - nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) - if nestedVal.IsValid() { - if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) - } - } - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { - confMap := valField.Interface().(map[string]string) - for key, val := range confMap { - var entr Entry - entr.Set(val) - (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { - netValsType := reflect.ValueOf(netVals) - netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn'tknow how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) - for j := 0; j < netInfoType.NumField(); j++ { - netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) - if netVal.IsValid() { - if netVal.Type().Kind() == reflect.String { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) - if netInfoType.Field(j).Name == "Netmask" { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") - } - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.Set(val) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr - } - } - } - } - } - } - } - } + n.initFrom(node) + // backward compatibility + n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) + n.Ipmi.Netmask.Set(node.IpmiNetmask) + n.Ipmi.Port.Set(node.IpmiPort) + n.Ipmi.Gateway.Set(node.IpmiGateway) + n.Ipmi.UserName.Set(node.IpmiUserName) + n.Ipmi.Password.Set(node.IpmiPassword) + n.Ipmi.Interface.Set(node.IpmiInterface) + n.Ipmi.Write.Set(node.IpmiWrite) + n.Kernel.Args.Set(node.KernelArgs) + n.Kernel.Override.Set(node.KernelOverride) + n.Kernel.Override.Set(node.KernelVersion) // delete deprecated structures so that they do not get unmarshalled node.IpmiIpaddr = "" node.IpmiNetmask = "" @@ -162,10 +179,6 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.IpmiPassword = "" node.IpmiInterface = "" node.IpmiWrite = "" - // backward compatibility - n.Kernel.Args.Set(node.KernelArgs) - n.Kernel.Override.Set(node.KernelOverride) - n.Kernel.Override.Set(node.KernelVersion) node.KernelArgs = "" node.KernelOverride = "" node.KernelVersion = "" @@ -179,7 +192,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, profileName) continue } - + // can't call setFrom() as we have to use SetAlt instead of Set for an Entry wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) nodeInfoVal := reflect.ValueOf(&n) nodeInfoType := reflect.TypeOf(&n) @@ -230,7 +243,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { if netVal.Type().Kind() == reflect.String { netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it + // normally the map should be created here, but did not manage it for key, val := range (netVal.Interface()).(map[string]string) { var entr Entry entr.SetAlt(val, profileName) @@ -269,32 +282,12 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { for name, profile := range config.NodeProfiles { var p NodeInfo - p.NetDevs = make(map[string]*NetDevEntry) - p.Tags = make(map[string]*Entry) - p.Kernel = new(KernelEntry) - p.Ipmi = new(IpmiEntry) p.Id.Set(name) - p.Comment.Set(profile.Comment) - p.ClusterName.Set(profile.ClusterName) - p.ContainerName.Set(profile.ContainerName) - p.Ipxe.Set(profile.Ipxe) - p.Init.Set(profile.Init) - // backward compatibility - p.Kernel.Args.Set(profile.KernelArgs) - p.Kernel.Override.Set(profile.KernelOverride) - p.Kernel.Override.Set(profile.KernelVersion) - profile.KernelArgs = "" - profile.KernelOverride = "" - profile.KernelVersion = "" - if profile.Kernel != nil { - p.Kernel.Args.Set(profile.Kernel.Args) - if profile.Kernel.Override != "" { - p.Kernel.Override.Set(profile.Kernel.Override) - } else if profile.Kernel.Version != "" { - p.Kernel.Override.Set(profile.Kernel.Version) - } + for keyname, key := range profile.Keys { + profile.Tags[keyname] = key + delete(profile.Keys, keyname) } - // backward compatibility for old Ipmi config + p.initFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) p.Ipmi.Port.Set(profile.IpmiPort) @@ -303,7 +296,10 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { p.Ipmi.Password.Set(profile.IpmiPassword) p.Ipmi.Interface.Set(profile.IpmiInterface) p.Ipmi.Write.Set(profile.IpmiWrite) - // delete deprectated structures so that they do not get unmarshalled + p.Kernel.Args.Set(profile.KernelArgs) + p.Kernel.Override.Set(profile.KernelOverride) + p.Kernel.Override.Set(profile.KernelVersion) + // delete deprecated stuff profile.IpmiIpaddr = "" profile.IpmiNetmask = "" profile.IpmiGateway = "" @@ -311,74 +307,9 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.IpmiPassword = "" profile.IpmiInterface = "" profile.IpmiWrite = "" - if profile.Ipmi != nil { - p.Ipmi.Netmask.Set(profile.Ipmi.Netmask) - p.Ipmi.Port.Set(profile.Ipmi.Port) - p.Ipmi.Gateway.Set(profile.Ipmi.Gateway) - p.Ipmi.UserName.Set(profile.Ipmi.UserName) - p.Ipmi.Password.Set(profile.Ipmi.Password) - p.Ipmi.Interface.Set(profile.Ipmi.Interface) - p.Ipmi.Write.Set(profile.Ipmi.Write) - } - p.RuntimeOverlay.SetSlice(profile.RuntimeOverlay) - p.SystemOverlay.SetSlice(profile.SystemOverlay) - p.Root.Set(profile.Root) - p.AssetKey.Set(profile.AssetKey) - p.Discoverable.Set(profile.Discoverable) - - for devname, netdev := range profile.NetDevs { - if _, ok := p.NetDevs[devname]; !ok { - var netdev NetDevEntry - p.NetDevs[devname] = &netdev - } - - wwlog.Printf(wwlog.DEBUG, "Updating profile netdev: %s\n", devname) - - p.NetDevs[devname].Device.Set(netdev.Device) - p.NetDevs[devname].Netmask.Set(netdev.Netmask) - p.NetDevs[devname].Gateway.Set(netdev.Gateway) - p.NetDevs[devname].Type.Set(netdev.Type) - p.NetDevs[devname].OnBoot.Set(netdev.OnBoot) - p.NetDevs[devname].Primary.Set(netdev.Primary) - p.NetDevs[devname].Primary.Set(netdev.Default) // backwards compatibility - - // The following should not be set in a profile. - if netdev.Ipaddr != "" { - wwlog.Printf(wwlog.WARN, "Ignoring ip address %v in profile %v\n", netdev.Ipaddr, name) - } - if netdev.Hwaddr != "" { - wwlog.Printf(wwlog.WARN, "Ignoring hardware address %v in profile %v\n", netdev.Hwaddr, name) - } - p.NetDevs[devname].Tags = make(map[string]*Entry) - for keyname, key := range netdev.Tags { - if _, ok := p.Tags[keyname]; !ok { - var keyVar Entry - p.NetDevs[devname].Tags[keyname] = &keyVar - } - p.NetDevs[devname].Tags[keyname].Set(key) - } - - } - - // Merge Keys into Tags for backwards compatibility - if len(profile.Tags) == 0 { - profile.Tags = make(map[string]string) - } - for keyname, key := range profile.Keys { - profile.Tags[keyname] = key - delete(profile.Keys, keyname) - } - - for keyname, key := range profile.Tags { - if _, ok := p.Tags[keyname]; !ok { - var key Entry - p.Tags[keyname] = &key - } - p.Tags[keyname].Set(key) - } - - // TODO: Validate or die on all inputs - + profile.KernelArgs = "" + profile.KernelOverride = "" + profile.KernelVersion = "" ret = append(ret, p) } sort.Slice(ret, func(i, j int) bool { diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 7627465f..c27785ec 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -342,6 +342,10 @@ Add an entry in a map */ func AddEntry(entryMapInt interface{}, val interface{}) { if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { + if reflect.ValueOf(entryMapInt).Elem().IsNil() { + newMap := make(map[string]*Entry) + entryMapInt = &newMap + } entryMap := entryMapInt.(*map[string]*Entry) str, ok := (val).(string) if !ok { @@ -388,7 +392,6 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { field := reflect.ValueOf(node).Elem().FieldByName(fieldName) if field.IsValid() { if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { - //fmt.Println(reflect.TypeOf(field.Addr().Interface())) SetEntry(field.Addr().Interface(), val) } else if field.Addr().Type() == reflect.TypeOf((*[]string)(nil)) { SetEntry(field.Addr().Interface(), val) @@ -421,10 +424,11 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { switch nestedField.Addr().Type() { case reflect.TypeOf((**KernelEntry)(nil)): entry := nestedField.Addr().Interface().(**KernelEntry) - (*entry).SetField(fieldNames[1], val) + (*entry).SetField(strings.Join(fieldNames[1:], "."), val) case reflect.TypeOf((**IpmiEntry)(nil)): entry := nestedField.Addr().Interface().(**IpmiEntry) - (*entry).SetField(fieldNames[1], val) + fmt.Println(fieldNames) + (*entry).SetField(strings.Join(fieldNames[1:], "."), val) case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): if len(fieldNames) >= 3 { entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) @@ -458,7 +462,15 @@ func (node *KernelEntry) SetField(fieldName string, val interface{}) { if field.IsValid() { SetEntry(field.Addr().Interface(), val) } else { - panic(fmt.Sprintf("field %s does not exists in node.KernEntry\n", fieldName)) + valFields := strings.Split(fieldName, ".") + field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) + if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { + AddEntry(field.Addr().Interface(), val) + } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { + DelEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) + } } } @@ -470,7 +482,16 @@ func (node *IpmiEntry) SetField(fieldName string, val interface{}) { if field.IsValid() { SetEntry(field.Addr().Interface(), val) } else { - panic(fmt.Sprintf("field %s does not exists in node.ImpiEntry\n", fieldName)) + fmt.Println(fieldName) + valFields := strings.Split(fieldName, ".") + field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) + if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { + AddEntry(field.Addr().Interface(), val) + } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { + DelEntry(field.Addr().Interface(), val) + } else { + panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) + } } } From 41d12888abc3da021904c543351d73f8c71ab451 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 5 Aug 2022 12:33:58 +0200 Subject: [PATCH 26/38] reflections for unmarshal --- internal/app/wwctl/node/list/main.go | 3 + internal/app/wwctl/profile/delete/main.go | 5 +- internal/pkg/api/node/methods.go | 2 +- internal/pkg/node/constructors.go | 144 +---------- internal/pkg/node/datastructure.go | 2 +- internal/pkg/node/methods.go | 37 +-- internal/pkg/node/modifiers.go | 121 +-------- internal/pkg/node/transformers.go | 283 ++++++++++++++++++++++ 8 files changed, 320 insertions(+), 277 deletions(-) create mode 100644 internal/pkg/node/transformers.go diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 602687eb..1a5d8515 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -72,6 +72,9 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { fieldName = "tag:" + subkeys[1] case "IpmiEntry": fieldName = ipmiLopt[subkeys[1]] + if len(subkeys) == 3 { + fieldName = "ipmikey:" + subkeys[2] + } case "KernelEntry": fieldName = kernelLopt[subkeys[1]] case "NetDevEntry": diff --git a/internal/app/wwctl/profile/delete/main.go b/internal/app/wwctl/profile/delete/main.go index b16696a6..f71e1f18 100644 --- a/internal/app/wwctl/profile/delete/main.go +++ b/internal/app/wwctl/profile/delete/main.go @@ -5,7 +5,6 @@ import ( "os" "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/manifoldco/promptui" "github.com/pkg/errors" @@ -36,10 +35,10 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } for _, n := range nodes { - for _, np := range n.Profiles { + for _, np := range n.Profiles.GetSlice() { if np == r { wwlog.Printf(wwlog.VERBOSE, "Removing profile from node %s: %s\n", n.Id.Get(), r) - n.Profiles = util.SliceRemoveElement(n.Profiles, r) + n.Profiles.SliceRemoveElement(r) err := nodeDB.NodeUpdate(n) if err != nil { return errors.Wrap(err, "failed to update node") diff --git a/internal/pkg/api/node/methods.go b/internal/pkg/api/node/methods.go index 57428170..8943d455 100644 --- a/internal/pkg/api/node/methods.go +++ b/internal/pkg/api/node/methods.go @@ -72,7 +72,7 @@ func GetFields(n interface{}) map[string]*wwapiv1.NodeField { } } default: - fmt.Println(nodeType.Field(i).Type) + panic(fmt.Sprintf("Can't handle: %s\n", nodeType.Field(i).Type)) } } return fieldMap diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index b3f03a2f..a8690d44 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -4,7 +4,6 @@ import ( "errors" "io/ioutil" "path" - "reflect" "sort" "strings" @@ -42,76 +41,6 @@ func New() (NodeYaml, error) { return ret, nil } -func (node *NodeInfo) initFrom(n *NodeConf) { - nodeInfoVal := reflect.ValueOf(node) - nodeInfoType := reflect.TypeOf(node) - nodeConfVal := reflect.ValueOf(n) - // now iterate of every field - for i := 0; i < nodeInfoType.Elem().NumField(); i++ { - valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) - if valField.IsValid() { - // found field with same name for Conf and Info - if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { - if valField.Type().Kind() == reflect.String { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) - } else if valField.Type() == reflect.TypeOf([]string{}) { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) - } - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { - nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) - netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) - nestedConfVal := reflect.ValueOf(valField.Interface()) - for j := 0; j < nestedInfoType.Elem().NumField(); j++ { - nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) - if nestedVal.IsValid() { - if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) - } - } - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { - confMap := valField.Interface().(map[string]string) - for key, val := range confMap { - var entr Entry - entr.Set(val) - (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { - netValsType := reflect.ValueOf(netVals) - netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn'tknow how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) - for j := 0; j < netInfoType.NumField(); j++ { - netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) - if netVal.IsValid() { - if netVal.Type().Kind() == reflect.String { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) - if netInfoType.Field(j).Name == "Netmask" { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") - } - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.Set(val) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr - } - } - } - } - } - } - } - } - -} - /* Get all the nodes of a configuration. This function also merges the nodes with the given profiles and set the default values @@ -147,9 +76,9 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // special handling for profile to get the default one if len(node.Profiles) == 0 { - n.Profiles = []string{"default"} + n.Profiles.SetSlice([]string{"default"}) } else { - n.Profiles = node.Profiles + n.Profiles.SetSlice(node.Profiles) } // node explciti nodename field in NodeConf n.Id.Set(nodename) @@ -158,7 +87,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags[keyname] = key delete(node.Keys, keyname) } - n.initFrom(node) + n.setFrom(node) // backward compatibility n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) n.Ipmi.Netmask.Set(node.IpmiNetmask) @@ -187,75 +116,14 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags = make(map[string]string) } - for _, profileName := range n.Profiles { + for _, profileName := range n.Profiles.GetSlice() { if _, ok := config.NodeProfiles[profileName]; !ok { wwlog.Printf(wwlog.WARN, "Profile not found for node '%s': %s\n", nodename, profileName) continue } // can't call setFrom() as we have to use SetAlt instead of Set for an Entry wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) - nodeInfoVal := reflect.ValueOf(&n) - nodeInfoType := reflect.TypeOf(&n) - profileConfVal := reflect.ValueOf(config.NodeProfiles[profileName]) - for i := 0; i < nodeInfoType.Elem().NumField(); i++ { - valField := profileConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) - if valField.IsValid() { - // found field with same name for Conf and Info - if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { - if valField.Type().Kind() == reflect.String { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAlt(valField.String(), profileName) - } else if valField.Type() == reflect.TypeOf([]string{}) { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAltSlice(valField.Interface().([]string), profileName) - } - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { - nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) - netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) - nestedConfVal := reflect.ValueOf(valField.Interface()) - for j := 0; j < nestedInfoType.Elem().NumField(); j++ { - nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) - if nestedVal.IsValid() { - if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).SetAlt(nestedVal.String(), profileName) - } - } - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { - confMap := valField.Interface().(map[string]string) - for key, val := range confMap { - var entr Entry - entr.SetAlt(val, profileName) - (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { - netValsType := reflect.ValueOf(netVals) - netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn'tknow how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) - for j := 0; j < netInfoType.NumField(); j++ { - netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) - if netVal.IsValid() { - if netVal.Type().Kind() == reflect.String { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normally the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.SetAlt(val, profileName) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr - } - } - } - } - } - } - } - } + config.NodeProfiles[profileName].setAltFrom(n, profileName) } ret = append(ret, n) } @@ -287,7 +155,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.Tags[keyname] = key delete(profile.Keys, keyname) } - p.initFrom(profile) + p.setFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) p.Ipmi.Port.Set(profile.IpmiPort) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 5f2d0e82..1255dd53 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -120,7 +120,7 @@ type NodeInfo struct { AssetKey Entry Kernel *KernelEntry Ipmi *IpmiEntry - Profiles []string + Profiles Entry NetDevs map[string]*NetDevEntry Tags map[string]*Entry } diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index c27785ec..a8713e8f 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -50,10 +50,10 @@ func FilterByName(set []NodeInfo, searchList []string) []NodeInfo { *********/ /* - Set value. If argument is 'UNDEF', 'DELETE', - 'UNSET" or '--' the value is removed. - N.B. the '--' might never ever happen as '--' - is parsed out by cobra +Set value. If argument is 'UNDEF', 'DELETE', +'UNSET" or '--' the value is removed. +N.B. the '--' might never ever happen as '--' +is parsed out by cobra */ func (ent *Entry) Set(val string) { if val == "" { @@ -147,6 +147,13 @@ func (ent *Entry) SetDefaultSlice(val []string) { } +/* +Remove a elemnt from a slice +*/ +func (ent *Entry) SliceRemoveElement(val string) { + util.SliceRemoveElement(ent.value, val) +} + /********** * * Gets @@ -340,7 +347,7 @@ func SetEntry(entryPtr interface{}, val interface{}) { /* Add an entry in a map */ -func AddEntry(entryMapInt interface{}, val interface{}) { +func addEntry(entryMapInt interface{}, val interface{}) { if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { if reflect.ValueOf(entryMapInt).Elem().IsNil() { newMap := make(map[string]*Entry) @@ -369,7 +376,7 @@ func AddEntry(entryMapInt interface{}, val interface{}) { /* Del an entry in a map */ -func DelEntry(entryMapInt interface{}, val interface{}) { +func delEntry(entryMapInt interface{}, val interface{}) { if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { entryMap := entryMapInt.(*map[string]*Entry) str, ok := (val).(string) @@ -411,9 +418,9 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { fieldMap := reflect.ValueOf(node).Elem().FieldByName(fieldNames[1]) if fieldMap.IsValid() { if fieldNames[0] == "del" { - DelEntry(fieldMap.Addr().Elem().Interface(), val) + delEntry(fieldMap.Addr().Interface(), val) } else if fieldNames[0] == "add" { - AddEntry(fieldMap.Addr().Elem().Interface(), val) + addEntry(fieldMap.Addr().Interface(), val) } } else { panic(fmt.Sprintf("invalid del/add operation with name %s called, field %s does not exists\n", fieldName, fieldNames[0])) @@ -427,7 +434,6 @@ func (node *NodeInfo) SetField(fieldName string, val interface{}) { (*entry).SetField(strings.Join(fieldNames[1:], "."), val) case reflect.TypeOf((**IpmiEntry)(nil)): entry := nestedField.Addr().Interface().(**IpmiEntry) - fmt.Println(fieldNames) (*entry).SetField(strings.Join(fieldNames[1:], "."), val) case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): if len(fieldNames) >= 3 { @@ -465,9 +471,9 @@ func (node *KernelEntry) SetField(fieldName string, val interface{}) { valFields := strings.Split(fieldName, ".") field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - AddEntry(field.Addr().Interface(), val) + addEntry(field.Addr().Interface(), val) } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - DelEntry(field.Addr().Interface(), val) + delEntry(field.Addr().Interface(), val) } else { panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) } @@ -482,13 +488,12 @@ func (node *IpmiEntry) SetField(fieldName string, val interface{}) { if field.IsValid() { SetEntry(field.Addr().Interface(), val) } else { - fmt.Println(fieldName) valFields := strings.Split(fieldName, ".") field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - AddEntry(field.Addr().Interface(), val) + addEntry(field.Addr().Interface(), val) } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - DelEntry(field.Addr().Interface(), val) + delEntry(field.Addr().Interface(), val) } else { panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) } @@ -506,9 +511,9 @@ func (node *NetDevEntry) SetField(fieldName string, val interface{}) { valFields := strings.Split(fieldName, ".") field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - AddEntry(field.Addr().Interface(), val) + addEntry(field.Addr().Interface(), val) } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - DelEntry(field.Addr().Interface(), val) + delEntry(field.Addr().Interface(), val) } else { panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) } diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 4d094dc6..bb3a5677 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -29,7 +29,7 @@ func (config *NodeYaml) AddNode(nodeID string) (NodeInfo, error) { config.Nodes[nodeID].Profiles = []string{"default"} config.Nodes[nodeID].NetDevs = make(map[string]*NetDevs) n.Id.Set(nodeID) - n.Profiles = []string{"default"} + n.Profiles.SetSlice([]string{"default"}) n.NetDevs = make(map[string]*NetDevEntry) n.Ipmi = new(IpmiEntry) n.Kernel = new(KernelEntry) @@ -55,68 +55,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error { if _, ok := config.Nodes[nodeID]; !ok { return errors.New("Nodename does not exist: " + nodeID) } - - config.Nodes[nodeID].Comment = node.Comment.GetReal() - config.Nodes[nodeID].ContainerName = node.ContainerName.GetReal() - config.Nodes[nodeID].ClusterName = node.ClusterName.GetReal() - config.Nodes[nodeID].Ipxe = node.Ipxe.GetReal() - config.Nodes[nodeID].Init = node.Init.GetReal() - - if node.Kernel != nil && (node.Kernel.Override.GotReal() || node.Kernel.Args.GotReal()) { - config.Nodes[nodeID].Kernel = new(KernelConf) - config.Nodes[nodeID].Kernel.Override = node.Kernel.Override.GetReal() - config.Nodes[nodeID].Kernel.Args = node.Kernel.Args.GetReal() - } - - if node.Ipmi != nil && (node.Ipmi.Ipaddr.GotReal() || node.Ipmi.Netmask.GotReal() || - node.Ipmi.Port.GotReal() || node.Ipmi.Gateway.GotReal() || node.Ipmi.UserName.GotReal() || - node.Ipmi.Password.GotReal() || node.Ipmi.Interface.GotReal() || node.Ipmi.Write.GotReal()) { - config.Nodes[nodeID].Ipmi = new(IpmiConf) - config.Nodes[nodeID].Ipmi.Ipaddr = node.Ipmi.Ipaddr.GetReal() - config.Nodes[nodeID].Ipmi.Netmask = node.Ipmi.Netmask.GetReal() - config.Nodes[nodeID].Ipmi.Port = node.Ipmi.Port.GetReal() - config.Nodes[nodeID].Ipmi.Gateway = node.Ipmi.Gateway.GetReal() - config.Nodes[nodeID].Ipmi.UserName = node.Ipmi.UserName.GetReal() - config.Nodes[nodeID].Ipmi.Password = node.Ipmi.Password.GetReal() - config.Nodes[nodeID].Ipmi.Interface = node.Ipmi.Interface.GetReal() - config.Nodes[nodeID].Ipmi.Write = node.Ipmi.Write.Get() - } - config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetRealSlice() - config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetRealSlice() - config.Nodes[nodeID].Root = node.Root.GetReal() - config.Nodes[nodeID].AssetKey = node.AssetKey.GetReal() - config.Nodes[nodeID].Discoverable = node.Discoverable.GetReal() - - config.Nodes[nodeID].Profiles = node.Profiles - - config.Nodes[nodeID].NetDevs = make(map[string]*NetDevs) - for devname, netdev := range node.NetDevs { - var newdev NetDevs - config.Nodes[nodeID].NetDevs[devname] = &newdev - - config.Nodes[nodeID].NetDevs[devname].Device = netdev.Device.GetReal() - config.Nodes[nodeID].NetDevs[devname].Ipaddr = netdev.Ipaddr.GetReal() - config.Nodes[nodeID].NetDevs[devname].Netmask = netdev.Netmask.GetReal() - config.Nodes[nodeID].NetDevs[devname].Hwaddr = netdev.Hwaddr.GetReal() - config.Nodes[nodeID].NetDevs[devname].Gateway = netdev.Gateway.GetReal() - config.Nodes[nodeID].NetDevs[devname].Type = netdev.Type.GetReal() - config.Nodes[nodeID].NetDevs[devname].OnBoot = netdev.OnBoot.GetReal() - config.Nodes[nodeID].NetDevs[devname].Primary = netdev.Primary.GetReal() - config.Nodes[nodeID].NetDevs[devname].Tags = make(map[string]string) - for keyname, key := range netdev.Tags { - if key.GetReal() != "" { - config.Nodes[nodeID].NetDevs[devname].Tags[keyname] = key.GetReal() - } - } - } - - config.Nodes[nodeID].Tags = make(map[string]string) - for keyname, key := range node.Tags { - if key.GetReal() != "" { - config.Nodes[nodeID].Tags[keyname] = key.GetReal() - } - } - + config.Nodes[nodeID].getRealFrom(node) return nil } @@ -164,61 +103,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { if _, ok := config.NodeProfiles[profileID]; !ok { return errors.New("Profile name does not exist: " + profileID) } - config.NodeProfiles[profileID].Comment = profile.Comment.GetReal() - config.NodeProfiles[profileID].ContainerName = profile.ContainerName.GetReal() - config.NodeProfiles[profileID].Ipxe = profile.Ipxe.GetReal() - config.NodeProfiles[profileID].Init = profile.Init.GetReal() - config.NodeProfiles[profileID].ClusterName = profile.ClusterName.GetReal() - if profile.Kernel.Override.GotReal() || profile.Kernel.Args.GotReal() { - config.NodeProfiles[profileID].Kernel = new(KernelConf) - config.NodeProfiles[profileID].Kernel.Override = profile.Kernel.Override.GetReal() - config.NodeProfiles[profileID].Kernel.Args = profile.Kernel.Args.GetReal() - } - if profile.Ipmi.Ipaddr.GotReal() || profile.Ipmi.Netmask.GotReal() || - profile.Ipmi.Port.GotReal() || profile.Ipmi.Gateway.GotReal() || profile.Ipmi.UserName.GotReal() || - profile.Ipmi.Password.GotReal() || profile.Ipmi.Interface.GotReal() || profile.Ipmi.Write.GotReal() { - config.NodeProfiles[profileID].Ipmi = new(IpmiConf) - config.NodeProfiles[profileID].Ipmi.Ipaddr = profile.Ipmi.Ipaddr.GetReal() - config.NodeProfiles[profileID].Ipmi.Netmask = profile.Ipmi.Netmask.GetReal() - config.NodeProfiles[profileID].Ipmi.Port = profile.Ipmi.Port.GetReal() - config.NodeProfiles[profileID].Ipmi.Gateway = profile.Ipmi.Gateway.GetReal() - config.NodeProfiles[profileID].Ipmi.UserName = profile.Ipmi.UserName.GetReal() - config.NodeProfiles[profileID].Ipmi.Password = profile.Ipmi.Password.GetReal() - config.NodeProfiles[profileID].Ipmi.Interface = profile.Ipmi.Interface.GetReal() - config.NodeProfiles[profileID].Ipmi.Write = profile.Ipmi.Interface.Get() - } - config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetRealSlice() - config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetRealSlice() - config.NodeProfiles[profileID].Root = profile.Root.GetReal() - config.NodeProfiles[profileID].AssetKey = profile.AssetKey.GetReal() - config.NodeProfiles[profileID].Discoverable = profile.Discoverable.GetReal() - - config.NodeProfiles[profileID].Profiles = profile.Profiles - - config.NodeProfiles[profileID].NetDevs = make(map[string]*NetDevs) - for devname, netdev := range profile.NetDevs { - var newdev NetDevs - config.NodeProfiles[profileID].NetDevs[devname] = &newdev - - config.NodeProfiles[profileID].NetDevs[devname].Device = netdev.Device.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Ipaddr = netdev.Ipaddr.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Netmask = netdev.Netmask.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Hwaddr = netdev.Hwaddr.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Gateway = netdev.Gateway.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Type = netdev.Type.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].OnBoot = netdev.OnBoot.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Primary = netdev.Primary.GetReal() - config.NodeProfiles[profileID].NetDevs[devname].Tags = make(map[string]string) - for key := range netdev.Tags { - config.NodeProfiles[profileID].NetDevs[devname].Tags[key] = netdev.Tags[key].GetReal() - } - } - - config.NodeProfiles[profileID].Tags = make(map[string]string) - for keyname, key := range profile.Tags { - config.NodeProfiles[profileID].Tags[keyname] = key.GetReal() - } - + config.NodeProfiles[profileID].getRealFrom(profile) return nil } diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go new file mode 100644 index 00000000..f8bb58a9 --- /dev/null +++ b/internal/pkg/node/transformers.go @@ -0,0 +1,283 @@ +package node + +import "reflect" + +/* +Populates a NodeConf struct (the one which goes to disk) from a +NodeInfo (which just lives in memory), with the values from all +the underlying entries using GetReal, so just the explicit values +go do disk. +*/ +func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { + nodeInfoType := reflect.TypeOf(nodeInfo) + nodeInfoVal := reflect.ValueOf(nodeInfo) + configVal := reflect.ValueOf(nodeConf) + // now iterate of every field + for i := 0; i < nodeInfoType.NumField(); i++ { + // found field with same name for Conf and Info + confField := configVal.Elem().FieldByName(nodeInfoType.Field(i).Name) + if confField.IsValid() { + if nodeInfoVal.Field(i).Type() == reflect.TypeOf(Entry{}) { + if confField.Type().Kind() == reflect.String { + newValue := (confField.Addr().Interface()).(*string) + entryVal := nodeInfoVal.Field(i).Interface().(Entry) + *newValue = entryVal.GetReal() + } else if confField.Type() == reflect.TypeOf([]string{}) { + newValue := (confField.Addr().Interface()).(*[]string) + entryVal := nodeInfoVal.Field(i).Interface().(Entry) + *newValue = entryVal.GetRealSlice() + } + } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { + entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) + for key, val := range entryMap { + confField.Interface().(map[string]string)[key] = val.GetReal() + } + } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { + if confField.Addr().Elem().IsZero() { + switch confField.Addr().Elem().Type() { + case reflect.TypeOf((*KernelConf)(nil)): + var newConf KernelConf + newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**KernelConf) + *newConfPtr = &newConf + case reflect.TypeOf((*IpmiConf)(nil)): + var newConf IpmiConf + newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**IpmiConf) + *newConfPtr = &newConf + } + } + needNestedStruct := false + nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface()) + nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface()) + nestedConfVal := reflect.ValueOf(confField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + if nestedVal.Type().Kind() == reflect.String { + newValue := (nestedVal.Addr().Interface()).(*string) + entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) + *newValue = entryVal.GetReal() + needNestedStruct = needNestedStruct || entryVal.GotReal() + } else if nestedVal.Type() == reflect.TypeOf([]string{}) { + newValue := (nestedVal.Addr().Interface()).(*[]string) + entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) + *newValue = entryVal.GetRealSlice() + needNestedStruct = needNestedStruct || entryVal.GotReal() + + } + } else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) { + if nestedVal.IsNil() { + mapPtr := nestedVal.Addr().Interface().(*map[string]string) + *mapPtr = make(map[string]string) + } + entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) + for key, val := range entryMap { + nestedVal.Interface().(map[string]string)[key] = val.GetReal() + } + } + //} + } + // Check if the nested struct has any values, if not replace it with a nil pointer so + // that it does not get unmarshalled to someting like ipmi: {} + if !needNestedStruct { + switch confField.Type() { + case reflect.TypeOf((*IpmiConf)(nil)): + newConf := (confField.Addr().Interface()).(**IpmiConf) + *newConf = (*IpmiConf)(nil) + case reflect.TypeOf((*KernelConf)(nil)): + newConf := (confField.Addr().Interface()).(**KernelConf) + *newConf = (*KernelConf)(nil) + } + } + } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { + nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) + for netName, netVal := range nestedMap { + netValsType := reflect.ValueOf(netVal) + netMap := confField.Interface().(map[string](*NetDevs)) + var newNet NetDevs + newNet.Tags = make(map[string]string) + netMap[netName] = &newNet + netConfType := reflect.TypeOf(newNet) + netConfVal := reflect.ValueOf(&newNet) + for j := 0; j < netConfType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netConfType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type() == reflect.TypeOf(Entry{}) { + newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) + *newVal = (netVal.Addr().Interface()).(*Entry).GetReal() + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.Set(val) + netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + + } + } + } + } + /* else { + // NodeInfo has the Id field, nodeConf not + fmt.Println("INVALID", nodeInfoType.Field(i).Name) + } + */ + } +} + +/* +Populates all fields of NodeInfo with Set from the +values of NodeConf. +*/ +func (node *NodeInfo) setFrom(n *NodeConf) { + nodeInfoVal := reflect.ValueOf(node) + nodeInfoType := reflect.TypeOf(node) + nodeConfVal := reflect.ValueOf(n) + // now iterate of every field + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name for Conf and Info + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) + } else { + confMap := nestedVal.Interface().(map[string]string) + if netstedInfoVal.Elem().Field(j).IsNil() { + newMap := make(map[string]*Entry) + mapPtr := (netstedInfoVal.Elem().Field(j).Addr().Interface()).(*map[string](*Entry)) + *mapPtr = newMap + } + for key, val := range confMap { + var entr Entry + entr.Set(val) + (netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = &entr + } + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.Set(val) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { + nestedMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range nestedMap { + netValsType := reflect.ValueOf(netVals) + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + // This should be done a bit down, but didn't know how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) + if netInfoType.Field(j).Name == "Netmask" { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") + } + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.Set(val) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } + } + } + } + } +} + +/* +Populates all fields of NodeInfo with SetAlt from the +values of NodeConf. The string profileName is used to +destermine from which source/NodeInfo the entry came +from. +*/ +func (node *NodeConf) setAltFrom(nodeInfo NodeInfo, profileName string) { + nodeInfoVal := reflect.ValueOf(&nodeInfo) + nodeInfoType := reflect.TypeOf(&nodeInfo) + profileConfVal := reflect.ValueOf(node) + for i := 0; i < nodeInfoType.Elem().NumField(); i++ { + valField := profileConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + if valField.IsValid() { + // found field with same name for Conf and Info + if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { + if valField.Type().Kind() == reflect.String { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAlt(valField.String(), profileName) + } else if valField.Type() == reflect.TypeOf([]string{}) { + (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAltSlice(valField.Interface().([]string), profileName) + } + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { + nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + nestedConfVal := reflect.ValueOf(valField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedVal.IsValid() { + if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).SetAlt(nestedVal.String(), profileName) + } + } + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { + confMap := valField.Interface().(map[string]string) + for key, val := range confMap { + var entr Entry + entr.SetAlt(val, profileName) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { + nestedMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range nestedMap { + netValsType := reflect.ValueOf(netVals) + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + // This should be done a bit down, but didn'tknow how to do it + netMap[netName] = &newNet + netInfoType := reflect.TypeOf(newNet) + netInfoVal := reflect.ValueOf(&newNet) + for j := 0; j < netInfoType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type().Kind() == reflect.String { + netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normally the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.SetAlt(val, profileName) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + } + } + } + } + } +} From 8c2d40881dbda0ac0284b319b3cd7fc0695ed35a Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 10 Aug 2022 15:29:55 +0200 Subject: [PATCH 27/38] use reflect on overlays --- internal/pkg/api/node/node.go | 3 +- internal/pkg/node/constructors.go | 6 +- internal/pkg/node/methods.go | 1 + internal/pkg/node/modifiers.go | 4 +- internal/pkg/node/transformers.go | 145 ++++++++++++++++++++++---- internal/pkg/overlay/datastructure.go | 102 ++++-------------- 6 files changed, 157 insertions(+), 104 deletions(-) diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index 14263082..df1c64f3 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "os" + "sort" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/node" @@ -177,7 +178,7 @@ func NodeList(nodeNames []string) (nodeInfo []*wwapiv1.NodeInfo, err error) { } nodeNames = hostlist.Expand(nodeNames) - + sort.Strings(nodeNames) // Translate to the protobuf structure so wwapiv1 can use this across the wire. // This is the same logic as was in wwctl. for _, n := range node.FilterByName(nodes, nodeNames) { diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index a8690d44..8afb52ae 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -87,7 +87,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags[keyname] = key delete(node.Keys, keyname) } - n.setFrom(node) + n.SetFrom(node) // backward compatibility n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) n.Ipmi.Netmask.Set(node.IpmiNetmask) @@ -123,7 +123,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // can't call setFrom() as we have to use SetAlt instead of Set for an Entry wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) - config.NodeProfiles[profileName].setAltFrom(n, profileName) + config.NodeProfiles[profileName].SetAltFrom(n, profileName) } ret = append(ret, n) } @@ -155,7 +155,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.Tags[keyname] = key delete(profile.Keys, keyname) } - p.setFrom(profile) + p.SetFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) p.Ipmi.Port.Set(profile.IpmiPort) diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index a8713e8f..b9e77ceb 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -16,6 +16,7 @@ import ( * Filters * *********/ + /* Filter a given slice of NodeInfo against a given regular expression diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index bb3a5677..a89b06de 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -55,7 +55,7 @@ func (config *NodeYaml) NodeUpdate(node NodeInfo) error { if _, ok := config.Nodes[nodeID]; !ok { return errors.New("Nodename does not exist: " + nodeID) } - config.Nodes[nodeID].getRealFrom(node) + config.Nodes[nodeID].GetRealFrom(node) return nil } @@ -103,7 +103,7 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { if _, ok := config.NodeProfiles[profileID]; !ok { return errors.New("Profile name does not exist: " + profileID) } - config.NodeProfiles[profileID].getRealFrom(profile) + config.NodeProfiles[profileID].GetRealFrom(profile) return nil } diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index f8bb58a9..1428500b 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -1,6 +1,8 @@ package node -import "reflect" +import ( + "reflect" +) /* Populates a NodeConf struct (the one which goes to disk) from a @@ -8,7 +10,7 @@ NodeInfo (which just lives in memory), with the values from all the underlying entries using GetReal, so just the explicit values go do disk. */ -func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { +func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { nodeInfoType := reflect.TypeOf(nodeInfo) nodeInfoVal := reflect.ValueOf(nodeInfo) configVal := reflect.ValueOf(nodeConf) @@ -45,7 +47,6 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { *newConfPtr = &newConf } } - needNestedStruct := false nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface()) nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface()) nestedConfVal := reflect.ValueOf(confField.Interface()) @@ -56,12 +57,10 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { newValue := (nestedVal.Addr().Interface()).(*string) entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) *newValue = entryVal.GetReal() - needNestedStruct = needNestedStruct || entryVal.GotReal() } else if nestedVal.Type() == reflect.TypeOf([]string{}) { newValue := (nestedVal.Addr().Interface()).(*[]string) entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) *newValue = entryVal.GetRealSlice() - needNestedStruct = needNestedStruct || entryVal.GotReal() } } else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) { @@ -76,18 +75,7 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { } //} } - // Check if the nested struct has any values, if not replace it with a nil pointer so - // that it does not get unmarshalled to someting like ipmi: {} - if !needNestedStruct { - switch confField.Type() { - case reflect.TypeOf((*IpmiConf)(nil)): - newConf := (confField.Addr().Interface()).(**IpmiConf) - *newConf = (*IpmiConf)(nil) - case reflect.TypeOf((*KernelConf)(nil)): - newConf := (confField.Addr().Interface()).(**KernelConf) - *newConf = (*KernelConf)(nil) - } - } + } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) for netName, netVal := range nestedMap { @@ -126,11 +114,130 @@ func (nodeConf *NodeConf) getRealFrom(nodeInfo NodeInfo) { } } +/* +Populates a NodeConf struct from a NodeInfo, with the combined +values from the underlying entries using Get. +*/ +func (nodeConf *NodeConf) GetFrom(nodeInfo NodeInfo) { + nodeInfoType := reflect.TypeOf(nodeInfo) + nodeInfoVal := reflect.ValueOf(nodeInfo) + configVal := reflect.ValueOf(nodeConf) + // now iterate of every field + for i := 0; i < nodeInfoType.NumField(); i++ { + // found field with same name for Conf and Info + confField := configVal.Elem().FieldByName(nodeInfoType.Field(i).Name) + if confField.IsValid() { + if nodeInfoVal.Field(i).Type() == reflect.TypeOf(Entry{}) { + if confField.Type().Kind() == reflect.String { + newValue := (confField.Addr().Interface()).(*string) + entryVal := nodeInfoVal.Field(i).Interface().(Entry) + *newValue = entryVal.Get() + } else if confField.Type() == reflect.TypeOf([]string{}) { + newValue := (confField.Addr().Interface()).(*[]string) + entryVal := nodeInfoVal.Field(i).Interface().(Entry) + *newValue = entryVal.GetSlice() + } + } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { + if confField.IsNil() { + confFieldPtr := confField.Addr().Interface().(*map[string]string) + *confFieldPtr = make(map[string]string) + } + entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) + for key, val := range entryMap { + confField.Interface().(map[string]string)[key] = val.Get() + } + } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { + if confField.Addr().Elem().IsZero() { + switch confField.Addr().Elem().Type() { + case reflect.TypeOf((*KernelConf)(nil)): + var newConf KernelConf + newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**KernelConf) + *newConfPtr = &newConf + case reflect.TypeOf((*IpmiConf)(nil)): + var newConf IpmiConf + newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**IpmiConf) + *newConfPtr = &newConf + } + } + nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface()) + nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface()) + nestedConfVal := reflect.ValueOf(confField.Interface()) + for j := 0; j < nestedInfoType.Elem().NumField(); j++ { + nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) + if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { + if nestedVal.Type().Kind() == reflect.String { + newValue := (nestedVal.Addr().Interface()).(*string) + entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) + *newValue = entryVal.Get() + } else if nestedVal.Type() == reflect.TypeOf([]string{}) { + newValue := (nestedVal.Addr().Interface()).(*[]string) + entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) + *newValue = entryVal.GetSlice() + + } + } else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) { + if nestedVal.IsNil() { + mapPtr := nestedVal.Addr().Interface().(*map[string]string) + *mapPtr = make(map[string]string) + } + entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) + for key, val := range entryMap { + nestedVal.Interface().(map[string]string)[key] = val.Get() + } + } + } + } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { + nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) + for netName, netVal := range nestedMap { + netValsType := reflect.ValueOf(netVal) + if confField.IsNil() { + netMapPtr := confField.Addr().Interface().(*map[string](*NetDevs)) + *netMapPtr = make(map[string](*NetDevs)) + } + netMap := confField.Interface().(map[string](*NetDevs)) + var newNet NetDevs + newNet.Tags = make(map[string]string) + netMap[netName] = &newNet + netConfType := reflect.TypeOf(newNet) + netConfVal := reflect.ValueOf(&newNet) + for j := 0; j < netConfType.NumField(); j++ { + netVal := netValsType.Elem().FieldByName(netConfType.Field(j).Name) + if netVal.IsValid() { + if netVal.Type() == reflect.TypeOf(Entry{}) { + newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) + *newVal = (netVal.Addr().Interface()).(*Entry).Get() + } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { + // normaly the map should be created here, but did not manage it + for key, val := range (netVal.Interface()).(map[string]string) { + var entr Entry + entr.Set(val) + netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + } + } + } + + } + } + } + } /*else { + // NodeInfo has the Id field, nodeConf not + fmt.Println("INVALID", nodeInfoType.Field(i).Name) + } */ + } +} + /* Populates all fields of NodeInfo with Set from the values of NodeConf. */ -func (node *NodeInfo) setFrom(n *NodeConf) { +func (node *NodeInfo) SetFrom(n *NodeConf) { + // get the full memory, taking the shortcut and init Ipmi and Kernel directly + if node.Kernel == nil { + node.Kernel = new(KernelEntry) + } + if node.Ipmi == nil { + node.Ipmi = new(IpmiEntry) + } nodeInfoVal := reflect.ValueOf(node) nodeInfoType := reflect.TypeOf(node) nodeConfVal := reflect.ValueOf(n) @@ -217,7 +324,7 @@ values of NodeConf. The string profileName is used to destermine from which source/NodeInfo the entry came from. */ -func (node *NodeConf) setAltFrom(nodeInfo NodeInfo, profileName string) { +func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) { nodeInfoVal := reflect.ValueOf(&nodeInfo) nodeInfoType := reflect.TypeOf(&nodeInfo) profileConfVal := reflect.ValueOf(node) diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 4a0575af..60716dc7 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -16,33 +16,25 @@ struct which contains the variables to which are available in the templates. */ type TemplateStruct struct { - Id string - Hostname string - ClusterName string - Container string - Kernel *node.KernelConf - Init string - Root string - Ipmi *node.IpmiConf - RuntimeOverlay string - SystemOverlay string - NetDevs map[string]*node.NetDevs - Tags map[string]string - Keys map[string]string - AllNodes []node.NodeInfo - BuildHost string - BuildTime string - BuildTimeUnix string - BuildSource string - Ipaddr string - Ipaddr6 string - Netmask string - Network string - NetworkCIDR string - Ipv6 bool - Dhcp warewulfconf.DhcpConf - Nfs warewulfconf.NfsConf - Warewulf warewulfconf.WarewulfConf + Id string + Hostname string + BuildHost string + BuildTime string + BuildTimeUnix string + BuildSource string + Ipaddr string + Ipaddr6 string + Netmask string + Network string + NetworkCIDR string + Ipv6 bool + Dhcp warewulfconf.DhcpConf + Nfs warewulfconf.NfsConf + Warewulf warewulfconf.WarewulfConf + AllNodes []node.NodeInfo + node.NodeConf + // backward compatiblity + Container string } /* @@ -65,63 +57,12 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { wwlog.Printf(wwlog.ERROR, "%s\n", err) os.Exit(1) } - - tstruct.Kernel = new(node.KernelConf) - tstruct.Ipmi = new(node.IpmiConf) + // init some convininence vars tstruct.Id = nodeInfo.Id.Get() tstruct.Hostname = nodeInfo.Id.Get() tstruct.Id = nodeInfo.Id.Get() tstruct.Hostname = nodeInfo.Id.Get() - tstruct.ClusterName = nodeInfo.ClusterName.Get() - tstruct.Container = nodeInfo.ContainerName.Get() - tstruct.Kernel.Version = nodeInfo.Kernel.Override.Get() - tstruct.Kernel.Override = nodeInfo.Kernel.Override.Get() - tstruct.Kernel.Args = nodeInfo.Kernel.Args.Get() - tstruct.Init = nodeInfo.Init.Get() - tstruct.Root = nodeInfo.Root.Get() - tstruct.Ipmi.Ipaddr = nodeInfo.Ipmi.Ipaddr.Get() - tstruct.Ipmi.Netmask = nodeInfo.Ipmi.Netmask.Get() - tstruct.Ipmi.Port = nodeInfo.Ipmi.Port.Get() - tstruct.Ipmi.Gateway = nodeInfo.Ipmi.Gateway.Get() - tstruct.Ipmi.UserName = nodeInfo.Ipmi.UserName.Get() - tstruct.Ipmi.Password = nodeInfo.Ipmi.Password.Get() - tstruct.Ipmi.Interface = nodeInfo.Ipmi.Interface.Get() - tstruct.Ipmi.Write = nodeInfo.Ipmi.Write.Get() - tstruct.RuntimeOverlay = nodeInfo.RuntimeOverlay.Print() - tstruct.SystemOverlay = nodeInfo.SystemOverlay.Print() - tstruct.NetDevs = make(map[string]*node.NetDevs) - tstruct.Keys = make(map[string]string) - tstruct.Tags = make(map[string]string) - for devname, netdev := range nodeInfo.NetDevs { - var nd node.NetDevs - tstruct.NetDevs[devname] = &nd - tstruct.NetDevs[devname].Device = netdev.Device.Get() - tstruct.NetDevs[devname].Hwaddr = netdev.Hwaddr.Get() - tstruct.NetDevs[devname].Ipaddr = netdev.Ipaddr.Get() - tstruct.NetDevs[devname].Netmask = netdev.Netmask.Get() - tstruct.NetDevs[devname].Gateway = netdev.Gateway.Get() - tstruct.NetDevs[devname].Type = netdev.Type.Get() - tstruct.NetDevs[devname].OnBoot = netdev.OnBoot.Get() - tstruct.NetDevs[devname].Primary = netdev.Primary.Get() - mask := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4()) - ipaddr := net.ParseIP(netdev.Ipaddr.Get()).To4() - netaddr := net.IPNet{IP: ipaddr, Mask: mask} - netPrefix, _ := net.IPMask(net.ParseIP(netdev.Netmask.Get()).To4()).Size() - tstruct.NetDevs[devname].Prefix = strconv.Itoa(netPrefix) - tstruct.NetDevs[devname].IpCIDR = netaddr.String() - tstruct.NetDevs[devname].Ipaddr6 = netdev.Ipaddr6.Get() - tstruct.NetDevs[devname].Tags = make(map[string]string) - for key, value := range netdev.Tags { - tstruct.NetDevs[devname].Tags[key] = value.Get() - } - } // Backwards compatibility for templates using "Keys" - for keyname, key := range nodeInfo.Tags { - tstruct.Keys[keyname] = key.Get() - } - for keyname, key := range nodeInfo.Tags { - tstruct.Tags[keyname] = key.Get() - } tstruct.AllNodes = allNodes tstruct.Nfs = *controller.Nfs tstruct.Dhcp = *controller.Dhcp @@ -142,6 +83,9 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { dt := time.Now() tstruct.BuildTime = dt.Format("01-02-2006 15:04:05 MST") tstruct.BuildTimeUnix = strconv.FormatInt(dt.Unix(), 10) + tstruct.NodeConf.GetFrom(nodeInfo) + // backward compatibilty + tstruct.Container = tstruct.ContainerName return tstruct From 20fa9d2e2a54eea40c54400d86b9f29c3106cc80 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 11 Aug 2022 16:38:13 +0200 Subject: [PATCH 28/38] fix regression on container import --- internal/pkg/api/container/container.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/pkg/api/container/container.go b/internal/pkg/api/container/container.go index 4c0296b7..bf11302e 100644 --- a/internal/pkg/api/container/container.go +++ b/internal/pkg/api/container/container.go @@ -163,7 +163,8 @@ func ContainerImport(cip *wwapiv1.ContainerImportParameter) (containerName strin wwlog.Error(err.Error()) return } - } else if strings.HasPrefix(cip.Source, "docker://") || strings.HasPrefix(cip.Source, "docker-daemon://") { + } else if strings.HasPrefix(cip.Source, "docker://") || strings.HasPrefix(cip.Source, "docker-daemon://") || + strings.HasPrefix(cip.Source, "file://") || util.IsFile(cip.Source) { var sCtx *types.SystemContext sCtx, err = getSystemContext() if err != nil { From b2dc31e20b5865d520eb4c815e5a2ac2a05d87ef Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 12 Aug 2022 09:29:41 +0200 Subject: [PATCH 29/38] fixed mergin profiles into nodes --- internal/pkg/node/constructors.go | 6 +++--- internal/pkg/node/transformers.go | 36 ++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 8afb52ae..5581a681 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -87,7 +87,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags[keyname] = key delete(node.Keys, keyname) } - n.SetFrom(node) + n.setFrom(node) // backward compatibility n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) n.Ipmi.Netmask.Set(node.IpmiNetmask) @@ -123,7 +123,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // can't call setFrom() as we have to use SetAlt instead of Set for an Entry wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) - config.NodeProfiles[profileName].SetAltFrom(n, profileName) + n.setAltFrom(config.NodeProfiles[profileName], profileName) } ret = append(ret, n) } @@ -155,7 +155,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.Tags[keyname] = key delete(profile.Keys, keyname) } - p.SetFrom(profile) + p.setFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) p.Ipmi.Port.Set(profile.IpmiPort) diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 1428500b..54f2bb05 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -230,7 +230,7 @@ func (nodeConf *NodeConf) GetFrom(nodeInfo NodeInfo) { Populates all fields of NodeInfo with Set from the values of NodeConf. */ -func (node *NodeInfo) SetFrom(n *NodeConf) { +func (node *NodeInfo) setFrom(n *NodeConf) { // get the full memory, taking the shortcut and init Ipmi and Kernel directly if node.Kernel == nil { node.Kernel = new(KernelEntry) @@ -324,12 +324,20 @@ values of NodeConf. The string profileName is used to destermine from which source/NodeInfo the entry came from. */ -func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) { - nodeInfoVal := reflect.ValueOf(&nodeInfo) - nodeInfoType := reflect.TypeOf(&nodeInfo) - profileConfVal := reflect.ValueOf(node) +func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { + // get the full memory, taking the shortcut and init Ipmi and Kernel directly + if node.Kernel == nil { + node.Kernel = new(KernelEntry) + } + if node.Ipmi == nil { + node.Ipmi = new(IpmiEntry) + } + nodeInfoVal := reflect.ValueOf(node) + nodeInfoType := reflect.TypeOf(node) + nodeConfVal := reflect.ValueOf(n) + // now iterate of every field for i := 0; i < nodeInfoType.Elem().NumField(); i++ { - valField := profileConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) + valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) if valField.IsValid() { // found field with same name for Conf and Info if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { @@ -347,6 +355,18 @@ func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) { if nestedVal.IsValid() { if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).SetAlt(nestedVal.String(), profileName) + } else { + confMap := nestedVal.Interface().(map[string]string) + if netstedInfoVal.Elem().Field(j).IsNil() { + newMap := make(map[string]*Entry) + mapPtr := (netstedInfoVal.Elem().Field(j).Addr().Interface()).(*map[string](*Entry)) + *mapPtr = newMap + } + for key, val := range confMap { + var entr Entry + entr.SetAlt(val, profileName) + (netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = &entr + } } } } @@ -364,7 +384,7 @@ func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) { netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) var newNet NetDevEntry newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn'tknow how to do it + // This should be done a bit down, but didn't know how to do it netMap[netName] = &newNet netInfoType := reflect.TypeOf(newNet) netInfoVal := reflect.ValueOf(&newNet) @@ -374,7 +394,7 @@ func (node *NodeConf) SetAltFrom(nodeInfo NodeInfo, profileName string) { if netVal.Type().Kind() == reflect.String { netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normally the map should be created here, but did not manage it + // normaly the map should be created here, but did not manage it for key, val := range (netVal.Interface()).(map[string]string) { var entr Entry entr.SetAlt(val, profileName) From bc647f0bf31d158372bef7025f8354e76cb92bcb Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 12 Aug 2022 10:17:28 +0200 Subject: [PATCH 30/38] Fix IpCIDR for templates --- internal/pkg/overlay/datastructure.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index 60716dc7..dd657657 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -84,6 +84,14 @@ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { tstruct.BuildTime = dt.Format("01-02-2006 15:04:05 MST") tstruct.BuildTimeUnix = strconv.FormatInt(dt.Unix(), 10) tstruct.NodeConf.GetFrom(nodeInfo) + // FIXME: Set ipCIDR address at this point, will fail with + // invalid ipv4 addr + for _, network := range tstruct.NetDevs { + ipCIDR := net.IPNet{ + IP: net.ParseIP(network.Ipaddr), + Mask: net.IPMask(net.ParseIP(network.Netmask))} + network.IpCIDR = ipCIDR.String() + } // backward compatibilty tstruct.Container = tstruct.ContainerName From 02d47e8f113bcda0b2f620d523582522f519fdf1 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 12 Aug 2022 15:36:54 +0200 Subject: [PATCH 31/38] automatic add primary for single netdev --- internal/pkg/node/constructors.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 5581a681..3e8205e7 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -88,6 +88,13 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { delete(node.Keys, keyname) } n.setFrom(node) + // set default/primary network is just one network exist + if len(n.NetDevs) == 1 { + // only way to get the key + for key, _ := range node.NetDevs { + n.NetDevs[key].Primary.SetB(true) + } + } // backward compatibility n.Ipmi.Ipaddr.Set(node.IpmiIpaddr) n.Ipmi.Netmask.Set(node.IpmiNetmask) From f744934122cab0813f19ba1a0ade0d8bd6772e56 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 12 Aug 2022 15:52:38 +0200 Subject: [PATCH 32/38] fixed linting --- internal/pkg/node/constructors.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 3e8205e7..9189168d 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -91,7 +91,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { // set default/primary network is just one network exist if len(n.NetDevs) == 1 { // only way to get the key - for key, _ := range node.NetDevs { + for key := range node.NetDevs { n.NetDevs[key].Primary.SetB(true) } } From 0ca17dd4541145b63bfcdcdc84571feac09e1ee6 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 15 Aug 2022 17:12:36 +0200 Subject: [PATCH 33/38] using functor for Get and GetReal --- internal/pkg/node/constructors.go | 6 +- internal/pkg/node/methods.go | 2 +- internal/pkg/node/transformers.go | 279 ++++++------------------------ 3 files changed, 61 insertions(+), 226 deletions(-) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 9189168d..9afabd2c 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -87,7 +87,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { node.Tags[keyname] = key delete(node.Keys, keyname) } - n.setFrom(node) + n.SetFrom(node) // set default/primary network is just one network exist if len(n.NetDevs) == 1 { // only way to get the key @@ -130,7 +130,7 @@ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { } // can't call setFrom() as we have to use SetAlt instead of Set for an Entry wwlog.Printf(wwlog.VERBOSE, "Merging profile into node: %s <- %s\n", nodename, profileName) - n.setAltFrom(config.NodeProfiles[profileName], profileName) + n.SetAltFrom(config.NodeProfiles[profileName], profileName) } ret = append(ret, n) } @@ -162,7 +162,7 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.Tags[keyname] = key delete(profile.Keys, keyname) } - p.setFrom(profile) + p.SetFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) p.Ipmi.Port.Set(profile.IpmiPort) diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index b9e77ceb..02d26809 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -149,7 +149,7 @@ func (ent *Entry) SetDefaultSlice(val []string) { } /* -Remove a elemnt from a slice +Remove a element from a slice */ func (ent *Entry) SliceRemoveElement(val string) { util.SliceRemoveElement(ent.value, val) diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 54f2bb05..5113d96d 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -11,6 +11,24 @@ the underlying entries using GetReal, so just the explicit values go do disk. */ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { + nodeConf.getterFrom(nodeInfo, (*Entry).GetReal, (*Entry).GetRealSlice) +} + +/* +Populates a NodeConf struct from a NodeInfo, with the combined +values from the underlying entries using Get. +*/ +func (nodeConf *NodeConf) GetFrom(nodeInfo NodeInfo) { + nodeConf.getterFrom(nodeInfo, (*Entry).Get, (*Entry).GetSlice) +} + +/* +Abstract function which populates a NodeConf form the given NodeInfo +via getter functions. +*/ +func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, + getter func(*Entry) string, + getterSlice func(*Entry) []string) { nodeInfoType := reflect.TypeOf(nodeInfo) nodeInfoVal := reflect.ValueOf(nodeInfo) configVal := reflect.ValueOf(nodeConf) @@ -23,16 +41,16 @@ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { if confField.Type().Kind() == reflect.String { newValue := (confField.Addr().Interface()).(*string) entryVal := nodeInfoVal.Field(i).Interface().(Entry) - *newValue = entryVal.GetReal() + *newValue = getter(&entryVal) } else if confField.Type() == reflect.TypeOf([]string{}) { newValue := (confField.Addr().Interface()).(*[]string) entryVal := nodeInfoVal.Field(i).Interface().(Entry) - *newValue = entryVal.GetRealSlice() + *newValue = getterSlice(&entryVal) } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) for key, val := range entryMap { - confField.Interface().(map[string]string)[key] = val.GetReal() + confField.Interface().(map[string]string)[key] = getter(val) } } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { if confField.Addr().Elem().IsZero() { @@ -56,11 +74,11 @@ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { if nestedVal.Type().Kind() == reflect.String { newValue := (nestedVal.Addr().Interface()).(*string) entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) - *newValue = entryVal.GetReal() + *newValue = getter(&entryVal) } else if nestedVal.Type() == reflect.TypeOf([]string{}) { newValue := (nestedVal.Addr().Interface()).(*[]string) entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) - *newValue = entryVal.GetRealSlice() + *newValue = getterSlice(&entryVal) } } else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) { @@ -70,7 +88,7 @@ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { } entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) for key, val := range entryMap { - nestedVal.Interface().(map[string]string)[key] = val.GetReal() + nestedVal.Interface().(map[string]string)[key] = getter(val) } } //} @@ -91,13 +109,10 @@ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { if netVal.IsValid() { if netVal.Type() == reflect.TypeOf(Entry{}) { newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) - *newVal = (netVal.Addr().Interface()).(*Entry).GetReal() + *newVal = getter((netVal.Addr().Interface()).(*Entry)) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.Set(val) - netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + for key, val := range (netVal.Interface()).(map[string]*string) { + *val = getter(netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]) } } } @@ -114,208 +129,18 @@ func (nodeConf *NodeConf) GetRealFrom(nodeInfo NodeInfo) { } } -/* -Populates a NodeConf struct from a NodeInfo, with the combined -values from the underlying entries using Get. -*/ -func (nodeConf *NodeConf) GetFrom(nodeInfo NodeInfo) { - nodeInfoType := reflect.TypeOf(nodeInfo) - nodeInfoVal := reflect.ValueOf(nodeInfo) - configVal := reflect.ValueOf(nodeConf) - // now iterate of every field - for i := 0; i < nodeInfoType.NumField(); i++ { - // found field with same name for Conf and Info - confField := configVal.Elem().FieldByName(nodeInfoType.Field(i).Name) - if confField.IsValid() { - if nodeInfoVal.Field(i).Type() == reflect.TypeOf(Entry{}) { - if confField.Type().Kind() == reflect.String { - newValue := (confField.Addr().Interface()).(*string) - entryVal := nodeInfoVal.Field(i).Interface().(Entry) - *newValue = entryVal.Get() - } else if confField.Type() == reflect.TypeOf([]string{}) { - newValue := (confField.Addr().Interface()).(*[]string) - entryVal := nodeInfoVal.Field(i).Interface().(Entry) - *newValue = entryVal.GetSlice() - } - } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { - if confField.IsNil() { - confFieldPtr := confField.Addr().Interface().(*map[string]string) - *confFieldPtr = make(map[string]string) - } - entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) - for key, val := range entryMap { - confField.Interface().(map[string]string)[key] = val.Get() - } - } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { - if confField.Addr().Elem().IsZero() { - switch confField.Addr().Elem().Type() { - case reflect.TypeOf((*KernelConf)(nil)): - var newConf KernelConf - newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**KernelConf) - *newConfPtr = &newConf - case reflect.TypeOf((*IpmiConf)(nil)): - var newConf IpmiConf - newConfPtr := (confField.Addr().Elem().Addr().Interface()).(**IpmiConf) - *newConfPtr = &newConf - } - } - nestedInfoType := reflect.TypeOf(nodeInfoVal.Field(i).Interface()) - nestedInfoVal := reflect.ValueOf(nodeInfoVal.Field(i).Interface()) - nestedConfVal := reflect.ValueOf(confField.Interface()) - for j := 0; j < nestedInfoType.Elem().NumField(); j++ { - nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) - if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - if nestedVal.Type().Kind() == reflect.String { - newValue := (nestedVal.Addr().Interface()).(*string) - entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) - *newValue = entryVal.Get() - } else if nestedVal.Type() == reflect.TypeOf([]string{}) { - newValue := (nestedVal.Addr().Interface()).(*[]string) - entryVal := nestedInfoVal.Elem().Field(j).Interface().(Entry) - *newValue = entryVal.GetSlice() - - } - } else if nestedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(map[string]*Entry{}) { - if nestedVal.IsNil() { - mapPtr := nestedVal.Addr().Interface().(*map[string]string) - *mapPtr = make(map[string]string) - } - entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) - for key, val := range entryMap { - nestedVal.Interface().(map[string]string)[key] = val.Get() - } - } - } - } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { - nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) - for netName, netVal := range nestedMap { - netValsType := reflect.ValueOf(netVal) - if confField.IsNil() { - netMapPtr := confField.Addr().Interface().(*map[string](*NetDevs)) - *netMapPtr = make(map[string](*NetDevs)) - } - netMap := confField.Interface().(map[string](*NetDevs)) - var newNet NetDevs - newNet.Tags = make(map[string]string) - netMap[netName] = &newNet - netConfType := reflect.TypeOf(newNet) - netConfVal := reflect.ValueOf(&newNet) - for j := 0; j < netConfType.NumField(); j++ { - netVal := netValsType.Elem().FieldByName(netConfType.Field(j).Name) - if netVal.IsValid() { - if netVal.Type() == reflect.TypeOf(Entry{}) { - newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) - *newVal = (netVal.Addr().Interface()).(*Entry).Get() - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.Set(val) - netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr - } - } - } - - } - } - } - } /*else { - // NodeInfo has the Id field, nodeConf not - fmt.Println("INVALID", nodeInfoType.Field(i).Name) - } */ - } -} - /* Populates all fields of NodeInfo with Set from the values of NodeConf. */ -func (node *NodeInfo) setFrom(n *NodeConf) { - // get the full memory, taking the shortcut and init Ipmi and Kernel directly - if node.Kernel == nil { - node.Kernel = new(KernelEntry) +func (node *NodeInfo) SetFrom(n *NodeConf) { + setWrap := func(entr *Entry, val string, nameArg string) { + entr.Set(val) } - if node.Ipmi == nil { - node.Ipmi = new(IpmiEntry) - } - nodeInfoVal := reflect.ValueOf(node) - nodeInfoType := reflect.TypeOf(node) - nodeConfVal := reflect.ValueOf(n) - // now iterate of every field - for i := 0; i < nodeInfoType.Elem().NumField(); i++ { - valField := nodeConfVal.Elem().FieldByName(nodeInfoType.Elem().Field(i).Name) - if valField.IsValid() { - // found field with same name for Conf and Info - if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { - if valField.Type().Kind() == reflect.String { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).Set(valField.String()) - } else if valField.Type() == reflect.TypeOf([]string{}) { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetSlice(valField.Interface().([]string)) - } - } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { - nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) - netstedInfoVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) - nestedConfVal := reflect.ValueOf(valField.Interface()) - for j := 0; j < nestedInfoType.Elem().NumField(); j++ { - nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) - if nestedVal.IsValid() { - if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).Set(nestedVal.String()) - } else { - confMap := nestedVal.Interface().(map[string]string) - if netstedInfoVal.Elem().Field(j).IsNil() { - newMap := make(map[string]*Entry) - mapPtr := (netstedInfoVal.Elem().Field(j).Addr().Interface()).(*map[string](*Entry)) - *mapPtr = newMap - } - for key, val := range confMap { - var entr Entry - entr.Set(val) - (netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = &entr - } - } - } - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { - confMap := valField.Interface().(map[string]string) - for key, val := range confMap { - var entr Entry - entr.Set(val) - (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr - } - } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { - netValsType := reflect.ValueOf(netVals) - netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn't know how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) - for j := 0; j < netInfoType.NumField(); j++ { - netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) - if netVal.IsValid() { - if netVal.Type().Kind() == reflect.String { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).Set(netVal.String()) - if netInfoType.Field(j).Name == "Netmask" { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetDefault("255.255.255.0") - } - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it - for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.Set(val) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr - } - } - } - } - } - } - } + setSliceWrap := func(entr *Entry, val []string, nameArg string) { + entr.SetSlice(val) } + node.setterFrom(n, "", setWrap, setSliceWrap) } /* @@ -324,7 +149,17 @@ values of NodeConf. The string profileName is used to destermine from which source/NodeInfo the entry came from. */ -func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { +func (node *NodeInfo) SetAltFrom(n *NodeConf, profileName string) { + node.setterFrom(n, profileName, (*Entry).SetAlt, (*Entry).SetAltSlice) +} + +/* +Abstract function which populates a NodeInfo from a NodeConf via +setter functionns. +*/ +func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string, + setter func(*Entry, string, string), + setterSlice func(*Entry, []string, string)) { // get the full memory, taking the shortcut and init Ipmi and Kernel directly if node.Kernel == nil { node.Kernel = new(KernelEntry) @@ -342,9 +177,9 @@ func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { // found field with same name for Conf and Info if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(Entry{}) { if valField.Type().Kind() == reflect.String { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAlt(valField.String(), profileName) + setter(nodeInfoVal.Elem().Field(i).Addr().Interface().(*Entry), valField.String(), nameArg) } else if valField.Type() == reflect.TypeOf([]string{}) { - (nodeInfoVal.Elem().Field(i).Addr().Interface()).(*Entry).SetAltSlice(valField.Interface().([]string), profileName) + setterSlice(nodeInfoVal.Elem().Field(i).Addr().Interface().(*Entry), valField.Interface().([]string), nameArg) } } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr && !valField.IsZero() { nestedInfoType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) @@ -354,7 +189,7 @@ func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { nestedVal := nestedConfVal.Elem().FieldByName(nestedInfoType.Elem().Field(j).Name) if nestedVal.IsValid() { if netstedInfoVal.Elem().Field(j).Type() == reflect.TypeOf(Entry{}) { - netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry).SetAlt(nestedVal.String(), profileName) + setter(netstedInfoVal.Elem().Field(j).Addr().Interface().(*Entry), nestedVal.String(), nameArg) } else { confMap := nestedVal.Interface().(map[string]string) if netstedInfoVal.Elem().Field(j).IsNil() { @@ -363,9 +198,9 @@ func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { *mapPtr = newMap } for key, val := range confMap { - var entr Entry - entr.SetAlt(val, profileName) - (netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = &entr + entr := new(Entry) + setter(entr, val, nameArg) + (netstedInfoVal.Elem().Field(j).Interface()).(map[string](*Entry))[key] = entr } } } @@ -373,9 +208,9 @@ func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*Entry)(nil)) { confMap := valField.Interface().(map[string]string) for key, val := range confMap { - var entr Entry - entr.SetAlt(val, profileName) - (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = &entr + entr := new(Entry) + setter(entr, val, nameArg) + (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = entr } } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { nestedMap := valField.Interface().(map[string](*NetDevs)) @@ -392,13 +227,13 @@ func (node *NodeInfo) setAltFrom(n *NodeConf, profileName string) { netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) if netVal.IsValid() { if netVal.Type().Kind() == reflect.String { - netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)).SetAlt(netVal.String(), profileName) + setter(netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)), netVal.String(), nameArg) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { // normaly the map should be created here, but did not manage it for key, val := range (netVal.Interface()).(map[string]string) { - var entr Entry - entr.SetAlt(val, profileName) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = &entr + entr := new(Entry) + setter(entr, val, nameArg) + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = entr } } } From 2016588f36b97cf5bb8f3b0af36c990d1bc73ca6 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 16 Aug 2022 16:49:02 +0200 Subject: [PATCH 34/38] fallten the Nodes and NodeProfile before write --- internal/pkg/node/modifiers.go | 12 +++++++-- internal/pkg/node/transformers.go | 44 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index a89b06de..b54e322b 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -112,9 +112,17 @@ func (config *NodeYaml) ProfileUpdate(profile NodeInfo) error { * PERSISTENCE * ****/ - +/* +Write the the NodeYaml to disk. +*/ func (config *NodeYaml) Persist() error { - + // flatten out profiles and nodes + for _, val := range config.NodeProfiles { + val.Flatten() + } + for _, val := range config.Nodes { + val.Flatten() + } out, err := yaml.Marshal(config) if err != nil { return err diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 5113d96d..aac784b3 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -95,6 +95,10 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { + if confField.IsNil() { + netMapPtr := confField.Addr().Interface().(*map[string](*NetDevs)) + *netMapPtr = make(map[string](*NetDevs)) + } nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) for netName, netVal := range nestedMap { netValsType := reflect.ValueOf(netVal) @@ -243,3 +247,43 @@ func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string, } } } + +/* +Flattens out a NodeConf, which means if there are no explicit values in *IpmiConf +or *KernelConf, these pointer will set to nil. This will remove something like +ipmi: {} from nodes.conf +*/ +func (info *NodeConf) Flatten() { + confType := reflect.TypeOf(info) + confVal := reflect.ValueOf(info) + for j := 0; j < confType.Elem().NumField(); j++ { + if confVal.Elem().Field(j).Type().Kind() == reflect.Ptr && !confVal.Elem().Field(j).IsNil() { + // iterate now over the ptr fields + setToNil := true + nestedType := reflect.TypeOf(confVal.Elem().Field(j).Interface()) + nestedVal := reflect.ValueOf(confVal.Elem().Field(j).Interface()) + for i := 0; i < nestedType.Elem().NumField(); i++ { + if nestedType.Elem().Field(i).Type.Kind() == reflect.String && + nestedVal.Elem().Field(i).Interface().(string) != "" { + setToNil = false + } else if nestedType.Elem().Field(i).Type == reflect.TypeOf([]string{}) && + len(nestedVal.Elem().Field(i).Interface().([]string)) != 0 { + setToNil = false + } else if nestedType.Elem().Field(i).Type == reflect.TypeOf(map[string]string{}) && + len(nestedVal.Elem().Field(i).Interface().(map[string]string)) != 0 { + setToNil = false + } + } + if setToNil { + switch confType.Elem().Field(j).Type { + case reflect.TypeOf((*IpmiConf)(nil)): + ptr := confVal.Elem().Field(j).Addr().Interface().(**IpmiConf) + *ptr = (*IpmiConf)(nil) + case reflect.TypeOf((*KernelConf)(nil)): + ptr := confVal.Elem().Field(j).Addr().Interface().(**KernelConf) + *ptr = (*KernelConf)(nil) + } + } + } + } +} From b485ea999f9c89ede0884e429112dd9f16abacd1 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 17 Aug 2022 16:41:20 +0200 Subject: [PATCH 35/38] removed optionStrMap in favor of NodeConf openStrMap is a map[string]string which is sent arround. This is now done by using a unmarshalled NodeConf instead. --- internal/app/api/wwapid/wwapid.go | 11 +- internal/app/wwctl/node/add/main.go | 28 +- internal/app/wwctl/node/add/root.go | 10 +- internal/app/wwctl/node/list/main.go | 171 +---- internal/app/wwctl/node/set/main.go | 35 +- internal/app/wwctl/node/set/root.go | 11 +- internal/app/wwctl/profile/add/main.go | 35 +- internal/app/wwctl/profile/add/root.go | 10 +- internal/app/wwctl/profile/set/main.go | 32 +- internal/app/wwctl/profile/set/root.go | 11 +- .../pkg/api/apiconfig/container/container.go | 2 +- internal/pkg/api/node/list.go | 178 +++++ internal/pkg/api/node/node.go | 85 +-- internal/pkg/api/profile/profile.go | 18 +- internal/pkg/api/routes/v1/routes.proto | 21 +- internal/pkg/api/routes/wwapiv1/routes.pb.go | 653 ++++++++++------- internal/pkg/node/methods.go | 654 +++++++++--------- internal/pkg/node/transformers.go | 71 ++ 18 files changed, 1161 insertions(+), 875 deletions(-) create mode 100644 internal/pkg/api/node/list.go diff --git a/internal/app/api/wwapid/wwapid.go b/internal/app/api/wwapid/wwapid.go index 0d19e29d..7d6a1de4 100644 --- a/internal/app/api/wwapid/wwapid.go +++ b/internal/app/api/wwapid/wwapid.go @@ -331,11 +331,12 @@ func (s *apiServer) Version(ctx context.Context, request *emptypb.Empty) (respon func (s *apiServer) nodeListInternal(nodeNames []string) (response *wwapiv1.NodeListResponse, err error) { var nodes []*wwapiv1.NodeInfo - nodes, err = apinode.NodeList(nodeNames) - if err != nil { - return - } - + /* + nodes, err = apinode.NodeList(nodeNames) + if err != nil { + return + } + */ response = &wwapiv1.NodeListResponse{ Nodes: nodes, } diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 2b63ad94..4837809d 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -1,26 +1,34 @@ package add import ( - "errors" + "os" + + "gopkg.in/yaml.v2" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { - OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - if netWithoutName { - return errors.New("a netname must be given for any network related configuration") - } - realMap := make(map[string]string) + // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + // if netWithoutName { + // return errors.New("a netname must be given for any network related configuration") + // } + // realMap := make(map[string]string) - for key, val := range OptionStrMap { - realMap[key] = *val + // for key, val := range OptionStrMap { + // realMap[key] = *val + // } + buffer, err := yaml.Marshal(nodeConf) + if err != nil { + wwlog.Error("Cant marshall nodeInfo", err) + os.Exit(1) } set := wwapiv1.NodeAddParameter{ - OptionsStrMap: realMap, - NodeNames: args, + NodeConfYaml: string(buffer[:]), + NodeNames: args, } return apinode.NodeAdd(&set) diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index b0e6af19..18dee9ae 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -19,16 +19,12 @@ var ( RunE: CobraRunE, Args: cobra.MinimumNArgs(1), } - OptionStrMap map[string]*string + nodeConf node.NodeConf ) func init() { - // init empty helper structs, so that we know what's inside - myBase := node.CobraCommand{Command: baseCmd} - var emptyNodeConf node.NodeConf - emptyNodeConf.Kernel = new(node.KernelConf) - emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) + nodeConf := node.NewConf() + nodeConf.CreateFlags(baseCmd, []string{}) // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() diff --git a/internal/app/wwctl/node/list/main.go b/internal/app/wwctl/node/list/main.go index 1a5d8515..0bbad793 100644 --- a/internal/app/wwctl/node/list/main.go +++ b/internal/app/wwctl/node/list/main.go @@ -2,174 +2,29 @@ package list import ( "fmt" - "sort" - "strings" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - - nodeInfo, err := apinode.NodeList(args) - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) - return + req := wwapiv1.GetNodeList{ + Nodes: args, + Type: wwapiv1.GetNodeList_Simple, } - nodeLopt := node.GetloptMap(node.NodeConf{}) - ipmiLopt := node.GetloptMap(node.IpmiConf{}) - kernelLopt := node.GetloptMap(node.KernelConf{}) - netdevLopt := node.GetloptMap(node.NetDevs{}) if ShowAll { - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := `UNKNOWN` - if _, ok := ni.Fields["Id"]; ok { - nodeName = ni.Fields["Id"].Print - } - var nodeconfkeys, ipmiconfkeys, kernelconfkeys, netdevkys []string - for k := range ni.Fields { - subkeys := strings.Split(k, ":") - if len(subkeys) == 1 { - nodeconfkeys = append(nodeconfkeys, k) - } - if len(subkeys) >= 2 { - switch subkeys[0] { - case "IpmiEntry": - ipmiconfkeys = append(ipmiconfkeys, k) - case "KernelEntry": - kernelconfkeys = append(kernelconfkeys, k) - case "NetDevEntry": - netdevkys = append(netdevkys, k) - case "key": - nodeconfkeys = append(nodeconfkeys, k) - } - } - } - sort.Strings(nodeconfkeys) - sort.Strings(ipmiconfkeys) - sort.Strings(kernelconfkeys) - sort.Strings(netdevkys) - keyssorted := append(nodeconfkeys, kernelconfkeys...) - keyssorted = append(keyssorted, ipmiconfkeys...) - keyssorted = append(keyssorted, netdevkys...) - fmt.Printf("################################################################################\n") - fmt.Printf("%-20s %-18s %-12s %s\n", "NODE", "FIELD", "PROFILE", "VALUE") - for _, keys := range keyssorted { - fieldName := keys - subkeys := strings.Split(keys, ":") - if len(subkeys) == 1 { - if subkeys[0] == "Id" { - continue - } - fieldName = nodeLopt[subkeys[0]] - } - if len(subkeys) >= 2 { - switch subkeys[0] { - case "key": - fieldName = "tag:" + subkeys[1] - case "IpmiEntry": - fieldName = ipmiLopt[subkeys[1]] - if len(subkeys) == 3 { - fieldName = "ipmikey:" + subkeys[2] - } - case "KernelEntry": - fieldName = kernelLopt[subkeys[1]] - case "NetDevEntry": - if len(subkeys) == 3 { - fieldName = subkeys[1] + ":" + netdevLopt[subkeys[2]] - } else if len(subkeys) == 4 { - fieldName = subkeys[1] + ":keys:" + subkeys[3] - } - } - } - fmt.Printf("%-20s %-18s %-12s %s\n", nodeName, fieldName, ni.Fields[keys].Source, ni.Fields[keys].Print) - } - } - } else if ShowNet { - fmt.Printf("%-22s %-8s %-18s %-15s %-15s %-15s\n", "NODE NAME", "NAME", "HWADDR", "IPADDR", "GATEWAY", "DEVICE") - fmt.Println(strings.Repeat("=", 90)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := `UNKNOWN` - if _, ok := ni.Fields["Id"]; ok { - nodeName = ni.Fields["Id"].Print - } - netNames := make(map[string]bool) - for k := range ni.Fields { - subkeys := strings.Split(k, ":") - if len(subkeys) == 3 && subkeys[0] == "NetDevEntry" { - netNames[subkeys[1]] = true - } - } - if len(netNames) > 0 { - for name := range netNames { - fmt.Printf("%-22s %-8s %-18s %-15s %-15s %-15s\n", nodeName, name, - ni.Fields["NetDevEntry:"+name+":Hwaddr"].Print, - ni.Fields["NetDevEntry:"+name+":Ipaddr"].Print, - ni.Fields["NetDevEntry:"+name+":Gateway"].Print, - ni.Fields["NetDevEntry:"+name+":Device"].Print) - } - } else { - fmt.Printf("%-22s %-6s %-18s %-15s %-15s\n", nodeName, "--", "--", "--", "--") - } - } + req.Type = wwapiv1.GetNodeList_All } else if ShowIpmi { - fmt.Printf("%-22s %-16s %-10s %-20s %-14s\n", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI INTERFACE") - fmt.Println(strings.Repeat("=", 98)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := `UNKNOWN` - if _, ok := ni.Fields["Id"]; ok { - nodeName = ni.Fields["Id"].Print - } - fmt.Printf("%-22s %-16s %-10s %-20s %-14s\n", nodeName, - ni.Fields["IpmiEntry:Ipaddr"].Print, - ni.Fields["IpmiEntry:Port"].Print, - ni.Fields["IpmiEntry:UserName"].Print, - ni.Fields["IpmiEntry:Interface"].Print) - } - + req.Type = wwapiv1.GetNodeList_Ipmi + } else if ShowNet { + req.Type = wwapiv1.GetNodeList_Network } else if ShowLong { - fmt.Printf("%-22s %-16s %-16s %s\n", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)") - fmt.Println(strings.Repeat("=", 85)) - - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := `UNKNOWN` - if _, ok := ni.Fields["Id"]; ok { - nodeName = ni.Fields["Id"].Print - } - fmt.Printf("%-22s %-16s %-16s %s\n", nodeName, - ni.Fields["KernelEntry:Override"].Print, - ni.Fields["ContainerName"].Print, - ni.Fields["SystemOverlay"].Print+"/"+ni.Fields["RuntimeOverlay"].Print) - } - - } else { - fmt.Printf("%-22s %-26s %s\n", "NODE NAME", "PROFILES", "NETWORK") - fmt.Println(strings.Repeat("=", 80)) - for i := 0; i < len(nodeInfo); i++ { - ni := nodeInfo[i] - nodeName := `UNKNOWN` - if _, ok := ni.Fields["Id"]; ok { - nodeName = ni.Fields["Id"].Print - } - netNameMap := make(map[string]bool) - var netNames []string - for k := range ni.Fields { - subkeys := strings.Split(k, ":") - if len(subkeys) == 3 && subkeys[0] == "NetDevEntry" && !netNameMap[subkeys[1]] { - netNameMap[subkeys[1]] = true - netNames = append(netNames, subkeys[1]) - } - } - fmt.Printf("%-22s %-26s %s\n", nodeName, ni.Fields["Profiles"].Print, strings.Join(netNames, ", ")) - } + req.Type = wwapiv1.GetNodeList_Long + } + nodeInfo, err := apinode.NodeList(&req) + for _, str := range nodeInfo.Output { + fmt.Printf("%s\n", str) } return } diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index 83187b24..c7c6be47 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -1,32 +1,39 @@ package set import ( - "errors" "fmt" + "os" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/api/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" + "gopkg.in/yaml.v2" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - if netWithoutName { - return errors.New("a netname must be given for any network related configuration") - } - realMap := make(map[string]string) + // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + // if netWithoutName { + // return errors.New("a netname must be given for any network related configuration") + // } + // realMap := make(map[string]string) - for key, val := range OptionStrMap { - realMap[key] = *val + // for key, val := range OptionStrMap { + // realMap[key] = *val + // } + buffer, err := yaml.Marshal(nodeConf) + if err != nil { + wwlog.Error("Cant marshall nodeInfo", err) + os.Exit(1) } - set := wwapiv1.NodeSetParameter{ - OptionsStrMap: realMap, - NetdevDelete: SetNetDevDel, - AllNodes: SetNodeAll, - Force: SetForce, - NodeNames: args, + NodeConfYaml: string(buffer[:]), + + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, } if !SetYes { diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 32c58292..3e0a4675 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -36,17 +36,12 @@ var ( SetNodeAll bool SetYes bool SetForce bool - OptionStrMap map[string]*string + nodeConf node.NodeConf ) func init() { - // init empty helper structs, so that we know what's inside - myBase := node.CobraCommand{Command: baseCmd} - var emptyNodeConf node.NodeConf - emptyNodeConf.Kernel = new(node.KernelConf) - emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf, []string{}) - + nodeConf := node.NewConf() + nodeConf.CreateFlags(baseCmd, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index 6871520b..3e689a3d 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -2,33 +2,38 @@ package add import ( "fmt" + "os" - apinode "github.com/hpcng/warewulf/internal/pkg/api/node" apiprofile "github.com/hpcng/warewulf/internal/pkg/api/profile" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "gopkg.in/yaml.v2" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/api/util" - "github.com/pkg/errors" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - if netWithoutName { - return errors.New("a netname must be given for any network related configuration") - } - realMap := make(map[string]string) + // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + // if netWithoutName { + // return errors.New("a netname must be given for any network related configuration") + // } + // realMap := make(map[string]string) - for key, val := range OptionStrMap { - realMap[key] = *val + // for key, val := range OptionStrMap { + // realMap[key] = *val + // } + buffer, err := yaml.Marshal(profileConf) + if err != nil { + wwlog.Error("Cant marshall nodeInfo", err) + os.Exit(1) } - set := wwapiv1.NodeSetParameter{ - OptionsStrMap: realMap, - NetdevDelete: SetNetDevDel, - AllNodes: SetNodeAll, - Force: SetForce, - NodeNames: args, + NodeConfYaml: string(buffer[:]), + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, } if !SetYes { diff --git a/internal/app/wwctl/profile/add/root.go b/internal/app/wwctl/profile/add/root.go index 7380dec4..a7e60b26 100644 --- a/internal/app/wwctl/profile/add/root.go +++ b/internal/app/wwctl/profile/add/root.go @@ -23,17 +23,13 @@ var ( SetNodeAll bool SetYes bool SetForce bool - OptionStrMap map[string]*string + profileConf node.NodeConf ) // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { - // init empty helper structs, so that we know what's inside - myBase := node.CobraCommand{Command: baseCmd} - var emptyNodeConf node.NodeConf - emptyNodeConf.Kernel = new(node.KernelConf) - emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf, + profileConf = node.NewConf() + profileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index b177a6b5..43e0446a 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -2,32 +2,32 @@ package set import ( "fmt" + "os" - apinode "github.com/hpcng/warewulf/internal/pkg/api/node" apiprofile "github.com/hpcng/warewulf/internal/pkg/api/profile" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/api/util" - "github.com/pkg/errors" + "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" + "gopkg.in/yaml.v2" ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - if netWithoutName { - return errors.New("a netname must be given for any network related configuration") + // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) + // if netWithoutName { + // return errors.New("a netname must be given for any network related configuration") + // } + buffer, err := yaml.Marshal(profileConf) + if err != nil { + wwlog.Error("Cant marshall nodeInfo", err) + os.Exit(1) } - realMap := make(map[string]string) - - for key, val := range OptionStrMap { - realMap[key] = *val - } - set := wwapiv1.NodeSetParameter{ - OptionsStrMap: realMap, - NetdevDelete: SetNetDevDel, - AllNodes: SetNodeAll, - Force: SetForce, - NodeNames: args, + NodeConfYaml: string(buffer[:]), + NetdevDelete: SetNetDevDel, + AllNodes: SetNodeAll, + Force: SetForce, + NodeNames: args, } if !SetYes { diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 9bb96d6f..577e0312 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -36,18 +36,13 @@ var ( SetNodeAll bool SetYes bool SetForce bool - OptionStrMap map[string]*string + profileConf node.NodeConf ) func init() { - // init empty helper structs, so that we know what's inside - myBase := node.CobraCommand{Command: baseCmd} - var emptyNodeConf node.NodeConf - emptyNodeConf.Kernel = new(node.KernelConf) - emptyNodeConf.Ipmi = new(node.IpmiConf) - OptionStrMap = myBase.CreateFlags(emptyNodeConf, + profileConf = node.NewConf() + profileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) - baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/api/apiconfig/container/container.go b/internal/pkg/api/apiconfig/container/container.go index e4242e7d..d0e4ab3a 100644 --- a/internal/pkg/api/apiconfig/container/container.go +++ b/internal/pkg/api/apiconfig/container/container.go @@ -376,4 +376,4 @@ func getSystemContext() (sCtx *types.SystemContext, err error) { } return sCtx, nil -} \ No newline at end of file +} diff --git a/internal/pkg/api/node/list.go b/internal/pkg/api/node/list.go new file mode 100644 index 00000000..f31b8604 --- /dev/null +++ b/internal/pkg/api/node/list.go @@ -0,0 +1,178 @@ +package apinode + +import ( + "fmt" + "reflect" + "sort" + "strings" + + "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/pkg/hostlist" +) + +/* +NodeList lists all to none of the nodes managed by Warewulf. Returns +a formated string slice, with each line as separate string +*/ +func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err error) { + // nil is okay for nodeNames + nodeDB, err := node.New() + if err != nil { + return + } + nodes, err := nodeDB.FindAllNodes() + if err != nil { + return + } + nodeGet.Nodes = hostlist.Expand(nodeGet.Nodes) + sort.Strings(nodeGet.Nodes) + if nodeGet.Type == wwapiv1.GetNodeList_Simple { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-26s %s", "NODE NAME", "PROFILES", "NETWORK")) + nodeList.Output = append(nodeList.Output, (strings.Repeat("=", 80))) + for _, n := range node.FilterByName(nodes, nodeGet.Nodes) { + var netNames []string + for k := range n.NetDevs { + netNames = append(netNames, k) + } + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-26s %s", n.Id.Print(), n.Profiles.Print(), strings.Join(netNames, ", "))) + } + } else if nodeGet.Type == wwapiv1.GetNodeList_Network { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-8s %-18s %-15s %-15s %-15s", "NODE NAME", "NAME", "HWADDR", "IPADDR", "GATEWAY", "DEVICE"), + strings.Repeat("=", 90)) + for _, n := range node.FilterByName(nodes, nodeGet.Nodes) { + if len(n.NetDevs) > 0 { + for name := range n.NetDevs { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-8s %-18s %-15s %-15s %-15s", n.Id.Print(), name, + n.NetDevs[name].Hwaddr.Print(), + n.NetDevs[name].Ipaddr.Print(), + n.NetDevs[name].Gateway.Print(), + n.NetDevs[name].Device.Print())) + } + } else { + fmt.Printf("%-22s %-6s %-18s %-15s %-15s", n.Id.Print(), "--", "--", "--", "--") + } + } + } else if nodeGet.Type == wwapiv1.GetNodeList_Ipmi { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-16s %-10s %-20s %-14s", "NODE NAME", "IPMI IPADDR", "IPMI PORT", "IPMI USERNAME", "IPMI INTERFACE"), + strings.Repeat("=", 98)) + for _, n := range node.FilterByName(nodes, nodeGet.Nodes) { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-16s %-10s %-20s %-14s", n.Id.Print(), + n.Ipmi.Ipaddr.Print(), + n.Ipmi.Port.Print(), + n.Ipmi.UserName.Print(), + n.Ipmi.Interface.Print())) + } + } else if nodeGet.Type == wwapiv1.GetNodeList_Long { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-16s %-16s %s", "NODE NAME", "KERNEL OVERRIDE", "CONTAINER", "OVERLAYS (S/R)"), + strings.Repeat("=", 85)) + for _, n := range node.FilterByName(nodes, nodeGet.Nodes) { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-22s %-16s %-16s %s", n.Id.Print(), + n.Kernel.Override.Print(), + n.ContainerName.Print(), + n.SystemOverlay.Print()+"/"+n.RuntimeOverlay.Print())) + } + } else if nodeGet.Type == wwapiv1.GetNodeList_All { + for _, n := range node.FilterByName(nodes, nodeGet.Nodes) { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", "NODE", "FIELD", "PROFILE", "VALUE"), strings.Repeat("=", 85)) + nType := reflect.TypeOf(n) + nVal := reflect.ValueOf(n) + nConfType := reflect.TypeOf(node.NodeConf{}) + for i := 0; i < nType.NumField(); i++ { + var fieldName, fieldSource, fieldVal string + nConfField, ok := nConfType.FieldByName(nType.Field(i).Name) + if ok { + fieldName = nConfField.Tag.Get("lopt") + } else { + fieldName = nType.Field(i).Name + } + if nType.Field(i).Type == reflect.TypeOf(node.Entry{}) { + entr := nVal.Field(i).Interface().(node.Entry) + fieldSource = entr.Source() + fieldVal = entr.Print() + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + } else if nType.Field(i).Type == reflect.TypeOf(map[string]*node.Entry{}) { + entrMap := nVal.Field(i).Interface().(map[string]*node.Entry) + for key, val := range entrMap { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), key, val.Source(), val.Print())) + } + } else if nType.Field(i).Type == reflect.TypeOf(map[string]*node.NetDevEntry{}) { + netDevs := nVal.Field(i).Interface().(map[string]*node.NetDevEntry) + for netName, netWork := range netDevs { + netInfoType := reflect.TypeOf(*netWork) + netInfoVal := reflect.ValueOf(*netWork) + netConfType := reflect.TypeOf(node.NetDevs{}) + for j := 0; j < netInfoType.NumField(); j++ { + netConfField, ok := netConfType.FieldByName(netInfoType.Field(j).Name) + if ok { + fieldName = netName + ":" + netConfField.Tag.Get("lopt") + } else { + fieldName = netName + ":" + netInfoType.Field(j).Name + } + if netInfoType.Field(j).Type == reflect.TypeOf(node.Entry{}) { + entr := netInfoVal.Field(j).Interface().(node.Entry) + fieldSource = entr.Source() + fieldVal = entr.Print() + // only print fields with lopt + if netConfField.Tag.Get("lopt") != "" { + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + } + } else if netInfoType.Field(j).Type == reflect.TypeOf(map[string]*node.Entry{}) { + for key, val := range netInfoVal.Field(j).Interface().(map[string]*node.Entry) { + fieldName = fieldName + ":" + key + fieldSource = val.Source() + fieldVal = val.Print() + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + } + } + + } + } + } else if nType.Field(i).Type.Kind() == reflect.Ptr { + nestInfoType := reflect.TypeOf(nVal.Field(i).Interface()) + nestInfoVal := reflect.ValueOf(nVal.Field(i).Interface()) + // nestConfType := reflect.TypeOf(nConfField.Type.Elem().FieldByName()) + for j := 0; j < nestInfoType.Elem().NumField(); j++ { + nestConfField, ok := nConfField.Type.Elem().FieldByName(nestInfoType.Elem().Field(j).Name) + if ok { + fieldName = nestConfField.Tag.Get("lopt") + } else { + fieldName = nestInfoType.Elem().Field(j).Name + } + if nestInfoType.Elem().Field(j).Type == reflect.TypeOf(node.Entry{}) { + entr := nestInfoVal.Elem().Field(j).Interface().(node.Entry) + fieldSource = entr.Source() + fieldVal = entr.Print() + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + } else if nestInfoType.Elem().Field(j).Type == reflect.TypeOf(map[string]*node.Entry{}) { + for key, val := range nestInfoVal.Elem().Field(j).Interface().(map[string]*node.Entry) { + fieldName = fieldName + ":" + key + fieldSource = val.Source() + fieldVal = val.Print() + nodeList.Output = append(nodeList.Output, + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + } + } + } + } + + } + } + + } + return +} diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index df1c64f3..e3c7d890 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "os" - "sort" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "github.com/hpcng/warewulf/internal/pkg/node" @@ -14,6 +13,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/hpcng/warewulf/pkg/hostlist" "github.com/pkg/errors" + "gopkg.in/yaml.v2" "github.com/hpcng/warewulf/internal/pkg/warewulfd" ) @@ -31,6 +31,11 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { } node_args := hostlist.Expand(nap.NodeNames) + var nodeConf node.NodeConf + err = yaml.Unmarshal([]byte(nap.NodeConfYaml), &nodeConf) + if err != nil { + return errors.Wrap(err, "Failed to decode nodeConf") + } for _, a := range node_args { var n node.NodeInfo @@ -39,29 +44,24 @@ func NodeAdd(nap *wwapiv1.NodeAddParameter) (err error) { return errors.Wrap(err, "failed to add node") } wwlog.Printf(wwlog.INFO, "Added node: %s\n", a) - netName := nap.OptionsStrMap["NetDevs"] - if nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"] != "" { + var netName string + for netName = range nodeConf.NetDevs { + // as map should only have key this should give is the first and + // only key + } + // setting node from the received yaml + n.SetFrom(&nodeConf) + if netName != "" && nodeConf.NetDevs[netName].Ipaddr != "" { // if more nodes are added increment IPv4 address - nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"], 1) + nodeConf.NetDevs[netName].Ipaddr = util.IncrementIPv4(nodeConf.NetDevs[netName].Ipaddr, 1) - wwlog.Verbose("Node: %s:%s, Setting Ipaddr to: %s\n", - n.Id.Get(), nap.OptionsStrMap["NetDevs"], nap.OptionsStrMap["NetDevs."+netName+".Ipaddr"]) + wwlog.Verbose("Incremented IP addr to %s\n", nodeConf.NetDevs[netName].Ipaddr) } - if nap.OptionsStrMap["Ipmi.Ipaddr"] != "" { + if nodeConf.Ipmi != nil && nodeConf.Ipmi.Ipaddr != "" { // if more nodes are added increment IPv4 address - nap.OptionsStrMap["Ipmi.Ipaddr"] = util.IncrementIPv4(nap.OptionsStrMap["Ipmi.Ipaddr"], 1) - - wwlog.Verbose("Node: %s:, Setting IPMIIpaddr to: %s\n", - n.Id.Get(), nap.OptionsStrMap["Ipmi.Ipaddr"]) + nodeConf.Ipmi.Ipaddr = util.IncrementIPv4(nodeConf.Ipmi.Ipaddr, 1) + wwlog.Verbose("Incremented IP addr to %s\n", nodeConf.Ipmi.Ipaddr) } - // Now set all the rest - for key, val := range nap.OptionsStrMap { - if val != "" { - wwlog.Verbose("node:%s setting %s to %s\n", n.Id.Get(), key, val) - n.SetField(key, val) - } - } - err = nodeDB.NodeUpdate(n) if err != nil { return errors.Wrap(err, "failed to update nodedb") @@ -162,33 +162,6 @@ func NodeDeleteParameterCheck(ndp *wwapiv1.NodeDeleteParameter, console bool) (n return } -// NodeList lists all to none of the nodes managed by Warewulf. -func NodeList(nodeNames []string) (nodeInfo []*wwapiv1.NodeInfo, err error) { - - // nil is okay for nodeNames - - nodeDB, err := node.New() - if err != nil { - return - } - - nodes, err := nodeDB.FindAllNodes() - if err != nil { - return - } - - nodeNames = hostlist.Expand(nodeNames) - sort.Strings(nodeNames) - // Translate to the protobuf structure so wwapiv1 can use this across the wire. - // This is the same logic as was in wwctl. - for _, n := range node.FilterByName(nodes, nodeNames) { - var ni wwapiv1.NodeInfo - ni.Fields = GetFields(n) - nodeInfo = append(nodeInfo, &ni) - } - return -} - // NodeSet is the wwapiv1 implmentation for updating node fields. func NodeSet(set *wwapiv1.NodeSetParameter) (err error) { @@ -211,7 +184,7 @@ func NodeSet(set *wwapiv1.NodeSetParameter) (err error) { func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, nodeCount uint, err error) { if set == nil { - err = fmt.Errorf("Node set parameter is nil") + err = fmt.Errorf("node set parameter is nil") if console { fmt.Printf("%v\n", err) return @@ -219,7 +192,7 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB } if set.NodeNames == nil { - err = fmt.Errorf("Node set parameter: NodeNames is nil") + err = fmt.Errorf("node set parameter: NodeNames is nil") if console { fmt.Printf("%v\n", err) return @@ -257,17 +230,17 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB for _, n := range nodes { wwlog.Printf(wwlog.VERBOSE, "Evaluating node: %s\n", n.Id.Get()) - for key, val := range set.OptionsStrMap { - if val != "" { - wwlog.Verbose("node:%s setting %s to %s\n", n.Id.Get(), key, val) - n.SetField(key, val) - } + var nodeConf node.NodeConf + err = yaml.Unmarshal([]byte(set.NodeConfYaml), &nodeConf) + if err != nil { + wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + return } - + n.SetFrom(&nodeConf) if set.NetdevDelete != "" { if _, ok := n.NetDevs[set.NetdevDelete]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete) wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) return } @@ -313,7 +286,7 @@ func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusRespo } if controller.Ipaddr == "" { - err = fmt.Errorf("The Warewulf Server IP Address is not properly configured") + err = fmt.Errorf("the Warewulf Server IP Address is not properly configured") wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) return } diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index 24ebff8f..1f25b897 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -10,6 +10,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/pkg/errors" + "gopkg.in/yaml.v2" ) // NodeSet is the wwapiv1 implmentation for updating nodeinfo fields. @@ -34,7 +35,7 @@ func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, profileCount uint, err error) { if set == nil { - err = fmt.Errorf("Profile set parameter is nil") + err = fmt.Errorf("profile set parameter is nil") if console { fmt.Printf("%v\n", err) return @@ -42,7 +43,7 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node } if set.NodeNames == nil { - err = fmt.Errorf("Profile set parameter: ProfileNames is nil") + err = fmt.Errorf("profile set parameter: ProfileNames is nil") if console { fmt.Printf("%v\n", err) return @@ -75,16 +76,17 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node } return } + var pConf node.NodeConf + err = yaml.Unmarshal([]byte(set.NodeConfYaml), &pConf) + if err != nil { + wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) + return + } for _, p := range profiles { if util.InSlice(set.NodeNames, p.Id.Get()) { wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) - for key, val := range set.OptionsStrMap { - if val != "" { - wwlog.Verbose("profile:%s setting %s to %s\n", p.Id.Get(), key, val) - p.SetField(key, val) - } - } + p.SetFrom(&pConf) if set.NetdevDelete != "" { diff --git a/internal/pkg/api/routes/v1/routes.proto b/internal/pkg/api/routes/v1/routes.proto index d3b3de2f..eb2fcb44 100644 --- a/internal/pkg/api/routes/v1/routes.proto +++ b/internal/pkg/api/routes/v1/routes.proto @@ -102,10 +102,27 @@ message NodeListResponse { repeated NodeInfo nodes = 1; } +// Request a node list +message GetNodeList { + enum ListType { + Simple = 0; + Ipmi = 1; + Network = 2; + Long = 3; + All = 4; + } + ListType type = 7; + repeated string Nodes = 8; +} + +message NodeList { + repeated string Output = 1; +} + // NodeAddParameter contains all input for adding a node to be managed by // Warewulf. message NodeAddParameter { - map optionsStrMap = 1; + string nodeConfYaml = 1; repeated string nodeNames = 10; } @@ -119,7 +136,7 @@ message NodeDeleteParameter { // NodeSetParameter contains all fields for updating aspects of nodes managed // by Warewulf. message NodeSetParameter { - map optionsStrMap = 1; + string nodeConfYaml = 1; string container = 2; string netdevDelete = 14; bool allNodes = 27; diff --git a/internal/pkg/api/routes/wwapiv1/routes.pb.go b/internal/pkg/api/routes/wwapiv1/routes.pb.go index 30d23083..5d38b99e 100644 --- a/internal/pkg/api/routes/wwapiv1/routes.pb.go +++ b/internal/pkg/api/routes/wwapiv1/routes.pb.go @@ -25,6 +25,61 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type GetNodeList_ListType int32 + +const ( + GetNodeList_Simple GetNodeList_ListType = 0 + GetNodeList_Ipmi GetNodeList_ListType = 1 + GetNodeList_Network GetNodeList_ListType = 2 + GetNodeList_Long GetNodeList_ListType = 3 + GetNodeList_All GetNodeList_ListType = 4 +) + +// Enum value maps for GetNodeList_ListType. +var ( + GetNodeList_ListType_name = map[int32]string{ + 0: "Simple", + 1: "Ipmi", + 2: "Network", + 3: "Long", + 4: "All", + } + GetNodeList_ListType_value = map[string]int32{ + "Simple": 0, + "Ipmi": 1, + "Network": 2, + "Long": 3, + "All": 4, + } +) + +func (x GetNodeList_ListType) Enum() *GetNodeList_ListType { + p := new(GetNodeList_ListType) + *p = x + return p +} + +func (x GetNodeList_ListType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GetNodeList_ListType) Descriptor() protoreflect.EnumDescriptor { + return file_routes_proto_enumTypes[0].Descriptor() +} + +func (GetNodeList_ListType) Type() protoreflect.EnumType { + return &file_routes_proto_enumTypes[0] +} + +func (x GetNodeList_ListType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use GetNodeList_ListType.Descriptor instead. +func (GetNodeList_ListType) EnumDescriptor() ([]byte, []int) { + return file_routes_proto_rawDescGZIP(), []int{13, 0} +} + // ContainerBuildParameter contains input for building zero or more containers. type ContainerBuildParameter struct { state protoimpl.MessageState @@ -811,6 +866,109 @@ func (x *NodeListResponse) GetNodes() []*NodeInfo { return nil } +// Request a node list +type GetNodeList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type GetNodeList_ListType `protobuf:"varint,7,opt,name=type,proto3,enum=wwapi.v1.GetNodeList_ListType" json:"type,omitempty"` + Nodes []string `protobuf:"bytes,8,rep,name=Nodes,proto3" json:"Nodes,omitempty"` +} + +func (x *GetNodeList) Reset() { + *x = GetNodeList{} + if protoimpl.UnsafeEnabled { + mi := &file_routes_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNodeList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNodeList) ProtoMessage() {} + +func (x *GetNodeList) ProtoReflect() protoreflect.Message { + mi := &file_routes_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNodeList.ProtoReflect.Descriptor instead. +func (*GetNodeList) Descriptor() ([]byte, []int) { + return file_routes_proto_rawDescGZIP(), []int{13} +} + +func (x *GetNodeList) GetType() GetNodeList_ListType { + if x != nil { + return x.Type + } + return GetNodeList_Simple +} + +func (x *GetNodeList) GetNodes() []string { + if x != nil { + return x.Nodes + } + return nil +} + +type NodeList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Output []string `protobuf:"bytes,1,rep,name=Output,proto3" json:"Output,omitempty"` +} + +func (x *NodeList) Reset() { + *x = NodeList{} + if protoimpl.UnsafeEnabled { + mi := &file_routes_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeList) ProtoMessage() {} + +func (x *NodeList) ProtoReflect() protoreflect.Message { + mi := &file_routes_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeList.ProtoReflect.Descriptor instead. +func (*NodeList) Descriptor() ([]byte, []int) { + return file_routes_proto_rawDescGZIP(), []int{14} +} + +func (x *NodeList) GetOutput() []string { + if x != nil { + return x.Output + } + return nil +} + // NodeAddParameter contains all input for adding a node to be managed by // Warewulf. type NodeAddParameter struct { @@ -818,14 +976,14 @@ type NodeAddParameter struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - OptionsStrMap map[string]string `protobuf:"bytes,1,rep,name=optionsStrMap,proto3" json:"optionsStrMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - NodeNames []string `protobuf:"bytes,10,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` + NodeConfYaml string `protobuf:"bytes,1,opt,name=nodeConfYaml,proto3" json:"nodeConfYaml,omitempty"` + NodeNames []string `protobuf:"bytes,10,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` } func (x *NodeAddParameter) Reset() { *x = NodeAddParameter{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[13] + mi := &file_routes_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -838,7 +996,7 @@ func (x *NodeAddParameter) String() string { func (*NodeAddParameter) ProtoMessage() {} func (x *NodeAddParameter) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[13] + mi := &file_routes_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -851,14 +1009,14 @@ func (x *NodeAddParameter) ProtoReflect() protoreflect.Message { // Deprecated: Use NodeAddParameter.ProtoReflect.Descriptor instead. func (*NodeAddParameter) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{13} + return file_routes_proto_rawDescGZIP(), []int{15} } -func (x *NodeAddParameter) GetOptionsStrMap() map[string]string { +func (x *NodeAddParameter) GetNodeConfYaml() string { if x != nil { - return x.OptionsStrMap + return x.NodeConfYaml } - return nil + return "" } func (x *NodeAddParameter) GetNodeNames() []string { @@ -882,7 +1040,7 @@ type NodeDeleteParameter struct { func (x *NodeDeleteParameter) Reset() { *x = NodeDeleteParameter{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[14] + mi := &file_routes_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -895,7 +1053,7 @@ func (x *NodeDeleteParameter) String() string { func (*NodeDeleteParameter) ProtoMessage() {} func (x *NodeDeleteParameter) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[14] + mi := &file_routes_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -908,7 +1066,7 @@ func (x *NodeDeleteParameter) ProtoReflect() protoreflect.Message { // Deprecated: Use NodeDeleteParameter.ProtoReflect.Descriptor instead. func (*NodeDeleteParameter) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{14} + return file_routes_proto_rawDescGZIP(), []int{16} } func (x *NodeDeleteParameter) GetForce() bool { @@ -932,18 +1090,18 @@ type NodeSetParameter struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - OptionsStrMap map[string]string `protobuf:"bytes,1,rep,name=optionsStrMap,proto3" json:"optionsStrMap,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Container string `protobuf:"bytes,2,opt,name=container,proto3" json:"container,omitempty"` - NetdevDelete string `protobuf:"bytes,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` - AllNodes bool `protobuf:"varint,27,opt,name=allNodes,proto3" json:"allNodes,omitempty"` - Force bool `protobuf:"varint,31,opt,name=force,proto3" json:"force,omitempty"` - NodeNames []string `protobuf:"bytes,39,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` + NodeConfYaml string `protobuf:"bytes,1,opt,name=nodeConfYaml,proto3" json:"nodeConfYaml,omitempty"` + Container string `protobuf:"bytes,2,opt,name=container,proto3" json:"container,omitempty"` + NetdevDelete string `protobuf:"bytes,14,opt,name=netdevDelete,proto3" json:"netdevDelete,omitempty"` + AllNodes bool `protobuf:"varint,27,opt,name=allNodes,proto3" json:"allNodes,omitempty"` + Force bool `protobuf:"varint,31,opt,name=force,proto3" json:"force,omitempty"` + NodeNames []string `protobuf:"bytes,39,rep,name=nodeNames,proto3" json:"nodeNames,omitempty"` } func (x *NodeSetParameter) Reset() { *x = NodeSetParameter{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[15] + mi := &file_routes_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -956,7 +1114,7 @@ func (x *NodeSetParameter) String() string { func (*NodeSetParameter) ProtoMessage() {} func (x *NodeSetParameter) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[15] + mi := &file_routes_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -969,14 +1127,14 @@ func (x *NodeSetParameter) ProtoReflect() protoreflect.Message { // Deprecated: Use NodeSetParameter.ProtoReflect.Descriptor instead. func (*NodeSetParameter) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{15} + return file_routes_proto_rawDescGZIP(), []int{17} } -func (x *NodeSetParameter) GetOptionsStrMap() map[string]string { +func (x *NodeSetParameter) GetNodeConfYaml() string { if x != nil { - return x.OptionsStrMap + return x.NodeConfYaml } - return nil + return "" } func (x *NodeSetParameter) GetContainer() string { @@ -1030,7 +1188,7 @@ type NodeStatus struct { func (x *NodeStatus) Reset() { *x = NodeStatus{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[16] + mi := &file_routes_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1043,7 +1201,7 @@ func (x *NodeStatus) String() string { func (*NodeStatus) ProtoMessage() {} func (x *NodeStatus) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[16] + mi := &file_routes_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1056,7 +1214,7 @@ func (x *NodeStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use NodeStatus.ProtoReflect.Descriptor instead. func (*NodeStatus) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{16} + return file_routes_proto_rawDescGZIP(), []int{18} } func (x *NodeStatus) GetNodeName() string { @@ -1106,7 +1264,7 @@ type NodeStatusResponse struct { func (x *NodeStatusResponse) Reset() { *x = NodeStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[17] + mi := &file_routes_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1119,7 +1277,7 @@ func (x *NodeStatusResponse) String() string { func (*NodeStatusResponse) ProtoMessage() {} func (x *NodeStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[17] + mi := &file_routes_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1132,7 +1290,7 @@ func (x *NodeStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NodeStatusResponse.ProtoReflect.Descriptor instead. func (*NodeStatusResponse) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{17} + return file_routes_proto_rawDescGZIP(), []int{19} } func (x *NodeStatusResponse) GetNodeStatus() []*NodeStatus { @@ -1156,7 +1314,7 @@ type VersionResponse struct { func (x *VersionResponse) Reset() { *x = VersionResponse{} if protoimpl.UnsafeEnabled { - mi := &file_routes_proto_msgTypes[18] + mi := &file_routes_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1169,7 +1327,7 @@ func (x *VersionResponse) String() string { func (*VersionResponse) ProtoMessage() {} func (x *VersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_routes_proto_msgTypes[18] + mi := &file_routes_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1182,7 +1340,7 @@ func (x *VersionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionResponse.ProtoReflect.Descriptor instead. func (*VersionResponse) Descriptor() ([]byte, []int) { - return file_routes_proto_rawDescGZIP(), []int{18} + return file_routes_proto_rawDescGZIP(), []int{20} } func (x *VersionResponse) GetApiPrefix() string { @@ -1329,135 +1487,132 @@ var file_routes_proto_rawDesc = []byte{ 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x22, 0xc7, 0x01, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x0d, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, - 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x12, 0x1c, 0x0a, - 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x49, 0x0a, - 0x13, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, - 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, - 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xbb, 0x02, 0x0a, 0x10, 0x4e, 0x6f, 0x64, - 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x53, 0x0a, - 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, - 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x0d, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x4d, - 0x61, 0x70, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, - 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x64, 0x65, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x1e, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x40, 0x0a, + 0x08, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x70, 0x6d, 0x69, 0x10, 0x01, 0x12, + 0x0b, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, + 0x4c, 0x6f, 0x6e, 0x67, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x6c, 0x6c, 0x10, 0x04, 0x22, + 0x22, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x4f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x22, 0x54, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x64, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, + 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x6e, + 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x13, 0x4e, 0x6f, 0x64, + 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, - 0x6d, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x12, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, - 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, - 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, - 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, - 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, - 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, - 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, - 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, - 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, + 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x22, 0xc8, 0x01, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x6f, 0x64, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x59, 0x61, 0x6d, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x59, 0x61, 0x6d, 0x6c, 0x12, 0x1c, 0x0a, + 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x6e, + 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x74, 0x64, 0x65, 0x76, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x1b, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x27, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, + 0x86, 0x01, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x12, 0x1a, 0x0a, 0x08, + 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x6c, 0x61, 0x73, 0x74, 0x73, 0x65, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, + 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x22, 0x79, 0x0a, 0x0f, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x69, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x69, 0x50, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x0f, 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, + 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x77, 0x61, 0x72, 0x65, 0x77, 0x75, 0x6c, 0x66, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, + 0xa6, 0x08, 0x0a, 0x05, 0x57, 0x57, 0x41, 0x70, 0x69, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x21, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x42, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, - 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, - 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, - 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, - 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, - 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, - 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, - 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, + 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x64, + 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x15, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x2a, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x12, 0x70, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x70, 0x6f, + 0x72, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5f, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x1f, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, 0x77, 0x12, 0x20, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x68, 0x6f, + 0x77, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1f, 0x2e, 0x77, 0x77, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, + 0x68, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x73, 0x68, 0x6f, 0x77, 0x12, 0x56, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x64, + 0x64, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x41, 0x64, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, - 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, - 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, - 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, - 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0d, 0x22, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x55, + 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x77, + 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x2a, 0x08, 0x2f, 0x76, 0x31, + 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x13, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, + 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x59, 0x0a, 0x07, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x12, + 0x1a, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, + 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x1a, 0x1a, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x22, + 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x65, 0x74, 0x3a, 0x01, 0x2a, 0x12, + 0x57, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x13, 0x2e, + 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x1a, 0x1c, 0x2e, 0x77, 0x77, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4e, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x77, 0x77, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, + 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x5a, 0x27, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x2f, 0x77, 0x77, 0x61, 0x70, 0x69, 0x76, 0x31, 0x3b, 0x77, 0x77, 0x61, 0x70, + 0x69, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1472,82 +1627,83 @@ func file_routes_proto_rawDescGZIP() []byte { return file_routes_proto_rawDescData } +var file_routes_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_routes_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_routes_proto_goTypes = []interface{}{ - (*ContainerBuildParameter)(nil), // 0: wwapi.v1.ContainerBuildParameter - (*ContainerDeleteParameter)(nil), // 1: wwapi.v1.ContainerDeleteParameter - (*ContainerImportParameter)(nil), // 2: wwapi.v1.ContainerImportParameter - (*ContainerInfo)(nil), // 3: wwapi.v1.ContainerInfo - (*ContainerListResponse)(nil), // 4: wwapi.v1.ContainerListResponse - (*ContainerShowParameter)(nil), // 5: wwapi.v1.ContainerShowParameter - (*ContainerShowResponse)(nil), // 6: wwapi.v1.ContainerShowResponse - (*ContainerSyncUserParameter)(nil), // 7: wwapi.v1.ContainerSyncUserParameter - (*NodeNames)(nil), // 8: wwapi.v1.NodeNames - (*NodeField)(nil), // 9: wwapi.v1.NodeField - (*NetDev)(nil), // 10: wwapi.v1.NetDev - (*NodeInfo)(nil), // 11: wwapi.v1.NodeInfo - (*NodeListResponse)(nil), // 12: wwapi.v1.NodeListResponse - (*NodeAddParameter)(nil), // 13: wwapi.v1.NodeAddParameter - (*NodeDeleteParameter)(nil), // 14: wwapi.v1.NodeDeleteParameter - (*NodeSetParameter)(nil), // 15: wwapi.v1.NodeSetParameter - (*NodeStatus)(nil), // 16: wwapi.v1.NodeStatus - (*NodeStatusResponse)(nil), // 17: wwapi.v1.NodeStatusResponse - (*VersionResponse)(nil), // 18: wwapi.v1.VersionResponse - nil, // 19: wwapi.v1.NetDev.FieldEntry - nil, // 20: wwapi.v1.NetDev.TagsEntry - nil, // 21: wwapi.v1.NodeInfo.FieldsEntry - nil, // 22: wwapi.v1.NodeInfo.NetDevsEntry - nil, // 23: wwapi.v1.NodeInfo.TagsEntry - nil, // 24: wwapi.v1.NodeInfo.KeysEntry - nil, // 25: wwapi.v1.NodeAddParameter.OptionsStrMapEntry - nil, // 26: wwapi.v1.NodeSetParameter.OptionsStrMapEntry - (*empty.Empty)(nil), // 27: google.protobuf.Empty + (GetNodeList_ListType)(0), // 0: wwapi.v1.GetNodeList.ListType + (*ContainerBuildParameter)(nil), // 1: wwapi.v1.ContainerBuildParameter + (*ContainerDeleteParameter)(nil), // 2: wwapi.v1.ContainerDeleteParameter + (*ContainerImportParameter)(nil), // 3: wwapi.v1.ContainerImportParameter + (*ContainerInfo)(nil), // 4: wwapi.v1.ContainerInfo + (*ContainerListResponse)(nil), // 5: wwapi.v1.ContainerListResponse + (*ContainerShowParameter)(nil), // 6: wwapi.v1.ContainerShowParameter + (*ContainerShowResponse)(nil), // 7: wwapi.v1.ContainerShowResponse + (*ContainerSyncUserParameter)(nil), // 8: wwapi.v1.ContainerSyncUserParameter + (*NodeNames)(nil), // 9: wwapi.v1.NodeNames + (*NodeField)(nil), // 10: wwapi.v1.NodeField + (*NetDev)(nil), // 11: wwapi.v1.NetDev + (*NodeInfo)(nil), // 12: wwapi.v1.NodeInfo + (*NodeListResponse)(nil), // 13: wwapi.v1.NodeListResponse + (*GetNodeList)(nil), // 14: wwapi.v1.GetNodeList + (*NodeList)(nil), // 15: wwapi.v1.NodeList + (*NodeAddParameter)(nil), // 16: wwapi.v1.NodeAddParameter + (*NodeDeleteParameter)(nil), // 17: wwapi.v1.NodeDeleteParameter + (*NodeSetParameter)(nil), // 18: wwapi.v1.NodeSetParameter + (*NodeStatus)(nil), // 19: wwapi.v1.NodeStatus + (*NodeStatusResponse)(nil), // 20: wwapi.v1.NodeStatusResponse + (*VersionResponse)(nil), // 21: wwapi.v1.VersionResponse + nil, // 22: wwapi.v1.NetDev.FieldEntry + nil, // 23: wwapi.v1.NetDev.TagsEntry + nil, // 24: wwapi.v1.NodeInfo.FieldsEntry + nil, // 25: wwapi.v1.NodeInfo.NetDevsEntry + nil, // 26: wwapi.v1.NodeInfo.TagsEntry + nil, // 27: wwapi.v1.NodeInfo.KeysEntry + (*empty.Empty)(nil), // 28: google.protobuf.Empty } var file_routes_proto_depIdxs = []int32{ - 3, // 0: wwapi.v1.ContainerListResponse.containers:type_name -> wwapi.v1.ContainerInfo - 19, // 1: wwapi.v1.NetDev.Field:type_name -> wwapi.v1.NetDev.FieldEntry - 20, // 2: wwapi.v1.NetDev.Tags:type_name -> wwapi.v1.NetDev.TagsEntry - 21, // 3: wwapi.v1.NodeInfo.Fields:type_name -> wwapi.v1.NodeInfo.FieldsEntry - 22, // 4: wwapi.v1.NodeInfo.NetDevs:type_name -> wwapi.v1.NodeInfo.NetDevsEntry - 23, // 5: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry - 24, // 6: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry - 11, // 7: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo - 25, // 8: wwapi.v1.NodeAddParameter.optionsStrMap:type_name -> wwapi.v1.NodeAddParameter.OptionsStrMapEntry - 26, // 9: wwapi.v1.NodeSetParameter.optionsStrMap:type_name -> wwapi.v1.NodeSetParameter.OptionsStrMapEntry - 16, // 10: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus - 9, // 11: wwapi.v1.NetDev.FieldEntry.value:type_name -> wwapi.v1.NodeField - 9, // 12: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField - 9, // 13: wwapi.v1.NodeInfo.FieldsEntry.value:type_name -> wwapi.v1.NodeField - 10, // 14: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev - 9, // 15: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField - 9, // 16: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField - 0, // 17: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter - 1, // 18: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter - 2, // 19: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter - 27, // 20: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty - 5, // 21: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter - 13, // 22: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter - 14, // 23: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter - 8, // 24: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames - 15, // 25: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter - 8, // 26: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames - 27, // 27: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty - 4, // 28: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse - 27, // 29: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty - 4, // 30: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse - 4, // 31: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse - 6, // 32: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse - 12, // 33: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse - 27, // 34: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty - 12, // 35: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse - 12, // 36: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse - 17, // 37: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse - 18, // 38: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse - 28, // [28:39] is the sub-list for method output_type - 17, // [17:28] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 4, // 0: wwapi.v1.ContainerListResponse.containers:type_name -> wwapi.v1.ContainerInfo + 22, // 1: wwapi.v1.NetDev.Field:type_name -> wwapi.v1.NetDev.FieldEntry + 23, // 2: wwapi.v1.NetDev.Tags:type_name -> wwapi.v1.NetDev.TagsEntry + 24, // 3: wwapi.v1.NodeInfo.Fields:type_name -> wwapi.v1.NodeInfo.FieldsEntry + 25, // 4: wwapi.v1.NodeInfo.NetDevs:type_name -> wwapi.v1.NodeInfo.NetDevsEntry + 26, // 5: wwapi.v1.NodeInfo.Tags:type_name -> wwapi.v1.NodeInfo.TagsEntry + 27, // 6: wwapi.v1.NodeInfo.Keys:type_name -> wwapi.v1.NodeInfo.KeysEntry + 12, // 7: wwapi.v1.NodeListResponse.nodes:type_name -> wwapi.v1.NodeInfo + 0, // 8: wwapi.v1.GetNodeList.type:type_name -> wwapi.v1.GetNodeList.ListType + 19, // 9: wwapi.v1.NodeStatusResponse.nodeStatus:type_name -> wwapi.v1.NodeStatus + 10, // 10: wwapi.v1.NetDev.FieldEntry.value:type_name -> wwapi.v1.NodeField + 10, // 11: wwapi.v1.NetDev.TagsEntry.value:type_name -> wwapi.v1.NodeField + 10, // 12: wwapi.v1.NodeInfo.FieldsEntry.value:type_name -> wwapi.v1.NodeField + 11, // 13: wwapi.v1.NodeInfo.NetDevsEntry.value:type_name -> wwapi.v1.NetDev + 10, // 14: wwapi.v1.NodeInfo.TagsEntry.value:type_name -> wwapi.v1.NodeField + 10, // 15: wwapi.v1.NodeInfo.KeysEntry.value:type_name -> wwapi.v1.NodeField + 1, // 16: wwapi.v1.WWApi.ContainerBuild:input_type -> wwapi.v1.ContainerBuildParameter + 2, // 17: wwapi.v1.WWApi.ContainerDelete:input_type -> wwapi.v1.ContainerDeleteParameter + 3, // 18: wwapi.v1.WWApi.ContainerImport:input_type -> wwapi.v1.ContainerImportParameter + 28, // 19: wwapi.v1.WWApi.ContainerList:input_type -> google.protobuf.Empty + 6, // 20: wwapi.v1.WWApi.ContainerShow:input_type -> wwapi.v1.ContainerShowParameter + 16, // 21: wwapi.v1.WWApi.NodeAdd:input_type -> wwapi.v1.NodeAddParameter + 17, // 22: wwapi.v1.WWApi.NodeDelete:input_type -> wwapi.v1.NodeDeleteParameter + 9, // 23: wwapi.v1.WWApi.NodeList:input_type -> wwapi.v1.NodeNames + 18, // 24: wwapi.v1.WWApi.NodeSet:input_type -> wwapi.v1.NodeSetParameter + 9, // 25: wwapi.v1.WWApi.NodeStatus:input_type -> wwapi.v1.NodeNames + 28, // 26: wwapi.v1.WWApi.Version:input_type -> google.protobuf.Empty + 5, // 27: wwapi.v1.WWApi.ContainerBuild:output_type -> wwapi.v1.ContainerListResponse + 28, // 28: wwapi.v1.WWApi.ContainerDelete:output_type -> google.protobuf.Empty + 5, // 29: wwapi.v1.WWApi.ContainerImport:output_type -> wwapi.v1.ContainerListResponse + 5, // 30: wwapi.v1.WWApi.ContainerList:output_type -> wwapi.v1.ContainerListResponse + 7, // 31: wwapi.v1.WWApi.ContainerShow:output_type -> wwapi.v1.ContainerShowResponse + 13, // 32: wwapi.v1.WWApi.NodeAdd:output_type -> wwapi.v1.NodeListResponse + 28, // 33: wwapi.v1.WWApi.NodeDelete:output_type -> google.protobuf.Empty + 13, // 34: wwapi.v1.WWApi.NodeList:output_type -> wwapi.v1.NodeListResponse + 13, // 35: wwapi.v1.WWApi.NodeSet:output_type -> wwapi.v1.NodeListResponse + 20, // 36: wwapi.v1.WWApi.NodeStatus:output_type -> wwapi.v1.NodeStatusResponse + 21, // 37: wwapi.v1.WWApi.Version:output_type -> wwapi.v1.VersionResponse + 27, // [27:38] is the sub-list for method output_type + 16, // [16:27] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_routes_proto_init() } @@ -1713,7 +1869,7 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeAddParameter); i { + switch v := v.(*GetNodeList); i { case 0: return &v.state case 1: @@ -1725,7 +1881,7 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeDeleteParameter); i { + switch v := v.(*NodeList); i { case 0: return &v.state case 1: @@ -1737,7 +1893,7 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeSetParameter); i { + switch v := v.(*NodeAddParameter); i { case 0: return &v.state case 1: @@ -1749,7 +1905,7 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeStatus); i { + switch v := v.(*NodeDeleteParameter); i { case 0: return &v.state case 1: @@ -1761,7 +1917,7 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeStatusResponse); i { + switch v := v.(*NodeSetParameter); i { case 0: return &v.state case 1: @@ -1773,6 +1929,30 @@ func file_routes_proto_init() { } } file_routes_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeStatus); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_routes_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeStatusResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_routes_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*VersionResponse); i { case 0: return &v.state @@ -1790,13 +1970,14 @@ func file_routes_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_routes_proto_rawDesc, - NumEnums: 0, + NumEnums: 1, NumMessages: 27, NumExtensions: 0, NumServices: 1, }, GoTypes: file_routes_proto_goTypes, DependencyIndexes: file_routes_proto_depIdxs, + EnumInfos: file_routes_proto_enumTypes, MessageInfos: file_routes_proto_msgTypes, }.Build() File_routes_proto = out.File diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 02d26809..5780937e 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -2,13 +2,11 @@ package node import ( "fmt" - "reflect" "regexp" "strings" "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/spf13/cobra" ) /********** @@ -312,348 +310,356 @@ func (ent *Entry) Defined() bool { } /* -Set the Entry trough an interface by trying to cast the interface +Create an empty node NodeConf */ -func SetEntry(entryPtr interface{}, val interface{}) { - valKind := reflect.TypeOf(val) - if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) { - entry := entryPtr.(*Entry) - if valKind.Kind() == reflect.String { - entry.Set(val.(string)) - } else if valKind.Kind() == reflect.Slice { - if valKind.Elem().Kind() == reflect.String { - entry.SetSlice(val.([]string)) - } else { - panic("Got unknown slice type") - } - } - } else if reflect.TypeOf(entryPtr) == reflect.TypeOf((*[]string)(nil)) { - entry := entryPtr.(*[]string) - if valKind.Kind() == reflect.String { - // most likely we got a comma seperated string slice - *entry = strings.Split(val.(string), ",") - } else if valKind.Kind() == reflect.Slice { - if valKind.Elem().Kind() == reflect.String { - *entry = val.([]string) - } else { - panic("Got unknown slice type") - } - } - } else { - panic(fmt.Sprintf("Can't convert %s to *node.Entry to call Set\n", reflect.TypeOf(entryPtr))) - } - +func NewConf() (nodeconf NodeConf) { + nodeconf.Ipmi = new(IpmiConf) + nodeconf.Kernel = new(KernelConf) + nodeconf.NetDevs = map[string]*NetDevs{} + return nodeconf } -/* -Add an entry in a map -*/ -func addEntry(entryMapInt interface{}, val interface{}) { - if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { - if reflect.ValueOf(entryMapInt).Elem().IsNil() { - newMap := make(map[string]*Entry) - entryMapInt = &newMap - } - entryMap := entryMapInt.(*map[string]*Entry) - str, ok := (val).(string) - if !ok { - panic("AddEntry must be called with string value") - } - for _, token := range strings.Split(str, ",") { - keyVal := strings.Split(token, "=") - if len(keyVal) == 2 { - _, mapOk := (*entryMap)[keyVal[0]] - if !mapOk { - (*entryMap)[keyVal[0]] = new(Entry) - } - (*entryMap)[keyVal[0]].Set(keyVal[1]) - } - } - } else { - panic(fmt.Sprintf("Do not know how to add %v to %v\n", val, entryMapInt)) - } -} +// /* +// Set the Entry trough an interface by trying to cast the interface +// */ +// func SetEntry(entryPtr interface{}, val interface{}) { +// valKind := reflect.TypeOf(val) +// if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) { +// entry := entryPtr.(*Entry) +// if valKind.Kind() == reflect.String { +// entry.Set(val.(string)) +// } else if valKind.Kind() == reflect.Slice { +// if valKind.Elem().Kind() == reflect.String { +// entry.SetSlice(val.([]string)) +// } else { +// panic("Got unknown slice type") +// } +// } +// } else if reflect.TypeOf(entryPtr) == reflect.TypeOf((*[]string)(nil)) { +// entry := entryPtr.(*[]string) +// if valKind.Kind() == reflect.String { +// // most likely we got a comma seperated string slice +// *entry = strings.Split(val.(string), ",") +// } else if valKind.Kind() == reflect.Slice { +// if valKind.Elem().Kind() == reflect.String { +// *entry = val.([]string) +// } else { +// panic("Got unknown slice type") +// } +// } +// } else { +// panic(fmt.Sprintf("Can't convert %s to *node.Entry to call Set\n", reflect.TypeOf(entryPtr))) +// } -/* -Del an entry in a map -*/ -func delEntry(entryMapInt interface{}, val interface{}) { - if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { - entryMap := entryMapInt.(*map[string]*Entry) - str, ok := (val).(string) - if !ok { - panic("DelEntry must be called with string value") - } - for _, token := range strings.Split(str, ",") { - delete(*entryMap, token) - } - } else { - panic(fmt.Sprintf("Do not know how to del %v to %v\n", val, entryMapInt)) - } +// } -} +// /* +// Add an entry in a map +// */ +// func addEntry(entryMapInt interface{}, val interface{}) { +// if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { +// if reflect.ValueOf(entryMapInt).Elem().IsNil() { +// newMap := make(map[string]*Entry) +// entryMapInt = &newMap +// } +// entryMap := entryMapInt.(*map[string]*Entry) +// str, ok := (val).(string) +// if !ok { +// panic("AddEntry must be called with string value") +// } +// for _, token := range strings.Split(str, ",") { +// keyVal := strings.Split(token, "=") +// if len(keyVal) == 2 { +// _, mapOk := (*entryMap)[keyVal[0]] +// if !mapOk { +// (*entryMap)[keyVal[0]] = new(Entry) +// } +// (*entryMap)[keyVal[0]].Set(keyVal[1]) +// } +// } +// } else { +// panic(fmt.Sprintf("Do not know how to add %v to %v\n", val, entryMapInt)) +// } +// } -/* -Call SetEntry for given field (NodeInfo). -*/ -func (node *NodeInfo) SetField(fieldName string, val interface{}) { - field := reflect.ValueOf(node).Elem().FieldByName(fieldName) - if field.IsValid() { - if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { - SetEntry(field.Addr().Interface(), val) - } else if field.Addr().Type() == reflect.TypeOf((*[]string)(nil)) { - SetEntry(field.Addr().Interface(), val) - } - /* - else if field.Addr().Kind() == reflect.Map { - fmt.Println(field.Addr()) - } else { - //fmt.Println("Not working field.Addr().Kind():", field.Addr().Type()) - // is most likely NetDevEntry, ignore it - } - */ - } else { - fieldNames := strings.Split(fieldName, ".") - if len(fieldNames) >= 2 { - if fieldNames[0] == "del" || fieldNames[0] == "add" { - fieldMap := reflect.ValueOf(node).Elem().FieldByName(fieldNames[1]) - if fieldMap.IsValid() { - if fieldNames[0] == "del" { - delEntry(fieldMap.Addr().Interface(), val) - } else if fieldNames[0] == "add" { - addEntry(fieldMap.Addr().Interface(), val) - } - } else { - panic(fmt.Sprintf("invalid del/add operation with name %s called, field %s does not exists\n", fieldName, fieldNames[0])) - } - } else { - nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) - if nestedField.IsValid() { - switch nestedField.Addr().Type() { - case reflect.TypeOf((**KernelEntry)(nil)): - entry := nestedField.Addr().Interface().(**KernelEntry) - (*entry).SetField(strings.Join(fieldNames[1:], "."), val) - case reflect.TypeOf((**IpmiEntry)(nil)): - entry := nestedField.Addr().Interface().(**IpmiEntry) - (*entry).SetField(strings.Join(fieldNames[1:], "."), val) - case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): - if len(fieldNames) >= 3 { - entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) - if myVal, ok := (*entryMap)[fieldNames[1]]; ok { - myVal.SetField(strings.Join(fieldNames[2:], "."), val) - } else { - var newEntry NetDevEntry - (*entryMap)[fieldNames[1]] = &newEntry - newEntry.SetField(strings.Join(fieldNames[2:], "."), val) - } - } - default: - panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) - } - } else { - panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) - } - } - } else { - panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) - } - } +// /* +// Del an entry in a map +// */ +// func delEntry(entryMapInt interface{}, val interface{}) { +// if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { +// entryMap := entryMapInt.(*map[string]*Entry) +// str, ok := (val).(string) +// if !ok { +// panic("DelEntry must be called with string value") +// } +// for _, token := range strings.Split(str, ",") { +// delete(*entryMap, token) +// } +// } else { +// panic(fmt.Sprintf("Do not know how to del %v to %v\n", val, entryMapInt)) +// } -} +// } -/* -Call SetEntry for given field (KernelEntry) -*/ -func (node *KernelEntry) SetField(fieldName string, val interface{}) { - field := reflect.ValueOf(node).Elem().FieldByName(fieldName) - if field.IsValid() { - SetEntry(field.Addr().Interface(), val) - } else { - valFields := strings.Split(fieldName, ".") - field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) - if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - addEntry(field.Addr().Interface(), val) - } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - delEntry(field.Addr().Interface(), val) - } else { - panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) - } - } -} +// /* +// Call SetEntry for given field (NodeInfo). +// */ +// func (node *NodeInfo) SetField(fieldName string, val interface{}) { +// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) +// if field.IsValid() { +// if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { +// SetEntry(field.Addr().Interface(), val) +// } else if field.Addr().Type() == reflect.TypeOf((*[]string)(nil)) { +// SetEntry(field.Addr().Interface(), val) +// } +// /* +// else if field.Addr().Kind() == reflect.Map { +// fmt.Println(field.Addr()) +// } else { +// //fmt.Println("Not working field.Addr().Kind():", field.Addr().Type()) +// // is most likely NetDevEntry, ignore it +// } +// */ +// } else { +// fieldNames := strings.Split(fieldName, ".") +// if len(fieldNames) >= 2 { +// if fieldNames[0] == "del" || fieldNames[0] == "add" { +// fieldMap := reflect.ValueOf(node).Elem().FieldByName(fieldNames[1]) +// if fieldMap.IsValid() { +// if fieldNames[0] == "del" { +// delEntry(fieldMap.Addr().Interface(), val) +// } else if fieldNames[0] == "add" { +// addEntry(fieldMap.Addr().Interface(), val) +// } +// } else { +// panic(fmt.Sprintf("invalid del/add operation with name %s called, field %s does not exists\n", fieldName, fieldNames[0])) +// } +// } else { +// nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) +// if nestedField.IsValid() { +// switch nestedField.Addr().Type() { +// case reflect.TypeOf((**KernelEntry)(nil)): +// entry := nestedField.Addr().Interface().(**KernelEntry) +// (*entry).SetField(strings.Join(fieldNames[1:], "."), val) +// case reflect.TypeOf((**IpmiEntry)(nil)): +// entry := nestedField.Addr().Interface().(**IpmiEntry) +// (*entry).SetField(strings.Join(fieldNames[1:], "."), val) +// case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): +// if len(fieldNames) >= 3 { +// entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) +// if myVal, ok := (*entryMap)[fieldNames[1]]; ok { +// myVal.SetField(strings.Join(fieldNames[2:], "."), val) +// } else { +// var newEntry NetDevEntry +// (*entryMap)[fieldNames[1]] = &newEntry +// newEntry.SetField(strings.Join(fieldNames[2:], "."), val) +// } +// } +// default: +// panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) +// } +// } else { +// panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) +// } +// } +// } else { +// panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) +// } +// } -/* -Call SetEntry for given field (ImpiEntry) -*/ -func (node *IpmiEntry) SetField(fieldName string, val interface{}) { - field := reflect.ValueOf(node).Elem().FieldByName(fieldName) - if field.IsValid() { - SetEntry(field.Addr().Interface(), val) - } else { - valFields := strings.Split(fieldName, ".") - field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) - if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - addEntry(field.Addr().Interface(), val) - } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - delEntry(field.Addr().Interface(), val) - } else { - panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) - } - } -} +// } -/* -Call SetEntry for given field (NetDevEntry) -*/ -func (node *NetDevEntry) SetField(fieldName string, val interface{}) { - field := reflect.ValueOf(node).Elem().FieldByName(fieldName) - if field.IsValid() { - SetEntry(field.Addr().Interface(), val) - } else { - valFields := strings.Split(fieldName, ".") - field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) - if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { - addEntry(field.Addr().Interface(), val) - } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { - delEntry(field.Addr().Interface(), val) - } else { - panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) - } - } -} +// /* +// Call SetEntry for given field (KernelEntry) +// */ +// func (node *KernelEntry) SetField(fieldName string, val interface{}) { +// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) +// if field.IsValid() { +// SetEntry(field.Addr().Interface(), val) +// } else { +// valFields := strings.Split(fieldName, ".") +// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) +// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { +// addEntry(field.Addr().Interface(), val) +// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { +// delEntry(field.Addr().Interface(), val) +// } else { +// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) +// } +// } +// } + +// /* +// Call SetEntry for given field (ImpiEntry) +// */ +// func (node *IpmiEntry) SetField(fieldName string, val interface{}) { +// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) +// if field.IsValid() { +// SetEntry(field.Addr().Interface(), val) +// } else { +// valFields := strings.Split(fieldName, ".") +// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) +// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { +// addEntry(field.Addr().Interface(), val) +// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { +// delEntry(field.Addr().Interface(), val) +// } else { +// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) +// } +// } +// } + +// /* +// Call SetEntry for given field (NetDevEntry) +// */ +// func (node *NetDevEntry) SetField(fieldName string, val interface{}) { +// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) +// if field.IsValid() { +// SetEntry(field.Addr().Interface(), val) +// } else { +// valFields := strings.Split(fieldName, ".") +// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) +// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { +// addEntry(field.Addr().Interface(), val) +// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { +// delEntry(field.Addr().Interface(), val) +// } else { +// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) +// } +// } +// } + +// /* +// Get all names of the fields in the given struct (recursive) +// and create a map[name of struct field]*string if the the field +// of the struct bears the comment tag. +// */ +// func GetOptionsMap(theStruct interface{}) map[string]*string { +// optionsMap := make(map[string]*string) +// structVal := reflect.ValueOf(theStruct) +// structTyp := structVal.Type() +// for i := 0; i < structVal.NumField(); i++ { +// field := structTyp.Field(i) +// if field.Type.Kind() == reflect.Struct { +// subStruct := GetOptionsMap(field) +// for key, val := range subStruct { +// optionsMap[key] = val +// } +// } else if field.Tag.Get("comment") != "" { +// optionsMap[field.Name] = new(string) +// } + +// } +// return optionsMap +// } + +// type CobraCommand struct { +// *cobra.Command +// } /* Get all names of the fields in the given struct (recursive) and create a map[name of struct field]*string if the the field of the struct bears the comment tag. */ -func GetOptionsMap(theStruct interface{}) map[string]*string { - optionsMap := make(map[string]*string) - structVal := reflect.ValueOf(theStruct) - structTyp := structVal.Type() - for i := 0; i < structVal.NumField(); i++ { - field := structTyp.Field(i) - if field.Type.Kind() == reflect.Struct { - subStruct := GetOptionsMap(field) - for key, val := range subStruct { - optionsMap[key] = val - } - } else if field.Tag.Get("comment") != "" { - optionsMap[field.Name] = new(string) - } +// func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []string) map[string]*string { +// structVal := reflect.ValueOf(theStruct) +// for i := 0; i < structVal.NumField(); i++ { +// field := structVal.Type().Field(i) +// //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) +// if field.Type.Kind() == reflect.Ptr { +// a := structVal.Field(i).Elem().Interface() +// subStruct := baseCmd.CreateFlags(a, excludeList) +// for key, val := range subStruct { +// optionsMap[field.Name+"."+key] = val +// } - } - return optionsMap -} +// } else if field.Type.Kind() == reflect.Map { +// // check the type of map +// mapType := field.Type.Elem() +// if mapType.Kind() == reflect.Ptr { +// //a := reflect.ValueOf((mapType.Elem())) node.NetDevs +// subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) +// for key, val := range subMap { +// optionsMap[field.Name+"."+key] = val +// } +// if mapType == reflect.TypeOf((*NetDevs)(nil)) { +// // set the option for the network name here +// var netName string +// optionsMap[field.Name] = &netName +// baseCmd.PersistentFlags().StringVarP(&netName, +// "netname", "n", "", "Define the network name to configure") +// } +// } else if mapType.Kind() == reflect.String { +// if field.Tag.Get("lopt") != "" { +// var addPair string +// optionsMap["add"+"."+field.Name] = &addPair +// baseCmd.PersistentFlags().StringVarP(&addPair, +// field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) +// var delPair string +// optionsMap["del"+"."+field.Name] = &delPair +// baseCmd.PersistentFlags().StringVarP(&delPair, +// field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) +// } +// } else { +// // TODO: implement handling of string maps +// wwlog.Warn("handling of %v not implemented\n", field.Type) +// } -type CobraCommand struct { - *cobra.Command -} +// } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Tag.Get("lopt")) { +// var newStr string +// optionsMap[field.Name] = &newStr +// if field.Tag.Get("sopt") != "" { +// baseCmd.PersistentFlags().StringVarP(&newStr, +// field.Tag.Get("lopt"), +// field.Tag.Get("sopt"), +// field.Tag.Get("default"), +// field.Tag.Get("comment")) +// } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { +// baseCmd.PersistentFlags().StringVar(&newStr, +// field.Tag.Get("lopt"), +// field.Tag.Get("default"), +// field.Tag.Get("comment")) -/* -Get all names of the fields in the given struct (recursive) -and create a map[name of struct field]*string if the the field -of the struct bears the comment tag. -*/ -func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []string) map[string]*string { - optionsMap := make(map[string]*string) - structVal := reflect.ValueOf(theStruct) - structTyp := structVal.Type() - for i := 0; i < structVal.NumField(); i++ { - field := structTyp.Field(i) - //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) - if field.Type.Kind() == reflect.Ptr { - a := structVal.Field(i).Elem().Interface() - subStruct := baseCmd.CreateFlags(a, excludeList) - for key, val := range subStruct { - optionsMap[field.Name+"."+key] = val - } +// } +// } - } else if field.Type.Kind() == reflect.Map { - // check the type of map - mapType := field.Type.Elem() - if mapType.Kind() == reflect.Ptr { - //a := reflect.ValueOf((mapType.Elem())) node.NetDevs - subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) - for key, val := range subMap { - optionsMap[field.Name+"."+key] = val - } - if mapType == reflect.TypeOf((*NetDevs)(nil)) { - // set the option for the network name here - var netName string - optionsMap[field.Name] = &netName - baseCmd.PersistentFlags().StringVarP(&netName, - "netname", "n", "", "Define the network name to configure") - } - } else if mapType.Kind() == reflect.String { - if field.Tag.Get("lopt") != "" { - var addPair string - optionsMap["add"+"."+field.Name] = &addPair - baseCmd.PersistentFlags().StringVarP(&addPair, - field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) - var delPair string - optionsMap["del"+"."+field.Name] = &delPair - baseCmd.PersistentFlags().StringVarP(&delPair, - field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) - } - } else { - // TODO: implement handling of string maps - wwlog.Warn("handling of %v not implemented\n", field.Type) - } +// } +// return optionsMap +// } - } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Tag.Get("lopt")) { - var newStr string - optionsMap[field.Name] = &newStr - if field.Tag.Get("sopt") != "" { - baseCmd.PersistentFlags().StringVarP(&newStr, - field.Tag.Get("lopt"), - field.Tag.Get("sopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) - } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { - baseCmd.PersistentFlags().StringVar(&newStr, - field.Tag.Get("lopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) +// /* +// Helper function which gets the lopt of a given interface +// */ +// func GetLoptOf(myStruct interface{}, name string) string { +// retStr := "" +// if reflect.TypeOf(myStruct).Kind() != reflect.Struct { +// return retStr +// } +// myType := reflect.TypeOf(myStruct) +// field, ok := myType.FieldByName(name) +// if ok { +// retStr = field.Tag.Get("lopt") +// } +// return retStr - } - } +// } - } - return optionsMap -} - -/* -Helper function which gets the lopt of a given interface -*/ -func GetLoptOf(myStruct interface{}, name string) string { - retStr := "" - if reflect.TypeOf(myStruct).Kind() != reflect.Struct { - return retStr - } - myType := reflect.TypeOf(myStruct) - field, ok := myType.FieldByName(name) - if ok { - retStr = field.Tag.Get("lopt") - } - return retStr - -} - -/* -Returns a translation map of field name and its associated lopt. -*/ -func GetloptMap(myStruct interface{}) map[string]string { - retMap := make(map[string]string) - if reflect.TypeOf(myStruct).Kind() != reflect.Struct { - return retMap - } - structType := reflect.TypeOf(myStruct) - for i := 0; i < structType.NumField(); i++ { - retMap[structType.Field(i).Name] = structType.Field(i).Name - lopt := structType.Field(i).Tag.Get("lopt") - if lopt != "" { - retMap[structType.Field(i).Name] = lopt - } - } - return retMap -} +// /* +// Returns a translation map of field name and its associated lopt. +// */ +// func GetloptMap(myStruct interface{}) map[string]string { +// retMap := make(map[string]string) +// if reflect.TypeOf(myStruct).Kind() != reflect.Struct { +// return retMap +// } +// structType := reflect.TypeOf(myStruct) +// for i := 0; i < structType.NumField(); i++ { +// retMap[structType.Field(i).Name] = structType.Field(i).Name +// lopt := structType.Field(i).Tag.Get("lopt") +// if lopt != "" { +// retMap[structType.Field(i).Name] = lopt +// } +// } +// return retMap +// } diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index aac784b3..8653a78a 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -2,6 +2,9 @@ package node import ( "reflect" + + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/spf13/cobra" ) /* @@ -132,6 +135,74 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, */ } } +func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) { + // nodeInfoType := reflect.TypeOf(nodeConf) + nodeInfoVal := reflect.ValueOf(nodeConf) + // now iterate of every field + for i := 0; i < nodeInfoVal.Elem().NumField(); i++ { + field := nodeInfoVal.Elem().Type().Field(i) + //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) + // if field.Type.Kind() == reflect.Ptr { + // a := structVal.Field(i).Elem().Interface() + // subStruct := baseCmd.CreateFlags(a, excludeList) + // for key, val := range subStruct { + // optionsMap[field.Name+"."+key] = val + // } + + // } else if field.Type.Kind() == reflect.Map { + // // check the type of map + // mapType := field.Type.Elem() + // if mapType.Kind() == reflect.Ptr { + // //a := reflect.ValueOf((mapType.Elem())) node.NetDevs + // subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) + // for key, val := range subMap { + // optionsMap[field.Name+"."+key] = val + // } + // if mapType == reflect.TypeOf((*NetDevs)(nil)) { + // // set the option for the network name here + // var netName string + // optionsMap[field.Name] = &netName + // baseCmd.PersistentFlags().StringVarP(&netName, + // "netname", "n", "", "Define the network name to configure") + // } + // } else + // if mapType.Kind() == reflect.String { + // if field.Tag.Get("lopt") != "" { + // baseCmd.PersistentFlags().StringVarP(nodeInfoVal.Field(i).Interface()(string), + // field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) + // var delPair string + // optionsMap["del"+"."+field.Name] = &delPair + // baseCmd.PersistentFlags().StringVarP(&delPair, + // field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) + // } + // } else { + // // TODO: implement handling of string maps + // wwlog.Warn("handling of %v not implemented\n", field.Type) + // } + + // } else + if field.Type.Kind() == reflect.String && + field.Tag.Get("comment") != "" && + !util.InSlice(excludeList, field.Tag.Get("lopt")) { + ptr := nodeInfoVal.Elem().Field(i).Addr().Interface().(*string) + if field.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringVarP(ptr, + field.Tag.Get("lopt"), + field.Tag.Get("sopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { + baseCmd.PersistentFlags().StringVar(ptr, + field.Tag.Get("lopt"), + field.Tag.Get("default"), + field.Tag.Get("comment")) + + } + } + + } + // return optionsMap +} /* Populates all fields of NodeInfo with Set from the From 063c781710324020fd702a4c58f1f9423e0b2005 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 19 Aug 2022 09:47:07 +0200 Subject: [PATCH 36/38] recreate CreateFlag based on NodeConf This will always create the network named default, so this has to be changed if a new netowk is set --- internal/pkg/node/datastructure.go | 11 +- internal/pkg/node/methods.go | 345 ----------------------------- internal/pkg/node/transformers.go | 125 ++++++----- 3 files changed, 76 insertions(+), 405 deletions(-) diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 1255dd53..2e259a5b 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -48,8 +48,9 @@ type NodeConf struct { Discoverable string `yaml:"discoverable,omitempty" lopt:"discoverable" comment:"Make discoverable in given network (yes/no)"` Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` - Tags map[string]string `yaml:"tags,omitempty" lopt:"tag" comment:"base key"` - Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility + Tags map[string]string `yaml:"tags,omitempty" lopt:"tagadd" comment:"base key"` + TagsDel []string `lopt:"tagdel" comment:"remove this tags"` // does not go to disk only to wire + Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility } type IpmiConf struct { @@ -61,7 +62,8 @@ type IpmiConf struct { Gateway string `yaml:"gateway,omitempty" lopt:"ipmigateway" comment:"Set the IPMI gateway"` Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` - Tags map[string]string `yaml:"tags,omitempty" lopt:"ipmitag" comment:"ipmi keys"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"ipmitagadd" comment:"add ipmitags"` + TagsDel []string `lopt:"ipmitagdel" comment:"remove ipmitags"` // does not go to disk only to wire } type KernelConf struct { Version string `yaml:"version,omitempty"` @@ -82,7 +84,8 @@ type NetDevs struct { Gateway string `yaml:"gateway,omitempty" lopt:"gateway" sopt:"G" comment:"Set the node's network device gateway"` Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)"` Default string `yaml:"default,omitempty"` /* backward compatibility */ - Tags map[string]string `yaml:"tags,omitempty" lopt:"nettag" comment:"network keys"` + Tags map[string]string `yaml:"tags,omitempty" lopt:"nettagadd" comment:"network tags"` + TagsDel []string `lopt:"nettagdel" comment:"delete network tags"` // does not go to disk only to wire } /****** diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 5780937e..267f265b 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -318,348 +318,3 @@ func NewConf() (nodeconf NodeConf) { nodeconf.NetDevs = map[string]*NetDevs{} return nodeconf } - -// /* -// Set the Entry trough an interface by trying to cast the interface -// */ -// func SetEntry(entryPtr interface{}, val interface{}) { -// valKind := reflect.TypeOf(val) -// if reflect.TypeOf(entryPtr) == reflect.TypeOf((*Entry)(nil)) { -// entry := entryPtr.(*Entry) -// if valKind.Kind() == reflect.String { -// entry.Set(val.(string)) -// } else if valKind.Kind() == reflect.Slice { -// if valKind.Elem().Kind() == reflect.String { -// entry.SetSlice(val.([]string)) -// } else { -// panic("Got unknown slice type") -// } -// } -// } else if reflect.TypeOf(entryPtr) == reflect.TypeOf((*[]string)(nil)) { -// entry := entryPtr.(*[]string) -// if valKind.Kind() == reflect.String { -// // most likely we got a comma seperated string slice -// *entry = strings.Split(val.(string), ",") -// } else if valKind.Kind() == reflect.Slice { -// if valKind.Elem().Kind() == reflect.String { -// *entry = val.([]string) -// } else { -// panic("Got unknown slice type") -// } -// } -// } else { -// panic(fmt.Sprintf("Can't convert %s to *node.Entry to call Set\n", reflect.TypeOf(entryPtr))) -// } - -// } - -// /* -// Add an entry in a map -// */ -// func addEntry(entryMapInt interface{}, val interface{}) { -// if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { -// if reflect.ValueOf(entryMapInt).Elem().IsNil() { -// newMap := make(map[string]*Entry) -// entryMapInt = &newMap -// } -// entryMap := entryMapInt.(*map[string]*Entry) -// str, ok := (val).(string) -// if !ok { -// panic("AddEntry must be called with string value") -// } -// for _, token := range strings.Split(str, ",") { -// keyVal := strings.Split(token, "=") -// if len(keyVal) == 2 { -// _, mapOk := (*entryMap)[keyVal[0]] -// if !mapOk { -// (*entryMap)[keyVal[0]] = new(Entry) -// } -// (*entryMap)[keyVal[0]].Set(keyVal[1]) -// } -// } -// } else { -// panic(fmt.Sprintf("Do not know how to add %v to %v\n", val, entryMapInt)) -// } -// } - -// /* -// Del an entry in a map -// */ -// func delEntry(entryMapInt interface{}, val interface{}) { -// if reflect.TypeOf(entryMapInt) == reflect.TypeOf((*map[string]*Entry)(nil)) { -// entryMap := entryMapInt.(*map[string]*Entry) -// str, ok := (val).(string) -// if !ok { -// panic("DelEntry must be called with string value") -// } -// for _, token := range strings.Split(str, ",") { -// delete(*entryMap, token) -// } -// } else { -// panic(fmt.Sprintf("Do not know how to del %v to %v\n", val, entryMapInt)) -// } - -// } - -// /* -// Call SetEntry for given field (NodeInfo). -// */ -// func (node *NodeInfo) SetField(fieldName string, val interface{}) { -// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) -// if field.IsValid() { -// if field.Addr().Type() == reflect.TypeOf((*Entry)(nil)) { -// SetEntry(field.Addr().Interface(), val) -// } else if field.Addr().Type() == reflect.TypeOf((*[]string)(nil)) { -// SetEntry(field.Addr().Interface(), val) -// } -// /* -// else if field.Addr().Kind() == reflect.Map { -// fmt.Println(field.Addr()) -// } else { -// //fmt.Println("Not working field.Addr().Kind():", field.Addr().Type()) -// // is most likely NetDevEntry, ignore it -// } -// */ -// } else { -// fieldNames := strings.Split(fieldName, ".") -// if len(fieldNames) >= 2 { -// if fieldNames[0] == "del" || fieldNames[0] == "add" { -// fieldMap := reflect.ValueOf(node).Elem().FieldByName(fieldNames[1]) -// if fieldMap.IsValid() { -// if fieldNames[0] == "del" { -// delEntry(fieldMap.Addr().Interface(), val) -// } else if fieldNames[0] == "add" { -// addEntry(fieldMap.Addr().Interface(), val) -// } -// } else { -// panic(fmt.Sprintf("invalid del/add operation with name %s called, field %s does not exists\n", fieldName, fieldNames[0])) -// } -// } else { -// nestedField := reflect.ValueOf(node).Elem().FieldByName(fieldNames[0]) -// if nestedField.IsValid() { -// switch nestedField.Addr().Type() { -// case reflect.TypeOf((**KernelEntry)(nil)): -// entry := nestedField.Addr().Interface().(**KernelEntry) -// (*entry).SetField(strings.Join(fieldNames[1:], "."), val) -// case reflect.TypeOf((**IpmiEntry)(nil)): -// entry := nestedField.Addr().Interface().(**IpmiEntry) -// (*entry).SetField(strings.Join(fieldNames[1:], "."), val) -// case reflect.TypeOf((*map[string]*NetDevEntry)(nil)): -// if len(fieldNames) >= 3 { -// entryMap := nestedField.Addr().Interface().(*map[string]*NetDevEntry) -// if myVal, ok := (*entryMap)[fieldNames[1]]; ok { -// myVal.SetField(strings.Join(fieldNames[2:], "."), val) -// } else { -// var newEntry NetDevEntry -// (*entryMap)[fieldNames[1]] = &newEntry -// newEntry.SetField(strings.Join(fieldNames[2:], "."), val) -// } -// } -// default: -// panic(fmt.Sprintf("not implemented type %v\n", nestedField.Addr().Type())) -// } -// } else { -// panic(fmt.Sprintf("field %s is not a nested type of %s", fieldNames[0], fieldName)) -// } -// } -// } else { -// panic(fmt.Sprintf("field %s does not exists in node.NodeInfo\n", fieldName)) -// } -// } - -// } - -// /* -// Call SetEntry for given field (KernelEntry) -// */ -// func (node *KernelEntry) SetField(fieldName string, val interface{}) { -// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) -// if field.IsValid() { -// SetEntry(field.Addr().Interface(), val) -// } else { -// valFields := strings.Split(fieldName, ".") -// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) -// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { -// addEntry(field.Addr().Interface(), val) -// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { -// delEntry(field.Addr().Interface(), val) -// } else { -// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) -// } -// } -// } - -// /* -// Call SetEntry for given field (ImpiEntry) -// */ -// func (node *IpmiEntry) SetField(fieldName string, val interface{}) { -// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) -// if field.IsValid() { -// SetEntry(field.Addr().Interface(), val) -// } else { -// valFields := strings.Split(fieldName, ".") -// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) -// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { -// addEntry(field.Addr().Interface(), val) -// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { -// delEntry(field.Addr().Interface(), val) -// } else { -// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) -// } -// } -// } - -// /* -// Call SetEntry for given field (NetDevEntry) -// */ -// func (node *NetDevEntry) SetField(fieldName string, val interface{}) { -// field := reflect.ValueOf(node).Elem().FieldByName(fieldName) -// if field.IsValid() { -// SetEntry(field.Addr().Interface(), val) -// } else { -// valFields := strings.Split(fieldName, ".") -// field = reflect.ValueOf(node).Elem().FieldByName(valFields[1]) -// if field.IsValid() && len(valFields) == 2 && valFields[0] == "add" { -// addEntry(field.Addr().Interface(), val) -// } else if field.IsValid() && len(valFields) == 2 && valFields[0] == "del" { -// delEntry(field.Addr().Interface(), val) -// } else { -// panic(fmt.Sprintf("field %s does not exists in node.NetDevEntry\n", fieldName)) -// } -// } -// } - -// /* -// Get all names of the fields in the given struct (recursive) -// and create a map[name of struct field]*string if the the field -// of the struct bears the comment tag. -// */ -// func GetOptionsMap(theStruct interface{}) map[string]*string { -// optionsMap := make(map[string]*string) -// structVal := reflect.ValueOf(theStruct) -// structTyp := structVal.Type() -// for i := 0; i < structVal.NumField(); i++ { -// field := structTyp.Field(i) -// if field.Type.Kind() == reflect.Struct { -// subStruct := GetOptionsMap(field) -// for key, val := range subStruct { -// optionsMap[key] = val -// } -// } else if field.Tag.Get("comment") != "" { -// optionsMap[field.Name] = new(string) -// } - -// } -// return optionsMap -// } - -// type CobraCommand struct { -// *cobra.Command -// } - -/* -Get all names of the fields in the given struct (recursive) -and create a map[name of struct field]*string if the the field -of the struct bears the comment tag. -*/ -// func (baseCmd *CobraCommand) CreateFlags(theStruct interface{}, excludeList []string) map[string]*string { -// structVal := reflect.ValueOf(theStruct) -// for i := 0; i < structVal.NumField(); i++ { -// field := structVal.Type().Field(i) -// //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) -// if field.Type.Kind() == reflect.Ptr { -// a := structVal.Field(i).Elem().Interface() -// subStruct := baseCmd.CreateFlags(a, excludeList) -// for key, val := range subStruct { -// optionsMap[field.Name+"."+key] = val -// } - -// } else if field.Type.Kind() == reflect.Map { -// // check the type of map -// mapType := field.Type.Elem() -// if mapType.Kind() == reflect.Ptr { -// //a := reflect.ValueOf((mapType.Elem())) node.NetDevs -// subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) -// for key, val := range subMap { -// optionsMap[field.Name+"."+key] = val -// } -// if mapType == reflect.TypeOf((*NetDevs)(nil)) { -// // set the option for the network name here -// var netName string -// optionsMap[field.Name] = &netName -// baseCmd.PersistentFlags().StringVarP(&netName, -// "netname", "n", "", "Define the network name to configure") -// } -// } else if mapType.Kind() == reflect.String { -// if field.Tag.Get("lopt") != "" { -// var addPair string -// optionsMap["add"+"."+field.Name] = &addPair -// baseCmd.PersistentFlags().StringVarP(&addPair, -// field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) -// var delPair string -// optionsMap["del"+"."+field.Name] = &delPair -// baseCmd.PersistentFlags().StringVarP(&delPair, -// field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) -// } -// } else { -// // TODO: implement handling of string maps -// wwlog.Warn("handling of %v not implemented\n", field.Type) -// } - -// } else if field.Tag.Get("comment") != "" && !util.InSlice(excludeList, field.Tag.Get("lopt")) { -// var newStr string -// optionsMap[field.Name] = &newStr -// if field.Tag.Get("sopt") != "" { -// baseCmd.PersistentFlags().StringVarP(&newStr, -// field.Tag.Get("lopt"), -// field.Tag.Get("sopt"), -// field.Tag.Get("default"), -// field.Tag.Get("comment")) -// } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { -// baseCmd.PersistentFlags().StringVar(&newStr, -// field.Tag.Get("lopt"), -// field.Tag.Get("default"), -// field.Tag.Get("comment")) - -// } -// } - -// } -// return optionsMap -// } - -// /* -// Helper function which gets the lopt of a given interface -// */ -// func GetLoptOf(myStruct interface{}, name string) string { -// retStr := "" -// if reflect.TypeOf(myStruct).Kind() != reflect.Struct { -// return retStr -// } -// myType := reflect.TypeOf(myStruct) -// field, ok := myType.FieldByName(name) -// if ok { -// retStr = field.Tag.Get("lopt") -// } -// return retStr - -// } - -// /* -// Returns a translation map of field name and its associated lopt. -// */ -// func GetloptMap(myStruct interface{}) map[string]string { -// retMap := make(map[string]string) -// if reflect.TypeOf(myStruct).Kind() != reflect.Struct { -// return retMap -// } -// structType := reflect.TypeOf(myStruct) -// for i := 0; i < structType.NumField(); i++ { -// retMap[structType.Field(i).Name] = structType.Field(i).Name -// lopt := structType.Field(i).Tag.Get("lopt") -// if lopt != "" { -// retMap[structType.Field(i).Name] = lopt -// } -// } -// return retMap -// } diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 8653a78a..ce5e039a 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -136,72 +136,85 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, } } func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) { - // nodeInfoType := reflect.TypeOf(nodeConf) + nodeInfoType := reflect.TypeOf(nodeConf) nodeInfoVal := reflect.ValueOf(nodeConf) // now iterate of every field for i := 0; i < nodeInfoVal.Elem().NumField(); i++ { - field := nodeInfoVal.Elem().Type().Field(i) - //fmt.Printf("%s: field.Kind() == %s\n", field.Name, field.Type.Kind()) - // if field.Type.Kind() == reflect.Ptr { - // a := structVal.Field(i).Elem().Interface() - // subStruct := baseCmd.CreateFlags(a, excludeList) - // for key, val := range subStruct { - // optionsMap[field.Name+"."+key] = val - // } + if nodeInfoType.Elem().Field(i).Tag.Get("comment") != "" && + !util.InSlice(excludeList, nodeInfoType.Elem().Field(i).Tag.Get("lopt")) { + createFlags(baseCmd, excludeList, nodeInfoType.Elem().Field(i), nodeInfoVal.Elem().Field(i)) + } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { + nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) + nestVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) + for j := 0; j < nestType.Elem().NumField(); j++ { + createFlags(baseCmd, excludeList, nestType.Elem().Field(j), nestVal.Elem().Field(j)) + } + } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { + netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) + // add a default network so that it can hold values + netMap["default"] = new(NetDevs) + netType := reflect.TypeOf(netMap["default"]) + netVal := reflect.ValueOf(netMap["default"]) + for j := 0; j < netType.Elem().NumField(); j++ { + createFlags(baseCmd, excludeList, netType.Elem().Field(j), netVal.Elem().Field(j)) + } + } + } +} - // } else if field.Type.Kind() == reflect.Map { - // // check the type of map - // mapType := field.Type.Elem() - // if mapType.Kind() == reflect.Ptr { - // //a := reflect.ValueOf((mapType.Elem())) node.NetDevs - // subMap := baseCmd.CreateFlags(reflect.New(mapType.Elem()).Elem().Interface(), excludeList) - // for key, val := range subMap { - // optionsMap[field.Name+"."+key] = val - // } - // if mapType == reflect.TypeOf((*NetDevs)(nil)) { - // // set the option for the network name here - // var netName string - // optionsMap[field.Name] = &netName - // baseCmd.PersistentFlags().StringVarP(&netName, - // "netname", "n", "", "Define the network name to configure") - // } - // } else - // if mapType.Kind() == reflect.String { - // if field.Tag.Get("lopt") != "" { - // baseCmd.PersistentFlags().StringVarP(nodeInfoVal.Field(i).Interface()(string), - // field.Tag.Get("lopt")+"add", "", "", "Add key/value pair to "+field.Tag.Get("comment")) - // var delPair string - // optionsMap["del"+"."+field.Name] = &delPair - // baseCmd.PersistentFlags().StringVarP(&delPair, - // field.Tag.Get("lopt")+"del", "", "", "Delete key/value pair to "+field.Tag.Get("comment")) - // } - // } else { - // // TODO: implement handling of string maps - // wwlog.Warn("handling of %v not implemented\n", field.Type) - // } - - // } else - if field.Type.Kind() == reflect.String && - field.Tag.Get("comment") != "" && - !util.InSlice(excludeList, field.Tag.Get("lopt")) { - ptr := nodeInfoVal.Elem().Field(i).Addr().Interface().(*string) - if field.Tag.Get("sopt") != "" { +/* +Helper function to create the different PerisitantFlags() for different types. +*/ +func createFlags(baseCmd *cobra.Command, excludeList []string, + myType reflect.StructField, myVal reflect.Value) { + if myType.Tag.Get("lopt") != "" { + if myType.Type.Kind() == reflect.String { + ptr := myVal.Addr().Interface().(*string) + if myType.Tag.Get("sopt") != "" { baseCmd.PersistentFlags().StringVarP(ptr, - field.Tag.Get("lopt"), - field.Tag.Get("sopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) - } else if !util.InSlice(excludeList, field.Tag.Get("lopt")) { + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + myType.Tag.Get("default"), + myType.Tag.Get("comment")) + } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { baseCmd.PersistentFlags().StringVar(ptr, - field.Tag.Get("lopt"), - field.Tag.Get("default"), - field.Tag.Get("comment")) + myType.Tag.Get("lopt"), + myType.Tag.Get("default"), + myType.Tag.Get("comment")) + + } + } else if myType.Type == reflect.TypeOf([]string{}) { + ptr := myVal.Addr().Interface().(*[]string) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringSliceVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + []string{myType.Tag.Get("default")}, + myType.Tag.Get("comment")) + } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { + baseCmd.PersistentFlags().StringSliceVar(ptr, + myType.Tag.Get("lopt"), + []string{myType.Tag.Get("default")}, + myType.Tag.Get("comment")) + + } + } else if myType.Type == reflect.TypeOf(map[string]string{}) { + ptr := myVal.Addr().Interface().(*map[string]string) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().StringToStringVarP(ptr, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + map[string]string{}, // empty default! + myType.Tag.Get("comment")) + } else if !util.InSlice(excludeList, myType.Tag.Get("lopt")) { + baseCmd.PersistentFlags().StringToStringVar(ptr, + myType.Tag.Get("lopt"), + map[string]string{}, // empty default! + myType.Tag.Get("comment")) } } - } - // return optionsMap } /* From 255ff61dc8fcbe753301591f12ccf525348287f3 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 31 Aug 2022 15:42:57 +0200 Subject: [PATCH 37/38] adding netname option back --- internal/app/wwctl/node/add/main.go | 17 ++++++++--------- internal/app/wwctl/node/add/root.go | 9 ++++++--- internal/app/wwctl/node/set/main.go | 17 ++++++++--------- internal/app/wwctl/node/set/root.go | 8 +++++--- internal/app/wwctl/profile/add/main.go | 17 ++++++++--------- internal/app/wwctl/profile/add/root.go | 8 +++++--- internal/app/wwctl/profile/set/main.go | 15 ++++++++++----- internal/app/wwctl/profile/set/root.go | 8 +++++--- internal/pkg/node/datastructure.go | 8 ++++---- internal/pkg/node/methods.go | 2 ++ internal/pkg/node/transformers.go | 11 +++++++---- 11 files changed, 68 insertions(+), 52 deletions(-) diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 4837809d..762907bf 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -12,16 +12,15 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - // if netWithoutName { - // return errors.New("a netname must be given for any network related configuration") - // } - // realMap := make(map[string]string) + // remove the default network as the all network values are assigned + // to this network + if NetName != "" { + netDev := *NodeConf.NetDevs["default"] + NodeConf.NetDevs[NetName] = &netDev + delete(NodeConf.NetDevs, "default") - // for key, val := range OptionStrMap { - // realMap[key] = *val - // } - buffer, err := yaml.Marshal(nodeConf) + } + buffer, err := yaml.Marshal(NodeConf) if err != nil { wwlog.Error("Cant marshall nodeInfo", err) os.Exit(1) diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index 18dee9ae..76297f9a 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -19,12 +19,15 @@ var ( RunE: CobraRunE, Args: cobra.MinimumNArgs(1), } - nodeConf node.NodeConf + NodeConf node.NodeConf + NetName string ) func init() { - nodeConf := node.NewConf() - nodeConf.CreateFlags(baseCmd, []string{}) + NodeConf = node.NewConf() + NodeConf.CreateFlags(baseCmd, []string{}) + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index c7c6be47..e71a5d10 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -13,16 +13,15 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - // if netWithoutName { - // return errors.New("a netname must be given for any network related configuration") - // } - // realMap := make(map[string]string) + // remove the default network as the all network values are assigned + // to this network + if NetName != "" { + netDev := *NodeConf.NetDevs["default"] + NodeConf.NetDevs[NetName] = &netDev + delete(NodeConf.NetDevs, "default") - // for key, val := range OptionStrMap { - // realMap[key] = *val - // } - buffer, err := yaml.Marshal(nodeConf) + } + buffer, err := yaml.Marshal(NodeConf) if err != nil { wwlog.Error("Cant marshall nodeInfo", err) os.Exit(1) diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index 3e0a4675..b3087897 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -33,16 +33,18 @@ var ( }, } SetNetDevDel string + NetName string SetNodeAll bool SetYes bool SetForce bool - nodeConf node.NodeConf + NodeConf node.NodeConf ) func init() { - nodeConf := node.NewConf() - nodeConf.CreateFlags(baseCmd, []string{}) + NodeConf = node.NewConf() + NodeConf.CreateFlags(baseCmd, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") diff --git a/internal/app/wwctl/profile/add/main.go b/internal/app/wwctl/profile/add/main.go index 3e689a3d..0260f232 100644 --- a/internal/app/wwctl/profile/add/main.go +++ b/internal/app/wwctl/profile/add/main.go @@ -14,16 +14,15 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - // if netWithoutName { - // return errors.New("a netname must be given for any network related configuration") - // } - // realMap := make(map[string]string) + // remove the default network as the all network values are assigned + // to this network + if NetName != "" { + netDev := *ProfileConf.NetDevs["default"] + ProfileConf.NetDevs[NetName] = &netDev + delete(ProfileConf.NetDevs, "default") - // for key, val := range OptionStrMap { - // realMap[key] = *val - // } - buffer, err := yaml.Marshal(profileConf) + } + buffer, err := yaml.Marshal(ProfileConf) if err != nil { wwlog.Error("Cant marshall nodeInfo", err) os.Exit(1) diff --git a/internal/app/wwctl/profile/add/root.go b/internal/app/wwctl/profile/add/root.go index a7e60b26..14694477 100644 --- a/internal/app/wwctl/profile/add/root.go +++ b/internal/app/wwctl/profile/add/root.go @@ -23,14 +23,16 @@ var ( SetNodeAll bool SetYes bool SetForce bool - profileConf node.NodeConf + NetName string + ProfileConf node.NodeConf ) // GetRootCommand returns the root cobra.Command for the application. func GetCommand() *cobra.Command { - profileConf = node.NewConf() - profileConf.CreateFlags(baseCmd, + ProfileConf = node.NewConf() + ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { list, _ := container.ListSources() diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index 43e0446a..d0d8dcfd 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -13,11 +13,16 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) (err error) { - // OptionStrMap, netWithoutName := apinode.AddNetname(OptionStrMap) - // if netWithoutName { - // return errors.New("a netname must be given for any network related configuration") - // } - buffer, err := yaml.Marshal(profileConf) + + // remove the default network as the all network values are assigned + // to this network + if NetName != "" { + netDev := *ProfileConf.NetDevs["default"] + ProfileConf.NetDevs[NetName] = &netDev + delete(ProfileConf.NetDevs, "default") + + } + buffer, err := yaml.Marshal(ProfileConf) if err != nil { wwlog.Error("Cant marshall nodeInfo", err) os.Exit(1) diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 577e0312..807d2367 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -36,13 +36,15 @@ var ( SetNodeAll bool SetYes bool SetForce bool - profileConf node.NodeConf + NetName string + ProfileConf node.NodeConf ) func init() { - profileConf = node.NewConf() - profileConf.CreateFlags(baseCmd, + ProfileConf = node.NewConf() + ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 2e259a5b..6efc2959 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -49,8 +49,8 @@ type NodeConf struct { Profiles []string `yaml:"profiles,omitempty" lopt:"profile" sopt:"P" comment:"Set the node's profile members (comma separated)"` NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"` Tags map[string]string `yaml:"tags,omitempty" lopt:"tagadd" comment:"base key"` - TagsDel []string `lopt:"tagdel" comment:"remove this tags"` // does not go to disk only to wire - Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility + TagsDel []string `yaml:"tagsdel,omitempty" lopt:"tagdel" comment:"remove this tags"` // should not go to disk only to wire + Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility } type IpmiConf struct { @@ -63,7 +63,7 @@ type IpmiConf struct { Interface string `yaml:"interface,omitempty" lopt:"ipmiinterface" comment:"Set the node's IPMI interface (defaults: 'lan')"` Write string `yaml:"write,omitempty" lopt:"ipmiwrite" comment:"Enable the write of impi configuration (yes/no)"` Tags map[string]string `yaml:"tags,omitempty" lopt:"ipmitagadd" comment:"add ipmitags"` - TagsDel []string `lopt:"ipmitagdel" comment:"remove ipmitags"` // does not go to disk only to wire + TagsDel []string `yaml:"tagsdel,omitempty" lopt:"ipmitagdel" comment:"remove ipmitags"` // should not go to disk only to wire } type KernelConf struct { Version string `yaml:"version,omitempty"` @@ -85,7 +85,7 @@ type NetDevs struct { Primary string `yaml:"primary,omitempty" lopt:"primary" comment:"Enable/disable network device as primary (yes/no)"` Default string `yaml:"default,omitempty"` /* backward compatibility */ Tags map[string]string `yaml:"tags,omitempty" lopt:"nettagadd" comment:"network tags"` - TagsDel []string `lopt:"nettagdel" comment:"delete network tags"` // does not go to disk only to wire + TagsDel []string `yaml:"tagsdel,omitempty" lopt:"nettagdel" comment:"delete network tags"` // should not go to disk only to wire } /****** diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 267f265b..f33b7c3a 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -81,6 +81,8 @@ func (ent *Entry) SetB(val bool) { func (ent *Entry) SetSlice(val []string) { if len(val) == 0 { return + } else if len(val) == 1 && val[0] == "" { // check also for an "empty" slice + return } if val[0] == "UNDEF" || val[0] == "DELETE" || val[0] == "UNSET" || val[0] == "--" { ent.value = []string{} diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index ce5e039a..4a2369f9 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -142,12 +142,14 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri for i := 0; i < nodeInfoVal.Elem().NumField(); i++ { if nodeInfoType.Elem().Field(i).Tag.Get("comment") != "" && !util.InSlice(excludeList, nodeInfoType.Elem().Field(i).Tag.Get("lopt")) { - createFlags(baseCmd, excludeList, nodeInfoType.Elem().Field(i), nodeInfoVal.Elem().Field(i)) + field := nodeInfoVal.Elem().Field(i) + createFlags(baseCmd, excludeList, nodeInfoType.Elem().Field(i), &field) } else if nodeInfoType.Elem().Field(i).Type.Kind() == reflect.Ptr { nestType := reflect.TypeOf(nodeInfoVal.Elem().Field(i).Interface()) nestVal := reflect.ValueOf(nodeInfoVal.Elem().Field(i).Interface()) for j := 0; j < nestType.Elem().NumField(); j++ { - createFlags(baseCmd, excludeList, nestType.Elem().Field(j), nestVal.Elem().Field(j)) + field := nestVal.Elem().Field(j) + createFlags(baseCmd, excludeList, nestType.Elem().Field(j), &field) } } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) @@ -156,7 +158,8 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri netType := reflect.TypeOf(netMap["default"]) netVal := reflect.ValueOf(netMap["default"]) for j := 0; j < netType.Elem().NumField(); j++ { - createFlags(baseCmd, excludeList, netType.Elem().Field(j), netVal.Elem().Field(j)) + field := netVal.Elem().Field(j) + createFlags(baseCmd, excludeList, netType.Elem().Field(j), &field) } } } @@ -166,7 +169,7 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri Helper function to create the different PerisitantFlags() for different types. */ func createFlags(baseCmd *cobra.Command, excludeList []string, - myType reflect.StructField, myVal reflect.Value) { + myType reflect.StructField, myVal *reflect.Value) { if myType.Tag.Get("lopt") != "" { if myType.Type.Kind() == reflect.String { ptr := myVal.Addr().Interface().(*string) From 18eb531d4b884a8d660404ec3e0540829eaf5ffe Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 1 Sep 2022 10:08:31 +0200 Subject: [PATCH 38/38] fixed deletion of network and deletion of tags --- internal/app/wwctl/node/set/main.go | 8 +- internal/app/wwctl/node/set/root.go | 2 +- internal/app/wwctl/profile/list/main.go | 2 +- internal/app/wwctl/profile/set/main.go | 6 +- internal/app/wwctl/profile/set/root.go | 2 +- internal/pkg/api/node/list.go | 4 +- internal/pkg/api/node/node.go | 15 ++- internal/pkg/api/profile/profile.go | 20 ++-- internal/pkg/node/constructors.go | 10 ++ internal/pkg/node/transformers.go | 130 ++++++++++++++++++------ 10 files changed, 144 insertions(+), 55 deletions(-) diff --git a/internal/app/wwctl/node/set/main.go b/internal/app/wwctl/node/set/main.go index e71a5d10..63dad15f 100644 --- a/internal/app/wwctl/node/set/main.go +++ b/internal/app/wwctl/node/set/main.go @@ -15,15 +15,13 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) (err error) { // remove the default network as the all network values are assigned // to this network - if NetName != "" { - netDev := *NodeConf.NetDevs["default"] - NodeConf.NetDevs[NetName] = &netDev + if NetName != "default" { + NodeConf.NetDevs[NetName] = NodeConf.NetDevs["default"] delete(NodeConf.NetDevs, "default") - } buffer, err := yaml.Marshal(NodeConf) if err != nil { - wwlog.Error("Cant marshall nodeInfo", err) + wwlog.Error("Can't marshall nodeInfo", err) os.Exit(1) } set := wwapiv1.NodeSetParameter{ diff --git a/internal/app/wwctl/node/set/root.go b/internal/app/wwctl/node/set/root.go index b3087897..0e5e81cf 100644 --- a/internal/app/wwctl/node/set/root.go +++ b/internal/app/wwctl/node/set/root.go @@ -44,7 +44,7 @@ func init() { NodeConf = node.NewConf() NodeConf.CreateFlags(baseCmd, []string{}) baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") - baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") baseCmd.PersistentFlags().BoolVarP(&SetForce, "force", "f", false, "Force configuration (even on error)") diff --git a/internal/app/wwctl/profile/list/main.go b/internal/app/wwctl/profile/list/main.go index 7e8d7163..2c9782ef 100644 --- a/internal/app/wwctl/profile/list/main.go +++ b/internal/app/wwctl/profile/list/main.go @@ -70,7 +70,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } } else { fmt.Printf("%-20s %s\n", "PROFILE NAME", "COMMENT/DESCRIPTION") - fmt.Println(strings.Repeat("=", 80)) + fmt.Printf(strings.Repeat("=", 80) + "\n") for _, profile := range node.FilterByName(profiles, args) { fmt.Printf("%-20s %s\n", profile.Id.Print(), profile.Comment.Print()) diff --git a/internal/app/wwctl/profile/set/main.go b/internal/app/wwctl/profile/set/main.go index d0d8dcfd..f905f2a9 100644 --- a/internal/app/wwctl/profile/set/main.go +++ b/internal/app/wwctl/profile/set/main.go @@ -16,11 +16,9 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { // remove the default network as the all network values are assigned // to this network - if NetName != "" { - netDev := *ProfileConf.NetDevs["default"] - ProfileConf.NetDevs[NetName] = &netDev + if NetName != "default" { + ProfileConf.NetDevs[NetName] = ProfileConf.NetDevs["default"] delete(ProfileConf.NetDevs, "default") - } buffer, err := yaml.Marshal(ProfileConf) if err != nil { diff --git a/internal/app/wwctl/profile/set/root.go b/internal/app/wwctl/profile/set/root.go index 807d2367..f95cbb6c 100644 --- a/internal/app/wwctl/profile/set/root.go +++ b/internal/app/wwctl/profile/set/root.go @@ -44,7 +44,7 @@ func init() { ProfileConf = node.NewConf() ProfileConf.CreateFlags(baseCmd, []string{"ipaddr", "ipaddr6", "ipmiaddr", "profile"}) - baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + baseCmd.PersistentFlags().StringVar(&NetName, "netname", "default", "Set network name for network options") baseCmd.PersistentFlags().StringVarP(&SetNetDevDel, "netdel", "D", "", "Delete the node's network device") baseCmd.PersistentFlags().BoolVarP(&SetNodeAll, "all", "a", false, "Set all nodes") baseCmd.PersistentFlags().BoolVarP(&SetYes, "yes", "y", false, "Set 'yes' to all questions asked") diff --git a/internal/pkg/api/node/list.go b/internal/pkg/api/node/list.go index f31b8604..f8f995eb 100644 --- a/internal/pkg/api/node/list.go +++ b/internal/pkg/api/node/list.go @@ -131,11 +131,11 @@ func NodeList(nodeGet *wwapiv1.GetNodeList) (nodeList wwapiv1.NodeList, err erro } } else if netInfoType.Field(j).Type == reflect.TypeOf(map[string]*node.Entry{}) { for key, val := range netInfoVal.Field(j).Interface().(map[string]*node.Entry) { - fieldName = fieldName + ":" + key + keyfieldName := fieldName + ":" + key fieldSource = val.Source() fieldVal = val.Print() nodeList.Output = append(nodeList.Output, - fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), fieldName, fieldSource, fieldVal)) + fmt.Sprintf("%-20s %-18s %-12s %s", n.Id.Print(), keyfieldName, fieldSource, fieldVal)) } } diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index e3c7d890..e34169b8 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -238,7 +238,6 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB } n.SetFrom(&nodeConf) if set.NetdevDelete != "" { - if _, ok := n.NetDevs[set.NetdevDelete]; !ok { err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete) wwlog.Printf(wwlog.ERROR, fmt.Sprintf("%v\n", err.Error())) @@ -248,7 +247,19 @@ func NodeSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB wwlog.Printf(wwlog.VERBOSE, "Node: %s, Deleting network device: %s\n", n.Id.Get(), set.NetdevDelete) delete(n.NetDevs, set.NetdevDelete) } - + for _, key := range nodeConf.TagsDel { + delete(n.Tags, key) + } + for _, key := range nodeConf.Ipmi.TagsDel { + delete(n.Ipmi.Tags, key) + } + for net := range nodeConf.NetDevs { + for _, key := range nodeConf.NetDevs[net].TagsDel { + if _, ok := n.NetDevs[net]; ok { + delete(n.NetDevs[net].Tags, key) + } + } + } err := nodeDB.NodeUpdate(n) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) diff --git a/internal/pkg/api/profile/profile.go b/internal/pkg/api/profile/profile.go index 1f25b897..48c53a73 100644 --- a/internal/pkg/api/profile/profile.go +++ b/internal/pkg/api/profile/profile.go @@ -33,7 +33,6 @@ func ProfileSet(set *wwapiv1.NodeSetParameter) (err error) { // TODO: Determine if the console switch does wwlog or not. // - console may end up being textOutput? func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (nodeDB node.NodeYaml, profileCount uint, err error) { - if set == nil { err = fmt.Errorf("profile set parameter is nil") if console { @@ -87,19 +86,28 @@ func ProfileSetParameterCheck(set *wwapiv1.NodeSetParameter, console bool) (node if util.InSlice(set.NodeNames, p.Id.Get()) { wwlog.Printf(wwlog.VERBOSE, "Evaluating profile: %s\n", p.Id.Get()) p.SetFrom(&pConf) - if set.NetdevDelete != "" { - if _, ok := p.NetDevs[set.NetdevDelete]; !ok { - err = fmt.Errorf("Network device name doesn't exist: %s", set.NetdevDelete) + err = fmt.Errorf("network device name doesn't exist: %s", set.NetdevDelete) wwlog.Error(fmt.Sprintf("%v\n", err.Error())) return } - wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Deleting network device: %s\n", p.Id.Get(), set.NetdevDelete) delete(p.NetDevs, set.NetdevDelete) } - + for _, key := range pConf.TagsDel { + delete(p.Tags, key) + } + for _, key := range pConf.Ipmi.TagsDel { + delete(p.Ipmi.Tags, key) + } + for net := range pConf.NetDevs { + for _, key := range pConf.NetDevs[net].TagsDel { + if _, ok := p.NetDevs[net]; ok { + delete(p.NetDevs[net].Tags, key) + } + } + } err := nodeDB.ProfileUpdate(p) if err != nil { wwlog.Error("%s\n", err) diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 9afabd2c..428145ec 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -157,11 +157,16 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { for name, profile := range config.NodeProfiles { var p NodeInfo + p.NetDevs = make(map[string]*NetDevEntry) + p.Tags = make(map[string]*Entry) + p.Kernel = new(KernelEntry) + p.Ipmi = new(IpmiEntry) p.Id.Set(name) for keyname, key := range profile.Keys { profile.Tags[keyname] = key delete(profile.Keys, keyname) } + p.SetFrom(profile) p.Ipmi.Ipaddr.Set(profile.IpmiIpaddr) p.Ipmi.Netmask.Set(profile.IpmiNetmask) @@ -185,6 +190,11 @@ func (config *NodeYaml) FindAllProfiles() ([]NodeInfo, error) { profile.KernelArgs = "" profile.KernelOverride = "" profile.KernelVersion = "" + // Merge Keys into Tags for backwards compatibility + if len(profile.Tags) == 0 { + profile.Tags = make(map[string]string) + } + ret = append(ret, p) } sort.Slice(ret, func(i, j int) bool { diff --git a/internal/pkg/node/transformers.go b/internal/pkg/node/transformers.go index 4a2369f9..a50ca263 100644 --- a/internal/pkg/node/transformers.go +++ b/internal/pkg/node/transformers.go @@ -52,8 +52,23 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*Entry{}) { entryMap := nodeInfoVal.Field(i).Interface().(map[string]*Entry) + confMap := confField.Interface().(map[string]string) + + if len(confMap) > len(entryMap) { + for confKey := range confMap { + foundKey := false + for entrKey := range entryMap { + if confKey == entrKey { + foundKey = true + } + } + if !foundKey { + delete(confMap, confKey) + } + } + } for key, val := range entryMap { - confField.Interface().(map[string]string)[key] = getter(val) + confMap[key] = getter(val) } } else if nodeInfoVal.Field(i).Type().Kind() == reflect.Ptr { if confField.Addr().Elem().IsZero() { @@ -90,11 +105,24 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, *mapPtr = make(map[string]string) } entryMap := nestedInfoVal.Elem().Field(j).Interface().(map[string]*Entry) + confMap := nestedVal.Interface().(map[string]string) + if len(confMap) > len(entryMap) { + for confKey := range confMap { + foundKey := false + for entrKey := range entryMap { + if confKey == entrKey { + foundKey = true + } + } + if !foundKey { + delete(confMap, confKey) + } + } + } for key, val := range entryMap { - nestedVal.Interface().(map[string]string)[key] = getter(val) + confMap[key] = getter(val) } } - //} } } else if nodeInfoVal.Field(i).Type() == reflect.TypeOf(map[string]*NetDevEntry{}) { @@ -103,36 +131,59 @@ func (nodeConf *NodeConf) getterFrom(nodeInfo NodeInfo, *netMapPtr = make(map[string](*NetDevs)) } nestedMap := nodeInfoVal.Field(i).Interface().(map[string]*NetDevEntry) + netMap := confField.Interface().(map[string](*NetDevs)) + // check if a network was deleted + if len(netMap) > len(nestedMap) { + for netMapKey := range netMap { + foundKey := false + for nestedMapKey := range nestedMap { + if netMapKey == nestedMapKey { + foundKey = true + } + } + if !foundKey { + delete(netMap, netMapKey) + } + } + } for netName, netVal := range nestedMap { netValsType := reflect.ValueOf(netVal) - netMap := confField.Interface().(map[string](*NetDevs)) - var newNet NetDevs - newNet.Tags = make(map[string]string) - netMap[netName] = &newNet - netConfType := reflect.TypeOf(newNet) - netConfVal := reflect.ValueOf(&newNet) + if _, ok := netMap[netName]; !ok { + netMap[netName] = new(NetDevs) + } + netConfType := reflect.TypeOf(*netMap[netName]) + netConfVal := reflect.ValueOf(netMap[netName]) for j := 0; j < netConfType.NumField(); j++ { netVal := netValsType.Elem().FieldByName(netConfType.Field(j).Name) if netVal.IsValid() { if netVal.Type() == reflect.TypeOf(Entry{}) { newVal := netConfVal.Elem().Field(j).Addr().Interface().((*string)) *newVal = getter((netVal.Addr().Interface()).(*Entry)) - } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - for key, val := range (netVal.Interface()).(map[string]*string) { - *val = getter(netConfVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]) + } else if netVal.Type() == reflect.TypeOf(map[string]*Entry{}) { + entryMap := netVal.Interface().(map[string](*Entry)) + confMap := netConfVal.Elem().Field(j).Interface().(map[string]string) + if len(confMap) > len(entryMap) { + for confMapKey := range confMap { + foundKey := false + for entryMapKey := range entryMap { + if confMapKey == entryMapKey { + foundKey = true + } + } + if !foundKey { + delete(netConfVal.Elem().Field(j).Interface().(map[string]string), confMapKey) + } + } + } + for key, val := range entryMap { + netConfVal.Elem().Field(j).Interface().(map[string]string)[key] = getter(val) } } } - } } } } - /* else { - // NodeInfo has the Id field, nodeConf not - fmt.Println("INVALID", nodeInfoType.Field(i).Name) - } - */ } } func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []string) { @@ -154,9 +205,17 @@ func (nodeConf *NodeConf) CreateFlags(baseCmd *cobra.Command, excludeList []stri } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string]*NetDevs(nil)) { netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string]*NetDevs) // add a default network so that it can hold values - netMap["default"] = new(NetDevs) - netType := reflect.TypeOf(netMap["default"]) - netVal := reflect.ValueOf(netMap["default"]) + key := "default" + if len(netMap) == 0 { + netMap[key] = new(NetDevs) + } else { + for keyIt := range netMap { + key = keyIt + break + } + } + netType := reflect.TypeOf(netMap[key]) + netVal := reflect.ValueOf(netMap[key]) for j := 0; j < netType.Elem().NumField(); j++ { field := netVal.Elem().Field(j) createFlags(baseCmd, excludeList, netType.Elem().Field(j), &field) @@ -304,27 +363,32 @@ func (node *NodeInfo) setterFrom(n *NodeConf, nameArg string, (nodeInfoVal.Elem().Field(i).Interface()).(map[string](*Entry))[key] = entr } } else if nodeInfoType.Elem().Field(i).Type == reflect.TypeOf(map[string](*NetDevEntry)(nil)) { - nestedMap := valField.Interface().(map[string](*NetDevs)) - for netName, netVals := range nestedMap { + netValMap := valField.Interface().(map[string](*NetDevs)) + for netName, netVals := range netValMap { netValsType := reflect.ValueOf(netVals) netMap := nodeInfoVal.Elem().Field(i).Interface().(map[string](*NetDevEntry)) - var newNet NetDevEntry - newNet.Tags = make(map[string]*Entry) - // This should be done a bit down, but didn't know how to do it - netMap[netName] = &newNet - netInfoType := reflect.TypeOf(newNet) - netInfoVal := reflect.ValueOf(&newNet) + if nodeInfoVal.Elem().Field(i).IsNil() { + netMap = make(map[string]*NetDevEntry) + } + if _, ok := netMap[netName]; !ok { + var newNet NetDevEntry + newNet.Tags = make(map[string]*Entry) + netMap[netName] = &newNet + } + netInfoType := reflect.TypeOf(*netMap[netName]) + netInfoVal := reflect.ValueOf(netMap[netName]) for j := 0; j < netInfoType.NumField(); j++ { netVal := netValsType.Elem().FieldByName(netInfoType.Field(j).Name) if netVal.IsValid() { if netVal.Type().Kind() == reflect.String { setter(netInfoVal.Elem().Field(j).Addr().Interface().((*Entry)), netVal.String(), nameArg) } else if netVal.Type() == reflect.TypeOf(map[string]string{}) { - // normaly the map should be created here, but did not manage it for key, val := range (netVal.Interface()).(map[string]string) { - entr := new(Entry) - setter(entr, val, nameArg) - netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = entr + //netTagMap := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry))) + if _, ok := netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key]; !ok { + netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key] = new(Entry) + } + setter(netInfoVal.Elem().Field(j).Interface().((map[string](*Entry)))[key], val, nameArg) } } }