diff --git a/CHANGELOG.md b/CHANGELOG.md index d1522e07..4cf3d357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 parameter. (#644) - Add support for listing profile/node via comma-separated values. #739 - Sort the node list returned entries by name. +- Add `--parents` option to `overlay import` subcommand to create necessary + parent folder. #608 ### Changed diff --git a/internal/app/wwctl/overlay/imprt/main.go b/internal/app/wwctl/overlay/imprt/main.go index e83a5e59..f8a863ec 100644 --- a/internal/app/wwctl/overlay/imprt/main.go +++ b/internal/app/wwctl/overlay/imprt/main.go @@ -3,6 +3,7 @@ package imprt import ( "os" "path" + "path/filepath" "github.com/hpcng/warewulf/internal/pkg/node" "github.com/hpcng/warewulf/internal/pkg/overlay" @@ -42,6 +43,23 @@ func CobraRunE(cmd *cobra.Command, args []string) error { os.Exit(1) } + if CreateDirs { + parent := filepath.Dir(path.Join(overlaySource, dest)) + if _, err := os.Stat(parent); os.IsNotExist(err) { + wwlog.Debug("Create dir: %s", parent) + srcInfo, err := os.Stat(source) + if err != nil { + wwlog.Error("Could not retrieve the stat for file: %s", err) + return err + } + err = os.MkdirAll(parent, srcInfo.Mode()) + if err != nil { + wwlog.Error("Could not create parent dif: %s: %v", parent, err) + return err + } + } + } + err := util.CopyFile(source, path.Join(overlaySource, dest)) if err != nil { return errors.Wrap(err, "could not copy file into overlay") diff --git a/internal/app/wwctl/overlay/imprt/main_test.go b/internal/app/wwctl/overlay/imprt/main_test.go new file mode 100644 index 00000000..e74c84b5 --- /dev/null +++ b/internal/app/wwctl/overlay/imprt/main_test.go @@ -0,0 +1,95 @@ +package imprt + +import ( + "fmt" + "io/ioutil" + "os" + "testing" + + warewulfconf "github.com/hpcng/warewulf/internal/pkg/config" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/warewulfd" + "github.com/stretchr/testify/assert" +) + +func Test_List(t *testing.T) { + tmpdir, err := ioutil.TempDir(os.TempDir(), "warewulf") + if err != nil { + t.Errorf("Could not create temp folder: %v", err) + t.FailNow() + } + defer os.RemoveAll(tmpdir) + + overlayDir := fmt.Sprintf("%s/overlay", tmpdir) + err = os.MkdirAll(overlayDir, 0o755) + if err != nil { + t.Errorf("Could not create target folder: %s, err: %v", overlayDir, err) + t.FailNow() + } + + importDir := fmt.Sprintf("%s/test", overlayDir) + err = os.MkdirAll(importDir, 0o755) + if err != nil { + t.Errorf("Could not create target folder: %s, err: %v", importDir, err) + t.FailNow() + } + + file, err := ioutil.TempFile(tmpdir, "file") + if err != nil { + t.Errorf("Could not create tempfile") + t.FailNow() + } + file.Close() + err = os.Chmod(file.Name(), 0o755) + if err != nil { + t.Errorf("Could not change the file %s mode: %v", file.Name(), err) + t.FailNow() + } + + inDb := `WW_INTERNAL: 43 +nodeprofiles: + default: {} +nodes: {} +` + conf_yml := ` +WW_INTERNAL: 0 + ` + + conf := warewulfconf.New() + err = conf.Parse([]byte(conf_yml)) + assert.NoError(t, err) + warewulfd.SetNoDaemon() + conf.Paths.WWOverlaydir = overlayDir + + _, err = node.Parse([]byte(inDb)) + assert.NoError(t, err) + t.Logf("Running test: wwctl overlay import test\n") + t.Run("wwctl overlay import test", func(t *testing.T) { + baseCmd := GetCommand() + baseCmd.SetArgs([]string{"-n", "test", file.Name()}) + baseCmd.SetOut(nil) + baseCmd.SetErr(nil) + err = baseCmd.Execute() + if err == nil { + t.Errorf("Should recieve error when running command") + t.FailNow() + } + if _, err = os.Stat(importDir + file.Name()); err == nil { + t.Errorf("Target file %s should not exist", importDir+file.Name()) + t.FailNow() + } + + baseCmd.SetArgs([]string{"-p", "-n", "test", file.Name()}) + baseCmd.SetOut(nil) + baseCmd.SetErr(nil) + err = baseCmd.Execute() + if err != nil { + t.Errorf("Received error when running command, err: %v\n", err) + t.FailNow() + } + if _, err = os.Stat(importDir + file.Name()); os.IsNotExist(err) { + t.Errorf("Target file %s should exist", importDir+file.Name()) + t.FailNow() + } + }) +} diff --git a/internal/app/wwctl/overlay/imprt/root.go b/internal/app/wwctl/overlay/imprt/root.go index fd9b957f..f0f9e8a4 100644 --- a/internal/app/wwctl/overlay/imprt/root.go +++ b/internal/app/wwctl/overlay/imprt/root.go @@ -23,10 +23,12 @@ var ( }, } NoOverlayUpdate bool + CreateDirs bool ) func init() { baseCmd.PersistentFlags().BoolVarP(&NoOverlayUpdate, "noupdate", "n", false, "Don't update overlays") + baseCmd.PersistentFlags().BoolVarP(&CreateDirs, "parents", "p", false, "Create any necessary parent directories") } // GetRootCommand returns the root cobra.Command for the application.