github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/v7/delete_service_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/LukasHeimann/cloudfoundrycli/v8/actor/actionerror"
     7  	"github.com/LukasHeimann/cloudfoundrycli/v8/actor/v7action"
     8  	"github.com/LukasHeimann/cloudfoundrycli/v8/command/commandfakes"
     9  	. "github.com/LukasHeimann/cloudfoundrycli/v8/command/v7"
    10  	"github.com/LukasHeimann/cloudfoundrycli/v8/command/v7/v7fakes"
    11  	"github.com/LukasHeimann/cloudfoundrycli/v8/util/configv3"
    12  	"github.com/LukasHeimann/cloudfoundrycli/v8/util/ui"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	. "github.com/onsi/gomega/gbytes"
    16  )
    17  
    18  var _ = Describe("delete-service command", func() {
    19  	const (
    20  		serviceInstanceName = "service-instance-name"
    21  		orgName             = "fake-org-name"
    22  		spaceName           = "fake-space-name"
    23  		spaceGUID           = "fake-space-guid"
    24  		username            = "fake-username"
    25  	)
    26  
    27  	var (
    28  		input           *Buffer
    29  		testUI          *ui.UI
    30  		fakeConfig      *commandfakes.FakeConfig
    31  		fakeSharedActor *commandfakes.FakeSharedActor
    32  		fakeActor       *v7fakes.FakeActor
    33  		cmd             DeleteServiceCommand
    34  		executeErr      error
    35  	)
    36  
    37  	testActorInteractions := func() {
    38  		It("delegates to the actor", func() {
    39  			Expect(fakeActor.DeleteServiceInstanceCallCount()).To(Equal(1))
    40  			actualName, actualSpaceGUID := fakeActor.DeleteServiceInstanceArgsForCall(0)
    41  			Expect(actualName).To(Equal(serviceInstanceName))
    42  			Expect(actualSpaceGUID).To(Equal(spaceGUID))
    43  		})
    44  
    45  		When("the service instance did not exist", func() {
    46  			BeforeEach(func() {
    47  				fakeActor.DeleteServiceInstanceReturns(
    48  					nil,
    49  					v7action.Warnings{"delete warning"},
    50  					actionerror.ServiceInstanceNotFoundError{},
    51  				)
    52  			})
    53  
    54  			It("succeeds with a message", func() {
    55  				Expect(executeErr).NotTo(HaveOccurred())
    56  				Expect(testUI.Err).To(Say("delete warning"))
    57  				Expect(testUI.Out).To(SatisfyAll(
    58  					Say("\n"),
    59  					Say(`Service instance %s did not exist\.\n`, serviceInstanceName),
    60  					Say("OK\n"),
    61  				))
    62  			})
    63  		})
    64  
    65  		When("the service instance is successfully deleted", func() {
    66  			BeforeEach(func() {
    67  				fakeActor.DeleteServiceInstanceReturns(
    68  					nil,
    69  					v7action.Warnings{"delete warning"},
    70  					nil,
    71  				)
    72  			})
    73  
    74  			It("succeeds with a message", func() {
    75  				Expect(executeErr).NotTo(HaveOccurred())
    76  				Expect(testUI.Err).To(Say("delete warning"))
    77  				Expect(testUI.Out).To(SatisfyAll(
    78  					Say("\n"),
    79  					Say(`Service instance %s deleted\.\n`, serviceInstanceName),
    80  					Say("OK\n"),
    81  				))
    82  			})
    83  		})
    84  
    85  		When("the service instance deletion is in progress", func() {
    86  			BeforeEach(func() {
    87  				fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
    88  					stream := make(chan v7action.PollJobEvent)
    89  
    90  					go func() {
    91  						stream <- v7action.PollJobEvent{
    92  							State: v7action.JobPolling,
    93  						}
    94  						// channel not closed
    95  					}()
    96  
    97  					return stream, v7action.Warnings{"delete warning"}, nil
    98  				})
    99  			})
   100  
   101  			It("succeeds with a message", func() {
   102  				Expect(executeErr).NotTo(HaveOccurred())
   103  				Expect(testUI.Err).To(Say("delete warning"))
   104  				Expect(testUI.Out).To(SatisfyAll(
   105  					Say("\n"),
   106  					Say(`Delete in progress. Use 'cf services' or 'cf service %s' to check operation status\.\n`, serviceInstanceName),
   107  					Say("OK\n"),
   108  				))
   109  			})
   110  
   111  			When("there is a warning in the event stream", func() {
   112  				BeforeEach(func() {
   113  					fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
   114  						stream := make(chan v7action.PollJobEvent)
   115  
   116  						go func() {
   117  							stream <- v7action.PollJobEvent{
   118  								Warnings: v7action.Warnings{"stream warning"},
   119  							}
   120  							close(stream)
   121  						}()
   122  
   123  						return stream, v7action.Warnings{"delete warning"}, nil
   124  					})
   125  				})
   126  
   127  				It("prints it", func() {
   128  					Expect(testUI.Err).To(Say("stream warning"))
   129  				})
   130  			})
   131  
   132  			When("there is an error in the event stream", func() {
   133  				BeforeEach(func() {
   134  					fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
   135  						stream := make(chan v7action.PollJobEvent)
   136  
   137  						go func() {
   138  							stream <- v7action.PollJobEvent{
   139  								Err: errors.New("stream error"),
   140  							}
   141  							close(stream)
   142  						}()
   143  
   144  						return stream, v7action.Warnings{"delete warning"}, nil
   145  					})
   146  				})
   147  
   148  				It("returns it", func() {
   149  					Expect(executeErr).To(MatchError("stream error"))
   150  				})
   151  			})
   152  		})
   153  
   154  		When("the actor returns an error", func() {
   155  			BeforeEach(func() {
   156  				fakeActor.DeleteServiceInstanceReturns(
   157  					nil,
   158  					v7action.Warnings{"delete warning"},
   159  					errors.New("bang"),
   160  				)
   161  			})
   162  
   163  			It("fails with warnings", func() {
   164  				Expect(executeErr).To(MatchError("bang"))
   165  				Expect(testUI.Err).To(Say("delete warning"))
   166  				Expect(testUI.Out).NotTo(Say("OK"))
   167  			})
   168  		})
   169  
   170  		When("the -w flag is specified", func() {
   171  			BeforeEach(func() {
   172  				setFlag(&cmd, "-w")
   173  
   174  				fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
   175  					stream := make(chan v7action.PollJobEvent)
   176  
   177  					go func() {
   178  						stream <- v7action.PollJobEvent{State: v7action.JobPolling}
   179  						stream <- v7action.PollJobEvent{State: v7action.JobComplete}
   180  						close(stream)
   181  					}()
   182  
   183  					return stream, v7action.Warnings{"delete warning"}, nil
   184  				})
   185  			})
   186  
   187  			It("succeeds with a message", func() {
   188  				Expect(executeErr).NotTo(HaveOccurred())
   189  				Expect(testUI.Err).To(Say("delete warning"))
   190  				Expect(testUI.Out).To(SatisfyAll(
   191  					Say(`Waiting for the operation to complete\.\.\n`),
   192  					Say("\n"),
   193  					Say(`Service instance %s deleted\.\n`, serviceInstanceName),
   194  					Say("OK\n"),
   195  				))
   196  			})
   197  
   198  			When("there is a warning in the event stream", func() {
   199  				BeforeEach(func() {
   200  					fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
   201  						stream := make(chan v7action.PollJobEvent)
   202  
   203  						go func() {
   204  							stream <- v7action.PollJobEvent{
   205  								Warnings: v7action.Warnings{"stream warning"},
   206  							}
   207  							close(stream)
   208  						}()
   209  
   210  						return stream, v7action.Warnings{"delete warning"}, nil
   211  					})
   212  				})
   213  
   214  				It("prints it", func() {
   215  					Expect(testUI.Err).To(Say("stream warning"))
   216  				})
   217  			})
   218  
   219  			When("there is an error in the event stream", func() {
   220  				BeforeEach(func() {
   221  					fakeActor.DeleteServiceInstanceCalls(func(name, spaceGUID string) (chan v7action.PollJobEvent, v7action.Warnings, error) {
   222  						stream := make(chan v7action.PollJobEvent)
   223  
   224  						go func() {
   225  							stream <- v7action.PollJobEvent{
   226  								Err: errors.New("stream error"),
   227  							}
   228  							close(stream)
   229  						}()
   230  
   231  						return stream, v7action.Warnings{"delete warning"}, nil
   232  					})
   233  				})
   234  
   235  				It("returns it", func() {
   236  					Expect(executeErr).To(MatchError("stream error"))
   237  				})
   238  			})
   239  		})
   240  	}
   241  
   242  	confirmYes := func() {
   243  		_, err := input.Write([]byte("y\n"))
   244  		Expect(err).NotTo(HaveOccurred())
   245  	}
   246  
   247  	BeforeEach(func() {
   248  		input = NewBuffer()
   249  		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
   250  		fakeConfig = new(commandfakes.FakeConfig)
   251  		fakeSharedActor = new(commandfakes.FakeSharedActor)
   252  		fakeActor = new(v7fakes.FakeActor)
   253  
   254  		fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: orgName})
   255  		fakeConfig.TargetedSpaceReturns(configv3.Space{Name: spaceName, GUID: spaceGUID})
   256  		fakeActor.GetCurrentUserReturns(configv3.User{Name: username}, nil)
   257  
   258  		cmd = DeleteServiceCommand{
   259  			BaseCommand: BaseCommand{
   260  				UI:          testUI,
   261  				Config:      fakeConfig,
   262  				SharedActor: fakeSharedActor,
   263  				Actor:       fakeActor,
   264  			},
   265  		}
   266  
   267  		setPositionalFlags(&cmd, serviceInstanceName)
   268  	})
   269  
   270  	JustBeforeEach(func() {
   271  		executeErr = cmd.Execute(nil)
   272  	})
   273  
   274  	It("checks the user is logged in, and targeting an org and space", func() {
   275  		Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
   276  		orgChecked, spaceChecked := fakeSharedActor.CheckTargetArgsForCall(0)
   277  		Expect(orgChecked).To(BeTrue())
   278  		Expect(spaceChecked).To(BeTrue())
   279  	})
   280  
   281  	It("prompts the user", func() {
   282  		Expect(testUI.Out).To(SatisfyAll(
   283  			Say(`This action impacts all resources scoped to this service instance, including service bindings, service keys and route bindings\.`),
   284  			Say(`This will remove the service instance from any spaces where it has been shared\.`),
   285  			Say(`Really delete the service instance %s\? \[yN\]:`, serviceInstanceName),
   286  		))
   287  	})
   288  
   289  	When("the user says yes", func() {
   290  		BeforeEach(func() {
   291  			confirmYes()
   292  		})
   293  
   294  		It("informs the user what it is doing", func() {
   295  			Expect(testUI.Out).To(SatisfyAll(
   296  				Say(`Deleting service instance %s in org %s / space %s as %s\.\.\.\n`, serviceInstanceName, orgName, spaceName, username),
   297  				Say(`\n`),
   298  			))
   299  		})
   300  
   301  		testActorInteractions()
   302  	})
   303  
   304  	When("the user says no", func() {
   305  		BeforeEach(func() {
   306  			_, err := input.Write([]byte("n\n"))
   307  			Expect(err).NotTo(HaveOccurred())
   308  		})
   309  
   310  		It("does not call the actor", func() {
   311  			Expect(fakeActor.DeleteServiceInstanceCallCount()).To(BeZero())
   312  		})
   313  
   314  		It("says the delete was cancelled", func() {
   315  			Expect(executeErr).NotTo(HaveOccurred())
   316  			Expect(testUI.Out).To(Say("Delete cancelled\n"))
   317  		})
   318  	})
   319  
   320  	When("the -f flag is specified", func() {
   321  		BeforeEach(func() {
   322  			setFlag(&cmd, "-f")
   323  		})
   324  
   325  		It("does not prompt the user", func() {
   326  			Expect(testUI.Out).NotTo(Say("Really delete"))
   327  		})
   328  
   329  		testActorInteractions()
   330  	})
   331  
   332  	Context("errors", func() {
   333  		When("checking the target returns an error", func() {
   334  			BeforeEach(func() {
   335  				fakeSharedActor.CheckTargetReturns(errors.New("explode"))
   336  			})
   337  
   338  			It("returns the error", func() {
   339  				Expect(executeErr).To(MatchError("explode"))
   340  			})
   341  		})
   342  
   343  		When("getting the username fails", func() {
   344  			BeforeEach(func() {
   345  				fakeActor.GetCurrentUserReturns(configv3.User{}, errors.New("boom"))
   346  				confirmYes()
   347  			})
   348  
   349  			It("returns the error", func() {
   350  				Expect(executeErr).To(MatchError("boom"))
   351  			})
   352  		})
   353  	})
   354  })