diff --git a/CHANGELOG.md b/CHANGELOG.md index e014c0fa..f4979976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fixed a bug in `wwclient` which prevented proper cleanup of ephemeral files. - Fixed `wwclient --debug` to properly enable debug logging. - Updated golang BuildRequires in RPM specfile. #1990 +- Fixed handling of `wwctl` boolean options for disk related seetings. ## v4.6.3, 2025-08-01 @@ -48,7 +49,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `DELETE /api/overlays/{name}?force=true` can delete overlays that are in use - `warewulfd` overlay autobuild rebuilds overlays after node discovery. #1468 - Improved netplan support. #1873 -- fixed boolean options for the disk related seetings ### Fixed diff --git a/internal/app/wwctl/profile/set/main_test.go b/internal/app/wwctl/profile/set/main_test.go index 4d1da289..88674ca6 100644 --- a/internal/app/wwctl/profile/set/main_test.go +++ b/internal/app/wwctl/profile/set/main_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/warewulf/warewulf/internal/pkg/testenv" "github.com/warewulf/warewulf/internal/pkg/warewulfd" - "github.com/warewulf/warewulf/internal/pkg/wwlog" ) func Test_Profile_Set(t *testing.T) { @@ -187,7 +186,7 @@ nodeprofiles: default: disks: /dev/vda: - wipe_table: "true" + wipe_table: true partitions: var: number: "1" @@ -205,7 +204,7 @@ nodeprofiles: default: disks: /dev/vda: - wipe_table: "true" + wipe_table: true partitions: var: number: "1" @@ -220,7 +219,7 @@ nodeprofiles: default: disks: /dev/vda: - wipe_table: "false" + wipe_table: false partitions: var: number: "1" @@ -232,7 +231,6 @@ nodes: {}`, }, } - wwlog.SetLogLevel(wwlog.DEBUG) for name, tt := range tests { t.Run(name, func(t *testing.T) { env := testenv.New(t) diff --git a/internal/pkg/api/node/set.go b/internal/pkg/api/node/set.go index 51f7fbe1..c19ec97f 100644 --- a/internal/pkg/api/node/set.go +++ b/internal/pkg/api/node/set.go @@ -72,7 +72,7 @@ func NodeSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesYaml return } // merge in - err = mergo.Merge(nodePtr, &newConf, mergo.WithOverride) + err = mergo.Merge(nodePtr, &newConf, mergo.WithOverride, mergo.WithTransformers(node.Transformer{})) if err != nil { return } diff --git a/internal/pkg/api/profile/set.go b/internal/pkg/api/profile/set.go index e20cd55c..c35b4ade 100644 --- a/internal/pkg/api/profile/set.go +++ b/internal/pkg/api/profile/set.go @@ -72,7 +72,7 @@ func ProfileSetParameterCheck(set *wwapiv1.ConfSetParameter) (nodeDB node.NodesY return } // merge in - err = mergo.Merge(profilePtr, &newProfile, mergo.WithOverride) + err = mergo.Merge(profilePtr, &newProfile, mergo.WithOverride, mergo.WithTransformers(node.Transformer{})) if err != nil { return } diff --git a/internal/pkg/config/api.go b/internal/pkg/config/api.go index 349909c4..766c86db 100644 --- a/internal/pkg/config/api.go +++ b/internal/pkg/config/api.go @@ -4,6 +4,7 @@ import ( "net" "github.com/creasty/defaults" + "github.com/warewulf/warewulf/internal/pkg/util" ) type IPNet net.IPNet @@ -46,5 +47,5 @@ func (conf *APIConf) Unmarshal(unmarshal func(interface{}) error) error { } func (conf APIConf) Enabled() bool { - return BoolP(conf.EnabledP) + return util.BoolP(conf.EnabledP) } diff --git a/internal/pkg/config/buildconfig.go.in b/internal/pkg/config/buildconfig.go.in index 8896d30e..a0ff26f9 100644 --- a/internal/pkg/config/buildconfig.go.in +++ b/internal/pkg/config/buildconfig.go.in @@ -1,6 +1,7 @@ package config import ( + "github.com/warewulf/warewulf/internal/pkg/util" "path" ) @@ -34,7 +35,7 @@ type TFTPConf struct { } func (conf TFTPConf) Enabled() bool { - return BoolP(conf.EnabledP) + return util.BoolP(conf.EnabledP) } // WarewulfConf adds additional Warewulf-specific configuration to @@ -50,19 +51,19 @@ type WarewulfConf struct { } func (conf WarewulfConf) Secure() bool { - return BoolP(conf.SecureP) + return util.BoolP(conf.SecureP) } func (conf WarewulfConf) AutobuildOverlays() bool { - return BoolP(conf.AutobuildOverlaysP) + return util.BoolP(conf.AutobuildOverlaysP) } func (conf WarewulfConf) EnableHostOverlay() bool { - return BoolP(conf.EnableHostOverlayP) + return util.BoolP(conf.EnableHostOverlayP) } func (conf WarewulfConf) GrubBoot() bool { - return BoolP(conf.GrubBootP) + return util.BoolP(conf.GrubBootP) } func (paths BuildConfig) NodesConf() string { diff --git a/internal/pkg/config/dhcp.go b/internal/pkg/config/dhcp.go index a225b478..419ca266 100644 --- a/internal/pkg/config/dhcp.go +++ b/internal/pkg/config/dhcp.go @@ -1,5 +1,9 @@ package config +import ( + "github.com/warewulf/warewulf/internal/pkg/util" +) + // DHCPConf represents the configuration for the DHCP service that // Warewulf will configure. type DHCPConf struct { @@ -11,5 +15,5 @@ type DHCPConf struct { } func (conf DHCPConf) Enabled() bool { - return BoolP(conf.EnabledP) + return util.BoolP(conf.EnabledP) } diff --git a/internal/pkg/config/mounts.go b/internal/pkg/config/mounts.go index 5eadfb0e..0bfc323a 100644 --- a/internal/pkg/config/mounts.go +++ b/internal/pkg/config/mounts.go @@ -1,5 +1,9 @@ package config +import ( + "github.com/warewulf/warewulf/internal/pkg/util" +) + // A MountEntry represents a bind mount that is applied to an image // during exec and shell. type MountEntry struct { @@ -11,9 +15,9 @@ type MountEntry struct { } func (mount MountEntry) ReadOnly() bool { - return BoolP(mount.ReadOnlyP) + return util.BoolP(mount.ReadOnlyP) } func (mount MountEntry) Copy() bool { - return BoolP(mount.CopyP) + return util.BoolP(mount.CopyP) } diff --git a/internal/pkg/config/nfs.go b/internal/pkg/config/nfs.go index 9b4f118a..5ecb50cc 100644 --- a/internal/pkg/config/nfs.go +++ b/internal/pkg/config/nfs.go @@ -2,6 +2,7 @@ package config import ( "github.com/creasty/defaults" + "github.com/warewulf/warewulf/internal/pkg/util" ) // NFSConf represents the NFS configuration that will be used by @@ -14,7 +15,7 @@ type NFSConf struct { } func (conf NFSConf) Enabled() bool { - return BoolP(conf.EnabledP) + return util.BoolP(conf.EnabledP) } // An NFSExportConf reprents a single NFS export / mount. diff --git a/internal/pkg/config/util.go b/internal/pkg/config/util.go index 9e74d9cd..5c277651 100644 --- a/internal/pkg/config/util.go +++ b/internal/pkg/config/util.go @@ -5,10 +5,6 @@ import ( "net" ) -func BoolP(p *bool) bool { - return p != nil && *p -} - func GetOutboundIP() net.IP { conn, err := net.Dial("udp", "192.0.2.1:80") if err != nil { diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 73397e65..4e7ed512 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -3,6 +3,7 @@ package node import ( "net" + "github.com/warewulf/warewulf/internal/pkg/util" "github.com/warewulf/warewulf/internal/pkg/wwtype" ) @@ -93,7 +94,7 @@ Holds the disks of a node */ type Disk struct { id string `yaml:"-" json:"-"` - WipeTable wwtype.WWbool `yaml:"wipe_table,omitempty" json:"wipe_table,omitempty" lopt:"diskwipe" comment:"whether or not the partition tables shall be wiped"` + WipeTableP *bool `yaml:"wipe_table,omitempty" json:"wipe_table,omitempty" lopt:"diskwipe" comment:"whether or not the partition tables shall be wiped"` Partitions map[string]*Partition `yaml:"partitions,omitempty" json:"partitions,omitempty"` } @@ -102,29 +103,52 @@ partition definition, the label must be uniq so its used as the key in the Partitions map */ type Partition struct { - id string `yaml:"-" json:"-"` - Number string `yaml:"number,omitempty" json:"number,omitempty" lopt:"partnumber" comment:"Set the partition number, if not set next free slot is used" type:"uint"` - SizeMiB string `yaml:"size_mib,omitempty" json:"size_mib,omitempty" lopt:"partsize" comment:"Set the size of the partition, if not set maximal possible size is used" type:"uint"` - StartMiB string `yaml:"start_mib,omitempty" json:"start_mib,omitempty" comment:"the start of the partition" type:"uint"` - TypeGuid string `yaml:"type_guid,omitempty" json:"type_guid,omitempty" lopt:"parttype" comment:"Set the partition type GUID"` - Guid string `yaml:"guid,omitempty" json:"guid,omitempty" comment:"the GPT unique partition GUID"` - WipePartitionEntry wwtype.WWbool `yaml:"wipe_partition_entry,omitempty" json:"wipe_partition_entry,omitempty" comment:"if true, Ignition will clobber an existing partition if it does not match the config"` - ShouldExist wwtype.WWbool `yaml:"should_exist,omitempty" json:"should_exist,omitempty" lopt:"partcreate" comment:"Create partition if it does not exist"` - Resize wwtype.WWbool `yaml:"resize,omitempty" json:"resize,omitempty" comment:"whether or not the existing partition should be resize"` + id string `yaml:"-" json:"-"` + Number string `yaml:"number,omitempty" json:"number,omitempty" lopt:"partnumber" comment:"Set the partition number, if not set next free slot is used" type:"uint"` + SizeMiB string `yaml:"size_mib,omitempty" json:"size_mib,omitempty" lopt:"partsize" comment:"Set the size of the partition, if not set maximal possible size is used" type:"uint"` + StartMiB string `yaml:"start_mib,omitempty" json:"start_mib,omitempty" comment:"the start of the partition" type:"uint"` + TypeGuid string `yaml:"type_guid,omitempty" json:"type_guid,omitempty" lopt:"parttype" comment:"Set the partition type GUID"` + Guid string `yaml:"guid,omitempty" json:"guid,omitempty" comment:"the GPT unique partition GUID"` + WipePartitionEntryP *bool `yaml:"wipe_partition_entry,omitempty" json:"wipe_partition_entry,omitempty" comment:"if true, Ignition will clobber an existing partition if it does not match the config"` + ShouldExistP *bool `yaml:"should_exist,omitempty" json:"should_exist,omitempty" lopt:"partcreate" comment:"Create partition if it does not exist"` + ResizeP *bool `yaml:"resize,omitempty" json:"resize,omitempty" comment:"whether or not the existing partition should be resize"` } /* Definition of a filesystem. The device is uniq so its used as key */ type FileSystem struct { - id string `yaml:"-" json:"-"` - Format string `yaml:"format,omitempty" json:"format,omitempty" lopt:"fsformat" comment:"format of the file system"` - Path string `yaml:"path,omitempty" json:"path,omitempty" lopt:"fspath" comment:"the mount point of the file system"` - WipeFileSystem wwtype.WWbool `yaml:"wipe_filesystem,omitempty" json:"wipe_filesystem,omitempty" lopt:"fswipe" comment:"wipe file system at boot"` - Label string `yaml:"label,omitempty" json:"label,omitempty" comment:"the label of the filesystem"` - Uuid string `yaml:"uuid,omitempty" json:"uuid,omitempty" comment:"the uuid of the filesystem"` - Options []string `yaml:"options,omitempty" json:"options,omitempty" comment:"any additional options to be passed to the format-specific mkfs utility"` - MountOptions string `yaml:"mount_options,omitempty" json:"mount_options,omitempty" comment:"any special options to be passed to the mount command"` + id string `yaml:"-" json:"-"` + Format string `yaml:"format,omitempty" json:"format,omitempty" lopt:"fsformat" comment:"format of the file system"` + Path string `yaml:"path,omitempty" json:"path,omitempty" lopt:"fspath" comment:"the mount point of the file system"` + WipeFileSystemP *bool `yaml:"wipe_filesystem,omitempty" json:"wipe_filesystem,omitempty" lopt:"fswipe" comment:"wipe file system at boot"` + Label string `yaml:"label,omitempty" json:"label,omitempty" comment:"the label of the filesystem"` + Uuid string `yaml:"uuid,omitempty" json:"uuid,omitempty" comment:"the uuid of the filesystem"` + Options []string `yaml:"options,omitempty" json:"options,omitempty" comment:"any additional options to be passed to the format-specific mkfs utility"` + MountOptions string `yaml:"mount_options,omitempty" json:"mount_options,omitempty" comment:"any special options to be passed to the mount command"` } type Resource interface{} + +// Disk methods +func (disk *Disk) WipeTable() bool { + return util.BoolP(disk.WipeTableP) +} + +// Partition methods +func (partition *Partition) WipePartitionEntry() bool { + return util.BoolP(partition.WipePartitionEntryP) +} + +func (partition *Partition) ShouldExist() bool { + return util.BoolP(partition.ShouldExistP) +} + +func (partition *Partition) Resize() bool { + return util.BoolP(partition.ResizeP) +} + +// FileSystem methods +func (fs *FileSystem) WipeFileSystem() bool { + return util.BoolP(fs.WipeFileSystemP) +} diff --git a/internal/pkg/node/fields_test.go b/internal/pkg/node/fields_test.go index ca82203f..f2244140 100644 --- a/internal/pkg/node/fields_test.go +++ b/internal/pkg/node/fields_test.go @@ -113,7 +113,7 @@ nodes: rootfs: resize: false`, node: "n1", - field: "Disks[/dev/vda].Partitions[rootfs].Resize", + field: "Disks[/dev/vda].Partitions[rootfs].ResizeP", value: "false", }, } diff --git a/internal/pkg/node/flags.go b/internal/pkg/node/flags.go index 7ea41956..a1326197 100644 --- a/internal/pkg/node/flags.go +++ b/internal/pkg/node/flags.go @@ -3,11 +3,60 @@ package node import ( "net" "reflect" + "strconv" + "strings" "github.com/spf13/cobra" "github.com/warewulf/warewulf/internal/pkg/wwtype" ) +// boolPtrFlag implements pflag.Value for *bool fields +type boolPtrFlag struct { + ptr **bool +} + +func (f *boolPtrFlag) String() string { + if *f.ptr == nil { + return "" + } + return strconv.FormatBool(**f.ptr) +} + +func (f *boolPtrFlag) Set(value string) error { + // Handle unset values + unsetValues := []string{"unset", "delete", "undef", "--", "nil"} + for _, unset := range unsetValues { + if strings.ToLower(value) == unset { + *f.ptr = nil + return nil + } + } + + // Handle yes/no + if strings.ToLower(value) == "yes" { + v := true + *f.ptr = &v + return nil + } + if strings.ToLower(value) == "no" { + v := false + *f.ptr = &v + return nil + } + + // Parse boolean + if val, err := strconv.ParseBool(value); err == nil { + *f.ptr = &val + return nil + } + + return nil +} + +func (f *boolPtrFlag) Type() string { + return "bool" +} + type NodeConfDel struct { TagsDel []string `lopt:"tagdel" comment:"add tags"` IpmiTagsDel []string `lopt:"ipmitagdel" comment:"delete ipmi tags"` @@ -173,6 +222,21 @@ func createFlags(baseCmd *cobra.Command, net.IP{}, // empty default! myType.Tag.Get("comment")) } + } else if myType.Type == reflect.TypeOf((*bool)(nil)) { + // Handle *bool type for nullable booleans + ptr := myVal.Addr().Interface().(**bool) + if myType.Tag.Get("sopt") != "" { + baseCmd.PersistentFlags().VarP(&boolPtrFlag{ptr: ptr}, + myType.Tag.Get("lopt"), + myType.Tag.Get("sopt"), + myType.Tag.Get("comment")) + baseCmd.Flag(myType.Tag.Get("lopt")).NoOptDefVal = "true" + } else { + baseCmd.PersistentFlags().Var(&boolPtrFlag{ptr: ptr}, + myType.Tag.Get("lopt"), + myType.Tag.Get("comment")) + baseCmd.Flag(myType.Tag.Get("lopt")).NoOptDefVal = "true" + } } else if myType.Type == reflect.TypeOf(wwbool) { ptr := myVal.Addr().Interface().(*wwtype.WWbool) if myType.Tag.Get("sopt") != "" { diff --git a/internal/pkg/node/mergo.go b/internal/pkg/node/mergo.go index 575243ae..166b2c01 100644 --- a/internal/pkg/node/mergo.go +++ b/internal/pkg/node/mergo.go @@ -69,7 +69,18 @@ func (config *NodesYaml) getProfilesProfiles(input []string, visited map[string] type Transformer struct{} func (t Transformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ == reflect.TypeOf(net.IP{}) { + if typ == reflect.TypeOf((*bool)(nil)) { + return func(dst, src reflect.Value) error { + if !src.IsValid() { + return nil + } + // Always override *bool values when source is set + if !src.IsNil() { + dst.Set(src) + } + return nil + } + } else if typ == reflect.TypeOf(net.IP{}) { return func(dst, src reflect.Value) error { if !src.IsValid() || src.IsNil() { return nil diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 7a9eaf1b..b51e1759 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -187,12 +187,16 @@ func recursiveFlatten(obj interface{}) (hasContent bool) { case reflect.Ptr: if valObj.Elem().Field(i).Addr().IsValid() { - ret := recursiveFlatten((valObj.Elem().Field(i).Interface())) - if !ret { - valObj.Elem().Field(i).Set(reflect.Zero(valObj.Elem().Field(i).Type())) + // Handle *bool fields separately as they are not structs + if typeObj.Elem().Field(i).Type == reflect.TypeOf((*bool)(nil)) { + hasContent = !valObj.Elem().Field(i).IsZero() || hasContent + } else { + ret := recursiveFlatten((valObj.Elem().Field(i).Interface())) + if !ret { + valObj.Elem().Field(i).Set(reflect.Zero(valObj.Elem().Field(i).Type())) + } + hasContent = ret || hasContent } - hasContent = ret || hasContent - } case reflect.Struct: ret := recursiveFlatten((valObj.Elem().Field(i).Addr().Interface())) diff --git a/internal/pkg/node/storage.go b/internal/pkg/node/storage.go index 5e1eb162..afc706d4 100644 --- a/internal/pkg/node/storage.go +++ b/internal/pkg/node/storage.go @@ -111,11 +111,13 @@ func (node *Node) GetIgnitionStorage() (stor types_3_4.Storage, rep string, err for _, opt := range fs.Options { fsOption = append(fsOption, types_3_4.FilesystemOption(opt)) } - wipe := fs.WipeFileSystem myFs := types_3_4.Filesystem{ - Device: fsdevice, - Path: &fs.Path, - WipeFilesystem: wipe.BoolPtr(), + Device: fsdevice, + Path: &fs.Path, + } + if fs.WipeFileSystemP != nil { + wipeFs := fs.WipeFileSystem() + myFs.WipeFilesystem = &wipeFs } if fs.Format != "" { myFs.Format = &fs.Format @@ -142,9 +144,6 @@ func (node *Node) GetIgnitionStorage() (stor types_3_4.Storage, rep string, err for diskDev, disk := range node.Disks { var partitions []types_3_4.Partition for partlabel, part := range disk.Partitions { - resize := part.Resize - shouldExist := part.ShouldExist - wipe := part.WipePartitionEntry label := partlabel var number int if part.Number != "" { @@ -154,16 +153,23 @@ func (node *Node) GetIgnitionStorage() (stor types_3_4.Storage, rep string, err } } myPart := types_3_4.Partition{ - Label: &label, - Number: number, - ShouldExist: shouldExist.BoolPtr(), - WipePartitionEntry: wipe.BoolPtr(), + Label: &label, + Number: number, + } + if part.ShouldExistP != nil { + shouldExist := part.ShouldExist() + myPart.ShouldExist = &shouldExist + } + if part.WipePartitionEntryP != nil { + wipeEntry := part.WipePartitionEntry() + myPart.WipePartitionEntry = &wipeEntry } if part.Guid != "" { myPart.GUID = &part.Guid } - if part.Resize.Bool() { - myPart.Resize = resize.BoolPtr() + if part.ResizeP != nil { + resize := part.Resize() + myPart.Resize = &resize } if part.SizeMiB != "" { var size int @@ -198,12 +204,15 @@ func (node *Node) GetIgnitionStorage() (stor types_3_4.Storage, rep string, err } return partitions[i].Number < partitions[j].Number }) - wipe := disk.WipeTable - disks = append(disks, types_3_4.Disk{ + disk_struct := types_3_4.Disk{ Device: diskDev, Partitions: partitions, - WipeTable: wipe.BoolPtr(), - }) + } + if disk.WipeTableP != nil { + wipe := disk.WipeTable() + disk_struct.WipeTable = &wipe + } + disks = append(disks, disk_struct) } stor = types_3_4.Storage{ Disks: disks, diff --git a/internal/pkg/overlay/funcmap_test.go b/internal/pkg/overlay/funcmap_test.go index fb108cf0..0253f164 100644 --- a/internal/pkg/overlay/funcmap_test.go +++ b/internal/pkg/overlay/funcmap_test.go @@ -33,8 +33,7 @@ func Test_createIgnitionJson(t *testing.T) { "partitions": [ { "label": "scratch", - "shouldExist": true, - "wipePartitionEntry": false + "shouldExist": true } ], "wipeTable": true diff --git a/internal/pkg/upgrade/node.go b/internal/pkg/upgrade/node.go index 2234c98a..eb2a0622 100644 --- a/internal/pkg/upgrade/node.go +++ b/internal/pkg/upgrade/node.go @@ -710,9 +710,10 @@ func (legacy *Disk) Upgrade() (upgraded *node.Disk) { upgraded.Partitions[name] = partition.Upgrade() } } - err := upgraded.WipeTable.Set(legacy.WipeTable) - if err != nil { - wwlog.Warn("error when parsing legacy.WipeTable: %w", err) + if legacy.WipeTable != "" { + if val, err := strconv.ParseBool(legacy.WipeTable); err == nil { + upgraded.WipeTableP = &val + } } return } @@ -732,20 +733,23 @@ func (legacy *Partition) Upgrade() (upgraded *node.Partition) { upgraded = new(node.Partition) upgraded.Guid = legacy.Guid upgraded.Number = legacy.Number - err := upgraded.Resize.Set(legacy.Resize) - if err != nil { - wwlog.Warn("error when parsing legacy.Resize: %w", err) + if legacy.Resize != "" { + if val, err := strconv.ParseBool(legacy.Resize); err == nil { + upgraded.ResizeP = &val + } } - err = upgraded.ShouldExist.Set(legacy.ShouldExist) - if err != nil { - wwlog.Warn("error when parsing legacy.ShouldExist: %w", err) + if legacy.ShouldExist != "" { + if val, err := strconv.ParseBool(legacy.ShouldExist); err == nil { + upgraded.ShouldExistP = &val + } } upgraded.SizeMiB = legacy.SizeMiB upgraded.StartMiB = legacy.StartMiB upgraded.TypeGuid = legacy.TypeGuid - err = upgraded.WipePartitionEntry.Set(legacy.WipePartitionEntry) - if err != nil { - wwlog.Warn("error when parsing legacy.WipePartitionEntry: %w", err) + if legacy.WipePartitionEntry != "" { + if val, err := strconv.ParseBool(legacy.WipePartitionEntry); err == nil { + upgraded.WipePartitionEntryP = &val + } } return } @@ -782,9 +786,10 @@ func (legacy *FileSystem) Upgrade() (upgraded *node.FileSystem) { upgraded.Options = append(upgraded.Options, legacy.Options...) upgraded.Path = legacy.Path upgraded.Uuid = legacy.Uuid - err := upgraded.WipeFileSystem.Set(legacy.WipeFileSystem) - if err != nil { - wwlog.Warn("error when parsing legacy.WipeFileSystem: %w", err) + if legacy.WipeFileSystem != "" { + if val, err := strconv.ParseBool(legacy.WipeFileSystem); err == nil { + upgraded.WipeFileSystemP = &val + } } return } diff --git a/internal/pkg/upgrade/node_test.go b/internal/pkg/upgrade/node_test.go index c0de8123..4ed513ba 100644 --- a/internal/pkg/upgrade/node_test.go +++ b/internal/pkg/upgrade/node_test.go @@ -589,11 +589,11 @@ nodes: n1: disks: /dev/vda: - wipe_table: "true" + wipe_table: true partitions: scratch: number: "1" - should_exist: "true" + should_exist: true swap: number: "2" size_mib: "1024" diff --git a/internal/pkg/util/util.go b/internal/pkg/util/util.go index 839ee9ff..de6945a2 100644 --- a/internal/pkg/util/util.go +++ b/internal/pkg/util/util.go @@ -617,3 +617,8 @@ func EqualYaml(a interface{}, b interface{}) (bool, error) { return bytes.Equal(aYaml, bYaml), nil } + +// BoolP returns the value of a bool pointer, or false if nil +func BoolP(p *bool) bool { + return p != nil && *p +} diff --git a/internal/pkg/util/util_test.go b/internal/pkg/util/util_test.go index 35d7dbad..dcc793ea 100644 --- a/internal/pkg/util/util_test.go +++ b/internal/pkg/util/util_test.go @@ -1,4 +1,4 @@ -package util +package util_test import ( "path/filepath" @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/warewulf/warewulf/internal/pkg/testenv" + "github.com/warewulf/warewulf/internal/pkg/util" ) func Test_FindFiles(t *testing.T) { @@ -36,7 +37,7 @@ func Test_FindFiles(t *testing.T) { env.CreateFile(filepath.Join("/test", file_)) } - files := FindFiles(env.GetPath("/test")) + files := util.FindFiles(env.GetPath("/test")) assert.Equal(t, tt.findFiles, files) }) } @@ -86,7 +87,7 @@ func Test_FindFilterFiles(t *testing.T) { env.CreateFile(filepath.Join("/test", file_)) } - files, err := FindFilterFiles(env.GetPath("/test"), tt.include, tt.exclude, true) + files, err := util.FindFilterFiles(env.GetPath("/test"), tt.include, tt.exclude, true) assert.NoError(t, err) assert.Equal(t, tt.findFiles, files) }) diff --git a/internal/pkg/wwtype/wwbool.go b/internal/pkg/wwtype/wwbool.go index 344c0c1f..c47efbb1 100644 --- a/internal/pkg/wwtype/wwbool.go +++ b/internal/pkg/wwtype/wwbool.go @@ -33,14 +33,6 @@ func (val WWbool) Bool() bool { return bval } -/* -Return a pointer to a bool -*/ -func (val WWbool) BoolPtr() *bool { - ret := val.Bool() - return &ret -} - func (val WWbool) BoolDefaultTrue() bool { str := strings.ToLower(string(val)) if isUnsetValue(str) { diff --git a/overlays/ignition/internal/ignition_test.go b/overlays/ignition/internal/ignition_test.go index 83c63d97..10633944 100644 --- a/overlays/ignition/internal/ignition_test.go +++ b/overlays/ignition/internal/ignition_test.go @@ -242,15 +242,12 @@ nodes: "partitions": [ { "label": "scratch", - "shouldExist": true, - "wipePartitionEntry": false + "shouldExist": true }, { "label": "swap", "number": 1, - "shouldExist": false, - "sizeMiB": 1024, - "wipePartitionEntry": false + "sizeMiB": 1024 } ], "wipeTable": true @@ -266,8 +263,7 @@ nodes: { "device": "/dev/disk/by-partlabel/swap", "format": "swap", - "path": "swap", - "wipeFilesystem": false + "path": "swap" } ] }