Support upgrading warewulf.conf
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
@@ -26,23 +26,23 @@ const Release = "@RELEASE@"
|
||||
|
||||
type TFTPConf struct {
|
||||
Enabled bool `yaml:"enabled" default:"true"`
|
||||
TftpRoot string `yaml:"tftproot" default:"@TFTPDIR@"`
|
||||
SystemdName string `yaml:"systemd name" default:"tftp"`
|
||||
TftpRoot string `yaml:"tftproot,omitempty" default:"@TFTPDIR@"`
|
||||
SystemdName string `yaml:"systemd name,omitempty" default:"tftp"`
|
||||
|
||||
IpxeBinaries map[string]string `yaml:"ipxe" default:"{\"00:09\": \"ipxe-snponly-x86_64.efi\",\"00:00\": \"undionly.kpxe\",\"00:0B\": \"arm64-efi/snponly.efi\",\"00:07\": \"ipxe-snponly-x86_64.efi\"}"`
|
||||
IpxeBinaries map[string]string `yaml:"ipxe,omitempty" default:"{\"00:09\": \"ipxe-snponly-x86_64.efi\",\"00:00\": \"undionly.kpxe\",\"00:0B\": \"arm64-efi/snponly.efi\",\"00:07\": \"ipxe-snponly-x86_64.efi\"}"`
|
||||
}
|
||||
|
||||
// WarewulfConf adds additional Warewulf-specific configuration to
|
||||
// BaseConf.
|
||||
type WarewulfConf struct {
|
||||
Port int `yaml:"port" default:"9873"`
|
||||
Port int `yaml:"port,omitempty" default:"9873"`
|
||||
Secure bool `yaml:"secure" default:"true"`
|
||||
UpdateInterval int `yaml:"update interval" default:"60"`
|
||||
AutobuildOverlays bool `yaml:"autobuild overlays" default:"true"`
|
||||
UpdateInterval int `yaml:"update interval,omitempty" default:"60"`
|
||||
AutobuildOverlays bool `yaml:"autobuild overlays,omitempty" default:"true"`
|
||||
EnableHostOverlay bool `yaml:"host overlay" default:"true"`
|
||||
Syslog bool `yaml:"syslog" default:"false"`
|
||||
DataStore string `yaml:"datastore" default:"@DATADIR@"`
|
||||
GrubBoot bool `yaml:"grubboot" default:"false"`
|
||||
Syslog bool `yaml:"syslog,omitempty" default:"false"`
|
||||
DataStore string `yaml:"datastore,omitempty" default:"@DATADIR@"`
|
||||
GrubBoot bool `yaml:"grubboot,omitempty" default:"false"`
|
||||
}
|
||||
|
||||
func (paths BuildConfig) OciBlobCachedir() string {
|
||||
|
||||
@@ -4,8 +4,8 @@ package config
|
||||
// Warewulf will configure.
|
||||
type DHCPConf struct {
|
||||
Enabled bool `yaml:"enabled" default:"true"`
|
||||
Template string `yaml:"template" default:"default"`
|
||||
Template string `yaml:"template,omitempty" default:"default"`
|
||||
RangeStart string `yaml:"range start,omitempty"`
|
||||
RangeEnd string `yaml:"range end,omitempty"`
|
||||
SystemdName string `yaml:"systemd name" default:"dhcpd"`
|
||||
SystemdName string `yaml:"systemd name,omitempty" default:"dhcpd"`
|
||||
}
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
// nodes.
|
||||
type NFSConf struct {
|
||||
Enabled bool `yaml:"enabled" default:"true"`
|
||||
ExportsExtended []*NFSExportConf `yaml:"export paths" default:"[]"`
|
||||
SystemdName string `yaml:"systemd name" default:"nfsd"`
|
||||
ExportsExtended []*NFSExportConf `yaml:"export paths,omitempty" default:"[]"`
|
||||
SystemdName string `yaml:"systemd name,omitempty" default:"nfsd"`
|
||||
}
|
||||
|
||||
// An NFSExportConf reprents a single NFS export / mount.
|
||||
type NFSExportConf struct {
|
||||
Path string `yaml:"path" default:"/dev/null"`
|
||||
ExportOptions string `default:"rw,sync,no_subtree_check" yaml:"export options"`
|
||||
MountOptions string `default:"defaults" yaml:"mount options"`
|
||||
Mount bool `default:"true" yaml:"mount"`
|
||||
ExportOptions string `yaml:"export options,omitempty" default:"rw,sync,no_subtree_check"`
|
||||
MountOptions string `yaml:"mount options,omitempty" default:"defaults"`
|
||||
Mount bool `yaml:"mount" default:"true"`
|
||||
}
|
||||
|
||||
// Implements the Unmarshal interface for NFSConf to set default
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -27,19 +28,19 @@ var cachedConf WarewulfYaml
|
||||
// [WarewulfConf], [DHCPConf], [TFTPConf], and [NFSConf] sub-sections.
|
||||
type WarewulfYaml struct {
|
||||
Comment string `yaml:"comment,omitempty"`
|
||||
Ipaddr string `yaml:"ipaddr"`
|
||||
Ipaddr string `yaml:"ipaddr,omitempty"`
|
||||
Ipaddr6 string `yaml:"ipaddr6,omitempty"`
|
||||
Netmask string `yaml:"netmask"`
|
||||
Netmask string `yaml:"netmask,omitempty"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
Ipv6net string `yaml:"ipv6net,omitempty"`
|
||||
Fqdn string `yaml:"fqdn,omitempty"`
|
||||
Warewulf *WarewulfConf `yaml:"warewulf"`
|
||||
DHCP *DHCPConf `yaml:"dhcp"`
|
||||
TFTP *TFTPConf `yaml:"tftp"`
|
||||
NFS *NFSConf `yaml:"nfs"`
|
||||
Warewulf *WarewulfConf `yaml:"warewulf,omitempty"`
|
||||
DHCP *DHCPConf `yaml:"dhcp,omitempty"`
|
||||
TFTP *TFTPConf `yaml:"tftp,omitempty"`
|
||||
NFS *NFSConf `yaml:"nfs,omitempty"`
|
||||
SSH *SSHConf `yaml:"ssh,omitempty"`
|
||||
MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"`
|
||||
Paths *BuildConfig `yaml:"paths"`
|
||||
MountsContainer []*MountEntry `yaml:"container mounts,omitempty" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"`
|
||||
Paths *BuildConfig `yaml:"paths,omitempty"`
|
||||
WWClient *WWClientConf `yaml:"wwclient,omitempty"`
|
||||
|
||||
warewulfconf string
|
||||
@@ -206,3 +207,31 @@ func (conf *WarewulfYaml) InitializedFromFile() bool {
|
||||
func (conf *WarewulfYaml) GetWarewulfConf() string {
|
||||
return conf.warewulfconf
|
||||
}
|
||||
|
||||
func (config *WarewulfYaml) Dump() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
yamlEncoder := yaml.NewEncoder(&buf)
|
||||
yamlEncoder.SetIndent(2)
|
||||
err := yamlEncoder.Encode(config)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func (config *WarewulfYaml) PersistToFile(configFile string) error {
|
||||
out, dumpErr := config.Dump()
|
||||
if dumpErr != nil {
|
||||
wwlog.Error("%s", dumpErr)
|
||||
return dumpErr
|
||||
}
|
||||
file, err := os.OpenFile(configFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o644)
|
||||
if err != nil {
|
||||
wwlog.Error("%s", err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = file.WriteString(string(out))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wwlog.Debug("persisted: %s", configFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package config
|
||||
|
||||
type SSHConf struct {
|
||||
KeyTypes []string `yaml:"key types" default:"[\"rsa\",\"dsa\",\"ecdsa\",\"ed25519\"]"`
|
||||
KeyTypes []string `yaml:"key types,omitempty" default:"[\"rsa\",\"dsa\",\"ecdsa\",\"ed25519\"]"`
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package config
|
||||
|
||||
type WWClientConf struct {
|
||||
Port uint16 `yaml:"port" default:"0"`
|
||||
Port uint16 `yaml:"port,omitempty" default:"0"`
|
||||
}
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
package upgrade
|
||||
|
||||
type WarewulfYaml struct {
|
||||
WWInternal string `yaml:"WW_INTERNAL"`
|
||||
Comment string `yaml:"comment,omitempty"`
|
||||
Ipaddr string `yaml:"ipaddr"`
|
||||
Ipaddr6 string `yaml:"ipaddr6,omitempty"`
|
||||
Netmask string `yaml:"netmask"`
|
||||
Network string `yaml:"network,omitempty"`
|
||||
Ipv6net string `yaml:"ipv6net,omitempty"`
|
||||
Fqdn string `yaml:"fqdn,omitempty"`
|
||||
Warewulf *WarewulfConf `yaml:"warewulf"`
|
||||
DHCP *DHCPConf `yaml:"dhcp"`
|
||||
TFTP *TFTPConf `yaml:"tftp"`
|
||||
NFS *NFSConf `yaml:"nfs"`
|
||||
SSH *SSHConf `yaml:"ssh,omitempty"`
|
||||
MountsContainer []*MountEntry `yaml:"container mounts"`
|
||||
Paths *BuildConfig `yaml:"paths"`
|
||||
WWClient *WWClientConf `yaml:"wwclient"`
|
||||
}
|
||||
|
||||
type WarewulfConf struct {
|
||||
Port int `yaml:"port"`
|
||||
Secure bool `yaml:"secure"`
|
||||
UpdateInterval int `yaml:"update interval"`
|
||||
AutobuildOverlays bool `yaml:"autobuild overlays"`
|
||||
EnableHostOverlay bool `yaml:"host overlay"`
|
||||
Syslog bool `yaml:"syslog"`
|
||||
DataStore string `yaml:"datastore"`
|
||||
GrubBoot bool `yaml:"grubboot"`
|
||||
}
|
||||
|
||||
type DHCPConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Template string `yaml:"template"`
|
||||
RangeStart string `yaml:"range start,omitempty"`
|
||||
RangeEnd string `yaml:"range end,omitempty"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
}
|
||||
|
||||
type TFTPConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
TftpRoot string `yaml:"tftproot"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
|
||||
IpxeBinaries map[string]string `yaml:"ipxe"`
|
||||
}
|
||||
|
||||
type NFSConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ExportsExtended []*NFSExportConf `yaml:"export paths"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
}
|
||||
|
||||
type NFSExportConf struct {
|
||||
Path string `yaml:"path"`
|
||||
ExportOptions string `yaml:"export options"`
|
||||
MountOptions string `yaml:"mount options"`
|
||||
Mount bool `yaml:"mount"`
|
||||
}
|
||||
|
||||
type SSHConf struct {
|
||||
KeyTypes []string `yaml:"key types"`
|
||||
}
|
||||
|
||||
type MountEntry struct {
|
||||
Source string `yaml:"source"`
|
||||
Dest string `yaml:"dest,omitempty"`
|
||||
ReadOnly bool `yaml:"readonly,omitempty"`
|
||||
Options string `yaml:"options,omitempty"`
|
||||
Copy bool `yaml:"copy,omitempty"`
|
||||
}
|
||||
|
||||
type BuildConfig struct {
|
||||
Bindir string
|
||||
Sysconfdir string
|
||||
Localstatedir string
|
||||
Cachedir string
|
||||
Ipxesource string
|
||||
Srvdir string
|
||||
Firewallddir string
|
||||
Systemddir string
|
||||
WWOverlaydir string
|
||||
WWChrootdir string
|
||||
WWProvisiondir string
|
||||
WWClientdir string
|
||||
}
|
||||
|
||||
type WWClientConf struct {
|
||||
Port uint16 `yaml:"port"`
|
||||
}
|
||||
237
internal/pkg/upgrade/config.go
Normal file
237
internal/pkg/upgrade/config.go
Normal file
@@ -0,0 +1,237 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/config"
|
||||
)
|
||||
|
||||
func ParseConfig(data []byte) (warewulfYaml *WarewulfYaml, err error) {
|
||||
warewulfYaml = new(WarewulfYaml)
|
||||
if err = yaml.Unmarshal(data, warewulfYaml); err != nil {
|
||||
return warewulfYaml, err
|
||||
}
|
||||
return warewulfYaml, nil
|
||||
}
|
||||
|
||||
type WarewulfYaml struct {
|
||||
WWInternal string `yaml:"WW_INTERNAL"`
|
||||
Comment string `yaml:"comment"`
|
||||
Ipaddr string `yaml:"ipaddr"`
|
||||
Ipaddr6 string `yaml:"ipaddr6"`
|
||||
Netmask string `yaml:"netmask"`
|
||||
Network string `yaml:"network"`
|
||||
Ipv6net string `yaml:"ipv6net"`
|
||||
Fqdn string `yaml:"fqdn"`
|
||||
Warewulf *WarewulfConf `yaml:"warewulf"`
|
||||
DHCP *DHCPConf `yaml:"dhcp"`
|
||||
TFTP *TFTPConf `yaml:"tftp"`
|
||||
NFS *NFSConf `yaml:"nfs"`
|
||||
SSH *SSHConf `yaml:"ssh"`
|
||||
MountsContainer []*MountEntry `yaml:"container mounts"`
|
||||
Paths *BuildConfig `yaml:"paths"`
|
||||
WWClient *WWClientConf `yaml:"wwclient"`
|
||||
}
|
||||
|
||||
func (this *WarewulfYaml) Upgrade() (upgraded *config.WarewulfYaml) {
|
||||
upgraded = new(config.WarewulfYaml)
|
||||
if this.WWInternal != "" {
|
||||
logIgnore("WW_INTERNAL", this.WWInternal, "obsolete")
|
||||
}
|
||||
upgraded.Comment = this.Comment
|
||||
upgraded.Ipaddr = this.Ipaddr
|
||||
upgraded.Ipaddr6 = this.Ipaddr6
|
||||
upgraded.Netmask = this.Netmask
|
||||
upgraded.Network = this.Network
|
||||
upgraded.Ipv6net = this.Ipv6net
|
||||
upgraded.Fqdn = this.Fqdn
|
||||
if this.Warewulf != nil {
|
||||
upgraded.Warewulf = this.Warewulf.Upgrade()
|
||||
}
|
||||
if this.DHCP != nil {
|
||||
upgraded.DHCP = this.DHCP.Upgrade()
|
||||
}
|
||||
if this.TFTP != nil {
|
||||
upgraded.TFTP = this.TFTP.Upgrade()
|
||||
}
|
||||
if this.NFS != nil {
|
||||
upgraded.NFS = this.NFS.Upgrade()
|
||||
}
|
||||
if this.SSH != nil {
|
||||
upgraded.SSH = this.SSH.Upgrade()
|
||||
}
|
||||
upgraded.MountsContainer = make([]*config.MountEntry, 0)
|
||||
for _, mount := range this.MountsContainer {
|
||||
upgraded.MountsContainer = append(upgraded.MountsContainer, mount.Upgrade())
|
||||
}
|
||||
if this.Paths != nil {
|
||||
upgraded.Paths = this.Paths.Upgrade()
|
||||
}
|
||||
if this.WWClient != nil {
|
||||
upgraded.WWClient = this.WWClient.Upgrade()
|
||||
}
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type WarewulfConf struct {
|
||||
Port int `yaml:"port"`
|
||||
Secure bool `yaml:"secure"`
|
||||
UpdateInterval int `yaml:"update interval"`
|
||||
AutobuildOverlays bool `yaml:"autobuild overlays"`
|
||||
EnableHostOverlay bool `yaml:"host overlay"`
|
||||
Syslog bool `yaml:"syslog"`
|
||||
DataStore string `yaml:"datastore"`
|
||||
GrubBoot bool `yaml:"grubboot"`
|
||||
}
|
||||
|
||||
func (this *WarewulfConf) Upgrade() (upgraded *config.WarewulfConf) {
|
||||
upgraded = new(config.WarewulfConf)
|
||||
upgraded.Port = this.Port
|
||||
upgraded.Secure = this.Secure
|
||||
upgraded.UpdateInterval = this.UpdateInterval
|
||||
upgraded.AutobuildOverlays = this.AutobuildOverlays
|
||||
upgraded.EnableHostOverlay = this.EnableHostOverlay
|
||||
upgraded.Syslog = this.Syslog
|
||||
upgraded.DataStore = this.DataStore
|
||||
upgraded.GrubBoot = this.GrubBoot
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type DHCPConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Template string `yaml:"template"`
|
||||
RangeStart string `yaml:"range start"`
|
||||
RangeEnd string `yaml:"range end"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
}
|
||||
|
||||
func (this *DHCPConf) Upgrade() (upgraded *config.DHCPConf) {
|
||||
upgraded = new(config.DHCPConf)
|
||||
upgraded.Enabled = this.Enabled
|
||||
upgraded.Template = this.Template
|
||||
upgraded.RangeStart = this.RangeStart
|
||||
upgraded.RangeEnd = this.RangeEnd
|
||||
upgraded.SystemdName = this.SystemdName
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type TFTPConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
TftpRoot string `yaml:"tftproot"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
IpxeBinaries map[string]string `yaml:"ipxe"`
|
||||
}
|
||||
|
||||
func (this *TFTPConf) Upgrade() (upgraded *config.TFTPConf) {
|
||||
upgraded = new(config.TFTPConf)
|
||||
upgraded.Enabled = this.Enabled
|
||||
upgraded.TftpRoot = this.TftpRoot
|
||||
upgraded.SystemdName = this.SystemdName
|
||||
upgraded.IpxeBinaries = make(map[string]string)
|
||||
for name, binary := range this.IpxeBinaries {
|
||||
upgraded.IpxeBinaries[name] = binary
|
||||
}
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type NFSConf struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
ExportsExtended []*NFSExportConf `yaml:"export paths"`
|
||||
SystemdName string `yaml:"systemd name"`
|
||||
}
|
||||
|
||||
func (this *NFSConf) Upgrade() (upgraded *config.NFSConf) {
|
||||
upgraded = new(config.NFSConf)
|
||||
upgraded.Enabled = this.Enabled
|
||||
upgraded.ExportsExtended = make([]*config.NFSExportConf, 0)
|
||||
for _, export := range this.ExportsExtended {
|
||||
upgraded.ExportsExtended = append(upgraded.ExportsExtended, export.Upgrade())
|
||||
}
|
||||
upgraded.SystemdName = this.SystemdName
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type NFSExportConf struct {
|
||||
Path string `yaml:"path"`
|
||||
ExportOptions string `yaml:"export options"`
|
||||
MountOptions string `yaml:"mount options"`
|
||||
Mount bool `yaml:"mount"`
|
||||
}
|
||||
|
||||
func (this *NFSExportConf) Upgrade() (upgraded *config.NFSExportConf) {
|
||||
upgraded = new(config.NFSExportConf)
|
||||
upgraded.Path = this.Path
|
||||
upgraded.ExportOptions = this.ExportOptions
|
||||
upgraded.MountOptions = this.MountOptions
|
||||
upgraded.Mount = this.Mount
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type SSHConf struct {
|
||||
KeyTypes []string `yaml:"key types"`
|
||||
}
|
||||
|
||||
func (this *SSHConf) Upgrade() (upgraded *config.SSHConf) {
|
||||
upgraded = new(config.SSHConf)
|
||||
upgraded.KeyTypes = append([]string{}, this.KeyTypes...)
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type MountEntry struct {
|
||||
Source string `yaml:"source"`
|
||||
Dest string `yaml:"dest"`
|
||||
ReadOnly bool `yaml:"readonly"`
|
||||
Options string `yaml:"options"`
|
||||
Copy bool `yaml:"copy"`
|
||||
}
|
||||
|
||||
func (this *MountEntry) Upgrade() (upgraded *config.MountEntry) {
|
||||
upgraded = new(config.MountEntry)
|
||||
upgraded.Source = this.Source
|
||||
upgraded.Dest = this.Dest
|
||||
upgraded.ReadOnly = this.ReadOnly
|
||||
upgraded.Options = this.Options
|
||||
upgraded.Copy = this.Copy
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type BuildConfig struct {
|
||||
Bindir string
|
||||
Sysconfdir string
|
||||
Localstatedir string
|
||||
Cachedir string
|
||||
Ipxesource string
|
||||
Srvdir string
|
||||
Firewallddir string
|
||||
Systemddir string
|
||||
WWOverlaydir string
|
||||
WWChrootdir string
|
||||
WWProvisiondir string
|
||||
WWClientdir string
|
||||
}
|
||||
|
||||
func (this *BuildConfig) Upgrade() (upgraded *config.BuildConfig) {
|
||||
upgraded = new(config.BuildConfig)
|
||||
upgraded.Bindir = this.Bindir
|
||||
upgraded.Sysconfdir = this.Sysconfdir
|
||||
upgraded.Localstatedir = this.Localstatedir
|
||||
upgraded.Cachedir = this.Cachedir
|
||||
upgraded.Ipxesource = this.Ipxesource
|
||||
upgraded.Srvdir = this.Srvdir
|
||||
upgraded.Firewallddir = this.Firewallddir
|
||||
upgraded.WWOverlaydir = this.WWOverlaydir
|
||||
upgraded.WWChrootdir = this.WWChrootdir
|
||||
upgraded.WWProvisiondir = this.WWProvisiondir
|
||||
upgraded.WWClientdir = this.WWClientdir
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type WWClientConf struct {
|
||||
Port uint16 `yaml:"port"`
|
||||
}
|
||||
|
||||
func (this *WWClientConf) Upgrade() (upgraded *config.WWClientConf) {
|
||||
upgraded = new(config.WWClientConf)
|
||||
upgraded.Port = this.Port
|
||||
return upgraded
|
||||
}
|
||||
415
internal/pkg/upgrade/config_test.go
Normal file
415
internal/pkg/upgrade/config_test.go
Normal file
@@ -0,0 +1,415 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var configUpgradeTests = []struct {
|
||||
name string
|
||||
legacyYaml string
|
||||
upgradedYaml string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
legacyYaml: ``,
|
||||
upgradedYaml: `{}`,
|
||||
},
|
||||
{
|
||||
name: "v4.0.0",
|
||||
legacyYaml: `
|
||||
ipaddr: 192.168.1.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
update interval: 60
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 192.168.1.150
|
||||
range end: 192.168.1.200
|
||||
template: default
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
systemd name: nfs-server
|
||||
exports:
|
||||
- /home
|
||||
- /var/warewulf
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 192.168.1.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
update interval: 60
|
||||
host overlay: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 192.168.1.150
|
||||
range end: 192.168.1.200
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "v4.1.0",
|
||||
legacyYaml: `
|
||||
ipaddr: 192.168.1.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
update interval: 60
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 192.168.1.150
|
||||
range end: 192.168.1.200
|
||||
template: default
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
systemd name: nfs-server
|
||||
exports:
|
||||
- /home
|
||||
- /var/warewulf
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 192.168.1.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
update interval: 60
|
||||
host overlay: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 192.168.1.150
|
||||
range end: 192.168.1.200
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "v4.2.0",
|
||||
legacyYaml: `
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
autobuild overlays: true
|
||||
update interval: 60
|
||||
syslog: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
template: default
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
systemd name: nfs-server
|
||||
exports:
|
||||
- /home
|
||||
- /var/warewulf
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: true
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: /var/lib/tftpboot
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "v4.3.0",
|
||||
legacyYaml: `
|
||||
WW_INTERNAL: 43
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
network: 192.168.200.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
syslog: false
|
||||
datastore: ""
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
tftproot: ""
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
network: 192.168.200.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
dhcp:
|
||||
enabled: true
|
||||
template: default
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "v4.4.1",
|
||||
legacyYaml: `
|
||||
WW_INTERNAL: 43
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
network: 192.168.200.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
syslog: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 192.168.200.1
|
||||
netmask: 255.255.255.0
|
||||
network: 192.168.200.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 192.168.200.50
|
||||
range end: 192.168.200.99
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
systemd name: tftp
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "v4.5.8",
|
||||
legacyYaml: `
|
||||
WW_INTERNAL: 45
|
||||
ipaddr: 10.0.0.1
|
||||
netmask: 255.255.252.0
|
||||
network: 10.0.0.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
syslog: false
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 10.0.1.1
|
||||
range end: 10.0.1.255
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
systemd name: tftp
|
||||
ipxe:
|
||||
00:09: ipxe-snponly-x86_64.efi
|
||||
00:00: undionly.kpxe
|
||||
00:0B: arm64-efi/snponly.efi
|
||||
00:07: ipxe-snponly-x86_64.efi
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
container mounts:
|
||||
- source: /etc/resolv.conf
|
||||
dest: /etc/resolv.conf
|
||||
readonly: true
|
||||
ssh:
|
||||
key types:
|
||||
- rsa
|
||||
- dsa
|
||||
- ecdsa
|
||||
- ed25519
|
||||
`,
|
||||
upgradedYaml: `
|
||||
ipaddr: 10.0.0.1
|
||||
netmask: 255.255.252.0
|
||||
network: 10.0.0.0
|
||||
warewulf:
|
||||
port: 9873
|
||||
secure: false
|
||||
update interval: 60
|
||||
autobuild overlays: true
|
||||
host overlay: true
|
||||
dhcp:
|
||||
enabled: true
|
||||
range start: 10.0.1.1
|
||||
range end: 10.0.1.255
|
||||
systemd name: dhcpd
|
||||
tftp:
|
||||
enabled: true
|
||||
systemd name: tftp
|
||||
ipxe:
|
||||
00:0B: arm64-efi/snponly.efi
|
||||
"00:00": undionly.kpxe
|
||||
"00:07": ipxe-snponly-x86_64.efi
|
||||
"00:09": ipxe-snponly-x86_64.efi
|
||||
nfs:
|
||||
enabled: true
|
||||
export paths:
|
||||
- path: /home
|
||||
export options: rw,sync
|
||||
mount options: defaults
|
||||
mount: true
|
||||
- path: /opt
|
||||
export options: ro,sync,no_root_squash
|
||||
mount options: defaults
|
||||
mount: false
|
||||
systemd name: nfs-server
|
||||
ssh:
|
||||
key types:
|
||||
- rsa
|
||||
- dsa
|
||||
- ecdsa
|
||||
- ed25519
|
||||
container mounts:
|
||||
- source: /etc/resolv.conf
|
||||
dest: /etc/resolv.conf
|
||||
readonly: true
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
func Test_UpgradeConfig(t *testing.T) {
|
||||
for _, tt := range configUpgradeTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
legacy, err := ParseConfig([]byte(tt.legacyYaml))
|
||||
assert.NoError(t, err)
|
||||
upgraded := legacy.Upgrade()
|
||||
upgradedYaml, err := upgraded.Dump()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(tt.upgradedYaml), strings.TrimSpace(string(upgradedYaml)))
|
||||
})
|
||||
}
|
||||
}
|
||||
15
internal/pkg/upgrade/logging.go
Normal file
15
internal/pkg/upgrade/logging.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func logIgnore(name string, value interface{}, reason string) {
|
||||
wwlog.Warn("ignore: %s: %v (%s)", name, value, reason)
|
||||
}
|
||||
|
||||
func warnError(err error) {
|
||||
if err != nil {
|
||||
wwlog.Warn("%s", err)
|
||||
}
|
||||
}
|
||||
@@ -35,33 +35,7 @@ var genericSplitOverlays = []string{
|
||||
"syncuser",
|
||||
}
|
||||
|
||||
func indexOf[T comparable](slice []T, item T) int {
|
||||
for i, v := range slice {
|
||||
if v == item {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func replaceSliceElement[T any](original []T, index int, replacement []T) []T {
|
||||
if index < 0 || index >= len(original) {
|
||||
return original
|
||||
}
|
||||
return append(original[:index], append(replacement, original[index+1:]...)...)
|
||||
}
|
||||
|
||||
func logIgnore(name string, value interface{}, reason string) {
|
||||
wwlog.Warn("ignore: %s: %v (%s)", name, value, reason)
|
||||
}
|
||||
|
||||
func warnError(err error) {
|
||||
if err != nil {
|
||||
wwlog.Warn("%s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Parse(data []byte) (nodesYaml *NodesYaml, err error) {
|
||||
func ParseNodes(data []byte) (nodesYaml *NodesYaml, err error) {
|
||||
nodesYaml = new(NodesYaml)
|
||||
if err = yaml.Unmarshal(data, nodesYaml); err != nil {
|
||||
return nodesYaml, err
|
||||
|
||||
@@ -689,7 +689,7 @@ nodes:
|
||||
func Test_UpgradeNodesYaml(t *testing.T) {
|
||||
for _, tt := range nodesYamlUpgradeTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
legacy, err := Parse([]byte(tt.legacyYaml))
|
||||
legacy, err := ParseNodes([]byte(tt.legacyYaml))
|
||||
assert.NoError(t, err)
|
||||
upgraded := legacy.Upgrade(tt.addDefaults, tt.replaceOverlays)
|
||||
upgradedYaml, err := upgraded.Dump()
|
||||
|
||||
17
internal/pkg/upgrade/slices.go
Normal file
17
internal/pkg/upgrade/slices.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package upgrade
|
||||
|
||||
func indexOf[T comparable](slice []T, item T) int {
|
||||
for i, v := range slice {
|
||||
if v == item {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func replaceSliceElement[T any](original []T, index int, replacement []T) []T {
|
||||
if index < 0 || index >= len(original) {
|
||||
return original
|
||||
}
|
||||
return append(original[:index], append(replacement, original[index+1:]...)...)
|
||||
}
|
||||
Reference in New Issue
Block a user