Add container rename support

Signed-off-by: jason yang <jasonyangshadow@gmail.com>
This commit is contained in:
jason yang
2023-12-21 23:32:10 -07:00
committed by Jonathon Anderson
parent 7d17bcc6fa
commit d262ec10ef
10 changed files with 822 additions and 385 deletions

View File

@@ -0,0 +1,45 @@
package rename
import (
"fmt"
api "github.com/hpcng/warewulf/internal/pkg/api/container"
"github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1"
"github.com/hpcng/warewulf/internal/pkg/container"
"github.com/hpcng/warewulf/internal/pkg/wwlog"
"github.com/spf13/cobra"
)
func CobraRunE(cmd *cobra.Command, args []string) (err error) {
if len(args) > 2 {
wwlog.Warn("rename only requires 2 arguments but you provided %d arguments. Hence, they will be ignored.", len(args))
}
crp := &wwapiv1.ContainerRenameParameter{
ContainerName: args[0],
TargetName: args[1],
Build: SetBuild,
}
if !container.DoesSourceExist(crp.ContainerName) {
return fmt.Errorf("%s source dir does not exist", crp.ContainerName)
}
if container.DoesSourceExist(crp.TargetName) {
return fmt.Errorf("an other container with the name %s already exists", crp.TargetName)
}
if !container.ValidName(crp.TargetName) {
wwlog.Error("Container name contains illegal characters : %s", crp.TargetName)
return
}
err = api.ContainerRename(crp)
if err != nil {
err = fmt.Errorf("could not rename image: %s", err.Error())
return
}
wwlog.Info("Container %s successfully renamed as %s", crp.ContainerName, crp.TargetName)
return
}

View File

@@ -0,0 +1,63 @@
package rename
import (
"bytes"
"io"
"os"
"path"
"testing"
containerList "github.com/hpcng/warewulf/internal/app/wwctl/container/list"
"github.com/hpcng/warewulf/internal/pkg/testenv"
"github.com/hpcng/warewulf/internal/pkg/warewulfd"
"github.com/stretchr/testify/assert"
)
func Test_Rename(t *testing.T) {
env := testenv.New(t)
env.WriteFile(t, path.Join(testenv.WWChrootdir, "test-container/rootfs/file"), `test`)
defer env.RemoveAll(t)
warewulfd.SetNoDaemon()
// first we will verify that there is an existing container
t.Run("container list", func(t *testing.T) {
verifyContainerListOutput(t, "test-container")
})
// then rename it
t.Run("container rename", func(t *testing.T) {
baseCmd := GetCommand()
baseCmd.SetOut(nil)
baseCmd.SetErr(nil)
baseCmd.SetArgs([]string{"test-container", "test-container-rename"})
err := baseCmd.Execute()
assert.NoError(t, err)
})
// retrieve again
t.Run("Container list", func(t *testing.T) {
verifyContainerListOutput(t, "test-container-rename")
})
}
func verifyContainerListOutput(t *testing.T, content string) {
baseCmd := containerList.GetCommand()
baseCmd.SetOut(nil)
baseCmd.SetErr(nil)
stdoutR, stdoutW, _ := os.Pipe()
os.Stdout = stdoutW
err := baseCmd.Execute()
assert.NoError(t, err)
stdoutC := make(chan string)
go func() {
var buf bytes.Buffer
_, _ = io.Copy(&buf, stdoutR)
stdoutC <- buf.String()
}()
stdoutW.Close()
stdout := <-stdoutC
assert.NotEmpty(t, stdout, "output should not be empty")
assert.Contains(t, stdout, content)
}

View File

@@ -0,0 +1,35 @@
package rename
import (
"github.com/hpcng/warewulf/internal/pkg/container"
"github.com/spf13/cobra"
)
var baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "rename CONTAINER NEW_NAME",
Aliases: []string{"rn"},
Short: "Rename an existing container",
Long: "This command will rename an existing container.",
RunE: CobraRunE,
Args: cobra.MinimumNArgs(2),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
return nil, cobra.ShellCompDirectiveNoFileComp
}
list, _ := container.ListSources()
return list, cobra.ShellCompDirectiveNoFileComp
},
}
var SetBuild bool
func init() {
// Nothing to do here
baseCmd.PersistentFlags().BoolVarP(&SetBuild, "build", "b", false, "Build container after rename")
}
// GetRootCommand returns the root cobra.Command for the application.
func GetCommand() *cobra.Command {
return baseCmd
}

View File

@@ -7,23 +7,22 @@ import (
"github.com/hpcng/warewulf/internal/app/wwctl/container/exec"
"github.com/hpcng/warewulf/internal/app/wwctl/container/imprt"
"github.com/hpcng/warewulf/internal/app/wwctl/container/list"
"github.com/hpcng/warewulf/internal/app/wwctl/container/rename"
"github.com/hpcng/warewulf/internal/app/wwctl/container/shell"
"github.com/hpcng/warewulf/internal/app/wwctl/container/show"
"github.com/hpcng/warewulf/internal/app/wwctl/container/syncuser"
"github.com/spf13/cobra"
)
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "container COMMAND [OPTIONS]",
Short: "Container / VNFS image management",
Long: "Starting with version 4, Warewulf uses containers to build the bootable VNFS\n" +
"node images. These commands will help you import, manage, and transform\n" +
"containers into bootable Warewulf VNFS images.",
Aliases: []string{"vnfs"},
}
)
var baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "container COMMAND [OPTIONS]",
Short: "Container / VNFS image management",
Long: "Starting with version 4, Warewulf uses containers to build the bootable VNFS\n" +
"node images. These commands will help you import, manage, and transform\n" +
"containers into bootable Warewulf VNFS images.",
Aliases: []string{"vnfs"},
}
func init() {
baseCmd.AddCommand(build.GetCommand())
@@ -35,7 +34,7 @@ func init() {
baseCmd.AddCommand(show.GetCommand())
baseCmd.AddCommand(syncuser.GetCommand())
baseCmd.AddCommand(copy.GetCommand())
baseCmd.AddCommand(rename.GetCommand())
}
// GetRootCommand returns the root cobra.Command for the application.