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