From ae54fd207b01557bb74514140e768397785783b2 Mon Sep 17 00:00:00 2001 From: Timothy Middelkoop Date: Sun, 23 Feb 2025 16:29:05 +0000 Subject: [PATCH 1/2] Add `--overwrite` to `wwctl overlay import` - Closes: #386 Signed-off-by: Timothy Middelkoop --- CHANGELOG.md | 4 ++++ internal/app/wwctl/overlay/imprt/main.go | 2 +- internal/app/wwctl/overlay/imprt/root.go | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ce56f03..10637794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## v4.6.1, unreleased +### Added + +- Added `wwctl overlay import --overwrite` to overwrite existing overlay file. + ### Fixed - Fixed panic in warewulfd if node netdev is only defined in a profile. #1817 diff --git a/internal/app/wwctl/overlay/imprt/main.go b/internal/app/wwctl/overlay/imprt/main.go index 335ab673..ef948fe7 100644 --- a/internal/app/wwctl/overlay/imprt/main.go +++ b/internal/app/wwctl/overlay/imprt/main.go @@ -42,7 +42,7 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { dest = path.Join(dest, path.Base(source)) } - if util.IsFile(overlay_.File(dest)) { + if !OverwriteFile && util.IsFile(overlay_.File(dest)) { return fmt.Errorf("a file with that name already exists in the overlay: %s", overlayName) } diff --git a/internal/app/wwctl/overlay/imprt/root.go b/internal/app/wwctl/overlay/imprt/root.go index 8d54521e..c3958d86 100644 --- a/internal/app/wwctl/overlay/imprt/root.go +++ b/internal/app/wwctl/overlay/imprt/root.go @@ -24,12 +24,14 @@ var ( } }, } + OverwriteFile bool NoOverlayUpdate bool CreateDirs bool Workers int ) func init() { + baseCmd.PersistentFlags().BoolVarP(&OverwriteFile, "overwrite", "o", false, "Overwrite file if exists") baseCmd.PersistentFlags().BoolVarP(&NoOverlayUpdate, "noupdate", "n", false, "Don't update overlays") baseCmd.PersistentFlags().BoolVarP(&CreateDirs, "parents", "p", false, "Create any necessary parent directories") baseCmd.PersistentFlags().IntVar(&Workers, "workers", 0, "The number of parallel workers building overlays (<=0 indicates 1 worker per CPU)") From c7bda5e655a2a32e0bc80fee17a7251c07df8fea Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Fri, 21 Mar 2025 23:37:03 -0600 Subject: [PATCH 2/2] Add tests for overlay import --overwrite Signed-off-by: Jonathon Anderson --- internal/app/wwctl/overlay/imprt/main_test.go | 79 +++++++++++++++++++ internal/pkg/util/copyfile.go | 10 +-- 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/internal/app/wwctl/overlay/imprt/main_test.go b/internal/app/wwctl/overlay/imprt/main_test.go index 2003ce93..dbbfcc94 100644 --- a/internal/app/wwctl/overlay/imprt/main_test.go +++ b/internal/app/wwctl/overlay/imprt/main_test.go @@ -1,6 +1,7 @@ package imprt import ( + "bytes" "fmt" "os" "testing" @@ -8,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" warewulfconf "github.com/warewulf/warewulf/internal/pkg/config" "github.com/warewulf/warewulf/internal/pkg/node" + "github.com/warewulf/warewulf/internal/pkg/testenv" "github.com/warewulf/warewulf/internal/pkg/warewulfd" ) @@ -89,3 +91,80 @@ nodes: {} } }) } + +func Test_Import(t *testing.T) { + tests := map[string]struct { + initFiles []string + initDirs []string + args []string + errExpected bool + }{ + "import a file": { + initFiles: []string{"importfile"}, + initDirs: []string{"/var/lib/warewulf/overlays/to1/rootfs"}, + args: []string{"to1", "importfile"}, + }, + + "import missing parent": { + initFiles: []string{"importfile"}, + initDirs: []string{"/var/lib/warewulf/overlays/to1/rootfs"}, + args: []string{"to1", "importfile", "a/b/importfile"}, + errExpected: true, + }, + + "import create parents": { + initFiles: []string{"importfile"}, + initDirs: []string{"/var/lib/warewulf/overlays/to1/rootfs"}, + args: []string{"to1", "importfile", "a/b/importfile", "--parents"}, + errExpected: false, + }, + + "import fail overwrite": { + initFiles: []string{"importfile", "/var/lib/warewulf/overlays/to1/rootfs/importfile"}, + args: []string{"to1", "importfile"}, + errExpected: true, + }, + + "import overwrite": { + initFiles: []string{"importfile", "/var/lib/warewulf/overlays/to1/rootfs/importfile"}, + args: []string{"to1", "importfile", "--overwrite"}, + errExpected: false, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + env := testenv.New(t) + defer env.RemoveAll() + { + wd, err := os.Getwd() + assert.NoError(t, err) + defer func() { assert.NoError(t, os.Chdir(wd)) }() + } + assert.NoError(t, os.Chdir(env.GetPath("."))) + + OverwriteFile = false + CreateDirs = false + + for _, file := range tt.initFiles { + env.CreateFile(file) + } + for _, dir := range tt.initDirs { + env.MkdirAll(dir) + } + + cmd := GetCommand() + cmd.SetArgs(tt.args) + stdout := new(bytes.Buffer) + cmd.SetOut(stdout) + stderr := new(bytes.Buffer) + cmd.SetErr(stderr) + err := cmd.Execute() + if tt.errExpected { + assert.Error(t, err, stdout) + } else { + assert.NoError(t, err, stderr) + } + }) + } +} diff --git a/internal/pkg/util/copyfile.go b/internal/pkg/util/copyfile.go index ccaabbda..7f1a984b 100644 --- a/internal/pkg/util/copyfile.go +++ b/internal/pkg/util/copyfile.go @@ -14,27 +14,27 @@ func CopyFile(src string, dst string) error { // Open source file srcFD, err := os.Open(src) if err != nil { - wwlog.Error("Could not open source file %s: %s", src, err) + wwlog.Debug("Could not open source file %s: %s", src, err) return err } defer srcFD.Close() srcInfo, err := srcFD.Stat() if err != nil { - wwlog.Error("Could not stat source file %s: %s", src, err) + wwlog.Debug("Could not stat source file %s: %s", src, err) return err } dstFD, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, srcInfo.Mode()) if err != nil { - wwlog.Error("Could not create destination file %s: %s", dst, err) + wwlog.Debug("Could not create destination file %s: %s", dst, err) return err } defer dstFD.Close() bytes, err := io.Copy(dstFD, srcFD) if err != nil { - wwlog.Error("File copy from %s to %s failed.\n %s", src, dst, err) + wwlog.Debug("File copy from %s to %s failed.\n %s", src, dst, err) return err } else { wwlog.Debug("Copied %d bytes from %s to %s.", bytes, src, dst) @@ -42,7 +42,7 @@ func CopyFile(src string, dst string) error { err = CopyUIDGID(src, dst) if err != nil { - wwlog.Error("Ownership copy from %s to %s failed.\n %s", src, dst, err) + wwlog.Debug("Ownership copy from %s to %s failed.\n %s", src, dst, err) return err } return nil