github.com/cloudfoundry/cli@v7.1.0+incompatible/cf/commands/service/service_test.go (about)

     1  package service_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/cf/api"
     5  	"code.cloudfoundry.org/cli/cf/commandregistry"
     6  	"code.cloudfoundry.org/cli/cf/commands/service"
     7  	"code.cloudfoundry.org/cli/cf/flags"
     8  	"code.cloudfoundry.org/cli/cf/models"
     9  	"code.cloudfoundry.org/cli/cf/requirements"
    10  
    11  	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"
    12  	testterm "code.cloudfoundry.org/cli/cf/util/testhelpers/terminal"
    13  
    14  	"fmt"
    15  
    16  	"code.cloudfoundry.org/cli/cf/api/applications/applicationsfakes"
    17  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    18  	"code.cloudfoundry.org/cli/plugin/models"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  )
    22  
    23  var _ = Describe("service command", func() {
    24  	var (
    25  		ui                         *testterm.FakeUI
    26  		deps                       commandregistry.Dependency
    27  		flagContext                flags.FlagContext
    28  		reqFactory                 *requirementsfakes.FakeFactory
    29  		loginRequirement           requirements.Requirement
    30  		targetedSpaceRequirement   requirements.Requirement
    31  		serviceInstanceRequirement *requirementsfakes.FakeServiceInstanceRequirement
    32  		pluginCall                 bool
    33  
    34  		cmd *service.ShowService
    35  	)
    36  
    37  	BeforeEach(func() {
    38  		ui = &testterm.FakeUI{}
    39  		pluginCall = false
    40  
    41  		appRepo := new(applicationsfakes.FakeRepository)
    42  		appRepo.GetAppStub = func(appGUID string) (models.Application, error) {
    43  			if appGUID == "app1-guid" {
    44  				return models.Application{
    45  					ApplicationFields: models.ApplicationFields{
    46  						Name: "app1",
    47  					},
    48  				}, nil
    49  			}
    50  			return models.Application{}, fmt.Errorf("Called stubbed applications repo GetApp with incorrect app GUID\nExpected \"app1-guid\"\nGot \"%s\"\n", appGUID)
    51  		}
    52  
    53  		deps = commandregistry.Dependency{
    54  			UI:           ui,
    55  			PluginModels: &commandregistry.PluginModels{},
    56  			RepoLocator:  api.RepositoryLocator{}.SetApplicationRepository(appRepo),
    57  		}
    58  
    59  		cmd = &service.ShowService{}
    60  
    61  		flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
    62  		reqFactory = new(requirementsfakes.FakeFactory)
    63  
    64  		loginRequirement = &passingRequirement{Name: "login-requirement"}
    65  		reqFactory.NewLoginRequirementReturns(loginRequirement)
    66  		targetedSpaceRequirement = &passingRequirement{Name: "targeted-space-requirement"}
    67  		reqFactory.NewTargetedSpaceRequirementReturns(targetedSpaceRequirement)
    68  		serviceInstanceRequirement = &requirementsfakes.FakeServiceInstanceRequirement{}
    69  		reqFactory.NewServiceInstanceRequirementReturns(serviceInstanceRequirement)
    70  	})
    71  
    72  	Describe("Requirements", func() {
    73  		BeforeEach(func() {
    74  			cmd.SetDependency(deps, pluginCall)
    75  		})
    76  
    77  		Context("when not provided exactly 1 argument", func() {
    78  			It("fails", func() {
    79  				err := flagContext.Parse("too", "many")
    80  				Expect(err).NotTo(HaveOccurred())
    81  				_, err = cmd.Requirements(reqFactory, flagContext)
    82  				Expect(err).To(HaveOccurred())
    83  				Expect(ui.Outputs()).To(ContainSubstrings(
    84  					[]string{"Incorrect Usage", "Requires an argument"},
    85  				))
    86  			})
    87  		})
    88  
    89  		Context("when provided exactly one arg", func() {
    90  			var actualRequirements []requirements.Requirement
    91  
    92  			BeforeEach(func() {
    93  				err := flagContext.Parse("service-name")
    94  				Expect(err).NotTo(HaveOccurred())
    95  				actualRequirements, err = cmd.Requirements(reqFactory, flagContext)
    96  				Expect(err).NotTo(HaveOccurred())
    97  			})
    98  
    99  			It("returns a LoginRequirement", func() {
   100  				Expect(reqFactory.NewLoginRequirementCallCount()).To(Equal(1))
   101  				Expect(actualRequirements).To(ContainElement(loginRequirement))
   102  			})
   103  
   104  			It("returns a TargetedSpaceRequirement", func() {
   105  				Expect(reqFactory.NewTargetedSpaceRequirementCallCount()).To(Equal(1))
   106  				Expect(actualRequirements).To(ContainElement(targetedSpaceRequirement))
   107  			})
   108  
   109  			It("returns a ServiceInstanceRequirement", func() {
   110  				Expect(reqFactory.NewServiceInstanceRequirementCallCount()).To(Equal(1))
   111  				Expect(actualRequirements).To(ContainElement(serviceInstanceRequirement))
   112  			})
   113  		})
   114  	})
   115  
   116  	Describe("Execute", func() {
   117  		var serviceInstance models.ServiceInstance
   118  
   119  		BeforeEach(func() {
   120  			serviceInstance = models.ServiceInstance{
   121  				ServiceInstanceFields: models.ServiceInstanceFields{
   122  					GUID: "service1-guid",
   123  					Name: "service1",
   124  					LastOperation: models.LastOperationFields{
   125  						Type:        "create",
   126  						State:       "in progress",
   127  						Description: "creating resource - step 1",
   128  						CreatedAt:   "created-date",
   129  						UpdatedAt:   "updated-date",
   130  					},
   131  					DashboardURL: "some-url",
   132  				},
   133  				ServiceBindings: []models.ServiceBindingFields{
   134  					models.ServiceBindingFields{
   135  						AppGUID: "app1-guid",
   136  					},
   137  				},
   138  				ServicePlan: models.ServicePlanFields{
   139  					GUID: "plan-guid",
   140  					Name: "plan-name",
   141  				},
   142  				ServiceOffering: models.ServiceOfferingFields{
   143  					Label:            "mysql",
   144  					DocumentationURL: "http://documentation.url",
   145  					Description:      "the-description",
   146  				},
   147  			}
   148  		})
   149  
   150  		JustBeforeEach(func() {
   151  			serviceInstanceRequirement.GetServiceInstanceReturns(serviceInstance)
   152  			cmd.SetDependency(deps, pluginCall)
   153  			cmd.Requirements(reqFactory, flagContext)
   154  			cmd.Execute(flagContext)
   155  		})
   156  
   157  		Context("when invoked by a plugin", func() {
   158  			var (
   159  				pluginModel *plugin_models.GetService_Model
   160  			)
   161  
   162  			BeforeEach(func() {
   163  				pluginModel = &plugin_models.GetService_Model{}
   164  				deps.PluginModels.Service = pluginModel
   165  				pluginCall = true
   166  				err := flagContext.Parse("service1")
   167  				Expect(err).NotTo(HaveOccurred())
   168  			})
   169  
   170  			It("populates the plugin model upon execution", func() {
   171  				Expect(pluginModel.Name).To(Equal("service1"))
   172  				Expect(pluginModel.Guid).To(Equal("service1-guid"))
   173  				Expect(pluginModel.LastOperation.Type).To(Equal("create"))
   174  				Expect(pluginModel.LastOperation.State).To(Equal("in progress"))
   175  				Expect(pluginModel.LastOperation.Description).To(Equal("creating resource - step 1"))
   176  				Expect(pluginModel.LastOperation.CreatedAt).To(Equal("created-date"))
   177  				Expect(pluginModel.LastOperation.UpdatedAt).To(Equal("updated-date"))
   178  				Expect(pluginModel.LastOperation.Type).To(Equal("create"))
   179  				Expect(pluginModel.ServicePlan.Name).To(Equal("plan-name"))
   180  				Expect(pluginModel.ServicePlan.Guid).To(Equal("plan-guid"))
   181  				Expect(pluginModel.ServiceOffering.DocumentationUrl).To(Equal("http://documentation.url"))
   182  				Expect(pluginModel.ServiceOffering.Name).To(Equal("mysql"))
   183  			})
   184  		})
   185  
   186  		Context("when the service is externally provided", func() {
   187  			Context("when only the service name is specified", func() {
   188  				BeforeEach(func() {
   189  					err := flagContext.Parse("service1")
   190  					Expect(err).NotTo(HaveOccurred())
   191  				})
   192  
   193  				It("shows the service", func() {
   194  					Expect(ui.Outputs()).To(ContainSubstrings(
   195  						[]string{"Service instance:", "service1"},
   196  						[]string{"Service: ", "mysql"},
   197  						[]string{"Bound apps: ", "app1"},
   198  						[]string{"Plan: ", "plan-name"},
   199  						[]string{"Description: ", "the-description"},
   200  						[]string{"Documentation url: ", "http://documentation.url"},
   201  						[]string{"Dashboard: ", "some-url"},
   202  						[]string{"Last Operation"},
   203  						[]string{"Status: ", "create in progress"},
   204  						[]string{"Message: ", "creating resource - step 1"},
   205  						[]string{"Started: ", "created-date"},
   206  						[]string{"Updated: ", "updated-date"},
   207  					))
   208  				})
   209  
   210  				Context("when the service instance CreatedAt is empty", func() {
   211  					BeforeEach(func() {
   212  						serviceInstance.LastOperation.CreatedAt = ""
   213  					})
   214  
   215  					It("does not output the Started line", func() {
   216  						Expect(ui.Outputs()).To(ContainSubstrings(
   217  							[]string{"Service instance:", "service1"},
   218  							[]string{"Service: ", "mysql"},
   219  							[]string{"Bound apps: ", "app1"},
   220  							[]string{"Plan: ", "plan-name"},
   221  							[]string{"Description: ", "the-description"},
   222  							[]string{"Documentation url: ", "http://documentation.url"},
   223  							[]string{"Dashboard: ", "some-url"},
   224  							[]string{"Last Operation"},
   225  							[]string{"Status: ", "create in progress"},
   226  							[]string{"Message: ", "creating resource - step 1"},
   227  							[]string{"Updated: ", "updated-date"},
   228  						))
   229  						Expect(ui.Outputs()).ToNot(ContainSubstrings(
   230  							[]string{"Started: "},
   231  						))
   232  					})
   233  				})
   234  
   235  				Context("when the state is 'in progress'", func() {
   236  					BeforeEach(func() {
   237  						serviceInstance.LastOperation.State = "in progress"
   238  					})
   239  
   240  					It("shows status: `create in progress`", func() {
   241  						Expect(ui.Outputs()).To(ContainSubstrings(
   242  							[]string{"Status: ", "create in progress"},
   243  						))
   244  					})
   245  				})
   246  
   247  				Context("when the state is 'succeeded'", func() {
   248  					BeforeEach(func() {
   249  						serviceInstance.LastOperation.State = "succeeded"
   250  					})
   251  
   252  					It("shows status: `create succeeded`", func() {
   253  						Expect(ui.Outputs()).To(ContainSubstrings(
   254  							[]string{"Status: ", "create succeeded"},
   255  						))
   256  					})
   257  				})
   258  
   259  				Context("when the state is 'failed'", func() {
   260  					BeforeEach(func() {
   261  						serviceInstance.LastOperation.State = "failed"
   262  					})
   263  
   264  					It("shows status: `create failed`", func() {
   265  						Expect(ui.Outputs()).To(ContainSubstrings(
   266  							[]string{"Status: ", "create failed"},
   267  						))
   268  					})
   269  				})
   270  
   271  				Context("when the state is empty", func() {
   272  					BeforeEach(func() {
   273  						serviceInstance.LastOperation.State = ""
   274  					})
   275  
   276  					It("shows status: ``", func() {
   277  						Expect(ui.Outputs()).To(ContainSubstrings(
   278  							[]string{"Status: ", ""},
   279  						))
   280  					})
   281  				})
   282  			})
   283  
   284  			Context("when the guid flag is provided", func() {
   285  				BeforeEach(func() {
   286  					err := flagContext.Parse("--guid", "service1")
   287  					Expect(err).NotTo(HaveOccurred())
   288  				})
   289  
   290  				It("shows only the service guid", func() {
   291  					Expect(ui.Outputs()).To(ContainSubstrings(
   292  						[]string{"service1-guid"},
   293  					))
   294  
   295  					Expect(ui.Outputs()).ToNot(ContainSubstrings(
   296  						[]string{"Service instance:", "service1"},
   297  					))
   298  				})
   299  			})
   300  		})
   301  
   302  		Context("when the service is user provided", func() {
   303  			BeforeEach(func() {
   304  				serviceInstance = models.ServiceInstance{
   305  					ServiceInstanceFields: models.ServiceInstanceFields{
   306  						Name: "service1",
   307  						GUID: "service1-guid",
   308  						Type: "user_provided_service_instance",
   309  					},
   310  					ServiceBindings: []models.ServiceBindingFields{
   311  						models.ServiceBindingFields{
   312  							AppGUID: "app1-guid",
   313  						},
   314  					},
   315  				}
   316  
   317  				err := flagContext.Parse("service1")
   318  				Expect(err).NotTo(HaveOccurred())
   319  			})
   320  
   321  			It("shows user provided services", func() {
   322  				Expect(ui.Outputs()).To(ContainSubstrings(
   323  					[]string{"Service instance: ", "service1"},
   324  					[]string{"Service: ", "user-provided"},
   325  					[]string{"Bound apps: ", "app1"},
   326  				))
   327  			})
   328  		})
   329  
   330  		Context("when the service has tags", func() {
   331  			BeforeEach(func() {
   332  				serviceInstance = models.ServiceInstance{
   333  					ServiceInstanceFields: models.ServiceInstanceFields{
   334  						Tags: []string{"tag1", "tag2"},
   335  					},
   336  					ServicePlan: models.ServicePlanFields{GUID: "plan-guid", Name: "plan-name"},
   337  				}
   338  
   339  				err := flagContext.Parse("service1")
   340  				Expect(err).NotTo(HaveOccurred())
   341  			})
   342  
   343  			It("includes the tags in the output", func() {
   344  				Expect(ui.Outputs()).To(ContainSubstrings(
   345  					[]string{"Tags: ", "tag1, tag2"},
   346  				))
   347  			})
   348  		})
   349  	})
   350  })
   351  
   352  var _ = Describe("ServiceInstanceStateToStatus", func() {
   353  	var operationType string
   354  	Context("when the service is not user provided", func() {
   355  		isUserProvided := false
   356  
   357  		Context("when operationType is `create`", func() {
   358  			BeforeEach(func() { operationType = "create" })
   359  
   360  			It("returns status: `create in progress` when state: `in progress`", func() {
   361  				status := service.InstanceStateToStatus(operationType, "in progress", isUserProvided)
   362  				Expect(status).To(Equal("create in progress"))
   363  			})
   364  
   365  			It("returns status: `create succeeded` when state: `succeeded`", func() {
   366  				status := service.InstanceStateToStatus(operationType, "succeeded", isUserProvided)
   367  				Expect(status).To(Equal("create succeeded"))
   368  			})
   369  
   370  			It("returns status: `create failed` when state: `failed`", func() {
   371  				status := service.InstanceStateToStatus(operationType, "failed", isUserProvided)
   372  				Expect(status).To(Equal("create failed"))
   373  			})
   374  
   375  			It("returns status: `` when state: ``", func() {
   376  				status := service.InstanceStateToStatus(operationType, "", isUserProvided)
   377  				Expect(status).To(Equal(""))
   378  			})
   379  		})
   380  	})
   381  
   382  	Context("when the service is user provided", func() {
   383  		isUserProvided := true
   384  
   385  		It("returns status: `` when state: ``", func() {
   386  			status := service.InstanceStateToStatus(operationType, "", isUserProvided)
   387  			Expect(status).To(Equal(""))
   388  		})
   389  	})
   390  })