github.com/bdwilliams/libcompose@v0.3.1-0.20160826154243-d81a9bdacff0/config/merge_test.go (about) 1 package config 2 3 import ( 4 "io/ioutil" 5 "testing" 6 ) 7 8 type NullLookup struct { 9 } 10 11 func (n *NullLookup) Lookup(file, relativeTo string) ([]byte, string, error) { 12 return nil, "", nil 13 } 14 15 func (n *NullLookup) ResolvePath(path, inFile string) string { 16 return "" 17 } 18 19 type FileLookup struct { 20 } 21 22 func (f *FileLookup) Lookup(file, relativeTo string) ([]byte, string, error) { 23 bytes, err := ioutil.ReadFile(file) 24 return bytes, file, err 25 } 26 27 func (f *FileLookup) ResolvePath(path, inFile string) string { 28 return "" 29 } 30 31 func TestExtendsInheritImage(t *testing.T) { 32 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 33 parent: 34 image: foo 35 child: 36 extends: 37 service: parent 38 `), nil) 39 if err != nil { 40 t.Fatal(err) 41 } 42 43 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 44 version: '2' 45 services: 46 parent: 47 image: foo 48 child: 49 extends: 50 service: parent 51 `), nil) 52 if err != nil { 53 t.Fatal(err) 54 } 55 56 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 57 parent := config["parent"] 58 child := config["child"] 59 60 if parent.Image != "foo" { 61 t.Fatal("Invalid parent image", parent.Image) 62 } 63 64 t.Logf("%#v", config["child"]) 65 if child.Build.Context != "" { 66 t.Fatalf("Invalid build %#v", child.Build) 67 } 68 69 if child.Image != "foo" { 70 t.Fatal("Invalid child image", child.Image) 71 } 72 } 73 } 74 75 func TestExtendsInheritBuild(t *testing.T) { 76 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 77 parent: 78 build: . 79 child: 80 extends: 81 service: parent 82 `), nil) 83 if err != nil { 84 t.Fatal(err) 85 } 86 87 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 88 version: '2' 89 services: 90 parent: 91 build: 92 context: . 93 child: 94 extends: 95 service: parent 96 `), nil) 97 if err != nil { 98 t.Fatal(err) 99 } 100 101 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 102 parent := config["parent"] 103 child := config["child"] 104 105 if parent.Build.Context != "." { 106 t.Fatal("Invalid build", parent.Build) 107 } 108 109 if child.Build.Context != "." { 110 t.Fatal("Invalid build", child.Build) 111 } 112 113 if child.Image != "" { 114 t.Fatal("Invalid image", child.Image) 115 } 116 } 117 } 118 119 func TestExtendBuildOverImage(t *testing.T) { 120 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 121 parent: 122 image: foo 123 child: 124 build: . 125 extends: 126 service: parent 127 `), nil) 128 if err != nil { 129 t.Fatal(err) 130 } 131 132 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 133 version: '2' 134 services: 135 parent: 136 image: foo 137 child: 138 build: 139 context: . 140 extends: 141 service: parent 142 `), nil) 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 148 parent := config["parent"] 149 child := config["child"] 150 151 if parent.Image != "foo" { 152 t.Fatal("Invalid image", parent.Image) 153 } 154 155 if child.Build.Context != "." { 156 t.Fatal("Invalid build", child.Build) 157 } 158 159 if child.Image != "" { 160 t.Fatal("Invalid image", child.Image) 161 } 162 } 163 } 164 165 func TestExtendImageOverBuild(t *testing.T) { 166 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 167 parent: 168 build: . 169 child: 170 image: foo 171 extends: 172 service: parent 173 `), nil) 174 if err != nil { 175 t.Fatal(err) 176 } 177 178 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 179 version: '2' 180 services: 181 parent: 182 build: 183 context: . 184 child: 185 image: foo 186 extends: 187 service: parent 188 `), nil) 189 if err != nil { 190 t.Fatal(err) 191 } 192 193 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 194 parent := config["parent"] 195 child := config["child"] 196 197 if parent.Image != "" { 198 t.Fatal("Invalid image", parent.Image) 199 } 200 201 if parent.Build.Context != "." { 202 t.Fatal("Invalid build", parent.Build) 203 } 204 205 if child.Build.Context != "" { 206 t.Fatal("Invalid build", child.Build) 207 } 208 209 if child.Image != "foo" { 210 t.Fatal("Invalid image", child.Image) 211 } 212 } 213 } 214 215 func TestMergesEnvFile(t *testing.T) { 216 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &FileLookup{}, "", []byte(` 217 test: 218 image: foo 219 env_file: 220 - testdata/.env 221 `), nil) 222 if err != nil { 223 t.Fatal(err) 224 } 225 226 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &FileLookup{}, "", []byte(` 227 version: '2' 228 services: 229 test: 230 image: foo 231 env_file: 232 - testdata/.env 233 `), nil) 234 if err != nil { 235 t.Fatal(err) 236 } 237 238 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 239 test := config["test"] 240 241 if len(test.Environment) != 2 { 242 t.Fatal("env_file is not merged", test.Environment) 243 } 244 245 for _, environment := range test.Environment { 246 if (environment != "FOO=foo") && (environment != "BAR=bar") { 247 t.Fatal("Empty line and comment should be excluded", environment) 248 } 249 } 250 } 251 } 252 253 func TestRestartNo(t *testing.T) { 254 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 255 test: 256 restart: "no" 257 image: foo 258 `), nil) 259 if err != nil { 260 t.Fatal(err) 261 } 262 263 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 264 version: '2' 265 services: 266 test: 267 restart: "no" 268 image: foo 269 `), nil) 270 if err != nil { 271 t.Fatal(err) 272 } 273 274 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 275 test := config["test"] 276 277 if test.Restart != "no" { 278 t.Fatal("Invalid restart policy", test.Restart) 279 } 280 } 281 } 282 283 func TestRestartAlways(t *testing.T) { 284 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 285 test: 286 restart: always 287 image: foo 288 `), nil) 289 if err != nil { 290 t.Fatal(err) 291 } 292 293 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 294 version: '2' 295 services: 296 test: 297 restart: always 298 image: foo 299 `), nil) 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 305 test := config["test"] 306 307 if test.Restart != "always" { 308 t.Fatal("Invalid restart policy", test.Restart) 309 } 310 } 311 } 312 313 func TestIsValidRemote(t *testing.T) { 314 gitUrls := []string{ 315 "git://github.com/docker/docker", 316 "git@github.com:docker/docker.git", 317 "git@bitbucket.org:atlassianlabs/atlassian-docker.git", 318 "https://github.com/docker/docker.git", 319 "http://github.com/docker/docker.git", 320 "http://github.com/docker/docker.git#branch", 321 "http://github.com/docker/docker.git#:dir", 322 } 323 incompleteGitUrls := []string{ 324 "github.com/docker/docker", 325 } 326 invalidGitUrls := []string{ 327 "http://github.com/docker/docker.git:#branch", 328 } 329 for _, url := range gitUrls { 330 if !IsValidRemote(url) { 331 t.Fatalf("%q should have been a valid remote", url) 332 } 333 } 334 for _, url := range incompleteGitUrls { 335 if !IsValidRemote(url) { 336 t.Fatalf("%q should have been a valid remote", url) 337 } 338 } 339 for _, url := range invalidGitUrls { 340 if !IsValidRemote(url) { 341 t.Fatalf("%q should have been a valid remote", url) 342 } 343 } 344 } 345 346 func preprocess(services RawServiceMap) (RawServiceMap, error) { 347 for name := range services { 348 services[name]["image"] = "foo2" 349 } 350 return services, nil 351 } 352 353 func postprocess(services map[string]*ServiceConfig) (map[string]*ServiceConfig, error) { 354 for name := range services { 355 services[name].ContainerName = "cname" 356 } 357 return services, nil 358 } 359 360 func TestParseOptions(t *testing.T) { 361 parseOptions := ParseOptions{ 362 Interpolate: false, 363 Validate: false, 364 Preprocess: preprocess, 365 Postprocess: postprocess, 366 } 367 368 _, configV1, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 369 test: 370 image: foo 371 labels: 372 x: $X 373 test2: 374 invalid_key: true 375 `), &parseOptions) 376 if err != nil { 377 t.Fatal(err) 378 } 379 380 _, configV2, _, _, err := Merge(NewServiceConfigs(), nil, &NullLookup{}, "", []byte(` 381 version: '2' 382 services: 383 test: 384 image: foo 385 labels: 386 x: $X 387 test2: 388 invalid_key: true 389 `), &parseOptions) 390 if err != nil { 391 t.Fatal(err) 392 } 393 394 for _, config := range []map[string]*ServiceConfig{configV1, configV2} { 395 test := config["test"] 396 397 if test.Image != "foo2" { 398 t.Fatal("Preprocess failed to change image", test.Image) 399 } 400 if test.ContainerName != "cname" { 401 t.Fatal("Postprocess failed to change container name", test.ContainerName) 402 } 403 if test.Labels["x"] != "$X" { 404 t.Fatal("Failed to disable interpolation") 405 } 406 } 407 } 408 409 func TestParseNetworks(t *testing.T) { 410 composeFile := []byte(`networks: 411 public:`) 412 413 networkConfigs, err := ParseNetworks(composeFile) 414 if err != nil { 415 t.Fatal(err) 416 } 417 for key, networkConfig := range networkConfigs { 418 if networkConfig == nil { 419 t.Fatalf("networkConfig %s was nil, shouldn't be", key) 420 } 421 } 422 }