github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/actor/v3action/package_test.go (about)

     1  package v3action_test
     2  
     3  import (
     4  	"archive/zip"
     5  	"errors"
     6  	"io/ioutil"
     7  	"net/url"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	. "code.cloudfoundry.org/cli/actor/v3action"
    12  	"code.cloudfoundry.org/cli/actor/v3action/v3actionfakes"
    13  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    14  
    15  	. "github.com/onsi/ginkgo"
    16  	. "github.com/onsi/ginkgo/extensions/table"
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  func createFile(root, path, contents string) int64 {
    21  	filepath := filepath.Join(root, path)
    22  	err := ioutil.WriteFile(filepath, []byte(contents), 0666)
    23  	Expect(err).NotTo(HaveOccurred())
    24  
    25  	fileInfo, err := os.Stat(filepath)
    26  	Expect(err).NotTo(HaveOccurred())
    27  	return fileInfo.Size()
    28  }
    29  
    30  var _ = Describe("Package Actions", func() {
    31  	var (
    32  		actor                     *Actor
    33  		fakeCloudControllerClient *v3actionfakes.FakeCloudControllerClient
    34  		fakeConfig                *v3actionfakes.FakeConfig
    35  	)
    36  
    37  	BeforeEach(func() {
    38  		fakeCloudControllerClient = new(v3actionfakes.FakeCloudControllerClient)
    39  		fakeConfig = new(v3actionfakes.FakeConfig)
    40  		actor = NewActor(fakeCloudControllerClient, fakeConfig)
    41  	})
    42  
    43  	Describe("CreateAndUploadPackageByApplicationNameAndSpace", func() {
    44  		Context("when the application can be retrieved", func() {
    45  			BeforeEach(func() {
    46  				fakeCloudControllerClient.GetApplicationsReturns(
    47  					[]ccv3.Application{
    48  						{
    49  							Name: "some-app-name",
    50  							GUID: "some-app-guid",
    51  						},
    52  					},
    53  					ccv3.Warnings{"some-app-warning"},
    54  					nil,
    55  				)
    56  			})
    57  
    58  			Context("when the zip can be created", func() {
    59  				var (
    60  					bitsPath           string
    61  					expectedFilesInZip map[string]int64
    62  				)
    63  
    64  				BeforeEach(func() {
    65  					var err error
    66  					bitsPath, err = ioutil.TempDir("", "example")
    67  					Expect(err).ToNot(HaveOccurred())
    68  
    69  					expectedFilesInZip = map[string]int64{
    70  						"tmpfile":         0,
    71  						"folder1/tmpfile": 0,
    72  					}
    73  
    74  					err = os.Mkdir(filepath.Join(bitsPath, "folder1"), 0777)
    75  					Expect(err).ToNot(HaveOccurred())
    76  
    77  					for path, _ := range expectedFilesInZip {
    78  						expectedFilesInZip[path] = createFile(bitsPath, path, "some-contents")
    79  					}
    80  					expectedFilesInZip["folder1/"] = 0
    81  
    82  				})
    83  
    84  				AfterEach(func() {
    85  					if bitsPath != "" {
    86  						err := os.RemoveAll(bitsPath)
    87  						Expect(err).ToNot(HaveOccurred())
    88  					}
    89  				})
    90  
    91  				Context("when the package is created successfully", func() {
    92  					var createdPackage ccv3.Package
    93  
    94  					BeforeEach(func() {
    95  						createdPackage = ccv3.Package{
    96  							GUID:  "some-pkg-guid",
    97  							State: ccv3.PackageStateAwaitingUpload,
    98  							Relationships: ccv3.Relationships{
    99  								ccv3.ApplicationRelationship: ccv3.Relationship{
   100  									GUID: "some-app-guid",
   101  								},
   102  							},
   103  						}
   104  
   105  						fakeCloudControllerClient.CreatePackageReturns(
   106  							createdPackage,
   107  							ccv3.Warnings{"some-pkg-warning"},
   108  							nil,
   109  						)
   110  					})
   111  
   112  					Context("when the file uploading is successful", func() {
   113  						BeforeEach(func() {
   114  							fakeCloudControllerClient.UploadPackageReturns(ccv3.Package{}, ccv3.Warnings{"some-upload-pkg-warning"}, nil)
   115  						})
   116  
   117  						Context("when the polling is successful", func() {
   118  							BeforeEach(func() {
   119  								fakeCloudControllerClient.GetPackageReturns(
   120  									ccv3.Package{GUID: "some-pkg-guid", State: ccv3.PackageStateReady},
   121  									ccv3.Warnings{"some-get-pkg-warning"},
   122  									nil,
   123  								)
   124  							})
   125  
   126  							It("correctly constructs the zip", func() {
   127  								fakeCloudControllerClient.UploadPackageStub = func(pkg ccv3.Package, zipFilePart string) (ccv3.Package, ccv3.Warnings, error) {
   128  									filestats := map[string]int64{}
   129  									reader, err := zip.OpenReader(zipFilePart)
   130  									Expect(err).ToNot(HaveOccurred())
   131  
   132  									for _, file := range reader.File {
   133  										filestats[file.Name] = file.FileInfo().Size()
   134  									}
   135  
   136  									Expect(filestats).To(Equal(expectedFilesInZip))
   137  
   138  									return ccv3.Package{}, nil, nil
   139  								}
   140  								_, _, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   141  								Expect(err).NotTo(HaveOccurred())
   142  								Expect(fakeCloudControllerClient.UploadPackageCallCount()).To(Equal(1))
   143  							})
   144  
   145  							It("collects all warnings", func() {
   146  								_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   147  								Expect(err).NotTo(HaveOccurred())
   148  								Expect(warnings).To(ConsistOf("some-app-warning", "some-pkg-warning", "some-upload-pkg-warning", "some-get-pkg-warning"))
   149  							})
   150  
   151  							It("successfully resolves the app name", func() {
   152  								_, _, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   153  								Expect(err).ToNot(HaveOccurred())
   154  
   155  								Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1))
   156  								expectedQuery := url.Values{
   157  									"names":       []string{"some-app-name"},
   158  									"space_guids": []string{"some-space-guid"},
   159  								}
   160  								query := fakeCloudControllerClient.GetApplicationsArgsForCall(0)
   161  								Expect(query).To(Equal(expectedQuery))
   162  							})
   163  
   164  							It("successfully creates the Package", func() {
   165  								_, _, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   166  								Expect(err).ToNot(HaveOccurred())
   167  
   168  								Expect(fakeCloudControllerClient.CreatePackageCallCount()).To(Equal(1))
   169  								inputPackage := fakeCloudControllerClient.CreatePackageArgsForCall(0)
   170  								Expect(inputPackage).To(Equal(ccv3.Package{
   171  									Type: ccv3.PackageTypeBits,
   172  									Relationships: ccv3.Relationships{
   173  										ccv3.ApplicationRelationship: ccv3.Relationship{GUID: "some-app-guid"},
   174  									},
   175  								}))
   176  							})
   177  
   178  							It("returns the package", func() {
   179  								pkg, _, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   180  								Expect(err).ToNot(HaveOccurred())
   181  
   182  								expectedPackage := ccv3.Package{
   183  									GUID:  "some-pkg-guid",
   184  									State: ccv3.PackageStateReady,
   185  								}
   186  								Expect(pkg).To(Equal(Package(expectedPackage)))
   187  
   188  								Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(1))
   189  								Expect(fakeCloudControllerClient.GetPackageArgsForCall(0)).To(Equal("some-pkg-guid"))
   190  							})
   191  
   192  							DescribeTable("polls until terminal state is reached",
   193  								func(finalState ccv3.PackageState, expectedErr error) {
   194  									fakeCloudControllerClient.GetPackageReturns(
   195  										ccv3.Package{GUID: "some-pkg-guid", State: ccv3.PackageStateAwaitingUpload},
   196  										ccv3.Warnings{"some-get-pkg-warning"},
   197  										nil,
   198  									)
   199  									fakeCloudControllerClient.GetPackageReturnsOnCall(
   200  										2,
   201  										ccv3.Package{State: finalState},
   202  										ccv3.Warnings{"some-get-pkg-warning"},
   203  										nil,
   204  									)
   205  
   206  									_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   207  
   208  									if expectedErr == nil {
   209  										Expect(err).ToNot(HaveOccurred())
   210  									} else {
   211  										Expect(err).To(MatchError(expectedErr))
   212  									}
   213  
   214  									Expect(warnings).To(ConsistOf("some-app-warning", "some-pkg-warning", "some-upload-pkg-warning", "some-get-pkg-warning", "some-get-pkg-warning", "some-get-pkg-warning"))
   215  
   216  									Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(3))
   217  									Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(3))
   218  								},
   219  
   220  								Entry("READY", ccv3.PackageStateReady, nil),
   221  								Entry("FAILED", ccv3.PackageStateFailed, PackageProcessingFailedError{}),
   222  								Entry("EXPIRED", ccv3.PackageStateExpired, PackageProcessingExpiredError{}),
   223  							)
   224  						})
   225  
   226  						Context("when the polling errors", func() {
   227  							var expectedErr error
   228  							BeforeEach(func() {
   229  								expectedErr = errors.New("Fake error during polling")
   230  								fakeCloudControllerClient.GetPackageReturns(
   231  									ccv3.Package{},
   232  									ccv3.Warnings{"some-get-pkg-warning"},
   233  									expectedErr,
   234  								)
   235  							})
   236  
   237  							It("returns the error and warnings", func() {
   238  								_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   239  								Expect(err).To(MatchError(expectedErr))
   240  								Expect(warnings).To(ConsistOf("some-app-warning", "some-pkg-warning", "some-upload-pkg-warning", "some-get-pkg-warning"))
   241  							})
   242  						})
   243  					})
   244  
   245  					Context("when the file uploading errors", func() {
   246  						var expectedErr error
   247  
   248  						BeforeEach(func() {
   249  							expectedErr = errors.New("ZOMG Package Uploading")
   250  							fakeCloudControllerClient.UploadPackageReturns(ccv3.Package{}, ccv3.Warnings{"some-upload-pkg-warning"}, expectedErr)
   251  						})
   252  
   253  						It("returns the warnings and the error", func() {
   254  							_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   255  							Expect(err).To(MatchError(expectedErr))
   256  							Expect(warnings).To(ConsistOf("some-app-warning", "some-pkg-warning", "some-upload-pkg-warning"))
   257  						})
   258  					})
   259  				})
   260  
   261  				Context("when the package creation errors", func() {
   262  					var expectedErr error
   263  
   264  					BeforeEach(func() {
   265  						expectedErr = errors.New("ZOMG Package Creation")
   266  						fakeCloudControllerClient.CreatePackageReturns(
   267  							ccv3.Package{},
   268  							ccv3.Warnings{"some-pkg-warning"},
   269  							expectedErr,
   270  						)
   271  					})
   272  
   273  					It("returns the warnings and the error", func() {
   274  						_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath)
   275  						Expect(err).To(MatchError(expectedErr))
   276  						Expect(warnings).To(ConsistOf("some-app-warning", "some-pkg-warning"))
   277  					})
   278  				})
   279  			})
   280  
   281  			Context("when creating the zip errors", func() {
   282  				It("returns the warnings and the error", func() {
   283  					_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", "/banana")
   284  					// Windows returns back a different error message
   285  					Expect(err.Error()).To(MatchRegexp("open /banana: no such file or directory|The system cannot find the file specified"))
   286  					Expect(warnings).To(ConsistOf("some-app-warning"))
   287  				})
   288  			})
   289  		})
   290  
   291  		Context("when retrieving the application errors", func() {
   292  			var expectedErr error
   293  
   294  			BeforeEach(func() {
   295  				expectedErr = errors.New("I am a CloudControllerClient Error")
   296  				fakeCloudControllerClient.GetApplicationsReturns(
   297  					[]ccv3.Application{},
   298  					ccv3.Warnings{"some-warning"},
   299  					expectedErr)
   300  			})
   301  
   302  			It("returns the warnings and the error", func() {
   303  				_, warnings, err := actor.CreateAndUploadPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", "some-path")
   304  				Expect(err).To(MatchError(expectedErr))
   305  				Expect(warnings).To(ConsistOf("some-warning"))
   306  			})
   307  		})
   308  	})
   309  })