data_funcs.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package config
  2. import (
  3. log "github.com/Sirupsen/logrus"
  4. yaml "github.com/cloudfoundry-incubator/candiedyaml"
  5. "strings"
  6. "github.com/rancher/os/util"
  7. )
  8. type CfgFunc func(*CloudConfig) (*CloudConfig, error)
  9. func ChainCfgFuncs(cfg *CloudConfig, cfgFuncs ...CfgFunc) (*CloudConfig, error) {
  10. for i, cfgFunc := range cfgFuncs {
  11. log.Debugf("[%d/%d] Starting", i+1, len(cfgFuncs))
  12. var err error
  13. if cfg, err = cfgFunc(cfg); err != nil {
  14. log.Errorf("Failed [%d/%d] %d%%", i+1, len(cfgFuncs), ((i + 1) * 100 / len(cfgFuncs)))
  15. return cfg, err
  16. }
  17. log.Debugf("[%d/%d] Done %d%%", i+1, len(cfgFuncs), ((i + 1) * 100 / len(cfgFuncs)))
  18. }
  19. return cfg, nil
  20. }
  21. func filterKey(data map[interface{}]interface{}, key []string) (filtered, rest map[interface{}]interface{}) {
  22. if len(key) == 0 {
  23. return data, map[interface{}]interface{}{}
  24. }
  25. filtered = map[interface{}]interface{}{}
  26. rest = util.MapCopy(data)
  27. k := key[0]
  28. if d, ok := data[k]; ok {
  29. switch d := d.(type) {
  30. case map[interface{}]interface{}:
  31. f, r := filterKey(d, key[1:])
  32. if len(f) != 0 {
  33. filtered[k] = f
  34. }
  35. if len(r) != 0 {
  36. rest[k] = r
  37. } else {
  38. delete(rest, k)
  39. }
  40. default:
  41. filtered[k] = d
  42. delete(rest, k)
  43. }
  44. }
  45. return
  46. }
  47. func filterPrivateKeys(data map[interface{}]interface{}) map[interface{}]interface{} {
  48. for _, privateKey := range PrivateKeys {
  49. _, data = filterKey(data, strings.Split(privateKey, "."))
  50. }
  51. return data
  52. }
  53. func getOrSetVal(args string, data map[interface{}]interface{}, value interface{}) (interface{}, map[interface{}]interface{}) {
  54. parts := strings.Split(args, ".")
  55. tData := data
  56. if value != nil {
  57. tData = util.MapCopy(data)
  58. }
  59. t := tData
  60. for i, part := range parts {
  61. val, ok := t[part]
  62. last := i+1 == len(parts)
  63. // Reached end, set the value
  64. if last && value != nil {
  65. if s, ok := value.(string); ok {
  66. value = unmarshalOrReturnString(s)
  67. }
  68. t[part] = value
  69. return value, tData
  70. }
  71. // Missing intermediate key, create key
  72. if !last && value != nil && !ok {
  73. newData := map[interface{}]interface{}{}
  74. t[part] = newData
  75. t = newData
  76. continue
  77. }
  78. if !ok {
  79. break
  80. }
  81. if last {
  82. return val, tData
  83. }
  84. newData, ok := val.(map[interface{}]interface{})
  85. if !ok {
  86. break
  87. }
  88. t = newData
  89. }
  90. return "", tData
  91. }
  92. // YAML parsers will remove newlines, but we'd like to keep those
  93. // replace newlines with magicString, and then undo after unmarshaling
  94. var magicString = "9XsJcx6dR5EERYCC"
  95. func reverseReplacement(result interface{}) interface{} {
  96. switch val := result.(type) {
  97. case map[interface{}]interface{}:
  98. for k, v := range val {
  99. val[k] = reverseReplacement(v)
  100. }
  101. return val
  102. case []interface{}:
  103. for i, item := range val {
  104. val[i] = reverseReplacement(item)
  105. }
  106. return val
  107. case string:
  108. return strings.Replace(val, magicString, "\n", -1)
  109. }
  110. return result
  111. }
  112. func unmarshalOrReturnString(value string) (result interface{}) {
  113. value = strings.Replace(value, "\n", magicString, -1)
  114. if err := yaml.Unmarshal([]byte(value), &result); err != nil {
  115. result = value
  116. }
  117. result = reverseReplacement(result)
  118. return
  119. }
  120. func parseCmdline(cmdLine string) map[interface{}]interface{} {
  121. result := make(map[interface{}]interface{})
  122. outer:
  123. for _, part := range strings.Split(cmdLine, " ") {
  124. if !strings.HasPrefix(part, "rancher.") {
  125. continue
  126. }
  127. var value string
  128. kv := strings.SplitN(part, "=", 2)
  129. if len(kv) == 1 {
  130. value = "true"
  131. } else {
  132. value = kv[1]
  133. }
  134. current := result
  135. keys := strings.Split(kv[0], ".")
  136. for i, key := range keys {
  137. if i == len(keys)-1 {
  138. current[key] = unmarshalOrReturnString(value)
  139. } else {
  140. if obj, ok := current[key]; ok {
  141. if newCurrent, ok := obj.(map[interface{}]interface{}); ok {
  142. current = newCurrent
  143. } else {
  144. continue outer
  145. }
  146. } else {
  147. newCurrent := make(map[interface{}]interface{})
  148. current[key] = newCurrent
  149. current = newCurrent
  150. }
  151. }
  152. }
  153. }
  154. log.Debugf("Input obj %v", result)
  155. return result
  156. }