2015-03-15 04:27:04 +00:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
|
|
|
2016-03-28 23:36:59 +00:00
|
|
|
yaml "github.com/cloudfoundry-incubator/candiedyaml"
|
2015-10-12 11:50:17 +00:00
|
|
|
"github.com/rancher/os/util"
|
2015-03-15 04:27:04 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2015-09-23 11:36:28 +00:00
|
|
|
type CfgFunc func(*CloudConfig) (*CloudConfig, error)
|
|
|
|
|
|
|
|
func ChainCfgFuncs(cfg *CloudConfig, cfgFuncs ...CfgFunc) (*CloudConfig, error) {
|
|
|
|
for i, cfgFunc := range cfgFuncs {
|
|
|
|
log.Debugf("[%d/%d] Starting", i+1, len(cfgFuncs))
|
|
|
|
var err error
|
|
|
|
if cfg, err = cfgFunc(cfg); err != nil {
|
|
|
|
log.Errorf("Failed [%d/%d] %d%%", i+1, len(cfgFuncs), ((i + 1) * 100 / len(cfgFuncs)))
|
|
|
|
return cfg, err
|
|
|
|
}
|
|
|
|
log.Debugf("[%d/%d] Done %d%%", i+1, len(cfgFuncs), ((i + 1) * 100 / len(cfgFuncs)))
|
|
|
|
}
|
|
|
|
return cfg, nil
|
|
|
|
}
|
|
|
|
|
2015-07-29 06:52:15 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
func filterDottedKeys(data map[interface{}]interface{}, keys []string) (filtered, rest map[interface{}]interface{}) {
|
|
|
|
filtered = map[interface{}]interface{}{}
|
|
|
|
rest = util.MapCopy(data)
|
|
|
|
|
|
|
|
for _, key := range keys {
|
|
|
|
f, r := filterKey(data, strings.Split(key, "."))
|
2015-09-23 11:36:28 +00:00
|
|
|
filtered = util.MapsUnion(filtered, f)
|
|
|
|
rest = util.MapsIntersection(rest, r)
|
2015-07-29 06:52:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-09-23 11:36:28 +00:00
|
|
|
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, ".")
|
|
|
|
|
2015-09-23 11:36:28 +00:00
|
|
|
tData := data
|
|
|
|
if value != nil {
|
|
|
|
tData = util.MapCopy(data)
|
|
|
|
}
|
|
|
|
t := tData
|
2015-03-15 04:27:04 +00:00
|
|
|
for i, part := range parts {
|
2015-09-23 11:36:28 +00:00
|
|
|
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 {
|
2016-03-28 23:36:59 +00:00
|
|
|
value = unmarshalOrReturnString(s)
|
2015-03-15 04:27:04 +00:00
|
|
|
}
|
|
|
|
|
2015-09-23 11:36:28 +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{}{}
|
2015-09-23 11:36:28 +00:00
|
|
|
t[part] = newData
|
|
|
|
t = newData
|
2015-03-15 04:27:04 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if last {
|
2015-09-23 11:36:28 +00:00
|
|
|
return val, tData
|
2015-03-15 04:27:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
newData, ok := val.(map[interface{}]interface{})
|
|
|
|
if !ok {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2015-09-23 11:36:28 +00:00
|
|
|
t = newData
|
2015-03-15 04:27:04 +00:00
|
|
|
}
|
|
|
|
|
2015-09-23 11:36:28 +00:00
|
|
|
return "", tData
|
2015-03-15 04:27:04 +00:00
|
|
|
}
|
|
|
|
|
2016-03-28 23:36:59 +00:00
|
|
|
func unmarshalOrReturnString(value string) (result interface{}) {
|
|
|
|
if err := yaml.Unmarshal([]byte(value), &result); err != nil {
|
|
|
|
result = value
|
2015-03-15 04:27:04 +00:00
|
|
|
}
|
2016-03-28 23:36:59 +00:00
|
|
|
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, "rancher.") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var value string
|
|
|
|
kv := strings.SplitN(part, "=", 2)
|
|
|
|
|
|
|
|
if len(kv) == 1 {
|
|
|
|
value = "true"
|
|
|
|
} else {
|
|
|
|
value = kv[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
current := result
|
2015-07-29 06:52:15 +00:00
|
|
|
keys := strings.Split(kv[0], ".")
|
2015-03-15 04:27:04 +00:00
|
|
|
for i, key := range keys {
|
|
|
|
if i == len(keys)-1 {
|
2016-03-28 23:36:59 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debugf("Input obj %v", result)
|
|
|
|
return result
|
|
|
|
}
|