github.com/cloudfoundry/cli@v7.1.0+incompatible/actor/v2action/service_test.go (about)

     1  package v2action_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	. "code.cloudfoundry.org/cli/actor/v2action"
     9  	"code.cloudfoundry.org/cli/actor/v2action/v2actionfakes"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Service Actions", func() {
    17  	var (
    18  		actor                     *Actor
    19  		fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient
    20  	)
    21  
    22  	BeforeEach(func() {
    23  		fakeCloudControllerClient = new(v2actionfakes.FakeCloudControllerClient)
    24  		actor = NewActor(fakeCloudControllerClient, nil, nil)
    25  	})
    26  
    27  	Describe("GetService", func() {
    28  		var (
    29  			service         Service
    30  			serviceWarnings Warnings
    31  			serviceErr      error
    32  		)
    33  
    34  		JustBeforeEach(func() {
    35  			service, serviceWarnings, serviceErr = actor.GetService("some-service-guid")
    36  		})
    37  
    38  		When("no errors are encountered getting the service", func() {
    39  			var returnedService ccv2.Service
    40  
    41  			BeforeEach(func() {
    42  				returnedService = ccv2.Service{
    43  					GUID:             "some-service-guid",
    44  					Label:            "some-service",
    45  					Description:      "some-description",
    46  					DocumentationURL: "some-url",
    47  				}
    48  				fakeCloudControllerClient.GetServiceReturns(
    49  					returnedService,
    50  					ccv2.Warnings{"get-service-warning"},
    51  					nil)
    52  			})
    53  
    54  			It("returns the service and all warnings", func() {
    55  				Expect(serviceErr).ToNot(HaveOccurred())
    56  				Expect(service).To(Equal(Service(returnedService)))
    57  				Expect(serviceWarnings).To(ConsistOf("get-service-warning"))
    58  
    59  				Expect(fakeCloudControllerClient.GetServiceCallCount()).To(Equal(1))
    60  				Expect(fakeCloudControllerClient.GetServiceArgsForCall(0)).To(Equal("some-service-guid"))
    61  			})
    62  		})
    63  
    64  		When("an error is encountered getting the service", func() {
    65  			var expectedErr error
    66  
    67  			BeforeEach(func() {
    68  				expectedErr = errors.New("some-error")
    69  				fakeCloudControllerClient.GetServiceReturns(
    70  					ccv2.Service{},
    71  					ccv2.Warnings{"get-service-warning"},
    72  					expectedErr)
    73  			})
    74  
    75  			It("returns the errors and all warnings", func() {
    76  				Expect(serviceErr).To(MatchError(expectedErr))
    77  				Expect(serviceWarnings).To(ConsistOf("get-service-warning"))
    78  
    79  				Expect(fakeCloudControllerClient.GetServiceCallCount()).To(Equal(1))
    80  				Expect(fakeCloudControllerClient.GetServiceArgsForCall(0)).To(Equal("some-service-guid"))
    81  			})
    82  		})
    83  	})
    84  
    85  	Describe("GetServiceByNameAndBrokerName", func() {
    86  		var (
    87  			service           Service
    88  			serviceWarnings   Warnings
    89  			serviceErr        error
    90  			serviceBrokerName string
    91  		)
    92  
    93  		BeforeEach(func() {
    94  			serviceBrokerName = ""
    95  		})
    96  
    97  		JustBeforeEach(func() {
    98  			service, serviceWarnings, serviceErr = actor.GetServiceByNameAndBrokerName("some-service", serviceBrokerName)
    99  		})
   100  
   101  		When("broker name is empty", func() {
   102  			It("should not fetch a broker", func() {
   103  				Expect(fakeCloudControllerClient.GetServiceBrokersCallCount()).To(Equal(0))
   104  			})
   105  
   106  			When("one service is returned from the client", func() {
   107  				var returnedServices []ccv2.Service
   108  
   109  				BeforeEach(func() {
   110  					returnedServices = []ccv2.Service{
   111  						{
   112  							GUID:             "some-service-guid",
   113  							Label:            "some-service",
   114  							Description:      "some-description",
   115  							DocumentationURL: "some-url",
   116  						},
   117  					}
   118  
   119  					fakeCloudControllerClient.GetServicesReturns(
   120  						returnedServices,
   121  						ccv2.Warnings{"get-services-warning"},
   122  						nil)
   123  				})
   124  
   125  				It("returns the service and all warnings", func() {
   126  					Expect(serviceErr).ToNot(HaveOccurred())
   127  					Expect(service).To(Equal(Service(returnedServices[0])))
   128  					Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   129  
   130  					Expect(fakeCloudControllerClient.GetServicesCallCount()).To(Equal(1))
   131  					Expect(fakeCloudControllerClient.GetServicesArgsForCall(0)).To(Equal([]ccv2.Filter{{
   132  						Type:     constant.LabelFilter,
   133  						Operator: constant.EqualOperator,
   134  						Values:   []string{"some-service"},
   135  					}}))
   136  				})
   137  			})
   138  
   139  			When("multiple services are returned from the client", func() {
   140  				var returnedServices []ccv2.Service
   141  
   142  				BeforeEach(func() {
   143  					returnedServices = []ccv2.Service{
   144  						{
   145  							GUID:             "some-service-1-guid",
   146  							Label:            "some-service-1",
   147  							Description:      "some-description",
   148  							DocumentationURL: "some-url",
   149  						},
   150  						{
   151  							GUID:             "some-service-2-guid",
   152  							Label:            "some-service-2",
   153  							Description:      "some-description",
   154  							DocumentationURL: "some-url",
   155  						},
   156  					}
   157  
   158  					fakeCloudControllerClient.GetServicesReturns(
   159  						returnedServices,
   160  						ccv2.Warnings{"get-services-warning"},
   161  						nil)
   162  				})
   163  
   164  				It("returns a DuplicateServiceError and all warnings", func() {
   165  					Expect(serviceErr).To(MatchError(actionerror.DuplicateServiceError{Name: "some-service"}))
   166  					Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   167  				})
   168  
   169  			})
   170  		})
   171  
   172  		When("broker name is provided", func() {
   173  			var returnedBrokers []ccv2.ServiceBroker
   174  
   175  			BeforeEach(func() {
   176  				serviceBrokerName = "some-broker"
   177  
   178  				returnedBrokers = []ccv2.ServiceBroker{
   179  					{
   180  						Name: "some-broker",
   181  						GUID: "some-broker-guid",
   182  					},
   183  				}
   184  
   185  				fakeCloudControllerClient.GetServiceBrokersReturns(
   186  					returnedBrokers,
   187  					ccv2.Warnings{"get-services-warning"},
   188  					nil)
   189  			})
   190  
   191  			It("fetches the the broker by name", func() {
   192  				Expect(fakeCloudControllerClient.GetServiceBrokersCallCount()).To(Equal(1))
   193  				Expect(fakeCloudControllerClient.GetServiceBrokersArgsForCall(0)).To(Equal([]ccv2.Filter{{
   194  					Type:     constant.NameFilter,
   195  					Operator: constant.EqualOperator,
   196  					Values:   []string{serviceBrokerName},
   197  				}}))
   198  			})
   199  
   200  			When("fetching the broker by name errors", func() {
   201  				BeforeEach(func() {
   202  					fakeCloudControllerClient.GetServiceBrokersReturns(
   203  						nil,
   204  						ccv2.Warnings{"get-services-warning"},
   205  						errors.New("failed-to-fetch-broker"))
   206  				})
   207  
   208  				It("propagates the error and all warnings", func() {
   209  					Expect(serviceErr).To(MatchError("failed-to-fetch-broker"))
   210  					Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   211  				})
   212  			})
   213  
   214  			When("one service is returned from the client", func() {
   215  				var returnedServices []ccv2.Service
   216  
   217  				BeforeEach(func() {
   218  					returnedServices = []ccv2.Service{
   219  						{
   220  							GUID:              "some-service-guid",
   221  							Label:             "some-service",
   222  							Description:       "some-description",
   223  							DocumentationURL:  "some-url",
   224  							ServiceBrokerName: "some-broker",
   225  						},
   226  					}
   227  
   228  					fakeCloudControllerClient.GetServicesReturns(
   229  						returnedServices,
   230  						ccv2.Warnings{"get-services-warning"},
   231  						nil)
   232  				})
   233  
   234  				It("returns the service filtered by label and broker guid and all warnings", func() {
   235  					Expect(serviceErr).ToNot(HaveOccurred())
   236  					Expect(service).To(Equal(Service(returnedServices[0])))
   237  					Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   238  
   239  					Expect(fakeCloudControllerClient.GetServicesCallCount()).To(Equal(1))
   240  					Expect(fakeCloudControllerClient.GetServicesArgsForCall(0)).To(ConsistOf(
   241  						ccv2.Filter{
   242  							Type:     constant.LabelFilter,
   243  							Operator: constant.EqualOperator,
   244  							Values:   []string{"some-service"},
   245  						},
   246  						ccv2.Filter{
   247  							Type:     constant.ServiceBrokerGUIDFilter,
   248  							Operator: constant.EqualOperator,
   249  							Values:   []string{"some-broker-guid"},
   250  						},
   251  					))
   252  				})
   253  			})
   254  		})
   255  
   256  		When("there are no services returned by the client", func() {
   257  			BeforeEach(func() {
   258  				fakeCloudControllerClient.GetServicesReturns(
   259  					[]ccv2.Service{},
   260  					ccv2.Warnings{"get-services-warning"},
   261  					nil)
   262  			})
   263  
   264  			It("returns a ServiceNotFoundError and all warnings", func() {
   265  				Expect(serviceErr).To(MatchError(actionerror.ServiceNotFoundError{Name: "some-service"}))
   266  				Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   267  			})
   268  		})
   269  
   270  		When("the client returns an error", func() {
   271  			BeforeEach(func() {
   272  				fakeCloudControllerClient.GetServicesReturns(
   273  					[]ccv2.Service{},
   274  					ccv2.Warnings{"get-services-warning"},
   275  					errors.New("client-error"))
   276  			})
   277  
   278  			It("propagates the error and all warnings", func() {
   279  				Expect(serviceErr).To(MatchError(errors.New("client-error")))
   280  				Expect(serviceWarnings).To(ConsistOf("get-services-warning"))
   281  			})
   282  		})
   283  	})
   284  
   285  	Describe("GetServicesWithPlans", func() {
   286  		When("the broker has no services", func() {
   287  			BeforeEach(func() {
   288  				fakeCloudControllerClient.GetServicesReturns([]ccv2.Service{}, nil, nil)
   289  			})
   290  
   291  			It("returns no services", func() {
   292  				servicesWithPlans, _, err := actor.GetServicesWithPlans(Filter{
   293  					Type:     constant.ServiceBrokerGUIDFilter,
   294  					Operator: constant.EqualOperator,
   295  					Values:   []string{"some-broker-guid"},
   296  				})
   297  				Expect(err).NotTo(HaveOccurred())
   298  
   299  				Expect(servicesWithPlans).To(HaveLen(0))
   300  			})
   301  		})
   302  
   303  		When("there is a service with no plans", func() {
   304  			BeforeEach(func() {
   305  				fakeCloudControllerClient.GetServicesReturns(
   306  					[]ccv2.Service{
   307  						{
   308  							GUID:  "some-service-guid-1",
   309  							Label: "some-service-label-1",
   310  						},
   311  					},
   312  					nil, nil)
   313  
   314  				fakeCloudControllerClient.GetServicePlansReturns([]ccv2.ServicePlan{}, nil, nil)
   315  			})
   316  
   317  			It("returns a service with no plans", func() {
   318  				servicesWithPlans, _, err := actor.GetServicesWithPlans(Filter{
   319  					Type:     constant.ServiceBrokerGUIDFilter,
   320  					Operator: constant.EqualOperator,
   321  					Values:   []string{"some-broker-guid"},
   322  				})
   323  				Expect(err).NotTo(HaveOccurred())
   324  
   325  				Expect(servicesWithPlans).To(HaveLen(1))
   326  				Expect(servicesWithPlans).To(HaveKeyWithValue(
   327  					Service{GUID: "some-service-guid-1", Label: "some-service-label-1"},
   328  					[]ServicePlan{},
   329  				))
   330  			})
   331  		})
   332  
   333  		When("there are services with plans", func() {
   334  			BeforeEach(func() {
   335  				fakeCloudControllerClient.GetServicesReturns(
   336  					[]ccv2.Service{
   337  						{
   338  							GUID:  "some-service-guid-1",
   339  							Label: "some-service-label-1",
   340  						},
   341  						{
   342  							GUID:  "some-service-guid-2",
   343  							Label: "some-service-label-2",
   344  						},
   345  					},
   346  					ccv2.Warnings{"get-service-warning"}, nil)
   347  
   348  				fakeCloudControllerClient.GetServicePlansReturnsOnCall(0,
   349  					[]ccv2.ServicePlan{
   350  						{
   351  							GUID: "some-plan-guid-1",
   352  							Name: "some-plan-name-1",
   353  						},
   354  						{
   355  							GUID: "some-plan-guid-2",
   356  							Name: "some-plan-name-2",
   357  						},
   358  					},
   359  					ccv2.Warnings{"get-plan-warning"}, nil)
   360  				fakeCloudControllerClient.GetServicePlansReturnsOnCall(1,
   361  					[]ccv2.ServicePlan{
   362  						{
   363  							GUID: "some-plan-guid-3",
   364  							Name: "some-plan-name-3",
   365  						},
   366  						{
   367  							GUID: "some-plan-guid-4",
   368  							Name: "some-plan-name-4",
   369  						},
   370  					},
   371  					nil, nil)
   372  			})
   373  
   374  			It("returns all services with associated plans and warnings", func() {
   375  				servicesWithPlans, warnings, err := actor.GetServicesWithPlans(Filter{
   376  					Type:     constant.ServiceBrokerGUIDFilter,
   377  					Operator: constant.EqualOperator,
   378  					Values:   []string{"some-broker-guid"},
   379  				},
   380  				)
   381  				Expect(err).NotTo(HaveOccurred())
   382  
   383  				Expect(servicesWithPlans).To(HaveLen(2))
   384  				Expect(servicesWithPlans).To(HaveKeyWithValue(
   385  					Service{GUID: "some-service-guid-1", Label: "some-service-label-1"},
   386  					[]ServicePlan{
   387  						{GUID: "some-plan-guid-1", Name: "some-plan-name-1"},
   388  						{GUID: "some-plan-guid-2", Name: "some-plan-name-2"},
   389  					},
   390  				))
   391  				Expect(servicesWithPlans).To(HaveKeyWithValue(
   392  					Service{GUID: "some-service-guid-2", Label: "some-service-label-2"},
   393  					[]ServicePlan{
   394  						{GUID: "some-plan-guid-3", Name: "some-plan-name-3"},
   395  						{GUID: "some-plan-guid-4", Name: "some-plan-name-4"},
   396  					},
   397  				))
   398  				Expect(fakeCloudControllerClient.GetServicesCallCount()).To(Equal(1))
   399  				Expect(fakeCloudControllerClient.GetServicesArgsForCall(0)).To(ConsistOf(ccv2.Filter{
   400  					Type:     constant.ServiceBrokerGUIDFilter,
   401  					Operator: constant.EqualOperator,
   402  					Values:   []string{"some-broker-guid"},
   403  				}))
   404  
   405  				Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(2))
   406  				Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(0)).To(ConsistOf(ccv2.Filter{
   407  					Type:     constant.ServiceGUIDFilter,
   408  					Operator: constant.EqualOperator,
   409  					Values:   []string{"some-service-guid-1"},
   410  				}))
   411  				Expect(fakeCloudControllerClient.GetServicePlansArgsForCall(1)).To(ConsistOf(ccv2.Filter{
   412  					Type:     constant.ServiceGUIDFilter,
   413  					Operator: constant.EqualOperator,
   414  					Values:   []string{"some-service-guid-2"},
   415  				}))
   416  
   417  				Expect(warnings).To(ConsistOf("get-service-warning", "get-plan-warning"))
   418  			})
   419  
   420  			When("a service name is provided", func() {
   421  				It("filters by service label", func() {
   422  					_, _, err := actor.GetServicesWithPlans(Filter{
   423  						Type:     constant.ServiceBrokerGUIDFilter,
   424  						Operator: constant.EqualOperator,
   425  						Values:   []string{"some-broker-guid"},
   426  					},
   427  						Filter{
   428  							Type:     constant.LabelFilter,
   429  							Operator: constant.EqualOperator,
   430  							Values:   []string{"some-service-name"},
   431  						})
   432  					Expect(err).NotTo(HaveOccurred())
   433  
   434  					Expect(fakeCloudControllerClient.GetServicesCallCount()).To(Equal(1))
   435  					Expect(fakeCloudControllerClient.GetServicesArgsForCall(0)).To(ConsistOf(
   436  						ccv2.Filter{
   437  							Type:     constant.ServiceBrokerGUIDFilter,
   438  							Operator: constant.EqualOperator,
   439  							Values:   []string{"some-broker-guid"},
   440  						},
   441  						ccv2.Filter{
   442  							Type:     constant.LabelFilter,
   443  							Operator: constant.EqualOperator,
   444  							Values:   []string{"some-service-name"},
   445  						},
   446  					))
   447  				})
   448  			})
   449  		})
   450  
   451  		When("fetching services returns an error", func() {
   452  			BeforeEach(func() {
   453  				fakeCloudControllerClient.GetServicesReturns([]ccv2.Service{}, ccv2.Warnings{"get-service-warning"}, errors.New("EXPLODE"))
   454  			})
   455  
   456  			It("propagates the error and warnings", func() {
   457  				_, warnings, err := actor.GetServicesWithPlans(Filter{
   458  					Type:     constant.ServiceBrokerGUIDFilter,
   459  					Operator: constant.EqualOperator,
   460  					Values:   []string{"some-broker-guid"},
   461  				})
   462  				Expect(err).To(MatchError("EXPLODE"))
   463  
   464  				Expect(warnings).To(ConsistOf("get-service-warning"))
   465  			})
   466  		})
   467  
   468  		When("fetching plans for a service returns an error", func() {
   469  			BeforeEach(func() {
   470  				fakeCloudControllerClient.GetServicesReturns(
   471  					[]ccv2.Service{
   472  						{
   473  							GUID:  "some-service-guid-1",
   474  							Label: "some-service-label-1",
   475  						},
   476  					},
   477  					ccv2.Warnings{"get-service-warning"}, nil)
   478  
   479  				fakeCloudControllerClient.GetServicePlansReturns([]ccv2.ServicePlan{}, ccv2.Warnings{"get-plan-warning"}, errors.New("EXPLODE"))
   480  			})
   481  
   482  			It("propagates the error and warnings", func() {
   483  				_, warnings, err := actor.GetServicesWithPlans(Filter{
   484  					Type:     constant.ServiceBrokerGUIDFilter,
   485  					Operator: constant.EqualOperator,
   486  					Values:   []string{"some-broker-guid"},
   487  				})
   488  
   489  				Expect(err).To(MatchError("EXPLODE"))
   490  
   491  				Expect(warnings).To(ConsistOf("get-service-warning", "get-plan-warning"))
   492  			})
   493  		})
   494  	})
   495  
   496  	Describe("ServiceExistsWithName", func() {
   497  		var (
   498  			exists   bool
   499  			warnings Warnings
   500  			err      error
   501  		)
   502  
   503  		JustBeforeEach(func() {
   504  			exists, warnings, err = actor.ServiceExistsWithName("some-service")
   505  		})
   506  
   507  		When("a service exists with that name", func() {
   508  			BeforeEach(func() {
   509  				fakeCloudControllerClient.GetServicesReturns([]ccv2.Service{
   510  					{
   511  						GUID:             "some-service-guid",
   512  						Label:            "some-service",
   513  						Description:      "some-description",
   514  						DocumentationURL: "some-url",
   515  					},
   516  				}, ccv2.Warnings{"warning-1", "warning-2"}, nil)
   517  			})
   518  
   519  			It("succeeds, returning true and warnings", func() {
   520  				Expect(exists).To(BeTrue())
   521  				Expect(err).NotTo(HaveOccurred())
   522  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   523  
   524  				Expect(fakeCloudControllerClient.GetServicesCallCount()).To(Equal(1))
   525  				filters := fakeCloudControllerClient.GetServicesArgsForCall(0)
   526  				Expect(filters).To(Equal(
   527  					[]ccv2.Filter{{
   528  						Type:     constant.LabelFilter,
   529  						Operator: constant.EqualOperator,
   530  						Values:   []string{"some-service"},
   531  					}}))
   532  			})
   533  		})
   534  
   535  		When("no service exists with that name", func() {
   536  			BeforeEach(func() {
   537  				fakeCloudControllerClient.GetServicesReturns([]ccv2.Service{}, ccv2.Warnings{"warning-1", "warning-2"}, nil)
   538  			})
   539  
   540  			It("returns false and warnings", func() {
   541  				Expect(exists).To(BeFalse())
   542  				Expect(err).NotTo(HaveOccurred())
   543  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   544  			})
   545  		})
   546  
   547  		When("fetching services throws an error", func() {
   548  			BeforeEach(func() {
   549  				fakeCloudControllerClient.GetServicesReturns([]ccv2.Service{}, ccv2.Warnings{"warning-1", "warning-2"}, errors.New("boom"))
   550  			})
   551  
   552  			It("propagates the error and warnings", func() {
   553  				Expect(err).To(MatchError("boom"))
   554  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   555  			})
   556  		})
   557  	})
   558  
   559  	Describe("PurgeServiceOffering", func() {
   560  		var (
   561  			warnings Warnings
   562  			purgeErr error
   563  		)
   564  
   565  		JustBeforeEach(func() {
   566  			warnings, purgeErr = actor.PurgeServiceOffering(Service{
   567  				Label: "some-service",
   568  				GUID:  "some-service-guid",
   569  			})
   570  		})
   571  
   572  		When("purging the service succeeds", func() {
   573  			BeforeEach(func() {
   574  				fakeCloudControllerClient.DeleteServiceReturns(
   575  					ccv2.Warnings{"delete-service-warning"},
   576  					nil,
   577  				)
   578  			})
   579  
   580  			It("should purge the returned service instance and return any warnings", func() {
   581  				Expect(purgeErr).NotTo(HaveOccurred())
   582  				Expect(warnings).To(ConsistOf("delete-service-warning"))
   583  
   584  				Expect(fakeCloudControllerClient.DeleteServiceCallCount()).To(Equal(1))
   585  
   586  				serviceOfferingBeingPurged, purge := fakeCloudControllerClient.DeleteServiceArgsForCall(0)
   587  				Expect(serviceOfferingBeingPurged).To(Equal("some-service-guid"))
   588  				Expect(purge).To(BeTrue())
   589  			})
   590  		})
   591  
   592  		When("purging the service fails", func() {
   593  			BeforeEach(func() {
   594  				fakeCloudControllerClient.DeleteServiceReturns(
   595  					ccv2.Warnings{"delete-service-warning"},
   596  					fmt.Errorf("it didn't work"),
   597  				)
   598  			})
   599  
   600  			It("should return the error and any warnings", func() {
   601  				Expect(purgeErr).To(MatchError(fmt.Errorf("it didn't work")))
   602  				Expect(warnings).To(ConsistOf("delete-service-warning"))
   603  			})
   604  		})
   605  	})
   606  })