github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/integration/v6/experimental/v3_push_command_test.go (about) 1 package experimental 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "regexp" 9 "time" 10 11 "code.cloudfoundry.org/cli/integration/helpers" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/gbytes" 15 . "github.com/onsi/gomega/gexec" 16 ) 17 18 var _ = Describe("v3-push command", func() { 19 var ( 20 orgName string 21 spaceName string 22 appName string 23 userName string 24 PublicDockerImage = "cloudfoundry/diego-docker-app-custom" 25 ) 26 27 BeforeEach(func() { 28 orgName = helpers.NewOrgName() 29 spaceName = helpers.NewSpaceName() 30 appName = helpers.PrefixedRandomName("app") 31 userName, _ = helpers.GetCredentials() 32 helpers.TurnOffExperimental() 33 }) 34 35 AfterEach(func() { 36 helpers.TurnOnExperimental() 37 }) 38 39 Describe("help", func() { 40 When("--help flag is set", func() { 41 It("Displays command usage to output", func() { 42 session := helpers.CF("v3-push", "--help") 43 Eventually(session).Should(Say("NAME:")) 44 Eventually(session).Should(Say("v3-push - Push a new app or sync changes to an existing app")) 45 Eventually(session).Should(Say("USAGE:")) 46 Eventually(session).Should(Say("cf v3-push APP_NAME \\[-b BUILDPACK\\]\\.\\.\\. \\[-p APP_PATH\\] \\[--no-route\\]")) 47 Eventually(session).Should(Say("cf v3-push APP_NAME --docker-image \\[REGISTRY_HOST:PORT/\\]IMAGE\\[:TAG\\] \\[--docker-username USERNAME\\] \\[--no-route\\]")) 48 Eventually(session).Should(Say("OPTIONS:")) 49 Eventually(session).Should(Say("-b\\s+Custom buildpack by name \\(e\\.g\\. my-buildpack\\) or Git URL \\(e\\.g\\. 'https://github.com/cloudfoundry/java-buildpack.git'\\) or Git URL with a branch or tag \\(e\\.g\\. 'https://github.com/cloudfoundry/java-buildpack\\.git#v3.3.0' for 'v3.3.0' tag\\)\\. To use built-in buildpacks only, specify 'default' or 'null'")) 50 Eventually(session).Should(Say("--docker-image, -o\\s+Docker image to use \\(e\\.g\\. user/docker-image-name\\)")) 51 Eventually(session).Should(Say("--docker-username\\s+Repository username; used with password from environment variable CF_DOCKER_PASSWORD")) 52 Eventually(session).Should(Say("--no-route\\s+Do not map a route to this app")) 53 Eventually(session).Should(Say("-p\\s+Path to app directory or to a zip file of the contents of the app directory")) 54 Eventually(session).Should(Say("ENVIRONMENT:")) 55 Eventually(session).Should(Say("CF_DOCKER_PASSWORD=\\s+Password used for private docker repository")) 56 Eventually(session).Should(Say("CF_STAGING_TIMEOUT=15\\s+Max wait time for buildpack staging, in minutes")) 57 Eventually(session).Should(Say("CF_STARTUP_TIMEOUT=5\\s+Max wait time for app instance startup, in minutes")) 58 59 Eventually(session).Should(Exit(0)) 60 }) 61 }) 62 }) 63 64 When("the app name is not provided", func() { 65 It("tells the user that the app name is required, prints help text, and exits 1", func() { 66 session := helpers.CF("v3-push") 67 68 Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided")) 69 Eventually(session).Should(Say("NAME:")) 70 Eventually(session).Should(Exit(1)) 71 }) 72 }) 73 74 It("displays the experimental warning", func() { 75 session := helpers.CF("v3-push", appName) 76 Eventually(session.Err).Should(Say("This command is in EXPERIMENTAL stage and may change without notice")) 77 Eventually(session).Should(Exit()) 78 }) 79 80 When("the -b flag is not given an arg", func() { 81 It("tells the user that the flag requires an arg, prints help text, and exits 1", func() { 82 session := helpers.CF("v3-push", appName, "-b") 83 84 Eventually(session.Err).Should(Say("Incorrect Usage: expected argument for flag `-b'")) 85 Eventually(session).Should(Say("NAME:")) 86 Eventually(session).Should(Exit(1)) 87 }) 88 }) 89 90 When("the -p flag is not given an arg", func() { 91 It("tells the user that the flag requires an arg, prints help text, and exits 1", func() { 92 session := helpers.CF("v3-push", appName, "-p") 93 94 Eventually(session.Err).Should(Say("Incorrect Usage: expected argument for flag `-p'")) 95 Eventually(session).Should(Say("NAME:")) 96 Eventually(session).Should(Exit(1)) 97 }) 98 }) 99 100 When("the -p flag path does not exist", func() { 101 It("tells the user that the flag requires an arg, prints help text, and exits 1", func() { 102 session := helpers.CF("v3-push", appName, "-p", "path/that/does/not/exist") 103 104 Eventually(session.Err).Should(Say("Incorrect Usage: The specified path 'path/that/does/not/exist' does not exist.")) 105 Eventually(session).Should(Say("NAME:")) 106 Eventually(session).Should(Exit(1)) 107 }) 108 }) 109 110 When("the environment is not setup correctly", func() { 111 When("no API endpoint is set", func() { 112 BeforeEach(func() { 113 helpers.UnsetAPI() 114 }) 115 116 It("fails with no API endpoint set message", func() { 117 session := helpers.CF("v3-push", appName) 118 Eventually(session).Should(Say("FAILED")) 119 Eventually(session.Err).Should(Say("No API endpoint set\\. Use 'cf login' or 'cf api' to target an endpoint\\.")) 120 Eventually(session).Should(Exit(1)) 121 }) 122 }) 123 124 When("not logged in", func() { 125 BeforeEach(func() { 126 helpers.LogoutCF() 127 }) 128 129 It("fails with not logged in message", func() { 130 session := helpers.CF("v3-push", appName) 131 Eventually(session).Should(Say("FAILED")) 132 Eventually(session.Err).Should(Say("Not logged in\\. Use 'cf login' or 'cf login --sso' to log in\\.")) 133 Eventually(session).Should(Exit(1)) 134 }) 135 }) 136 137 When("there is no org set", func() { 138 BeforeEach(func() { 139 helpers.LogoutCF() 140 helpers.LoginCF() 141 }) 142 143 It("fails with no org targeted error message", func() { 144 session := helpers.CF("v3-push", appName) 145 Eventually(session).Should(Say("FAILED")) 146 Eventually(session.Err).Should(Say("No org targeted, use 'cf target -o ORG' to target an org\\.")) 147 Eventually(session).Should(Exit(1)) 148 }) 149 }) 150 151 When("there is no space set", func() { 152 BeforeEach(func() { 153 helpers.LogoutCF() 154 helpers.LoginCF() 155 helpers.TargetOrg(ReadOnlyOrg) 156 }) 157 158 It("fails with no space targeted error message", func() { 159 session := helpers.CF("v3-push", appName) 160 Eventually(session).Should(Say("FAILED")) 161 Eventually(session.Err).Should(Say("No space targeted, use 'cf target -s SPACE' to target a space\\.")) 162 Eventually(session).Should(Exit(1)) 163 }) 164 }) 165 }) 166 167 When("the environment is set up correctly", func() { 168 var domainName string 169 170 BeforeEach(func() { 171 helpers.SetupCF(orgName, spaceName) 172 domainName = helpers.DefaultSharedDomain() 173 }) 174 175 AfterEach(func() { 176 helpers.QuickDeleteOrg(orgName) 177 }) 178 179 When("the app exists", func() { 180 var session *Session 181 BeforeEach(func() { 182 helpers.WithHelloWorldApp(func(appDir string) { 183 Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName)).Should(Exit(0)) 184 }) 185 186 helpers.WithHelloWorldApp(func(appDir string) { 187 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "https://github.com/cloudfoundry/staticfile-buildpack") 188 Eventually(session).Should(Exit(0)) 189 }) 190 }) 191 192 It("pushes the app", func() { 193 Eventually(session).Should(Say("Updating app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 194 Eventually(session).Should(Say("OK")) 195 Eventually(session).Should(Say("")) 196 Eventually(session).Should(Say("Uploading and creating bits package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 197 Eventually(session).Should(Say("OK")) 198 Eventually(session).Should(Say("")) 199 Eventually(session).Should(Say("Stopping app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 200 Eventually(session).Should(Say("OK")) 201 Eventually(session).Should(Say("")) 202 Eventually(session).Should(Say("Staging package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 203 Eventually(session).Should(Say("OK")) 204 Eventually(session).Should(Say("Setting app %s to droplet .+ in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 205 Eventually(session).Should(Say("OK")) 206 Eventually(session).Should(Say("")) 207 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 208 Eventually(session).Should(Say("OK")) 209 Eventually(session).Should(Say("")) 210 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 211 Eventually(session).Should(Say("OK")) 212 Eventually(session).Should(Say("")) 213 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 214 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 215 Eventually(session).Should(Say("")) 216 Eventually(session).Should(Say("name:\\s+%s", appName)) 217 Eventually(session).Should(Say("requested state:\\s+started")) 218 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 219 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 220 221 // TODO: Uncomment when capi sorts out droplet buildpack name/detectoutput 222 // Eventually(session).Should(Say("buildpacks:\\s+https://github.com/cloudfoundry/staticfile-buildpack")) 223 Eventually(session).Should(Say("")) 224 Eventually(session).Should(Say("type:\\s+web")) 225 Eventually(session).Should(Say("instances:\\s+1/1")) 226 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 227 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 228 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 229 }) 230 }) 231 232 When("the app does not already exist", func() { 233 var session *Session 234 235 BeforeEach(func() { 236 helpers.WithHelloWorldApp(func(appDir string) { 237 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName) 238 Eventually(session).Should(Exit(0)) 239 }) 240 }) 241 242 It("pushes the app", func() { 243 Eventually(session).Should(Say("Creating app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 244 Eventually(session).Should(Say("OK")) 245 Eventually(session).Should(Say("")) 246 Eventually(session).Should(Say("Uploading and creating bits package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 247 Eventually(session).Should(Say("OK")) 248 Eventually(session).Should(Say("")) 249 Consistently(session).ShouldNot(Say("Stopping app %s", appName)) 250 Eventually(session).Should(Say("Staging package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 251 Eventually(session).Should(Say("OK")) 252 Eventually(session).Should(Say("Setting app %s to droplet .+ in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 253 Eventually(session).Should(Say("OK")) 254 Eventually(session).Should(Say("")) 255 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 256 Eventually(session).Should(Say("OK")) 257 Eventually(session).Should(Say("")) 258 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 259 Eventually(session).Should(Say("OK")) 260 Eventually(session).Should(Say("")) 261 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 262 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 263 Eventually(session).Should(Say("")) 264 Eventually(session).Should(Say("name:\\s+%s", appName)) 265 Eventually(session).Should(Say("requested state:\\s+started")) 266 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 267 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 268 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 269 Eventually(session).Should(Say("")) 270 Eventually(session).Should(Say("type:\\s+web")) 271 Eventually(session).Should(Say("instances:\\s+1/1")) 272 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 273 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 274 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 275 }) 276 }) 277 278 When("the app crashes", func() { 279 var session *Session 280 281 BeforeEach(func() { 282 helpers.WithCrashingApp(func(appDir string) { 283 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName) 284 Eventually(session).Should(Exit(0)) 285 }) 286 }) 287 288 It("pushes the app", func() { 289 Eventually(session).Should(Say("Creating app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 290 Eventually(session).Should(Say("OK")) 291 Eventually(session).Should(Say("")) 292 Eventually(session).Should(Say("Uploading and creating bits package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 293 Eventually(session).Should(Say("OK")) 294 Eventually(session).Should(Say("")) 295 Consistently(session).ShouldNot(Say("Stopping app %s", appName)) 296 Eventually(session).Should(Say("Staging package for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 297 Eventually(session).Should(Say("OK")) 298 Eventually(session).Should(Say("Setting app %s to droplet .+ in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 299 Eventually(session).Should(Say("OK")) 300 Eventually(session).Should(Say("")) 301 Eventually(session).Should(Say("Mapping routes\\.\\.\\.")) 302 Eventually(session).Should(Say("OK")) 303 Eventually(session).Should(Say("")) 304 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 305 Eventually(session).Should(Say("OK")) 306 Eventually(session).Should(Say("")) 307 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 308 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 309 Eventually(session).Should(Say("")) 310 Eventually(session).Should(Say("name:\\s+%s", appName)) 311 Eventually(session).Should(Say("requested state:\\s+started")) 312 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 313 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 314 Eventually(session).Should(Say("buildpacks:\\s+ruby")) 315 Eventually(session).Should(Say("")) 316 Eventually(session).Should(Say("type:\\s+web")) 317 Eventually(session).Should(Say("instances:\\s+0/1")) 318 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 319 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 320 Eventually(session).Should(Say("#0\\s+crashed\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 321 }) 322 }) 323 324 When("the -p flag is provided", func() { 325 When("the path is a directory", func() { 326 When("the directory contains files", func() { 327 It("pushes the app from the directory", func() { 328 helpers.WithHelloWorldApp(func(appDir string) { 329 session := helpers.CF("v3-push", appName, "-p", appDir) 330 331 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 332 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 333 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 334 Eventually(session).Should(Say("")) 335 Eventually(session).Should(Say("name:\\s+%s", appName)) 336 Eventually(session).Should(Say("requested state:\\s+started")) 337 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 338 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 339 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 340 Eventually(session).Should(Say("")) 341 Eventually(session).Should(Say("type:\\s+web")) 342 Eventually(session).Should(Say("instances:\\s+1/1")) 343 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 344 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 345 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 346 347 Eventually(session).Should(Exit(0)) 348 }) 349 }) 350 }) 351 352 When("the directory is empty", func() { 353 var emptyDir string 354 355 BeforeEach(func() { 356 var err error 357 emptyDir, err = ioutil.TempDir("", "integration-push-path-empty") 358 Expect(err).ToNot(HaveOccurred()) 359 }) 360 361 AfterEach(func() { 362 Expect(os.RemoveAll(emptyDir)).ToNot(HaveOccurred()) 363 }) 364 365 It("returns an error", func() { 366 session := helpers.CF("v3-push", appName, "-p", emptyDir) 367 Eventually(session.Err).Should(Say("No app files found in '%s'", regexp.QuoteMeta(emptyDir))) 368 Eventually(session).Should(Exit(1)) 369 }) 370 }) 371 }) 372 373 When("the path is a zip file", func() { 374 Context("pushing a zip file", func() { 375 var archive string 376 377 BeforeEach(func() { 378 helpers.WithHelloWorldApp(func(appDir string) { 379 tmpfile, err := ioutil.TempFile("", "push-archive-integration") 380 Expect(err).ToNot(HaveOccurred()) 381 archive = tmpfile.Name() 382 Expect(tmpfile.Close()) 383 384 err = helpers.Zipit(appDir, archive, "") 385 Expect(err).ToNot(HaveOccurred()) 386 }) 387 }) 388 389 AfterEach(func() { 390 Expect(os.RemoveAll(archive)).ToNot(HaveOccurred()) 391 }) 392 393 It("pushes the app from the zip file", func() { 394 session := helpers.CF("v3-push", appName, "-p", archive) 395 396 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 397 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 398 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 399 Eventually(session).Should(Say("")) 400 Eventually(session).Should(Say("name:\\s+%s", appName)) 401 Eventually(session).Should(Say("requested state:\\s+started")) 402 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 403 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 404 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 405 Eventually(session).Should(Say("")) 406 Eventually(session).Should(Say("type:\\s+web")) 407 Eventually(session).Should(Say("instances:\\s+1/1")) 408 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 409 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 410 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 411 412 Eventually(session).Should(Exit(0)) 413 }) 414 }) 415 }) 416 417 When("the path is a symlink to a directory", func() { 418 var symlinkPath string 419 420 BeforeEach(func() { 421 tempFile, err := ioutil.TempFile("", "symlink-") 422 Expect(err).ToNot(HaveOccurred()) 423 Expect(tempFile.Close()).To(Succeed()) 424 425 symlinkPath = tempFile.Name() 426 Expect(os.Remove(symlinkPath)).To(Succeed()) 427 }) 428 429 AfterEach(func() { 430 Expect(os.Remove(symlinkPath)).To(Succeed()) 431 }) 432 433 It("creates and uploads the package from the directory", func() { 434 helpers.WithHelloWorldApp(func(appDir string) { 435 Expect(os.Symlink(appDir, symlinkPath)).To(Succeed()) 436 437 session := helpers.CF("v3-push", appName, "-p", symlinkPath) 438 439 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 440 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 441 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 442 Eventually(session).Should(Say("")) 443 Eventually(session).Should(Say("name:\\s+%s", appName)) 444 Eventually(session).Should(Say("requested state:\\s+started")) 445 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 446 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 447 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 448 Eventually(session).Should(Say("")) 449 Eventually(session).Should(Say("type:\\s+web")) 450 Eventually(session).Should(Say("instances:\\s+1/1")) 451 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 452 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 453 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 454 455 Eventually(session).Should(Exit(0)) 456 }) 457 }) 458 }) 459 460 When("the path is a symlink to a zip file", func() { 461 var ( 462 archive string 463 symlinkPath string 464 ) 465 466 BeforeEach(func() { 467 helpers.WithHelloWorldApp(func(appDir string) { 468 tmpfile, err := ioutil.TempFile("", "package-archive-integration") 469 Expect(err).ToNot(HaveOccurred()) 470 archive = tmpfile.Name() 471 Expect(tmpfile.Close()) 472 473 err = helpers.Zipit(appDir, archive, "") 474 Expect(err).ToNot(HaveOccurred()) 475 }) 476 477 tempFile, err := ioutil.TempFile("", "symlink-to-archive-") 478 Expect(err).ToNot(HaveOccurred()) 479 Expect(tempFile.Close()).To(Succeed()) 480 481 symlinkPath = tempFile.Name() 482 Expect(os.Remove(symlinkPath)).To(Succeed()) 483 Expect(os.Symlink(archive, symlinkPath)).To(Succeed()) 484 }) 485 486 AfterEach(func() { 487 Expect(os.Remove(archive)).To(Succeed()) 488 Expect(os.Remove(symlinkPath)).To(Succeed()) 489 }) 490 491 It("creates and uploads the package from the zip file", func() { 492 session := helpers.CF("v3-push", appName, "-p", symlinkPath) 493 494 Eventually(session).Should(Say("Starting app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 495 Eventually(session).Should(Say("Waiting for app to start\\.\\.\\.")) 496 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 497 Eventually(session).Should(Say("")) 498 Eventually(session).Should(Say("name:\\s+%s", appName)) 499 Eventually(session).Should(Say("requested state:\\s+started")) 500 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 501 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 502 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 503 Eventually(session).Should(Say("")) 504 Eventually(session).Should(Say("type:\\s+web")) 505 Eventually(session).Should(Say("instances:\\s+1/1")) 506 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 507 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 508 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 509 510 Eventually(session).Should(Exit(0)) 511 }) 512 }) 513 }) 514 515 When("the --no-route flag is set", func() { 516 var session *Session 517 518 BeforeEach(func() { 519 helpers.WithHelloWorldApp(func(appDir string) { 520 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "--no-route") 521 Eventually(session).Should(Exit(0)) 522 }) 523 }) 524 525 It("does not map any routes to the app", func() { 526 Consistently(session).ShouldNot(Say("Mapping routes\\.\\.\\.")) 527 Eventually(session).Should(Say("name:\\s+%s", appName)) 528 Eventually(session).Should(Say("requested state:\\s+started")) 529 Eventually(session).Should(Say("routes:\\s+\n")) 530 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 531 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 532 Eventually(session).Should(Say("")) 533 Eventually(session).Should(Say("type:\\s+web")) 534 Eventually(session).Should(Say("instances:\\s+1/1")) 535 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 536 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 537 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 538 }) 539 }) 540 541 When("the -b flag is set", func() { 542 var session *Session 543 544 When("pushing a multi-buildpack app", func() { 545 BeforeEach(func() { 546 helpers.WithMultiBuildpackApp(func(appDir string) { 547 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "ruby_buildpack", "-b", "go_buildpack") 548 549 // TODO: uncomment this expectation once capi-release displays all buildpacks on droplet 550 // Story: https://www.pivotaltracker.com/story/show/150425459 551 // Eventually(session).Should(Say("buildpacks:.*ruby_buildpack, go_buildpack")) 552 553 Eventually(session, 10*time.Minute).Should(Exit(0)) 554 }) 555 }) 556 557 It("successfully compiles and runs the app", func() { 558 resp, err := http.Get(fmt.Sprintf("http://%s.%s", appName, helpers.DefaultSharedDomain())) 559 Expect(err).ToNot(HaveOccurred()) 560 Expect(resp.StatusCode).To(Equal(http.StatusOK)) 561 }) 562 }) 563 564 When("resetting the buildpack to default", func() { 565 BeforeEach(func() { 566 helpers.WithHelloWorldApp(func(appDir string) { 567 Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "java_buildpack")).Should(Exit(1)) 568 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "default") 569 Eventually(session).Should(Exit(0)) 570 }) 571 }) 572 573 It("successfully pushes the app", func() { 574 Eventually(session).Should(Say("name:\\s+%s", appName)) 575 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 576 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 577 }) 578 }) 579 580 When("omitting the buildpack", func() { 581 BeforeEach(func() { 582 helpers.WithHelloWorldApp(func(appDir string) { 583 Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "java_buildpack")).Should(Exit(1)) 584 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName) 585 Eventually(session).Should(Exit(1)) 586 }) 587 }) 588 589 It("continues using previously set buildpack", func() { 590 Eventually(session).Should(Say("FAILED")) 591 }) 592 }) 593 594 When("the buildpack is invalid", func() { 595 BeforeEach(func() { 596 helpers.WithHelloWorldApp(func(appDir string) { 597 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "wut") 598 Eventually(session).Should(Exit(1)) 599 }) 600 }) 601 602 It("errors and does not push the app", func() { 603 Consistently(session).ShouldNot(Say("Creating app")) 604 Eventually(session).Should(Say("FAILED")) 605 Eventually(session.Err).Should(Say(`Buildpack "wut" must be an existing admin buildpack or a valid git URI`)) 606 }) 607 }) 608 609 When("the buildpack is valid", func() { 610 BeforeEach(func() { 611 helpers.WithHelloWorldApp(func(appDir string) { 612 session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "v3-push", appName, "-b", "https://github.com/cloudfoundry/staticfile-buildpack") 613 Eventually(session).Should(Exit(0)) 614 }) 615 }) 616 617 It("uses the specified buildpack", func() { 618 Eventually(session).Should(Say("name:\\s+%s", appName)) 619 Eventually(session).Should(Say("requested state:\\s+started")) 620 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 621 Eventually(session).Should(Say("stack:\\s+cflinuxfs")) 622 623 // TODO: Uncomment when capi sorts out droplet buildpack name/detectoutput 624 // Eventually(session).Should(Say("buildpacks:\\s+https://github.com/cloudfoundry/staticfile-buildpack")) 625 Eventually(session).Should(Say("")) 626 Eventually(session).Should(Say("type:\\s+web")) 627 Eventually(session).Should(Say("instances:\\s+1/1")) 628 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 629 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 630 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 631 }) 632 }) 633 }) 634 635 When("the -o flag is set", func() { 636 When("the docker image is valid", func() { 637 It("uses the specified docker image", func() { 638 session := helpers.CF("v3-push", appName, "-o", PublicDockerImage) 639 640 Eventually(session).Should(Say("name:\\s+%s", appName)) 641 Eventually(session).Should(Say("requested state:\\s+started")) 642 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 643 Eventually(session).Should(Say("stack:")) 644 Eventually(session).ShouldNot(Say("buildpacks:")) 645 Eventually(session).Should(Say("docker image:\\s+%s", PublicDockerImage)) 646 Eventually(session).Should(Say("")) 647 Eventually(session).Should(Say("type:\\s+web")) 648 Eventually(session).Should(Say("instances:\\s+1/1")) 649 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 650 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 651 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 652 Eventually(session).Should(Exit(0)) 653 }) 654 }) 655 656 When("the docker image is invalid", func() { 657 It("displays an error and exits 1", func() { 658 session := helpers.CF("v3-push", appName, "-o", "some-invalid-docker-image") 659 Eventually(session).Should(Say("FAILED")) 660 Eventually(session.Err).Should(Say("StagingError - Staging error: staging failed")) 661 Eventually(session).Should(Exit(1)) 662 }) 663 }) 664 665 When("a docker username and password are provided with a private image", func() { 666 var ( 667 privateDockerImage string 668 privateDockerUsername string 669 privateDockerPassword string 670 ) 671 672 BeforeEach(func() { 673 privateDockerImage = os.Getenv("CF_INT_DOCKER_IMAGE") 674 privateDockerUsername = os.Getenv("CF_INT_DOCKER_USERNAME") 675 privateDockerPassword = os.Getenv("CF_INT_DOCKER_PASSWORD") 676 677 if privateDockerImage == "" || privateDockerUsername == "" || privateDockerPassword == "" { 678 Skip("CF_INT_DOCKER_IMAGE, CF_INT_DOCKER_USERNAME, or CF_INT_DOCKER_PASSWORD is not set") 679 } 680 }) 681 682 It("uses the specified private docker image", func() { 683 session := helpers.CustomCF( 684 helpers.CFEnv{ 685 EnvVars: map[string]string{"CF_DOCKER_PASSWORD": privateDockerPassword}, 686 }, 687 "v3-push", "--docker-username", privateDockerUsername, "--docker-image", privateDockerImage, appName, 688 ) 689 690 Eventually(session).Should(Say("name:\\s+%s", appName)) 691 Eventually(session).Should(Say("requested state:\\s+started")) 692 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 693 Eventually(session).Should(Say("stack:")) 694 Eventually(session).ShouldNot(Say("buildpacks:")) 695 Eventually(session).Should(Say("docker image:\\s+%s", privateDockerImage)) 696 Eventually(session).Should(Say("")) 697 Eventually(session).Should(Say("type:\\s+web")) 698 Eventually(session).Should(Say("instances:\\s+1/1")) 699 Eventually(session).Should(Say("memory usage:\\s+\\d+(M|G)")) 700 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk`)) 701 Eventually(session).Should(Say("#0\\s+running\\s+\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} [AP]M")) 702 Eventually(session).Should(Exit(0)) 703 }) 704 }) 705 }) 706 707 Describe("argument combination errors", func() { 708 When("the --docker-username is provided without the -o flag", func() { 709 It("displays an error and exits 1", func() { 710 helpers.WithHelloWorldApp(func(appDir string) { 711 session := helpers.CF("v3-push", appName, "--docker-username", "some-username") 712 Eventually(session).Should(Say("FAILED")) 713 Eventually(session.Err).Should(Say("Incorrect Usage: '--docker-image, -o' and '--docker-username' must be used together.")) 714 Eventually(session).Should(Say("NAME:")) 715 Eventually(session).Should(Exit(1)) 716 }) 717 }) 718 }) 719 720 When("the --docker-username and -p flags are provided together", func() { 721 It("displays an error and exits 1", func() { 722 helpers.WithHelloWorldApp(func(appDir string) { 723 session := helpers.CF("v3-push", appName, "--docker-username", "some-username", "-p", appDir) 724 Eventually(session).Should(Say("FAILED")) 725 Eventually(session.Err).Should(Say("Incorrect Usage: '--docker-image, -o' and '--docker-username' must be used together.")) 726 Eventually(session).Should(Say("NAME:")) 727 Eventually(session).Should(Exit(1)) 728 }) 729 }) 730 }) 731 732 When("the --docker-username is provided without a password", func() { 733 var oldPassword string 734 735 BeforeEach(func() { 736 oldPassword = os.Getenv("CF_DOCKER_PASSWORD") 737 err := os.Unsetenv("CF_DOCKER_PASSWORD") 738 Expect(err).ToNot(HaveOccurred()) 739 }) 740 741 AfterEach(func() { 742 err := os.Setenv("CF_DOCKER_PASSWORD", oldPassword) 743 Expect(err).ToNot(HaveOccurred()) 744 }) 745 746 It("displays an error and exits 1", func() { 747 helpers.WithHelloWorldApp(func(appDir string) { 748 session := helpers.CF("v3-push", appName, "--docker-username", "some-username", "--docker-image", "some-image") 749 Eventually(session).Should(Say("FAILED")) 750 Eventually(session.Err).Should(Say("Environment variable CF_DOCKER_PASSWORD not set\\.")) 751 Eventually(session).Should(Exit(1)) 752 }) 753 }) 754 }) 755 756 When("the -o and -p flags are provided together", func() { 757 It("displays an error and exits 1", func() { 758 helpers.WithHelloWorldApp(func(appDir string) { 759 session := helpers.CF("v3-push", appName, "-o", PublicDockerImage, "-p", appDir) 760 Eventually(session).Should(Say("FAILED")) 761 Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: --docker-image, -o, -p")) 762 Eventually(session).Should(Say("NAME:")) 763 Eventually(session).Should(Exit(1)) 764 }) 765 }) 766 }) 767 768 When("the -o and -b flags are provided together", func() { 769 It("displays an error and exits 1", func() { 770 helpers.WithHelloWorldApp(func(appDir string) { 771 session := helpers.CF("v3-push", appName, "-o", PublicDockerImage, "-b", "some-buildpack") 772 Eventually(session).Should(Say("FAILED")) 773 Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -b, --docker-image, -o")) 774 Eventually(session).Should(Say("NAME:")) 775 Eventually(session).Should(Exit(1)) 776 }) 777 }) 778 }) 779 }) 780 }) 781 })