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 }