github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/integration/v7/isolated/service_command_test.go (about) 1 package isolated 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/LukasHeimann/cloudfoundrycli/v8/integration/helpers" 9 "github.com/LukasHeimann/cloudfoundrycli/v8/integration/helpers/servicebrokerstub" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/gbytes" 13 . "github.com/onsi/gomega/gexec" 14 ) 15 16 var _ = Describe("service command", func() { 17 const serviceCommand = "service" 18 19 Describe("help", func() { 20 const serviceInstanceName = "fake-service-instance-name" 21 22 matchHelpMessage := SatisfyAll( 23 Say(`NAME:\n`), 24 Say(fmt.Sprintf(`\s+%s - Show service instance info\n`, serviceCommand)), 25 Say(`\n`), 26 Say(`USAGE:\n`), 27 Say(`\s+cf service SERVICE_INSTANCE\n`), 28 Say(`\n`), 29 Say(`OPTIONS:\n`), 30 Say(`\s+--guid\s+Retrieve and display the given service instances's guid. All other output is suppressed.\n`), 31 Say(`\s+--params\s+Retrieve and display the given service instances's parameters. All other output is suppressed.\n`), 32 Say(`\n`), 33 Say(`SEE ALSO:\n`), 34 Say(`\s+bind-service, rename-service, update-service\n`), 35 Say(`$`), 36 ) 37 38 When("the -h flag is specified", func() { 39 It("succeeds and prints help", func() { 40 session := helpers.CF(serviceCommand, serviceInstanceName, "-h") 41 Eventually(session).Should(Exit(0)) 42 Expect(session.Out).To(matchHelpMessage) 43 }) 44 }) 45 46 When("the service instance name is missing", func() { 47 It("fails with an error and prints help", func() { 48 session := helpers.CF(serviceCommand) 49 Eventually(session).Should(Exit(1)) 50 Expect(session.Err).To(Say("Incorrect Usage: the required argument `SERVICE_INSTANCE` was not provided")) 51 Expect(session.Out).To(matchHelpMessage) 52 }) 53 }) 54 55 When("an extra parameter is specified", func() { 56 It("fails with an error and prints help", func() { 57 session := helpers.CF(serviceCommand, serviceInstanceName, "anotherRandomParameter") 58 Eventually(session).Should(Exit(1)) 59 Expect(session.Err).To(Say(`Incorrect Usage: unexpected argument "anotherRandomParameter"`)) 60 Expect(session.Out).To(SatisfyAll( 61 Say(`FAILED\n\n`), 62 matchHelpMessage, 63 )) 64 }) 65 }) 66 67 When("an extra flag is specified", func() { 68 It("fails with an error and prints help", func() { 69 session := helpers.CF(serviceCommand, serviceInstanceName, "--anotherRandomFlag") 70 Eventually(session).Should(Exit(1)) 71 Expect(session.Err).To(Say("Incorrect Usage: unknown flag `anotherRandomFlag'")) 72 Expect(session.Out).To(matchHelpMessage) 73 }) 74 }) 75 }) 76 77 When("environment is not set up", func() { 78 It("displays an error and exits 1", func() { 79 helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, serviceCommand, "serviceInstanceName") 80 }) 81 }) 82 83 When("user is logged in and targeting a space", func() { 84 var ( 85 serviceInstanceName string 86 orgName string 87 spaceName string 88 ) 89 90 BeforeEach(func() { 91 orgName = helpers.NewOrgName() 92 spaceName = helpers.NewSpaceName() 93 helpers.SetupCF(orgName, spaceName) 94 95 serviceInstanceName = helpers.NewServiceInstanceName() 96 }) 97 98 AfterEach(func() { 99 helpers.QuickDeleteOrg(orgName) 100 }) 101 102 When("the service instance is user-provided", func() { 103 const ( 104 routeServiceURL = "https://route.com" 105 syslogURL = "https://syslog.com" 106 tags = "foo, bar" 107 ) 108 109 BeforeEach(func() { 110 command := []string{ 111 "create-user-provided-service", serviceInstanceName, 112 "-r", routeServiceURL, 113 "-l", syslogURL, 114 "-t", tags, 115 } 116 Eventually(helpers.CF(command...)).Should(Exit(0)) 117 }) 118 119 It("can show the GUID", func() { 120 session := helpers.CF(serviceCommand, serviceInstanceName, "--guid") 121 Eventually(session).Should(Exit(0)) 122 Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length") 123 }) 124 125 It("can show the service instance details", func() { 126 session := helpers.CF(serviceCommand, serviceInstanceName) 127 Eventually(session).Should(Exit(0)) 128 129 username, _ := helpers.GetCredentials() 130 Expect(session).To(SatisfyAll( 131 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 132 Say(`\n`), 133 Say(`name:\s+%s\n`, serviceInstanceName), 134 Say(`guid:\s+\S{36}\n`), 135 Say(`type:\s+user-provided`), 136 Say(`tags:\s+%s\n`, tags), 137 Say(`route service url:\s+%s\n`, routeServiceURL), 138 Say(`syslog drain url:\s+%s\n`, syslogURL), 139 Say(`\n`), 140 Say(`Showing status of last operation:\n`), 141 Say(`status:\s+create succeeded\n`), 142 Say(`message:\s+Operation succeeded\n`), 143 Say(`started:\s+%s\n`, helpers.TimestampRegex), 144 Say(`updated:\s+%s\n`, helpers.TimestampRegex), 145 Say(`\n`), 146 Say(`Showing bound apps:\n`), 147 Say(`There are no bound apps for this service instance\.\n`), 148 )) 149 }) 150 151 When("bound to apps", func() { 152 var ( 153 appName1 string 154 appName2 string 155 bindingName1 string 156 bindingName2 string 157 ) 158 159 BeforeEach(func() { 160 appName1 = helpers.PrefixedRandomName("APP1") 161 appName2 = helpers.PrefixedRandomName("APP2") 162 bindingName1 = helpers.RandomName() 163 bindingName2 = helpers.RandomName() 164 165 helpers.WithHelloWorldApp(func(appDir string) { 166 Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 167 Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 168 }) 169 Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1)).Should(Exit(0)) 170 Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2)).Should(Exit(0)) 171 }) 172 173 It("displays the bound apps", func() { 174 session := helpers.CF(serviceCommand, serviceInstanceName, "-v") 175 Eventually(session).Should(Exit(0)) 176 177 Expect(session).To(SatisfyAll( 178 Say(`Showing bound apps:\n`), 179 Say(`name\s+binding name\s+status\s+message\n`), 180 Say(`%s\s+%s\s+create succeeded\s*\n`, appName1, bindingName1), 181 Say(`%s\s+%s\s+create succeeded\s*\n`, appName2, bindingName2), 182 )) 183 }) 184 }) 185 186 When("--params is requested", func() { 187 When("service instance parameters have been set", func() { 188 It("reports the service instance parameters JSON", func() { 189 session := helpers.CF(serviceCommand, serviceInstanceName, "--params") 190 Eventually(session).Should(Exit(1)) 191 192 Eventually(session.Err).Should(Say("This service does not support fetching service instance parameters.")) 193 }) 194 }) 195 }) 196 197 }) 198 199 When("the service instance is managed by a broker", func() { 200 const ( 201 testPollingInterval = time.Second 202 testTimeout = time.Minute 203 ) 204 205 var broker *servicebrokerstub.ServiceBrokerStub 206 207 AfterEach(func() { 208 broker.Forget() 209 }) 210 211 When("created successfully", func() { 212 const tags = "foo, bar" 213 214 BeforeEach(func() { 215 broker = servicebrokerstub.New().WithAsyncDelay(time.Nanosecond).EnableServiceAccess() 216 217 helpers.CreateManagedServiceInstance( 218 broker.FirstServiceOfferingName(), 219 broker.FirstServicePlanName(), 220 serviceInstanceName, 221 "-t", tags, 222 ) 223 }) 224 225 It("can show the service instance details", func() { 226 session := helpers.CF(serviceCommand, serviceInstanceName) 227 Eventually(session).Should(Exit(0)) 228 229 username, _ := helpers.GetCredentials() 230 Expect(session).To(SatisfyAll( 231 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 232 Say(`\n`), 233 Say(`name:\s+%s\n`, serviceInstanceName), 234 Say(`guid:\s+\S+\n`), 235 Say(`type:\s+managed`), 236 Say(`broker:\s+%s`, broker.Name), 237 Say(`offering:\s+%s`, broker.FirstServiceOfferingName()), 238 Say(`plan:\s+%s`, broker.FirstServicePlanName()), 239 Say(`tags:\s+%s\n`, tags), 240 Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")), 241 Say(`description:\s+%s\n`, broker.Services[0].Description), 242 Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL), 243 Say(`dashboard url:\s+http://example.com\n`), 244 Say(`\n`), 245 Say(`Showing status of last operation:\n`), 246 Say(`status:\s+create succeeded\n`), 247 Say(`message:\s+very happy service\n`), 248 Say(`started:\s+%s\n`, helpers.TimestampRegex), 249 Say(`updated:\s+%s\n`, helpers.TimestampRegex), 250 Say(`\n`), 251 Say(`Showing bound apps:\n`), 252 Say(`There are no bound apps for this service instance\.\n`), 253 Say(`\n`), 254 Say(`Showing sharing info:\n`), 255 Say(`This service instance is not currently being shared.`), 256 Say(`\n`), 257 Say(`Upgrades are not supported by this broker.\n`), 258 )) 259 }) 260 }) 261 262 When("creation is in progress", func() { 263 const ( 264 tags = "foo, bar" 265 brokerAsyncDelay = time.Second 266 ) 267 268 BeforeEach(func() { 269 broker = servicebrokerstub.New().WithAsyncDelay(brokerAsyncDelay).EnableServiceAccess() 270 command := []string{ 271 "create-service", 272 broker.FirstServiceOfferingName(), 273 broker.FirstServicePlanName(), 274 serviceInstanceName, 275 "-t", tags, 276 } 277 Eventually(helpers.CF(command...)).Should(Exit(0)) 278 }) 279 280 It("can show the GUID immediately", func() { 281 session := helpers.CF(serviceCommand, serviceInstanceName, "--guid") 282 Eventually(session).Should(Exit(0)) 283 Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length") 284 }) 285 286 It("can show the service instance details", func() { 287 session := helpers.CF(serviceCommand, serviceInstanceName) 288 Eventually(session).Should(Exit(0)) 289 290 username, _ := helpers.GetCredentials() 291 Expect(session).To(SatisfyAll( 292 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 293 Say(`\n`), 294 Say(`name:\s+%s\n`, serviceInstanceName), 295 Say(`guid:\s+\S+\n`), 296 Say(`type:\s+managed`), 297 Say(`broker:\s+%s`, broker.Name), 298 Say(`offering:\s+%s`, broker.FirstServiceOfferingName()), 299 Say(`plan:\s+%s`, broker.FirstServicePlanName()), 300 Say(`tags:\s+%s\n`, tags), 301 Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")), 302 Say(`description:\s+%s\n`, broker.Services[0].Description), 303 Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL), 304 Say(`dashboard url:\s+http://example.com\n`), 305 Say(`\n`), 306 Say(`Showing status of last operation:\n`), 307 Say(`status:\s+create in progress\n`), 308 Say(`message:\s+very happy service\n`), 309 Say(`started:\s+%s\n`, helpers.TimestampRegex), 310 Say(`updated:\s+%s\n`, helpers.TimestampRegex), 311 Say(`\n`), 312 Say(`Showing bound apps:\n`), 313 Say(`There are no bound apps for this service instance\.\n`), 314 Say(`\n`), 315 Say(`Showing sharing info:\n`), 316 Say(`This service instance is not currently being shared.`), 317 Say(`\n`), 318 Say(`Showing upgrade status:\n`), 319 Say(`Upgrades are not supported by this broker.\n`), 320 )) 321 }) 322 }) 323 324 When("the instance is shared with another space", func() { 325 var sharedToSpaceName string 326 327 BeforeEach(func() { 328 sharedToSpaceName = helpers.NewSpaceName() 329 helpers.CreateSpace(sharedToSpaceName) 330 331 broker = servicebrokerstub.New().EnableServiceAccess() 332 command := []string{ 333 "create-service", 334 broker.FirstServiceOfferingName(), 335 broker.FirstServicePlanName(), 336 serviceInstanceName, 337 } 338 Eventually(helpers.CF(command...)).Should(Exit(0)) 339 340 output := func() *Buffer { 341 session := helpers.CF(serviceCommand, serviceInstanceName) 342 session.Wait() 343 return session.Out 344 } 345 346 Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`)) 347 348 command = []string{ 349 "share-service", 350 serviceInstanceName, 351 "-s", 352 sharedToSpaceName, 353 } 354 Eventually(helpers.CF(command...)).Should(Exit(0)) 355 }) 356 357 AfterEach(func() { 358 command := []string{ 359 "unshare-service", 360 serviceInstanceName, 361 "-s", sharedToSpaceName, 362 "-f", 363 } 364 Eventually(helpers.CF(command...)).Should(Exit(0)) 365 366 helpers.QuickDeleteSpace(sharedToSpaceName) 367 }) 368 369 It("can show that the service is being shared", func() { 370 session := helpers.CF(serviceCommand, serviceInstanceName) 371 Eventually(session).Should(Exit(0)) 372 373 Expect(session).To(SatisfyAll( 374 Say(`Showing sharing info:\n`), 375 Say(`Shared with spaces:\n`), 376 Say(`org\s+space\s+bindings\n`), 377 Say(`%s\s+%s\s+0\s*\n`, orgName, sharedToSpaceName), 378 )) 379 }) 380 }) 381 382 When("the instance is being accessed form shared to space", func() { 383 var sharedToSpaceName string 384 385 BeforeEach(func() { 386 sharedToSpaceName = helpers.NewSpaceName() 387 helpers.CreateSpace(sharedToSpaceName) 388 389 broker = servicebrokerstub.New().EnableServiceAccess() 390 command := []string{ 391 "create-service", 392 broker.FirstServiceOfferingName(), 393 broker.FirstServicePlanName(), 394 serviceInstanceName, 395 } 396 Eventually(helpers.CF(command...)).Should(Exit(0)) 397 398 output := func() *Buffer { 399 session := helpers.CF(serviceCommand, serviceInstanceName) 400 session.Wait() 401 return session.Out 402 } 403 404 Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`)) 405 406 command = []string{ 407 "share-service", 408 serviceInstanceName, 409 "-s", 410 sharedToSpaceName, 411 } 412 Eventually(helpers.CF(command...)).Should(Exit(0)) 413 414 helpers.TargetOrgAndSpace(orgName, sharedToSpaceName) 415 }) 416 417 AfterEach(func() { 418 helpers.TargetOrgAndSpace(orgName, spaceName) 419 420 command := []string{ 421 "unshare-service", 422 serviceInstanceName, 423 "-s", sharedToSpaceName, 424 "-f", 425 } 426 Eventually(helpers.CF(command...)).Should(Exit(0)) 427 428 helpers.QuickDeleteSpace(sharedToSpaceName) 429 }) 430 431 It("can show that the service has been shared", func() { 432 session := helpers.CF(serviceCommand, serviceInstanceName) 433 Eventually(session).Should(Exit(0)) 434 435 Expect(session).To(SatisfyAll( 436 Say(`Showing sharing info:\n`), 437 Say(`This service instance is shared from space %s of org %s.\n`, spaceName, orgName), 438 )) 439 }) 440 }) 441 442 When("the broker supports maintenance info", func() { 443 When("the service is up to date", func() { 444 var serviceInstanceName string 445 446 BeforeEach(func() { 447 serviceInstanceName = helpers.NewServiceInstanceName() 448 broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess() 449 helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName) 450 }) 451 452 It("says that the service has no upgrades available", func() { 453 session := helpers.CF(serviceCommand, serviceInstanceName) 454 Eventually(session).Should(Exit(0)) 455 456 Expect(session).To(SatisfyAll( 457 Say(`Showing upgrade status:\n`), 458 Say(`There is no upgrade available for this service.\n`), 459 )) 460 }) 461 }) 462 463 When("an update is available", func() { 464 var serviceInstanceName string 465 466 BeforeEach(func() { 467 serviceInstanceName = helpers.NewServiceInstanceName() 468 broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess() 469 helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName) 470 471 broker.WithMaintenanceInfo("1.2.4", "really cool improvement").Configure().Register() 472 }) 473 474 It("displays information about the upgrade", func() { 475 session := helpers.CF(serviceCommand, serviceInstanceName) 476 Eventually(session).Should(Exit(0)) 477 478 Expect(session).To(SatisfyAll( 479 Say(`Showing upgrade status:\n`), 480 Say(`There is an upgrade available for this service.\n`), 481 Say(`Upgrade description: really cool improvement\n`), 482 Say(`TIP: You can upgrade using 'cf upgrade-service %s'\n`, serviceInstanceName), 483 )) 484 }) 485 }) 486 }) 487 488 When("bound to apps", func() { 489 var ( 490 appName1 string 491 appName2 string 492 bindingName1 string 493 bindingName2 string 494 ) 495 496 BeforeEach(func() { 497 appName1 = helpers.PrefixedRandomName("APP1") 498 appName2 = helpers.PrefixedRandomName("APP2") 499 bindingName1 = helpers.RandomName() 500 bindingName2 = helpers.RandomName() 501 502 broker = servicebrokerstub.New().WithAsyncDelay(time.Millisecond).EnableServiceAccess() 503 504 helpers.CreateManagedServiceInstance( 505 broker.FirstServiceOfferingName(), 506 broker.FirstServicePlanName(), 507 serviceInstanceName, 508 ) 509 510 helpers.WithHelloWorldApp(func(appDir string) { 511 Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 512 Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 513 }) 514 515 Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1, "--wait")).Should(Exit(0)) 516 Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2, "--wait")).Should(Exit(0)) 517 }) 518 519 It("displays the bound apps", func() { 520 session := helpers.CF(serviceCommand, serviceInstanceName, "-v") 521 Eventually(session).Should(Exit(0)) 522 523 Expect(session).To(SatisfyAll( 524 Say(`Showing bound apps:\n`), 525 Say(`name\s+binding name\s+status\s+message\n`), 526 Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName1, bindingName1), 527 Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName2, bindingName2), 528 )) 529 }) 530 }) 531 532 When("--params is requested", func() { 533 var key string 534 var value string 535 536 BeforeEach(func() { 537 key = "foo" 538 value = helpers.RandomName() 539 540 broker = servicebrokerstub.New().EnableServiceAccess() 541 helpers.CreateManagedServiceInstance( 542 broker.FirstServiceOfferingName(), 543 broker.FirstServicePlanName(), 544 serviceInstanceName, 545 "-c", fmt.Sprintf(`{"%s":"%s"}`, key, value), 546 ) 547 }) 548 549 It("reports the service instance parameters JSON", func() { 550 session := helpers.CF(serviceCommand, serviceInstanceName, "--params") 551 Eventually(session).Should(Exit(0)) 552 553 Expect(session).To(SatisfyAll( 554 Say(`\{\n`), 555 Say(` %q: %q\n`, key, value), 556 Say(`\}\n`), 557 )) 558 }) 559 }) 560 }) 561 }) 562 })