-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
146 lines (126 loc) · 3.64 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package pxeserver
import (
"fmt"
"io"
"io/ioutil"
"strings"
// This yaml library outputs maps with string keys for better
// interoperability with template funcs like 'toJson'
"github.com/ghodss/yaml"
"github.com/imdario/mergo"
)
type Config struct {
macToFiles map[string][]File
macToVars map[string]map[string]interface{}
macToSecrets map[string][]SecretDef
pixiecoreConfig Pixiecore
}
type ServerConfig struct {
Hosts []Host
Vars map[string]interface{}
SharedSecrets []SecretDef `json:"shared_secrets"`
}
type Pixiecore map[MacAddress]MachineConfig
type MacAddress string
type MachineConfig struct {
Kernel string
Initrd []string
Cmdline string
ForcePXELinux bool
}
type Host struct {
Mac string
Kernel File
Initrds []File
Files []File
BootArgs []string `json:"boot_args"`
Vars map[string]interface{}
Secrets []SecretDef
ForcePXELinux bool `json:"force_pxe_linux"`
}
type File struct {
Mac string
Path string
URL string
SHA256 string
ID string
Template bool
Vars map[string]interface{}
ImageConvert ImageConvert `json:"image_convert"`
Gzip bool
}
type ImageConvert struct {
InputFormat string `json:"input_format"`
}
func LoadConfig(configReader io.Reader) (Config, error) {
c := Config{
pixiecoreConfig: Pixiecore{},
macToFiles: make(map[string][]File),
macToVars: make(map[string]map[string]interface{}),
macToSecrets: make(map[string][]SecretDef),
}
input := ServerConfig{}
configContents, err := ioutil.ReadAll(configReader)
if err != nil {
return Config{}, err
}
if err = yaml.Unmarshal(configContents, &input); err != nil {
return Config{}, fmt.Errorf("config file was not valid YAML/JSON: %s", err)
}
if len(input.SharedSecrets) > 0 {
c.macToSecrets[""] = input.SharedSecrets
}
for _, host := range input.Hosts {
machine := MachineConfig{}
host.Kernel.ID = fmt.Sprintf("%s-__kernel__", host.Mac)
host.Kernel.Mac = host.Mac
c.macToFiles[host.Mac] = append(c.macToFiles[host.Mac], host.Kernel)
machine.Kernel = host.Kernel.ID
for i, f := range host.Initrds {
f.ID = fmt.Sprintf("%s-__initrd%d__", host.Mac, i)
f.Mac = host.Mac
c.macToFiles[host.Mac] = append(c.macToFiles[host.Mac], f)
machine.Initrd = append(machine.Initrd, f.ID)
}
if err := mergo.Merge(&host.Vars, input.Vars); err != nil {
return Config{}, err
}
c.macToVars[host.Mac] = host.Vars
c.macToSecrets[host.Mac] = host.Secrets
for _, f := range host.Files {
if len(f.Vars) > 0 && !f.Template {
return Config{}, fmt.Errorf("file with ID '%s' must have 'template: true' if 'vars' are non-empty", f.ID)
}
if err := mergo.Merge(&f.Vars, host.Vars, mergo.WithOverride); err != nil {
return Config{}, err
}
f.ID = fmt.Sprintf("%s-%s", host.Mac, f.ID)
f.Mac = host.Mac
c.macToFiles[host.Mac] = append(c.macToFiles[host.Mac], f)
}
machine.Cmdline = strings.Join(host.BootArgs, " ")
machine.ForcePXELinux = host.ForcePXELinux
c.pixiecoreConfig[MacAddress(host.Mac)] = machine
}
return c, nil
}
func (c *Config) Pixiecore() Pixiecore {
return c.pixiecoreConfig
}
func (c *Config) Files() []File {
allFiles := []File{}
for _, filesForHost := range c.macToFiles {
allFiles = append(allFiles, filesForHost...)
}
return allFiles
}
func (c *Config) SecretDefs() map[string][]SecretDef {
return c.macToSecrets
}
func (c *Config) VarsForHost(mac string) (map[string]interface{}, error) {
vars, ok := c.macToVars[mac]
if !ok {
return nil, fmt.Errorf("could not find host '%s' in config file", mac)
}
return vars, nil
}