interpolation.go 1.8 KB

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