github.com/willmadison/cli@v6.40.1-0.20181018160101-29d5937903ff+incompatible/integration/v6/push/buildpack_test.go (about) 1 package push 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "math/rand" 7 "os" 8 "path/filepath" 9 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 11 "code.cloudfoundry.org/cli/integration/helpers" 12 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gbytes" 16 . "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("push with different buildpack values", func() { 20 var ( 21 appName string 22 ) 23 24 BeforeEach(func() { 25 appName = helpers.NewAppName() 26 }) 27 28 When("the buildpack flag is provided", func() { 29 When("only one buildpack is provided", func() { 30 BeforeEach(func() { 31 helpers.WithHelloWorldApp(func(dir string) { 32 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 33 PushCommandName, appName, 34 "-b", "binary_buildpack", 35 "--no-start", 36 ) 37 38 Eventually(session).Should(Say("(?m)\\s+buildpacks:\\s+\\+\\s+binary_buildpack")) 39 Eventually(session).Should(Exit(0)) 40 }) 41 }) 42 43 It("pushing a staticfile app with a null buildpack sets buildpack to auto-detected (staticfile)", func() { 44 helpers.WithHelloWorldApp(func(dir string) { 45 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 46 PushCommandName, appName, 47 "-b", "null", 48 ) 49 Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+-\s+binary_buildpack`)) 50 Eventually(session).Should(Say(`buildpacks?:\s+staticfile`)) 51 Eventually(session).Should(Exit(0)) 52 }) 53 }) 54 55 It("pushing a staticfile app with a default buildpack sets buildpack to auto-detected (staticfile)", func() { 56 helpers.WithHelloWorldApp(func(dir string) { 57 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 58 PushCommandName, appName, 59 "-b", "default", 60 ) 61 Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+-\s+binary_buildpack`)) 62 Eventually(session).Should(Say(`buildpacks?:\s+staticfile`)) 63 Eventually(session).Should(Exit(0)) 64 }) 65 }) 66 }) 67 68 When("multiple instances of buildpack are provided", func() { 69 BeforeEach(func() { 70 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 71 }) 72 73 When("the buildpacks do not use the default stack", func() { 74 var ( 75 buildpacks []string 76 nonDefaultStack string 77 ) 78 79 BeforeEach(func() { 80 helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2) 81 nonDefaultStack = helpers.CreateStack() 82 buildpacks = []string{helpers.NewBuildpackName(), helpers.NewBuildpackName()} 83 for _, buildpack := range buildpacks { 84 helpers.SetupBuildpackWithStack(buildpack, nonDefaultStack) 85 } 86 }) 87 88 When("a stack is provided", func() { 89 It("pushes the app successfully with multiple buildpacks using the stack specified", func() { 90 helpers.WithProcfileApp(func(dir string) { 91 tempfile := filepath.Join(dir, "index.html") 92 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 93 Expect(err).ToNot(HaveOccurred()) 94 95 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 96 PushCommandName, appName, 97 "-b", buildpacks[0], "-b", buildpacks[1], "-s", nonDefaultStack, "--no-start", 98 ) 99 Eventually(session).Should(Exit(0)) 100 }) 101 102 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 103 104 Eventually(session).Should(Say(`\s+"buildpacks":\s+`)) 105 Eventually(session).Should(Say(`\s+"%s"`, buildpacks[0])) 106 Eventually(session).Should(Say(`\s+"%s"`, buildpacks[1])) 107 Eventually(session).Should(Say(`"stack":\s+"%s"`, nonDefaultStack)) 108 Eventually(session).Should(Exit(0)) 109 }) 110 }) 111 }) 112 113 When("the app does NOT have existing buildpack configurations", func() { 114 It("pushes the app successfully with multiple buildpacks", func() { 115 helpers.WithProcfileApp(func(dir string) { 116 tempfile := filepath.Join(dir, "index.html") 117 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 118 Expect(err).ToNot(HaveOccurred()) 119 120 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 121 PushCommandName, appName, 122 "-b", "staticfile_buildpack", "-b", "ruby_buildpack", "--no-start", 123 ) 124 Eventually(session).Should(Exit(0)) 125 }) 126 127 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 128 129 Eventually(session).Should(Say(`\s+"buildpacks":\s+`)) 130 Eventually(session).Should(Say(`\s+"staticfile_buildpack"`)) 131 Eventually(session).Should(Say(`\s+"ruby_buildpack"`)) 132 Eventually(session).Should(Exit(0)) 133 }) 134 }) 135 136 When("the app has existing buildpacks", func() { 137 It("pushes the app successfully and overrides the existing buildpacks", func() { 138 helpers.WithHelloWorldApp(func(dir string) { 139 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 140 "applications": []map[string]interface{}{ 141 { 142 "name": appName, 143 "buildpacks": []string{ 144 "ruby_buildpack", 145 "staticfile_buildpack", 146 }, 147 }, 148 }, 149 }) 150 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 151 PushCommandName, appName, 152 "-b", "php_buildpack", "-b", "go_buildpack", "--no-start", 153 ) 154 Eventually(session).Should(Exit(0)) 155 }) 156 157 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 158 159 Eventually(session).Should(Say(`\s+"buildpacks":\s+`)) 160 Eventually(session).Should(Say(`php_buildpack`)) 161 Eventually(session).Should(Say(`go_buildpack`)) 162 Eventually(session).Should(Exit(0)) 163 }) 164 }) 165 166 When("the app has existing `buildpack`", func() { 167 It("pushes the app successfully and overrides the existing buildpacks", func() { 168 helpers.WithHelloWorldApp(func(dir string) { 169 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 170 "applications": []map[string]interface{}{ 171 { 172 "name": appName, 173 "buildpack": "staticfile_buildpack", 174 }, 175 }, 176 }) 177 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 178 PushCommandName, appName, 179 "-b", "php_buildpack", "-b", "go_buildpack", "--no-start", 180 ) 181 Eventually(session).Should(Exit(0)) 182 }) 183 184 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 185 186 Eventually(session).Should(Say(`\s+"buildpacks":\s+`)) 187 Eventually(session).Should(Say(`php_buildpack`)) 188 Eventually(session).Should(Say(`go_buildpack`)) 189 Eventually(session).Should(Exit(0)) 190 }) 191 }) 192 193 When("one of the buildpacks provided is null or default", func() { 194 It("fails and prints an error", func() { 195 helpers.WithProcfileApp(func(dir string) { 196 tempfile := filepath.Join(dir, "index.html") 197 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 198 Expect(err).ToNot(HaveOccurred()) 199 200 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 201 PushCommandName, appName, 202 "-b", "staticfile_buildpack", "-b", "null", "--no-start", 203 ) 204 Eventually(session).Should(Exit(1)) 205 Eventually(session.Err).Should(Say("Multiple buildpacks flags cannot have null/default option.")) 206 }) 207 }) 208 }) 209 }) 210 }) 211 212 When("buildpack is provided via manifest", func() { 213 It("sets buildpack and returns a warning", func() { 214 helpers.WithHelloWorldApp(func(dir string) { 215 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 216 "applications": []map[string]interface{}{ 217 { 218 "name": appName, 219 "buildpack": "staticfile_buildpack", 220 }, 221 }, 222 }) 223 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "no-start") 224 Eventually(session).Should(Say("(?m)\\s+buildpacks:\\s+\\+\\s+staticfile_buildpack")) 225 Eventually(session.Err).Should(Say(`Deprecation warning: Use of 'buildpack'`)) 226 Eventually(session).Should(Exit(0)) 227 }) 228 }) 229 }) 230 231 When("buildpacks (plural) is provided via manifest", func() { 232 When("mutiple buildpacks are specified", func() { 233 BeforeEach(func() { 234 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 235 }) 236 237 It("sets all buildpacks correctly for the pushed app", func() { 238 helpers.WithHelloWorldApp(func(dir string) { 239 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 240 "applications": []map[string]interface{}{ 241 { 242 "name": appName, 243 "buildpacks": []string{ 244 "https://github.com/cloudfoundry/ruby-buildpack", 245 "https://github.com/cloudfoundry/staticfile-buildpack", 246 }, 247 }, 248 }, 249 }) 250 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 251 Eventually(session).Should(Exit(0)) 252 }) 253 254 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 255 256 Eventually(session).Should(Say(`https://github.com/cloudfoundry/ruby-buildpack"`)) 257 Eventually(session).Should(Say(`https://github.com/cloudfoundry/staticfile-buildpack"`)) 258 Eventually(session).Should(Exit(0)) 259 }) 260 }) 261 262 When("only one buildpack is specified", func() { 263 BeforeEach(func() { 264 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 265 }) 266 267 It("sets only one buildpack for the pushed app", func() { 268 helpers.WithHelloWorldApp(func(dir string) { 269 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 270 "applications": []map[string]interface{}{ 271 { 272 "name": appName, 273 "buildpacks": []string{ 274 "https://github.com/cloudfoundry/staticfile-buildpack", 275 }, 276 }, 277 }, 278 }) 279 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 280 Eventually(session).Should(Exit(0)) 281 }) 282 283 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 284 285 // TODO: fix during app command rework to actually test that the second buildpack does not exist 286 Eventually(session).Should(Say(`https://github.com/cloudfoundry/staticfile-buildpack"`)) 287 Eventually(session).Should(Exit(0)) 288 }) 289 }) 290 291 When("empty list of buildpacks is specified", func() { 292 BeforeEach(func() { 293 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 294 }) 295 296 It("autodetects the buildpack", func() { 297 helpers.WithHelloWorldApp(func(dir string) { 298 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "-b", "staticfile_buildpack", "--no-start") 299 Eventually(session).Should(Exit(0)) 300 301 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 302 "applications": []map[string]interface{}{ 303 { 304 "name": appName, 305 "buildpacks": []string{}, 306 }, 307 }, 308 }) 309 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 310 Eventually(session).Should(Exit(0)) 311 }) 312 313 By("displaying an empty buildpacks field") 314 session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName))) 315 316 Eventually(session).Should(Say(`"buildpacks": \[\]`)) 317 Eventually(session).Should(Exit(0)) 318 }) 319 }) 320 321 When("an empty string is specified", func() { 322 It("rasises an error", func() { 323 helpers.WithHelloWorldApp(func(dir string) { 324 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 325 "applications": []map[string]interface{}{ 326 { 327 "name": appName, 328 "buildpacks": nil, 329 }, 330 }, 331 }) 332 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 333 Eventually(session).Should(Exit(1)) 334 Eventually(session.Err).Should(Say("Buildpacks property cannot be an empty string.")) 335 }) 336 }) 337 }) 338 }) 339 340 When("both buildpack and buildpacks are provided via manifest", func() { 341 It("returns an error", func() { 342 helpers.WithHelloWorldApp(func(dir string) { 343 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 344 "applications": []map[string]interface{}{ 345 { 346 "name": appName, 347 "buildpack": "ruby_buildpack", 348 "buildpacks": []string{ 349 "https://github.com/cloudfoundry/staticfile-buildpack", 350 }, 351 }, 352 }, 353 }) 354 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 355 356 Eventually(session).Should(Exit(1)) 357 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: buildpack, buildpacks", appName)) 358 }) 359 }) 360 }) 361 362 When("both buildpacks and docker are provided via manfest", func() { 363 It("returns an error", func() { 364 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 365 helpers.WithHelloWorldApp(func(dir string) { 366 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 367 "applications": []map[string]interface{}{ 368 { 369 "name": appName, 370 "docker": map[string]interface{}{ 371 "image": PublicDockerImage, 372 }, 373 "buildpacks": []string{ 374 "https://github.com/cloudfoundry/staticfile-buildpack", 375 }, 376 }, 377 }, 378 }) 379 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName) 380 381 Eventually(session).Should(Exit(1)) 382 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, buildpacks", appName)) 383 }) 384 }) 385 }) 386 387 When("both buildpacks and docker are provided via flags", func() { 388 It("returns an error", func() { 389 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 390 helpers.WithHelloWorldApp(func(dir string) { 391 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 392 PushCommandName, appName, "-o", PublicDockerImage, "-b", "ruby_buildpack", "-b", "staticfile_buildpack", 393 ) 394 395 Eventually(session).Should(Exit(1)) 396 Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -b, --docker-image, -o")) 397 }) 398 }) 399 }) 400 401 When("buildpack is provided via manifest and droplet is provided via flags", func() { 402 var tempDroplet string 403 404 BeforeEach(func() { 405 f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-") 406 Expect(err).ToNot(HaveOccurred()) 407 Expect(f.Close()).ToNot(HaveOccurred()) 408 409 tempDroplet = f.Name() 410 }) 411 412 AfterEach(func() { 413 Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred()) 414 }) 415 416 It("returns an error", func() { 417 helpers.WithHelloWorldApp(func(dir string) { 418 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 419 "applications": []map[string]interface{}{ 420 { 421 "name": appName, 422 "buildpack": "https://github.com/cloudfoundry/staticfile-buildpack", 423 }, 424 }, 425 }) 426 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "--droplet", tempDroplet) 427 428 Eventually(session).Should(Exit(1)) 429 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpack", appName)) 430 }) 431 }) 432 }) 433 434 When("buildpacks is provided via manifest and droplet is provided via flags", func() { 435 var tempDroplet string 436 437 BeforeEach(func() { 438 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 439 f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-") 440 Expect(err).ToNot(HaveOccurred()) 441 Expect(f.Close()).ToNot(HaveOccurred()) 442 443 tempDroplet = f.Name() 444 }) 445 446 AfterEach(func() { 447 Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred()) 448 }) 449 450 It("returns an error", func() { 451 helpers.WithHelloWorldApp(func(dir string) { 452 helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{ 453 "applications": []map[string]interface{}{ 454 { 455 "name": appName, 456 "buildpacks": []string{ 457 "https://github.com/cloudfoundry/staticfile-buildpack", 458 }, 459 }, 460 }, 461 }) 462 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "--droplet", tempDroplet) 463 464 Eventually(session).Should(Exit(1)) 465 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpacks", appName)) 466 }) 467 }) 468 }) 469 470 When("both buildpack and droplet are provided via flags", func() { 471 var tempDroplet string 472 473 BeforeEach(func() { 474 f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-") 475 Expect(err).ToNot(HaveOccurred()) 476 Expect(f.Close()).ToNot(HaveOccurred()) 477 478 tempDroplet = f.Name() 479 }) 480 481 AfterEach(func() { 482 Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred()) 483 }) 484 485 It("returns an error", func() { 486 helpers.WithHelloWorldApp(func(dir string) { 487 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 488 PushCommandName, appName, "--droplet", tempDroplet, "-b", "staticfile_buildpack", 489 ) 490 491 Eventually(session).Should(Exit(1)) 492 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpack", appName)) 493 }) 494 }) 495 }) 496 497 When("both buildpacks and droplet are provided via flags", func() { 498 var tempDroplet string 499 500 BeforeEach(func() { 501 helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3) 502 f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-") 503 Expect(err).ToNot(HaveOccurred()) 504 Expect(f.Close()).ToNot(HaveOccurred()) 505 506 tempDroplet = f.Name() 507 }) 508 509 AfterEach(func() { 510 Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred()) 511 }) 512 513 It("returns an error", func() { 514 helpers.WithHelloWorldApp(func(dir string) { 515 session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, 516 PushCommandName, appName, "--droplet", tempDroplet, "-b", "ruby_buildpack", "-b", "staticfile_buildpack", 517 ) 518 519 Eventually(session).Should(Exit(1)) 520 Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpacks", appName)) 521 }) 522 }) 523 }) 524 })