github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+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  							input.Write([]byte("n\n"))
   184  						})
   185  
   186  						It("does not send an upgrade request", func() {
   187  							Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(0))
   188  						})
   189  
   190  						It("does not mention that it is updating a service", func() {
   191  							Expect(testUI.Out).ToNot(sayUpdatingServiceInstanceByCurrentUser)
   192  						})
   193  
   194  						It("cancels the update", func() {
   195  							Expect(executeErr).NotTo(HaveOccurred())
   196  							Expect(testUI.Out).To(Say("Update cancelled"))
   197  						})
   198  					})
   199  
   200  					When("user goes ahead with the upgrade", func() {
   201  						BeforeEach(func() {
   202  							input.Write([]byte("y\n"))
   203  						})
   204  
   205  						It("mentions which service instance was updated by which user", func() {
   206  							Expect(testUI.Out).To(sayUpdatingServiceInstanceByCurrentUser)
   207  						})
   208  
   209  						It("sends an upgrade request", func() {
   210  							Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(1), "upgrade should be requested")
   211  
   212  							actualServiceInstance := fakeActor.UpgradeServiceInstanceArgsForCall(0)
   213  							Expect(actualServiceInstance).To(Equal(serviceInstance))
   214  						})
   215  
   216  						When("the update request succeeds", func() {
   217  							It("says that the update was successful", func() {
   218  								Expect(executeErr).NotTo(HaveOccurred())
   219  								Expect(testUI.Out).To(Say("OK"))
   220  							})
   221  						})
   222  
   223  						When("the update request fails", func() {
   224  							BeforeEach(func() {
   225  								fakeActor.UpgradeServiceInstanceReturns(
   226  									v2action.Warnings{},
   227  									fmt.Errorf("bad things happened"),
   228  								)
   229  							})
   230  
   231  							It("says that the update has failed", func() {
   232  								Expect(executeErr).To(MatchError("bad things happened"))
   233  							})
   234  						})
   235  
   236  						When("the update request fails with upgrade not available error", func() {
   237  							BeforeEach(func() {
   238  								fakeActor.UpgradeServiceInstanceReturns(
   239  									v2action.Warnings{},
   240  									actionerror.ServiceUpgradeNotAvailableError{},
   241  								)
   242  							})
   243  
   244  							It("says that the update has failed", func() {
   245  								expectedErr := translatableerror.TipDecoratorError{
   246  									BaseError: actionerror.ServiceUpgradeNotAvailableError{},
   247  									Tip:       "To find out if upgrade is available run `cf service {{.ServiceName}}`.",
   248  									TipKeys: map[string]interface{}{
   249  										"ServiceName": serviceInstanceName,
   250  									},
   251  								}
   252  								Expect(executeErr).To(MatchError(expectedErr))
   253  							})
   254  						})
   255  
   256  						When("there are warnings", func() {
   257  							BeforeEach(func() {
   258  								fakeActor.UpgradeServiceInstanceReturns(
   259  									v2action.Warnings{"fake upgrade warning 1", "fake upgrade warning 2"},
   260  									nil,
   261  								)
   262  							})
   263  
   264  							It("outputs the warnings", func() {
   265  								Expect(testUI.Err).To(Say("fake upgrade warning 1"))
   266  								Expect(testUI.Err).To(Say("fake upgrade warning 2"))
   267  							})
   268  
   269  							It("can still output OK", func() {
   270  								Expect(testUI.Out).To(Say("OK"))
   271  							})
   272  						})
   273  					})
   274  
   275  					When("user presses return", func() {
   276  						BeforeEach(func() {
   277  							input.Write([]byte("\n"))
   278  						})
   279  
   280  						It("cancels the update", func() {
   281  							Expect(testUI.Out).To(Say("Update cancelled"))
   282  							Expect(executeErr).NotTo(HaveOccurred())
   283  						})
   284  					})
   285  
   286  					When("user does not answer", func() {
   287  						It("fails", func() {
   288  							Expect(executeErr).To(MatchError("EOF"))
   289  						})
   290  					})
   291  
   292  					When("--force is provided", func() {
   293  						BeforeEach(func() {
   294  							cmd.ForceUpgrade = true
   295  						})
   296  
   297  						It("mentions which service instance was updated by which user", func() {
   298  							Expect(testUI.Out).To(sayUpdatingServiceInstanceByCurrentUser)
   299  						})
   300  
   301  						It("sends an upgrade request", func() {
   302  							Expect(fakeActor.UpgradeServiceInstanceCallCount()).To(Equal(1), "upgrade should be requested")
   303  
   304  							actualServiceInstance := fakeActor.UpgradeServiceInstanceArgsForCall(0)
   305  							Expect(actualServiceInstance).To(Equal(serviceInstance))
   306  						})
   307  					})
   308  				})
   309  
   310  				When("getting the service instance fails", func() {
   311  					BeforeEach(func() {
   312  						fakeActor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{}, v2action.Warnings{"warning"}, errors.New("explode"))
   313  					})
   314  
   315  					It("propagates the error", func() {
   316  						Expect(executeErr).To(MatchError("explode"))
   317  					})
   318  
   319  					It("displays any warnings", func() {
   320  						Expect(testUI.Err).To(Say("warning"))
   321  					})
   322  				})
   323  			})
   324  
   325  			When("too many arguments are provided", func() {
   326  				BeforeEach(func() {
   327  					extraArgs = []string{"extra"}
   328  				})
   329  
   330  				It("returns a TooManyArgumentsError", func() {
   331  					Expect(executeErr).To(MatchError(translatableerror.TooManyArgumentsError{
   332  						ExtraArgument: "extra",
   333  					}))
   334  				})
   335  			})
   336  
   337  			When("checking the target returns an error", func() {
   338  				BeforeEach(func() {
   339  					fakeSharedActor.CheckTargetReturns(errors.New("explode"))
   340  				})
   341  
   342  				It("returns an error", func() {
   343  					Expect(executeErr).To(MatchError("explode"))
   344  				})
   345  			})
   346  		})
   347  	})
   348  })