interpolation.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package interpolation
  2. import (
  3. "github.com/docker/docker/cli/compose/template"
  4. "github.com/pkg/errors"
  5. )
  6. // Interpolate replaces variables in a string with the values from a mapping
  7. func Interpolate(config map[string]interface{}, section string, mapping template.Mapping) (map[string]interface{}, error) {
  8. out := map[string]interface{}{}
  9. for name, item := range config {
  10. if item == nil {
  11. out[name] = nil
  12. continue
  13. }
  14. mapItem, ok := item.(map[string]interface{})
  15. if !ok {
  16. return nil, errors.Errorf("Invalid type for %s : %T instead of %T", name, item, out)
  17. }
  18. interpolatedItem, err := interpolateSectionItem(name, mapItem, section, mapping)
  19. if err != nil {
  20. return nil, err
  21. }
  22. out[name] = interpolatedItem
  23. }
  24. return out, nil
  25. }
  26. func interpolateSectionItem(
  27. name string,
  28. item map[string]interface{},
  29. section string,
  30. mapping template.Mapping,
  31. ) (map[string]interface{}, error) {
  32. out := map[string]interface{}{}
  33. for key, value := range item {
  34. interpolatedValue, err := recursiveInterpolate(value, mapping)
  35. if err != nil {
  36. return nil, errors.Errorf(
  37. "Invalid interpolation format for %#v option in %s %#v: %#v. You may need to escape any $ with another $.",
  38. key, section, name, err.Template,
  39. )
  40. }
  41. out[key] = interpolatedValue
  42. }
  43. return out, nil
  44. }
  45. func recursiveInterpolate(
  46. value interface{},
  47. mapping template.Mapping,
  48. ) (interface{}, *template.InvalidTemplateError) {
  49. switch value := value.(type) {
  50. case string:
  51. return template.Substitute(value, mapping)
  52. case map[string]interface{}:
  53. out := map[string]interface{}{}
  54. for key, elem := range value {
  55. interpolatedElem, err := recursiveInterpolate(elem, mapping)
  56. if err != nil {
  57. return nil, err
  58. }
  59. out[key] = interpolatedElem
  60. }
  61. return out, nil
  62. case []interface{}:
  63. out := make([]interface{}, len(value))
  64. for i, elem := range value {
  65. interpolatedElem, err := recursiveInterpolate(elem, mapping)
  66. if err != nil {
  67. return nil, err
  68. }
  69. out[i] = interpolatedElem
  70. }
  71. return out, nil
  72. default:
  73. return value, nil
  74. }
  75. }