code.cloudfoundry.org/cli@v7.1.0+incompatible/command/v6/update_user_provided_service_command_test.go (about)

     1  package v6_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"code.cloudfoundry.org/cli/actor/v2action"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    10  	"code.cloudfoundry.org/cli/command/commandfakes"
    11  	"code.cloudfoundry.org/cli/command/flag"
    12  	. "code.cloudfoundry.org/cli/command/v6"
    13  	"code.cloudfoundry.org/cli/command/v6/v6fakes"
    14  	"code.cloudfoundry.org/cli/util/configv3"
    15  	"code.cloudfoundry.org/cli/util/ui"
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/gomega"
    18  	. "github.com/onsi/gomega/gbytes"
    19  	. "github.com/onsi/gomega/gstruct"
    20  )
    21  
    22  var _ = Describe("update-user-provided-service Command", func() {
    23  	const (
    24  		fakeServiceInstanceName = "fake-service-instance-name"
    25  	)
    26  
    27  	var (
    28  		cmd             *UpdateUserProvidedServiceCommand
    29  		fakeConfig      *commandfakes.FakeConfig
    30  		fakeSharedActor *commandfakes.FakeSharedActor
    31  		fakeActor       *v6fakes.FakeUpdateUserProvidedServiceActor
    32  		input           *Buffer
    33  		testUI          *ui.UI
    34  		executeErr      error
    35  		extraArgs       []string
    36  	)
    37  
    38  	BeforeEach(func() {
    39  		input = NewBuffer()
    40  		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
    41  		fakeConfig = new(commandfakes.FakeConfig)
    42  		fakeActor = new(v6fakes.FakeUpdateUserProvidedServiceActor)
    43  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    44  
    45  		cmd = &UpdateUserProvidedServiceCommand{
    46  			UI:           testUI,
    47  			Config:       fakeConfig,
    48  			SharedActor:  fakeSharedActor,
    49  			Actor:        fakeActor,
    50  			RequiredArgs: flag.ServiceInstance{ServiceInstance: fakeServiceInstanceName},
    51  		}
    52  	})
    53  
    54  	JustBeforeEach(func() {
    55  		executeErr = cmd.Execute(extraArgs)
    56  	})
    57  
    58  	It("checks the user is logged in, and targeting an org and space", func() {
    59  		Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    60  		orgChecked, spaceChecked := fakeSharedActor.CheckTargetArgsForCall(0)
    61  		Expect(orgChecked).To(BeTrue())
    62  		Expect(spaceChecked).To(BeTrue())
    63  	})
    64  
    65  	When("checking the target returns an error", func() {
    66  		BeforeEach(func() {
    67  			fakeSharedActor.CheckTargetReturns(errors.New("explode"))
    68  		})
    69  
    70  		It("returns the error", func() {
    71  			Expect(executeErr).To(MatchError("explode"))
    72  		})
    73  	})
    74  
    75  	When("the user is logged in, and is targeting an org and space", func() {
    76  		const (
    77  			fakeOrgName   = "fake-org-name"
    78  			fakeSpaceName = "fake-space-name"
    79  			fakeSpaceGUID = "fake-space-guid"
    80  			fakeUserName  = "fake-user-name"
    81  		)
    82  
    83  		BeforeEach(func() {
    84  			fakeConfig.TargetedSpaceReturns(configv3.Space{
    85  				Name: fakeSpaceName,
    86  				GUID: fakeSpaceGUID,
    87  			})
    88  
    89  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{
    90  				Name: fakeOrgName,
    91  			})
    92  
    93  			fakeConfig.CurrentUserReturns(configv3.User{Name: fakeUserName}, nil) //TODO: test errors
    94  		})
    95  
    96  		It("looks up the service instance GUID", func() {
    97  			Expect(fakeActor.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
    98  			name, spaceGUID := fakeActor.GetServiceInstanceByNameAndSpaceArgsForCall(0)
    99  			Expect(name).To(Equal(fakeServiceInstanceName))
   100  			Expect(spaceGUID).To(Equal(fakeSpaceGUID))
   101  		})
   102  
   103  		When("looking up the service instance GUID returns warnings", func() {
   104  			BeforeEach(func() {
   105  				fakeActor.GetServiceInstanceByNameAndSpaceReturns(
   106  					v2action.ServiceInstance{},
   107  					v2action.Warnings{"something obstreperous"},
   108  					nil,
   109  				)
   110  			})
   111  
   112  			It("reports the warning", func() {
   113  				Expect(testUI.Err).To(Say("something obstreperous"))
   114  			})
   115  		})
   116  
   117  		When("looking up the service instance GUID fails", func() {
   118  			BeforeEach(func() {
   119  				fakeActor.GetServiceInstanceByNameAndSpaceReturns(
   120  					v2action.ServiceInstance{},
   121  					v2action.Warnings{"something obstreperous"},
   122  					errors.New("something awful"),
   123  				)
   124  			})
   125  
   126  			It("returns the error and warnings", func() {
   127  				Expect(testUI.Err).To(Say("something obstreperous"))
   128  				Expect(executeErr).To(MatchError("something awful"))
   129  			})
   130  		})
   131  
   132  		When("the service instance is not user-provided", func() {
   133  			It("fails with an error", func() {
   134  				Expect(executeErr).To(MatchError(fmt.Sprintf("The service instance '%s' is not user-provided", fakeServiceInstanceName)))
   135  			})
   136  		})
   137  
   138  		When("looking up the service instance GUID succeeds, and it is user-provided", func() {
   139  			const (
   140  				fakeServiceInstanceGUID = "fake-service-instance-guid"
   141  			)
   142  
   143  			BeforeEach(func() {
   144  				fakeActor.GetServiceInstanceByNameAndSpaceReturns(
   145  					v2action.ServiceInstance{
   146  						GUID: fakeServiceInstanceGUID,
   147  						Type: constant.UserProvidedService,
   148  					},
   149  					nil,
   150  					nil,
   151  				)
   152  			})
   153  
   154  			When("no flags are provided", func() {
   155  				It("succeeds", func() {
   156  					Expect(executeErr).NotTo(HaveOccurred())
   157  				})
   158  
   159  				It("says that no flags were provided", func() {
   160  					Expect(testUI.Out).To(Say("No flags specified. No changes were made"))
   161  					Expect(testUI.Out).To(Say("OK"))
   162  				})
   163  			})
   164  
   165  			Context("updating log URL", func() {
   166  				BeforeEach(func() {
   167  					cmd.SyslogDrainURL.IsSet = true
   168  					cmd.SyslogDrainURL.Value = "fake-syslog-drain-url"
   169  				})
   170  
   171  				It("succeeds", func() {
   172  					Expect(executeErr).NotTo(HaveOccurred())
   173  				})
   174  
   175  				It("displays messages to the user", func() {
   176  					expectOKMessage(testUI, fakeServiceInstanceName, fakeOrgName, fakeSpaceName, fakeUserName)
   177  				})
   178  
   179  				It("updates the syslog URL", func() {
   180  					Expect(fakeActor.UpdateUserProvidedServiceInstanceCallCount()).To(Equal(1))
   181  					guid, instanceChanges := fakeActor.UpdateUserProvidedServiceInstanceArgsForCall(0)
   182  					Expect(guid).To(Equal(fakeServiceInstanceGUID))
   183  					Expect(instanceChanges).To(MatchAllFields(Fields{
   184  						"SyslogDrainURL":  PointTo(Equal("fake-syslog-drain-url")),
   185  						"RouteServiceURL": BeNil(),
   186  						"Tags":            BeNil(),
   187  						"Credentials":     BeNil(),
   188  					}))
   189  				})
   190  			})
   191  
   192  			Context("updating credentials", func() {
   193  				BeforeEach(func() {
   194  					cmd.Credentials.IsSet = true
   195  					cmd.Credentials.UserPromptCredentials = []string{"pass phrase", "cred"}
   196  
   197  					_, err := input.Write([]byte("very secret passphrase\nsecret cred\n"))
   198  					Expect(err).NotTo(HaveOccurred())
   199  				})
   200  
   201  				It("prompts the user for credentials", func() {
   202  					Expect(testUI.Out).To(Say("pass phrase: "))
   203  					Expect(testUI.Out).To(Say("cred: "))
   204  				})
   205  
   206  				It("does not echo the credentials", func() {
   207  					Expect(testUI.Out).NotTo(Say("secret"))
   208  					Expect(testUI.Err).NotTo(Say("secret"))
   209  				})
   210  
   211  				It("succeeds", func() {
   212  					Expect(executeErr).NotTo(HaveOccurred())
   213  				})
   214  
   215  				It("displays messages to the user", func() {
   216  					expectOKMessage(testUI, fakeServiceInstanceName, fakeOrgName, fakeSpaceName, fakeUserName)
   217  				})
   218  
   219  				It("updates the credentials", func() {
   220  					Expect(fakeActor.UpdateUserProvidedServiceInstanceCallCount()).To(Equal(1))
   221  					guid, instanceChanges := fakeActor.UpdateUserProvidedServiceInstanceArgsForCall(0)
   222  					Expect(guid).To(Equal(fakeServiceInstanceGUID))
   223  					Expect(instanceChanges).To(MatchAllFields(Fields{
   224  						"Credentials": Equal(map[string]interface{}{
   225  							"pass phrase": "very secret passphrase",
   226  							"cred":        "secret cred",
   227  						}),
   228  						"RouteServiceURL": BeNil(),
   229  						"Tags":            BeNil(),
   230  						"SyslogDrainURL":  BeNil(),
   231  					}))
   232  				})
   233  			})
   234  
   235  			Context("updating routes URL", func() {
   236  				BeforeEach(func() {
   237  					cmd.RouteServiceURL.IsSet = true
   238  					cmd.RouteServiceURL.Value = "fake-route-url"
   239  				})
   240  
   241  				It("succeeds", func() {
   242  					Expect(executeErr).NotTo(HaveOccurred())
   243  				})
   244  
   245  				It("displays messages to the user", func() {
   246  					expectOKMessage(testUI, fakeServiceInstanceName, fakeOrgName, fakeSpaceName, fakeUserName)
   247  				})
   248  
   249  				It("updates the routes URL", func() {
   250  					Expect(fakeActor.UpdateUserProvidedServiceInstanceCallCount()).To(Equal(1))
   251  					guid, instanceChanges := fakeActor.UpdateUserProvidedServiceInstanceArgsForCall(0)
   252  					Expect(guid).To(Equal(fakeServiceInstanceGUID))
   253  					Expect(instanceChanges).To(MatchAllFields(Fields{
   254  						"RouteServiceURL": PointTo(Equal("fake-route-url")),
   255  						"Tags":            BeNil(),
   256  						"SyslogDrainURL":  BeNil(),
   257  						"Credentials":     BeNil(),
   258  					}))
   259  				})
   260  			})
   261  
   262  			Context("updating tags", func() {
   263  				BeforeEach(func() {
   264  					cmd.Tags.IsSet = true
   265  					cmd.Tags.Value = []string{"foo", "bar"}
   266  				})
   267  
   268  				It("succeeds", func() {
   269  					Expect(executeErr).NotTo(HaveOccurred())
   270  				})
   271  
   272  				It("displays messages to the user", func() {
   273  					expectOKMessage(testUI, fakeServiceInstanceName, fakeOrgName, fakeSpaceName, fakeUserName)
   274  				})
   275  
   276  				It("updates the tags", func() {
   277  					Expect(fakeActor.UpdateUserProvidedServiceInstanceCallCount()).To(Equal(1))
   278  					guid, instanceChanges := fakeActor.UpdateUserProvidedServiceInstanceArgsForCall(0)
   279  					Expect(guid).To(Equal(fakeServiceInstanceGUID))
   280  					Expect(instanceChanges).To(MatchAllFields(Fields{
   281  						"Tags":            PointTo(ConsistOf("foo", "bar")),
   282  						"SyslogDrainURL":  BeNil(),
   283  						"RouteServiceURL": BeNil(),
   284  						"Credentials":     BeNil(),
   285  					}))
   286  				})
   287  			})
   288  
   289  			When("unsetting values", func() {
   290  				BeforeEach(func() {
   291  					cmd.RouteServiceURL.IsSet = true
   292  					cmd.Credentials.IsSet = true
   293  					cmd.SyslogDrainURL.IsSet = true
   294  					cmd.Tags.IsSet = true
   295  				})
   296  
   297  				It("sends empty values", func() {
   298  					Expect(fakeActor.UpdateUserProvidedServiceInstanceCallCount()).To(Equal(1))
   299  					guid, instanceChanges := fakeActor.UpdateUserProvidedServiceInstanceArgsForCall(0)
   300  					Expect(guid).To(Equal(fakeServiceInstanceGUID))
   301  					bytes, err := json.Marshal(instanceChanges)
   302  					Expect(err).NotTo(HaveOccurred())
   303  					Expect(bytes).To(MatchJSON(`
   304            {
   305  					  "tags": [],
   306  						"syslog_drain_url": "",
   307  						"route_service_url": "",
   308  						"credentials": {}
   309  					}`))
   310  				})
   311  			})
   312  
   313  			When("the action returns warnings", func() {
   314  				BeforeEach(func() {
   315  					cmd.Tags.IsSet = true
   316  					cmd.Tags.Value = []string{"foo", "bar"}
   317  
   318  					fakeActor.UpdateUserProvidedServiceInstanceReturns(v2action.Warnings{"some", "warnings"}, nil)
   319  				})
   320  
   321  				It("reports the warnings to the user", func() {
   322  					Expect(testUI.Err).To(Say("some"))
   323  					Expect(testUI.Err).To(Say("warnings"))
   324  				})
   325  			})
   326  
   327  			When("the action fails", func() {
   328  				BeforeEach(func() {
   329  					cmd.Tags.IsSet = true
   330  					cmd.Tags.Value = []string{"foo", "bar"}
   331  
   332  					fakeActor.UpdateUserProvidedServiceInstanceReturns(
   333  						v2action.Warnings{"some", "warnings"},
   334  						errors.New("utterly awful happenings"),
   335  					)
   336  				})
   337  
   338  				It("reports the failure and warnings", func() {
   339  					Expect(testUI.Err).To(Say("some"))
   340  					Expect(testUI.Err).To(Say("warnings"))
   341  					Expect(executeErr).To(MatchError("utterly awful happenings"))
   342  				})
   343  			})
   344  		})
   345  	})
   346  })
   347  
   348  func expectOKMessage(testUI *ui.UI, serviceName, orgName, spaceName, userName string) {
   349  	Expect(testUI.Out).To(Say("Updating user provided service %s in org %s / space %s as %s...", serviceName, orgName, spaceName, userName))
   350  	Expect(testUI.Out).To(Say("OK"))
   351  	Expect(testUI.Out).To(Say("TIP: Use 'cf restage' for any bound apps to ensure your env variable changes take effect"))
   352  }