Support inserting defaults during config upgrade
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
@@ -29,21 +30,64 @@ type NodesYaml struct {
|
||||
Nodes map[string]*Node
|
||||
}
|
||||
|
||||
func (this *NodesYaml) Upgrade() (upgraded *node.NodesYaml) {
|
||||
func (this *NodesYaml) Upgrade(addDefaults bool) (upgraded *node.NodesYaml) {
|
||||
upgraded = new(node.NodesYaml)
|
||||
upgraded.NodeProfiles = make(map[string]*node.Profile)
|
||||
upgraded.Nodes = make(map[string]*node.Node)
|
||||
if this.WWInternal != "" {
|
||||
logIgnore("WW_INTERNAL", this.WWInternal, "obsolete")
|
||||
}
|
||||
if this.NodeProfiles != nil {
|
||||
for name, profile := range this.NodeProfiles {
|
||||
upgraded.NodeProfiles[name] = profile.Upgrade()
|
||||
for name, profile := range this.NodeProfiles {
|
||||
upgraded.NodeProfiles[name] = profile.Upgrade(addDefaults)
|
||||
}
|
||||
for name, node := range this.Nodes {
|
||||
upgraded.Nodes[name] = node.Upgrade(addDefaults)
|
||||
if addDefaults && !util.InSlice(upgraded.Nodes[name].Profiles, "default") {
|
||||
wwlog.Warn("node %s does not include the default profile: verify default settings manually", name)
|
||||
}
|
||||
}
|
||||
if this.Nodes != nil {
|
||||
for name, node := range this.Nodes {
|
||||
upgraded.Nodes[name] = node.Upgrade()
|
||||
if addDefaults {
|
||||
if _, ok := upgraded.NodeProfiles["default"]; !ok {
|
||||
upgraded.NodeProfiles["default"] = new(node.Profile)
|
||||
upgraded.NodeProfiles["default"].Kernel = new(node.KernelConf)
|
||||
}
|
||||
defaultProfile := upgraded.NodeProfiles["default"]
|
||||
if len(defaultProfile.SystemOverlay) == 0 {
|
||||
defaultProfile.SystemOverlay = append(
|
||||
defaultProfile.SystemOverlay,
|
||||
"wwinit",
|
||||
"wwclient",
|
||||
"fstab",
|
||||
"hostname",
|
||||
"ssh.host_keys",
|
||||
"issue",
|
||||
"resolv",
|
||||
"udev.netname",
|
||||
"systemd.netname",
|
||||
"ifcfg",
|
||||
"NetworkManager",
|
||||
"debian.interfaces",
|
||||
"wicked",
|
||||
"ignition")
|
||||
}
|
||||
if len(defaultProfile.RuntimeOverlay) == 0 {
|
||||
defaultProfile.RuntimeOverlay = append(
|
||||
defaultProfile.RuntimeOverlay,
|
||||
"hosts",
|
||||
"ssh.authorized_keys",
|
||||
"syncuser")
|
||||
}
|
||||
if defaultProfile.Kernel.Args == "" {
|
||||
defaultProfile.Kernel.Args = "quiet crashkernel=no vga=791 net.naming-scheme=v238"
|
||||
}
|
||||
if defaultProfile.Init == "" {
|
||||
defaultProfile.Init = "/sbin/init"
|
||||
}
|
||||
if defaultProfile.Root == "" {
|
||||
defaultProfile.Root = "initramfs"
|
||||
}
|
||||
if defaultProfile.Ipxe == "" {
|
||||
defaultProfile.Ipxe = "default"
|
||||
}
|
||||
}
|
||||
return upgraded
|
||||
@@ -53,7 +97,7 @@ type Node struct {
|
||||
Profile `yaml:"-,inline"`
|
||||
}
|
||||
|
||||
func (this *Node) Upgrade() (upgraded *node.Node) {
|
||||
func (this *Node) Upgrade(addDefaults bool) (upgraded *node.Node) {
|
||||
upgraded = new(node.Node)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Disks = make(map[string]*node.Disk)
|
||||
@@ -136,7 +180,7 @@ func (this *Node) Upgrade() (upgraded *node.Node) {
|
||||
}
|
||||
if this.NetDevs != nil {
|
||||
for name, netDev := range this.NetDevs {
|
||||
upgraded.NetDevs[name] = netDev.Upgrade()
|
||||
upgraded.NetDevs[name] = netDev.Upgrade(addDefaults)
|
||||
}
|
||||
}
|
||||
if this.PrimaryNetDev != "" {
|
||||
@@ -153,6 +197,11 @@ func (this *Node) Upgrade() (upgraded *node.Node) {
|
||||
}
|
||||
}
|
||||
upgraded.Profiles = append(upgraded.Profiles, this.Profiles...)
|
||||
if addDefaults {
|
||||
if len(upgraded.Profiles) == 0 {
|
||||
upgraded.Profiles = append(upgraded.Profiles, "default")
|
||||
}
|
||||
}
|
||||
upgraded.Root = this.Root
|
||||
if this.RuntimeOverlay != nil {
|
||||
switch overlay := this.RuntimeOverlay.(type) {
|
||||
@@ -225,7 +274,7 @@ type Profile struct {
|
||||
TagsDel []string `yaml:"tagsdel,omitempty"`
|
||||
}
|
||||
|
||||
func (this *Profile) Upgrade() (upgraded *node.Profile) {
|
||||
func (this *Profile) Upgrade(addDefaults bool) (upgraded *node.Profile) {
|
||||
upgraded = new(node.Profile)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Disks = make(map[string]*node.Disk)
|
||||
@@ -310,7 +359,7 @@ func (this *Profile) Upgrade() (upgraded *node.Profile) {
|
||||
}
|
||||
if this.NetDevs != nil {
|
||||
for name, netDev := range this.NetDevs {
|
||||
upgraded.NetDevs[name] = netDev.Upgrade()
|
||||
upgraded.NetDevs[name] = netDev.Upgrade(addDefaults)
|
||||
}
|
||||
}
|
||||
if this.PrimaryNetDev != "" {
|
||||
@@ -434,7 +483,7 @@ type NetDev struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (this *NetDev) Upgrade() (upgraded *node.NetDev) {
|
||||
func (this *NetDev) Upgrade(addDefaults bool) (upgraded *node.NetDev) {
|
||||
upgraded = new(node.NetDev)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Device = this.Device
|
||||
@@ -468,6 +517,14 @@ func (this *NetDev) Upgrade() (upgraded *node.NetDev) {
|
||||
delete(upgraded.Tags, tag)
|
||||
}
|
||||
upgraded.Type = this.Type
|
||||
if addDefaults {
|
||||
if upgraded.Type == "" {
|
||||
upgraded.Type = "ethernet"
|
||||
}
|
||||
if upgraded.Netmask == nil {
|
||||
upgraded.Netmask = net.ParseIP("255.255.255.0")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -527,17 +584,19 @@ func (this *FileSystem) Upgrade() (upgraded *node.FileSystem) {
|
||||
upgraded.Options = make([]string, 0)
|
||||
upgraded.Format = this.Format
|
||||
upgraded.Label = this.Label
|
||||
switch mountOptions := this.MountOptions.(type) {
|
||||
case string:
|
||||
upgraded.MountOptions = mountOptions
|
||||
case []interface{}:
|
||||
mountOptionsStrings := make([]string, 0)
|
||||
for _, option := range mountOptions {
|
||||
mountOptionsStrings = append(mountOptionsStrings, option.(string))
|
||||
if this.MountOptions != nil {
|
||||
switch mountOptions := this.MountOptions.(type) {
|
||||
case string:
|
||||
upgraded.MountOptions = mountOptions
|
||||
case []interface{}:
|
||||
mountOptionsStrings := make([]string, 0)
|
||||
for _, option := range mountOptions {
|
||||
mountOptionsStrings = append(mountOptionsStrings, option.(string))
|
||||
}
|
||||
upgraded.MountOptions = strings.Join(mountOptionsStrings, " ")
|
||||
default:
|
||||
wwlog.Error("unparsable MountOptions: %v", mountOptions)
|
||||
}
|
||||
upgraded.MountOptions = strings.Join(mountOptionsStrings, " ")
|
||||
default:
|
||||
wwlog.Error("unparsable MountOptions: %v", mountOptions)
|
||||
}
|
||||
upgraded.Options = append(upgraded.Options, this.Options...)
|
||||
upgraded.Path = this.Path
|
||||
|
||||
@@ -9,11 +9,13 @@ import (
|
||||
|
||||
var nodesYamlUpgradeTests = []struct {
|
||||
name string
|
||||
addDefaults bool
|
||||
legacyYaml string
|
||||
upgradedYaml string
|
||||
}{
|
||||
{
|
||||
name: "captured vers42 example",
|
||||
name: "captured vers42 example",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
@@ -67,7 +69,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "captured vers43 example",
|
||||
name: "captured vers43 example",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
WW_INTERNAL: 45
|
||||
nodeprofiles:
|
||||
@@ -132,15 +135,17 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "remove WW_INTERNAL",
|
||||
legacyYaml: `WW_INTERNAL: 45`,
|
||||
name: "remove WW_INTERNAL",
|
||||
addDefaults: false,
|
||||
legacyYaml: `WW_INTERNAL: 45`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles: {}
|
||||
nodes: {}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "disabled is obsolete",
|
||||
name: "disabled is obsolete",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
@@ -157,7 +162,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "inline IPMI settings",
|
||||
name: "inline IPMI settings",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
@@ -210,7 +216,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "inline Kernel settings",
|
||||
name: "inline Kernel settings",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
@@ -239,7 +246,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "keys and tags",
|
||||
name: "keys and tags",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
@@ -328,7 +336,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "primary network",
|
||||
name: "primary network",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
@@ -383,7 +392,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "overlays",
|
||||
name: "overlays",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
@@ -442,7 +452,8 @@ nodes:
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "disk example",
|
||||
name: "disk example",
|
||||
addDefaults: false,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
@@ -485,6 +496,116 @@ nodes:
|
||||
/dev/disk/by-partlabel/swap:
|
||||
format: swap
|
||||
path: swap
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add defaults",
|
||||
addDefaults: true,
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
network devices:
|
||||
default:
|
||||
ipaddr: 192.168.0.100
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
ipxe template: default
|
||||
runtime overlay:
|
||||
- hosts
|
||||
- ssh.authorized_keys
|
||||
- syncuser
|
||||
system overlay:
|
||||
- wwinit
|
||||
- wwclient
|
||||
- fstab
|
||||
- hostname
|
||||
- ssh.host_keys
|
||||
- issue
|
||||
- resolv
|
||||
- udev.netname
|
||||
- systemd.netname
|
||||
- ifcfg
|
||||
- NetworkManager
|
||||
- debian.interfaces
|
||||
- wicked
|
||||
- ignition
|
||||
kernel:
|
||||
args: quiet crashkernel=no vga=791 net.naming-scheme=v238
|
||||
init: /sbin/init
|
||||
root: initramfs
|
||||
nodes:
|
||||
n1:
|
||||
profiles:
|
||||
- default
|
||||
network devices:
|
||||
default:
|
||||
type: ethernet
|
||||
ipaddr: 192.168.0.100
|
||||
netmask: 255.255.255.0
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "add defaults conflicts",
|
||||
addDefaults: true,
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
system overlay:
|
||||
- wwinit
|
||||
- wwclient
|
||||
- fstab
|
||||
- hostname
|
||||
- ssh.host_keys
|
||||
- issue
|
||||
- resolv
|
||||
- udev.netname
|
||||
- systemd.netname
|
||||
- NetworkManager
|
||||
custom: {}
|
||||
nodes:
|
||||
n1:
|
||||
profiles:
|
||||
- custom
|
||||
network devices:
|
||||
default:
|
||||
ipaddr: 10.0.0.100
|
||||
netmask: 255.255.0.0
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
custom: {}
|
||||
default:
|
||||
ipxe template: default
|
||||
runtime overlay:
|
||||
- hosts
|
||||
- ssh.authorized_keys
|
||||
- syncuser
|
||||
system overlay:
|
||||
- wwinit
|
||||
- wwclient
|
||||
- fstab
|
||||
- hostname
|
||||
- ssh.host_keys
|
||||
- issue
|
||||
- resolv
|
||||
- udev.netname
|
||||
- systemd.netname
|
||||
- NetworkManager
|
||||
kernel:
|
||||
args: quiet crashkernel=no vga=791 net.naming-scheme=v238
|
||||
init: /sbin/init
|
||||
root: initramfs
|
||||
nodes:
|
||||
n1:
|
||||
profiles:
|
||||
- custom
|
||||
network devices:
|
||||
default:
|
||||
type: ethernet
|
||||
ipaddr: 10.0.0.100
|
||||
netmask: 255.255.0.0
|
||||
`,
|
||||
},
|
||||
}
|
||||
@@ -494,7 +615,7 @@ func Test_UpgradeNodesYaml(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
legacy, err := Parse([]byte(tt.legacyYaml))
|
||||
assert.NoError(t, err)
|
||||
upgraded := legacy.Upgrade()
|
||||
upgraded := legacy.Upgrade(tt.addDefaults)
|
||||
upgradedYaml, err := upgraded.Dump()
|
||||
assert.Equal(t, strings.TrimSpace(tt.upgradedYaml), strings.TrimSpace(string(upgradedYaml)))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user