github.com/LukasHeimann/cloudfoundrycli@v7.1.0+incompatible/actor/v7action/droplet_test.go (about)

     1  package v7action_test
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"strings"
     7  
     8  	"code.cloudfoundry.org/cli/actor/actionerror"
     9  	. "code.cloudfoundry.org/cli/actor/v7action"
    10  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    14  	"code.cloudfoundry.org/cli/resources"
    15  
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  var _ = Describe("Droplet Actions", func() {
    21  	var (
    22  		actor                     *Actor
    23  		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient)
    28  		actor = NewActor(fakeCloudControllerClient, nil, nil, nil, nil, nil)
    29  	})
    30  
    31  	Describe("CreateApplicationDroplet", func() {
    32  		When("there are no client errors", func() {
    33  			BeforeEach(func() {
    34  				fakeCloudControllerClient.CreateDropletReturns(
    35  					resources.Droplet{
    36  						GUID:      "some-droplet-guid",
    37  						State:     constant.DropletAwaitingUpload,
    38  						CreatedAt: "2017-08-14T21:16:42Z",
    39  						Image:     "docker/some-image",
    40  						Stack:     "penguin",
    41  					},
    42  					ccv3.Warnings{"create-application-droplet-warning"},
    43  					nil,
    44  				)
    45  			})
    46  
    47  			It("creates a droplet for the app", func() {
    48  				droplet, warnings, err := actor.CreateApplicationDroplet("some-app-guid")
    49  
    50  				Expect(err).ToNot(HaveOccurred())
    51  				Expect(warnings).To(ConsistOf("create-application-droplet-warning"))
    52  				Expect(droplet).To(Equal(resources.Droplet{
    53  					GUID:      "some-droplet-guid",
    54  					State:     constant.DropletAwaitingUpload,
    55  					CreatedAt: "2017-08-14T21:16:42Z",
    56  					Image:     "docker/some-image",
    57  					Stack:     "penguin",
    58  				}))
    59  
    60  				Expect(fakeCloudControllerClient.CreateDropletCallCount()).To(Equal(1))
    61  				Expect(fakeCloudControllerClient.CreateDropletArgsForCall(0)).To(Equal("some-app-guid"))
    62  			})
    63  		})
    64  
    65  		When("creating the application droplet fails", func() {
    66  			var expectedErr error
    67  
    68  			BeforeEach(func() {
    69  				expectedErr = errors.New("some upload droplet error")
    70  
    71  				fakeCloudControllerClient.CreateDropletReturns(
    72  					resources.Droplet{},
    73  					ccv3.Warnings{"create-application-droplet-warning"},
    74  					expectedErr,
    75  				)
    76  			})
    77  
    78  			It("returns the error", func() {
    79  				_, warnings, err := actor.CreateApplicationDroplet("some-app-guid")
    80  
    81  				Expect(err).To(Equal(expectedErr))
    82  				Expect(warnings).To(ConsistOf("create-application-droplet-warning"))
    83  			})
    84  		})
    85  	})
    86  
    87  	Describe("SetApplicationDropletByApplicationNameAndSpace", func() {
    88  		When("there are no client errors", func() {
    89  			BeforeEach(func() {
    90  				fakeCloudControllerClient.GetApplicationsReturns(
    91  					[]resources.Application{
    92  						{GUID: "some-app-guid"},
    93  					},
    94  					ccv3.Warnings{"get-applications-warning"},
    95  					nil,
    96  				)
    97  
    98  				fakeCloudControllerClient.SetApplicationDropletReturns(
    99  					resources.Relationship{GUID: "some-droplet-guid"},
   100  					ccv3.Warnings{"set-application-droplet-warning"},
   101  					nil,
   102  				)
   103  			})
   104  
   105  			It("sets the app's droplet", func() {
   106  				warnings, err := actor.SetApplicationDropletByApplicationNameAndSpace("some-app-name", "some-space-guid", "some-droplet-guid")
   107  
   108  				Expect(err).ToNot(HaveOccurred())
   109  				Expect(warnings).To(ConsistOf("get-applications-warning", "set-application-droplet-warning"))
   110  
   111  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   112  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   113  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   114  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   115  				))
   116  
   117  				Expect(fakeCloudControllerClient.SetApplicationDropletCallCount()).To(Equal(1))
   118  				appGUID, dropletGUID := fakeCloudControllerClient.SetApplicationDropletArgsForCall(0)
   119  				Expect(appGUID).To(Equal("some-app-guid"))
   120  				Expect(dropletGUID).To(Equal("some-droplet-guid"))
   121  			})
   122  		})
   123  
   124  		When("getting the application fails", func() {
   125  			var expectedErr error
   126  
   127  			BeforeEach(func() {
   128  				expectedErr = errors.New("some get application error")
   129  
   130  				fakeCloudControllerClient.GetApplicationsReturns(
   131  					[]resources.Application{},
   132  					ccv3.Warnings{"get-applications-warning"},
   133  					expectedErr,
   134  				)
   135  			})
   136  
   137  			It("returns the error", func() {
   138  				warnings, err := actor.SetApplicationDropletByApplicationNameAndSpace("some-app-name", "some-space-guid", "some-droplet-guid")
   139  
   140  				Expect(err).To(Equal(expectedErr))
   141  				Expect(warnings).To(ConsistOf("get-applications-warning"))
   142  			})
   143  		})
   144  
   145  		When("setting the droplet fails", func() {
   146  			var expectedErr error
   147  			BeforeEach(func() {
   148  				expectedErr = errors.New("some set application-droplet error")
   149  				fakeCloudControllerClient.GetApplicationsReturns(
   150  					[]resources.Application{
   151  						{GUID: "some-app-guid"},
   152  					},
   153  					ccv3.Warnings{"get-applications-warning"},
   154  					nil,
   155  				)
   156  
   157  				fakeCloudControllerClient.SetApplicationDropletReturns(
   158  					resources.Relationship{},
   159  					ccv3.Warnings{"set-application-droplet-warning"},
   160  					expectedErr,
   161  				)
   162  			})
   163  
   164  			It("returns the error", func() {
   165  				warnings, err := actor.SetApplicationDropletByApplicationNameAndSpace("some-app-name", "some-space-guid", "some-droplet-guid")
   166  
   167  				Expect(err).To(Equal(expectedErr))
   168  				Expect(warnings).To(ConsistOf("get-applications-warning", "set-application-droplet-warning"))
   169  			})
   170  
   171  			When("the cc client response contains an UnprocessableEntityError", func() {
   172  				BeforeEach(func() {
   173  					fakeCloudControllerClient.SetApplicationDropletReturns(
   174  						resources.Relationship{},
   175  						ccv3.Warnings{"set-application-droplet-warning"},
   176  						ccerror.UnprocessableEntityError{Message: "some-message"},
   177  					)
   178  				})
   179  
   180  				It("raises the error as AssignDropletError and returns warnings", func() {
   181  					warnings, err := actor.SetApplicationDropletByApplicationNameAndSpace("some-app-name", "some-space-guid", "some-droplet-guid")
   182  
   183  					Expect(err).To(MatchError("some-message"))
   184  					Expect(warnings).To(ConsistOf("get-applications-warning", "set-application-droplet-warning"))
   185  				})
   186  			})
   187  
   188  		})
   189  	})
   190  
   191  	Describe("SetApplicationDroplet", func() {
   192  		When("there are no client errors", func() {
   193  			BeforeEach(func() {
   194  				fakeCloudControllerClient.SetApplicationDropletReturns(
   195  					resources.Relationship{GUID: "some-droplet-guid"},
   196  					ccv3.Warnings{"set-application-droplet-warning"},
   197  					nil,
   198  				)
   199  			})
   200  
   201  			It("sets the app's droplet", func() {
   202  				warnings, err := actor.SetApplicationDroplet("some-app-guid", "some-droplet-guid")
   203  
   204  				Expect(err).ToNot(HaveOccurred())
   205  				Expect(warnings).To(ConsistOf("set-application-droplet-warning"))
   206  
   207  				Expect(fakeCloudControllerClient.SetApplicationDropletCallCount()).To(Equal(1))
   208  				appGUID, dropletGUID := fakeCloudControllerClient.SetApplicationDropletArgsForCall(0)
   209  				Expect(appGUID).To(Equal("some-app-guid"))
   210  				Expect(dropletGUID).To(Equal("some-droplet-guid"))
   211  			})
   212  		})
   213  
   214  		When("setting the droplet fails", func() {
   215  			var expectedErr error
   216  
   217  			BeforeEach(func() {
   218  				expectedErr = errors.New("some set application-droplet error")
   219  
   220  				fakeCloudControllerClient.SetApplicationDropletReturns(
   221  					resources.Relationship{},
   222  					ccv3.Warnings{"set-application-droplet-warning"},
   223  					expectedErr,
   224  				)
   225  			})
   226  
   227  			It("returns the error", func() {
   228  				warnings, err := actor.SetApplicationDroplet("some-app-guid", "some-droplet-guid")
   229  
   230  				Expect(err).To(Equal(expectedErr))
   231  				Expect(warnings).To(ConsistOf("set-application-droplet-warning"))
   232  			})
   233  
   234  			When("the cc client response contains an UnprocessableEntityError", func() {
   235  				BeforeEach(func() {
   236  					fakeCloudControllerClient.SetApplicationDropletReturns(
   237  						resources.Relationship{},
   238  						ccv3.Warnings{"set-application-droplet-warning"},
   239  						ccerror.UnprocessableEntityError{Message: "some-message"},
   240  					)
   241  				})
   242  
   243  				It("raises the error as AssignDropletError and returns warnings", func() {
   244  					warnings, err := actor.SetApplicationDroplet("some-app-guid", "some-droplet-guid")
   245  
   246  					Expect(err).To(MatchError("some-message"))
   247  					Expect(warnings).To(ConsistOf("set-application-droplet-warning"))
   248  				})
   249  			})
   250  		})
   251  	})
   252  
   253  	Describe("GetApplicationDroplets", func() {
   254  		When("there are no client errors", func() {
   255  			BeforeEach(func() {
   256  				fakeCloudControllerClient.GetApplicationsReturns(
   257  					[]resources.Application{
   258  						{GUID: "some-app-guid"},
   259  					},
   260  					ccv3.Warnings{"get-applications-warning"},
   261  					nil,
   262  				)
   263  
   264  				fakeCloudControllerClient.GetDropletsReturns(
   265  					[]resources.Droplet{
   266  						{
   267  							GUID:      "some-droplet-guid-1",
   268  							State:     constant.DropletStaged,
   269  							CreatedAt: "2017-08-14T21:16:42Z",
   270  							Buildpacks: []resources.DropletBuildpack{
   271  								{Name: "ruby"},
   272  								{Name: "nodejs"},
   273  							},
   274  							Image: "docker/some-image",
   275  							Stack: "penguin",
   276  						},
   277  						{
   278  							GUID:      "some-droplet-guid-2",
   279  							State:     constant.DropletFailed,
   280  							CreatedAt: "2017-08-16T00:18:24Z",
   281  							Buildpacks: []resources.DropletBuildpack{
   282  								{Name: "java"},
   283  							},
   284  							Stack: "windows",
   285  						},
   286  					},
   287  					ccv3.Warnings{"get-application-droplets-warning"},
   288  					nil,
   289  				)
   290  
   291  				fakeCloudControllerClient.GetApplicationDropletCurrentReturns(
   292  					resources.Droplet{
   293  						GUID:      "some-droplet-guid-2",
   294  						State:     constant.DropletFailed,
   295  						CreatedAt: "2017-08-16T00:18:24Z",
   296  						Buildpacks: []resources.DropletBuildpack{
   297  							{Name: "java"},
   298  						},
   299  						Stack: "windows",
   300  					},
   301  					ccv3.Warnings{"get-current-droplet-warning"},
   302  					nil,
   303  				)
   304  			})
   305  
   306  			It("gets the app's droplets", func() {
   307  				droplets, warnings, err := actor.GetApplicationDroplets("some-app-name", "some-space-guid")
   308  
   309  				Expect(err).ToNot(HaveOccurred())
   310  				Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-droplets-warning", "get-current-droplet-warning"))
   311  				Expect(droplets).To(Equal([]resources.Droplet{
   312  					{
   313  						GUID:      "some-droplet-guid-1",
   314  						State:     constant.DropletStaged,
   315  						CreatedAt: "2017-08-14T21:16:42Z",
   316  						Buildpacks: []resources.DropletBuildpack{
   317  							{Name: "ruby"},
   318  							{Name: "nodejs"},
   319  						},
   320  						Image:     "docker/some-image",
   321  						Stack:     "penguin",
   322  						IsCurrent: false,
   323  					},
   324  					{
   325  						GUID:      "some-droplet-guid-2",
   326  						State:     constant.DropletFailed,
   327  						CreatedAt: "2017-08-16T00:18:24Z",
   328  						Buildpacks: []resources.DropletBuildpack{
   329  							{Name: "java"},
   330  						},
   331  						Stack:     "windows",
   332  						IsCurrent: true,
   333  					},
   334  				}))
   335  
   336  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   337  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   338  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   339  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   340  				))
   341  
   342  				Expect(fakeCloudControllerClient.GetDropletsCallCount()).To(Equal(1))
   343  				Expect(fakeCloudControllerClient.GetDropletsArgsForCall(0)).To(ConsistOf(
   344  					ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{"some-app-guid"}},
   345  					ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}},
   346  				))
   347  
   348  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentCallCount()).To(Equal(1))
   349  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentArgsForCall(0)).To(Equal("some-app-guid"))
   350  			})
   351  		})
   352  
   353  		When("the application does not have associated droplets", func() {
   354  			BeforeEach(func() {
   355  				fakeCloudControllerClient.GetApplicationsReturns(
   356  					[]resources.Application{
   357  						{GUID: "some-app-guid"},
   358  					},
   359  					ccv3.Warnings{"get-applications-warning"},
   360  					nil,
   361  				)
   362  
   363  				fakeCloudControllerClient.GetDropletsReturns(
   364  					[]resources.Droplet{},
   365  					ccv3.Warnings{"get-application-droplets-warning"},
   366  					nil,
   367  				)
   368  			})
   369  
   370  			It("does not error", func() {
   371  				_, warnings, err := actor.GetApplicationDroplets("some-app-name", "some-space-guid")
   372  
   373  				Expect(err).To(BeNil())
   374  				Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-droplets-warning"))
   375  
   376  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentCallCount()).To(Equal(0))
   377  			})
   378  		})
   379  
   380  		When("getting the application fails", func() {
   381  			var expectedErr error
   382  
   383  			BeforeEach(func() {
   384  				expectedErr = errors.New("some get application error")
   385  
   386  				fakeCloudControllerClient.GetApplicationsReturns(
   387  					[]resources.Application{},
   388  					ccv3.Warnings{"get-applications-warning"},
   389  					expectedErr,
   390  				)
   391  			})
   392  
   393  			It("returns the error", func() {
   394  				_, warnings, err := actor.GetApplicationDroplets("some-app-name", "some-space-guid")
   395  
   396  				Expect(err).To(Equal(expectedErr))
   397  				Expect(warnings).To(ConsistOf("get-applications-warning"))
   398  			})
   399  		})
   400  
   401  		When("getting the application droplets fails", func() {
   402  			var expectedErr error
   403  
   404  			BeforeEach(func() {
   405  				expectedErr = errors.New("some get application error")
   406  
   407  				fakeCloudControllerClient.GetApplicationsReturns(
   408  					[]resources.Application{
   409  						{GUID: "some-app-guid"},
   410  					},
   411  					ccv3.Warnings{"get-applications-warning"},
   412  					nil,
   413  				)
   414  
   415  				fakeCloudControllerClient.GetDropletsReturns(
   416  					[]resources.Droplet{},
   417  					ccv3.Warnings{"get-application-droplets-warning"},
   418  					expectedErr,
   419  				)
   420  			})
   421  
   422  			It("returns the error", func() {
   423  				_, warnings, err := actor.GetApplicationDroplets("some-app-name", "some-space-guid")
   424  
   425  				Expect(err).To(Equal(expectedErr))
   426  				Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-droplets-warning"))
   427  			})
   428  		})
   429  
   430  		When("the application does not have a current droplet set", func() {
   431  			BeforeEach(func() {
   432  				fakeCloudControllerClient.GetApplicationsReturns(
   433  					[]resources.Application{
   434  						{GUID: "some-app-guid"},
   435  					},
   436  					ccv3.Warnings{"get-applications-warning"},
   437  					nil,
   438  				)
   439  
   440  				fakeCloudControllerClient.GetDropletsReturns(
   441  					[]resources.Droplet{
   442  						{
   443  							GUID:      "some-droplet-guid-1",
   444  							State:     constant.DropletStaged,
   445  							CreatedAt: "2017-08-14T21:16:42Z",
   446  							Buildpacks: []resources.DropletBuildpack{
   447  								{Name: "ruby"},
   448  								{Name: "nodejs"},
   449  							},
   450  							Image: "docker/some-image",
   451  							Stack: "penguin",
   452  						},
   453  					},
   454  					ccv3.Warnings{"get-application-droplets-warning"},
   455  					nil,
   456  				)
   457  
   458  				fakeCloudControllerClient.GetApplicationDropletCurrentReturns(
   459  					resources.Droplet{},
   460  					ccv3.Warnings{"get-current-droplet-warning"},
   461  					ccerror.DropletNotFoundError{},
   462  				)
   463  			})
   464  
   465  			It("does not error and returns all droplets", func() {
   466  				droplets, warnings, err := actor.GetApplicationDroplets("some-app-name", "some-space-guid")
   467  
   468  				Expect(err).To(Not(HaveOccurred()))
   469  				Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-droplets-warning", "get-current-droplet-warning"))
   470  				Expect(droplets).To(Equal([]resources.Droplet{
   471  					{
   472  						GUID:      "some-droplet-guid-1",
   473  						State:     constant.DropletStaged,
   474  						CreatedAt: "2017-08-14T21:16:42Z",
   475  						Buildpacks: []resources.DropletBuildpack{
   476  							{Name: "ruby"},
   477  							{Name: "nodejs"},
   478  						},
   479  						Image:     "docker/some-image",
   480  						Stack:     "penguin",
   481  						IsCurrent: false,
   482  					},
   483  				}))
   484  			})
   485  		})
   486  	})
   487  
   488  	Describe("GetCurrentDropletByApplication", func() {
   489  		var (
   490  			appGUID string
   491  
   492  			currentDroplet resources.Droplet
   493  			warnings       Warnings
   494  			executionErr   error
   495  		)
   496  
   497  		BeforeEach(func() {
   498  			appGUID = "some-app-guid"
   499  		})
   500  
   501  		JustBeforeEach(func() {
   502  			currentDroplet, warnings, executionErr = actor.GetCurrentDropletByApplication(appGUID)
   503  		})
   504  
   505  		When("the current droplet exists", func() {
   506  			BeforeEach(func() {
   507  				fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{GUID: "some-droplet-guid"}, ccv3.Warnings{"some-warning"}, nil)
   508  			})
   509  
   510  			It("returns the current droplet", func() {
   511  				Expect(executionErr).ToNot(HaveOccurred())
   512  				Expect(warnings).To(ConsistOf("some-warning"))
   513  				Expect(currentDroplet).To(Equal(resources.Droplet{GUID: "some-droplet-guid"}))
   514  
   515  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentCallCount()).To(Equal(1))
   516  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentArgsForCall(0)).To(Equal("some-app-guid"))
   517  			})
   518  		})
   519  
   520  		When("an error occurs", func() {
   521  			When("the app does not exist", func() {
   522  				BeforeEach(func() {
   523  					fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{GUID: "some-droplet-guid"}, ccv3.Warnings{"some-warning"}, ccerror.ApplicationNotFoundError{})
   524  				})
   525  
   526  				It("returns an ApplicationNotFoundError and warnings", func() {
   527  					Expect(executionErr).To(MatchError(actionerror.ApplicationNotFoundError{GUID: appGUID}))
   528  					Expect(warnings).To(ConsistOf("some-warning"))
   529  				})
   530  			})
   531  
   532  			When("the current droplet does not exist", func() {
   533  				BeforeEach(func() {
   534  					fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{}, ccv3.Warnings{"some-warning"}, ccerror.DropletNotFoundError{})
   535  				})
   536  
   537  				It("returns an DropletNotFoundError and warnings", func() {
   538  					Expect(executionErr).To(MatchError(actionerror.DropletNotFoundError{AppGUID: appGUID}))
   539  					Expect(warnings).To(ConsistOf("some-warning"))
   540  				})
   541  			})
   542  
   543  			When("a generic error occurs", func() {
   544  				var expectedErr error
   545  
   546  				BeforeEach(func() {
   547  					expectedErr = errors.New("some error")
   548  					fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{}, ccv3.Warnings{"some-warning"}, expectedErr)
   549  				})
   550  
   551  				It("returns the error and warnings", func() {
   552  					Expect(executionErr).To(MatchError(expectedErr))
   553  					Expect(warnings).To(ConsistOf("some-warning"))
   554  				})
   555  			})
   556  		})
   557  	})
   558  
   559  	Describe("UploadDroplet", func() {
   560  		var (
   561  			dropletGUID     string
   562  			dropletFilePath string
   563  			reader          io.Reader
   564  			readerLength    int64
   565  
   566  			warnings   Warnings
   567  			executeErr error
   568  		)
   569  
   570  		BeforeEach(func() {
   571  			dropletGUID = "some-droplet-guid"
   572  			dropletContents := "i am a droplet"
   573  			reader = strings.NewReader(dropletContents)
   574  			readerLength = int64(len([]byte(dropletContents)))
   575  		})
   576  
   577  		JustBeforeEach(func() {
   578  			dropletFilePath = "tmp/droplet.tgz"
   579  			warnings, executeErr = actor.UploadDroplet(dropletGUID, dropletFilePath, reader, readerLength)
   580  		})
   581  
   582  		When("the upload is successful", func() {
   583  			BeforeEach(func() {
   584  				fakeCloudControllerClient.UploadDropletBitsReturns(
   585  					ccv3.JobURL("some-job-url"),
   586  					ccv3.Warnings{"some-upload-warning"},
   587  					nil,
   588  				)
   589  
   590  				fakeCloudControllerClient.PollJobReturns(
   591  					ccv3.Warnings{"some-job-warning"},
   592  					nil,
   593  				)
   594  			})
   595  
   596  			It("returns any CC warnings", func() {
   597  				Expect(warnings).To(Equal(Warnings{"some-upload-warning", "some-job-warning"}))
   598  				Expect(executeErr).NotTo(HaveOccurred())
   599  			})
   600  		})
   601  
   602  		When("the upload returns an error", func() {
   603  			var uploadErr = errors.New("upload failed")
   604  
   605  			BeforeEach(func() {
   606  				fakeCloudControllerClient.UploadDropletBitsReturns(
   607  					"",
   608  					ccv3.Warnings{"some-upload-warning"},
   609  					uploadErr,
   610  				)
   611  			})
   612  
   613  			It("returns any warnings and the error", func() {
   614  				Expect(warnings).To(Equal(Warnings{"some-upload-warning"}))
   615  				Expect(executeErr).To(Equal(uploadErr))
   616  			})
   617  		})
   618  
   619  		When("the upload job fails eventually", func() {
   620  			var jobErr = errors.New("job failed")
   621  
   622  			BeforeEach(func() {
   623  				fakeCloudControllerClient.UploadDropletBitsReturns(
   624  					ccv3.JobURL("some-job-url"),
   625  					ccv3.Warnings{"some-upload-warning"},
   626  					nil,
   627  				)
   628  
   629  				fakeCloudControllerClient.PollJobReturns(
   630  					ccv3.Warnings{"some-job-warning"},
   631  					jobErr,
   632  				)
   633  			})
   634  
   635  			It("returns any warning and the error", func() {
   636  				Expect(warnings).To(Equal(Warnings{"some-upload-warning", "some-job-warning"}))
   637  				Expect(executeErr).To(Equal(jobErr))
   638  			})
   639  		})
   640  	})
   641  
   642  	Describe("DownloadCurrentDropletByAppName", func() {
   643  		var (
   644  			appName   string
   645  			spaceGUID string
   646  
   647  			dropletBytes []byte
   648  			dropletGUID  string
   649  			warnings     Warnings
   650  			executionErr error
   651  		)
   652  
   653  		BeforeEach(func() {
   654  			appName = "some-app-name"
   655  			spaceGUID = "some-space-guid"
   656  
   657  			fakeCloudControllerClient.GetApplicationsReturns(
   658  				[]resources.Application{
   659  					{
   660  						Name: "some-app-name",
   661  						GUID: "some-app-guid",
   662  					},
   663  				},
   664  				ccv3.Warnings{"get-app-warning"},
   665  				nil,
   666  			)
   667  			fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{GUID: "some-droplet-guid"}, ccv3.Warnings{"some-warning"}, nil)
   668  		})
   669  
   670  		JustBeforeEach(func() {
   671  			dropletBytes, dropletGUID, warnings, executionErr = actor.DownloadCurrentDropletByAppName(appName, spaceGUID)
   672  		})
   673  
   674  		When("there is a current droplet available for download", func() {
   675  			BeforeEach(func() {
   676  				fakeCloudControllerClient.DownloadDropletReturns([]byte{'d', 'r', 'o', 'p'}, ccv3.Warnings{"some-droplet-warning"}, nil)
   677  			})
   678  
   679  			It("successfully downloads", func() {
   680  				Expect(executionErr).ToNot(HaveOccurred())
   681  				Expect(warnings).To(ConsistOf("get-app-warning", "some-droplet-warning", "some-warning"))
   682  				Expect(dropletBytes).To(Equal([]byte{'d', 'r', 'o', 'p'}))
   683  				Expect(dropletGUID).To(Equal("some-droplet-guid"))
   684  
   685  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   686  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   687  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   688  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   689  				))
   690  
   691  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentCallCount()).To(Equal(1))
   692  				Expect(fakeCloudControllerClient.GetApplicationDropletCurrentArgsForCall(0)).To(Equal("some-app-guid"))
   693  				Expect(fakeCloudControllerClient.DownloadDropletCallCount()).To(Equal(1))
   694  				Expect(fakeCloudControllerClient.DownloadDropletArgsForCall(0)).To(Equal("some-droplet-guid"))
   695  
   696  			})
   697  		})
   698  
   699  		When("the app does not exist", func() {
   700  			BeforeEach(func() {
   701  				fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{}, ccv3.Warnings{"some-warning"}, nil)
   702  			})
   703  
   704  			It("returns an ApplicationNotFoundError and warnings", func() {
   705  				Expect(executionErr).To(MatchError(actionerror.ApplicationNotFoundError{Name: appName}))
   706  				Expect(warnings).To(ConsistOf("some-warning"))
   707  			})
   708  		})
   709  
   710  		When("the current droplet does not exist", func() {
   711  			BeforeEach(func() {
   712  				fakeCloudControllerClient.GetApplicationDropletCurrentReturns(resources.Droplet{}, ccv3.Warnings{"some-warning"}, ccerror.DropletNotFoundError{})
   713  			})
   714  
   715  			It("returns an DropletNotFoundError and warnings", func() {
   716  				Expect(executionErr).To(MatchError(actionerror.DropletNotFoundError{}))
   717  				Expect(warnings).To(ConsistOf("get-app-warning", "some-warning"))
   718  			})
   719  		})
   720  
   721  		When("an error occurs downloading the droplet", func() {
   722  			BeforeEach(func() {
   723  				fakeCloudControllerClient.DownloadDropletReturns([]byte{}, ccv3.Warnings{"some-droplet-warning"}, errors.New("droplet-download-err"))
   724  			})
   725  
   726  			It("returns the error and warnings", func() {
   727  				Expect(executionErr).To(MatchError("droplet-download-err"))
   728  				Expect(warnings).To(ConsistOf("get-app-warning", "some-warning", "some-droplet-warning"))
   729  			})
   730  		})
   731  	})
   732  
   733  	Describe("DownloadDropletByGUIDAndAppName", func() {
   734  		var (
   735  			appName   string
   736  			spaceGUID string
   737  
   738  			dropletBytes []byte
   739  			dropletGUID  string
   740  			warnings     Warnings
   741  			executionErr error
   742  		)
   743  
   744  		BeforeEach(func() {
   745  			appName = "some-app-name"
   746  			spaceGUID = "some-space-guid"
   747  			dropletGUID = "some-droplet-guid"
   748  
   749  			fakeCloudControllerClient.GetApplicationsReturns(
   750  				[]resources.Application{
   751  					{
   752  						Name: "some-app-name",
   753  						GUID: "some-app-guid",
   754  					},
   755  				},
   756  				ccv3.Warnings{"get-app-warning"},
   757  				nil,
   758  			)
   759  			fakeCloudControllerClient.GetDropletsReturns([]resources.Droplet{{GUID: dropletGUID}}, ccv3.Warnings{"some-warning"}, nil)
   760  		})
   761  
   762  		JustBeforeEach(func() {
   763  			dropletBytes, warnings, executionErr = actor.DownloadDropletByGUIDAndAppName(dropletGUID, appName, spaceGUID)
   764  		})
   765  
   766  		When("there is a droplet available for download", func() {
   767  			BeforeEach(func() {
   768  				fakeCloudControllerClient.DownloadDropletReturns([]byte{'d', 'r', 'o', 'p'}, ccv3.Warnings{"some-droplet-warning"}, nil)
   769  			})
   770  
   771  			It("successfully downloads", func() {
   772  				Expect(executionErr).ToNot(HaveOccurred())
   773  				Expect(warnings).To(ConsistOf("get-app-warning", "some-droplet-warning", "some-warning"))
   774  				Expect(dropletBytes).To(Equal([]byte{'d', 'r', 'o', 'p'}))
   775  
   776  				Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   777  				Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf(
   778  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}},
   779  					ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}},
   780  				))
   781  
   782  				Expect(fakeCloudControllerClient.GetDropletsCallCount()).To(Equal(1))
   783  				Expect(fakeCloudControllerClient.GetDropletsArgsForCall(0)).To(ConsistOf(
   784  					ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{"some-droplet-guid"}},
   785  					ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{"some-app-guid"}},
   786  				))
   787  
   788  				Expect(fakeCloudControllerClient.DownloadDropletCallCount()).To(Equal(1))
   789  				Expect(fakeCloudControllerClient.DownloadDropletArgsForCall(0)).To(Equal("some-droplet-guid"))
   790  
   791  			})
   792  		})
   793  
   794  		When("the app does not exist", func() {
   795  			BeforeEach(func() {
   796  				fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{}, ccv3.Warnings{"some-warning"}, nil)
   797  			})
   798  
   799  			It("returns an ApplicationNotFoundError and warnings", func() {
   800  				Expect(executionErr).To(MatchError(actionerror.ApplicationNotFoundError{Name: appName}))
   801  				Expect(warnings).To(ConsistOf("some-warning"))
   802  			})
   803  		})
   804  
   805  		When("the droplet does not exist", func() {
   806  			BeforeEach(func() {
   807  				fakeCloudControllerClient.GetDropletsReturns([]resources.Droplet{}, ccv3.Warnings{"some-warning"}, nil)
   808  			})
   809  
   810  			It("returns an DropletNotFoundError and warnings", func() {
   811  				Expect(executionErr).To(MatchError(actionerror.DropletNotFoundError{}))
   812  				Expect(warnings).To(ConsistOf("get-app-warning", "some-warning"))
   813  			})
   814  		})
   815  
   816  		When("an error occurs downloading the droplet", func() {
   817  			BeforeEach(func() {
   818  				fakeCloudControllerClient.DownloadDropletReturns([]byte{}, ccv3.Warnings{"some-droplet-warning"}, errors.New("droplet-download-err"))
   819  			})
   820  
   821  			It("returns the error and warnings", func() {
   822  				Expect(executionErr).To(MatchError("droplet-download-err"))
   823  				Expect(warnings).To(ConsistOf("get-app-warning", "some-warning", "some-droplet-warning"))
   824  			})
   825  		})
   826  	})
   827  })