added the wwctl overlay parse command

The `wwctl overlay parse -n NODE FILE` will interpret the given overlay file and print it stdout, via wwlog.PRINTF.
The overlay code had to be refactored for this, but hopefully this makes the code a bit more readable. Also the tstruct has not its own initilization code.
This commit is contained in:
Christian Goll
2022-05-25 11:41:33 +02:00
parent dfe3f907b9
commit 9e5b2d1aa3
4 changed files with 140 additions and 6 deletions

View File

@@ -0,0 +1,83 @@
package parse
import (
"bufio"
"bytes"
"os"
"path/filepath"
"regexp"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/hpcng/warewulf/internal/pkg/overlay"
"github.com/hpcng/warewulf/internal/pkg/util"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
)
func CobraRunE(cmd *cobra.Command, args []string) error {
var host node.NodeInfo
if NodeName == "" {
host.Kernel = new(node.KernelEntry)
host.Ipmi = new(node.IpmiEntry)
var idEntry node.Entry
hostname, _ := os.Hostname()
idEntry.Set(hostname)
host.Id = idEntry
} else {
nodeDB, err := node.New()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err)
os.Exit(1)
}
nodes, err := nodeDB.FindAllNodes()
if err != nil {
wwlog.Printf(wwlog.ERROR, "Could not get node list: %s\n", err)
os.Exit(1)
}
node := node.FilterByName(nodes, []string{NodeName})
if len(node) != 1 {
wwlog.Printf(wwlog.ERROR, "%v does not identify a single node\n", NodeName)
os.Exit(1)
}
host = node[0]
}
if !util.IsFile(args[0]) {
wwlog.Printf(wwlog.ERROR, "%s is not a file\n", args[0])
}
tstruct := overlay.InitStruct(host)
buffer, backupFile, writeFile, err := overlay.RenderTemplateFile(args[0], tstruct)
if err != nil {
return err
}
if filepath.Ext(args[0]) != ".ww" {
wwlog.Printf(wwlog.WARN, "%s has not the '.ww' so wont be rendered if in overlay\n", args[0])
}
wwlog.Printf(wwlog.INFO, "backupFile: %v\nwriteFile: %v\n", backupFile, writeFile)
var outBuffer bytes.Buffer
// search for magic file name comment
bufferScanner := bufio.NewScanner(bytes.NewReader(buffer.Bytes()))
bufferScanner.Split(overlay.ScanLines)
reg := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
foundFileComment := false
destFileName := args[0]
for bufferScanner.Scan() {
line := bufferScanner.Text()
filenameFromTemplate := reg.FindAllStringSubmatch(line, -1)
if len(filenameFromTemplate) != 0 {
wwlog.Printf(wwlog.DEBUG, "Found multifile comment, new filename %s\n", filenameFromTemplate[0][1])
if foundFileComment {
wwlog.Printf(wwlog.INFO, "%s", outBuffer.String())
outBuffer.Reset()
}
destFileName = filenameFromTemplate[0][1]
wwlog.Printf(wwlog.INFO, "Filename: %s\n\n", destFileName)
wwlog.Printf(wwlog.INFO, "%s", outBuffer.String())
foundFileComment = true
} else {
_, _ = outBuffer.WriteString(line)
}
}
wwlog.Printf(wwlog.INFO, "Filename: %s\n\n", destFileName)
wwlog.Printf(wwlog.INFO, "%s", outBuffer.String())
return nil
}

View File

@@ -0,0 +1,41 @@
package parse
import (
"log"
"github.com/hpcng/warewulf/internal/pkg/node"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "parse [OPTIONS] FILE_NAME",
Short: "parses interprets the given file as warewulf template",
Long: "This command tries to parse a given file as warewulf template, it needs not to be in overlay folder.",
RunE: CobraRunE,
Aliases: []string{"parse"},
Args: cobra.ExactArgs(1),
}
NodeName string
)
func init() {
baseCmd.PersistentFlags().StringVarP(&NodeName, "node", "n", "", "node used for the variables in the template")
if err := baseCmd.RegisterFlagCompletionFunc("node", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
nodeDB, _ := node.New()
nodes, _ := nodeDB.FindAllNodes()
var node_names []string
for _, node := range nodes {
node_names = append(node_names, node.Id.Get())
}
return node_names, cobra.ShellCompDirectiveNoFileComp
}); err != nil {
log.Println(err)
}
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/imprt"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/list"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/mkdir"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/parse"
"github.com/hpcng/warewulf/internal/app/wwctl/overlay/show"
"github.com/spf13/cobra"
)
@@ -17,9 +18,9 @@ import (
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "overlay COMMAND [OPTIONS]",
Short: "Warewulf Overlay Management",
Long: "Management interface for Warewulf overlays",
Use: "overlay COMMAND [OPTIONS]",
Short: "Warewulf Overlay Management",
Long: "Management interface for Warewulf overlays",
}
)
@@ -34,6 +35,8 @@ func init() {
baseCmd.AddCommand(imprt.GetCommand())
baseCmd.AddCommand(chmod.GetCommand())
baseCmd.AddCommand(chown.GetCommand())
baseCmd.AddCommand(parse.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.