github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/actor/v7action/service_access_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 7 . "code.cloudfoundry.org/cli/actor/v7action" 8 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 "code.cloudfoundry.org/cli/resources" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("service access actions", func() { 17 var ( 18 actor *Actor 19 fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient 20 ) 21 22 BeforeEach(func() { 23 actor, fakeCloudControllerClient, _, _, _, _, _ = NewTestActor() 24 }) 25 26 Describe("GetServiceAccess", func() { 27 BeforeEach(func() { 28 fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationReturns(fakeServicePlans(), ccv3.Warnings{"plans warning"}, nil) 29 fakeCloudControllerClient.GetServiceOfferingsReturns(fakeServiceOfferings(), ccv3.Warnings{"offerings warning"}, nil) 30 31 visibility1 := resources.ServicePlanVisibility{ 32 Organizations: []resources.ServicePlanVisibilityDetail{{Name: "org-3"}}, 33 } 34 visibility2 := resources.ServicePlanVisibility{ 35 Organizations: []resources.ServicePlanVisibilityDetail{{Name: "org-1"}, {Name: "org-2"}}, 36 } 37 fakeCloudControllerClient.GetServicePlanVisibilityReturnsOnCall(0, visibility1, ccv3.Warnings{"visibility1 1 warning"}, nil) 38 fakeCloudControllerClient.GetServicePlanVisibilityReturnsOnCall(1, visibility2, ccv3.Warnings{"visibility1 2 warning"}, nil) 39 }) 40 41 It("produces a slice of ServicePlanAccess objects", func() { 42 access, warnings, err := actor.GetServiceAccess("", "", "") 43 Expect(err).NotTo(HaveOccurred()) 44 Expect(warnings).To(ConsistOf("plans warning", "offerings warning", "visibility1 1 warning", "visibility1 2 warning")) 45 Expect(access).To(ConsistOf( 46 ServicePlanAccess{ 47 BrokerName: "land-broker", 48 ServiceOfferingName: "yellow", 49 ServicePlanName: "orange", 50 VisibilityType: "organization", 51 VisibilityDetails: []string{"org-1", "org-2"}, 52 }, 53 ServicePlanAccess{ 54 BrokerName: "land-broker", 55 ServiceOfferingName: "yellow", 56 ServicePlanName: "yellow", 57 VisibilityType: "organization", 58 VisibilityDetails: []string{"org-3"}, 59 }, 60 ServicePlanAccess{ 61 BrokerName: "sea-broker", 62 ServiceOfferingName: "magenta", 63 ServicePlanName: "red", 64 VisibilityType: "public", 65 VisibilityDetails: nil, 66 }, 67 ServicePlanAccess{ 68 BrokerName: "sea-broker", 69 ServiceOfferingName: "magenta", 70 ServicePlanName: "violet", 71 VisibilityType: "public", 72 VisibilityDetails: nil, 73 }, 74 ServicePlanAccess{ 75 BrokerName: "sky-broker", 76 ServiceOfferingName: "cyan", 77 ServicePlanName: "blue", 78 VisibilityType: "space", 79 VisibilityDetails: []string{"some-space (org: some-org)"}, 80 }, 81 ServicePlanAccess{ 82 BrokerName: "sky-broker", 83 ServiceOfferingName: "cyan", 84 ServicePlanName: "green", 85 VisibilityType: "space", 86 VisibilityDetails: []string{"some-space (org: some-org)"}, 87 }, 88 ServicePlanAccess{ 89 BrokerName: "sky-broker", 90 ServiceOfferingName: "key", 91 ServicePlanName: "indigo", 92 VisibilityType: "space", 93 VisibilityDetails: []string{"some-space (org: some-org)"}, 94 }, 95 )) 96 }) 97 98 When("there are no service offerings", func() { 99 BeforeEach(func() { 100 fakeCloudControllerClient.GetServiceOfferingsReturns([]resources.ServiceOffering{}, ccv3.Warnings{"offerings warning"}, nil) 101 }) 102 103 It("returns an empty slice", func() { 104 result, warnings, err := actor.GetServiceAccess("", "", "") 105 Expect(err).NotTo(HaveOccurred()) 106 Expect(warnings).To(ContainElement("offerings warning")) 107 Expect(result).To(BeEmpty()) 108 }) 109 }) 110 111 When("filtering on organization", func() { 112 const ( 113 guid = "fake-org-guid" 114 name = "fake-org-name" 115 warning = "fake get org warning" 116 ) 117 118 BeforeEach(func() { 119 fakeCloudControllerClient.GetOrganizationsReturns([]resources.Organization{{GUID: guid}}, ccv3.Warnings{warning}, nil) 120 }) 121 122 It("passes the organization in the plan filter", func() { 123 _, warnings, err := actor.GetServiceAccess("", "", name) 124 Expect(err).NotTo(HaveOccurred()) 125 Expect(warnings).To(ContainElement(warning)) 126 127 Expect(fakeCloudControllerClient.GetOrganizationsCallCount()).To(Equal(1)) 128 Expect(fakeCloudControllerClient.GetOrganizationsArgsForCall(0)).To(ContainElement(ccv3.Query{ 129 Key: ccv3.NameFilter, 130 Values: []string{name}, 131 })) 132 133 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationCallCount()).To(Equal(1)) 134 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationArgsForCall(0)).To(ContainElement(ccv3.Query{ 135 Key: ccv3.OrganizationGUIDFilter, 136 Values: []string{guid}, 137 })) 138 }) 139 140 When("the organization is not found", func() { 141 BeforeEach(func() { 142 fakeCloudControllerClient.GetOrganizationsReturns( 143 []resources.Organization{}, 144 ccv3.Warnings{"org warning"}, 145 nil, 146 ) 147 }) 148 149 It("returns an error and warnings", func() { 150 _, warnings, err := actor.GetServiceAccess("", "", "fake-org") 151 Expect(warnings).To(ContainElement("org warning")) 152 Expect(err).To(MatchError(actionerror.OrganizationNotFoundError{Name: "fake-org"})) 153 }) 154 }) 155 }) 156 157 When("filtering on service offering", func() { 158 const ( 159 guid = "fake-service-offering-guid" 160 name = "fake-service-offering-name" 161 warning = "fake get service offering warning" 162 ) 163 164 BeforeEach(func() { 165 fakeCloudControllerClient.GetServiceOfferingsReturns([]resources.ServiceOffering{{GUID: guid}}, ccv3.Warnings{warning}, nil) 166 }) 167 168 It("passes the service offering in the filters", func() { 169 _, warnings, err := actor.GetServiceAccess(name, "", "") 170 Expect(err).NotTo(HaveOccurred()) 171 Expect(warnings).To(ContainElement(warning)) 172 173 Expect(fakeCloudControllerClient.GetServiceOfferingsCallCount()).To(Equal(1)) 174 Expect(fakeCloudControllerClient.GetServiceOfferingsArgsForCall(0)).To(ContainElement(ccv3.Query{ 175 Key: ccv3.NameFilter, 176 Values: []string{name}, 177 })) 178 179 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationCallCount()).To(Equal(1)) 180 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationArgsForCall(0)).To(ContainElement(ccv3.Query{ 181 Key: ccv3.ServiceOfferingNamesFilter, 182 Values: []string{name}, 183 })) 184 }) 185 186 When("the service offering is not found", func() { 187 BeforeEach(func() { 188 fakeCloudControllerClient.GetServiceOfferingsReturns([]resources.ServiceOffering{}, ccv3.Warnings{warning}, nil) 189 }) 190 191 It("returns an error and warnings", func() { 192 _, warnings, err := actor.GetServiceAccess(name, "", "") 193 Expect(err).To(MatchError(actionerror.ServiceNotFoundError{Name: name})) 194 Expect(warnings).To(ContainElement(warning)) 195 }) 196 }) 197 }) 198 199 When("filtering on service broker", func() { 200 const name = "fake-service-broker-name" 201 202 It("passes the service broker in the filters", func() { 203 _, _, err := actor.GetServiceAccess("", name, "") 204 Expect(err).NotTo(HaveOccurred()) 205 206 Expect(fakeCloudControllerClient.GetServiceOfferingsCallCount()).To(Equal(1)) 207 Expect(fakeCloudControllerClient.GetServiceOfferingsArgsForCall(0)).To(ContainElement(ccv3.Query{ 208 Key: ccv3.ServiceBrokerNamesFilter, 209 Values: []string{name}, 210 })) 211 212 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationCallCount()).To(Equal(1)) 213 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationArgsForCall(0)).To(ContainElement(ccv3.Query{ 214 Key: ccv3.ServiceBrokerNamesFilter, 215 Values: []string{name}, 216 })) 217 }) 218 219 When("the service broker filter returns no service offerings", func() { 220 BeforeEach(func() { 221 fakeCloudControllerClient.GetServiceOfferingsReturns([]resources.ServiceOffering{}, ccv3.Warnings{"warning"}, nil) 222 }) 223 224 It("returns an error and warnings", func() { 225 _, warnings, err := actor.GetServiceAccess("", name, "") 226 Expect(err).To(MatchError(actionerror.ServiceNotFoundError{Broker: name})) 227 Expect(warnings).To(ContainElement("warning")) 228 }) 229 }) 230 }) 231 232 When("combining filters", func() { 233 const ( 234 orgGUID = "fake-org-guid" 235 orgName = "fake-org-name" 236 orgWarning = "fake get org warning" 237 offeringGUID = "fake-service-offering-guid" 238 offeringName = "fake-service-offering-name" 239 offeringWarning = "fake get service offering warning" 240 brokerName = "fake-service-broker-name" 241 ) 242 243 BeforeEach(func() { 244 fakeCloudControllerClient.GetOrganizationsReturns([]resources.Organization{{GUID: orgGUID}}, ccv3.Warnings{orgWarning}, nil) 245 fakeCloudControllerClient.GetServiceOfferingsReturns([]resources.ServiceOffering{{GUID: offeringGUID}}, ccv3.Warnings{offeringWarning}, nil) 246 }) 247 248 It("passes all the filters", func() { 249 _, warnings, err := actor.GetServiceAccess(offeringName, brokerName, orgName) 250 Expect(err).NotTo(HaveOccurred()) 251 Expect(warnings).To(ContainElements(orgWarning, offeringWarning)) 252 253 Expect(fakeCloudControllerClient.GetOrganizationsCallCount()).To(Equal(1)) 254 Expect(fakeCloudControllerClient.GetOrganizationsArgsForCall(0)).To(ContainElement(ccv3.Query{ 255 Key: ccv3.NameFilter, 256 Values: []string{orgName}, 257 })) 258 259 Expect(fakeCloudControllerClient.GetServiceOfferingsCallCount()).To(Equal(1)) 260 Expect(fakeCloudControllerClient.GetServiceOfferingsArgsForCall(0)).To(ContainElements( 261 ccv3.Query{ 262 Key: ccv3.NameFilter, 263 Values: []string{offeringName}, 264 }, 265 ccv3.Query{ 266 Key: ccv3.ServiceBrokerNamesFilter, 267 Values: []string{brokerName}, 268 }, 269 )) 270 271 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationCallCount()).To(Equal(1)) 272 Expect(fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationArgsForCall(0)).To(ContainElements( 273 ccv3.Query{ 274 Key: ccv3.OrganizationGUIDFilter, 275 Values: []string{orgGUID}, 276 }, 277 ccv3.Query{ 278 Key: ccv3.ServiceOfferingNamesFilter, 279 Values: []string{offeringName}, 280 }, 281 ccv3.Query{ 282 Key: ccv3.ServiceBrokerNamesFilter, 283 Values: []string{brokerName}, 284 }, 285 )) 286 }) 287 }) 288 289 When("the client fails to get resources", func() { 290 Context("service plans", func() { 291 BeforeEach(func() { 292 fakeCloudControllerClient.GetServicePlansWithSpaceAndOrganizationReturns( 293 nil, 294 ccv3.Warnings{"plans warning"}, 295 errors.New("fake plans error"), 296 ) 297 }) 298 299 It("returns the error and warnings", func() { 300 _, warnings, err := actor.GetServiceAccess("", "", "") 301 Expect(warnings).To(ContainElement("plans warning")) 302 Expect(err).To(MatchError("fake plans error")) 303 }) 304 }) 305 306 Context("service offerings", func() { 307 BeforeEach(func() { 308 fakeCloudControllerClient.GetServiceOfferingsReturns( 309 nil, 310 ccv3.Warnings{"offerings warning"}, 311 errors.New("fake offerings error"), 312 ) 313 }) 314 315 It("returns the error and warnings", func() { 316 _, warnings, err := actor.GetServiceAccess("", "", "") 317 Expect(warnings).To(ContainElement("offerings warning")) 318 Expect(err).To(MatchError("fake offerings error")) 319 }) 320 }) 321 322 Context("service plan visibility", func() { 323 BeforeEach(func() { 324 fakeCloudControllerClient.GetServicePlanVisibilityReturnsOnCall( 325 0, 326 resources.ServicePlanVisibility{}, 327 ccv3.Warnings{"visibility warning"}, 328 errors.New("fake visibility error"), 329 ) 330 }) 331 332 It("returns the error and warnings", func() { 333 _, warnings, err := actor.GetServiceAccess("", "", "") 334 Expect(warnings).To(ContainElement("visibility warning")) 335 Expect(err).To(MatchError("fake visibility error")) 336 }) 337 }) 338 }) 339 }) 340 341 Describe("EnableServiceAccess", func() { 342 BeforeEach(func() { 343 fakeCloudControllerClient.GetOrganizationsReturns( 344 []resources.Organization{{GUID: "org-guid"}}, 345 ccv3.Warnings{"org warning"}, 346 nil, 347 ) 348 349 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 350 resources.ServiceOffering{GUID: "fake-offering-guid"}, 351 ccv3.Warnings{"some warning"}, 352 nil, 353 ) 354 355 fakeCloudControllerClient.GetServicePlansReturns( 356 []resources.ServicePlan{ 357 {GUID: "fake-plan-guid-1"}, 358 {GUID: "fake-plan-guid-2"}, 359 }, 360 ccv3.Warnings{"other warning"}, 361 nil, 362 ) 363 364 fakeCloudControllerClient.UpdateServicePlanVisibilityReturns( 365 resources.ServicePlanVisibility{}, 366 ccv3.Warnings{"post warning"}, 367 nil, 368 ) 369 }) 370 371 It("sets visibility to public", func() { 372 skipped, warnings, err := actor.EnableServiceAccess("fake-offering", "", "", "") 373 Expect(err).NotTo(HaveOccurred()) 374 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning", "post warning")) 375 Expect(skipped).To(BeEmpty()) 376 377 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(2)) 378 379 planGUID, actualVisibility := fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(0) 380 Expect(planGUID).To(Equal("fake-plan-guid-1")) 381 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{Type: "public"})) 382 383 planGUID, actualVisibility = fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(1) 384 Expect(planGUID).To(Equal("fake-plan-guid-2")) 385 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{Type: "public"})) 386 }) 387 388 Describe("fetching service offering", func() { 389 It("filters by service offering and broker name", func() { 390 _, _, err := actor.EnableServiceAccess("fake-offering", "fake-broker-name", "", "") 391 Expect(err).NotTo(HaveOccurred()) 392 Expect(fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerCallCount()).To(Equal(1)) 393 requestedServiceName, requestedBrokerName := fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerArgsForCall(0) 394 Expect(requestedServiceName).To(Equal("fake-offering")) 395 Expect(requestedBrokerName).To(Equal("fake-broker-name")) 396 }) 397 398 When("the service offering does not exist", func() { 399 BeforeEach(func() { 400 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 401 resources.ServiceOffering{}, 402 ccv3.Warnings{"a warning"}, 403 ccerror.ServiceOfferingNotFoundError{ServiceOfferingName: "no-such-offering"}, 404 ) 405 }) 406 407 It("returns an error", func() { 408 _, warnings, err := actor.EnableServiceAccess("no-such-offering", "", "", "") 409 Expect(warnings).To(ContainElement("a warning")) 410 Expect(err).To(MatchError("Service offering 'no-such-offering' not found.")) 411 }) 412 }) 413 414 When("the service offering name is ambiguous", func() { 415 BeforeEach(func() { 416 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 417 resources.ServiceOffering{}, 418 ccv3.Warnings{"another warning"}, 419 ccerror.ServiceOfferingNameAmbiguityError{ 420 ServiceOfferingName: "duplicate-offering", 421 ServiceBrokerNames: []string{"a-broker", "another-broker"}, 422 }) 423 }) 424 425 It("returns an error", func() { 426 _, warnings, err := actor.EnableServiceAccess("duplicate-offering", "", "", "") 427 Expect(warnings).To(ContainElement("another warning")) 428 Expect(err).To(MatchError("Service 'duplicate-offering' is provided by multiple service brokers: a-broker, another-broker\nSpecify a broker by using the '-b' flag.")) 429 }) 430 }) 431 }) 432 433 Describe("fetching service plans", func() { 434 It("gets all plans for the service offering", func() { 435 _, warnings, err := actor.EnableServiceAccess("fake-offering", "fake-broker-name", "", "") 436 Expect(err).NotTo(HaveOccurred()) 437 Expect(warnings).To(ContainElements("some warning", "other warning")) 438 439 Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1)) 440 Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(0)).To(ConsistOf(ccv3.Query{ 441 Key: ccv3.ServiceOfferingGUIDsFilter, 442 Values: []string{"fake-offering-guid"}, 443 })) 444 }) 445 446 When("a plan name is specified", func() { 447 It("filters by plan name and service offering GUID", func() { 448 _, warnings, err := actor.EnableServiceAccess("fake-offering", "fake-broker-name", "", "fake-plan-name") 449 Expect(err).NotTo(HaveOccurred()) 450 Expect(warnings).To(ContainElements("some warning", "other warning")) 451 452 Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1)) 453 Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(0)).To(ConsistOf( 454 ccv3.Query{ 455 Key: ccv3.ServiceOfferingGUIDsFilter, 456 Values: []string{"fake-offering-guid"}, 457 }, 458 ccv3.Query{ 459 Key: ccv3.NameFilter, 460 Values: []string{"fake-plan-name"}, 461 }, 462 )) 463 }) 464 }) 465 466 When("no plans were found", func() { 467 BeforeEach(func() { 468 fakeCloudControllerClient.GetServicePlansReturns([]resources.ServicePlan{}, ccv3.Warnings{"other warning"}, nil) 469 }) 470 471 It("fails", func() { 472 _, warnings, err := actor.EnableServiceAccess("fake-offering", "fake-broker-name", "", "fake-plan-name") 473 Expect(err).To(MatchError(actionerror.ServicePlanNotFoundError{ 474 OfferingName: "fake-offering", 475 PlanName: "fake-plan-name", 476 })) 477 Expect(warnings).To(ContainElements("some warning", "other warning")) 478 }) 479 }) 480 481 When("fetching the plans fail", func() { 482 BeforeEach(func() { 483 fakeCloudControllerClient.GetServicePlansReturns([]resources.ServicePlan{}, ccv3.Warnings{"other warning"}, errors.New("fetch plans error")) 484 }) 485 486 It("fails", func() { 487 _, warnings, err := actor.EnableServiceAccess("", "", "", "") 488 Expect(err).To(MatchError("fetch plans error")) 489 Expect(warnings).To(ContainElements("some warning", "other warning")) 490 }) 491 }) 492 }) 493 494 Context("with org", func() { 495 It("sets visibility to orgs", func() { 496 _, warnings, err := actor.EnableServiceAccess("fake-offering", "", "fake-org-name", "") 497 498 Expect(err).NotTo(HaveOccurred()) 499 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning", "post warning", "org warning")) 500 501 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(2)) 502 503 planGUID, actualVisibility := fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(0) 504 Expect(planGUID).To(Equal("fake-plan-guid-1")) 505 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{ 506 Type: "organization", 507 Organizations: []resources.ServicePlanVisibilityDetail{{GUID: "org-guid"}}})) 508 509 planGUID, actualVisibility = fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(1) 510 Expect(planGUID).To(Equal("fake-plan-guid-2")) 511 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{ 512 Type: "organization", 513 Organizations: []resources.ServicePlanVisibilityDetail{{GUID: "org-guid"}}})) 514 }) 515 516 When("the plan is public", func() { 517 It("skips the plan", func() { 518 fakeCloudControllerClient.GetServicePlansReturns( 519 []resources.ServicePlan{ 520 {Name: "fake-plan-1", GUID: "fake-plan-guid-1", VisibilityType: "public"}, 521 {Name: "fake-plan-2", GUID: "fake-plan-guid-2", VisibilityType: "public"}, 522 {Name: "fake-plan-3", GUID: "fake-plan-guid-3", VisibilityType: "organization"}, 523 {Name: "fake-plan-4", GUID: "fake-plan-guid-4", VisibilityType: "admin"}, 524 }, 525 ccv3.Warnings{"other warning"}, 526 nil, 527 ) 528 529 skippedPlans, _, err := actor.EnableServiceAccess("fake-offering", "", "fake-org-name", "") 530 531 Expect(err).NotTo(HaveOccurred()) 532 533 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(2)) 534 Expect(skippedPlans).To(ConsistOf("fake-plan-1", "fake-plan-2")) 535 }) 536 }) 537 538 When("the org does not exist", func() { 539 It("returns an error", func() { 540 fakeCloudControllerClient.GetOrganizationsReturns([]resources.Organization{}, ccv3.Warnings{"org warning"}, nil) 541 542 _, warnings, err := actor.EnableServiceAccess("fake-offering", "", "fake-org-name", "") 543 Expect(err).To(MatchError(actionerror.OrganizationNotFoundError{ 544 Name: "fake-org-name", 545 })) 546 Expect(warnings).To(ConsistOf("some warning", "other warning", "org warning")) 547 }) 548 }) 549 }) 550 551 When("setting visibility fails", func() { 552 BeforeEach(func() { 553 fakeCloudControllerClient.UpdateServicePlanVisibilityReturns( 554 resources.ServicePlanVisibility{}, 555 ccv3.Warnings{"post warning"}, 556 errors.New("post error"), 557 ) 558 }) 559 560 It("returns error and stops setting visibility for the remaining plans", func() { 561 _, warnings, err := actor.EnableServiceAccess("fake-offering", "", "", "") 562 563 Expect(err).To(HaveOccurred()) 564 Expect(err).To(MatchError("post error")) 565 566 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(1)) 567 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning")) 568 }) 569 }) 570 571 When("the plan has visibility type 'space'", func() { 572 It("returns the appropriate error", func() { 573 fakeCloudControllerClient.GetServicePlansReturns( 574 []resources.ServicePlan{ 575 {GUID: "fake-plan-guid-1", VisibilityType: "space"}, 576 }, 577 ccv3.Warnings{"other warning"}, 578 nil, 579 ) 580 _, warnings, err := actor.EnableServiceAccess("fake-offering", "", "", "") 581 Expect(err).To(MatchError(actionerror.ServicePlanVisibilityTypeError{})) 582 Expect(warnings).To(ContainElement("other warning")) 583 }) 584 }) 585 }) 586 587 Describe("DisableServiceAccess", func() { 588 BeforeEach(func() { 589 fakeCloudControllerClient.GetOrganizationsReturns( 590 []resources.Organization{{GUID: "org-guid"}}, 591 ccv3.Warnings{"org warning"}, 592 nil, 593 ) 594 595 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 596 resources.ServiceOffering{GUID: "fake-offering-guid"}, 597 ccv3.Warnings{"some warning"}, 598 nil, 599 ) 600 601 fakeCloudControllerClient.GetServicePlansReturns( 602 []resources.ServicePlan{ 603 {GUID: "fake-plan-guid-1"}, 604 {GUID: "fake-plan-guid-2"}, 605 }, 606 ccv3.Warnings{"other warning"}, 607 nil, 608 ) 609 610 fakeCloudControllerClient.UpdateServicePlanVisibilityReturns( 611 resources.ServicePlanVisibility{}, 612 ccv3.Warnings{"post warning"}, 613 nil, 614 ) 615 }) 616 617 It("sets visibility to `admin`", func() { 618 skipped, warnings, err := actor.DisableServiceAccess("fake-offering", "", "", "") 619 Expect(err).NotTo(HaveOccurred()) 620 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning", "post warning")) 621 Expect(skipped).To(BeEmpty()) 622 623 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(2)) 624 Expect(fakeCloudControllerClient.DeleteServicePlanVisibilityCallCount()).To(Equal(0)) 625 626 planGUID, actualVisibility := fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(0) 627 Expect(planGUID).To(Equal("fake-plan-guid-1")) 628 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{Type: "admin"})) 629 630 planGUID, actualVisibility = fakeCloudControllerClient.UpdateServicePlanVisibilityArgsForCall(1) 631 Expect(planGUID).To(Equal("fake-plan-guid-2")) 632 Expect(actualVisibility).To(Equal(resources.ServicePlanVisibility{Type: "admin"})) 633 }) 634 635 Describe("fetching service offering", func() { 636 It("filters by service offering name and broker", func() { 637 _, _, err := actor.DisableServiceAccess("fake-offering", "fake-broker-name", "", "") 638 Expect(err).NotTo(HaveOccurred()) 639 Expect(fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerCallCount()).To(Equal(1)) 640 requestedServiceName, requestedBrokerName := fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerArgsForCall(0) 641 Expect(requestedServiceName).To(Equal("fake-offering")) 642 Expect(requestedBrokerName).To(Equal("fake-broker-name")) 643 }) 644 645 When("the service offering does not exist", func() { 646 BeforeEach(func() { 647 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 648 resources.ServiceOffering{}, 649 ccv3.Warnings{"a warning"}, 650 ccerror.ServiceOfferingNotFoundError{ServiceOfferingName: "no-such-offering"}, 651 ) 652 }) 653 654 It("returns an error", func() { 655 _, warnings, err := actor.DisableServiceAccess("no-such-offering", "", "", "") 656 Expect(warnings).To(ContainElement("a warning")) 657 Expect(err).To(MatchError("Service offering 'no-such-offering' not found.")) 658 }) 659 }) 660 661 When("the service offering name is ambiguous", func() { 662 BeforeEach(func() { 663 fakeCloudControllerClient.GetServiceOfferingByNameAndBrokerReturns( 664 resources.ServiceOffering{}, 665 ccv3.Warnings{"another warning"}, 666 ccerror.ServiceOfferingNameAmbiguityError{ 667 ServiceOfferingName: "duplicate-offering", 668 ServiceBrokerNames: []string{"a-broker", "another-broker"}, 669 }) 670 }) 671 672 It("returns an error", func() { 673 _, warnings, err := actor.DisableServiceAccess("duplicate-offering", "", "", "") 674 Expect(warnings).To(ContainElement("another warning")) 675 Expect(err).To(MatchError("Service 'duplicate-offering' is provided by multiple service brokers: a-broker, another-broker\nSpecify a broker by using the '-b' flag.")) 676 }) 677 }) 678 }) 679 680 Describe("fetching service plans", func() { 681 It("gets all plans for the service offering", func() { 682 _, warnings, err := actor.DisableServiceAccess("fake-offering", "fake-broker-name", "", "") 683 Expect(err).NotTo(HaveOccurred()) 684 Expect(warnings).To(ContainElements("some warning", "other warning")) 685 686 Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1)) 687 Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(0)).To(ConsistOf(ccv3.Query{ 688 Key: ccv3.ServiceOfferingGUIDsFilter, 689 Values: []string{"fake-offering-guid"}, 690 })) 691 }) 692 693 When("a plan name is specified", func() { 694 It("filters by plan name and service offering GUID", func() { 695 _, warnings, err := actor.DisableServiceAccess("fake-offering", "fake-broker-name", "", "fake-plan-name") 696 Expect(err).NotTo(HaveOccurred()) 697 Expect(warnings).To(ContainElements("some warning", "other warning")) 698 699 Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1)) 700 Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(0)).To(ConsistOf( 701 ccv3.Query{ 702 Key: ccv3.ServiceOfferingGUIDsFilter, 703 Values: []string{"fake-offering-guid"}, 704 }, 705 ccv3.Query{ 706 Key: ccv3.NameFilter, 707 Values: []string{"fake-plan-name"}, 708 }, 709 )) 710 }) 711 }) 712 713 When("no plans were found", func() { 714 BeforeEach(func() { 715 fakeCloudControllerClient.GetServicePlansReturns([]resources.ServicePlan{}, ccv3.Warnings{"other warning"}, nil) 716 }) 717 718 It("fails", func() { 719 _, warnings, err := actor.DisableServiceAccess("fake-offering", "fake-broker-name", "", "fake-plan-name") 720 Expect(err).To(MatchError(actionerror.ServicePlanNotFoundError{ 721 OfferingName: "fake-offering", 722 PlanName: "fake-plan-name", 723 })) 724 Expect(warnings).To(ContainElements("some warning", "other warning")) 725 }) 726 }) 727 728 When("fetching the plans fail", func() { 729 BeforeEach(func() { 730 fakeCloudControllerClient.GetServicePlansReturns([]resources.ServicePlan{}, ccv3.Warnings{"other warning"}, errors.New("fetch plans error")) 731 }) 732 733 It("fails", func() { 734 _, warnings, err := actor.DisableServiceAccess("", "", "", "") 735 Expect(err).To(MatchError("fetch plans error")) 736 Expect(warnings).To(ContainElements("some warning", "other warning")) 737 }) 738 }) 739 }) 740 741 Context("with org", func() { 742 BeforeEach(func() { 743 fakeCloudControllerClient.DeleteServicePlanVisibilityReturns( 744 ccv3.Warnings{"delete warning"}, 745 nil, 746 ) 747 }) 748 749 It("disables visibility to orgs", func() { 750 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "fake-org-name", "") 751 752 Expect(err).NotTo(HaveOccurred()) 753 Expect(warnings).To(ConsistOf("some warning", "other warning", "delete warning", "delete warning", "org warning")) 754 755 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(0)) 756 Expect(fakeCloudControllerClient.DeleteServicePlanVisibilityCallCount()).To(Equal(2)) 757 758 planGUID, orgGUID := fakeCloudControllerClient.DeleteServicePlanVisibilityArgsForCall(0) 759 Expect(planGUID).To(Equal("fake-plan-guid-1")) 760 Expect(orgGUID).To(Equal("org-guid")) 761 762 planGUID, orgGUID = fakeCloudControllerClient.DeleteServicePlanVisibilityArgsForCall(1) 763 Expect(planGUID).To(Equal("fake-plan-guid-2")) 764 Expect(orgGUID).To(Equal("org-guid")) 765 }) 766 767 When("one of the plans is public", func() { 768 It("fails and does not update other plans", func() { 769 fakeCloudControllerClient.GetServicePlansReturns( 770 []resources.ServicePlan{ 771 {Name: "fake-plan-1", GUID: "fake-plan-guid-1", VisibilityType: "organization"}, 772 {Name: "fake-plan-2", GUID: "fake-plan-guid-2", VisibilityType: "organization"}, 773 {Name: "fake-plan-3", GUID: "fake-plan-guid-3", VisibilityType: "public"}, 774 {Name: "fake-plan-4", GUID: "fake-plan-guid-4", VisibilityType: "organization"}, 775 }, 776 ccv3.Warnings{"other warning"}, 777 nil, 778 ) 779 780 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "fake-org-name", "") 781 Expect(err).To(MatchError("Cannot remove organization level access for public plans.")) 782 Expect(fakeCloudControllerClient.DeleteServicePlanVisibilityCallCount()).To(Equal(0)) 783 Expect(warnings).To(ConsistOf("some warning", "other warning", "org warning")) 784 }) 785 }) 786 787 When("there are admin access plans", func() { 788 It("reports that they were skipped", func() { 789 fakeCloudControllerClient.GetServicePlansReturns( 790 []resources.ServicePlan{ 791 {Name: "fake-plan-1", GUID: "fake-plan-guid-1", VisibilityType: "admin"}, 792 {Name: "fake-plan-2", GUID: "fake-plan-guid-2", VisibilityType: "organization"}, 793 {Name: "fake-plan-3", GUID: "fake-plan-guid-3", VisibilityType: "organization"}, 794 {Name: "fake-plan-4", GUID: "fake-plan-guid-4", VisibilityType: "admin"}, 795 }, 796 ccv3.Warnings{"other warning"}, 797 nil, 798 ) 799 800 skipped, warnings, err := actor.DisableServiceAccess("fake-offering", "", "fake-org-name", "") 801 Expect(err).NotTo(HaveOccurred()) 802 Expect(warnings).To(ConsistOf("some warning", "other warning", "org warning", "delete warning", "delete warning")) 803 804 Expect(skipped).To(ConsistOf("fake-plan-1", "fake-plan-4")) 805 806 Expect(fakeCloudControllerClient.DeleteServicePlanVisibilityCallCount()).To(Equal(2)) 807 }) 808 }) 809 810 When("the org does not exist", func() { 811 It("returns an error", func() { 812 fakeCloudControllerClient.GetOrganizationsReturns([]resources.Organization{}, ccv3.Warnings{"org warning"}, nil) 813 814 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "fake-org-name", "") 815 Expect(err).To(MatchError(actionerror.OrganizationNotFoundError{ 816 Name: "fake-org-name", 817 })) 818 Expect(warnings).To(ConsistOf("some warning", "other warning", "org warning")) 819 }) 820 }) 821 822 When("deleting access fails", func() { 823 It("fails", func() { 824 fakeCloudControllerClient.DeleteServicePlanVisibilityReturns( 825 ccv3.Warnings{"delete warning"}, 826 errors.New("delete failed"), 827 ) 828 829 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "fake-org-name", "") 830 Expect(err).To(MatchError("delete failed")) 831 Expect(warnings).To(ConsistOf("some warning", "other warning", "org warning", "delete warning")) 832 833 }) 834 }) 835 }) 836 837 When("there are admin access plans", func() { 838 It("reports that they were skipped", func() { 839 fakeCloudControllerClient.GetServicePlansReturns( 840 []resources.ServicePlan{ 841 {Name: "fake-plan-1", GUID: "fake-plan-guid-1", VisibilityType: "admin"}, 842 {Name: "fake-plan-2", GUID: "fake-plan-guid-2", VisibilityType: "organization"}, 843 {Name: "fake-plan-3", GUID: "fake-plan-guid-3", VisibilityType: "organization"}, 844 {Name: "fake-plan-4", GUID: "fake-plan-guid-4", VisibilityType: "admin"}, 845 }, 846 ccv3.Warnings{"other warning"}, 847 nil, 848 ) 849 850 skipped, warnings, err := actor.DisableServiceAccess("fake-offering", "", "", "") 851 Expect(err).NotTo(HaveOccurred()) 852 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning", "post warning")) 853 854 Expect(skipped).To(ConsistOf("fake-plan-1", "fake-plan-4")) 855 856 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(2)) 857 }) 858 }) 859 860 When("setting visibility fails", func() { 861 BeforeEach(func() { 862 fakeCloudControllerClient.UpdateServicePlanVisibilityReturns( 863 resources.ServicePlanVisibility{}, 864 ccv3.Warnings{"post warning"}, 865 errors.New("post error"), 866 ) 867 }) 868 869 It("returns error and stops setting visibility for the remaining plans", func() { 870 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "", "") 871 872 Expect(err).To(HaveOccurred()) 873 Expect(err).To(MatchError("post error")) 874 875 Expect(fakeCloudControllerClient.UpdateServicePlanVisibilityCallCount()).To(Equal(1)) 876 Expect(warnings).To(ConsistOf("some warning", "other warning", "post warning")) 877 }) 878 }) 879 880 When("the plan has visibility type 'space'", func() { 881 It("returns the appropriate error", func() { 882 fakeCloudControllerClient.GetServicePlansReturns( 883 []resources.ServicePlan{ 884 {GUID: "fake-plan-guid-1", VisibilityType: "space"}, 885 }, 886 ccv3.Warnings{"other warning"}, 887 nil, 888 ) 889 _, warnings, err := actor.DisableServiceAccess("fake-offering", "", "", "") 890 Expect(err).To(MatchError(actionerror.ServicePlanVisibilityTypeError{})) 891 Expect(warnings).To(ContainElement("other warning")) 892 }) 893 }) 894 }) 895 }) 896 897 func fakeServicePlans() []ccv3.ServicePlanWithSpaceAndOrganization { 898 return []ccv3.ServicePlanWithSpaceAndOrganization{ 899 { 900 Name: "violet", 901 ServiceOfferingGUID: "magenta-offering-guid", 902 VisibilityType: "public", 903 }, 904 { 905 Name: "green", 906 ServiceOfferingGUID: "cyan-offering-guid", 907 VisibilityType: "space", 908 SpaceName: "some-space", 909 OrganizationName: "some-org", 910 }, 911 { 912 Name: "indigo", 913 ServiceOfferingGUID: "key-offering-guid", 914 VisibilityType: "space", 915 SpaceName: "some-space", 916 OrganizationName: "some-org", 917 }, 918 { 919 Name: "red", 920 ServiceOfferingGUID: "magenta-offering-guid", 921 VisibilityType: "public", 922 }, 923 { 924 Name: "yellow", 925 ServiceOfferingGUID: "yellow-offering-guid", 926 VisibilityType: "organization", 927 }, 928 { 929 Name: "orange", 930 ServiceOfferingGUID: "yellow-offering-guid", 931 VisibilityType: "organization", 932 }, 933 { 934 Name: "blue", 935 ServiceOfferingGUID: "cyan-offering-guid", 936 VisibilityType: "space", 937 SpaceName: "some-space", 938 OrganizationName: "some-org", 939 }, 940 } 941 } 942 943 func fakeServiceOfferings() []resources.ServiceOffering { 944 return []resources.ServiceOffering{ 945 { 946 GUID: "cyan-offering-guid", 947 Name: "cyan", 948 ServiceBrokerName: "sky-broker", 949 }, 950 { 951 GUID: "magenta-offering-guid", 952 Name: "magenta", 953 ServiceBrokerName: "sea-broker", 954 }, 955 { 956 GUID: "yellow-offering-guid", 957 Name: "yellow", 958 ServiceBrokerName: "land-broker", 959 }, 960 { 961 GUID: "key-offering-guid", 962 Name: "key", 963 ServiceBrokerName: "sky-broker", 964 }, 965 } 966 }