github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/cf/commands/service/create_service_test.go (about) 1 package service_test 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 8 "github.com/cloudfoundry/cli/cf/actors/service_builder/fakes" 9 "github.com/cloudfoundry/cli/cf/configuration/core_config" 10 "github.com/cloudfoundry/cli/cf/errors" 11 "github.com/cloudfoundry/cli/cf/models" 12 "github.com/cloudfoundry/cli/generic" 13 14 testapi "github.com/cloudfoundry/cli/cf/api/fakes" 15 testcmd "github.com/cloudfoundry/cli/testhelpers/commands" 16 testconfig "github.com/cloudfoundry/cli/testhelpers/configuration" 17 testreq "github.com/cloudfoundry/cli/testhelpers/requirements" 18 testterm "github.com/cloudfoundry/cli/testhelpers/terminal" 19 20 "github.com/cloudfoundry/cli/cf/command_registry" 21 22 . "github.com/onsi/ginkgo" 23 . "github.com/onsi/gomega" 24 25 . "github.com/cloudfoundry/cli/testhelpers/matchers" 26 ) 27 28 var _ = Describe("create-service command", func() { 29 var ( 30 ui *testterm.FakeUI 31 config core_config.Repository 32 requirementsFactory *testreq.FakeReqFactory 33 serviceRepo *testapi.FakeServiceRepo 34 serviceBuilder *fakes.FakeServiceBuilder 35 36 offering1 models.ServiceOffering 37 offering2 models.ServiceOffering 38 deps command_registry.Dependency 39 ) 40 41 updateCommandDependency := func(pluginCall bool) { 42 deps.Ui = ui 43 deps.Config = config 44 deps.RepoLocator = deps.RepoLocator.SetServiceRepository(serviceRepo) 45 deps.ServiceBuilder = serviceBuilder 46 command_registry.Commands.SetCommand(command_registry.Commands.FindCommand("create-service").SetDependency(deps, pluginCall)) 47 } 48 49 BeforeEach(func() { 50 ui = &testterm.FakeUI{} 51 config = testconfig.NewRepositoryWithDefaults() 52 requirementsFactory = &testreq.FakeReqFactory{LoginSuccess: true, TargetedSpaceSuccess: true} 53 serviceRepo = &testapi.FakeServiceRepo{} 54 serviceBuilder = &fakes.FakeServiceBuilder{} 55 56 offering1 = models.ServiceOffering{} 57 offering1.Label = "cleardb" 58 offering1.Plans = []models.ServicePlanFields{{ 59 Name: "spark", 60 Guid: "cleardb-spark-guid", 61 Free: true, 62 }, { 63 Name: "expensive", 64 Guid: "luxury-guid", 65 Free: false, 66 }} 67 68 offering2 = models.ServiceOffering{} 69 offering2.Label = "postgres" 70 71 serviceBuilder.GetServicesByNameForSpaceWithPlansReturns(models.ServiceOfferings([]models.ServiceOffering{offering1, offering2}), nil) 72 }) 73 74 var callCreateService = func(args []string) bool { 75 return testcmd.RunCliCommand("create-service", args, requirementsFactory, updateCommandDependency, false) 76 } 77 78 Describe("requirements", func() { 79 It("passes when logged in and a space is targeted", func() { 80 Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeTrue()) 81 }) 82 83 It("fails when not logged in", func() { 84 requirementsFactory.LoginSuccess = false 85 Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeFalse()) 86 }) 87 88 It("fails when a space is not targeted", func() { 89 requirementsFactory.TargetedSpaceSuccess = false 90 Expect(callCreateService([]string{"cleardb", "spark", "my-cleardb-service"})).To(BeFalse()) 91 }) 92 }) 93 94 It("successfully creates a service", func() { 95 callCreateService([]string{"cleardb", "spark", "my-cleardb-service"}) 96 97 spaceGuid, serviceName := serviceBuilder.GetServicesByNameForSpaceWithPlansArgsForCall(0) 98 Expect(spaceGuid).To(Equal(config.SpaceFields().Guid)) 99 Expect(serviceName).To(Equal("cleardb")) 100 Expect(ui.Outputs).To(ContainSubstrings( 101 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 102 []string{"OK"}, 103 )) 104 Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service")) 105 Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid")) 106 }) 107 108 Context("when passing in tags", func() { 109 It("sucessfully creates a service and passes the tags as json", func() { 110 callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-t", "tag1, tag2,tag3, tag4"}) 111 112 Expect(ui.Outputs).To(ContainSubstrings( 113 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 114 []string{"OK"}, 115 )) 116 Expect(serviceRepo.CreateServiceInstanceArgs.Tags).To(ConsistOf("tag1", "tag2", "tag3", "tag4")) 117 }) 118 }) 119 120 Context("when passing arbitrary params", func() { 121 Context("as a json string", func() { 122 It("successfully creates a service and passes the params as a json string", func() { 123 callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", `{"foo": "bar"}`}) 124 125 Expect(ui.Outputs).To(ContainSubstrings( 126 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 127 []string{"OK"}, 128 )) 129 Expect(serviceRepo.CreateServiceInstanceArgs.Params).To(Equal(map[string]interface{}{"foo": "bar"})) 130 }) 131 132 Context("that are not valid json", func() { 133 It("returns an error to the UI", func() { 134 callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", `bad-json`}) 135 136 Expect(ui.Outputs).To(ContainSubstrings( 137 []string{"FAILED"}, 138 []string{"Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object."}, 139 )) 140 }) 141 }) 142 }) 143 144 Context("as a file that contains json", func() { 145 var jsonFile *os.File 146 var params string 147 148 BeforeEach(func() { 149 params = "{\"foo\": \"bar\"}" 150 }) 151 152 AfterEach(func() { 153 if jsonFile != nil { 154 jsonFile.Close() 155 os.Remove(jsonFile.Name()) 156 } 157 }) 158 159 JustBeforeEach(func() { 160 var err error 161 jsonFile, err = ioutil.TempFile("", "") 162 Expect(err).ToNot(HaveOccurred()) 163 164 err = ioutil.WriteFile(jsonFile.Name(), []byte(params), os.ModePerm) 165 Expect(err).NotTo(HaveOccurred()) 166 }) 167 168 It("successfully creates a service and passes the params as a json", func() { 169 callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", jsonFile.Name()}) 170 171 Expect(ui.Outputs).To(ContainSubstrings( 172 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 173 []string{"OK"}, 174 )) 175 Expect(serviceRepo.CreateServiceInstanceArgs.Params).To(Equal(map[string]interface{}{"foo": "bar"})) 176 }) 177 178 Context("that are not valid json", func() { 179 BeforeEach(func() { 180 params = "bad-json" 181 }) 182 183 It("returns an error to the UI", func() { 184 callCreateService([]string{"cleardb", "spark", "my-cleardb-service", "-c", jsonFile.Name()}) 185 186 Expect(ui.Outputs).To(ContainSubstrings( 187 []string{"FAILED"}, 188 []string{"Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object."}, 189 )) 190 }) 191 }) 192 }) 193 }) 194 195 Context("when service creation is asynchronous", func() { 196 var serviceInstance models.ServiceInstance 197 198 BeforeEach(func() { 199 serviceInstance = models.ServiceInstance{ 200 ServiceInstanceFields: models.ServiceInstanceFields{ 201 Name: "my-cleardb-service", 202 LastOperation: models.LastOperationFields{ 203 Type: "create", 204 State: "in progress", 205 Description: "fake service instance description", 206 }, 207 }, 208 } 209 serviceRepo.FindInstanceByNameMap = generic.NewMap() 210 serviceRepo.FindInstanceByNameMap.Set("my-cleardb-service", serviceInstance) 211 }) 212 213 It("successfully starts async service creation", func() { 214 callCreateService([]string{"cleardb", "spark", "my-cleardb-service"}) 215 216 spaceGuid, serviceName := serviceBuilder.GetServicesByNameForSpaceWithPlansArgsForCall(0) 217 Expect(spaceGuid).To(Equal(config.SpaceFields().Guid)) 218 Expect(serviceName).To(Equal("cleardb")) 219 220 creatingServiceMessage := fmt.Sprintf("Create in progress. Use 'cf services' or 'cf service %s' to check operation status.", serviceInstance.ServiceInstanceFields.Name) 221 222 Expect(ui.Outputs).To(ContainSubstrings( 223 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 224 []string{"OK"}, 225 []string{creatingServiceMessage}, 226 )) 227 Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service")) 228 Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid")) 229 }) 230 231 It("fails when service instance could is created but cannot be found", func() { 232 serviceRepo.FindInstanceByNameErr = true 233 callCreateService([]string{"cleardb", "spark", "fake-service-instance-name"}) 234 235 Expect(ui.Outputs).To(ContainSubstrings( 236 []string{"Creating service instance fake-service-instance-name in org my-org / space my-space as my-user..."}, 237 []string{"FAILED"}, 238 []string{"Error finding instance"})) 239 }) 240 }) 241 242 Describe("warning the user about paid services", func() { 243 It("does not warn the user when the service is free", func() { 244 callCreateService([]string{"cleardb", "spark", "my-free-cleardb-service"}) 245 Expect(ui.Outputs).To(ContainSubstrings( 246 []string{"Creating service instance", "my-free-cleardb-service", "my-org", "my-space", "my-user"}, 247 []string{"OK"}, 248 )) 249 Expect(ui.Outputs).NotTo(ContainSubstrings([]string{"will incurr a cost"})) 250 }) 251 252 It("warns the user when the service is not free", func() { 253 callCreateService([]string{"cleardb", "expensive", "my-expensive-cleardb-service"}) 254 Expect(ui.Outputs).To(ContainSubstrings( 255 []string{"Creating service instance", "my-expensive-cleardb-service", "my-org", "my-space", "my-user"}, 256 []string{"OK"}, 257 []string{"Attention: The plan `expensive` of service `cleardb` is not free. The instance `my-expensive-cleardb-service` will incur a cost. Contact your administrator if you think this is in error."}, 258 )) 259 }) 260 }) 261 262 It("warns the user when the service already exists with the same service plan", func() { 263 serviceRepo.CreateServiceInstanceReturns.Error = errors.NewModelAlreadyExistsError("Service", "my-cleardb-service") 264 265 callCreateService([]string{"cleardb", "spark", "my-cleardb-service"}) 266 267 Expect(ui.Outputs).To(ContainSubstrings( 268 []string{"Creating service instance", "my-cleardb-service"}, 269 []string{"OK"}, 270 []string{"my-cleardb-service", "already exists"}, 271 )) 272 Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service")) 273 Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid")) 274 }) 275 276 Context("When there are multiple services with the same label", func() { 277 It("finds the plan even if it has to search multiple services", func() { 278 offering2.Label = "cleardb" 279 280 serviceRepo.CreateServiceInstanceReturns.Error = errors.NewModelAlreadyExistsError("Service", "my-cleardb-service") 281 callCreateService([]string{"cleardb", "spark", "my-cleardb-service"}) 282 283 Expect(ui.Outputs).To(ContainSubstrings( 284 []string{"Creating service instance", "my-cleardb-service", "my-org", "my-space", "my-user"}, 285 []string{"OK"}, 286 )) 287 Expect(serviceRepo.CreateServiceInstanceArgs.Name).To(Equal("my-cleardb-service")) 288 Expect(serviceRepo.CreateServiceInstanceArgs.PlanGuid).To(Equal("cleardb-spark-guid")) 289 }) 290 }) 291 })