github.com/Thanhphan1147/cloudfoundry-cli@v7.1.0+incompatible/actor/v7pushaction/create_bits_package_for_application_test.go (about)

     1  package v7pushaction_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	"code.cloudfoundry.org/cli/actor/sharedaction"
     9  	"code.cloudfoundry.org/cli/actor/v7action"
    10  	. "code.cloudfoundry.org/cli/actor/v7pushaction"
    11  	"code.cloudfoundry.org/cli/actor/v7pushaction/v7pushactionfakes"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    14  	"code.cloudfoundry.org/cli/resources"
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/gomega"
    17  )
    18  
    19  func buildEmptyV3Resource(name string) sharedaction.V3Resource {
    20  	return sharedaction.V3Resource{
    21  		FilePath:    name,
    22  		Checksum:    ccv3.Checksum{Value: fmt.Sprintf("checksum-%s", name)},
    23  		SizeInBytes: 0,
    24  	}
    25  }
    26  
    27  var _ = Describe("CreateBitsPackageForApplication", func() {
    28  	var (
    29  		actor           *Actor
    30  		fakeV7Actor     *v7pushactionfakes.FakeV7Actor
    31  		fakeSharedActor *v7pushactionfakes.FakeSharedActor
    32  
    33  		returnedPushPlan PushPlan
    34  		paramPlan        PushPlan
    35  		fakeProgressBar  *v7pushactionfakes.FakeProgressBar
    36  
    37  		warnings   Warnings
    38  		executeErr error
    39  
    40  		events []Event
    41  	)
    42  
    43  	BeforeEach(func() {
    44  		actor, fakeV7Actor, fakeSharedActor = getTestPushActor()
    45  
    46  		fakeProgressBar = new(v7pushactionfakes.FakeProgressBar)
    47  
    48  		fakeSharedActor.ReadArchiveReturns(new(v7pushactionfakes.FakeReadCloser), 0, nil)
    49  
    50  		paramPlan = PushPlan{
    51  			Application: resources.Application{
    52  				GUID: "some-app-guid",
    53  			},
    54  		}
    55  	})
    56  
    57  	JustBeforeEach(func() {
    58  		events = EventFollower(func(eventStream chan<- *PushEvent) {
    59  			returnedPushPlan, warnings, executeErr = actor.CreateBitsPackageForApplication(paramPlan, eventStream, fakeProgressBar)
    60  		})
    61  	})
    62  
    63  	Describe("package upload", func() {
    64  		When("resource match errors ", func() {
    65  			BeforeEach(func() {
    66  				paramPlan.AllResources = []sharedaction.V3Resource{
    67  					buildV3Resource("some-filename"),
    68  				}
    69  
    70  				fakeV7Actor.ResourceMatchReturns(
    71  					nil,
    72  					v7action.Warnings{"some-resource-match-warning"},
    73  					errors.New("resource-match-error"))
    74  			})
    75  
    76  			It("raises the error", func() {
    77  				Expect(executeErr).To(MatchError("resource-match-error"))
    78  				Expect(events).To(ConsistOf(ResourceMatching))
    79  				Expect(warnings).To(ConsistOf("some-resource-match-warning"))
    80  			})
    81  		})
    82  
    83  		When("resource match is successful", func() {
    84  			var (
    85  				matches   []sharedaction.V3Resource
    86  				unmatches []sharedaction.V3Resource
    87  			)
    88  
    89  			When("all resources are empty", func() {
    90  				BeforeEach(func() {
    91  					emptyFiles := []sharedaction.V3Resource{
    92  						buildEmptyV3Resource("empty-filename-1"),
    93  						buildEmptyV3Resource("empty-filename-2"),
    94  					}
    95  
    96  					paramPlan = PushPlan{
    97  						Application: resources.Application{
    98  							Name: "some-app",
    99  							GUID: "some-app-guid",
   100  						},
   101  						BitsPath:     "/some-bits-path",
   102  						AllResources: emptyFiles,
   103  					}
   104  				})
   105  
   106  				It("skips resource matching", func() {
   107  					Expect(fakeV7Actor.ResourceMatchCallCount()).To(Equal(0))
   108  				})
   109  			})
   110  
   111  			When("there are unmatched resources", func() {
   112  				BeforeEach(func() {
   113  					matches = []sharedaction.V3Resource{
   114  						buildV3Resource("some-matching-filename"),
   115  					}
   116  
   117  					unmatches = []sharedaction.V3Resource{
   118  						buildV3Resource("some-unmatching-filename"),
   119  					}
   120  
   121  					paramPlan = PushPlan{
   122  						Application: resources.Application{
   123  							Name: "some-app",
   124  							GUID: "some-app-guid",
   125  						},
   126  						BitsPath: "/some-bits-path",
   127  						AllResources: append(
   128  							matches,
   129  							unmatches...,
   130  						),
   131  					}
   132  
   133  					fakeV7Actor.ResourceMatchReturns(
   134  						matches,
   135  						v7action.Warnings{"some-good-good-resource-match-warnings"},
   136  						nil,
   137  					)
   138  				})
   139  
   140  				When("the bits path is an archive", func() {
   141  					BeforeEach(func() {
   142  						paramPlan.Archive = true
   143  					})
   144  
   145  					It("creates the archive with the unmatched resources", func() {
   146  						Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(Equal(1))
   147  						bitsPath, resources := fakeSharedActor.ZipArchiveResourcesArgsForCall(0)
   148  						Expect(bitsPath).To(Equal("/some-bits-path"))
   149  						Expect(resources).To(HaveLen(1))
   150  						Expect(resources[0].ToV3Resource()).To(Equal(unmatches[0]))
   151  					})
   152  				})
   153  
   154  				When("The bits path is a directory", func() {
   155  					It("creates the archive", func() {
   156  						Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(Equal(1))
   157  						bitsPath, resources := fakeSharedActor.ZipDirectoryResourcesArgsForCall(0)
   158  						Expect(bitsPath).To(Equal("/some-bits-path"))
   159  						Expect(resources).To(HaveLen(1))
   160  						Expect(resources[0].ToV3Resource()).To(Equal(unmatches[0]))
   161  					})
   162  				})
   163  
   164  				When("the archive creation is successful", func() {
   165  					BeforeEach(func() {
   166  						fakeSharedActor.ZipDirectoryResourcesReturns("/some/archive/path", nil)
   167  						fakeV7Actor.UpdateApplicationReturns(
   168  							resources.Application{
   169  								Name: "some-app",
   170  								GUID: paramPlan.Application.GUID,
   171  							},
   172  							v7action.Warnings{"some-app-update-warnings"},
   173  							nil)
   174  					})
   175  
   176  					It("creates the package", func() {
   177  						Expect(fakeV7Actor.CreateBitsPackageByApplicationCallCount()).To(Equal(1))
   178  						Expect(fakeV7Actor.CreateBitsPackageByApplicationArgsForCall(0)).To(Equal("some-app-guid"))
   179  					})
   180  
   181  					When("the package creation is successful", func() {
   182  						BeforeEach(func() {
   183  							fakeV7Actor.CreateBitsPackageByApplicationReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"some-create-package-warning"}, nil)
   184  						})
   185  
   186  						It("reads the archive", func() {
   187  							Expect(fakeSharedActor.ReadArchiveCallCount()).To(Equal(1))
   188  							Expect(fakeSharedActor.ReadArchiveArgsForCall(0)).To(Equal("/some/archive/path"))
   189  						})
   190  
   191  						When("reading the archive is successful", func() {
   192  							BeforeEach(func() {
   193  								fakeReadCloser := new(v7pushactionfakes.FakeReadCloser)
   194  								fakeSharedActor.ReadArchiveReturns(fakeReadCloser, 6, nil)
   195  							})
   196  
   197  							It("uploads the bits package", func() {
   198  								Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1))
   199  								pkg, resource, _, size := fakeV7Actor.UploadBitsPackageArgsForCall(0)
   200  
   201  								Expect(pkg).To(Equal(v7action.Package{GUID: "some-guid"}))
   202  								Expect(resource).To(Equal(matches))
   203  								Expect(size).To(BeNumerically("==", 6))
   204  							})
   205  
   206  							When("the upload is successful", func() {
   207  								BeforeEach(func() {
   208  									fakeV7Actor.UploadBitsPackageReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"some-upload-package-warning"}, nil)
   209  								})
   210  
   211  								It("returns an upload complete event and warnings", func() {
   212  									Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete))
   213  									Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "some-upload-package-warning"))
   214  								})
   215  
   216  								When("the upload errors", func() {
   217  									When("the upload error is a retryable error", func() {
   218  										var someErr error
   219  
   220  										BeforeEach(func() {
   221  											someErr = errors.New("I AM A BANANA")
   222  											fakeV7Actor.UploadBitsPackageReturns(v7action.Package{}, v7action.Warnings{"upload-warnings-1", "upload-warnings-2"}, ccerror.PipeSeekError{Err: someErr})
   223  										})
   224  
   225  										It("should send a RetryUpload event and retry uploading", func() {
   226  											Expect(events).To(ConsistOf(
   227  												ResourceMatching, CreatingPackage, CreatingArchive,
   228  												ReadingArchive, UploadingApplicationWithArchive, RetryUpload,
   229  												ReadingArchive, UploadingApplicationWithArchive, RetryUpload,
   230  												ReadingArchive, UploadingApplicationWithArchive, RetryUpload,
   231  											))
   232  
   233  											Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "upload-warnings-1", "upload-warnings-2", "upload-warnings-1", "upload-warnings-2", "upload-warnings-1", "upload-warnings-2"))
   234  
   235  											Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(3))
   236  											Expect(executeErr).To(MatchError(actionerror.UploadFailedError{Err: someErr}))
   237  										})
   238  
   239  									})
   240  
   241  									When("the upload error is not a retryable error", func() {
   242  										BeforeEach(func() {
   243  											fakeV7Actor.UploadBitsPackageReturns(v7action.Package{}, v7action.Warnings{"upload-warnings-1", "upload-warnings-2"}, errors.New("dios mio"))
   244  										})
   245  
   246  										It("sends warnings and errors, then stops", func() {
   247  											Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive))
   248  											Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "upload-warnings-1", "upload-warnings-2"))
   249  											Expect(executeErr).To(MatchError("dios mio"))
   250  										})
   251  									})
   252  								})
   253  							})
   254  
   255  							When("reading the archive fails", func() {
   256  								BeforeEach(func() {
   257  									fakeSharedActor.ReadArchiveReturns(nil, 0, errors.New("the bits"))
   258  								})
   259  
   260  								It("returns an error", func() {
   261  									Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive))
   262  									Expect(executeErr).To(MatchError("the bits"))
   263  								})
   264  							})
   265  						})
   266  
   267  						When("the package creation errors", func() {
   268  							BeforeEach(func() {
   269  								fakeV7Actor.CreateBitsPackageByApplicationReturns(v7action.Package{}, v7action.Warnings{"package-creation-warning"}, errors.New("the package"))
   270  							})
   271  
   272  							It("it returns errors and warnings", func() {
   273  								Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage))
   274  
   275  								Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "package-creation-warning"))
   276  								Expect(executeErr).To(MatchError("the package"))
   277  							})
   278  						})
   279  					})
   280  
   281  					When("the archive creation errors", func() {
   282  						BeforeEach(func() {
   283  							fakeSharedActor.ZipDirectoryResourcesReturns("", errors.New("oh no"))
   284  						})
   285  
   286  						It("returns an error and exits", func() {
   287  							Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive))
   288  							Expect(executeErr).To(MatchError("oh no"))
   289  						})
   290  					})
   291  				})
   292  			})
   293  
   294  			When("All resources are matched", func() {
   295  				BeforeEach(func() {
   296  					matches = []sharedaction.V3Resource{
   297  						buildV3Resource("some-matching-filename"),
   298  					}
   299  
   300  					paramPlan = PushPlan{
   301  						Application: resources.Application{
   302  							Name: "some-app",
   303  							GUID: "some-app-guid",
   304  						},
   305  						BitsPath:     "/some-bits-path",
   306  						AllResources: matches,
   307  					}
   308  
   309  					fakeV7Actor.ResourceMatchReturns(
   310  						matches,
   311  						v7action.Warnings{"some-good-good-resource-match-warnings"},
   312  						nil,
   313  					)
   314  				})
   315  
   316  				When("package upload succeeds", func() {
   317  					BeforeEach(func() {
   318  						fakeV7Actor.UploadBitsPackageReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"upload-warning"}, nil)
   319  					})
   320  
   321  					It("Uploads the package without a zip", func() {
   322  						Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(BeZero())
   323  						Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(BeZero())
   324  						Expect(fakeSharedActor.ReadArchiveCallCount()).To(BeZero())
   325  
   326  						Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, UploadingApplication))
   327  						Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1))
   328  						_, actualMatchedResources, actualProgressReader, actualSize := fakeV7Actor.UploadBitsPackageArgsForCall(0)
   329  
   330  						Expect(actualMatchedResources).To(Equal(matches))
   331  						Expect(actualProgressReader).To(BeNil())
   332  						Expect(actualSize).To(BeZero())
   333  					})
   334  				})
   335  
   336  				When("package upload fails", func() {
   337  					BeforeEach(func() {
   338  						fakeV7Actor.UploadBitsPackageReturns(
   339  							v7action.Package{},
   340  							v7action.Warnings{"upload-warning"},
   341  							errors.New("upload-error"),
   342  						)
   343  					})
   344  
   345  					It("returns an error", func() {
   346  						Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(BeZero())
   347  						Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(BeZero())
   348  						Expect(fakeSharedActor.ReadArchiveCallCount()).To(BeZero())
   349  
   350  						Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, UploadingApplication))
   351  						Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1))
   352  						_, actualMatchedResources, actualProgressReader, actualSize := fakeV7Actor.UploadBitsPackageArgsForCall(0)
   353  
   354  						Expect(actualMatchedResources).To(Equal(matches))
   355  						Expect(actualProgressReader).To(BeNil())
   356  						Expect(actualSize).To(BeZero())
   357  
   358  						Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "upload-warning"))
   359  						Expect(executeErr).To(MatchError("upload-error"))
   360  					})
   361  				})
   362  			})
   363  		})
   364  	})
   365  
   366  	Describe("polling package", func() {
   367  		var (
   368  			matches   []sharedaction.V3Resource
   369  			unmatches []sharedaction.V3Resource
   370  		)
   371  
   372  		BeforeEach(func() {
   373  			matches = []sharedaction.V3Resource{
   374  				buildV3Resource("some-matching-filename"),
   375  			}
   376  
   377  			unmatches = []sharedaction.V3Resource{
   378  				buildV3Resource("some-unmatching-filename"),
   379  			}
   380  
   381  			paramPlan = PushPlan{
   382  				Application: resources.Application{
   383  					Name: "some-app",
   384  					GUID: "some-app-guid",
   385  				},
   386  				BitsPath: "/some-bits-path",
   387  				AllResources: append(
   388  					matches,
   389  					unmatches...,
   390  				),
   391  			}
   392  
   393  			fakeV7Actor.ResourceMatchReturns(
   394  				matches,
   395  				v7action.Warnings{"some-good-good-resource-match-warnings"},
   396  				nil,
   397  			)
   398  		})
   399  
   400  		When("the the polling is successful", func() {
   401  			BeforeEach(func() {
   402  				fakeV7Actor.PollPackageReturns(v7action.Package{GUID: "some-package-guid"}, v7action.Warnings{"some-poll-package-warning"}, nil)
   403  			})
   404  
   405  			It("returns warnings", func() {
   406  				Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete))
   407  				Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-poll-package-warning"))
   408  			})
   409  
   410  			It("sets the package guid on push plan", func() {
   411  				Expect(returnedPushPlan.PackageGUID).To(Equal("some-package-guid"))
   412  			})
   413  		})
   414  
   415  		When("the the polling returns an error", func() {
   416  			var someErr error
   417  
   418  			BeforeEach(func() {
   419  				someErr = errors.New("I AM A BANANA")
   420  				fakeV7Actor.PollPackageReturns(v7action.Package{}, v7action.Warnings{"some-poll-package-warning"}, someErr)
   421  			})
   422  
   423  			It("returns errors and warnings", func() {
   424  				Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete))
   425  				Expect(executeErr).To(MatchError(someErr))
   426  			})
   427  		})
   428  	})
   429  })