Merge pull request #2131 from anderbubble/docs-omnibus

Documentation improvements omnibus
This commit is contained in:
Christian Goll
2026-03-19 09:06:40 +01:00
committed by GitHub
59 changed files with 1009 additions and 241 deletions

View File

@@ -8,7 +8,7 @@ import (
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "hostfile [OPTIONS]",
Use: "hostfile [OPTIONS]",
Short: "update hostfile on master",
Long: "Manage the hostfile on the master node\n",
RunE: CobraRunE,

View File

@@ -8,7 +8,7 @@ import (
var (
baseCmd = &cobra.Command{
Use: "print",
Short: "print wareweulf.conf",
Short: "print warewulf.conf",
Long: "This command prints the actual used warewulf.conf, can be used to create an empty valid warewulf.conf",
RunE: CobraRunE,
Args: cobra.NoArgs,

View File

@@ -44,13 +44,13 @@ func init() {
baseCmd.PersistentFlags().BoolVarP(&SetUpdate, "update", "u", false, "Overwrite files in an existing image with the files of remote image")
baseCmd.PersistentFlags().BoolVarP(&SetBuild, "build", "b", false, "Build image after pulling")
baseCmd.PersistentFlags().BoolVar(&SyncUser, "syncuser", false, "Synchronize UIDs/GIDs from host to image")
baseCmd.PersistentFlags().BoolVar(&OciNoHttps, "nohttps", false, "Ignore wrong TLS certificates, superseedes env WAREWULF_OCI_NOHTTPS")
baseCmd.PersistentFlags().StringVar(&OciUsername, "username", "", "Set username for the access to the registry, superseedes env WAREWULF_OCI_USERNAME")
baseCmd.PersistentFlags().StringVar(&OciPassword, "password", "", "Set password for the access to the registry, superseedes env WAREWULF_OCI_PASSWORD")
baseCmd.PersistentFlags().StringVar(&OciPassword, "passwd", "", "Set password for the access to the registry, superseedes env WAREWULF_OCI_PASSWORD")
baseCmd.PersistentFlags().BoolVar(&OciNoHttps, "nohttps", false, "Ignore wrong TLS certificates, supersedes env WAREWULF_OCI_NOHTTPS")
baseCmd.PersistentFlags().StringVar(&OciUsername, "username", "", "Set username for the access to the registry, supersedes env WAREWULF_OCI_USERNAME")
baseCmd.PersistentFlags().StringVar(&OciPassword, "password", "", "Set password for the access to the registry, supersedes env WAREWULF_OCI_PASSWORD")
baseCmd.PersistentFlags().StringVar(&OciPassword, "passwd", "", "Set password for the access to the registry, supersedes env WAREWULF_OCI_PASSWORD")
_ = baseCmd.PersistentFlags().MarkHidden("passwd")
baseCmd.PersistentFlags().StringVar(&Platform, "platform", "", "Set other hardware platform e.g. amd64 or arm64, superseedes env WAREWULF_OCI_PLATFORM")
baseCmd.PersistentFlags().StringVar(&Platform, "arch", "", "Set other hardware platform, superseedes env WAREWULF_OCI_PLATFORM")
baseCmd.PersistentFlags().StringVar(&Platform, "platform", "", "Set other hardware platform e.g. amd64 or arm64, supersedes env WAREWULF_OCI_PLATFORM")
baseCmd.PersistentFlags().StringVar(&Platform, "arch", "", "Set other hardware platform, supersedes env WAREWULF_OCI_PLATFORM")
_ = baseCmd.PersistentFlags().MarkHidden("arch")
}

View File

@@ -19,11 +19,9 @@ var baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "image COMMAND [OPTIONS]",
Short: "Operating system image management",
Long: "Starting with version 4, Warewulf uses images to build the bootable\n" +
"node images. These commands will help you import, manage, and transform\n" +
"images into bootable Warewulf images.",
Aliases: []string{"vnfs", "container"},
Args: cobra.NoArgs,
Long: "Import, manage, and transform OS images as bootable Warewulf images.",
Aliases: []string{"vnfs", "container"},
Args: cobra.NoArgs,
}
func init() {

View File

@@ -22,7 +22,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
if write && !build {
// when write = true and build = false, we will print a warnning, this is the default case
wwlog.Warn("Syncuser is completed. Rebuild image or add `--build` flag for automatic rebuild after syncuser.")
wwlog.Info("Syncuser is completed. Rebuild image or add `--build` flag for automatic rebuild after syncuser.")
} else if write && build {
// if write = true and build = true, then it'll trigger the image build after sync
cbp := &wwapiv1.ImageBuildParameter{

View File

@@ -9,10 +9,15 @@ var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "syncuser [OPTIONS] IMAGE",
Short: "Synchronizes user in image",
Long: `Synchronize the uids and gids from the host to the image.
Users/groups which are only present in the image will be preserved if no
uid/gid collision is detected. File ownerships are also changed.`,
Short: "Synchronize UIDs/GIDs from the server to an OS image",
Long: `Synchronize UIDs and GIDs from the server into an OS image, updating
/etc/passwd, /etc/group, and file ownerships within the image. Users and
groups that exist only in the image are preserved unless a UID/GID collision
is detected.
This command affects the image itself (a one-time operation at build/import
time). To also make host users available on provisioned nodes at runtime, add
the "syncuser" overlay to the node or profile.`,
RunE: CobraRunE,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) != 0 {
@@ -29,8 +34,8 @@ uid/gid collision is detected. File ownerships are also changed.`,
)
func init() {
baseCmd.PersistentFlags().BoolVar(&write, "write", true, "Synchronize uis/gids and write files in image")
baseCmd.PersistentFlags().BoolVar(&build, "build", false, "Build image after syncuser is completed")
baseCmd.PersistentFlags().BoolVar(&write, "write", true, "Synchronize UIDs/GIDs and write files in OS image")
baseCmd.PersistentFlags().BoolVar(&build, "build", false, "Build OS image after syncuser is completed")
}
// GetRootCommand returns the root cobra.Command for the application.

View File

@@ -8,7 +8,7 @@ import (
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "export NODENAME",
Use: "export NODENAME",
Short: "Export nodes as yaml to stdout",
Long: "This command exports the given nodes as yaml to stdout.",
RunE: CobraRunE,

View File

@@ -17,7 +17,7 @@ import (
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "node COMMAND [OPTONS]",
Use: "node COMMAND [OPTIONS]",
Short: "Node management",
Long: "Management of node settings. All node ranges can use brackets to identify\n" +
"node ranges. For example: n00[00-4].cluster[0-1] will identify the first 5 nodes\n" +

View File

@@ -27,7 +27,7 @@ func init() {
panic(err)
}
baseCmd.PersistentFlags().StringVarP(&OverlayDir, "output", "o", "", `Do not create an overlay image for distribution but write to
the given directory. An overlay must also be ge given to use this option.`)
the given directory. An overlay must also be given to use this option.`)
baseCmd.PersistentFlags().IntVar(&Workers, "workers", 0, "The number of parallel workers building overlays (<=0 indicates 1 worker per CPU)")
}

View File

@@ -8,8 +8,8 @@ import (
var (
baseCmd = &cobra.Command{
DisableFlagsInUseLine: true,
Use: "edit [OPTIONS] NODENAME",
Short: "Edit node(s) with editor",
Use: "edit [OPTIONS] PROFILE",
Short: "Edit profile(s) with editor",
Long: "This command opens an editor for the given profiles.",
RunE: CobraRunE,
ValidArgsFunction: completions.Profiles,

View File

@@ -88,7 +88,7 @@ func NodeSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesYaml
if set.PartitionDelete != "" {
for diskname, disk := range nodePtr.Disks {
if _, ok := disk.Partitions[set.PartitionDelete]; ok {
wwlog.Verbose("Node: %s, on disk %, deleting partition: %s", nId, diskname, set.PartitionDelete)
wwlog.Verbose("Node: %s, on disk %s, deleting partition: %s", nId, diskname, set.PartitionDelete)
delete(disk.Partitions, set.PartitionDelete)
} else {
return nodeDB, count, fmt.Errorf("partition doesn't exist: %s", set.PartitionDelete)

View File

@@ -89,7 +89,7 @@ func ProfileSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesY
if set.PartitionDelete != "" {
for diskname, disk := range profilePtr.Disks {
if _, ok := disk.Partitions[set.PartitionDelete]; ok {
wwlog.Verbose("Node: %s, on disk %, deleting partition: %s", profileId, diskname, set.PartitionDelete)
wwlog.Verbose("Profile: %s, on disk %s, deleting partition: %s", profileId, diskname, set.PartitionDelete)
delete(disk.Partitions, set.PartitionDelete)
} else {
return nodeDB, count, fmt.Errorf("partition doesn't exist: %s", set.PartitionDelete)
@@ -99,7 +99,7 @@ func ProfileSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesY
}
if set.DiskDelete != "" {
if _, ok := profilePtr.Disks[set.DiskDelete]; ok {
wwlog.Verbose("Node: %s, deleting disk: %s", profileId, set.DiskDelete)
wwlog.Verbose("Profile: %s, deleting disk: %s", profileId, set.DiskDelete)
delete(profilePtr.Disks, set.DiskDelete)
} else {
return nodeDB, count, fmt.Errorf("disk doesn't exist: %s", set.DiskDelete)
@@ -107,7 +107,7 @@ func ProfileSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesY
}
if set.FilesystemDelete != "" {
if _, ok := profilePtr.FileSystems[set.FilesystemDelete]; ok {
wwlog.Verbose("Node: %s, deleting filesystem: %s", profileId, set.FilesystemDelete)
wwlog.Verbose("Profile: %s, deleting filesystem: %s", profileId, set.FilesystemDelete)
delete(profilePtr.FileSystems, set.FilesystemDelete)
} else {
return nodeDB, count, fmt.Errorf("disk doesn't exist: %s", set.FilesystemDelete)

View File

@@ -34,7 +34,7 @@ func Build(name string, buildForce bool) error {
var err error
ignore, err = util.ReadFile(excludes_file)
if err != nil {
return fmt.Errorf("failed creating directory: %s: %w", imagePath, err)
return fmt.Errorf("failed reading excludes file: %s: %w", excludes_file, err)
}
}

View File

@@ -58,7 +58,7 @@ func (f *boolPtrFlag) Type() string {
}
type NodeConfDel struct {
TagsDel []string `lopt:"tagdel" comment:"add tags"`
TagsDel []string `lopt:"tagdel" comment:"delete tags"`
IpmiTagsDel []string `lopt:"ipmitagdel" comment:"delete ipmi tags"`
NetTagsDel []string `lopt:"nettagdel" comment:"delete network tags"`
NetDel string `lopt:"netdel" comment:"network to delete"`

View File

@@ -54,7 +54,7 @@ func getImages() usecase.Interactor {
}
})
u.SetTitle("Get images")
u.SetDescription("Get all node images")
u.SetDescription("Get all OS images")
u.SetTags("Image")
return u
}
@@ -74,7 +74,7 @@ func getImageByName() usecase.Interactor {
}
})
u.SetTitle("Get an image")
u.SetDescription("Get a node image by its name")
u.SetDescription("Get an OS image by its name")
u.SetTags("Image")
return u
}
@@ -110,7 +110,7 @@ func importImage() usecase.Interactor {
}
})
u.SetTitle("Import an image")
u.SetDescription("Import a node image from an OCI registry")
u.SetDescription("Import an OS image from an OCI registry")
u.SetTags("Image")
return u
@@ -146,7 +146,7 @@ func deleteImage() usecase.Interactor {
return image_api.ImageDelete(cdp)
})
u.SetTitle("Delete an image")
u.SetDescription("Delete an existing node image")
u.SetDescription("Delete an existing OS image")
u.SetTags("Image")
return u
@@ -156,7 +156,7 @@ func updateImage() usecase.Interactor {
type renameImageInput struct {
Name string `path:"name" required:"true" description:"Name of image to update"`
NewName string `json:"name" description:"New name to rename the image to"`
Build bool `query:"build" default:"true" description:"Build the image image after renaming, default:'true'"`
Build bool `query:"build" default:"true" description:"Build the OS image after renaming, default:'true'"`
}
u := usecase.NewInteractor(func(ctx context.Context, input renameImageInput, output *Image) error {
@@ -179,7 +179,7 @@ func updateImage() usecase.Interactor {
return nil
})
u.SetTitle("Update or rename an image")
u.SetDescription("Update or rename an existing node image")
u.SetDescription("Update or rename an existing OS image")
u.SetTags("Image")
return u
@@ -188,7 +188,7 @@ func updateImage() usecase.Interactor {
func buildImage() usecase.Interactor {
type buildImageInput struct {
Name string `path:"name" required:"true" description:"Name of image to build"`
Force bool `query:"force" default:"false" description:"Build the image image even if it appears unnecessary, default:'false'"`
Force bool `query:"force" default:"false" description:"Build the OS image even if it appears unnecessary, default:'false'"`
}
u := usecase.NewInteractor(func(ctx context.Context, input buildImageInput, output *Image) error {
@@ -206,7 +206,7 @@ func buildImage() usecase.Interactor {
return nil
})
u.SetTitle("Build an image")
u.SetDescription("Build a node image")
u.SetDescription("Build an OS image")
u.SetTags("Image")
return u

View File

@@ -101,13 +101,13 @@ func (of *OverlayFile) readContents() (string, error) {
fullPath := of.FullPath()
f, err := os.ReadFile(fullPath)
if err != nil {
wwlog.Warn("os.ReadFile err %w", err)
wwlog.Warn("os.ReadFile err %v", err)
return "", err
}
// Populate the permissions, uid, and gid.
s, err := os.Stat(fullPath)
if err != nil {
wwlog.Warn("os.Stat err %w", err)
wwlog.Warn("os.Stat err %v", err)
return "", err
}
fileMode := s.Mode()

View File

@@ -82,7 +82,7 @@ func DaemonStatus() error {
} else {
err := process.Signal(syscall.Signal(0))
if err != nil {
return fmt.Errorf("failed to send process SIGCONT: %w", err)
return fmt.Errorf("failed to send signal 0 (process existence check): %w", err)
} else {
wwlog.Serv("Warewulf server is running at PID: %d", pid)
}

View File

@@ -6,6 +6,7 @@ import (
"path"
"github.com/warewulf/warewulf/internal/pkg/image"
"github.com/warewulf/warewulf/internal/pkg/util"
"github.com/warewulf/warewulf/internal/pkg/wwlog"
)
@@ -38,20 +39,20 @@ func HandleEfiBoot(w http.ResponseWriter, req *http.Request) {
case "grub.efi", "grub-tpm.efi", "grubx64.efi", "grubia32.efi", "grubaa64.efi", "grubarm.efi":
stageFile = image.GrubFind(imageName)
if stageFile == "" {
wwlog.Error("could't find grub*.efi for %s", imageName)
wwlog.Error("couldn't find grub*.efi for %s", imageName)
w.WriteHeader(http.StatusNotFound)
return
}
case "grub.cfg":
stageFile = path.Join(ctx.conf.Paths.Sysconfdir, "warewulf/grub/grub.cfg.ww")
tmplData = buildTemplateVars(ctx.conf, ctx.rinfo, ctx.remoteNode)
if stageFile == "" {
wwlog.Error("could't find grub.cfg template for %s", imageName)
if !util.IsFile(stageFile) {
wwlog.Error("couldn't find grub.cfg template for %s", imageName)
w.WriteHeader(http.StatusNotFound)
return
}
default:
wwlog.ErrorExc(fmt.Errorf("could't find efiboot file: %s", ctx.rinfo.efifile), "")
wwlog.ErrorExc(fmt.Errorf("couldn't find efiboot file: %s", ctx.rinfo.efifile), "")
w.WriteHeader(http.StatusNotFound)
return
}

View File

@@ -97,7 +97,7 @@ func RunServer() error {
auth := warewulfconf.NewAuthentication()
if util.IsFile(conf.Paths.AuthenticationConf()) {
if err := auth.Read(conf.Paths.AuthenticationConf()); err != nil {
wwlog.Warn("%w\n", err)
wwlog.Warn("%v", err)
}
}

View File

@@ -167,10 +167,10 @@ func SetLogWriterInfo(newOut io.Writer) {
}
/*
Set the log ofr info only
Set the log writer for errors
*/
func SetLogWriterErr(newOut io.Writer) {
logOut = newOut
logErr = newOut
}
/*