1
0
mirror of https://github.com/rancher/os.git synced 2025-05-31 10:55:32 +00:00
os/config/data_funcs.go

216 lines
4.5 KiB
Go
Raw Normal View History

2015-03-15 04:27:04 +00:00
package config
import (
yaml "github.com/cloudfoundry-incubator/candiedyaml"
"github.com/rancher/os/log"
2015-03-15 04:27:04 +00:00
"strings"
2016-05-31 21:34:04 +00:00
"github.com/rancher/os/util"
2015-03-15 04:27:04 +00:00
)
type CfgFunc func(*CloudConfig) (*CloudConfig, error)
type CfgFuncData struct {
Name string
Func CfgFunc
}
type CfgFuncs []CfgFuncData
func ChainCfgFuncs(cfg *CloudConfig, cfgFuncs CfgFuncs) (*CloudConfig, error) {
len := len(cfgFuncs)
for c, d := range cfgFuncs {
i := c + 1
name := d.Name
cfgFunc := d.Func
if cfg == nil {
log.Infof("[%d/%d] Starting %s WITH NIL cfg", i, len, name)
} else {
log.Infof("[%d/%d] Starting %s", i, len, name)
}
var err error
if cfg, err = cfgFunc(cfg); err != nil {
log.Errorf("Failed [%d/%d] %s: %s", i, len, name, err)
return cfg, err
}
log.Debugf("[%d/%d] Done %s", i, len, name)
}
return cfg, nil
}
func filterKey(data map[interface{}]interface{}, key []string) (filtered, rest map[interface{}]interface{}) {
if len(key) == 0 {
return data, map[interface{}]interface{}{}
}
filtered = map[interface{}]interface{}{}
rest = util.MapCopy(data)
k := key[0]
if d, ok := data[k]; ok {
switch d := d.(type) {
case map[interface{}]interface{}:
f, r := filterKey(d, key[1:])
if len(f) != 0 {
filtered[k] = f
}
if len(r) != 0 {
rest[k] = r
} else {
delete(rest, k)
}
default:
filtered[k] = d
delete(rest, k)
}
}
return
}
2016-05-31 21:34:04 +00:00
func filterPrivateKeys(data map[interface{}]interface{}) map[interface{}]interface{} {
for _, privateKey := range PrivateKeys {
_, data = filterKey(data, strings.Split(privateKey, "."))
}
2016-05-31 21:34:04 +00:00
return data
}
func getOrSetVal(args string, data map[interface{}]interface{}, value interface{}) (interface{}, map[interface{}]interface{}) {
2015-03-15 04:27:04 +00:00
parts := strings.Split(args, ".")
tData := data
if value != nil {
tData = util.MapCopy(data)
}
t := tData
2015-03-15 04:27:04 +00:00
for i, part := range parts {
val, ok := t[part]
2015-03-15 04:27:04 +00:00
last := i+1 == len(parts)
// Reached end, set the value
if last && value != nil {
if s, ok := value.(string); ok {
value = unmarshalOrReturnString(s)
2015-03-15 04:27:04 +00:00
}
t[part] = value
return value, tData
2015-03-15 04:27:04 +00:00
}
// Missing intermediate key, create key
if !last && value != nil && !ok {
newData := map[interface{}]interface{}{}
t[part] = newData
t = newData
2015-03-15 04:27:04 +00:00
continue
}
if !ok {
break
}
if last {
return val, tData
2015-03-15 04:27:04 +00:00
}
newData, ok := val.(map[interface{}]interface{})
if !ok {
break
}
t = newData
2015-03-15 04:27:04 +00:00
}
return "", tData
2015-03-15 04:27:04 +00:00
}
// Replace newlines, colons, and question marks with random strings
2016-09-18 23:35:32 +00:00
// This is done to avoid YAML treating these as special characters
var (
newlineMagicString = "9XsJcx6dR5EERYCC"
colonMagicString = "V0Rc21pIVknMm2rr"
questionMarkMagicString = "FoPL6JLMAaJqKMJT"
2016-09-18 23:35:32 +00:00
)
func reverseReplacement(result interface{}) interface{} {
switch val := result.(type) {
case map[interface{}]interface{}:
for k, v := range val {
val[k] = reverseReplacement(v)
}
return val
case []interface{}:
for i, item := range val {
val[i] = reverseReplacement(item)
}
return val
case string:
2016-09-18 23:35:32 +00:00
val = strings.Replace(val, newlineMagicString, "\n", -1)
val = strings.Replace(val, colonMagicString, ":", -1)
val = strings.Replace(val, questionMarkMagicString, "?", -1)
2016-09-18 23:35:32 +00:00
return val
}
return result
}
func unmarshalOrReturnString(value string) (result interface{}) {
2016-09-18 23:35:32 +00:00
value = strings.Replace(value, "\n", newlineMagicString, -1)
value = strings.Replace(value, ":", colonMagicString, -1)
value = strings.Replace(value, "?", questionMarkMagicString, -1)
if err := yaml.Unmarshal([]byte(value), &result); err != nil {
result = value
}
result = reverseReplacement(result)
return
2015-03-15 04:27:04 +00:00
}
func parseCmdline(cmdLine string) map[interface{}]interface{} {
result := make(map[interface{}]interface{})
outer:
for _, part := range strings.Split(cmdLine, " ") {
if strings.HasPrefix(part, "cc.") {
part = part[3:]
} else if !strings.HasPrefix(part, "rancher.") {
2015-03-15 04:27:04 +00:00
continue
}
var value string
kv := strings.SplitN(part, "=", 2)
if len(kv) == 1 {
value = "true"
} else {
value = kv[1]
}
current := result
keys := strings.Split(kv[0], ".")
2015-03-15 04:27:04 +00:00
for i, key := range keys {
if i == len(keys)-1 {
current[key] = unmarshalOrReturnString(value)
2015-03-15 04:27:04 +00:00
} else {
if obj, ok := current[key]; ok {
if newCurrent, ok := obj.(map[interface{}]interface{}); ok {
current = newCurrent
} else {
continue outer
}
} else {
newCurrent := make(map[interface{}]interface{})
current[key] = newCurrent
current = newCurrent
}
}
}
}
return result
}