github.com/connyay/libcompose@v0.4.0/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 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 _ = InterpolateRawServiceMap(&interpolatedData, MockEnvironmentLookup{envVariables}) 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 := InterpolateRawServiceMap(&interpolatedData, new(MockEnvironmentLookup)) 117 assert.NotNil(t, err) 118 } 119 120 func TestInterpolate(t *testing.T) { 121 testInterpolatedConfig(t, 122 `web: 123 # unbracketed name 124 image: busybox 125 126 # array element 127 ports: 128 - "80:8000" 129 130 # dictionary item value 131 labels: 132 mylabel: "myvalue" 133 134 # unset value 135 hostname: "host-" 136 137 # escaped interpolation 138 command: "${ESCAPED}"`, 139 `web: 140 # unbracketed name 141 image: $IMAGE 142 143 # array element 144 ports: 145 - "${HOST_PORT}:8000" 146 147 # dictionary item value 148 labels: 149 mylabel: "${LABEL_VALUE}" 150 151 # unset value 152 hostname: "host-${UNSET_VALUE}" 153 154 # escaped interpolation 155 command: "$${ESCAPED}"`, map[string]string{ 156 "IMAGE": "busybox", 157 "HOST_PORT": "80", 158 "LABEL_VALUE": "myvalue", 159 }) 160 161 // Same as above, but testing with equal signs in variables 162 testInterpolatedConfig(t, 163 `web: 164 # unbracketed name 165 image: =busybox 166 167 # array element 168 ports: 169 - "=:8000" 170 171 # dictionary item value 172 labels: 173 mylabel: "myvalue==" 174 175 # unset value 176 hostname: "host-" 177 178 # escaped interpolation 179 command: "${ESCAPED}"`, 180 `web: 181 # unbracketed name 182 image: $IMAGE 183 184 # array element 185 ports: 186 - "${HOST_PORT}:8000" 187 188 # dictionary item value 189 labels: 190 mylabel: "${LABEL_VALUE}" 191 192 # unset value 193 hostname: "host-${UNSET_VALUE}" 194 195 # escaped interpolation 196 command: "$${ESCAPED}"`, map[string]string{ 197 "IMAGE": "=busybox", 198 "HOST_PORT": "=", 199 "LABEL_VALUE": "myvalue==", 200 }) 201 202 testInvalidInterpolatedConfig(t, 203 `web: 204 image: "${"`) 205 206 testInvalidInterpolatedConfig(t, 207 `web: 208 image: busybox 209 210 # array element 211 ports: 212 - "${}:8000"`) 213 214 testInvalidInterpolatedConfig(t, 215 `web: 216 image: busybox 217 218 # array element 219 ports: 220 - "80:8000" 221 222 # dictionary item value 223 labels: 224 mylabel: "${ LABEL_VALUE}"`) 225 }