github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/integration/push/combination_manifest_and_flag_test.go (about) 1 package push 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "regexp" 8 9 "code.cloudfoundry.org/cli/integration/helpers" 10 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/ginkgo/extensions/table" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/gbytes" 15 . "github.com/onsi/gomega/gexec" 16 ) 17 18 var _ = Describe("push with a simple manifest and flags", func() { 19 var ( 20 appName string 21 ) 22 23 BeforeEach(func() { 24 appName = helpers.NewAppName() 25 }) 26 27 Context("when the app is new", func() { 28 Context("when pushing a single app from the manifest", func() { 29 Context("when the '-f' flag is provided", func() { 30 var ( 31 pathToManifest string // Can be a filepath or a directory with a manifest. 32 ) 33 34 Context("when the manifest file is passed", func() { 35 BeforeEach(func() { 36 tmpFile, err := ioutil.TempFile("", "combination-manifest") 37 Expect(err).ToNot(HaveOccurred()) 38 pathToManifest = tmpFile.Name() 39 Expect(tmpFile.Close()).ToNot(HaveOccurred()) 40 }) 41 42 AfterEach(func() { 43 Expect(os.Remove(pathToManifest)).ToNot(HaveOccurred()) 44 }) 45 46 Context("when pushing the app from the current directory", func() { 47 BeforeEach(func() { 48 helpers.WriteManifest(pathToManifest, map[string]interface{}{ 49 "applications": []map[string]string{ 50 { 51 "name": appName, 52 }, 53 }, 54 }) 55 }) 56 57 It("pushes the app from the current directory and the manifest for app settings", func() { 58 helpers.WithHelloWorldApp(func(dir string) { 59 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-f", pathToManifest) 60 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 61 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 62 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 63 Eventually(session).Should(Say("\\s+routes:")) 64 Eventually(session).Should(Say("(?i)\\+\\s+%s.%s", appName, defaultSharedDomain())) 65 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 66 Eventually(session).Should(Say("Uploading files\\.\\.\\.")) 67 Eventually(session).Should(Say("100.00%")) 68 Eventually(session).Should(Say("Waiting for API to complete processing files\\.\\.\\.")) 69 helpers.ConfirmStagingLogs(session) 70 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 71 Eventually(session).Should(Say("requested state:\\s+started")) 72 Eventually(session).Should(Exit(0)) 73 }) 74 75 session := helpers.CF("app", appName) 76 Eventually(session).Should(Say("name:\\s+%s", appName)) 77 Eventually(session).Should(Exit(0)) 78 }) 79 }) 80 81 Context("when the path to the application is provided in the manifest", func() { 82 It("pushes the app from the path specified in the manifest and uses the manifest for app settings", func() { 83 helpers.WithHelloWorldApp(func(dir string) { 84 helpers.WriteManifest(pathToManifest, map[string]interface{}{ 85 "applications": []map[string]string{ 86 { 87 "name": appName, 88 "path": filepath.Base(dir), 89 }, 90 }, 91 }) 92 93 session := helpers.CF(PushCommandName, "-f", pathToManifest) 94 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 95 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 96 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 97 Eventually(session).Should(Say("\\s+path:\\s+%s", regexp.QuoteMeta(dir))) 98 Eventually(session).Should(Say("requested state:\\s+started")) 99 Eventually(session).Should(Exit(0)) 100 }) 101 102 session := helpers.CF("app", appName) 103 Eventually(session).Should(Say("name:\\s+%s", appName)) 104 Eventually(session).Should(Exit(0)) 105 }) 106 }) 107 }) 108 109 Context("when a directory is passed", func() { 110 var ( 111 ymlFile string 112 yamlFile string 113 ) 114 115 BeforeEach(func() { 116 var err error 117 pathToManifest, err = ioutil.TempDir("", "manifest-integration-") 118 Expect(err).ToNot(HaveOccurred()) 119 }) 120 121 AfterEach(func() { 122 Expect(os.RemoveAll(pathToManifest)).ToNot(HaveOccurred()) 123 }) 124 125 Context("when the directory contains a 'manifest.yml' file", func() { 126 BeforeEach(func() { 127 ymlFile = filepath.Join(pathToManifest, "manifest.yml") 128 helpers.WriteManifest(ymlFile, map[string]interface{}{ 129 "applications": []map[string]interface{}{ 130 { 131 "name": appName, 132 "instances": 2, 133 }, 134 }, 135 }) 136 }) 137 138 It("pushes the app from the given directory and the found 'manifest.yml' for app settings", func() { 139 helpers.WithHelloWorldApp(func(dir string) { 140 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-f", pathToManifest, "--no-start") 141 Eventually(session).Should(Say("Using manifest file %s", regexp.QuoteMeta(ymlFile))) 142 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 143 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 144 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 145 Eventually(session).Should(Say("\\+\\s+instances:\\s+%d", 2)) 146 Eventually(session).Should(Say("\\s+routes:")) 147 Eventually(session).Should(Say("(?i)\\+\\s+%s.%s", appName, defaultSharedDomain())) 148 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 149 Eventually(session).Should(Say("Uploading files\\.\\.\\.")) 150 Eventually(session).Should(Say("100.00%")) 151 Eventually(session).Should(Say("Waiting for API to complete processing files\\.\\.\\.")) 152 Eventually(session).Should(Exit(0)) 153 }) 154 155 session := helpers.CF("app", appName) 156 Eventually(session).Should(Say("name:\\s+%s", appName)) 157 Eventually(session).Should(Exit(0)) 158 }) 159 }) 160 Context("when the directory contains a 'manifest.yaml' file", func() { 161 BeforeEach(func() { 162 yamlFile = filepath.Join(pathToManifest, "manifest.yaml") 163 helpers.WriteManifest(yamlFile, map[string]interface{}{ 164 "applications": []map[string]interface{}{ 165 { 166 "name": appName, 167 "instances": 2, 168 }, 169 }, 170 }) 171 }) 172 173 It("pushes the app from the given directory and the found 'manifest.yaml' for app settings", func() { 174 helpers.WithHelloWorldApp(func(dir string) { 175 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-f", pathToManifest, "--no-start") 176 Eventually(session).Should(Say("Using manifest file %s", regexp.QuoteMeta(yamlFile))) 177 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 178 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 179 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 180 Eventually(session).Should(Say("\\+\\s+instances:\\s+%d", 2)) 181 Eventually(session).Should(Say("\\s+routes:")) 182 Eventually(session).Should(Say("(?i)\\+\\s+%s.%s", appName, defaultSharedDomain())) 183 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 184 Eventually(session).Should(Say("Uploading files\\.\\.\\.")) 185 Eventually(session).Should(Say("100.00%")) 186 Eventually(session).Should(Say("Waiting for API to complete processing files\\.\\.\\.")) 187 Eventually(session).Should(Exit(0)) 188 }) 189 190 session := helpers.CF("app", appName) 191 Eventually(session).Should(Say("name:\\s+%s", appName)) 192 Eventually(session).Should(Exit(0)) 193 }) 194 }) 195 196 Context("when the directory contains both a 'manifest.yml' file and a 'manifest.yaml' file", func() { 197 BeforeEach(func() { 198 ymlFile = filepath.Join(pathToManifest, "manifest.yml") 199 helpers.WriteManifest(ymlFile, map[string]interface{}{ 200 "applications": []map[string]interface{}{ 201 { 202 "name": appName, 203 "instances": 2, 204 }, 205 }, 206 }) 207 208 yamlFile = filepath.Join(pathToManifest, "manifest.yaml") 209 helpers.WriteManifest(yamlFile, map[string]interface{}{ 210 "applications": []map[string]interface{}{ 211 { 212 "name": appName, 213 "instances": 4, 214 }, 215 }, 216 }) 217 }) 218 219 It("pushes the app from the given directory and the found 'manifest.yml' for app settings", func() { 220 helpers.WithHelloWorldApp(func(dir string) { 221 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-f", pathToManifest, "--no-start") 222 Eventually(session).Should(Say("Using manifest file %s", regexp.QuoteMeta(ymlFile))) 223 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 224 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 225 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 226 Eventually(session).Should(Say("\\+\\s+instances:\\s+%d", 2)) 227 Eventually(session).Should(Say("\\s+routes:")) 228 Eventually(session).Should(Say("(?i)\\+\\s+%s.%s", appName, defaultSharedDomain())) 229 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 230 Eventually(session).Should(Say("Uploading files\\.\\.\\.")) 231 Eventually(session).Should(Say("100.00%")) 232 Eventually(session).Should(Say("Waiting for API to complete processing files\\.\\.\\.")) 233 Eventually(session).Should(Exit(0)) 234 }) 235 236 session := helpers.CF("app", appName) 237 Eventually(session).Should(Say("name:\\s+%s", appName)) 238 Eventually(session).Should(Exit(0)) 239 }) 240 }) 241 242 Context("when the directory contains no manifest file", func() { 243 It("returns a no manifest file error", func() { 244 helpers.WithHelloWorldApp(func(dir string) { 245 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-f", pathToManifest, "--no-start") 246 Eventually(session.Err).Should(Say("Could not find 'manifest\\.yml' file in %s", regexp.QuoteMeta(pathToManifest))) 247 Eventually(session).Should(Say("FAILED")) 248 Eventually(session).Should(Exit(1)) 249 }) 250 }) 251 252 }) 253 }) 254 }) 255 256 Context("manifest contains a path and a '-p' is provided", func() { 257 var tempDir string 258 259 BeforeEach(func() { 260 var err error 261 tempDir, err = ioutil.TempDir("", "combination-manifest-with-p") 262 Expect(err).ToNot(HaveOccurred()) 263 264 helpers.WriteManifest(filepath.Join(tempDir, "manifest.yml"), map[string]interface{}{ 265 "applications": []map[string]string{ 266 { 267 "name": appName, 268 "path": "does-not-exist", 269 }, 270 }, 271 }) 272 }) 273 274 AfterEach(func() { 275 Expect(os.RemoveAll(tempDir)).ToNot(HaveOccurred()) 276 }) 277 278 It("overrides the manifest path with the '-p' path", func() { 279 helpers.WithHelloWorldApp(func(dir string) { 280 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, PushCommandName, "-p", dir) 281 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 282 Eventually(session).Should(Say("\\s+path:\\s+%s", regexp.QuoteMeta(dir))) 283 Eventually(session).Should(Say("requested state:\\s+started")) 284 Eventually(session).Should(Exit(0)) 285 }) 286 287 session := helpers.CF("app", appName) 288 Eventually(session).Should(Say("name:\\s+%s", appName)) 289 Eventually(session).Should(Exit(0)) 290 }) 291 }) 292 293 Context("manifest contains a name and a name is provided", func() { 294 It("overrides the manifest name", func() { 295 helpers.WithHelloWorldApp(func(dir string) { 296 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 297 "applications": []map[string]string{ 298 { 299 "name": "earle", 300 }, 301 }, 302 }) 303 304 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 305 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 306 Eventually(session).Should(Say("requested state:\\s+started")) 307 Eventually(session).Should(Exit(0)) 308 }) 309 310 session := helpers.CF("app", appName) 311 Eventually(session).Should(Say("name:\\s+%s", appName)) 312 Eventually(session).Should(Exit(0)) 313 }) 314 }) 315 316 Context("when the --no-manifest flag is passed", func() { 317 It("does not use the provided manifest", func() { 318 helpers.WithHelloWorldApp(func(dir string) { 319 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 320 "applications": []map[string]string{ 321 { 322 "name": "crazy-jerry", 323 }, 324 }, 325 }) 326 327 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "--no-manifest", appName) 328 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 329 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 330 Eventually(session).Should(Say("\\+\\s+name:\\s+%s", appName)) 331 Eventually(session).Should(Say("\\s+routes:")) 332 Eventually(session).Should(Say("(?i)\\+\\s+%s.%s", appName, defaultSharedDomain())) 333 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 334 Eventually(session).Should(Say("Uploading files\\.\\.\\.")) 335 Eventually(session).Should(Say("100.00%")) 336 Eventually(session).Should(Say("Waiting for API to complete processing files\\.\\.\\.")) 337 helpers.ConfirmStagingLogs(session) 338 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 339 Eventually(session).Should(Say("requested state:\\s+started")) 340 Eventually(session).Should(Exit(0)) 341 }) 342 343 session := helpers.CF("app", appName) 344 Eventually(session).Should(Say("name:\\s+%s", appName)) 345 Eventually(session).Should(Exit(0)) 346 }) 347 }) 348 349 Context("when the manifest contains 'routes'", func() { 350 var manifestContents map[string]interface{} 351 352 BeforeEach(func() { 353 manifestContents = map[string]interface{}{ 354 "applications": []map[string]interface{}{ 355 { 356 "name": appName, 357 "routes": []map[string]string{ 358 {"route": "some-route-1"}, 359 {"route": "some-route-2"}, 360 }, 361 }, 362 }, 363 } 364 }) 365 366 Context("when the -d flag is provided", func() { 367 It("returns an error message and exits 1", func() { 368 helpers.WithHelloWorldApp(func(dir string) { 369 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifestContents) 370 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-d", "some-domain.com") 371 372 Eventually(session).ShouldNot(Say("Getting app info")) 373 Eventually(session.Err).Should(Say("The following arguments cannot be used with an app manifest that declares routes using the 'route' attribute: -d, --hostname, -n, --no-hostname, --route-path")) 374 Eventually(session).Should(Exit(1)) 375 }) 376 }) 377 }) 378 379 Context("when the --hostname flag is provided", func() { 380 It("returns an error message and exits 1", func() { 381 helpers.WithHelloWorldApp(func(dir string) { 382 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifestContents) 383 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "--hostname", "some-host") 384 385 Eventually(session).ShouldNot(Say("Getting app info")) 386 Eventually(session.Err).Should(Say("The following arguments cannot be used with an app manifest that declares routes using the 'route' attribute: -d, --hostname, -n, --no-hostname, --route-path")) 387 Eventually(session).Should(Exit(1)) 388 }) 389 }) 390 }) 391 392 Context("when the -n flag is provided", func() { 393 It("returns an error message and exits 1", func() { 394 helpers.WithHelloWorldApp(func(dir string) { 395 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifestContents) 396 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "-n", "some-host") 397 398 Eventually(session).ShouldNot(Say("Getting app info")) 399 Eventually(session.Err).Should(Say("The following arguments cannot be used with an app manifest that declares routes using the 'route' attribute: -d, --hostname, -n, --no-hostname, --route-path")) 400 Eventually(session).Should(Exit(1)) 401 }) 402 }) 403 }) 404 405 Context("when the --no-hostname flag is provided", func() { 406 It("returns an error message and exits 1", func() { 407 helpers.WithHelloWorldApp(func(dir string) { 408 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifestContents) 409 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "--no-hostname") 410 411 Eventually(session).ShouldNot(Say("Getting app info")) 412 Eventually(session.Err).Should(Say("The following arguments cannot be used with an app manifest that declares routes using the 'route' attribute: -d, --hostname, -n, --no-hostname, --route-path")) 413 Eventually(session).Should(Exit(1)) 414 }) 415 }) 416 }) 417 418 Context("when the --route-path flag is provided", func() { 419 It("returns an error message and exits 1", func() { 420 helpers.WithHelloWorldApp(func(dir string) { 421 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), manifestContents) 422 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "--route-path", "some-path") 423 424 Eventually(session).ShouldNot(Say("Getting app info")) 425 Eventually(session.Err).Should(Say("The following arguments cannot be used with an app manifest that declares routes using the 'route' attribute: -d, --hostname, -n, --no-hostname, --route-path")) 426 Eventually(session).Should(Exit(1)) 427 }) 428 }) 429 }) 430 }) 431 }) 432 433 Context("when pushing multiple apps from the manifest", func() { 434 Context("manifest contains multiple apps and '--no-start' is provided", func() { 435 var appName1, appName2 string 436 437 BeforeEach(func() { 438 appName1 = helpers.NewAppName() 439 appName2 = helpers.NewAppName() 440 }) 441 442 It("does not start the apps", func() { 443 helpers.WithHelloWorldApp(func(dir string) { 444 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 445 "applications": []map[string]string{ 446 {"name": appName1}, 447 {"name": appName2}, 448 }, 449 }) 450 451 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, "--no-start") 452 Eventually(session).Should(Say("Getting app info\\.\\.\\.")) 453 Eventually(session).Should(Say("Creating app with these attributes\\.\\.\\.")) 454 Eventually(session).Should(Say("\\s+name:\\s+%s", appName1)) 455 Eventually(session).Should(Say("requested state:\\s+stopped")) 456 Eventually(session).Should(Say("\\s+name:\\s+%s", appName2)) 457 Eventually(session).Should(Say("requested state:\\s+stopped")) 458 Eventually(session).Should(Exit(0)) 459 }) 460 }) 461 }) 462 463 Context("manifest contains multiple apps and a '-p' is provided", func() { 464 var tempDir string 465 466 BeforeEach(func() { 467 var err error 468 tempDir, err = ioutil.TempDir("", "combination-manifest-with-p") 469 Expect(err).ToNot(HaveOccurred()) 470 471 helpers.WriteManifest(filepath.Join(tempDir, "manifest.yml"), map[string]interface{}{ 472 "applications": []map[string]string{ 473 { 474 "name": "name-1", 475 }, 476 { 477 "name": "name-2", 478 }, 479 }, 480 }) 481 }) 482 483 AfterEach(func() { 484 Expect(os.RemoveAll(tempDir)).ToNot(HaveOccurred()) 485 }) 486 487 It("returns an error", func() { 488 helpers.WithHelloWorldApp(func(dir string) { 489 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, PushCommandName, "-p", dir) 490 Eventually(session.Err).Should(Say(regexp.QuoteMeta("Incorrect Usage: Command line flags (except -f and --no-start) cannot be applied when pushing multiple apps from a manifest file."))) 491 Eventually(session).Should(Exit(1)) 492 }) 493 }) 494 }) 495 496 DescribeTable("errors when any flag (except for -f and --no-start) is specified", 497 func(flags ...string) { 498 helpers.WithHelloWorldApp(func(dir string) { 499 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 500 "applications": []map[string]string{ 501 {"name": "some-app"}, 502 {"name": "some-other-app"}, 503 }, 504 }) 505 506 args := append([]string{PushCommandName}, flags...) 507 session := helpers.CustomCF(helpers.CFEnv{ 508 WorkingDirectory: dir, 509 EnvVars: map[string]string{"CF_DOCKER_PASSWORD": "some-password"}, 510 }, args...) 511 Eventually(session.Err).Should(Say(regexp.QuoteMeta("Incorrect Usage: Command line flags (except -f and --no-start) cannot be applied when pushing multiple apps from a manifest file."))) 512 Eventually(session).Should(Exit(1)) 513 }) 514 }, 515 Entry("buildpack", "-b", "somethin"), 516 Entry("domain", "-d", "something"), 517 Entry("hostname", "-n", "something"), 518 Entry("quota", "-k", "100M"), 519 Entry("docker image", "-o", "something"), 520 Entry("docker image and username", "-o", "something", "--docker-username", "something"), 521 Entry("health check timeout", "-t", "10"), 522 Entry("health check type", "-u", "http"), 523 Entry("instances", "-i", "10"), 524 Entry("memory", "-m", "100M"), 525 Entry("no hostname", "--no-hostname"), 526 Entry("no route", "--no-route"), 527 Entry("random route", "--random-route"), 528 Entry("route path", "--route-path", "something"), 529 Entry("stack", "-s", "something"), 530 ) 531 }) 532 }) 533 })