github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/cf/manifest/manifest_test.go (about) 1 package manifest_test 2 3 import ( 4 "runtime" 5 "strings" 6 7 "github.com/liamawhite/cli-with-i18n/cf/manifest" 8 "github.com/liamawhite/cli-with-i18n/util/generic" 9 . "github.com/onsi/ginkgo" 10 . "github.com/onsi/gomega" 11 12 . "github.com/liamawhite/cli-with-i18n/util/testhelpers/matchers" 13 ) 14 15 func NewManifest(path string, data generic.Map) (m *manifest.Manifest) { 16 return &manifest.Manifest{Path: path, Data: data} 17 } 18 19 var _ = Describe("Manifests", func() { 20 It("merges global properties into each app's properties", func() { 21 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 22 "instances": "3", 23 "memory": "512M", 24 "applications": []interface{}{ 25 map[interface{}]interface{}{ 26 "name": "bitcoin-miner", 27 "no-route": true, 28 }, 29 }, 30 })) 31 32 apps, err := m.Applications() 33 Expect(err).NotTo(HaveOccurred()) 34 35 Expect(*apps[0].InstanceCount).To(Equal(3)) 36 Expect(*apps[0].Memory).To(Equal(int64(512))) 37 Expect(apps[0].NoRoute).To(BeTrue()) 38 }) 39 40 Context("when there is no applications block", func() { 41 It("returns a single application with the global properties", func() { 42 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 43 "instances": "3", 44 "memory": "512M", 45 })) 46 47 apps, err := m.Applications() 48 Expect(err).NotTo(HaveOccurred()) 49 50 Expect(len(apps)).To(Equal(1)) 51 Expect(*apps[0].InstanceCount).To(Equal(3)) 52 Expect(*apps[0].Memory).To(Equal(int64(512))) 53 }) 54 }) 55 56 It("returns an error when the memory limit doesn't have a unit", func() { 57 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 58 "instances": "3", 59 "memory": "512", 60 "applications": []interface{}{ 61 map[interface{}]interface{}{ 62 "name": "bitcoin-miner", 63 }, 64 }, 65 })) 66 67 _, err := m.Applications() 68 Expect(err).To(HaveOccurred()) 69 Expect(err.Error()).To(ContainSubstring("Invalid value for 'memory': 512")) 70 }) 71 72 It("returns an error when the memory limit is a non-string", func() { 73 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 74 "instances": "3", 75 "memory": 128, 76 "applications": []interface{}{ 77 map[interface{}]interface{}{ 78 "name": "bitcoin-miner", 79 }, 80 }, 81 })) 82 83 _, err := m.Applications() 84 Expect(err).To(HaveOccurred()) 85 Expect(err.Error()).To(ContainSubstring("Invalid value for 'memory': 128")) 86 }) 87 88 It("sets applications' health check timeouts", func() { 89 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 90 "applications": []interface{}{ 91 map[interface{}]interface{}{ 92 "name": "bitcoin-miner", 93 "timeout": "360", 94 }, 95 }, 96 })) 97 98 apps, err := m.Applications() 99 Expect(err).NotTo(HaveOccurred()) 100 Expect(*apps[0].HealthCheckTimeout).To(Equal(360)) 101 }) 102 103 It("allows boolean env var values", func() { 104 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 105 "env": generic.NewMap(map[interface{}]interface{}{ 106 "bar": true, 107 }), 108 })) 109 110 _, err := m.Applications() 111 Expect(err).ToNot(HaveOccurred()) 112 }) 113 114 It("allows nil value for global env if env is present in the app", func() { 115 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 116 "env": nil, 117 "applications": []interface{}{ 118 map[interface{}]interface{}{ 119 "name": "bad app", 120 "env": map[interface{}]interface{}{ 121 "foo": "bar", 122 }, 123 }, 124 }, 125 })) 126 127 apps, err := m.Applications() 128 Expect(err).NotTo(HaveOccurred()) 129 Expect(*apps[0].EnvironmentVars).To(Equal(map[string]interface{}{"foo": "bar"})) 130 }) 131 132 It("does not allow nil value for env in application", func() { 133 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 134 "env": generic.NewMap(map[interface{}]interface{}{ 135 "foo": "bar", 136 }), 137 "applications": []interface{}{ 138 map[interface{}]interface{}{ 139 "name": "bad app", 140 "env": nil, 141 }, 142 }, 143 })) 144 145 _, err := m.Applications() 146 Expect(err).To(HaveOccurred()) 147 Expect(err.Error()).To(ContainSubstring("env should not be null")) 148 }) 149 150 It("does not allow nil values for environment variables", func() { 151 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 152 "env": generic.NewMap(map[interface{}]interface{}{ 153 "bar": nil, 154 }), 155 "applications": []interface{}{ 156 map[interface{}]interface{}{ 157 "name": "bad app", 158 }, 159 }, 160 })) 161 162 _, err := m.Applications() 163 Expect(err).To(HaveOccurred()) 164 Expect(err.Error()).To(ContainSubstring("env var 'bar' should not be null")) 165 }) 166 167 It("returns an empty map when no env was present in the manifest", func() { 168 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 169 "applications": []interface{}{ 170 map[interface{}]interface{}{"name": "no-env-vars"}, 171 }, 172 })) 173 174 apps, err := m.Applications() 175 Expect(err).NotTo(HaveOccurred()) 176 Expect(*apps[0].EnvironmentVars).NotTo(BeNil()) 177 }) 178 179 It("allows applications to have absolute paths", func() { 180 if runtime.GOOS == "windows" { 181 m := NewManifest(`C:\some\path\manifest.yml`, generic.NewMap(map[interface{}]interface{}{ 182 "applications": []interface{}{ 183 map[interface{}]interface{}{ 184 "path": `C:\another\path`, 185 }, 186 }, 187 })) 188 189 apps, err := m.Applications() 190 Expect(err).NotTo(HaveOccurred()) 191 Expect(*apps[0].Path).To(Equal(`C:\another\path`)) 192 } else { 193 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 194 "applications": []interface{}{ 195 map[interface{}]interface{}{ 196 "path": "/another/path-segment", 197 }, 198 }, 199 })) 200 201 apps, err := m.Applications() 202 Expect(err).NotTo(HaveOccurred()) 203 Expect(*apps[0].Path).To(Equal("/another/path-segment")) 204 } 205 }) 206 207 It("expands relative app paths based on the manifest's path", func() { 208 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 209 "applications": []interface{}{ 210 map[interface{}]interface{}{ 211 "path": "../another/path-segment", 212 }, 213 }, 214 })) 215 216 apps, err := m.Applications() 217 Expect(err).NotTo(HaveOccurred()) 218 if runtime.GOOS == "windows" { 219 Expect(*apps[0].Path).To(Equal("\\some\\another\\path-segment")) 220 } else { 221 Expect(*apps[0].Path).To(Equal("/some/another/path-segment")) 222 } 223 }) 224 225 It("returns errors when there are null values", func() { 226 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 227 "applications": []interface{}{ 228 map[interface{}]interface{}{ 229 "disk_quota": nil, 230 "domain": nil, 231 "host": nil, 232 "name": nil, 233 "path": nil, 234 "stack": nil, 235 "memory": nil, 236 "instances": nil, 237 "timeout": nil, 238 "no-route": nil, 239 "no-hostname": nil, 240 "services": nil, 241 "env": nil, 242 "random-route": nil, 243 }, 244 }, 245 })) 246 247 _, err := m.Applications() 248 Expect(err).To(HaveOccurred()) 249 errorSlice := strings.Split(err.Error(), "\n") 250 manifestKeys := []string{"disk_quota", "domain", "host", "name", "path", "stack", 251 "memory", "instances", "timeout", "no-route", "no-hostname", "services", "env", "random-route"} 252 253 for _, key := range manifestKeys { 254 Expect(errorSlice).To(ContainSubstrings([]string{key, "not be null"})) 255 } 256 }) 257 258 It("returns errors when hosts/domains is not valid slice", func() { 259 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 260 "applications": []interface{}{ 261 map[interface{}]interface{}{ 262 "hosts": "bad-value", 263 "domains": []interface{}{"val1", "val2", false, true}, 264 }, 265 }, 266 })) 267 268 _, err := m.Applications() 269 Expect(err).To(HaveOccurred()) 270 errorSlice := strings.Split(err.Error(), "\n") 271 272 Expect(errorSlice).To(ContainSubstrings([]string{"hosts", "to be a list of strings"})) 273 Expect(errorSlice).To(ContainSubstrings([]string{"domains", "to be a list of strings"})) 274 }) 275 276 It("parses known manifest keys", func() { 277 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 278 "applications": []interface{}{ 279 map[interface{}]interface{}{ 280 "buildpack": "my-buildpack", 281 "disk_quota": "512M", 282 "domain": "my-domain", 283 "domains": []interface{}{"domain1.test", "domain2.test"}, 284 "host": "my-hostname", 285 "hosts": []interface{}{"host-1", "host-2"}, 286 "name": "my-app-name", 287 "stack": "my-stack", 288 "memory": "256M", 289 "health-check-type": "none", 290 "instances": 1, 291 "timeout": 11, 292 "no-route": true, 293 "no-hostname": true, 294 "random-route": true, 295 "docker": map[interface{}]interface{}{ 296 "image": "docker.com:3333/docker/docker:some-tag", 297 }, 298 }, 299 }, 300 })) 301 302 apps, err := m.Applications() 303 Expect(err).NotTo(HaveOccurred()) 304 Expect(len(apps)).To(Equal(1)) 305 306 Expect(*apps[0].BuildpackURL).To(Equal("my-buildpack")) 307 Expect(*apps[0].DiskQuota).To(Equal(int64(512))) 308 Expect(apps[0].Domains).To(ConsistOf([]string{"domain1.test", "domain2.test", "my-domain"})) 309 Expect(apps[0].Hosts).To(ConsistOf([]string{"host-1", "host-2", "my-hostname"})) 310 Expect(*apps[0].Name).To(Equal("my-app-name")) 311 Expect(*apps[0].StackName).To(Equal("my-stack")) 312 Expect(*apps[0].HealthCheckType).To(Equal("none")) 313 Expect(*apps[0].Memory).To(Equal(int64(256))) 314 Expect(*apps[0].InstanceCount).To(Equal(1)) 315 Expect(*apps[0].HealthCheckTimeout).To(Equal(11)) 316 Expect(apps[0].NoRoute).To(BeTrue()) 317 Expect(*apps[0].NoHostname).To(BeTrue()) 318 Expect(apps[0].UseRandomRoute).To(BeTrue()) 319 Expect(*apps[0].DockerImage).To(Equal("docker.com:3333/docker/docker:some-tag")) 320 }) 321 322 Context("when the health-check-type is 'http'", func() { 323 Context("when health-check-http-endpoint IS provided", func() { 324 It("sets http-health-check-endpoint to the provided endpoint", func() { 325 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 326 "applications": []interface{}{ 327 map[interface{}]interface{}{ 328 "health-check-type": "http", 329 "health-check-http-endpoint": "/some-endpoint", 330 }, 331 }, 332 })) 333 334 apps, err := m.Applications() 335 Expect(err).NotTo(HaveOccurred()) 336 Expect(len(apps)).To(Equal(1)) 337 338 Expect(*apps[0].HealthCheckType).To(Equal("http")) 339 Expect(*apps[0].HealthCheckHTTPEndpoint).To(Equal("/some-endpoint")) 340 }) 341 }) 342 }) 343 344 It("removes duplicated values in 'hosts' and 'domains'", func() { 345 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 346 "applications": []interface{}{ 347 map[interface{}]interface{}{ 348 "domain": "my-domain", 349 "domains": []interface{}{"my-domain", "domain1.test", "domain1.test", "domain2.test"}, 350 "host": "my-hostname", 351 "hosts": []interface{}{"my-hostname", "host-1", "host-1", "host-2"}, 352 "name": "my-app-name", 353 }, 354 }, 355 })) 356 357 apps, err := m.Applications() 358 Expect(err).NotTo(HaveOccurred()) 359 Expect(len(apps)).To(Equal(1)) 360 361 Expect(len(apps[0].Domains)).To(Equal(3)) 362 Expect(apps[0].Domains).To(ConsistOf([]string{"my-domain", "domain1.test", "domain2.test"})) 363 Expect(len(apps[0].Hosts)).To(Equal(3)) 364 Expect(apps[0].Hosts).To(ConsistOf([]string{"my-hostname", "host-1", "host-2"})) 365 }) 366 367 Context("old-style property syntax", func() { 368 It("returns an error when the manifest contains non-whitelist properties", func() { 369 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 370 "applications": []interface{}{ 371 generic.NewMap(map[interface{}]interface{}{ 372 "env": generic.NewMap(map[interface{}]interface{}{ 373 "bar": "many-${some_property-name}-are-cool", 374 }), 375 }), 376 }, 377 })) 378 379 _, err := m.Applications() 380 Expect(err).To(HaveOccurred()) 381 Expect(err.Error()).To(ContainSubstring("'${some_property-name}'")) 382 }) 383 384 It("replaces the '${random-word} with a combination of 2 random words", func() { 385 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 386 "applications": []interface{}{ 387 generic.NewMap(map[interface{}]interface{}{ 388 "env": generic.NewMap(map[interface{}]interface{}{ 389 "bar": "prefix_${random-word}_suffix", 390 "foo": "some-value", 391 }), 392 }), 393 }, 394 })) 395 396 apps, err := m.Applications() 397 Expect(err).NotTo(HaveOccurred()) 398 Expect((*apps[0].EnvironmentVars)["bar"]).To(MatchRegexp(`prefix_\w+-\w+_suffix`)) 399 Expect((*apps[0].EnvironmentVars)["foo"]).To(Equal("some-value")) 400 401 apps2, _ := m.Applications() 402 Expect((*apps2[0].EnvironmentVars)["bar"]).To(MatchRegexp(`prefix_\w+-\w+_suffix`)) 403 Expect((*apps2[0].EnvironmentVars)["bar"]).NotTo(Equal((*apps[0].EnvironmentVars)["bar"])) 404 }) 405 }) 406 407 It("sets the command and buildpack to blank when their values are null in the manifest", func() { 408 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 409 "applications": []interface{}{ 410 generic.NewMap(map[interface{}]interface{}{ 411 "buildpack": nil, 412 "command": nil, 413 }), 414 }, 415 })) 416 417 apps, err := m.Applications() 418 Expect(err).NotTo(HaveOccurred()) 419 Expect(*apps[0].Command).To(Equal("")) 420 Expect(*apps[0].BuildpackURL).To(Equal("")) 421 }) 422 423 It("sets the command and buildpack to blank when their values are 'default' in the manifest", func() { 424 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 425 "applications": []interface{}{ 426 generic.NewMap(map[interface{}]interface{}{ 427 "command": "default", 428 "buildpack": "default", 429 }), 430 }, 431 })) 432 433 apps, err := m.Applications() 434 Expect(err).NotTo(HaveOccurred()) 435 Expect(*apps[0].Command).To(Equal("")) 436 Expect(*apps[0].BuildpackURL).To(Equal("")) 437 }) 438 439 It("does not set the start command when the manifest doesn't have the 'command' key", func() { 440 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 441 "applications": []interface{}{ 442 map[interface{}]interface{}{}, 443 }, 444 })) 445 446 apps, err := m.Applications() 447 Expect(err).NotTo(HaveOccurred()) 448 Expect(apps[0].Command).To(BeNil()) 449 }) 450 451 It("can build the applications multiple times", func() { 452 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 453 "memory": "254m", 454 "applications": []interface{}{ 455 map[interface{}]interface{}{ 456 "name": "bitcoin-miner", 457 }, 458 map[interface{}]interface{}{ 459 "name": "bitcoin-miner", 460 }, 461 }, 462 })) 463 464 apps1, err := m.Applications() 465 Expect(err).NotTo(HaveOccurred()) 466 467 apps2, err := m.Applications() 468 Expect(err).NotTo(HaveOccurred()) 469 Expect(apps1).To(Equal(apps2)) 470 }) 471 472 Context("parsing app ports", func() { 473 It("parses app ports", func() { 474 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 475 "applications": []interface{}{ 476 map[interface{}]interface{}{ 477 "app-ports": []interface{}{ 478 8080, 479 9090, 480 }, 481 }, 482 }, 483 })) 484 485 apps, err := m.Applications() 486 Expect(err).NotTo(HaveOccurred()) 487 488 Expect(apps[0].AppPorts).NotTo(BeNil()) 489 Expect(*(apps[0].AppPorts)).To(Equal([]int{8080, 9090})) 490 }) 491 492 It("handles omitted field", func() { 493 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 494 "applications": []interface{}{ 495 map[interface{}]interface{}{}, 496 }, 497 })) 498 499 apps, err := m.Applications() 500 Expect(err).NotTo(HaveOccurred()) 501 502 Expect(apps[0].AppPorts).To(BeNil()) 503 }) 504 505 It("handles mixed arrays", func() { 506 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 507 "applications": []interface{}{ 508 map[interface{}]interface{}{ 509 "app-ports": []interface{}{ 510 8080, 511 "potato", 512 }, 513 }, 514 }, 515 })) 516 517 _, err := m.Applications() 518 Expect(err).To(HaveOccurred()) 519 Expect(err.Error()).To(ContainSubstring("Expected app-ports to be a list of integers.")) 520 }) 521 522 It("handles non-array values", func() { 523 m := NewManifest("/some/path", generic.NewMap(map[interface{}]interface{}{ 524 "applications": []interface{}{ 525 map[interface{}]interface{}{ 526 "app-ports": "potato", 527 }, 528 }, 529 })) 530 531 _, err := m.Applications() 532 Expect(err).To(HaveOccurred()) 533 Expect(err.Error()).To(ContainSubstring("Expected app-ports to be a list of integers.")) 534 }) 535 }) 536 537 Context("parsing env vars", func() { 538 It("handles values that are not strings", func() { 539 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 540 "applications": []interface{}{ 541 generic.NewMap(map[interface{}]interface{}{ 542 "env": map[interface{}]interface{}{ 543 "string-key": "value", 544 "int-key": 1, 545 "float-key": 11.1, 546 "large-int-key": 123456789, 547 "large-float-key": 123456789.12345678, 548 "bool-key": false, 549 }, 550 }), 551 }, 552 })) 553 554 app, err := m.Applications() 555 Expect(err).NotTo(HaveOccurred()) 556 557 Expect((*app[0].EnvironmentVars)["string-key"]).To(Equal("value")) 558 Expect((*app[0].EnvironmentVars)["int-key"]).To(Equal("1")) 559 Expect((*app[0].EnvironmentVars)["float-key"]).To(Equal("11.1")) 560 Expect((*app[0].EnvironmentVars)["large-int-key"]).To(Equal("123456789")) 561 Expect((*app[0].EnvironmentVars)["large-float-key"]).To(Equal("123456789.12345678")) 562 Expect((*app[0].EnvironmentVars)["bool-key"]).To(Equal("false")) 563 }) 564 }) 565 566 Context("parsing services", func() { 567 It("can read a list of service instance names", func() { 568 m := NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 569 "services": []interface{}{"service-1", "service-2"}, 570 })) 571 572 app, err := m.Applications() 573 Expect(err).NotTo(HaveOccurred()) 574 575 Expect(app[0].ServicesToBind).To(Equal([]string{"service-1", "service-2"})) 576 }) 577 }) 578 579 Context("when routes are provided", func() { 580 var manifest *manifest.Manifest 581 582 Context("when passed 'routes'", func() { 583 Context("valid 'routes'", func() { 584 BeforeEach(func() { 585 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 586 "applications": []interface{}{ 587 generic.NewMap(map[interface{}]interface{}{ 588 "routes": []interface{}{ 589 map[interface{}]interface{}{"route": "route1.example.com"}, 590 map[interface{}]interface{}{"route": "route2.example.com"}, 591 }, 592 }), 593 }, 594 })) 595 }) 596 597 It("parses routes into app params", func() { 598 apps, err := manifest.Applications() 599 Expect(err).NotTo(HaveOccurred()) 600 Expect(apps).To(HaveLen(1)) 601 602 routes := apps[0].Routes 603 Expect(routes).To(HaveLen(2)) 604 Expect(routes[0].Route).To(Equal("route1.example.com")) 605 Expect(routes[1].Route).To(Equal("route2.example.com")) 606 }) 607 }) 608 609 Context("invalid 'routes'", func() { 610 Context("'routes' is formatted incorrectly", func() { 611 BeforeEach(func() { 612 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 613 "applications": []interface{}{ 614 generic.NewMap(map[interface{}]interface{}{ 615 "routes": []string{}, 616 }), 617 }, 618 })) 619 }) 620 621 It("errors out", func() { 622 _, err := manifest.Applications() 623 Expect(err).To(HaveOccurred()) 624 Expect(err.Error()).To(MatchRegexp("should be a list")) 625 }) 626 }) 627 628 Context("an individual 'route' is formatted incorrectly", func() { 629 BeforeEach(func() { 630 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 631 "applications": []interface{}{ 632 generic.NewMap(map[interface{}]interface{}{ 633 "routes": []interface{}{ 634 map[interface{}]interface{}{"routef": "route1.example.com"}, 635 }, 636 }), 637 }, 638 })) 639 }) 640 641 It("parses routes into app params", func() { 642 _, err := manifest.Applications() 643 Expect(err).To(HaveOccurred()) 644 Expect(err.Error()).To(MatchRegexp("each route in 'routes' must have a 'route' property")) 645 }) 646 }) 647 }) 648 }) 649 650 Context("when there are no routes", func() { 651 BeforeEach(func() { 652 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 653 "applications": []interface{}{ 654 generic.NewMap(map[interface{}]interface{}{ 655 "buildpack": nil, 656 "command": "echo banana", 657 }), 658 }, 659 })) 660 }) 661 662 It("sets routes to be nil", func() { 663 apps, err := manifest.Applications() 664 Expect(err).NotTo(HaveOccurred()) 665 Expect(apps).To(HaveLen(1)) 666 Expect(apps[0].Routes).To(BeNil()) 667 }) 668 }) 669 670 Context("when no-hostname is not specified in the manifest", func() { 671 BeforeEach(func() { 672 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 673 "applications": []interface{}{ 674 generic.NewMap(map[interface{}]interface{}{ 675 "buildpack": nil, 676 "command": "echo banana", 677 }), 678 }, 679 })) 680 }) 681 682 It("sets no-hostname to be nil", func() { 683 apps, err := manifest.Applications() 684 Expect(err).NotTo(HaveOccurred()) 685 Expect(apps).To(HaveLen(1)) 686 Expect(apps[0].NoHostname).To(BeNil()) 687 }) 688 }) 689 690 Context("when no-hostname is specified in the manifest", func() { 691 Context("and it is set to true", func() { 692 Context("and the value is a boolean", func() { 693 BeforeEach(func() { 694 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 695 "applications": []interface{}{ 696 generic.NewMap(map[interface{}]interface{}{ 697 "buildpack": nil, 698 "command": "echo banana", 699 "no-hostname": true, 700 }), 701 }, 702 })) 703 }) 704 705 It("sets no-hostname to be true", func() { 706 apps, err := manifest.Applications() 707 Expect(err).NotTo(HaveOccurred()) 708 Expect(apps).To(HaveLen(1)) 709 Expect(*apps[0].NoHostname).To(BeTrue()) 710 }) 711 }) 712 Context("and the value is a string", func() { 713 BeforeEach(func() { 714 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 715 "applications": []interface{}{ 716 generic.NewMap(map[interface{}]interface{}{ 717 "buildpack": nil, 718 "command": "echo banana", 719 "no-hostname": "true", 720 }), 721 }, 722 })) 723 }) 724 725 It("sets no-hostname to be true", func() { 726 apps, err := manifest.Applications() 727 Expect(err).NotTo(HaveOccurred()) 728 Expect(apps).To(HaveLen(1)) 729 Expect(*apps[0].NoHostname).To(BeTrue()) 730 }) 731 }) 732 }) 733 Context("and it is set to false", func() { 734 BeforeEach(func() { 735 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 736 "applications": []interface{}{ 737 generic.NewMap(map[interface{}]interface{}{ 738 "buildpack": nil, 739 "command": "echo banana", 740 "no-hostname": false, 741 }), 742 }, 743 })) 744 }) 745 It("sets no-hostname to be false", func() { 746 apps, err := manifest.Applications() 747 Expect(err).NotTo(HaveOccurred()) 748 Expect(apps).To(HaveLen(1)) 749 Expect(*apps[0].NoHostname).To(BeFalse()) 750 }) 751 }) 752 }) 753 }) 754 755 Context("when the 'docker' property is not specified", func() { 756 var manifest *manifest.Manifest 757 758 BeforeEach(func() { 759 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 760 "applications": []interface{}{ 761 generic.NewMap(map[interface{}]interface{}{}), 762 }, 763 })) 764 }) 765 766 It("returns a parsed manifest that does not contain any docker fields", func() { 767 apps, err := manifest.Applications() 768 Expect(err).NotTo(HaveOccurred()) 769 Expect(apps).To(HaveLen(1)) 770 Expect(apps[0].DockerImage).To(BeNil()) 771 Expect(apps[0].DockerUsername).To(BeNil()) 772 }) 773 }) 774 775 Context("when the 'docker' property is specified but contains no properties", func() { 776 var manifest *manifest.Manifest 777 778 BeforeEach(func() { 779 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 780 "applications": []interface{}{ 781 generic.NewMap(map[interface{}]interface{}{ 782 "docker": map[interface{}]interface{}{}, 783 }), 784 }, 785 })) 786 }) 787 788 It("returns a parsed manifest that does not contain any docker fields", func() { 789 apps, err := manifest.Applications() 790 Expect(err).NotTo(HaveOccurred()) 791 Expect(apps).To(HaveLen(1)) 792 Expect(apps[0].DockerImage).To(BeNil()) 793 Expect(apps[0].DockerUsername).To(BeNil()) 794 }) 795 }) 796 797 Context("when the 'docker' property is specified", func() { 798 var manifest *manifest.Manifest 799 800 Context("when 'docker' contains an 'image' property", func() { 801 Context("when the 'image' property is not a string", func() { 802 BeforeEach(func() { 803 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 804 "applications": []interface{}{ 805 generic.NewMap(map[interface{}]interface{}{ 806 "docker": map[interface{}]interface{}{ 807 "image": []interface{}{}, 808 }, 809 }), 810 }, 811 })) 812 }) 813 814 It("returns an error", func() { 815 _, err := manifest.Applications() 816 Expect(err.Error()).To(MatchRegexp("'docker.image' must be a string")) 817 }) 818 }) 819 820 Context("when the 'image' property is a string", func() { 821 BeforeEach(func() { 822 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 823 "applications": []interface{}{ 824 generic.NewMap(map[interface{}]interface{}{ 825 "docker": map[interface{}]interface{}{ 826 "image": "docker.com:3333/docker/docker:tag", 827 }, 828 }), 829 }, 830 })) 831 }) 832 833 It("sets DockerImage to the 'image' property value", func() { 834 apps, err := manifest.Applications() 835 Expect(err).NotTo(HaveOccurred()) 836 Expect(apps).To(HaveLen(1)) 837 Expect(*apps[0].DockerImage).To(Equal("docker.com:3333/docker/docker:tag")) 838 }) 839 }) 840 }) 841 842 Context("when 'docker' contains a 'username' property", func() { 843 Context("when 'username' is not a string", func() { 844 BeforeEach(func() { 845 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 846 "applications": []interface{}{ 847 generic.NewMap(map[interface{}]interface{}{ 848 "docker": map[interface{}]interface{}{ 849 "username": []interface{}{}, 850 }, 851 }), 852 }, 853 })) 854 }) 855 856 It("returns an error", func() { 857 _, err := manifest.Applications() 858 Expect(err.Error()).To(MatchRegexp("'docker.username' must be a string")) 859 }) 860 }) 861 862 Context("when 'username' is a string", func() { 863 BeforeEach(func() { 864 manifest = NewManifest("/some/path/manifest.yml", generic.NewMap(map[interface{}]interface{}{ 865 "applications": []interface{}{ 866 generic.NewMap(map[interface{}]interface{}{ 867 "docker": map[interface{}]interface{}{ 868 "username": "some-user", 869 }, 870 }), 871 }, 872 })) 873 }) 874 875 It("sets DockerUsername to the 'username' property value", func() { 876 apps, err := manifest.Applications() 877 Expect(err).NotTo(HaveOccurred()) 878 Expect(apps).To(HaveLen(1)) 879 Expect(*apps[0].DockerUsername).To(Equal("some-user")) 880 }) 881 }) 882 }) 883 }) 884 })