committed by
Jonathon Anderson
parent
c3833b5ba0
commit
5ff27061a3
@@ -25,6 +25,8 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) error {
|
||||
if !node.ObjectIsEmpty(vars.nodeConf.NetDevs["UNDEF"]) {
|
||||
netDev := *vars.nodeConf.NetDevs["UNDEF"]
|
||||
vars.nodeConf.NetDevs[vars.nodeAdd.Net] = &netDev
|
||||
vars.nodeConf.NetDevs[vars.nodeAdd.Net].Tags = vars.nodeAdd.NetTagsAdd
|
||||
|
||||
}
|
||||
delete(vars.nodeConf.NetDevs, "UNDEF")
|
||||
if vars.nodeAdd.FsName != "" {
|
||||
@@ -50,6 +52,7 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("partition and disk must be specified")
|
||||
}
|
||||
delete(vars.nodeConf.Disks, "UNDEF")
|
||||
vars.nodeConf.Ipmi.Tags = vars.nodeAdd.IpmiTagsAdd
|
||||
if len(vars.nodeConf.Profiles) == 0 {
|
||||
vars.nodeConf.Profiles = []string{"default"}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err
|
||||
return fmt.Errorf("partition and disk must be specified")
|
||||
}
|
||||
delete(vars.nodeConf.Disks, "UNDEF")
|
||||
vars.nodeConf.Ipmi.Tags = vars.nodeAdd.IpmiTagsAdd
|
||||
buffer, err := yaml.Marshal(vars.nodeConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not marshall nodeInfo: %s", err)
|
||||
|
||||
@@ -18,32 +18,33 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err
|
||||
// to this network
|
||||
if !node.ObjectIsEmpty(vars.profileConf.NetDevs["UNDEF"]) {
|
||||
netDev := *vars.profileConf.NetDevs["UNDEF"]
|
||||
vars.profileConf.NetDevs[vars.nodeAdd.Net] = &netDev
|
||||
vars.profileConf.NetDevs[vars.profileAdd.Net] = &netDev
|
||||
}
|
||||
delete(vars.profileConf.NetDevs, "UNDEF")
|
||||
if vars.nodeAdd.FsName != "" {
|
||||
if !strings.HasPrefix(vars.nodeAdd.FsName, "/dev") {
|
||||
if vars.nodeAdd.FsName == vars.nodeAdd.PartName {
|
||||
vars.nodeAdd.FsName = "/dev/disk/by-partlabel/" + vars.nodeAdd.PartName
|
||||
if vars.profileAdd.FsName != "" {
|
||||
if !strings.HasPrefix(vars.profileAdd.FsName, "/dev") {
|
||||
if vars.profileAdd.FsName == vars.profileAdd.PartName {
|
||||
vars.profileAdd.FsName = "/dev/disk/by-partlabel/" + vars.profileAdd.PartName
|
||||
} else {
|
||||
return fmt.Errorf("filesystems need to have a underlying blockdev")
|
||||
}
|
||||
}
|
||||
fs := *vars.profileConf.FileSystems["UNDEF"]
|
||||
vars.profileConf.FileSystems[vars.nodeAdd.FsName] = &fs
|
||||
vars.profileConf.FileSystems[vars.profileAdd.FsName] = &fs
|
||||
}
|
||||
delete(vars.profileConf.FileSystems, "UNDEF")
|
||||
if vars.nodeAdd.DiskName != "" && vars.nodeAdd.PartName != "" {
|
||||
if vars.profileAdd.DiskName != "" && vars.profileAdd.PartName != "" {
|
||||
prt := *vars.profileConf.Disks["UNDEF"].Partitions["UNDEF"]
|
||||
vars.profileConf.Disks["UNDEF"].Partitions[vars.nodeAdd.PartName] = &prt
|
||||
vars.profileConf.Disks["UNDEF"].Partitions[vars.profileAdd.PartName] = &prt
|
||||
delete(vars.profileConf.Disks["UNDEF"].Partitions, "UNDEF")
|
||||
dsk := *vars.profileConf.Disks["UNDEF"]
|
||||
vars.profileConf.Disks[vars.nodeAdd.DiskName] = &dsk
|
||||
vars.profileConf.Disks[vars.profileAdd.DiskName] = &dsk
|
||||
}
|
||||
if (vars.nodeAdd.DiskName != "") != (vars.nodeAdd.PartName != "") {
|
||||
if (vars.profileAdd.DiskName != "") != (vars.profileAdd.PartName != "") {
|
||||
return fmt.Errorf("partition and disk must be specified")
|
||||
}
|
||||
delete(vars.profileConf.Disks, "UNDEF")
|
||||
vars.profileConf.Ipmi.Tags = vars.profileAdd.IpmiTagsAdd
|
||||
buffer, err := yaml.Marshal(vars.profileConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not marshall nodeInfo: %w", err)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
type variables struct {
|
||||
profileConf node.Profile
|
||||
nodeAdd node.NodeConfAdd
|
||||
profileAdd node.NodeConfAdd
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
@@ -29,7 +29,7 @@ func GetCommand() *cobra.Command {
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
vars.profileConf.CreateFlags(baseCmd)
|
||||
vars.nodeAdd.CreateAddFlags(baseCmd)
|
||||
vars.profileAdd.CreateAddFlags(baseCmd)
|
||||
// register the command line completions
|
||||
if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
list, _ := container.ListSources()
|
||||
|
||||
@@ -47,6 +47,7 @@ func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err err
|
||||
return fmt.Errorf("partition and disk must be specified")
|
||||
}
|
||||
delete(vars.profileConf.Disks, "UNDEF")
|
||||
vars.profileConf.Ipmi.Tags = vars.profileAdd.IpmiTagsAdd
|
||||
buffer, err := yaml.Marshal(vars.profileConf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can not marshall nodeInfo: %s", err)
|
||||
|
||||
31
internal/app/wwctl/resource/add/main.go
Normal file
31
internal/app/wwctl/resource/add/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
nodeYml, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load node configuration: %s", err)
|
||||
}
|
||||
if ok := nodeYml.Resource[args[0]] != nil; ok {
|
||||
return fmt.Errorf("resource %s already exists", args[0])
|
||||
}
|
||||
if nodeYml.Resource == nil {
|
||||
nodeYml.Resource = make(map[string]*node.RemoteRes)
|
||||
}
|
||||
res := node.RemoteRes{}
|
||||
for key, val := range vars.tags {
|
||||
res[key] = val
|
||||
}
|
||||
nodeYml.Resource[args[0]] = &res
|
||||
err = nodeYml.Persist()
|
||||
return err
|
||||
}
|
||||
}
|
||||
58
internal/app/wwctl/resource/add/main_test.go
Normal file
58
internal/app/wwctl/resource/add/main_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
)
|
||||
|
||||
func Test_resource_add(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
stdout string
|
||||
inDB string
|
||||
outDb string
|
||||
}{{
|
||||
name: "add resource",
|
||||
args: []string{"--restagadd", "foo=baar", "test"},
|
||||
wantErr: false,
|
||||
stdout: "",
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
`,
|
||||
outDb: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test:
|
||||
foo: baar
|
||||
`}}
|
||||
env := testenv.New(t)
|
||||
defer env.RemoveAll(t)
|
||||
warewulfd.SetNoDaemon()
|
||||
for _, tt := range tests {
|
||||
env.WriteFile(t, "etc/warewulf/nodes.conf", tt.inDB)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
baseCmd := GetCommand()
|
||||
baseCmd.SetArgs(tt.args)
|
||||
buf := new(bytes.Buffer)
|
||||
baseCmd.SetOut(buf)
|
||||
baseCmd.SetErr(buf)
|
||||
err := baseCmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, buf.String(), tt.stdout)
|
||||
content := env.ReadFile(t, "etc/warewulf/nodes.conf")
|
||||
assert.YAMLEq(t, tt.outDb, content)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
25
internal/app/wwctl/resource/add/root.go
Normal file
25
internal/app/wwctl/resource/add/root.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type variables struct {
|
||||
tags map[string]string
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
vars := variables{}
|
||||
baseCmd := &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "add PROFILE",
|
||||
Short: "Add a new node profile",
|
||||
Long: "This command adds a new named PROFILE.",
|
||||
Aliases: []string{"new", "create"},
|
||||
RunE: CobraRunE(&vars),
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
baseCmd.PersistentFlags().StringToStringVar(&vars.tags, "restagadd", map[string]string{}, "add cluster wide resource tags")
|
||||
return baseCmd
|
||||
}
|
||||
25
internal/app/wwctl/resource/delete/main.go
Normal file
25
internal/app/wwctl/resource/delete/main.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package delete
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
nodeYml, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load node configuration: %s", err)
|
||||
}
|
||||
for _, res := range args {
|
||||
if _, ok := nodeYml.Resource[res]; !ok {
|
||||
return fmt.Errorf("resource %s does not exist", res)
|
||||
}
|
||||
delete(nodeYml.Resource, res)
|
||||
}
|
||||
return nodeYml.Persist()
|
||||
}
|
||||
}
|
||||
63
internal/app/wwctl/resource/delete/main_test.go
Normal file
63
internal/app/wwctl/resource/delete/main_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package delete
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
)
|
||||
|
||||
func Test_resource_set(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
wantErr bool
|
||||
args []string
|
||||
stdout string
|
||||
inDB string
|
||||
outDb string
|
||||
}{
|
||||
{
|
||||
name: "delete resource",
|
||||
wantErr: false,
|
||||
stdout: "",
|
||||
args: []string{"test1"},
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test1: {}
|
||||
test2: {}
|
||||
`,
|
||||
|
||||
outDb: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test2: {}
|
||||
`},
|
||||
}
|
||||
env := testenv.New(t)
|
||||
defer env.RemoveAll(t)
|
||||
warewulfd.SetNoDaemon()
|
||||
for _, tt := range tests {
|
||||
env.WriteFile(t, "etc/warewulf/nodes.conf", tt.inDB)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
baseCmd := GetCommand()
|
||||
baseCmd.SetArgs(tt.args)
|
||||
buf := new(bytes.Buffer)
|
||||
baseCmd.SetOut(buf)
|
||||
baseCmd.SetErr(buf)
|
||||
err := baseCmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, buf.String(), tt.stdout)
|
||||
content := env.ReadFile(t, "etc/warewulf/nodes.conf")
|
||||
assert.YAMLEq(t, tt.outDb, content)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
31
internal/app/wwctl/resource/delete/root.go
Normal file
31
internal/app/wwctl/resource/delete/root.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package delete
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
)
|
||||
|
||||
type variables struct {
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
vars := variables{}
|
||||
baseCmd := &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "list [RESOURCE]",
|
||||
Short: "list resource",
|
||||
Long: "This list all values the named RESOURCE. If no resource is named a list of the resources is printed.",
|
||||
Aliases: []string{"show", "ls"},
|
||||
RunE: CobraRunE(&vars),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
if len(args) != 0 {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
nodeDB, _ := node.New()
|
||||
return nodeDB.ListAllResources(), cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
}
|
||||
return baseCmd
|
||||
}
|
||||
44
internal/app/wwctl/resource/list/main.go
Normal file
44
internal/app/wwctl/resource/list/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/table"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
nodeYml, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load node configuration: %s", err)
|
||||
}
|
||||
var resList []string
|
||||
if len(args) == 1 {
|
||||
resList = []string{args[0]}
|
||||
} else {
|
||||
resList = nodeYml.ListAllResources()
|
||||
}
|
||||
for _, resname := range resList {
|
||||
res, err := nodeYml.GetResource(resname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !vars.all {
|
||||
wwlog.Info("%s", resname)
|
||||
} else {
|
||||
t := table.New(cmd.OutOrStdout())
|
||||
t.AddHeader(resname, "key", "value")
|
||||
for key, val := range res {
|
||||
t.AddLine(resname, key, val)
|
||||
}
|
||||
t.Print()
|
||||
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
74
internal/app/wwctl/resource/list/main_test.go
Normal file
74
internal/app/wwctl/resource/list/main_test.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func Test_resource_set(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
stdout string
|
||||
inDB string
|
||||
}{
|
||||
{
|
||||
name: "list resource",
|
||||
args: []string{},
|
||||
wantErr: false,
|
||||
stdout: `test1
|
||||
test2
|
||||
`,
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test1: {}
|
||||
test2: {}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "list a existing resource",
|
||||
args: []string{"-a"},
|
||||
wantErr: false,
|
||||
stdout: `test key value
|
||||
---- --- -----
|
||||
test foo baar
|
||||
`,
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test:
|
||||
foo: baar
|
||||
`,
|
||||
},
|
||||
}
|
||||
env := testenv.New(t)
|
||||
defer env.RemoveAll(t)
|
||||
warewulfd.SetNoDaemon()
|
||||
for _, tt := range tests {
|
||||
env.WriteFile(t, "etc/warewulf/nodes.conf", tt.inDB)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
baseCmd := GetCommand()
|
||||
baseCmd.SetArgs(tt.args)
|
||||
buf := new(bytes.Buffer)
|
||||
baseCmd.SetOut(buf)
|
||||
baseCmd.SetErr(buf)
|
||||
wwlog.SetLogWriter(buf)
|
||||
err := baseCmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, buf.String(), tt.stdout)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
33
internal/app/wwctl/resource/list/root.go
Normal file
33
internal/app/wwctl/resource/list/root.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
)
|
||||
|
||||
type variables struct {
|
||||
all bool
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
vars := variables{}
|
||||
baseCmd := &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "list [RESOURCE]",
|
||||
Short: "list resource",
|
||||
Long: "This list all values the named RESOURCE. If no resource is named a list of the resources is printed.",
|
||||
Aliases: []string{"show", "ls"},
|
||||
RunE: CobraRunE(&vars),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
if len(args) != 0 {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
nodeDB, _ := node.New()
|
||||
return nodeDB.ListAllResources(), cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
}
|
||||
baseCmd.PersistentFlags().BoolVarP(&vars.all, "all", "a", false, "Show all resources")
|
||||
return baseCmd
|
||||
}
|
||||
30
internal/app/wwctl/resource/root.go
Normal file
30
internal/app/wwctl/resource/root.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/resource/add"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/resource/delete"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/resource/list"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/resource/set"
|
||||
)
|
||||
|
||||
var (
|
||||
baseCmd = &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "resource COMMAND [OPTIONS]",
|
||||
Short: "manage resources",
|
||||
Long: "Management of global resources",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
baseCmd.AddCommand(list.GetCommand())
|
||||
baseCmd.AddCommand(set.GetCommand())
|
||||
baseCmd.AddCommand(add.GetCommand())
|
||||
baseCmd.AddCommand(delete.GetCommand())
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
return baseCmd
|
||||
}
|
||||
31
internal/app/wwctl/resource/set/main.go
Normal file
31
internal/app/wwctl/resource/set/main.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) (err error) {
|
||||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
nodeYml, err := node.New()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load node configuration: %s", err)
|
||||
}
|
||||
if ok := nodeYml.Resource[args[0]] != nil; ok {
|
||||
if nodeYml.Resource == nil {
|
||||
nodeYml.Resource = make(map[string]*node.RemoteRes)
|
||||
}
|
||||
res := *nodeYml.Resource[args[0]]
|
||||
for key, val := range vars.tags {
|
||||
res[key] = val
|
||||
}
|
||||
err = nodeYml.Persist()
|
||||
return err
|
||||
} else {
|
||||
return fmt.Errorf("resource %s does not exist", args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
75
internal/app/wwctl/resource/set/main_test.go
Normal file
75
internal/app/wwctl/resource/set/main_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/warewulfd"
|
||||
)
|
||||
|
||||
func Test_resource_set(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
stdout string
|
||||
inDB string
|
||||
outDb string
|
||||
}{
|
||||
{
|
||||
name: "set resource",
|
||||
args: []string{"--tagset", "foo=test", "test"},
|
||||
wantErr: false,
|
||||
stdout: "",
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test:
|
||||
foo: baar
|
||||
`,
|
||||
outDb: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test:
|
||||
foo: test
|
||||
`},
|
||||
{
|
||||
name: "set non exiting resource",
|
||||
args: []string{"--tagset", "foo=test", "none"},
|
||||
wantErr: true,
|
||||
stdout: "",
|
||||
inDB: `nodeprofiles: {}
|
||||
nodes: {}
|
||||
resource:
|
||||
test:
|
||||
foo: baar
|
||||
`,
|
||||
outDb: ``},
|
||||
}
|
||||
env := testenv.New(t)
|
||||
defer env.RemoveAll(t)
|
||||
warewulfd.SetNoDaemon()
|
||||
for _, tt := range tests {
|
||||
env.WriteFile(t, "etc/warewulf/nodes.conf", tt.inDB)
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
baseCmd := GetCommand()
|
||||
baseCmd.SetArgs(tt.args)
|
||||
buf := new(bytes.Buffer)
|
||||
baseCmd.SetOut(buf)
|
||||
baseCmd.SetErr(buf)
|
||||
err := baseCmd.Execute()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, buf.String(), tt.stdout)
|
||||
content := env.ReadFile(t, "etc/warewulf/nodes.conf")
|
||||
assert.YAMLEq(t, tt.outDb, content)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
33
internal/app/wwctl/resource/set/root.go
Normal file
33
internal/app/wwctl/resource/set/root.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package set
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
)
|
||||
|
||||
type variables struct {
|
||||
tags map[string]string
|
||||
}
|
||||
|
||||
// GetRootCommand returns the root cobra.Command for the application.
|
||||
func GetCommand() *cobra.Command {
|
||||
vars := variables{}
|
||||
baseCmd := &cobra.Command{
|
||||
DisableFlagsInUseLine: true,
|
||||
Use: "set RESOURCE",
|
||||
Short: "change a resource",
|
||||
Long: "This command changes the named RESOURCE. Use UNDEF to remove a tag.",
|
||||
Aliases: []string{"modify", "change"},
|
||||
RunE: CobraRunE(&vars),
|
||||
Args: cobra.ExactArgs(1),
|
||||
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
if len(args) != 0 {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
nodeDB, _ := node.New()
|
||||
return nodeDB.ListAllResources(), cobra.ShellCompDirectiveNoFileComp
|
||||
},
|
||||
}
|
||||
baseCmd.PersistentFlags().StringToStringVar(&vars.tags, "tagset", map[string]string{}, "set cluster wide resource tags")
|
||||
return baseCmd
|
||||
}
|
||||
@@ -183,6 +183,18 @@ func (config *NodesYaml) ListAllProfiles() []string {
|
||||
return nodeList
|
||||
}
|
||||
|
||||
/*
|
||||
Return the names of all available remote resources
|
||||
*/
|
||||
func (config *NodesYaml) ListAllResources() []string {
|
||||
var resList []string
|
||||
for name := range config.Resource {
|
||||
resList = append(resList, name)
|
||||
}
|
||||
sort.Strings(resList)
|
||||
return resList
|
||||
}
|
||||
|
||||
/*
|
||||
FindDiscoverableNode returns the first discoverable node and an
|
||||
interface to associate with the discovered interface. If the nodUNDEFe has
|
||||
@@ -211,3 +223,13 @@ func (config *NodesYaml) FindDiscoverableNode() (Node, string, error) {
|
||||
|
||||
return EmptyNode(), "", ErrNoUnconfigured
|
||||
}
|
||||
|
||||
/*
|
||||
get the given resource
|
||||
*/
|
||||
func (config *NodesYaml) GetResource(id string) (res RemoteRes, err error) {
|
||||
if found, ok := config.Resource[id]; ok {
|
||||
return *found, nil
|
||||
}
|
||||
return res, ErrNotFound
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ Structure of which goes to disk
|
||||
type NodesYaml struct {
|
||||
NodeProfiles map[string]*Profile
|
||||
Nodes map[string]*Node
|
||||
Resource map[string]*RemoteRes `yaml:"resource,omitempty"`
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -53,6 +54,8 @@ type Profile struct {
|
||||
PrimaryNetDev string `yaml:"primary network,omitempty" lopt:"primarynet" sopt:"p" comment:"Set the primary network interface"`
|
||||
Disks map[string]*Disk `yaml:"disks,omitempty"`
|
||||
FileSystems map[string]*FileSystem `yaml:"filesystems,omitempty"`
|
||||
resource map[string]*RemoteRes `yaml:"omitempty"`
|
||||
Resources []string `yaml:"resources,omitempty" lopt:"resources" comment:"Set the resources available to the node or profile"`
|
||||
}
|
||||
|
||||
type IpmiConf struct {
|
||||
@@ -124,3 +127,14 @@ type FileSystem struct {
|
||||
Options []string `yaml:"options,omitempty" comment:"any additional options to be passed to the format-specific mkfs utility"`
|
||||
MountOptions string `yaml:"mount_options,omitempty" comment:"any special options to be passed to the mount command"`
|
||||
}
|
||||
|
||||
/*
|
||||
Definition of any remote. Can be a nfs share or other FS types
|
||||
*/
|
||||
|
||||
type RemoteRes map[string]string
|
||||
|
||||
// always return so that the resource isn't marshalled
|
||||
// func (res RemoteRes) IsZero() bool {
|
||||
// return true
|
||||
// }
|
||||
|
||||
@@ -53,6 +53,9 @@ func recursiveCreateFlags(obj interface{}, baseCmd *cobra.Command) {
|
||||
nodeInfoType := reflect.TypeOf(obj)
|
||||
nodeInfoVal := reflect.ValueOf(obj)
|
||||
for i := 0; i < nodeInfoVal.Elem().NumField(); i++ {
|
||||
if !nodeInfoType.Elem().Field(i).IsExported() {
|
||||
continue
|
||||
}
|
||||
if nodeInfoType.Elem().Field(i).Tag.Get("comment") != "" {
|
||||
field := nodeInfoVal.Elem().Field(i)
|
||||
createFlags(baseCmd, nodeInfoType.Elem().Field(i), &field)
|
||||
|
||||
@@ -103,6 +103,7 @@ func EmptyNode() (nodeconf Node) {
|
||||
nodeconf.Ipmi.Tags = map[string]string{}
|
||||
nodeconf.Kernel = new(KernelConf)
|
||||
nodeconf.NetDevs = make(map[string]*NetDev)
|
||||
nodeconf.resource = make(map[string]*RemoteRes)
|
||||
nodeconf.Tags = map[string]string{}
|
||||
return nodeconf
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user