From 70008e0ead14b87cc93790a7e84c1b6065fb2b11 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 23:38:17 +0000 Subject: [PATCH] cluster: NewFromConfig() trying JSON and YAML Signed-off-by: Alejandro Mery --- pkg/cluster/cluster_import.go | 137 ++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 pkg/cluster/cluster_import.go diff --git a/pkg/cluster/cluster_import.go b/pkg/cluster/cluster_import.go new file mode 100644 index 0000000..ac597da --- /dev/null +++ b/pkg/cluster/cluster_import.go @@ -0,0 +1,137 @@ +package cluster + +import ( + "encoding/json" + "fmt" + "os" + + "gopkg.in/yaml.v3" +) + +func (m *Cluster) init(opts *ScanOptions) error { + for _, fn := range []func(*ScanOptions) error{ + m.initZones, + m.scanZoneIDs, + m.scanSort, + m.scanGateways, + } { + if err := fn(opts); err != nil { + return err + } + } + + return nil +} + +func (m *Cluster) initZones(opts *ScanOptions) error { + var err error + + sub, err := DirFS(m.BaseDir) + if err != nil { + return err + } + + m.dir = sub + + m.ForEachZone(func(z *Zone) bool { + err = m.initZone(z, opts) + return err != nil + }) + + return err +} + +func (m *Cluster) initZone(z *Zone, _ *ScanOptions) error { + var hasMissing bool + var lastMachineID int + + z.zones = m + z.logger = m + + z.ForEachMachine(func(p *Machine) bool { + p.zone = z + p.logger = z + + switch { + case p.ID == 0: + hasMissing = true + case p.ID > lastMachineID: + lastMachineID = z.ID + } + + return false + }) + + if hasMissing { + next := lastMachineID + 1 + + z.ForEachMachine(func(p *Machine) bool { + if p.ID == 0 { + p.ID, next = next, next+1 + } + + return false + }) + } + + z.ForEachMachine(func(p *Machine) bool { + p.Name = fmt.Sprintf("%s-%v", z.Name, p.ID) + return false + }) + + return nil +} + +func decodeConfigData(data []byte) (out *Cluster, err error) { + // try JSON first + out = new(Cluster) + err = json.Unmarshal(data, out) + if err == nil { + // good json + return out, nil + } else if _, ok := err.(*json.SyntaxError); !ok { + // bad json + return nil, err + } + + out = new(Cluster) + err = yaml.Unmarshal(data, out) + if err != nil { + // bad yaml too + return nil, err + } + + // good yaml + return out, nil +} + +// NewFromConfig loads the cluster data from the given file +func NewFromConfig(filename string, opts ...ScanOption) (*Cluster, error) { + var scanOptions ScanOptions + + data, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + + m, err := decodeConfigData(data) + if err != nil { + return nil, err + } + + for _, opt := range opts { + if err = opt(m, &scanOptions); err != nil { + return nil, err + } + } + + if err = m.setScanDefaults(&scanOptions); err != nil { + return nil, err + } + + if err := m.init(&scanOptions); err != nil { + return nil, err + } + + return m, nil +}