util.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package utils
  2. import (
  3. "encoding/json"
  4. "sync"
  5. "github.com/Sirupsen/logrus"
  6. yaml "github.com/cloudfoundry-incubator/candiedyaml"
  7. )
  8. // InParallel holds a pool and a waitgroup to execute tasks in parallel and to be able
  9. // to wait for completion of all tasks.
  10. type InParallel struct {
  11. wg sync.WaitGroup
  12. pool sync.Pool
  13. }
  14. // Add runs the specified task in parallel and adds it to the waitGroup.
  15. func (i *InParallel) Add(task func() error) {
  16. i.wg.Add(1)
  17. go func() {
  18. defer i.wg.Done()
  19. err := task()
  20. if err != nil {
  21. i.pool.Put(err)
  22. }
  23. }()
  24. }
  25. // Wait waits for all tasks to complete and returns the latest error encountered if any.
  26. func (i *InParallel) Wait() error {
  27. i.wg.Wait()
  28. obj := i.pool.Get()
  29. if err, ok := obj.(error); ok {
  30. return err
  31. }
  32. return nil
  33. }
  34. // ConvertByJSON converts a struct (src) to another one (target) using json marshalling/unmarshalling.
  35. // If the structure are not compatible, this will throw an error as the unmarshalling will fail.
  36. func ConvertByJSON(src, target interface{}) error {
  37. newBytes, err := json.Marshal(src)
  38. if err != nil {
  39. return err
  40. }
  41. err = json.Unmarshal(newBytes, target)
  42. if err != nil {
  43. logrus.Errorf("Failed to unmarshall: %v\n%s", err, string(newBytes))
  44. }
  45. return err
  46. }
  47. // Convert converts a struct (src) to another one (target) using yaml marshalling/unmarshalling.
  48. // If the structure are not compatible, this will throw an error as the unmarshalling will fail.
  49. func Convert(src, target interface{}) error {
  50. newBytes, err := yaml.Marshal(src)
  51. if err != nil {
  52. return err
  53. }
  54. err = yaml.Unmarshal(newBytes, target)
  55. if err != nil {
  56. logrus.Errorf("Failed to unmarshall: %v\n%s", err, string(newBytes))
  57. }
  58. return err
  59. }
  60. // CopySlice creates an exact copy of the provided string slice
  61. func CopySlice(s []string) []string {
  62. if s == nil {
  63. return nil
  64. }
  65. r := make([]string, len(s))
  66. copy(r, s)
  67. return r
  68. }
  69. // CopyMap creates an exact copy of the provided string-to-string map
  70. func CopyMap(m map[string]string) map[string]string {
  71. if m == nil {
  72. return nil
  73. }
  74. r := map[string]string{}
  75. for k, v := range m {
  76. r[k] = v
  77. }
  78. return r
  79. }
  80. // FilterStringSet accepts a string set `s` (in the form of `map[string]bool`) and a filtering function `f`
  81. // and returns a string set containing only the strings `x` for which `f(x) == true`
  82. func FilterStringSet(s map[string]bool, f func(x string) bool) map[string]bool {
  83. result := map[string]bool{}
  84. for k := range s {
  85. if f(k) {
  86. result[k] = true
  87. }
  88. }
  89. return result
  90. }
  91. // FilterString returns a json representation of the specified map
  92. // that is used as filter for docker.
  93. func FilterString(data map[string][]string) string {
  94. // I can't imagine this would ever fail
  95. bytes, _ := json.Marshal(data)
  96. return string(bytes)
  97. }
  98. // Contains checks if the specified string (key) is present in the specified collection.
  99. func Contains(collection []string, key string) bool {
  100. for _, value := range collection {
  101. if value == key {
  102. return true
  103. }
  104. }
  105. return false
  106. }
  107. // Merge performs a union of two string slices: the result is an unordered slice
  108. // that includes every item from either argument exactly once
  109. func Merge(coll1, coll2 []string) []string {
  110. m := map[string]struct{}{}
  111. for _, v := range append(coll1, coll2...) {
  112. m[v] = struct{}{}
  113. }
  114. r := make([]string, 0, len(m))
  115. for k := range m {
  116. r = append(r, k)
  117. }
  118. return r
  119. }