Node upgrade tests
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
@@ -1,182 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
|
||||
"github.com/warewulf/warewulf/cmd/update_configuration/vers42"
|
||||
"github.com/warewulf/warewulf/cmd/update_configuration/vers43"
|
||||
"github.com/warewulf/warewulf/internal/pkg/util"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var nowrite bool
|
||||
var quiet bool
|
||||
var confFile string
|
||||
|
||||
const actvers int = 43
|
||||
|
||||
type nodeVersionOnly struct {
|
||||
WWInternal int `yaml:"WW_INTERNAL"`
|
||||
}
|
||||
|
||||
func saveConf(conf interface{}) {
|
||||
out, err := yaml.Marshal(conf)
|
||||
if err != nil {
|
||||
myprintf("Error in marshal of conf: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if nowrite {
|
||||
fmt.Print(string(out))
|
||||
} else {
|
||||
err = util.CopyFile(confFile, confFile+".bak")
|
||||
if err != nil {
|
||||
myprintf("Could write file: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
info, err := os.Stat(confFile)
|
||||
if err != nil {
|
||||
myprintf("Could not get file mode: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
myprintf("writing configuration file %s as type %s\n", confFile, reflect.TypeOf(conf))
|
||||
err = os.WriteFile(confFile, out, info.Mode())
|
||||
if err != nil {
|
||||
myprintf("Could not write file: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printB(x bool) string {
|
||||
if x {
|
||||
return "true"
|
||||
}
|
||||
return "false"
|
||||
}
|
||||
|
||||
func update42to43(conf42 vers42.NodeConf) vers43.NodeConf {
|
||||
ret := vers43.NodeConf{
|
||||
Comment: conf42.Comment,
|
||||
ClusterName: conf42.ClusterName,
|
||||
ContainerName: conf42.ContainerName,
|
||||
Init: conf42.Init,
|
||||
Root: conf42.Root,
|
||||
Discoverable: printB(conf42.Discoverable),
|
||||
Profiles: conf42.Profiles,
|
||||
Ipxe: conf42.Ipxe}
|
||||
if conf42.RuntimeOverlay != "" {
|
||||
ret.RuntimeOverlay = []string{conf42.RuntimeOverlay}
|
||||
}
|
||||
if conf42.SystemOverlay != "" {
|
||||
ret.SystemOverlay = []string{conf42.SystemOverlay}
|
||||
}
|
||||
if conf42.KernelArgs != "" || conf42.KernelVersion != "" {
|
||||
ret.Kernel = new(vers43.KernelConf)
|
||||
ret.Kernel.Override = conf42.KernelVersion
|
||||
ret.Kernel.Args = conf42.KernelArgs
|
||||
|
||||
}
|
||||
if conf42.IpmiUserName != "" || conf42.IpmiPassword != "" || conf42.IpmiIpaddr != "" ||
|
||||
conf42.IpmiNetmask != "" || conf42.IpmiPort != "" || conf42.IpmiGateway != "" ||
|
||||
conf42.IpmiInterface != "" {
|
||||
ret.Ipmi = new(vers43.IpmiConf)
|
||||
ret.Ipmi.UserName = conf42.IpmiUserName
|
||||
ret.Ipmi.Password = conf42.IpmiPassword
|
||||
ret.Ipmi.Ipaddr = conf42.IpmiIpaddr
|
||||
ret.Ipmi.Netmask = conf42.IpmiNetmask
|
||||
ret.Ipmi.Port = conf42.IpmiPort
|
||||
ret.Ipmi.Gateway = conf42.IpmiGateway
|
||||
ret.Ipmi.Interface = conf42.IpmiInterface
|
||||
}
|
||||
if len(conf42.Keys) != 0 {
|
||||
ret.Keys = map[string]string{}
|
||||
for k, v := range conf42.Keys {
|
||||
ret.Keys[k] = v
|
||||
}
|
||||
}
|
||||
ret.NetDevs = make(map[string]*vers43.NetDevs)
|
||||
for devn, netdev := range conf42.NetDevs {
|
||||
var device vers43.NetDevs = vers43.NetDevs{
|
||||
Type: netdev.Type,
|
||||
Device: devn,
|
||||
Primary: printB(netdev.Default),
|
||||
Hwaddr: netdev.Hwaddr,
|
||||
Ipaddr: netdev.Ipaddr,
|
||||
IpCIDR: netdev.IpCIDR,
|
||||
Prefix: netdev.Prefix,
|
||||
Netmask: netdev.Netmask,
|
||||
Gateway: netdev.Gateway}
|
||||
ret.NetDevs[devn] = &device
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func myprintf(format string, a ...interface{}) {
|
||||
if !quiet {
|
||||
fmt.Printf(format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var endVers int
|
||||
var startVers int
|
||||
flag.StringVar(&confFile, "f", "", "Config file for update")
|
||||
flag.IntVar(&endVers, "e", 0, "Final version of configuration file")
|
||||
flag.IntVar(&startVers, "s", 0, "Start version of configuration file, 0 is for autodetection")
|
||||
flag.BoolVar(&nowrite, "n", false, "Do not write, just print new conf to terminal")
|
||||
flag.BoolVar(&quiet, "q", false, "Do not print what the program is doing")
|
||||
flag.Parse()
|
||||
if confFile == "" {
|
||||
myprintf("No config file given\n!")
|
||||
os.Exit(1)
|
||||
}
|
||||
myprintf("Opening node configuration file: %s\n", confFile)
|
||||
data, err := os.ReadFile(confFile)
|
||||
if err != nil {
|
||||
myprintf("Could open file %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
var getConf nodeVersionOnly
|
||||
myprintf("Unmarshaling the node configuration\n")
|
||||
err = yaml.Unmarshal(data, &getConf)
|
||||
if err != nil {
|
||||
myprintf("Could not unmarshall: %v\n", err)
|
||||
}
|
||||
myprintf("Got version %v in %s\n", getConf.WWInternal, confFile)
|
||||
if getConf.WWInternal == actvers {
|
||||
myprintf("On actual version, bailing out\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
if startVers == 0 && getConf.WWInternal == 0 {
|
||||
startVers = 42
|
||||
}
|
||||
var conf42 vers42.NodeYaml
|
||||
conf42.NodeProfiles = make(map[string]*vers42.NodeConf)
|
||||
conf42.Nodes = make(map[string]*vers42.NodeConf)
|
||||
|
||||
var conf43 vers43.NodeYaml
|
||||
conf43.NodeProfiles = make(map[string]*vers43.NodeConf)
|
||||
conf43.Nodes = make(map[string]*vers43.NodeConf)
|
||||
conf43.WWInternal = 43
|
||||
|
||||
if startVers == 42 {
|
||||
myprintf("Unmarshaling the node configuration vers 42\n")
|
||||
err = yaml.Unmarshal(data, &conf42)
|
||||
if err != nil {
|
||||
myprintf("Could not unmarshall version 42: %v\n", err)
|
||||
}
|
||||
for pname, profile := range conf42.NodeProfiles {
|
||||
p43 := update42to43(*profile)
|
||||
conf43.NodeProfiles[pname] = &p43
|
||||
}
|
||||
for nname, node := range conf42.Nodes {
|
||||
n43 := update42to43(*node)
|
||||
conf43.Nodes[nname] = &n43
|
||||
}
|
||||
saveConf(conf43)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package vers42
|
||||
|
||||
/******
|
||||
* YAML data representations
|
||||
******/
|
||||
|
||||
// type nodeYaml struct {
|
||||
type NodeYaml struct { // <-Needs to be exported
|
||||
NodeProfiles map[string]*NodeConf
|
||||
Nodes map[string]*NodeConf
|
||||
}
|
||||
|
||||
type NodeConf struct {
|
||||
Comment string `yaml:"comment,omitempty"`
|
||||
ClusterName string `yaml:"cluster name,omitempty"`
|
||||
ContainerName string `yaml:"container name,omitempty"`
|
||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||
KernelVersion string `yaml:"kernel version,omitempty"`
|
||||
KernelArgs string `yaml:"kernel args,omitempty"`
|
||||
IpmiUserName string `yaml:"ipmi username,omitempty"`
|
||||
IpmiPassword string `yaml:"ipmi password,omitempty"`
|
||||
IpmiIpaddr string `yaml:"ipmi ipaddr,omitempty"`
|
||||
IpmiNetmask string `yaml:"ipmi netmask,omitempty"`
|
||||
IpmiPort string `yaml:"ipmi port,omitempty"`
|
||||
IpmiGateway string `yaml:"ipmi gateway,omitempty"`
|
||||
IpmiInterface string `yaml:"ipmi interface,omitempty"`
|
||||
RuntimeOverlay string `yaml:"runtime overlay,omitempty"`
|
||||
SystemOverlay string `yaml:"system overlay,omitempty"`
|
||||
Init string `yaml:"init,omitempty"`
|
||||
Root string `yaml:"root,omitempty"`
|
||||
Discoverable bool `yaml:"discoverable,omitempty"`
|
||||
Profiles []string `yaml:"profiles,omitempty"`
|
||||
NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"`
|
||||
Keys map[string]string `yaml:"keys,omitempty"`
|
||||
}
|
||||
|
||||
type NetDevs struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
Default bool `yaml:"default"`
|
||||
Hwaddr string
|
||||
Ipaddr string
|
||||
IpCIDR string
|
||||
Prefix string
|
||||
Netmask string
|
||||
Gateway string `yaml:"gateway,omitempty"`
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay: "generic"
|
||||
discoverable: false
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel version: "5.14.21"
|
||||
ipmi netmask: "255.255.255.0"
|
||||
keys:
|
||||
foo: baar
|
||||
network devices:
|
||||
lan1:
|
||||
gateway: 1.1.1.1
|
||||
nodes:
|
||||
node01:
|
||||
system overlay: "nodeoverlay"
|
||||
discoverable: true
|
||||
network devices:
|
||||
eth0:
|
||||
ipaddr: 1.2.3.4
|
||||
default: true
|
||||
@@ -1,65 +0,0 @@
|
||||
package vers43
|
||||
|
||||
/******
|
||||
* YAML data representations
|
||||
******/
|
||||
|
||||
// type nodeYaml struct {
|
||||
type NodeYaml struct { // <- needs to be exported
|
||||
WWInternal int `yaml:"WW_INTERNAL"`
|
||||
NodeProfiles map[string]*NodeConf
|
||||
Nodes map[string]*NodeConf
|
||||
}
|
||||
|
||||
/*
|
||||
NodeConf is the datastructure which is stored on disk.
|
||||
*/
|
||||
type NodeConf struct {
|
||||
Comment string `yaml:"comment,omitempty"`
|
||||
ClusterName string `yaml:"cluster name,omitempty"`
|
||||
ContainerName string `yaml:"container name,omitempty"`
|
||||
Ipxe string `yaml:"ipxe template,omitempty"`
|
||||
RuntimeOverlay []string `yaml:"runtime overlay,omitempty"`
|
||||
SystemOverlay []string `yaml:"system overlay,omitempty"`
|
||||
Kernel *KernelConf `yaml:"kernel,omitempty"`
|
||||
Ipmi *IpmiConf `yaml:"ipmi,omitempty"`
|
||||
Init string `yaml:"init,omitempty"`
|
||||
Root string `yaml:"root,omitempty"`
|
||||
AssetKey string `yaml:"asset key,omitempty"`
|
||||
Discoverable string `yaml:"discoverable,omitempty"`
|
||||
Profiles []string `yaml:"profiles,omitempty"`
|
||||
NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"`
|
||||
Tags map[string]string `yaml:"tags,omitempty"`
|
||||
Keys map[string]string `yaml:"keys,omitempty"` // Reverse compatibility
|
||||
}
|
||||
|
||||
type IpmiConf struct {
|
||||
UserName string `yaml:"username,omitempty"`
|
||||
Password string `yaml:"password,omitempty"`
|
||||
Ipaddr string `yaml:"ipaddr,omitempty"`
|
||||
Netmask string `yaml:"netmask,omitempty"`
|
||||
Port string `yaml:"port,omitempty"`
|
||||
Gateway string `yaml:"gateway,omitempty"`
|
||||
Interface string `yaml:"interface,omitempty"`
|
||||
Write bool `yaml:"write,omitempty"`
|
||||
}
|
||||
type KernelConf struct {
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Override string `yaml:"override,omitempty"`
|
||||
Args string `yaml:"args,omitempty"`
|
||||
}
|
||||
|
||||
type NetDevs struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
OnBoot string `yaml:"onboot,omitempty"`
|
||||
Device string `yaml:"device,omitempty"`
|
||||
Hwaddr string `yaml:"hwaddr,omitempty"`
|
||||
Ipaddr string `yaml:"ipaddr,omitempty"`
|
||||
IpCIDR string `yaml:"ipcidr,omitempty"`
|
||||
Ipaddr6 string `yaml:"ip6addr,omitempty"`
|
||||
Prefix string `yaml:"prefix,omitempty"`
|
||||
Netmask string `yaml:"netmask,omitempty"`
|
||||
Gateway string `yaml:"gateway,omitempty"`
|
||||
Primary string `yaml:"primary,omitempty"`
|
||||
Tags map[string]string `yaml:"tags,omitempty"`
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
WW_INTERNAL: 45
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay:
|
||||
- generic
|
||||
discoverable: "false"
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel:
|
||||
override: 5.14.21
|
||||
ipmi:
|
||||
netmask: 255.255.255.0
|
||||
discoverable: "false"
|
||||
network devices:
|
||||
lan1:
|
||||
device: lan1
|
||||
gateway: 1.1.1.1
|
||||
default: "false"
|
||||
keys:
|
||||
foo: baar
|
||||
nodes:
|
||||
node01:
|
||||
system overlay:
|
||||
- nodeoverlay
|
||||
discoverable: "true"
|
||||
network devices:
|
||||
eth0:
|
||||
device: eth0
|
||||
ipaddr: 1.2.3.4
|
||||
default: "true"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package upgrade
|
||||
|
||||
type WarewulfYaml struct {
|
||||
WWInternal int `yaml:"WW_INTERNAL"`
|
||||
WWInternal string `yaml:"WW_INTERNAL"`
|
||||
Comment string `yaml:"comment,omitempty"`
|
||||
Ipaddr string `yaml:"ipaddr"`
|
||||
Ipaddr6 string `yaml:"ipaddr6,omitempty"`
|
||||
|
||||
@@ -1,31 +1,194 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/warewulf/warewulf/internal/pkg/node"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func Parse(data []byte) (nodeYaml NodeYaml, err error) {
|
||||
if err = yaml.Unmarshal(data, &nodeYaml); err != nil {
|
||||
return nodeYaml, err
|
||||
}
|
||||
if nodeYaml.Nodes == nil {
|
||||
nodeYaml.Nodes = map[string]*Node{}
|
||||
}
|
||||
if nodeYaml.NodeProfiles == nil {
|
||||
nodeYaml.NodeProfiles = map[string]*Profile{}
|
||||
}
|
||||
return nodeYaml, nil
|
||||
func logIgnore(name string, value interface{}, reason string) {
|
||||
wwlog.Warn("ignore: %s: %v (%s)", name, value, reason)
|
||||
}
|
||||
|
||||
type NodeYaml struct {
|
||||
func Parse(data []byte) (nodesYaml *NodesYaml, err error) {
|
||||
nodesYaml = new(NodesYaml)
|
||||
if err = yaml.Unmarshal(data, nodesYaml); err != nil {
|
||||
return nodesYaml, err
|
||||
}
|
||||
return nodesYaml, nil
|
||||
}
|
||||
|
||||
type NodesYaml struct {
|
||||
WWInternal string `yaml:"WW_INTERNAL"`
|
||||
NodeProfiles map[string]*Profile
|
||||
Nodes map[string]*Node
|
||||
}
|
||||
|
||||
func (this *NodesYaml) Upgrade() (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()
|
||||
}
|
||||
}
|
||||
if this.Nodes != nil {
|
||||
for name, node := range this.Nodes {
|
||||
upgraded.Nodes[name] = node.Upgrade()
|
||||
}
|
||||
}
|
||||
return upgraded
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Profile `yaml:"-,inline"`
|
||||
}
|
||||
|
||||
func (this *Node) Upgrade() (upgraded *node.Node) {
|
||||
upgraded = new(node.Node)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Disks = make(map[string]*node.Disk)
|
||||
upgraded.FileSystems = make(map[string]*node.FileSystem)
|
||||
upgraded.Ipmi = new(node.IpmiConf)
|
||||
upgraded.Kernel = new(node.KernelConf)
|
||||
upgraded.NetDevs = make(map[string]*node.NetDev)
|
||||
upgraded.AssetKey = this.AssetKey
|
||||
upgraded.ClusterName = this.ClusterName
|
||||
upgraded.Comment = this.Comment
|
||||
upgraded.ContainerName = this.ContainerName
|
||||
if this.Disabled != "" {
|
||||
logIgnore("Disabled", this.Disabled, "obsolete")
|
||||
}
|
||||
if this.Discoverable != "" {
|
||||
upgraded.Discoverable.Set(this.Discoverable)
|
||||
}
|
||||
if this.Disks != nil {
|
||||
for name, disk := range this.Disks {
|
||||
upgraded.Disks[name] = disk.Upgrade()
|
||||
}
|
||||
}
|
||||
if this.FileSystems != nil {
|
||||
for name, fileSystem := range this.FileSystems {
|
||||
upgraded.FileSystems[name] = fileSystem.Upgrade()
|
||||
}
|
||||
}
|
||||
upgraded.Init = this.Init
|
||||
if this.Ipmi != nil {
|
||||
upgraded.Ipmi = this.Ipmi.Upgrade()
|
||||
} else {
|
||||
upgraded.Ipmi = new(node.IpmiConf)
|
||||
}
|
||||
if upgraded.Ipmi.EscapeChar == "" {
|
||||
upgraded.Ipmi.EscapeChar = this.IpmiEscapeChar
|
||||
}
|
||||
if upgraded.Ipmi.Gateway.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Gateway = net.ParseIP(this.IpmiGateway)
|
||||
}
|
||||
if upgraded.Ipmi.Interface == "" {
|
||||
upgraded.Ipmi.Interface = this.IpmiInterface
|
||||
}
|
||||
if upgraded.Ipmi.Ipaddr.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Ipaddr = net.ParseIP(this.IpmiIpaddr)
|
||||
}
|
||||
if upgraded.Ipmi.Netmask.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Netmask = net.ParseIP(this.IpmiNetmask)
|
||||
}
|
||||
if upgraded.Ipmi.Password == "" {
|
||||
upgraded.Ipmi.Password = this.IpmiPassword
|
||||
}
|
||||
if upgraded.Ipmi.Port == "" {
|
||||
upgraded.Ipmi.Port = this.IpmiPort
|
||||
}
|
||||
if upgraded.Ipmi.UserName == "" {
|
||||
upgraded.Ipmi.UserName = this.IpmiUserName
|
||||
}
|
||||
if upgraded.Ipmi.Write == "" {
|
||||
upgraded.Ipmi.Write.Set(this.IpmiWrite)
|
||||
}
|
||||
upgraded.Ipxe = this.Ipxe
|
||||
if this.Kernel != nil {
|
||||
upgraded.Kernel = this.Kernel.Upgrade()
|
||||
} else {
|
||||
upgraded.Kernel = new(node.KernelConf)
|
||||
}
|
||||
if upgraded.Kernel.Args == "" {
|
||||
upgraded.Kernel.Args = this.KernelArgs
|
||||
}
|
||||
if upgraded.Kernel.Override == "" {
|
||||
upgraded.Kernel.Override = this.KernelOverride
|
||||
}
|
||||
if upgraded.Kernel.Version == "" {
|
||||
upgraded.Kernel.Version = this.KernelVersion
|
||||
}
|
||||
if this.Keys != nil {
|
||||
for key, value := range this.Keys {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
if this.NetDevs != nil {
|
||||
for name, netDev := range this.NetDevs {
|
||||
upgraded.NetDevs[name] = netDev.Upgrade()
|
||||
}
|
||||
}
|
||||
if this.PrimaryNetDev != "" {
|
||||
upgraded.PrimaryNetDev = this.PrimaryNetDev
|
||||
} else {
|
||||
for name, netDev := range this.NetDevs {
|
||||
if b, _ := strconv.ParseBool(netDev.Primary); b {
|
||||
upgraded.PrimaryNetDev = name
|
||||
break
|
||||
} else if b, _ := strconv.ParseBool(netDev.Default); b {
|
||||
upgraded.PrimaryNetDev = name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
upgraded.Profiles = append(upgraded.Profiles, this.Profiles...)
|
||||
upgraded.Root = this.Root
|
||||
if this.RuntimeOverlay != nil {
|
||||
switch overlay := this.RuntimeOverlay.(type) {
|
||||
case string:
|
||||
upgraded.RuntimeOverlay = append(upgraded.RuntimeOverlay, strings.Split(overlay, ",")...)
|
||||
case []interface{}:
|
||||
for _, each := range overlay {
|
||||
upgraded.RuntimeOverlay = append(upgraded.RuntimeOverlay, each.(string))
|
||||
}
|
||||
default:
|
||||
wwlog.Error("unparsable RuntimeOverlay: %v", overlay)
|
||||
}
|
||||
}
|
||||
if this.SystemOverlay != nil {
|
||||
switch overlay := this.SystemOverlay.(type) {
|
||||
case string:
|
||||
upgraded.SystemOverlay = append(upgraded.SystemOverlay, strings.Split(overlay, ",")...)
|
||||
case []interface{}:
|
||||
for _, each := range overlay {
|
||||
upgraded.SystemOverlay = append(upgraded.SystemOverlay, each.(string))
|
||||
}
|
||||
default:
|
||||
wwlog.Error("unparsable SystemOverlay: %v", overlay)
|
||||
}
|
||||
}
|
||||
if this.Tags != nil {
|
||||
for key, value := range this.Tags {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
for _, tag := range this.TagsDel {
|
||||
delete(upgraded.Tags, tag)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
AssetKey string `yaml:"asset key,omitempty"`
|
||||
ClusterName string `yaml:"cluster name,omitempty"`
|
||||
@@ -56,12 +219,152 @@ type Profile struct {
|
||||
PrimaryNetDev string `yaml:"primary network,omitempty"`
|
||||
Profiles []string `yaml:"profiles,omitempty"`
|
||||
Root string `yaml:"root,omitempty"`
|
||||
RuntimeOverlay []string `yaml:"runtime overlay,omitempty"`
|
||||
SystemOverlay []string `yaml:"system overlay,omitempty"`
|
||||
RuntimeOverlay interface{} `yaml:"runtime overlay,omitempty"`
|
||||
SystemOverlay interface{} `yaml:"system overlay,omitempty"`
|
||||
Tags map[string]string `yaml:"tags,omitempty"`
|
||||
TagsDel []string `yaml:"tagsdel,omitempty"`
|
||||
}
|
||||
|
||||
func (this *Profile) Upgrade() (upgraded *node.Profile) {
|
||||
upgraded = new(node.Profile)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Disks = make(map[string]*node.Disk)
|
||||
upgraded.FileSystems = make(map[string]*node.FileSystem)
|
||||
upgraded.Kernel = new(node.KernelConf)
|
||||
upgraded.NetDevs = make(map[string]*node.NetDev)
|
||||
if this.AssetKey != "" {
|
||||
logIgnore("AssetKey", this.AssetKey, "invalid for profiles")
|
||||
}
|
||||
upgraded.ClusterName = this.ClusterName
|
||||
upgraded.Comment = this.Comment
|
||||
upgraded.ContainerName = this.ContainerName
|
||||
if this.Disabled != "" {
|
||||
logIgnore("Disabled", this.Disabled, "obsolete")
|
||||
}
|
||||
if this.Discoverable != "" {
|
||||
logIgnore("Discoverable", this.Discoverable, "invalid for profiles")
|
||||
}
|
||||
if this.Disks != nil {
|
||||
for name, disk := range this.Disks {
|
||||
upgraded.Disks[name] = disk.Upgrade()
|
||||
}
|
||||
}
|
||||
if this.FileSystems != nil {
|
||||
for name, fileSystem := range this.FileSystems {
|
||||
upgraded.FileSystems[name] = fileSystem.Upgrade()
|
||||
}
|
||||
}
|
||||
upgraded.Init = this.Init
|
||||
upgraded.Ipmi = new(node.IpmiConf)
|
||||
if this.Ipmi != nil {
|
||||
upgraded.Ipmi = this.Ipmi.Upgrade()
|
||||
} else {
|
||||
upgraded.Ipmi = new(node.IpmiConf)
|
||||
}
|
||||
if upgraded.Ipmi.EscapeChar == "" {
|
||||
upgraded.Ipmi.EscapeChar = this.IpmiEscapeChar
|
||||
}
|
||||
if upgraded.Ipmi.Gateway.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Gateway = net.ParseIP(this.IpmiGateway)
|
||||
}
|
||||
if upgraded.Ipmi.Interface == "" {
|
||||
upgraded.Ipmi.Interface = this.IpmiInterface
|
||||
}
|
||||
if upgraded.Ipmi.Ipaddr.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Ipaddr = net.ParseIP(this.IpmiIpaddr)
|
||||
}
|
||||
if upgraded.Ipmi.Netmask.Equal(net.IP{}) {
|
||||
upgraded.Ipmi.Netmask = net.ParseIP(this.IpmiNetmask)
|
||||
}
|
||||
if upgraded.Ipmi.Password == "" {
|
||||
upgraded.Ipmi.Password = this.IpmiPassword
|
||||
}
|
||||
if upgraded.Ipmi.Port == "" {
|
||||
upgraded.Ipmi.Port = this.IpmiPort
|
||||
}
|
||||
if upgraded.Ipmi.UserName == "" {
|
||||
upgraded.Ipmi.UserName = this.IpmiUserName
|
||||
}
|
||||
if upgraded.Ipmi.Write == "" {
|
||||
upgraded.Ipmi.Write.Set(this.IpmiWrite)
|
||||
}
|
||||
upgraded.Ipxe = this.Ipxe
|
||||
if this.Kernel != nil {
|
||||
upgraded.Kernel = this.Kernel.Upgrade()
|
||||
} else {
|
||||
upgraded.Kernel = new(node.KernelConf)
|
||||
}
|
||||
if upgraded.Kernel.Args == "" {
|
||||
upgraded.Kernel.Args = this.KernelArgs
|
||||
}
|
||||
if upgraded.Kernel.Override == "" {
|
||||
upgraded.Kernel.Override = this.KernelOverride
|
||||
}
|
||||
if upgraded.Kernel.Version == "" {
|
||||
upgraded.Kernel.Version = this.KernelVersion
|
||||
}
|
||||
if this.Keys != nil {
|
||||
for key, value := range this.Keys {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
if this.NetDevs != nil {
|
||||
for name, netDev := range this.NetDevs {
|
||||
upgraded.NetDevs[name] = netDev.Upgrade()
|
||||
}
|
||||
}
|
||||
if this.PrimaryNetDev != "" {
|
||||
upgraded.PrimaryNetDev = this.PrimaryNetDev
|
||||
} else {
|
||||
for name, netDev := range this.NetDevs {
|
||||
if b, _ := strconv.ParseBool(netDev.Primary); b {
|
||||
upgraded.PrimaryNetDev = name
|
||||
break
|
||||
} else if b, _ := strconv.ParseBool(netDev.Default); b {
|
||||
upgraded.PrimaryNetDev = name
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if this.Profiles != nil {
|
||||
logIgnore("Profiles", this.Profiles, "invalid for profiles")
|
||||
}
|
||||
upgraded.Root = this.Root
|
||||
if this.RuntimeOverlay != nil {
|
||||
switch overlay := this.RuntimeOverlay.(type) {
|
||||
case string:
|
||||
upgraded.RuntimeOverlay = append(upgraded.RuntimeOverlay, strings.Split(overlay, ",")...)
|
||||
case []interface{}:
|
||||
for _, each := range overlay {
|
||||
upgraded.RuntimeOverlay = append(upgraded.RuntimeOverlay, each.(string))
|
||||
}
|
||||
default:
|
||||
wwlog.Error("unparsable RuntimeOverlay: %v", overlay)
|
||||
}
|
||||
}
|
||||
if this.SystemOverlay != nil {
|
||||
switch overlay := this.SystemOverlay.(type) {
|
||||
case string:
|
||||
upgraded.SystemOverlay = append(upgraded.SystemOverlay, strings.Split(overlay, ",")...)
|
||||
case []interface{}:
|
||||
for _, each := range overlay {
|
||||
upgraded.SystemOverlay = append(upgraded.SystemOverlay, each.(string))
|
||||
}
|
||||
default:
|
||||
wwlog.Error("unparsable SystemOverlay: %v", overlay)
|
||||
}
|
||||
}
|
||||
if this.Tags != nil {
|
||||
for key, value := range this.Tags {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
for _, tag := range this.TagsDel {
|
||||
delete(upgraded.Tags, tag)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type IpmiConf struct {
|
||||
EscapeChar string `yaml:"escapechar,omitempty"`
|
||||
Gateway string `yaml:"gateway,omitempty"`
|
||||
@@ -76,12 +379,43 @@ type IpmiConf struct {
|
||||
Write string `yaml:"write,omitempty"`
|
||||
}
|
||||
|
||||
func (this *IpmiConf) Upgrade() (upgraded *node.IpmiConf) {
|
||||
upgraded = new(node.IpmiConf)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.EscapeChar = this.EscapeChar
|
||||
upgraded.Gateway = net.ParseIP(this.Gateway)
|
||||
upgraded.Interface = this.Interface
|
||||
upgraded.Ipaddr = net.ParseIP(this.Ipaddr)
|
||||
upgraded.Netmask = net.ParseIP(this.Netmask)
|
||||
upgraded.Password = this.Password
|
||||
upgraded.Port = this.Port
|
||||
if this.Tags != nil {
|
||||
for key, value := range this.Tags {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
for _, tag := range this.TagsDel {
|
||||
delete(upgraded.Tags, tag)
|
||||
}
|
||||
upgraded.UserName = this.UserName
|
||||
upgraded.Write.Set(this.Write)
|
||||
return
|
||||
}
|
||||
|
||||
type KernelConf struct {
|
||||
Args string `yaml:"args,omitempty"`
|
||||
Override string `yaml:"override,omitempty"`
|
||||
Version string `yaml:"version,omitempty"`
|
||||
}
|
||||
|
||||
func (this *KernelConf) Upgrade() (upgraded *node.KernelConf) {
|
||||
upgraded = new(node.KernelConf)
|
||||
upgraded.Args = this.Args
|
||||
upgraded.Override = this.Override
|
||||
upgraded.Version = this.Version
|
||||
return
|
||||
}
|
||||
|
||||
type NetDev struct {
|
||||
Default string `yaml:"default"`
|
||||
Device string `yaml:"device,omitempty"`
|
||||
@@ -100,11 +434,60 @@ type NetDev struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
}
|
||||
|
||||
func (this *NetDev) Upgrade() (upgraded *node.NetDev) {
|
||||
upgraded = new(node.NetDev)
|
||||
upgraded.Tags = make(map[string]string)
|
||||
upgraded.Device = this.Device
|
||||
upgraded.Gateway = net.ParseIP(this.Gateway)
|
||||
upgraded.Hwaddr = this.Hwaddr
|
||||
upgraded.Ipaddr = net.ParseIP(this.Ipaddr)
|
||||
upgraded.Ipaddr6 = net.ParseIP(this.Ipaddr6)
|
||||
upgraded.MTU = this.MTU
|
||||
upgraded.Netmask = net.ParseIP(this.Netmask)
|
||||
if this.IpCIDR != "" {
|
||||
cidrIP, cidrIPNet, err := net.ParseCIDR(this.IpCIDR)
|
||||
if err != nil {
|
||||
wwlog.Error("%v is not a valid CIDR address: %w", this.IpCIDR, err)
|
||||
} else {
|
||||
if upgraded.Ipaddr == nil {
|
||||
upgraded.Ipaddr = cidrIP
|
||||
}
|
||||
if upgraded.Netmask == nil {
|
||||
upgraded.Netmask = net.IP(cidrIPNet.Mask)
|
||||
}
|
||||
}
|
||||
}
|
||||
upgraded.OnBoot.Set(this.OnBoot)
|
||||
upgraded.Prefix = net.ParseIP(this.Prefix)
|
||||
if this.Tags != nil {
|
||||
for key, value := range this.Tags {
|
||||
upgraded.Tags[key] = value
|
||||
}
|
||||
}
|
||||
for _, tag := range this.TagsDel {
|
||||
delete(upgraded.Tags, tag)
|
||||
}
|
||||
upgraded.Type = this.Type
|
||||
return
|
||||
}
|
||||
|
||||
type Disk struct {
|
||||
Partitions map[string]*Partition `yaml:"partitions,omitempty"`
|
||||
WipeTable string `yaml:"wipe_table,omitempty"`
|
||||
}
|
||||
|
||||
func (this *Disk) Upgrade() (upgraded *node.Disk) {
|
||||
upgraded = new(node.Disk)
|
||||
upgraded.Partitions = make(map[string]*node.Partition)
|
||||
if this.Partitions != nil {
|
||||
for name, partition := range this.Partitions {
|
||||
upgraded.Partitions[name] = partition.Upgrade()
|
||||
}
|
||||
}
|
||||
upgraded.WipeTable, _ = strconv.ParseBool(this.WipeTable)
|
||||
return
|
||||
}
|
||||
|
||||
type Partition struct {
|
||||
Guid string `yaml:"guid,omitempty"`
|
||||
Number string `yaml:"number,omitempty"`
|
||||
@@ -116,13 +499,49 @@ type Partition struct {
|
||||
WipePartitionEntry string `yaml:"wipe_partition_entry,omitempty"`
|
||||
}
|
||||
|
||||
type FileSystem struct {
|
||||
Format string `yaml:"format,omitempty"`
|
||||
Label string `yaml:"label,omitempty"`
|
||||
MountOptions string `yaml:"mount_options,omitempty"`
|
||||
//MountOptions []string `yaml:"mount_options,omitempty"`
|
||||
Options []string `yaml:"options,omitempty"`
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Uuid string `yaml:"uuid,omitempty"`
|
||||
WipeFileSystem string `yaml:"wipe_filesystem,omitempty"`
|
||||
func (this *Partition) Upgrade() (upgraded *node.Partition) {
|
||||
upgraded = new(node.Partition)
|
||||
upgraded.Guid = this.Guid
|
||||
upgraded.Number = this.Number
|
||||
upgraded.Resize, _ = strconv.ParseBool(this.Resize)
|
||||
upgraded.ShouldExist, _ = strconv.ParseBool(this.ShouldExist)
|
||||
upgraded.SizeMiB = this.SizeMiB
|
||||
upgraded.StartMiB = this.StartMiB
|
||||
upgraded.TypeGuid = this.TypeGuid
|
||||
upgraded.WipePartitionEntry, _ = strconv.ParseBool(this.WipePartitionEntry)
|
||||
return
|
||||
}
|
||||
|
||||
type FileSystem struct {
|
||||
Format string `yaml:"format,omitempty"`
|
||||
Label string `yaml:"label,omitempty"`
|
||||
MountOptions interface{} `yaml:"mount_options,omitempty"`
|
||||
Options []string `yaml:"options,omitempty"`
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Uuid string `yaml:"uuid,omitempty"`
|
||||
WipeFileSystem string `yaml:"wipe_filesystem,omitempty"`
|
||||
}
|
||||
|
||||
func (this *FileSystem) Upgrade() (upgraded *node.FileSystem) {
|
||||
upgraded = new(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))
|
||||
}
|
||||
upgraded.MountOptions = strings.Join(mountOptionsStrings, " ")
|
||||
default:
|
||||
wwlog.Error("unparsable MountOptions: %v", mountOptions)
|
||||
}
|
||||
upgraded.Options = append(upgraded.Options, this.Options...)
|
||||
upgraded.Path = this.Path
|
||||
upgraded.Uuid = this.Uuid
|
||||
upgraded.WipeFileSystem, _ = strconv.ParseBool(this.WipeFileSystem)
|
||||
return
|
||||
}
|
||||
|
||||
502
internal/pkg/upgrade/node_test.go
Normal file
502
internal/pkg/upgrade/node_test.go
Normal file
@@ -0,0 +1,502 @@
|
||||
package upgrade
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var nodesYamlUpgradeTests = []struct {
|
||||
name string
|
||||
legacyYaml string
|
||||
upgradedYaml string
|
||||
}{
|
||||
{
|
||||
name: "captured vers42 example",
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay: "generic"
|
||||
discoverable: false
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel version: 5.14.21
|
||||
ipmi netmask: "255.255.255.0"
|
||||
keys:
|
||||
foo: baar
|
||||
network devices:
|
||||
lan1:
|
||||
gateway: 1.1.1.1
|
||||
nodes:
|
||||
node01:
|
||||
system overlay: "nodeoverlay"
|
||||
discoverable: true
|
||||
network devices:
|
||||
eth0:
|
||||
ipaddr: 1.2.3.4
|
||||
default: true
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay:
|
||||
- generic
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel:
|
||||
version: 5.14.21
|
||||
ipmi:
|
||||
netmask: 255.255.255.0
|
||||
network devices:
|
||||
lan1:
|
||||
gateway: 1.1.1.1
|
||||
tags:
|
||||
foo: baar
|
||||
nodes:
|
||||
node01:
|
||||
discoverable: "true"
|
||||
system overlay:
|
||||
- nodeoverlay
|
||||
network devices:
|
||||
eth0:
|
||||
ipaddr: 1.2.3.4
|
||||
primary network: eth0
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "captured vers43 example",
|
||||
legacyYaml: `
|
||||
WW_INTERNAL: 45
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay:
|
||||
- generic
|
||||
discoverable: "false"
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel:
|
||||
override: 5.14.21
|
||||
ipmi:
|
||||
netmask: 255.255.255.0
|
||||
discoverable: "false"
|
||||
network devices:
|
||||
lan1:
|
||||
device: lan1
|
||||
gateway: 1.1.1.1
|
||||
default: "false"
|
||||
keys:
|
||||
foo: baar
|
||||
nodes:
|
||||
node01:
|
||||
system overlay:
|
||||
- nodeoverlay
|
||||
discoverable: "true"
|
||||
network devices:
|
||||
eth0:
|
||||
device: eth0
|
||||
ipaddr: 1.2.3.4
|
||||
default: "true"
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
comment: This profile is automatically included for each node
|
||||
runtime overlay:
|
||||
- generic
|
||||
leap:
|
||||
comment: openSUSE leap
|
||||
kernel:
|
||||
override: 5.14.21
|
||||
ipmi:
|
||||
netmask: 255.255.255.0
|
||||
network devices:
|
||||
lan1:
|
||||
device: lan1
|
||||
gateway: 1.1.1.1
|
||||
tags:
|
||||
foo: baar
|
||||
nodes:
|
||||
node01:
|
||||
discoverable: "true"
|
||||
system overlay:
|
||||
- nodeoverlay
|
||||
network devices:
|
||||
eth0:
|
||||
device: eth0
|
||||
ipaddr: 1.2.3.4
|
||||
primary network: eth0
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "remove WW_INTERNAL",
|
||||
legacyYaml: `WW_INTERNAL: 45`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles: {}
|
||||
nodes: {}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "disabled is obsolete",
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
disabled: true
|
||||
nodeprofiles:
|
||||
default:
|
||||
disabled: true
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default: {}
|
||||
nodes:
|
||||
n1: {}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "inline IPMI settings",
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
ipmi escapechar: "~"
|
||||
ipmi gateway: 192.168.0.1
|
||||
ipmi interface: lanplus
|
||||
ipmi ipaddr: 192.168.0.100
|
||||
ipmi netmask: 255.255.255.0
|
||||
ipmi password: password
|
||||
ipmi port: 623
|
||||
ipmi username: admin
|
||||
ipmi write: true
|
||||
nodeprofiles:
|
||||
default:
|
||||
ipmi escapechar: "~"
|
||||
ipmi gateway: 192.168.0.1
|
||||
ipmi interface: lanplus
|
||||
ipmi ipaddr: 192.168.0.100
|
||||
ipmi netmask: 255.255.255.0
|
||||
ipmi password: password
|
||||
ipmi port: 623
|
||||
ipmi username: admin
|
||||
ipmi write: true
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
ipmi:
|
||||
username: admin
|
||||
password: password
|
||||
ipaddr: 192.168.0.100
|
||||
gateway: 192.168.0.1
|
||||
netmask: 255.255.255.0
|
||||
port: "623"
|
||||
interface: lanplus
|
||||
escapechar: "~"
|
||||
write: "true"
|
||||
nodes:
|
||||
n1:
|
||||
ipmi:
|
||||
username: admin
|
||||
password: password
|
||||
ipaddr: 192.168.0.100
|
||||
gateway: 192.168.0.1
|
||||
netmask: 255.255.255.0
|
||||
port: "623"
|
||||
interface: lanplus
|
||||
escapechar: "~"
|
||||
write: "true"
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "inline Kernel settings",
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
kernel args: quiet
|
||||
kernel override: rockylinux-9
|
||||
kernel version: 2.6
|
||||
nodes:
|
||||
n1:
|
||||
kernel args: quiet
|
||||
kernel override: rockylinux-9
|
||||
kernel version: 2.6
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
kernel:
|
||||
version: "2.6"
|
||||
override: rockylinux-9
|
||||
args: quiet
|
||||
nodes:
|
||||
n1:
|
||||
kernel:
|
||||
version: "2.6"
|
||||
override: rockylinux-9
|
||||
args: quiet
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "keys and tags",
|
||||
legacyYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
keys:
|
||||
key1: val1
|
||||
key2: val2
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
network devices:
|
||||
default:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
ipmi:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
nodes:
|
||||
n1:
|
||||
keys:
|
||||
key1: val1
|
||||
key2: val2
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
network devices:
|
||||
default:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
ipmi:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
key4: valD
|
||||
tagsdel:
|
||||
- key4
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
default:
|
||||
ipmi:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
network devices:
|
||||
default:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
tags:
|
||||
key1: val1
|
||||
key2: valB
|
||||
key3: valC
|
||||
nodes:
|
||||
n1:
|
||||
ipmi:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
network devices:
|
||||
default:
|
||||
tags:
|
||||
key2: valB
|
||||
key3: valC
|
||||
tags:
|
||||
key1: val1
|
||||
key2: valB
|
||||
key3: valC
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "primary network",
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
network devices:
|
||||
eth0: {}
|
||||
eth1:
|
||||
default: true
|
||||
n2:
|
||||
network devices:
|
||||
eth0:
|
||||
primary: true
|
||||
eth1: {}
|
||||
n3:
|
||||
network devices:
|
||||
eth0:
|
||||
primary: true
|
||||
eth1: {}
|
||||
primary network: eth1
|
||||
nodeprofiles:
|
||||
p1:
|
||||
network devices:
|
||||
eth0: {}
|
||||
eth1:
|
||||
default: true
|
||||
p2:
|
||||
network devices:
|
||||
eth0:
|
||||
primary: true
|
||||
eth1: {}
|
||||
p3:
|
||||
network devices:
|
||||
eth0:
|
||||
primary: true
|
||||
eth1: {}
|
||||
primary network: eth1
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
p1:
|
||||
primary network: eth1
|
||||
p2:
|
||||
primary network: eth0
|
||||
p3:
|
||||
primary network: eth1
|
||||
nodes:
|
||||
n1:
|
||||
primary network: eth1
|
||||
n2:
|
||||
primary network: eth0
|
||||
n3:
|
||||
primary network: eth1
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "overlays",
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
n2:
|
||||
runtime overlay: r1,r2
|
||||
system overlay: s1,s2
|
||||
nodeprofiles:
|
||||
p1:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
p2:
|
||||
runtime overlay: r1,r2
|
||||
system overlay: s1,s2
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles:
|
||||
p1:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
p2:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
nodes:
|
||||
n1:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
n2:
|
||||
runtime overlay:
|
||||
- r1
|
||||
- r2
|
||||
system overlay:
|
||||
- s1
|
||||
- s2
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "disk example",
|
||||
legacyYaml: `
|
||||
nodes:
|
||||
n1:
|
||||
disks:
|
||||
/dev/vda:
|
||||
wipe_table: true
|
||||
partitions:
|
||||
scratch:
|
||||
number: "1"
|
||||
should_exist: true
|
||||
swap:
|
||||
number: "2"
|
||||
size_mib: "1024"
|
||||
filesystems:
|
||||
/dev/disk/by-partlabel/scratch:
|
||||
format: btrfs
|
||||
path: /scratch
|
||||
/dev/disk/by-partlabel/swap:
|
||||
format: swap
|
||||
path: swap
|
||||
`,
|
||||
upgradedYaml: `
|
||||
nodeprofiles: {}
|
||||
nodes:
|
||||
n1:
|
||||
disks:
|
||||
/dev/vda:
|
||||
wipe_table: true
|
||||
partitions:
|
||||
scratch:
|
||||
number: "1"
|
||||
should_exist: true
|
||||
swap:
|
||||
number: "2"
|
||||
size_mib: "1024"
|
||||
filesystems:
|
||||
/dev/disk/by-partlabel/scratch:
|
||||
format: btrfs
|
||||
path: /scratch
|
||||
/dev/disk/by-partlabel/swap:
|
||||
format: swap
|
||||
path: swap
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
func Test_UpgradeNodesYaml(t *testing.T) {
|
||||
for _, tt := range nodesYamlUpgradeTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
legacy, err := Parse([]byte(tt.legacyYaml))
|
||||
assert.NoError(t, err)
|
||||
upgraded := legacy.Upgrade()
|
||||
upgradedYaml, err := upgraded.Dump()
|
||||
assert.Equal(t, strings.TrimSpace(tt.upgradedYaml), strings.TrimSpace(string(upgradedYaml)))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user