util.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package util
  2. import (
  3. "archive/tar"
  4. "bufio"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "math/rand"
  10. "net/http"
  11. "os"
  12. "path"
  13. "strings"
  14. "gopkg.in/yaml.v2"
  15. log "github.com/Sirupsen/logrus"
  16. "github.com/docker/docker/pkg/mount"
  17. )
  18. var (
  19. letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
  20. ErrNoNetwork = errors.New("Networking not available to load resource")
  21. ErrNotFound = errors.New("Failed to find resource")
  22. )
  23. func GetOSType() string {
  24. f, err := os.Open("/etc/os-release")
  25. defer f.Close()
  26. if err != nil {
  27. return "busybox"
  28. }
  29. scanner := bufio.NewScanner(f)
  30. for scanner.Scan() {
  31. line := scanner.Text()
  32. if len(line) > 8 && line[:8] == "ID_LIKE=" {
  33. return line[8:]
  34. }
  35. }
  36. return "busybox"
  37. }
  38. func Remount(directory, options string) error {
  39. return mount.Mount("", directory, "", fmt.Sprintf("remount,%s", options))
  40. }
  41. func ExtractTar(archive string, dest string) error {
  42. f, err := os.Open(archive)
  43. if err != nil {
  44. return err
  45. }
  46. defer f.Close()
  47. input := tar.NewReader(f)
  48. for {
  49. header, err := input.Next()
  50. if err == io.EOF {
  51. break
  52. } else if err != nil {
  53. return err
  54. }
  55. if header == nil {
  56. break
  57. }
  58. fileInfo := header.FileInfo()
  59. fileName := path.Join(dest, header.Name)
  60. if fileInfo.IsDir() {
  61. //log.Debugf("DIR : %s", fileName)
  62. err = os.MkdirAll(fileName, fileInfo.Mode())
  63. if err != nil {
  64. return err
  65. }
  66. } else {
  67. //log.Debugf("FILE: %s", fileName)
  68. destFile, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileInfo.Mode())
  69. if err != nil {
  70. return err
  71. }
  72. _, err = io.Copy(destFile, input)
  73. // Not deferring, concerned about holding open too many files
  74. destFile.Close()
  75. if err != nil {
  76. return err
  77. }
  78. }
  79. }
  80. return nil
  81. }
  82. func Contains(values []string, value string) bool {
  83. if len(value) == 0 {
  84. return false
  85. }
  86. for _, i := range values {
  87. if i == value {
  88. return true
  89. }
  90. }
  91. return false
  92. }
  93. type ReturnsErr func() error
  94. func ShortCircuit(funcs ...ReturnsErr) error {
  95. for _, f := range funcs {
  96. err := f()
  97. if err != nil {
  98. return err
  99. }
  100. }
  101. return nil
  102. }
  103. type ErrWriter struct {
  104. w io.Writer
  105. Err error
  106. }
  107. func NewErrorWriter(w io.Writer) *ErrWriter {
  108. return &ErrWriter{
  109. w: w,
  110. }
  111. }
  112. func (e *ErrWriter) Write(buf []byte) *ErrWriter {
  113. if e.Err != nil {
  114. return e
  115. }
  116. _, e.Err = e.w.Write(buf)
  117. return e
  118. }
  119. func RandSeq(n int) string {
  120. b := make([]rune, n)
  121. for i := range b {
  122. b[i] = letters[rand.Intn(len(letters))]
  123. }
  124. return string(b)
  125. }
  126. func Convert(from, to interface{}) error {
  127. bytes, err := yaml.Marshal(from)
  128. if err != nil {
  129. return err
  130. }
  131. return yaml.Unmarshal(bytes, to)
  132. }
  133. func MergeBytes(left, right []byte) ([]byte, error) {
  134. leftMap := make(map[interface{}]interface{})
  135. rightMap := make(map[interface{}]interface{})
  136. err := yaml.Unmarshal(left, &leftMap)
  137. if err != nil {
  138. return nil, err
  139. }
  140. err = yaml.Unmarshal(right, &rightMap)
  141. if err != nil {
  142. return nil, err
  143. }
  144. MergeMaps(leftMap, rightMap)
  145. return yaml.Marshal(leftMap)
  146. }
  147. func MergeMaps(left, right map[interface{}]interface{}) {
  148. for k, v := range right {
  149. merged := false
  150. if existing, ok := left[k]; ok {
  151. if rightMap, ok := v.(map[interface{}]interface{}); ok {
  152. if leftMap, ok := existing.(map[interface{}]interface{}); ok {
  153. merged = true
  154. MergeMaps(leftMap, rightMap)
  155. }
  156. }
  157. }
  158. if !merged {
  159. left[k] = v
  160. }
  161. }
  162. }
  163. func GetServices(urls []string) ([]string, error) {
  164. result := []string{}
  165. for _, url := range urls {
  166. indexUrl := fmt.Sprintf("%s/index.yml", url)
  167. content, err := LoadResource(indexUrl, true, []string{})
  168. if err != nil {
  169. log.Errorf("Failed to load %s: %v", indexUrl, err)
  170. continue
  171. }
  172. services := make(map[string][]string)
  173. err = yaml.Unmarshal(content, &services)
  174. if err != nil {
  175. log.Errorf("Failed to unmarshal %s: %v", indexUrl, err)
  176. continue
  177. }
  178. if list, ok := services["services"]; ok {
  179. result = append(result, list...)
  180. }
  181. }
  182. return result, nil
  183. }
  184. func LoadResource(location string, network bool, urls []string) ([]byte, error) {
  185. var bytes []byte
  186. err := ErrNotFound
  187. if strings.HasPrefix(location, "http:/") || strings.HasPrefix(location, "https:/") {
  188. if !network {
  189. return nil, ErrNoNetwork
  190. }
  191. resp, err := http.Get(location)
  192. if err != nil {
  193. return nil, err
  194. }
  195. if resp.StatusCode != http.StatusOK {
  196. return nil, fmt.Errorf("non-200 http response: %d", resp.StatusCode)
  197. }
  198. defer resp.Body.Close()
  199. return ioutil.ReadAll(resp.Body)
  200. } else if strings.HasPrefix(location, "/") {
  201. return ioutil.ReadFile(location)
  202. } else if len(location) > 0 {
  203. for _, url := range urls {
  204. ymlUrl := fmt.Sprintf("%s/%s/%s.yml", url, location[0:1], location)
  205. bytes, err = LoadResource(ymlUrl, network, []string{})
  206. if err == nil {
  207. log.Debugf("Loaded %s from %s", location, ymlUrl)
  208. return bytes, nil
  209. }
  210. }
  211. }
  212. return nil, err
  213. }
  214. func GetValue(kvPairs []string, key string) string {
  215. if kvPairs == nil {
  216. return ""
  217. }
  218. prefix := key + "="
  219. for _, i := range kvPairs {
  220. if strings.HasPrefix(i, prefix) {
  221. return strings.TrimPrefix(i, prefix)
  222. }
  223. }
  224. return ""
  225. }
  226. func Map2KVPairs(m map[string]string) []string {
  227. r := make([]string, 0, len(m))
  228. for k, v := range m {
  229. r = append(r, k+"="+v)
  230. }
  231. return r
  232. }
  233. func KVPairs2Map(kvs []string) map[string]string {
  234. r := make(map[string]string, len(kvs))
  235. for _, kv := range kvs {
  236. s := strings.SplitN(kv, "=", 2)
  237. r[s[0]] = s[1]
  238. }
  239. return r
  240. }