When editing an overlay, the temporary file was created within the overlay directory structure. This could lead to the temporary file being included in the overlay if not cleaned up properly. This change modifies the behavior to create the temporary file in the system's default temporary directory, avoiding any potential issues with the overlay itself. Not using this change the temporary file can be seen in the overlay: DEBUG : Using temporary file /usr/share/warewulf/overlays/host/ww-overlay-edit-2879742493 DEBUG : Checking if path exists as a file: /usr/share/warewulf/overlays/host/rootfs/etc/hosts.ww DEBUG : ExecInteractive(tee, [/usr/share/warewulf/overlays/host/ww-overlay-edit-2879742493]) # find /srv | grep ww-overlay /srv/warewulf/overlays/host/ww-overlay-edit-2879742493 With this patch applied: DEBUG : Using temporary file /tmp/ww-overlay-edit-266752840 DEBUG : Checking if path exists as a file: /usr/share/warewulf/overlays/host/rootfs/etc/hosts.ww DEBUG : ExecInteractive(tee, [/tmp/ww-overlay-edit-266752840]) # find /srv | grep ww-overlay Assisted-by: Gemini 2.5 Pro Signed-off-by: Adrian Reber <areber@redhat.com>
129 lines
3.7 KiB
Go
129 lines
3.7 KiB
Go
package edit
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/warewulf/warewulf/internal/pkg/overlay"
|
|
"github.com/warewulf/warewulf/internal/pkg/util"
|
|
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
|
)
|
|
|
|
const initialTemplate = `# This is a Warewulf Template file.
|
|
#
|
|
# This file (suffix '.ww') will be automatically rewritten without the suffix
|
|
# when the overlay is rendered for the individual nodes. Here are some examples
|
|
# of macros and logic which can be used within this file:
|
|
#
|
|
# Node FQDN = {{.Id}}
|
|
# Node Cluster = {{.ClusterName}}
|
|
# Network Config = {{.NetDevs.eth0.Ipaddr}}, {{.NetDevs.eth0.Hwaddr}}, etc.
|
|
#
|
|
# Go to the documentation pages for more information:
|
|
# https://warewulf.org/docs/main/contents/overlays.html
|
|
#
|
|
# Keep the following for better reference:
|
|
# ---
|
|
# This file is autogenerated by warewulf
|
|
`
|
|
|
|
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
|
overlayName := args[0]
|
|
fileName := args[1]
|
|
|
|
myOverlay, err := overlay.Get(overlayName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
overlayFile := myOverlay.File(fileName)
|
|
wwlog.Debug("Will edit overlay file: %s", overlayFile)
|
|
overlayFileDir := path.Dir(overlayFile)
|
|
if !(util.IsDir(overlayFileDir) || CreateDirs) {
|
|
return fmt.Errorf("%s does not exist. Use '--parents' option to create automatically", overlayFileDir)
|
|
}
|
|
|
|
tempFile, tempFileErr := os.CreateTemp("", "ww-overlay-edit-")
|
|
if tempFileErr != nil {
|
|
return fmt.Errorf("unable to create temporary file for editing: %s", tempFileErr)
|
|
}
|
|
defer os.Remove(tempFile.Name())
|
|
wwlog.Debug("Using temporary file %s", tempFile.Name())
|
|
|
|
if util.IsFile(overlayFile) {
|
|
originalFile, openErr := os.Open(overlayFile)
|
|
if openErr != nil {
|
|
return fmt.Errorf("unable to open %s: %s", overlayFile, openErr)
|
|
}
|
|
if _, err := io.Copy(tempFile, originalFile); err != nil {
|
|
return fmt.Errorf("unable to copy %s to %s for editing: %s", originalFile.Name(), tempFile.Name(), err)
|
|
}
|
|
originalFile.Close()
|
|
} else if filepath.Ext(overlayFile) == ".ww" {
|
|
if _, err := tempFile.Write([]byte(initialTemplate)); err != nil {
|
|
return fmt.Errorf("unable to write to %s: %s", tempFile.Name(), err)
|
|
}
|
|
}
|
|
tempFile.Close()
|
|
|
|
initialFile, err := os.Open(tempFile.Name())
|
|
if err != nil {
|
|
return fmt.Errorf("unable to open temp file for hashing: %s", err)
|
|
}
|
|
initialHash, err := util.HashFile(initialFile)
|
|
initialFile.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to calculate initial hash of %s: %s", tempFile.Name(), err)
|
|
}
|
|
|
|
editor := os.Getenv("EDITOR")
|
|
if editor == "" {
|
|
editor = "/bin/vi"
|
|
}
|
|
if editorErr := util.ExecInteractive(editor, tempFile.Name()); editorErr != nil {
|
|
return fmt.Errorf("editor process exited with an error: %s", editorErr)
|
|
}
|
|
|
|
finalFile, err := os.Open(tempFile.Name())
|
|
if err != nil {
|
|
return fmt.Errorf("unable to open temp file for final hashing: %s", err)
|
|
}
|
|
finalHash, err := util.HashFile(finalFile)
|
|
finalFile.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("unable to calculate final hash of %s: %s", tempFile.Name(), err)
|
|
}
|
|
|
|
if initialHash == finalHash {
|
|
wwlog.Debug("No change detected. Not updating overlay.")
|
|
return nil
|
|
}
|
|
|
|
if !myOverlay.IsSiteOverlay() {
|
|
myOverlay, err = myOverlay.CloneToSite()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
overlayFile = myOverlay.File(fileName)
|
|
overlayFileDir = path.Dir(overlayFile)
|
|
}
|
|
|
|
if CreateDirs {
|
|
if err := os.MkdirAll(overlayFileDir, 0755); err != nil {
|
|
return fmt.Errorf("could not create directory: %s", overlayFileDir)
|
|
}
|
|
}
|
|
|
|
// using CopyFile preserves target file permissions
|
|
cerr := util.CopyFile(tempFile.Name(), overlayFile)
|
|
if cerr != nil {
|
|
return fmt.Errorf("unable to copy data from temp file: %s to target file: %s, err: %s", tempFile.Name(), overlayFile, err)
|
|
}
|
|
|
|
return nil
|
|
}
|