github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/v7/service_command_test.go (about) 1 package v7_test 2 3 import ( 4 "errors" 5 "strings" 6 7 "github.com/LukasHeimann/cloudfoundrycli/v8/actor/v7action" 8 "github.com/LukasHeimann/cloudfoundrycli/v8/command/commandfakes" 9 . "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7" 10 "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7/v7fakes" 11 "github.com/LukasHeimann/cloudfoundrycli/v8/resources" 12 "github.com/LukasHeimann/cloudfoundrycli/v8/types" 13 "github.com/LukasHeimann/cloudfoundrycli/v8/util/configv3" 14 "github.com/LukasHeimann/cloudfoundrycli/v8/util/ui" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 . "github.com/onsi/gomega/gbytes" 18 ) 19 20 var _ = Describe("service command", func() { 21 const ( 22 serviceInstanceName = "fake-service-instance-name" 23 serviceInstanceGUID = "fake-service-instance-guid" 24 spaceName = "fake-space-name" 25 spaceGUID = "fake-space-guid" 26 orgName = "fake-org-name" 27 username = "fake-user-name" 28 ) 29 var ( 30 cmd ServiceCommand 31 testUI *ui.UI 32 fakeConfig *commandfakes.FakeConfig 33 fakeSharedActor *commandfakes.FakeSharedActor 34 fakeActor *v7fakes.FakeActor 35 executeErr error 36 ) 37 38 JustBeforeEach(func() { 39 executeErr = cmd.Execute(nil) 40 }) 41 42 BeforeEach(func() { 43 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 44 fakeConfig = new(commandfakes.FakeConfig) 45 fakeSharedActor = new(commandfakes.FakeSharedActor) 46 fakeActor = new(v7fakes.FakeActor) 47 48 cmd = ServiceCommand{ 49 BaseCommand: BaseCommand{ 50 UI: testUI, 51 Config: fakeConfig, 52 SharedActor: fakeSharedActor, 53 Actor: fakeActor, 54 }, 55 } 56 57 fakeActor.GetCurrentUserReturns(configv3.User{Name: username}, nil) 58 59 fakeConfig.TargetedSpaceReturns(configv3.Space{ 60 GUID: spaceGUID, 61 Name: spaceName, 62 }) 63 64 fakeConfig.TargetedOrganizationReturns(configv3.Organization{ 65 Name: orgName, 66 }) 67 68 fakeActor.GetServiceInstanceDetailsReturns( 69 v7action.ServiceInstanceDetails{ 70 ServiceInstance: resources.ServiceInstance{ 71 GUID: serviceInstanceGUID, 72 Name: serviceInstanceName, 73 }, 74 SharedStatus: v7action.SharedStatus{ 75 IsSharedToOtherSpaces: false, 76 }, 77 }, 78 v7action.Warnings{"warning one", "warning two"}, 79 nil, 80 ) 81 82 setPositionalFlags(&cmd, serviceInstanceName) 83 }) 84 85 It("checks the user is logged in, and targeting an org and space", func() { 86 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 87 orgChecked, spaceChecked := fakeSharedActor.CheckTargetArgsForCall(0) 88 Expect(orgChecked).To(BeTrue()) 89 Expect(spaceChecked).To(BeTrue()) 90 }) 91 92 When("the --guid flag is specified", func() { 93 BeforeEach(func() { 94 fakeActor.GetServiceInstanceByNameAndSpaceReturns( 95 resources.ServiceInstance{ 96 GUID: serviceInstanceGUID, 97 Name: serviceInstanceName, 98 }, 99 v7action.Warnings{"warning one", "warning two"}, 100 nil, 101 ) 102 103 setFlag(&cmd, "--guid") 104 }) 105 106 It("looks up the service instance and prints the GUID and no warnings", func() { 107 Expect(executeErr).NotTo(HaveOccurred()) 108 109 Expect(fakeActor.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1)) 110 actualName, actualSpaceGUID := fakeActor.GetServiceInstanceByNameAndSpaceArgsForCall(0) 111 Expect(actualName).To(Equal(serviceInstanceName)) 112 Expect(actualSpaceGUID).To(Equal(spaceGUID)) 113 114 Expect(testUI.Out).To(Say(`^%s\n$`, serviceInstanceGUID)) 115 Expect(testUI.Err).NotTo(Say("warning")) 116 }) 117 118 When("getting the service instance fails", func() { 119 BeforeEach(func() { 120 fakeActor.GetServiceInstanceByNameAndSpaceReturns( 121 resources.ServiceInstance{ 122 GUID: serviceInstanceGUID, 123 Name: serviceInstanceName, 124 }, 125 v7action.Warnings{"warning one", "warning two"}, 126 errors.New("yuck"), 127 ) 128 }) 129 130 It("returns the error", func() { 131 Expect(executeErr).To(MatchError("yuck")) 132 }) 133 }) 134 }) 135 136 When("it is a user-provided service instance", func() { 137 const ( 138 routeServiceURL = "https://route.com" 139 syslogURL = "https://syslog.com" 140 tags = "foo, bar" 141 lastOperationType = "update" 142 lastOperationState = "succeeded" 143 lastOperationDescription = "doing amazing work" 144 lastOperationStartTime = "a second ago" 145 lastOperationUpdatedTime = "just now" 146 ) 147 148 BeforeEach(func() { 149 fakeActor.GetServiceInstanceDetailsReturns( 150 v7action.ServiceInstanceDetails{ 151 ServiceInstance: resources.ServiceInstance{ 152 GUID: serviceInstanceGUID, 153 Name: serviceInstanceName, 154 Type: resources.UserProvidedServiceInstance, 155 SyslogDrainURL: types.NewOptionalString(syslogURL), 156 RouteServiceURL: types.NewOptionalString(routeServiceURL), 157 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 158 LastOperation: resources.LastOperation{ 159 Type: lastOperationType, 160 State: lastOperationState, 161 Description: lastOperationDescription, 162 CreatedAt: lastOperationStartTime, 163 UpdatedAt: lastOperationUpdatedTime, 164 }, 165 }, 166 }, 167 v7action.Warnings{"warning one", "warning two"}, 168 nil, 169 ) 170 }) 171 172 It("looks up the service instance and prints the details and warnings", func() { 173 Expect(executeErr).NotTo(HaveOccurred()) 174 175 Expect(fakeActor.GetServiceInstanceDetailsCallCount()).To(Equal(1)) 176 actualName, actualSpaceGUID, actualOmitApps := fakeActor.GetServiceInstanceDetailsArgsForCall(0) 177 Expect(actualName).To(Equal(serviceInstanceName)) 178 Expect(actualSpaceGUID).To(Equal(spaceGUID)) 179 Expect(actualOmitApps).To(BeFalse()) 180 181 Expect(testUI.Out).To(SatisfyAll( 182 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 183 Say(`\n`), 184 Say(`name:\s+%s\n`, serviceInstanceName), 185 Say(`guid:\s+\S+\n`), 186 Say(`type:\s+user-provided`), 187 Say(`tags:\s+%s\n`, tags), 188 Say(`route service url:\s+%s\n`, routeServiceURL), 189 Say(`syslog drain url:\s+%s\n`, syslogURL), 190 Say(`\n`), 191 Say(`Showing status of last operation:\n`), 192 Say(`\s+status:\s+%s %s\n`, lastOperationType, lastOperationState), 193 Say(`\s+message:\s+%s\n`, lastOperationDescription), 194 Say(`\s+started:\s+%s\n`, lastOperationStartTime), 195 Say(`\s+updated:\s+%s\n`, lastOperationUpdatedTime), 196 Say(`\n`), 197 Say(`Showing bound apps:\n`), 198 Say(`There are no bound apps for this service instance\.\n`), 199 )) 200 201 Expect(testUI.Err).To(SatisfyAll( 202 Say("warning one"), 203 Say("warning two"), 204 )) 205 }) 206 207 When("last operation is not set", func() { 208 BeforeEach(func() { 209 fakeActor.GetServiceInstanceDetailsReturns( 210 v7action.ServiceInstanceDetails{ 211 ServiceInstance: resources.ServiceInstance{ 212 GUID: serviceInstanceGUID, 213 Name: serviceInstanceName, 214 Type: resources.UserProvidedServiceInstance, 215 SyslogDrainURL: types.NewOptionalString(syslogURL), 216 RouteServiceURL: types.NewOptionalString(routeServiceURL), 217 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 218 }, 219 }, 220 v7action.Warnings{"warning one", "warning two"}, 221 nil, 222 ) 223 }) 224 225 It("when last operation does not exist", func() { 226 Expect(executeErr).NotTo(HaveOccurred()) 227 228 Expect(fakeActor.GetServiceInstanceDetailsCallCount()).To(Equal(1)) 229 actualName, actualSpaceGUID, actualOmitApps := fakeActor.GetServiceInstanceDetailsArgsForCall(0) 230 Expect(actualName).To(Equal(serviceInstanceName)) 231 Expect(actualSpaceGUID).To(Equal(spaceGUID)) 232 Expect(actualOmitApps).To(BeFalse()) 233 234 Expect(testUI.Out).To(SatisfyAll( 235 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 236 Say(`\n`), 237 Say(`name:\s+%s\n`, serviceInstanceName), 238 Say(`guid:\s+\S+\n`), 239 Say(`type:\s+user-provided`), 240 Say(`tags:\s+%s\n`, tags), 241 Say(`route service url:\s+%s\n`, routeServiceURL), 242 Say(`syslog drain url:\s+%s\n`, syslogURL), 243 Say(`\n`), 244 Say(`Showing status of last operation:\n`), 245 Say(`There is no last operation available for this service instance\.\n`), 246 Say(`\n`), 247 Say(`Showing bound apps:\n`), 248 Say(`There are no bound apps for this service instance\.\n`), 249 )) 250 251 Expect(testUI.Err).To(SatisfyAll( 252 Say("warning one"), 253 Say("warning two"), 254 )) 255 }) 256 }) 257 258 When("there are bound apps", func() { 259 BeforeEach(func() { 260 fakeActor.GetServiceInstanceDetailsReturns( 261 v7action.ServiceInstanceDetails{ 262 ServiceInstance: resources.ServiceInstance{ 263 GUID: serviceInstanceGUID, 264 Name: serviceInstanceName, 265 Type: resources.UserProvidedServiceInstance, 266 SyslogDrainURL: types.NewOptionalString(syslogURL), 267 RouteServiceURL: types.NewOptionalString(routeServiceURL), 268 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 269 }, 270 BoundApps: []resources.ServiceCredentialBinding{ 271 { 272 Name: "named-binding", 273 AppName: "app-1", 274 LastOperation: resources.LastOperation{ 275 Type: resources.CreateOperation, 276 State: resources.OperationSucceeded, 277 Description: "great", 278 }, 279 }, 280 { 281 AppName: "app-2", 282 LastOperation: resources.LastOperation{ 283 Type: resources.UpdateOperation, 284 State: resources.OperationFailed, 285 Description: "sorry", 286 }, 287 }, 288 }, 289 }, 290 v7action.Warnings{"warning one", "warning two"}, 291 nil, 292 ) 293 }) 294 295 It("prints the bound apps table", func() { 296 Expect(testUI.Out).To(SatisfyAll( 297 Say(`Showing bound apps:\n`), 298 Say(` name\s+binding name\s+status\s+message\n`), 299 Say(` app-1\s+named-binding\s+create succeeded\s+great\n`), 300 Say(` app-2\s+update failed\s+sorry\n`), 301 )) 302 }) 303 }) 304 }) 305 306 When("it is a managed service instance", func() { 307 const ( 308 dashboardURL = "https://dashboard.com" 309 tags = "foo, bar" 310 servicePlanName = "fake-service-plan-name" 311 serviceOfferingName = "fake-service-offering-name" 312 serviceOfferingDescription = "an amazing service" 313 serviceOfferingDocs = "https://service.docs.com" 314 serviceBrokerName = "fake-service-broker-name" 315 lastOperationType = "create" 316 lastOperationState = "in progress" 317 lastOperationDescription = "doing amazing work" 318 lastOperationStartTime = "a second ago" 319 lastOperationUpdatedTime = "just now" 320 ) 321 322 BeforeEach(func() { 323 fakeActor.GetServiceInstanceDetailsReturns( 324 v7action.ServiceInstanceDetails{ 325 ServiceInstance: resources.ServiceInstance{ 326 GUID: serviceInstanceGUID, 327 Name: serviceInstanceName, 328 Type: resources.ManagedServiceInstance, 329 DashboardURL: types.NewOptionalString(dashboardURL), 330 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 331 LastOperation: resources.LastOperation{ 332 Type: lastOperationType, 333 State: lastOperationState, 334 Description: lastOperationDescription, 335 CreatedAt: lastOperationStartTime, 336 UpdatedAt: lastOperationUpdatedTime, 337 }, 338 SpaceGUID: spaceGUID, 339 }, 340 SpaceName: spaceName, 341 OrganizationName: orgName, 342 ServiceOffering: resources.ServiceOffering{ 343 Name: serviceOfferingName, 344 Description: serviceOfferingDescription, 345 DocumentationURL: serviceOfferingDocs, 346 }, 347 ServicePlan: resources.ServicePlan{Name: servicePlanName}, 348 ServiceBrokerName: serviceBrokerName, 349 SharedStatus: v7action.SharedStatus{ 350 IsSharedToOtherSpaces: true, 351 UsageSummary: []v7action.UsageSummaryWithSpaceAndOrg{{"shared-to-space", "some-org", 3}}, 352 }, 353 }, 354 v7action.Warnings{"warning one", "warning two"}, 355 nil, 356 ) 357 }) 358 359 It("looks up the service instance and prints the details and warnings", func() { 360 Expect(executeErr).NotTo(HaveOccurred()) 361 362 Expect(fakeActor.GetServiceInstanceDetailsCallCount()).To(Equal(1)) 363 actualName, actualSpaceGUID, actualOmitApps := fakeActor.GetServiceInstanceDetailsArgsForCall(0) 364 Expect(actualName).To(Equal(serviceInstanceName)) 365 Expect(actualSpaceGUID).To(Equal(spaceGUID)) 366 Expect(actualOmitApps).To(BeFalse()) 367 368 Expect(testUI.Out).To(SatisfyAll( 369 Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username), 370 Say(`\n`), 371 Say(`name:\s+%s\n`, serviceInstanceName), 372 Say(`guid:\s+\S+\n`), 373 Say(`type:\s+managed`), 374 Say(`broker:\s+%s`, serviceBrokerName), 375 Say(`offering:\s+%s`, serviceOfferingName), 376 Say(`plan:\s+%s`, servicePlanName), 377 Say(`tags:\s+%s\n`, tags), 378 Say(`description:\s+%s\n`, serviceOfferingDescription), 379 Say(`documentation:\s+%s\n`, serviceOfferingDocs), 380 Say(`dashboard url:\s+%s\n`, dashboardURL), 381 Say(`\n`), 382 Say(`Showing status of last operation:`), 383 Say(`status:\s+%s %s\n`, lastOperationType, lastOperationState), 384 Say(`message:\s+%s\n`, lastOperationDescription), 385 Say(`started:\s+%s\n`, lastOperationStartTime), 386 Say(`updated:\s+%s\n`, lastOperationUpdatedTime), 387 Say(`\n`), 388 Say(`Showing bound apps:`), 389 Say(`There are no bound apps for this service instance\.\n`), 390 Say(`\n`), 391 Say(`Showing sharing info:`), 392 Say(`Shared with spaces:\n`), 393 Say(`Showing upgrade status:`), 394 Say(`Upgrades are not supported by this broker.\n`), 395 )) 396 397 Expect(testUI.Err).To(SatisfyAll( 398 Say("warning one"), 399 Say("warning two"), 400 )) 401 }) 402 403 Context("sharing", func() { 404 When("targeting original space", func() { 405 When("service instance is shared", func() { 406 It("shows shared information", func() { 407 Expect(testUI.Out).To(SatisfyAll( 408 Say(`Showing sharing info:`), 409 Say(`Shared with spaces:`), 410 Say(`org\s+space\s+bindings\s*\n`), 411 Say(`some-org\s+shared-to-space\s+3\s*\n`), 412 )) 413 }) 414 }) 415 416 When("service is not shared", func() { 417 BeforeEach(func() { 418 fakeActor.GetServiceInstanceDetailsReturns( 419 v7action.ServiceInstanceDetails{ 420 ServiceInstance: resources.ServiceInstance{ 421 SpaceGUID: spaceGUID, 422 }, 423 SharedStatus: v7action.SharedStatus{ 424 IsSharedToOtherSpaces: false, 425 }, 426 }, 427 v7action.Warnings{}, 428 nil, 429 ) 430 }) 431 432 It("displays that the service is not shared", func() { 433 Expect(testUI.Out).To(SatisfyAll( 434 Say(`Showing sharing info:`), 435 Say(`This service instance is not currently being shared.`), 436 )) 437 }) 438 }) 439 440 When("the service instance sharing feature is disabled", func() { 441 BeforeEach(func() { 442 fakeActor.GetServiceInstanceDetailsReturns( 443 v7action.ServiceInstanceDetails{ 444 ServiceInstance: resources.ServiceInstance{ 445 SpaceGUID: spaceGUID, 446 }, 447 SharedStatus: v7action.SharedStatus{ 448 FeatureFlagIsDisabled: true, 449 }, 450 }, 451 v7action.Warnings{}, 452 nil, 453 ) 454 }) 455 456 It("displays that the sharing feature is disabled", func() { 457 Expect(testUI.Out).To(SatisfyAll( 458 Say(`Showing sharing info:\n`), 459 Say(`\n`), 460 Say(`The "service_instance_sharing" feature flag is disabled for this Cloud Foundry platform.\n`), 461 Say(`\n`), 462 )) 463 }) 464 }) 465 466 When("the service instance sharing feature is enabled", func() { 467 BeforeEach(func() { 468 fakeActor.GetServiceInstanceDetailsReturns( 469 v7action.ServiceInstanceDetails{ 470 ServiceInstance: resources.ServiceInstance{}, 471 SharedStatus: v7action.SharedStatus{ 472 FeatureFlagIsDisabled: false, 473 }, 474 }, 475 v7action.Warnings{}, 476 nil, 477 ) 478 }) 479 480 It("does not display a warning", func() { 481 Expect(testUI.Out).NotTo( 482 Say(`The "service_instance_sharing" feature flag is disabled for this Cloud Foundry platform.`), 483 ) 484 }) 485 }) 486 487 When("the offering does not allow service instance sharing", func() { 488 BeforeEach(func() { 489 fakeActor.GetServiceInstanceDetailsReturns( 490 v7action.ServiceInstanceDetails{ 491 ServiceInstance: resources.ServiceInstance{ 492 SpaceGUID: spaceGUID, 493 }, 494 SharedStatus: v7action.SharedStatus{ 495 OfferingDisablesSharing: true, 496 }, 497 }, 498 v7action.Warnings{}, 499 nil, 500 ) 501 }) 502 503 It("displays that the sharing feature is disabled", func() { 504 Expect(testUI.Out).To(SatisfyAll( 505 Say(`Showing sharing info:\n`), 506 Say(`\n`), 507 Say(`Service instance sharing is disabled for this service offering.\n`), 508 Say(`\n`), 509 )) 510 }) 511 }) 512 513 When("the offering does allow service instance sharing", func() { 514 BeforeEach(func() { 515 fakeActor.GetServiceInstanceDetailsReturns( 516 v7action.ServiceInstanceDetails{ 517 ServiceInstance: resources.ServiceInstance{}, 518 SharedStatus: v7action.SharedStatus{ 519 OfferingDisablesSharing: false, 520 }, 521 }, 522 v7action.Warnings{}, 523 nil, 524 ) 525 }) 526 527 It("does not display a warning", func() { 528 Expect(testUI.Out).NotTo( 529 Say(`Service instance sharing is disabled for this service offering.`), 530 ) 531 }) 532 }) 533 }) 534 535 When("targeting shared to space", func() { 536 BeforeEach(func() { 537 sharedToSpaceGUID := "fake-shared-to-space-guid" 538 sharedToSpaceName := "fake-shared-to-space-name" 539 fakeConfig.TargetedSpaceReturns(configv3.Space{ 540 GUID: sharedToSpaceGUID, 541 Name: sharedToSpaceName, 542 }) 543 544 fakeActor.GetServiceInstanceDetailsReturns( 545 v7action.ServiceInstanceDetails{ 546 ServiceInstance: resources.ServiceInstance{ 547 SpaceGUID: spaceGUID, 548 }, 549 SpaceName: spaceName, 550 OrganizationName: orgName, 551 SharedStatus: v7action.SharedStatus{ 552 IsSharedFromOriginalSpace: true, 553 IsSharedToOtherSpaces: true, 554 OfferingDisablesSharing: true, 555 FeatureFlagIsDisabled: true, 556 }, 557 }, 558 v7action.Warnings{}, 559 nil, 560 ) 561 }) 562 563 It("shows original space information", func() { 564 Expect(testUI.Out).To(SatisfyAll( 565 Say(`Showing sharing info:\n`), 566 Say(`This service instance is shared from space %s of org %s.\n`, spaceName, orgName), 567 )) 568 }) 569 570 It("doesn't display any sharing warning", func() { 571 Expect(testUI.Out).NotTo(SatisfyAny( 572 Say(`This service instance is currently shared.`), 573 Say(`The "service_instance_sharing" feature flag is disabled for this Cloud Foundry platform.`), 574 Say(`Service instance sharing is disabled for this service offering.`), 575 )) 576 }) 577 }) 578 }) 579 580 Context("upgrading", func() { 581 When("an upgrade is available", func() { 582 BeforeEach(func() { 583 fakeActor.GetServiceInstanceDetailsReturns( 584 v7action.ServiceInstanceDetails{ 585 ServiceInstance: resources.ServiceInstance{ 586 GUID: serviceInstanceGUID, 587 Name: serviceInstanceName, 588 Type: resources.ManagedServiceInstance, 589 DashboardURL: types.NewOptionalString(dashboardURL), 590 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 591 LastOperation: resources.LastOperation{ 592 Type: lastOperationType, 593 State: lastOperationState, 594 Description: lastOperationDescription, 595 CreatedAt: lastOperationStartTime, 596 UpdatedAt: lastOperationUpdatedTime, 597 }, 598 }, 599 ServiceOffering: resources.ServiceOffering{ 600 Name: serviceOfferingName, 601 Description: serviceOfferingDescription, 602 DocumentationURL: serviceOfferingDocs, 603 }, 604 ServicePlan: resources.ServicePlan{Name: servicePlanName}, 605 ServiceBrokerName: serviceBrokerName, 606 UpgradeStatus: v7action.ServiceInstanceUpgradeStatus{ 607 State: v7action.ServiceInstanceUpgradeAvailable, 608 Description: "really cool upgrade\nwith juicy bits", 609 }, 610 }, 611 v7action.Warnings{"warning one", "warning two"}, 612 nil, 613 ) 614 }) 615 616 It("says an upgrade is available and shows the description", func() { 617 Expect(executeErr).NotTo(HaveOccurred()) 618 Expect(testUI.Out).To(SatisfyAll( 619 Say(`Showing upgrade status:\n`), 620 Say(`There is an upgrade available for this service.\n`), 621 Say(`Upgrade description: really cool upgrade\n`), 622 Say(`with juicy bits\n`), 623 Say(`TIP: You can upgrade using 'cf upgrade-service %s'\n`, serviceInstanceName), 624 )) 625 }) 626 }) 627 628 When("the service instance is up to date", func() { 629 BeforeEach(func() { 630 fakeActor.GetServiceInstanceDetailsReturns( 631 v7action.ServiceInstanceDetails{ 632 ServiceInstance: resources.ServiceInstance{ 633 GUID: serviceInstanceGUID, 634 Name: serviceInstanceName, 635 Type: resources.ManagedServiceInstance, 636 DashboardURL: types.NewOptionalString(dashboardURL), 637 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 638 LastOperation: resources.LastOperation{ 639 Type: lastOperationType, 640 State: lastOperationState, 641 Description: lastOperationDescription, 642 CreatedAt: lastOperationStartTime, 643 UpdatedAt: lastOperationUpdatedTime, 644 }, 645 }, 646 ServiceOffering: resources.ServiceOffering{ 647 Name: serviceOfferingName, 648 Description: serviceOfferingDescription, 649 DocumentationURL: serviceOfferingDocs, 650 }, 651 ServicePlan: resources.ServicePlan{Name: servicePlanName}, 652 ServiceBrokerName: serviceBrokerName, 653 UpgradeStatus: v7action.ServiceInstanceUpgradeStatus{ 654 State: v7action.ServiceInstanceUpgradeNotAvailable, 655 }, 656 }, 657 v7action.Warnings{"warning one", "warning two"}, 658 nil, 659 ) 660 }) 661 662 It("says an upgrade is available and shows the description", func() { 663 Expect(executeErr).NotTo(HaveOccurred()) 664 Expect(testUI.Out).To(SatisfyAll( 665 Say(`Showing upgrade status:\n`), 666 Say(`There is no upgrade available for this service.\n`), 667 )) 668 }) 669 }) 670 }) 671 672 Context("bound apps", func() { 673 BeforeEach(func() { 674 fakeActor.GetServiceInstanceDetailsReturns( 675 v7action.ServiceInstanceDetails{ 676 ServiceInstance: resources.ServiceInstance{ 677 GUID: serviceInstanceGUID, 678 Name: serviceInstanceName, 679 Type: resources.ManagedServiceInstance, 680 DashboardURL: types.NewOptionalString(dashboardURL), 681 Tags: types.NewOptionalStringSlice(strings.Split(tags, ", ")...), 682 LastOperation: resources.LastOperation{ 683 Type: lastOperationType, 684 State: lastOperationState, 685 Description: lastOperationDescription, 686 CreatedAt: lastOperationStartTime, 687 UpdatedAt: lastOperationUpdatedTime, 688 }, 689 SpaceGUID: spaceGUID, 690 }, 691 SpaceName: spaceName, 692 OrganizationName: orgName, 693 ServiceOffering: resources.ServiceOffering{ 694 Name: serviceOfferingName, 695 Description: serviceOfferingDescription, 696 DocumentationURL: serviceOfferingDocs, 697 }, 698 ServicePlan: resources.ServicePlan{Name: servicePlanName}, 699 ServiceBrokerName: serviceBrokerName, 700 SharedStatus: v7action.SharedStatus{ 701 IsSharedToOtherSpaces: true, 702 }, 703 BoundApps: []resources.ServiceCredentialBinding{ 704 { 705 Name: "named-binding", 706 AppName: "app-1", 707 LastOperation: resources.LastOperation{ 708 Type: resources.CreateOperation, 709 State: resources.OperationSucceeded, 710 Description: "great", 711 }, 712 }, 713 { 714 AppName: "app-2", 715 LastOperation: resources.LastOperation{ 716 Type: resources.UpdateOperation, 717 State: resources.OperationFailed, 718 Description: "sorry", 719 }, 720 }, 721 }, 722 }, 723 v7action.Warnings{"warning one", "warning two"}, 724 nil, 725 ) 726 }) 727 728 It("prints the bound apps table", func() { 729 Expect(testUI.Out).To(SatisfyAll( 730 Say(`Showing bound apps:\n`), 731 Say(`name\s+binding name\s+status\s+message\n`), 732 Say(`app-1\s+named-binding\s+create succeeded\s+great\n`), 733 Say(`app-2\s+update failed\s+sorry\n`), 734 )) 735 }) 736 }) 737 }) 738 739 When("the --params flag is specified", func() { 740 BeforeEach(func() { 741 setFlag(&cmd, "--params") 742 }) 743 744 When("parameters are set", func() { 745 BeforeEach(func() { 746 fakeActor.GetServiceInstanceParametersReturns( 747 map[string]interface{}{"foo": "bar"}, 748 v7action.Warnings{"warning one", "warning two"}, 749 nil, 750 ) 751 }) 752 753 It("returns parameters JSON", func() { 754 Expect(executeErr).NotTo(HaveOccurred()) 755 756 Expect(fakeActor.GetServiceInstanceParametersCallCount()).To(Equal(1)) 757 actualName, actualSpaceGUID := fakeActor.GetServiceInstanceParametersArgsForCall(0) 758 Expect(actualName).To(Equal(serviceInstanceName)) 759 Expect(actualSpaceGUID).To(Equal(spaceGUID)) 760 761 Expect(testUI.Out).To(SatisfyAll( 762 Say(`\{\n`), 763 Say(` "foo": "bar"\n`), 764 Say(`\}\n`), 765 )) 766 Expect(testUI.Err).To(SatisfyAll( 767 Say("warning one"), 768 Say("warning two"), 769 )) 770 }) 771 }) 772 773 When("there was a problem retrieving the parameters", func() { 774 BeforeEach(func() { 775 fakeActor.GetServiceInstanceParametersReturns( 776 v7action.ServiceInstanceParameters{}, 777 v7action.Warnings{"warning one", "warning two"}, 778 errors.New("something happened"), 779 ) 780 }) 781 782 It("displays the reason", func() { 783 Expect(executeErr).To(MatchError("something happened")) 784 Expect(testUI.Err).To(SatisfyAll( 785 Say("warning one"), 786 Say("warning two"), 787 )) 788 }) 789 }) 790 791 When("the parameters are empty", func() { 792 BeforeEach(func() { 793 fakeActor.GetServiceInstanceParametersReturns( 794 v7action.ServiceInstanceParameters{}, 795 v7action.Warnings{"warning one", "warning two"}, 796 nil, 797 ) 798 }) 799 800 It("displays empty parameters", func() { 801 Expect(executeErr).NotTo(HaveOccurred()) 802 Expect(testUI.Out).To(Say(`{}\n`)) 803 }) 804 }) 805 }) 806 807 When("there is a problem looking up the service instance", func() { 808 BeforeEach(func() { 809 fakeActor.GetServiceInstanceDetailsReturns( 810 v7action.ServiceInstanceDetails{}, 811 v7action.Warnings{"warning one", "warning two"}, 812 errors.New("boom"), 813 ) 814 }) 815 816 It("prints warnings and returns an error", func() { 817 Expect(executeErr).To(MatchError("boom")) 818 819 Expect(testUI.Err).To(SatisfyAll( 820 Say("warning one"), 821 Say("warning two"), 822 )) 823 }) 824 }) 825 826 When("checking the target returns an error", func() { 827 BeforeEach(func() { 828 fakeSharedActor.CheckTargetReturns(errors.New("explode")) 829 }) 830 831 It("returns the error", func() { 832 Expect(executeErr).To(MatchError("explode")) 833 }) 834 }) 835 })