github.com/bdwilliams/libcompose@v0.3.1-0.20160826154243-d81a9bdacff0/config/interpolation_test.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"gopkg.in/yaml.v2"
    10  )
    11  
    12  func testInterpolatedLine(t *testing.T, expectedLine, interpolatedLine string, envVariables map[string]string) {
    13  	interpolatedLine, _ = parseLine(interpolatedLine, func(s string) string {
    14  		return envVariables[s]
    15  	})
    16  
    17  	assert.Equal(t, expectedLine, interpolatedLine)
    18  }
    19  
    20  func testInvalidInterpolatedLine(t *testing.T, line string) {
    21  	_, success := parseLine(line, func(string) string {
    22  		return ""
    23  	})
    24  
    25  	assert.Equal(t, false, success)
    26  }
    27  
    28  func TestParseLine(t *testing.T) {
    29  	variables := map[string]string{
    30  		"A":           "ABC",
    31  		"X":           "XYZ",
    32  		"E":           "",
    33  		"lower":       "WORKED",
    34  		"MiXeD":       "WORKED",
    35  		"split_VaLue": "WORKED",
    36  		"9aNumber":    "WORKED",
    37  		"a9Number":    "WORKED",
    38  	}
    39  
    40  	testInterpolatedLine(t, "WORKED", "$lower", variables)
    41  	testInterpolatedLine(t, "WORKED", "${MiXeD}", variables)
    42  	testInterpolatedLine(t, "WORKED", "${split_VaLue}", variables)
    43  	// Starting with a number isn't valid
    44  	testInterpolatedLine(t, "", "$9aNumber", variables)
    45  	testInterpolatedLine(t, "WORKED", "$a9Number", variables)
    46  
    47  	testInterpolatedLine(t, "ABC", "$A", variables)
    48  	testInterpolatedLine(t, "ABC", "${A}", variables)
    49  
    50  	testInterpolatedLine(t, "ABC DE", "$A DE", variables)
    51  	testInterpolatedLine(t, "ABCDE", "${A}DE", variables)
    52  
    53  	testInterpolatedLine(t, "$A", "$$A", variables)
    54  	testInterpolatedLine(t, "${A}", "$${A}", variables)
    55  
    56  	testInterpolatedLine(t, "$ABC", "$$${A}", variables)
    57  	testInterpolatedLine(t, "$ABC", "$$$A", variables)
    58  
    59  	testInterpolatedLine(t, "ABC XYZ", "$A $X", variables)
    60  	testInterpolatedLine(t, "ABCXYZ", "$A$X", variables)
    61  	testInterpolatedLine(t, "ABCXYZ", "${A}${X}", variables)
    62  
    63  	testInterpolatedLine(t, "", "$B", variables)
    64  	testInterpolatedLine(t, "", "${B}", variables)
    65  	testInterpolatedLine(t, "", "$ADE", variables)
    66  
    67  	testInterpolatedLine(t, "", "$E", variables)
    68  	testInterpolatedLine(t, "", "${E}", variables)
    69  
    70  	testInvalidInterpolatedLine(t, "${")
    71  	testInvalidInterpolatedLine(t, "$}")
    72  	testInvalidInterpolatedLine(t, "${}")
    73  	testInvalidInterpolatedLine(t, "${ }")
    74  	testInvalidInterpolatedLine(t, "${A }")
    75  	testInvalidInterpolatedLine(t, "${ A}")
    76  	testInvalidInterpolatedLine(t, "${A!}")
    77  	testInvalidInterpolatedLine(t, "$!")
    78  }
    79  
    80  type MockEnvironmentLookup struct {
    81  	Variables map[string]string
    82  }
    83  
    84  func (m MockEnvironmentLookup) Lookup(key, serviceName string, config *ServiceConfig) []string {
    85  	return []string{fmt.Sprintf("%s=%s", key, m.Variables[key])}
    86  }
    87  
    88  func testInterpolatedConfig(t *testing.T, expectedConfig, interpolatedConfig string, envVariables map[string]string) {
    89  	for k, v := range envVariables {
    90  		os.Setenv(k, v)
    91  	}
    92  
    93  	expectedConfigBytes := []byte(expectedConfig)
    94  	interpolatedConfigBytes := []byte(interpolatedConfig)
    95  
    96  	expectedData := make(RawServiceMap)
    97  	interpolatedData := make(RawServiceMap)
    98  
    99  	yaml.Unmarshal(expectedConfigBytes, &expectedData)
   100  	yaml.Unmarshal(interpolatedConfigBytes, &interpolatedData)
   101  
   102  	_ = Interpolate(MockEnvironmentLookup{envVariables}, &interpolatedData)
   103  
   104  	for k := range envVariables {
   105  		os.Unsetenv(k)
   106  	}
   107  
   108  	assert.Equal(t, expectedData, interpolatedData)
   109  }
   110  
   111  func testInvalidInterpolatedConfig(t *testing.T, interpolatedConfig string) {
   112  	interpolatedConfigBytes := []byte(interpolatedConfig)
   113  	interpolatedData := make(RawServiceMap)
   114  	yaml.Unmarshal(interpolatedConfigBytes, &interpolatedData)
   115  
   116  	err := Interpolate(new(MockEnvironmentLookup), &interpolatedData)
   117  
   118  	assert.NotNil(t, err)
   119  }
   120  
   121  func TestInterpolate(t *testing.T) {
   122  	testInterpolatedConfig(t,
   123  		`web:
   124    # unbracketed name
   125    image: busybox
   126  
   127    # array element
   128    ports:
   129      - "80:8000"
   130  
   131    # dictionary item value
   132    labels:
   133      mylabel: "myvalue"
   134  
   135    # unset value
   136    hostname: "host-"
   137  
   138    # escaped interpolation
   139    command: "${ESCAPED}"`,
   140  		`web:
   141    # unbracketed name
   142    image: $IMAGE
   143  
   144    # array element
   145    ports:
   146      - "${HOST_PORT}:8000"
   147  
   148    # dictionary item value
   149    labels:
   150      mylabel: "${LABEL_VALUE}"
   151  
   152    # unset value
   153    hostname: "host-${UNSET_VALUE}"
   154  
   155    # escaped interpolation
   156    command: "$${ESCAPED}"`, map[string]string{
   157  			"IMAGE":       "busybox",
   158  			"HOST_PORT":   "80",
   159  			"LABEL_VALUE": "myvalue",
   160  		})
   161  
   162  	// Same as above, but testing with equal signs in variables
   163  	testInterpolatedConfig(t,
   164  		`web:
   165    # unbracketed name
   166    image: =busybox
   167  
   168    # array element
   169    ports:
   170      - "=:8000"
   171  
   172    # dictionary item value
   173    labels:
   174      mylabel: "myvalue=="
   175  
   176    # unset value
   177    hostname: "host-"
   178  
   179    # escaped interpolation
   180    command: "${ESCAPED}"`,
   181  		`web:
   182    # unbracketed name
   183    image: $IMAGE
   184  
   185    # array element
   186    ports:
   187      - "${HOST_PORT}:8000"
   188  
   189    # dictionary item value
   190    labels:
   191      mylabel: "${LABEL_VALUE}"
   192  
   193    # unset value
   194    hostname: "host-${UNSET_VALUE}"
   195  
   196    # escaped interpolation
   197    command: "$${ESCAPED}"`, map[string]string{
   198  			"IMAGE":       "=busybox",
   199  			"HOST_PORT":   "=",
   200  			"LABEL_VALUE": "myvalue==",
   201  		})
   202  
   203  	testInvalidInterpolatedConfig(t,
   204  		`web:
   205    image: "${"`)
   206  
   207  	testInvalidInterpolatedConfig(t,
   208  		`web:
   209    image: busybox
   210  
   211    # array element
   212    ports:
   213      - "${}:8000"`)
   214  
   215  	testInvalidInterpolatedConfig(t,
   216  		`web:
   217    image: busybox
   218  
   219    # array element
   220    ports:
   221      - "80:8000"
   222  
   223    # dictionary item value
   224    labels:
   225      mylabel: "${ LABEL_VALUE}"`)
   226  }