github.com/orange-cloudfoundry/cli@v7.1.0+incompatible/command/v6/update_service_command_test.go (about) 1 package v6_test 2 3 import ( 4 "errors" 5 "fmt" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 9 "code.cloudfoundry.org/cli/actor/v2action" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 11 "code.cloudfoundry.org/cli/command/commandfakes" 12 "code.cloudfoundry.org/cli/command/flag" 13 "code.cloudfoundry.org/cli/command/translatableerror" 14 . "code.cloudfoundry.org/cli/command/v6" 15 "code.cloudfoundry.org/cli/command/v6/v6fakes" 16 "code.cloudfoundry.org/cli/util/configv3" 17 "code.cloudfoundry.org/cli/util/ui" 18 . "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 . "github.com/onsi/gomega/gbytes" 21 ) 22 23 var _ = Describe("update-service Command", func() { 24 25 const ( 26 serviceInstanceName = "my-service" 27 spaceGUID = "space-guid" 28 instanceGUID = "instance-guid" 29 planGUID = "plan-guid" 30 username = "cf-user" 31 ) 32 33 var ( 34 cmd UpdateServiceCommand 35 fakeActor *v6fakes.FakeUpdateServiceActor 36 fakeSharedActor *commandfakes.FakeSharedActor 37 fakeConfig *commandfakes.FakeConfig 38 testUI *ui.UI 39 input *Buffer 40 executeErr error 41 extraArgs []string 42 43 space = configv3.Space{Name: "space-a", GUID: spaceGUID} 44 45 sayUpdatingServiceInstanceByCurrentUser = Say("Updating service instance %s as %s...", serviceInstanceName, username) 46 ) 47 48 BeforeEach(func() { 49 input = NewBuffer() 50 testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) 51 fakeActor = new(v6fakes.FakeUpdateServiceActor) 52 fakeSharedActor = new(commandfakes.FakeSharedActor) 53 fakeConfig = new(commandfakes.FakeConfig) 54 55 fakeConfig.TargetedSpaceReturns(space) 56 fakeConfig.CurrentUserNameReturns(username, nil) 57 58 extraArgs = []string{} 59 60 cmd = UpdateServiceCommand{ 61 UI: testUI, 62 Actor: fakeActor, 63 SharedActor: fakeSharedActor, 64 Config: fakeConfig, 65 RequiredArgs: flag.ServiceInstance{ServiceInstance: serviceInstanceName}, 66 } 67 }) 68 69 JustBeforeEach(func() { 70 executeErr = cmd.Execute(extraArgs) 71 }) 72 73 When("not upgrading", func() { 74 It("returns UnrefactoredCommandError", func() { 75 // delegates non-upgrades to legacy code 76 Expect(executeErr).To(MatchError(translatableerror.UnrefactoredCommandError{})) 77 }) 78 }) 79 80 When("combining upgrade with other flags", func() { 81 BeforeEach(func() { 82 cmd.Upgrade = true 83 }) 84 85 When("tags provided", func() { 86 BeforeEach(func() { 87 cmd.Tags = "tags" 88 }) 89 90 It("returns UpgradeArgumentCombinationError", func() { 91 Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{ 92 Args: []string{"--upgrade", "-t", "-c", "-p"}, 93 })) 94 }) 95 }) 96 97 When("parameters provided", func() { 98 BeforeEach(func() { 99 cmd.ParametersAsJSON = "{\"some\": \"stuff\"}" 100 }) 101 102 It("returns UpgradeArgumentCombinationError", func() { 103 Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{ 104 Args: []string{"--upgrade", "-t", "-c", "-p"}, 105 })) 106 }) 107 }) 108 109 When("plan provided", func() { 110 BeforeEach(func() { 111 cmd.Plan = "new-plan" 112 }) 113 114 It("returns UpgradeArgumentCombinationError", func() { 115 Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{ 116 Args: []string{"--upgrade", "-t", "-c", "-p"}, 117 })) 118 }) 119 }) 120 }) 121 122 When("upgrading", func() { 123 BeforeEach(func() { 124 cmd.Upgrade = true 125 }) 126 127 When("the version of CC API is less than minimum version supporting maintenance_info updates", func() { 128 BeforeEach(func() { 129 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinSupportedV2ClientVersion) 130 }) 131 132 It("should warn the user that the version of CAPI is too low and exit with an error", func() { 133 Expect(executeErr).To(MatchError(translatableerror.MinimumCFAPIVersionNotMetError{ 134 Command: "Option '--upgrade'", 135 CurrentVersion: ccversion.MinSupportedV2ClientVersion, 136 MinimumVersion: ccversion.MinVersionUpdateServiceInstanceMaintenanceInfoV2, 137 })) 138 }) 139 }) 140 141 When("the version of CC API supports maintenance_info updates", func() { 142 BeforeEach(func() { 143 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionUpdateServiceInstanceMaintenanceInfoV2) 144 }) 145 146 It("checks the user is logged in, and targeting an org and space", func() { 147 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 148 orgChecked, spaceChecked := fakeSharedActor.CheckTargetArgsForCall(0) 149 Expect(orgChecked).To(BeTrue()) 150 Expect(spaceChecked).To(BeTrue()) 151 }) 152 153 When("checking the target succeeds", func() { 154 When("getting the service instance succeeds", func() { 155 var ( 156 serviceInstance v2action.ServiceInstance 157 ) 158 159 BeforeEach(func() { 160 serviceInstance = v2action.ServiceInstance{ 161 Name: serviceInstanceName, 162 GUID: instanceGUID, 163 ServicePlanGUID: planGUID, 164 } 165 fakeActor.GetServiceInstanceByNameAndSpaceReturns( 166 serviceInstance, 167 v2action.Warnings{"warning"}, 168 nil) 169 }) 170 171 It("displays any warnings", func() { 172 Expect(testUI.Err).To(Say("warning")) 173 }) 174 175 It("prompts the user about the upgrade", func() { 176 Expect(testUI.Out).To(Say("You are about to update %s\\.", serviceInstanceName)) 177 Expect(testUI.Out).To(Say("Warning: This operation may be long running and will block further operations on the service until complete\\.")) 178 Expect(testUI.Out).To(Say("Really update service %s\\? \\[yN\\]:", serviceInstanceName)) 179 }) 180 181 When("user refuses to proceed with the upgrade", func() { 182 BeforeEach(func() { 183 _, err := input.Write([]byte("n\n")) 184 Expect(err).NotTo(HaveOccurred()) 185 }) 186 187 It("does not send an upgrade request", func() { 188 Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(0)) 189 }) 190 191 It("does not mention that it is updating a service", func() { 192 Expect(testUI.Out).ToNot(sayUpdatingServiceInstanceByCurrentUser) 193 }) 194 195 It("cancels the update", func() { 196 Expect(executeErr).NotTo(HaveOccurred()) 197 Expect(testUI.Out).To(Say("Update cancelled")) 198 }) 199 }) 200 201 When("user goes ahead with the upgrade", func() { 202 BeforeEach(func() { 203 _, err := input.Write([]byte("y\n")) 204 Expect(err).NotTo(HaveOccurred()) 205 }) 206 207 It("mentions which service instance was updated by which user", func() { 208 Expect(testUI.Out).To(sayUpdatingServiceInstanceByCurrentUser) 209 }) 210 211 It("sends an upgrade request", func() { 212 Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(1), "upgrade should be requested") 213 214 actualServiceInstance := fakeActor.UpgradeServiceInstanceArgsForCall(0) 215 Expect(actualServiceInstance).To(Equal(serviceInstance)) 216 }) 217 218 When("the update request succeeds", func() { 219 It("says that the update was successful", func() { 220 Expect(executeErr).NotTo(HaveOccurred()) 221 Expect(testUI.Out).To(Say("OK")) 222 }) 223 }) 224 225 When("the update request fails", func() { 226 BeforeEach(func() { 227 fakeActor.UpgradeServiceInstanceReturns( 228 v2action.Warnings{}, 229 fmt.Errorf("bad things happened"), 230 ) 231 }) 232 233 It("says that the update has failed", func() { 234 Expect(executeErr).To(MatchError("bad things happened")) 235 }) 236 }) 237 238 When("the update request fails with upgrade not available error", func() { 239 BeforeEach(func() { 240 fakeActor.UpgradeServiceInstanceReturns( 241 v2action.Warnings{}, 242 actionerror.ServiceUpgradeNotAvailableError{}, 243 ) 244 }) 245 246 It("says that the update has failed", func() { 247 expectedErr := translatableerror.TipDecoratorError{ 248 BaseError: actionerror.ServiceUpgradeNotAvailableError{}, 249 Tip: "To find out if upgrade is available run `cf service {{.ServiceName}}`.", 250 TipKeys: map[string]interface{}{ 251 "ServiceName": serviceInstanceName, 252 }, 253 } 254 Expect(executeErr).To(MatchError(expectedErr)) 255 }) 256 }) 257 258 When("there are warnings", func() { 259 BeforeEach(func() { 260 fakeActor.UpgradeServiceInstanceReturns( 261 v2action.Warnings{"fake upgrade warning 1", "fake upgrade warning 2"}, 262 nil, 263 ) 264 }) 265 266 It("outputs the warnings", func() { 267 Expect(testUI.Err).To(Say("fake upgrade warning 1")) 268 Expect(testUI.Err).To(Say("fake upgrade warning 2")) 269 }) 270 271 It("can still output OK", func() { 272 Expect(testUI.Out).To(Say("OK")) 273 }) 274 }) 275 }) 276 277 When("user presses return", func() { 278 BeforeEach(func() { 279 _, err := input.Write([]byte("\n")) 280 Expect(err).NotTo(HaveOccurred()) 281 }) 282 283 It("cancels the update", func() { 284 Expect(testUI.Out).To(Say("Update cancelled")) 285 Expect(executeErr).NotTo(HaveOccurred()) 286 }) 287 }) 288 289 When("user does not answer", func() { 290 It("fails", func() { 291 Expect(executeErr).To(MatchError("EOF")) 292 }) 293 }) 294 295 When("--force is provided", func() { 296 BeforeEach(func() { 297 cmd.ForceUpgrade = true 298 }) 299 300 It("mentions which service instance was updated by which user", func() { 301 Expect(testUI.Out).To(sayUpdatingServiceInstanceByCurrentUser) 302 }) 303 304 It("sends an upgrade request", func() { 305 Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(1), "upgrade should be requested") 306 307 actualServiceInstance := fakeActor.UpgradeServiceInstanceArgsForCall(0) 308 Expect(actualServiceInstance).To(Equal(serviceInstance)) 309 }) 310 }) 311 }) 312 313 When("getting the service instance fails", func() { 314 BeforeEach(func() { 315 fakeActor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{}, v2action.Warnings{"warning"}, errors.New("explode")) 316 }) 317 318 It("propagates the error", func() { 319 Expect(executeErr).To(MatchError("explode")) 320 }) 321 322 It("displays any warnings", func() { 323 Expect(testUI.Err).To(Say("warning")) 324 }) 325 }) 326 }) 327 328 When("too many arguments are provided", func() { 329 BeforeEach(func() { 330 extraArgs = []string{"extra"} 331 }) 332 333 It("returns a TooManyArgumentsError", func() { 334 Expect(executeErr).To(MatchError(translatableerror.TooManyArgumentsError{ 335 ExtraArgument: "extra", 336 })) 337 }) 338 }) 339 340 When("checking the target returns an error", func() { 341 BeforeEach(func() { 342 fakeSharedActor.CheckTargetReturns(errors.New("explode")) 343 }) 344 345 It("returns an error", func() { 346 Expect(executeErr).To(MatchError("explode")) 347 }) 348 }) 349 }) 350 }) 351 })