github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/integration/v7/isolated/service_command_test.go (about) 1 package isolated 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "code.cloudfoundry.org/cli/integration/helpers" 9 "code.cloudfoundry.org/cli/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 //Delay to reduce flakiness 175 time.Sleep(10 * time.Second) 176 session := helpers.CF(serviceCommand, serviceInstanceName, "-v") 177 Eventually(session).Should(Exit(0)) 178 179 Expect(session).To(SatisfyAll( 180 Say(`Showing bound apps:\n`), 181 Say(`name\s+binding name\s+status\s+message\n`), 182 Say(`%s\s+%s\s+create succeeded\s*\n`, appName1, bindingName1), 183 Say(`%s\s+%s\s+create succeeded\s*\n`, appName2, bindingName2), 184 )) 185 }) 186 }) 187 188 When("--params is requested", func() { 189 When("service instance parameters have been set", func() { 190 It("reports the service instance parameters JSON", func() { 191 session := helpers.CF(serviceCommand, serviceInstanceName, "--params") 192 Eventually(session).Should(Exit(1)) 193 194 Eventually(session.Err).Should(Say("This service does not support fetching service instance parameters.")) 195 }) 196 }) 197 }) 198 199 }) 200 201 When("the service instance is managed by a broker", func() { 202 const ( 203 testPollingInterval = time.Second 204 testTimeout = time.Minute 205 ) 206 207 var broker *servicebrokerstub.ServiceBrokerStub 208 209 AfterEach(func() { 210 broker.Forget() 211 }) 212 213 When("created successfully", func() { 214 const tags = "foo, bar" 215 216 BeforeEach(func() { 217 broker = servicebrokerstub.New().WithAsyncDelay(time.Nanosecond).EnableServiceAccess() 218 219 helpers.CreateManagedServiceInstance( 220 broker.FirstServiceOfferingName(), 221 broker.FirstServicePlanName(), 222 serviceInstanceName, 223 "-t", tags, 224 ) 225 }) 226 227 It("can show the service instance details", func() { 228 session := helpers.CF(serviceCommand, serviceInstanceName) 229 Eventually(session).Should(Exit(0)) 230 231 username, _ := helpers.GetCredentials() 232 Expect(session).To(SatisfyAll( 233 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 234 Say(`\n`), 235 Say(`name:\s+%s\n`, serviceInstanceName), 236 Say(`guid:\s+\S+\n`), 237 Say(`type:\s+managed`), 238 Say(`broker:\s+%s`, broker.Name), 239 Say(`offering:\s+%s`, broker.FirstServiceOfferingName()), 240 Say(`plan:\s+%s`, broker.FirstServicePlanName()), 241 Say(`tags:\s+%s\n`, tags), 242 Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")), 243 Say(`description:\s+%s\n`, broker.Services[0].Description), 244 Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL), 245 Say(`dashboard url:\s+http://example.com\n`), 246 Say(`\n`), 247 Say(`Showing status of last operation:\n`), 248 Say(`status:\s+create succeeded\n`), 249 Say(`message:\s+very happy service\n`), 250 Say(`started:\s+%s\n`, helpers.TimestampRegex), 251 Say(`updated:\s+%s\n`, helpers.TimestampRegex), 252 Say(`\n`), 253 Say(`Showing bound apps:\n`), 254 Say(`There are no bound apps for this service instance\.\n`), 255 Say(`\n`), 256 Say(`Showing sharing info:\n`), 257 Say(`This service instance is not currently being shared.`), 258 Say(`\n`), 259 Say(`Upgrades are not supported by this broker.\n`), 260 )) 261 }) 262 }) 263 264 When("creation is in progress", func() { 265 const ( 266 tags = "foo, bar" 267 brokerAsyncDelay = time.Second 268 ) 269 270 BeforeEach(func() { 271 broker = servicebrokerstub.New().WithAsyncDelay(brokerAsyncDelay).EnableServiceAccess() 272 command := []string{ 273 "create-service", 274 broker.FirstServiceOfferingName(), 275 broker.FirstServicePlanName(), 276 serviceInstanceName, 277 "-t", tags, 278 } 279 Eventually(helpers.CF(command...)).Should(Exit(0)) 280 }) 281 282 It("can show the GUID immediately", func() { 283 session := helpers.CF(serviceCommand, serviceInstanceName, "--guid") 284 Eventually(session).Should(Exit(0)) 285 Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length") 286 }) 287 288 It("can show the service instance details", func() { 289 session := helpers.CF(serviceCommand, serviceInstanceName) 290 Eventually(session).Should(Exit(0)) 291 292 username, _ := helpers.GetCredentials() 293 Expect(session).To(SatisfyAll( 294 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 295 Say(`\n`), 296 Say(`name:\s+%s\n`, serviceInstanceName), 297 Say(`guid:\s+\S+\n`), 298 Say(`type:\s+managed`), 299 Say(`broker:\s+%s`, broker.Name), 300 Say(`offering:\s+%s`, broker.FirstServiceOfferingName()), 301 Say(`plan:\s+%s`, broker.FirstServicePlanName()), 302 Say(`tags:\s+%s\n`, tags), 303 Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")), 304 Say(`description:\s+%s\n`, broker.Services[0].Description), 305 Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL), 306 Say(`dashboard url:\s+http://example.com\n`), 307 Say(`\n`), 308 Say(`Showing status of last operation:\n`), 309 Say(`status:\s+create in progress\n`), 310 Say(`message:\s+very happy service\n`), 311 Say(`started:\s+%s\n`, helpers.TimestampRegex), 312 Say(`updated:\s+%s\n`, helpers.TimestampRegex), 313 Say(`\n`), 314 Say(`Showing bound apps:\n`), 315 Say(`There are no bound apps for this service instance\.\n`), 316 Say(`\n`), 317 Say(`Showing sharing info:\n`), 318 Say(`This service instance is not currently being shared.`), 319 Say(`\n`), 320 Say(`Showing upgrade status:\n`), 321 Say(`Upgrades are not supported by this broker.\n`), 322 )) 323 }) 324 }) 325 326 When("the instance is shared with another space", func() { 327 var sharedToSpaceName string 328 329 BeforeEach(func() { 330 sharedToSpaceName = helpers.NewSpaceName() 331 helpers.CreateSpace(sharedToSpaceName) 332 333 broker = servicebrokerstub.New().EnableServiceAccess() 334 command := []string{ 335 "create-service", 336 broker.FirstServiceOfferingName(), 337 broker.FirstServicePlanName(), 338 serviceInstanceName, 339 } 340 Eventually(helpers.CF(command...)).Should(Exit(0)) 341 342 output := func() *Buffer { 343 session := helpers.CF(serviceCommand, serviceInstanceName) 344 session.Wait() 345 return session.Out 346 } 347 348 Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`)) 349 350 command = []string{ 351 "share-service", 352 serviceInstanceName, 353 "-s", 354 sharedToSpaceName, 355 } 356 Eventually(helpers.CF(command...)).Should(Exit(0)) 357 }) 358 359 AfterEach(func() { 360 command := []string{ 361 "unshare-service", 362 serviceInstanceName, 363 "-s", sharedToSpaceName, 364 "-f", 365 } 366 Eventually(helpers.CF(command...)).Should(Exit(0)) 367 368 helpers.QuickDeleteSpace(sharedToSpaceName) 369 }) 370 371 It("can show that the service is being shared", func() { 372 session := helpers.CF(serviceCommand, serviceInstanceName) 373 Eventually(session).Should(Exit(0)) 374 375 Expect(session).To(SatisfyAll( 376 Say(`Showing sharing info:\n`), 377 Say(`Shared with spaces:\n`), 378 Say(`org\s+space\s+bindings\n`), 379 Say(`%s\s+%s\s+0\s*\n`, orgName, sharedToSpaceName), 380 )) 381 }) 382 }) 383 384 When("the instance is being accessed form shared to space", func() { 385 var sharedToSpaceName string 386 387 BeforeEach(func() { 388 sharedToSpaceName = helpers.NewSpaceName() 389 helpers.CreateSpace(sharedToSpaceName) 390 391 broker = servicebrokerstub.New().EnableServiceAccess() 392 command := []string{ 393 "create-service", 394 broker.FirstServiceOfferingName(), 395 broker.FirstServicePlanName(), 396 serviceInstanceName, 397 } 398 Eventually(helpers.CF(command...)).Should(Exit(0)) 399 400 output := func() *Buffer { 401 session := helpers.CF(serviceCommand, serviceInstanceName) 402 session.Wait() 403 return session.Out 404 } 405 406 Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`)) 407 408 command = []string{ 409 "share-service", 410 serviceInstanceName, 411 "-s", 412 sharedToSpaceName, 413 } 414 Eventually(helpers.CF(command...)).Should(Exit(0)) 415 416 helpers.TargetOrgAndSpace(orgName, sharedToSpaceName) 417 }) 418 419 AfterEach(func() { 420 helpers.TargetOrgAndSpace(orgName, spaceName) 421 422 command := []string{ 423 "unshare-service", 424 serviceInstanceName, 425 "-s", sharedToSpaceName, 426 "-f", 427 } 428 Eventually(helpers.CF(command...)).Should(Exit(0)) 429 430 helpers.QuickDeleteSpace(sharedToSpaceName) 431 }) 432 433 It("can show that the service has been shared", func() { 434 session := helpers.CF(serviceCommand, serviceInstanceName) 435 Eventually(session).Should(Exit(0)) 436 437 Expect(session).To(SatisfyAll( 438 Say(`Showing sharing info:\n`), 439 Say(`This service instance is shared from space %s of org %s.\n`, spaceName, orgName), 440 )) 441 }) 442 }) 443 444 When("the broker supports maintenance info", func() { 445 When("the service is up to date", func() { 446 var serviceInstanceName string 447 448 BeforeEach(func() { 449 serviceInstanceName = helpers.NewServiceInstanceName() 450 broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess() 451 helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName) 452 }) 453 454 It("says that the service has no upgrades available", func() { 455 session := helpers.CF(serviceCommand, serviceInstanceName) 456 Eventually(session).Should(Exit(0)) 457 458 Expect(session).To(SatisfyAll( 459 Say(`Showing upgrade status:\n`), 460 Say(`There is no upgrade available for this service.\n`), 461 )) 462 }) 463 }) 464 465 When("an update is available", func() { 466 var serviceInstanceName string 467 468 BeforeEach(func() { 469 serviceInstanceName = helpers.NewServiceInstanceName() 470 broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess() 471 helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName) 472 473 broker.WithMaintenanceInfo("1.2.4", "really cool improvement").Configure().Register() 474 }) 475 476 It("displays information about the upgrade", func() { 477 session := helpers.CF(serviceCommand, serviceInstanceName) 478 Eventually(session).Should(Exit(0)) 479 480 Expect(session).To(SatisfyAll( 481 Say(`Showing upgrade status:\n`), 482 Say(`There is an upgrade available for this service.\n`), 483 Say(`Upgrade description: really cool improvement\n`), 484 Say(`TIP: You can upgrade using 'cf upgrade-service %s'\n`, serviceInstanceName), 485 )) 486 }) 487 }) 488 }) 489 490 When("bound to apps", func() { 491 var ( 492 appName1 string 493 appName2 string 494 bindingName1 string 495 bindingName2 string 496 ) 497 498 BeforeEach(func() { 499 appName1 = helpers.PrefixedRandomName("APP1") 500 appName2 = helpers.PrefixedRandomName("APP2") 501 bindingName1 = helpers.RandomName() 502 bindingName2 = helpers.RandomName() 503 504 broker = servicebrokerstub.New().WithAsyncDelay(time.Millisecond).EnableServiceAccess() 505 506 helpers.CreateManagedServiceInstance( 507 broker.FirstServiceOfferingName(), 508 broker.FirstServicePlanName(), 509 serviceInstanceName, 510 ) 511 512 helpers.WithHelloWorldApp(func(appDir string) { 513 Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 514 Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 515 }) 516 517 Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1, "--wait")).Should(Exit(0)) 518 Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2, "--wait")).Should(Exit(0)) 519 }) 520 521 It("displays the bound apps", func() { 522 session := helpers.CF(serviceCommand, serviceInstanceName, "-v") 523 Eventually(session).Should(Exit(0)) 524 525 Expect(session).To(SatisfyAll( 526 Say(`Showing bound apps:\n`), 527 Say(`name\s+binding name\s+status\s+message\n`), 528 Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName1, bindingName1), 529 Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName2, bindingName2), 530 )) 531 }) 532 }) 533 534 When("--params is requested", func() { 535 var key string 536 var value string 537 538 BeforeEach(func() { 539 key = "foo" 540 value = helpers.RandomName() 541 542 broker = servicebrokerstub.New().EnableServiceAccess() 543 helpers.CreateManagedServiceInstance( 544 broker.FirstServiceOfferingName(), 545 broker.FirstServicePlanName(), 546 serviceInstanceName, 547 "-c", fmt.Sprintf(`{"%s":"%s"}`, key, value), 548 ) 549 }) 550 551 It("reports the service instance parameters JSON", func() { 552 session := helpers.CF(serviceCommand, serviceInstanceName, "--params") 553 Eventually(session).Should(Exit(0)) 554 555 Expect(session).To(SatisfyAll( 556 Say(`\{\n`), 557 Say(` %q: %q\n`, key, value), 558 Say(`\}\n`), 559 )) 560 }) 561 }) 562 }) 563 }) 564 })