env.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. package engine
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "strconv"
  8. "strings"
  9. )
  10. type Env []string
  11. // Get returns the last value associated with the given key. If there are no
  12. // values associated with the key, Get returns the empty string.
  13. func (env *Env) Get(key string) (value string) {
  14. // not using Map() because of the extra allocations https://github.com/docker/docker/pull/7488#issuecomment-51638315
  15. for _, kv := range *env {
  16. if strings.Index(kv, "=") == -1 {
  17. continue
  18. }
  19. parts := strings.SplitN(kv, "=", 2)
  20. if parts[0] != key {
  21. continue
  22. }
  23. if len(parts) < 2 {
  24. value = ""
  25. } else {
  26. value = parts[1]
  27. }
  28. }
  29. return
  30. }
  31. func (env *Env) Exists(key string) bool {
  32. _, exists := env.Map()[key]
  33. return exists
  34. }
  35. // Len returns the number of keys in the environment.
  36. // Note that len(env) might be different from env.Len(),
  37. // because the same key might be set multiple times.
  38. func (env *Env) Len() int {
  39. return len(env.Map())
  40. }
  41. func (env *Env) Init(src *Env) {
  42. (*env) = make([]string, 0, len(*src))
  43. for _, val := range *src {
  44. (*env) = append((*env), val)
  45. }
  46. }
  47. func (env *Env) GetBool(key string) (value bool) {
  48. s := strings.ToLower(strings.Trim(env.Get(key), " \t"))
  49. if s == "" || s == "0" || s == "no" || s == "false" || s == "none" {
  50. return false
  51. }
  52. return true
  53. }
  54. func (env *Env) SetBool(key string, value bool) {
  55. if value {
  56. env.Set(key, "1")
  57. } else {
  58. env.Set(key, "0")
  59. }
  60. }
  61. func (env *Env) GetInt(key string) int {
  62. return int(env.GetInt64(key))
  63. }
  64. func (env *Env) GetInt64(key string) int64 {
  65. s := strings.Trim(env.Get(key), " \t")
  66. val, err := strconv.ParseInt(s, 10, 64)
  67. if err != nil {
  68. return 0
  69. }
  70. return val
  71. }
  72. func (env *Env) SetInt(key string, value int) {
  73. env.Set(key, fmt.Sprintf("%d", value))
  74. }
  75. func (env *Env) SetInt64(key string, value int64) {
  76. env.Set(key, fmt.Sprintf("%d", value))
  77. }
  78. // Returns nil if key not found
  79. func (env *Env) GetList(key string) []string {
  80. sval := env.Get(key)
  81. if sval == "" {
  82. return nil
  83. }
  84. l := make([]string, 0, 1)
  85. if err := json.Unmarshal([]byte(sval), &l); err != nil {
  86. l = append(l, sval)
  87. }
  88. return l
  89. }
  90. func (env *Env) GetSubEnv(key string) *Env {
  91. sval := env.Get(key)
  92. if sval == "" {
  93. return nil
  94. }
  95. buf := bytes.NewBufferString(sval)
  96. var sub Env
  97. if err := sub.Decode(buf); err != nil {
  98. return nil
  99. }
  100. return &sub
  101. }
  102. func (env *Env) SetSubEnv(key string, sub *Env) error {
  103. var buf bytes.Buffer
  104. if err := sub.Encode(&buf); err != nil {
  105. return err
  106. }
  107. env.Set(key, string(buf.Bytes()))
  108. return nil
  109. }
  110. func (env *Env) GetJson(key string, iface interface{}) error {
  111. sval := env.Get(key)
  112. if sval == "" {
  113. return nil
  114. }
  115. return json.Unmarshal([]byte(sval), iface)
  116. }
  117. func (env *Env) SetJson(key string, value interface{}) error {
  118. sval, err := json.Marshal(value)
  119. if err != nil {
  120. return err
  121. }
  122. env.Set(key, string(sval))
  123. return nil
  124. }
  125. func (env *Env) SetList(key string, value []string) error {
  126. return env.SetJson(key, value)
  127. }
  128. func (env *Env) Set(key, value string) {
  129. *env = append(*env, key+"="+value)
  130. }
  131. func NewDecoder(src io.Reader) *Decoder {
  132. return &Decoder{
  133. json.NewDecoder(src),
  134. }
  135. }
  136. type Decoder struct {
  137. *json.Decoder
  138. }
  139. func (decoder *Decoder) Decode() (*Env, error) {
  140. m := make(map[string]interface{})
  141. if err := decoder.Decoder.Decode(&m); err != nil {
  142. return nil, err
  143. }
  144. env := &Env{}
  145. for key, value := range m {
  146. env.SetAuto(key, value)
  147. }
  148. return env, nil
  149. }
  150. // DecodeEnv decodes `src` as a json dictionary, and adds
  151. // each decoded key-value pair to the environment.
  152. //
  153. // If `src` cannot be decoded as a json dictionary, an error
  154. // is returned.
  155. func (env *Env) Decode(src io.Reader) error {
  156. m := make(map[string]interface{})
  157. if err := json.NewDecoder(src).Decode(&m); err != nil {
  158. return err
  159. }
  160. for k, v := range m {
  161. env.SetAuto(k, v)
  162. }
  163. return nil
  164. }
  165. func (env *Env) SetAuto(k string, v interface{}) {
  166. // Issue 7941 - if the value in the incoming JSON is null then treat it
  167. // as if they never specified the property at all.
  168. if v == nil {
  169. return
  170. }
  171. // FIXME: we fix-convert float values to int, because
  172. // encoding/json decodes integers to float64, but cannot encode them back.
  173. // (See http://golang.org/src/pkg/encoding/json/decode.go#L46)
  174. if fval, ok := v.(float64); ok {
  175. env.SetInt64(k, int64(fval))
  176. } else if sval, ok := v.(string); ok {
  177. env.Set(k, sval)
  178. } else if val, err := json.Marshal(v); err == nil {
  179. env.Set(k, string(val))
  180. } else {
  181. env.Set(k, fmt.Sprintf("%v", v))
  182. }
  183. }
  184. func changeFloats(v interface{}) interface{} {
  185. switch v := v.(type) {
  186. case float64:
  187. return int(v)
  188. case map[string]interface{}:
  189. for key, val := range v {
  190. v[key] = changeFloats(val)
  191. }
  192. case []interface{}:
  193. for idx, val := range v {
  194. v[idx] = changeFloats(val)
  195. }
  196. }
  197. return v
  198. }
  199. func (env *Env) Encode(dst io.Writer) error {
  200. m := make(map[string]interface{})
  201. for k, v := range env.Map() {
  202. var val interface{}
  203. if err := json.Unmarshal([]byte(v), &val); err == nil {
  204. // FIXME: we fix-convert float values to int, because
  205. // encoding/json decodes integers to float64, but cannot encode them back.
  206. // (See http://golang.org/src/pkg/encoding/json/decode.go#L46)
  207. m[k] = changeFloats(val)
  208. } else {
  209. m[k] = v
  210. }
  211. }
  212. if err := json.NewEncoder(dst).Encode(&m); err != nil {
  213. return err
  214. }
  215. return nil
  216. }
  217. func (env *Env) WriteTo(dst io.Writer) (n int64, err error) {
  218. // FIXME: return the number of bytes written to respect io.WriterTo
  219. return 0, env.Encode(dst)
  220. }
  221. func (env *Env) Import(src interface{}) (err error) {
  222. defer func() {
  223. if err != nil {
  224. err = fmt.Errorf("ImportEnv: %s", err)
  225. }
  226. }()
  227. var buf bytes.Buffer
  228. if err := json.NewEncoder(&buf).Encode(src); err != nil {
  229. return err
  230. }
  231. if err := env.Decode(&buf); err != nil {
  232. return err
  233. }
  234. return nil
  235. }
  236. func (env *Env) Map() map[string]string {
  237. m := make(map[string]string)
  238. for _, kv := range *env {
  239. parts := strings.SplitN(kv, "=", 2)
  240. m[parts[0]] = parts[1]
  241. }
  242. return m
  243. }
  244. // MultiMap returns a representation of env as a
  245. // map of string arrays, keyed by string.
  246. // This is the same structure as http headers for example,
  247. // which allow each key to have multiple values.
  248. func (env *Env) MultiMap() map[string][]string {
  249. m := make(map[string][]string)
  250. for _, kv := range *env {
  251. parts := strings.SplitN(kv, "=", 2)
  252. m[parts[0]] = append(m[parts[0]], parts[1])
  253. }
  254. return m
  255. }
  256. // InitMultiMap removes all values in env, then initializes
  257. // new values from the contents of m.
  258. func (env *Env) InitMultiMap(m map[string][]string) {
  259. (*env) = make([]string, 0, len(m))
  260. for k, vals := range m {
  261. for _, v := range vals {
  262. env.Set(k, v)
  263. }
  264. }
  265. }