mirror of
https://github.com/kemko/xc.git
synced 2026-01-01 15:55:43 +03:00
271 lines
5.5 KiB
Go
271 lines
5.5 KiB
Go
package localini
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/viert/xc/config"
|
|
"github.com/viert/xc/store"
|
|
)
|
|
|
|
type parseSection int
|
|
|
|
const (
|
|
sectionWorkgroups parseSection = iota
|
|
sectionDatacenters
|
|
sectionGroups
|
|
sectionHosts
|
|
sectionNone
|
|
)
|
|
|
|
var (
|
|
lineCount = 0
|
|
)
|
|
|
|
// LocalIni backend loads hosts data from ini file
|
|
type LocalIni struct {
|
|
filename string
|
|
hosts []*store.Host
|
|
groups []*store.Group
|
|
workgroups []*store.WorkGroup
|
|
datacenters []*store.Datacenter
|
|
}
|
|
|
|
// New creates a new LocalIni backend
|
|
func New(cfg *config.XCConfig) (*LocalIni, error) {
|
|
filename, found := cfg.BackendCfg.Options["filename"]
|
|
if !found {
|
|
return nil, fmt.Errorf("localini backend filename option is missing")
|
|
}
|
|
return &LocalIni{filename: config.ExpandPath(filename)}, nil
|
|
}
|
|
|
|
// Hosts exported backend method
|
|
func (li *LocalIni) Hosts() []*store.Host {
|
|
return li.hosts
|
|
}
|
|
|
|
// Groups exported backend method
|
|
func (li *LocalIni) Groups() []*store.Group {
|
|
return li.groups
|
|
}
|
|
|
|
// WorkGroups exported backend method
|
|
func (li *LocalIni) WorkGroups() []*store.WorkGroup {
|
|
return li.workgroups
|
|
}
|
|
|
|
// Datacenters exported backend method
|
|
func (li *LocalIni) Datacenters() []*store.Datacenter {
|
|
return li.datacenters
|
|
}
|
|
|
|
// Load loads the data from file
|
|
func (li *LocalIni) Load() error {
|
|
f, err := os.Open(li.filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
return li.read(f)
|
|
}
|
|
|
|
// Reload force reloads data from file
|
|
func (li *LocalIni) Reload() error {
|
|
return li.Load()
|
|
}
|
|
|
|
func (li *LocalIni) read(f *os.File) error {
|
|
var line string
|
|
|
|
li.datacenters = make([]*store.Datacenter, 0)
|
|
li.hosts = make([]*store.Host, 0)
|
|
li.groups = make([]*store.Group, 0)
|
|
li.workgroups = make([]*store.WorkGroup, 0)
|
|
|
|
lineCount = 0
|
|
section := sectionNone
|
|
scan := bufio.NewScanner(f)
|
|
|
|
for scan.Scan() {
|
|
lineCount++
|
|
line = strings.TrimSpace(scan.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") {
|
|
continue
|
|
}
|
|
switch line {
|
|
case "[workgroups]":
|
|
section = sectionWorkgroups
|
|
case "[groups]":
|
|
section = sectionGroups
|
|
case "[datacenters]":
|
|
section = sectionDatacenters
|
|
case "[hosts]":
|
|
section = sectionHosts
|
|
default:
|
|
var err error
|
|
switch section {
|
|
case sectionNone:
|
|
err = fmt.Errorf("Unexpected line #%d outside sections: %s", lineCount, line)
|
|
case sectionWorkgroups:
|
|
err = li.addWorkgroup(line)
|
|
case sectionGroups:
|
|
err = li.addGroup(line)
|
|
case sectionDatacenters:
|
|
err = li.addDatacenter(line)
|
|
case sectionHosts:
|
|
err = li.addHost(line)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func parseLine(line string) (map[string]string, error) {
|
|
data := make(map[string]string)
|
|
tokens := strings.Split(line, " ")
|
|
if len(tokens) < 1 {
|
|
return nil, fmt.Errorf("Malformed line, can't read workgroup name at line %d: %s", lineCount, line)
|
|
}
|
|
data["id"] = tokens[0]
|
|
data["name"] = tokens[0]
|
|
tokens = tokens[1:]
|
|
for _, token := range tokens {
|
|
kv := strings.Split(token, "=")
|
|
if len(kv) != 2 {
|
|
return nil, fmt.Errorf("Invalid token \"%s\", expected key=value format at line %d", token, lineCount)
|
|
}
|
|
data[kv[0]] = kv[1]
|
|
}
|
|
|
|
return data, nil
|
|
}
|
|
|
|
func (li *LocalIni) addWorkgroup(line string) error {
|
|
data, err := parseLine(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
wg := new(store.WorkGroup)
|
|
for key, value := range data {
|
|
switch key {
|
|
case "id":
|
|
wg.ID = value
|
|
case "name":
|
|
wg.Name = value
|
|
case "description":
|
|
wg.Description = value
|
|
default:
|
|
return fmt.Errorf("Invalid token %s at line %d: %s", key, lineCount, line)
|
|
}
|
|
}
|
|
li.workgroups = append(li.workgroups, wg)
|
|
return nil
|
|
}
|
|
|
|
func (li *LocalIni) addDatacenter(line string) error {
|
|
data, err := parseLine(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
dc := new(store.Datacenter)
|
|
for key, value := range data {
|
|
switch key {
|
|
case "id":
|
|
dc.ID = value
|
|
case "name":
|
|
dc.Name = value
|
|
case "parent_id":
|
|
fallthrough
|
|
case "parent":
|
|
dc.ParentID = value
|
|
case "desc":
|
|
fallthrough
|
|
case "description":
|
|
dc.Description = value
|
|
default:
|
|
return fmt.Errorf("Invalid token %s at line %d: %s", key, lineCount, line)
|
|
}
|
|
}
|
|
li.datacenters = append(li.datacenters, dc)
|
|
return nil
|
|
}
|
|
|
|
func (li *LocalIni) addGroup(line string) error {
|
|
data, err := parseLine(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
group := new(store.Group)
|
|
for key, value := range data {
|
|
switch key {
|
|
case "id":
|
|
group.ID = value
|
|
case "name":
|
|
group.Name = value
|
|
case "parent_id":
|
|
fallthrough
|
|
case "parent":
|
|
group.ParentID = value
|
|
case "tags":
|
|
group.Tags = strings.Split(value, ",")
|
|
case "description":
|
|
group.Description = value
|
|
case "workgroup":
|
|
fallthrough
|
|
case "wg":
|
|
fallthrough
|
|
case "wg_id":
|
|
group.WorkGroupID = value
|
|
default:
|
|
return fmt.Errorf("Invalid token %s at line %d: %s", key, lineCount, line)
|
|
}
|
|
}
|
|
li.groups = append(li.groups, group)
|
|
return nil
|
|
}
|
|
|
|
func (li *LocalIni) addHost(line string) error {
|
|
data, err := parseLine(line)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
host := new(store.Host)
|
|
for key, value := range data {
|
|
switch key {
|
|
case "id":
|
|
host.ID = value
|
|
case "name":
|
|
host.FQDN = value
|
|
case "group_id":
|
|
fallthrough
|
|
case "group":
|
|
host.GroupID = value
|
|
case "aliases":
|
|
host.Aliases = strings.Split(value, ",")
|
|
case "tags":
|
|
host.Tags = strings.Split(value, ",")
|
|
case "description":
|
|
host.Description = value
|
|
case "datacenter":
|
|
fallthrough
|
|
case "datacenter_id":
|
|
fallthrough
|
|
case "dc":
|
|
fallthrough
|
|
case "dc_id":
|
|
host.DatacenterID = value
|
|
default:
|
|
return fmt.Errorf("Invalid token %s at line %d: %s", key, lineCount, line)
|
|
}
|
|
}
|
|
li.hosts = append(li.hosts, host)
|
|
return nil
|
|
}
|