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

     1  package v7action_test
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"code.cloudfoundry.org/cli/actor/actionerror"
    12  	. "code.cloudfoundry.org/cli/actor/v7action"
    13  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
    14  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    15  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    16  	"code.cloudfoundry.org/cli/types"
    17  	. "github.com/onsi/ginkgo"
    18  	. "github.com/onsi/gomega"
    19  )
    20  
    21  var _ = Describe("Buildpack", func() {
    22  	var (
    23  		actor                     *Actor
    24  		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
    25  	)
    26  
    27  	BeforeEach(func() {
    28  		actor, fakeCloudControllerClient, _, _, _, _, _ = NewTestActor()
    29  	})
    30  
    31  	Describe("GetBuildpackByNameAndStack", func() {
    32  		var (
    33  			buildpackName  = "buildpack-1"
    34  			buildpackStack = "stack-name"
    35  			buildpack      Buildpack
    36  			warnings       Warnings
    37  			executeErr     error
    38  		)
    39  
    40  		JustBeforeEach(func() {
    41  			buildpack, warnings, executeErr = actor.GetBuildpackByNameAndStack(buildpackName, buildpackStack)
    42  		})
    43  
    44  		When("getting buildpacks fails", func() {
    45  			BeforeEach(func() {
    46  
    47  				buildpackStack = "real-good-stack"
    48  				fakeCloudControllerClient.GetBuildpacksReturns(
    49  					nil,
    50  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
    51  					errors.New("some-error"))
    52  			})
    53  
    54  			It("returns warnings and error", func() {
    55  				Expect(executeErr).To(MatchError("some-error"))
    56  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
    57  				Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
    58  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
    59  				Expect(queries).To(ConsistOf(
    60  					ccv3.Query{
    61  						Key:    ccv3.NameFilter,
    62  						Values: []string{buildpackName},
    63  					},
    64  					ccv3.Query{
    65  						Key:    ccv3.StackFilter,
    66  						Values: []string{buildpackStack},
    67  					},
    68  				))
    69  			})
    70  		})
    71  
    72  		When("multiple buildpacks with stacks are returned", func() {
    73  			BeforeEach(func() {
    74  				ccBuildpacks := []ccv3.Buildpack{
    75  					{Name: buildpackName, Stack: "a-real-stack", Position: types.NullInt{Value: 1, IsSet: true}},
    76  					{Name: buildpackName, Stack: "another-stack", Position: types.NullInt{Value: 2, IsSet: true}},
    77  				}
    78  
    79  				fakeCloudControllerClient.GetBuildpacksReturns(
    80  					ccBuildpacks,
    81  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
    82  					nil)
    83  			})
    84  
    85  			It("returns warnings and MultipleBuildpacksFoundError", func() {
    86  				Expect(executeErr).To(MatchError(actionerror.MultipleBuildpacksFoundError{BuildpackName: buildpackName}))
    87  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
    88  			})
    89  
    90  		})
    91  
    92  		When("multiple buildpacks including one with no stack are returned", func() {
    93  			BeforeEach(func() {
    94  				ccBuildpacks := []ccv3.Buildpack{
    95  					{GUID: "buildpack-1-guid", Name: "buildpack-1", Stack: "a-real-stack", Position: types.NullInt{Value: 1, IsSet: true}},
    96  					{GUID: "buildpack-2-guid", Name: "buildpack-2", Stack: "", Position: types.NullInt{Value: 2, IsSet: true}},
    97  				}
    98  
    99  				fakeCloudControllerClient.GetBuildpacksReturns(
   100  					ccBuildpacks,
   101  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   102  					nil)
   103  			})
   104  
   105  			It("returns the nil stack buildpack and any warnings", func() {
   106  				Expect(executeErr).ToNot(HaveOccurred())
   107  				Expect(buildpack).To(Equal(Buildpack{Name: "buildpack-2", GUID: "buildpack-2-guid", Stack: "", Position: types.NullInt{Value: 2, IsSet: true}}))
   108  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   109  			})
   110  		})
   111  
   112  		When("zero buildpacks are returned", func() {
   113  			BeforeEach(func() {
   114  				var ccBuildpacks []ccv3.Buildpack
   115  
   116  				fakeCloudControllerClient.GetBuildpacksReturns(
   117  					ccBuildpacks,
   118  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   119  					nil)
   120  			})
   121  
   122  			It("returns warnings and a BuilpackNotFoundError", func() {
   123  				Expect(executeErr).To(MatchError(actionerror.BuildpackNotFoundError{BuildpackName: buildpackName, StackName: buildpackStack}))
   124  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   125  			})
   126  		})
   127  
   128  		When("getting buildpacks is successful", func() {
   129  			When("No stack is specified", func() {
   130  				BeforeEach(func() {
   131  					buildpackStack = ""
   132  					buildpackName = "my-buildpack"
   133  
   134  					ccBuildpack := ccv3.Buildpack{Name: "my-buildpack", GUID: "some-guid"}
   135  					fakeCloudControllerClient.GetBuildpacksReturns(
   136  						[]ccv3.Buildpack{ccBuildpack},
   137  						ccv3.Warnings{"some-warning-1", "some-warning-2"},
   138  						nil)
   139  				})
   140  
   141  				It("Returns the proper buildpack", func() {
   142  					Expect(executeErr).ToNot(HaveOccurred())
   143  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   144  					Expect(buildpack).To(Equal(Buildpack{Name: "my-buildpack", GUID: "some-guid"}))
   145  				})
   146  
   147  				It("Does not pass a stack query to the client", func() {
   148  					Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   149  					queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   150  					Expect(queries).To(ConsistOf(
   151  						ccv3.Query{
   152  							Key:    ccv3.NameFilter,
   153  							Values: []string{buildpackName},
   154  						},
   155  					))
   156  				})
   157  			})
   158  
   159  			When("A stack is specified", func() {
   160  				BeforeEach(func() {
   161  					buildpackStack = "good-stack"
   162  					buildpackName = "my-buildpack"
   163  
   164  					ccBuildpack := ccv3.Buildpack{Name: "my-buildpack", GUID: "some-guid", Stack: "good-stack"}
   165  					fakeCloudControllerClient.GetBuildpacksReturns(
   166  						[]ccv3.Buildpack{ccBuildpack},
   167  						ccv3.Warnings{"some-warning-1", "some-warning-2"},
   168  						nil)
   169  				})
   170  
   171  				It("Returns the proper buildpack", func() {
   172  					Expect(executeErr).ToNot(HaveOccurred())
   173  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   174  					Expect(buildpack).To(Equal(Buildpack{Name: "my-buildpack", GUID: "some-guid", Stack: "good-stack"}))
   175  				})
   176  
   177  				It("Does pass a stack query to the client", func() {
   178  					Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   179  					queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   180  					Expect(queries).To(ConsistOf(
   181  						ccv3.Query{
   182  							Key:    ccv3.NameFilter,
   183  							Values: []string{buildpackName},
   184  						},
   185  						ccv3.Query{
   186  							Key:    ccv3.StackFilter,
   187  							Values: []string{buildpackStack},
   188  						},
   189  					))
   190  				})
   191  			})
   192  		})
   193  	})
   194  
   195  	Describe("GetBuildpacks", func() {
   196  		var (
   197  			buildpacks    []Buildpack
   198  			warnings      Warnings
   199  			executeErr    error
   200  			labelSelector string
   201  		)
   202  
   203  		JustBeforeEach(func() {
   204  			buildpacks, warnings, executeErr = actor.GetBuildpacks(labelSelector)
   205  		})
   206  
   207  		It("calls CloudControllerClient.GetBuildpacks()", func() {
   208  			Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   209  		})
   210  
   211  		When("a label selector is not provided", func() {
   212  			BeforeEach(func() {
   213  				labelSelector = ""
   214  			})
   215  			It("only passes through a OrderBy query to the CloudControllerClient", func() {
   216  				positionQuery := ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.PositionOrder}}
   217  				Expect(fakeCloudControllerClient.GetBuildpacksArgsForCall(0)).To(ConsistOf(positionQuery))
   218  			})
   219  		})
   220  
   221  		When("a label selector is provided", func() {
   222  			BeforeEach(func() {
   223  				labelSelector = "some-label-selector"
   224  			})
   225  
   226  			It("passes the labels selector through", func() {
   227  				labelQuery := ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}
   228  				Expect(fakeCloudControllerClient.GetBuildpacksArgsForCall(0)).To(ContainElement(labelQuery))
   229  			})
   230  		})
   231  
   232  		When("getting buildpacks fails", func() {
   233  			BeforeEach(func() {
   234  				fakeCloudControllerClient.GetBuildpacksReturns(
   235  					nil,
   236  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   237  					errors.New("some-error"))
   238  			})
   239  
   240  			It("returns warnings and error", func() {
   241  				Expect(executeErr).To(MatchError("some-error"))
   242  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   243  			})
   244  		})
   245  
   246  		When("getting buildpacks is successful", func() {
   247  			BeforeEach(func() {
   248  				ccBuildpacks := []ccv3.Buildpack{
   249  					{Name: "buildpack-1", Position: types.NullInt{Value: 1, IsSet: true}},
   250  					{Name: "buildpack-2", Position: types.NullInt{Value: 2, IsSet: true}},
   251  				}
   252  
   253  				fakeCloudControllerClient.GetBuildpacksReturns(
   254  					ccBuildpacks,
   255  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   256  					nil)
   257  			})
   258  
   259  			It("returns the buildpacks and warnings", func() {
   260  				Expect(executeErr).ToNot(HaveOccurred())
   261  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   262  				Expect(buildpacks).To(Equal([]Buildpack{
   263  					{Name: "buildpack-1", Position: types.NullInt{Value: 1, IsSet: true}},
   264  					{Name: "buildpack-2", Position: types.NullInt{Value: 2, IsSet: true}},
   265  				}))
   266  			})
   267  		})
   268  	})
   269  
   270  	Describe("CreateBuildpack", func() {
   271  		var (
   272  			buildpack  Buildpack
   273  			warnings   Warnings
   274  			executeErr error
   275  			bp         Buildpack
   276  		)
   277  
   278  		JustBeforeEach(func() {
   279  			buildpack, warnings, executeErr = actor.CreateBuildpack(bp)
   280  		})
   281  
   282  		When("creating a buildpack fails", func() {
   283  			BeforeEach(func() {
   284  				fakeCloudControllerClient.CreateBuildpackReturns(
   285  					ccv3.Buildpack{},
   286  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   287  					errors.New("some-error"))
   288  			})
   289  
   290  			It("returns warnings and error", func() {
   291  				Expect(executeErr).To(MatchError("some-error"))
   292  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   293  				Expect(buildpack).To(Equal(Buildpack{}))
   294  			})
   295  		})
   296  
   297  		When("creating a buildpack is successful", func() {
   298  			var returnBuildpack Buildpack
   299  			BeforeEach(func() {
   300  				bp = Buildpack{Name: "some-name", Stack: "some-stack"}
   301  				returnBuildpack = Buildpack{GUID: "some-guid", Name: "some-name", Stack: "some-stack"}
   302  				fakeCloudControllerClient.CreateBuildpackReturns(
   303  					ccv3.Buildpack(returnBuildpack),
   304  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   305  					nil)
   306  			})
   307  
   308  			It("returns the buildpacks and warnings", func() {
   309  				Expect(executeErr).ToNot(HaveOccurred())
   310  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   311  				Expect(buildpack).To(Equal(returnBuildpack))
   312  
   313  				Expect(fakeCloudControllerClient.CreateBuildpackCallCount()).To(Equal(1))
   314  				Expect(fakeCloudControllerClient.CreateBuildpackArgsForCall(0)).To(Equal(ccv3.Buildpack(bp)))
   315  			})
   316  		})
   317  	})
   318  
   319  	Describe("UpdateBuildpackByNameAndStack", func() {
   320  		var (
   321  			buildpackName  = "my-buidpack"
   322  			buildpackStack = "my-stack"
   323  			buildpack      = Buildpack{
   324  				Stack: "new-stack",
   325  			}
   326  
   327  			retBuildpack Buildpack
   328  			warnings     Warnings
   329  			executeErr   error
   330  		)
   331  
   332  		JustBeforeEach(func() {
   333  			retBuildpack, warnings, executeErr = actor.UpdateBuildpackByNameAndStack(buildpackName, buildpackStack, buildpack)
   334  		})
   335  
   336  		When("it is successful", func() {
   337  			var updatedBuildpack Buildpack
   338  			BeforeEach(func() {
   339  				foundBuildpack := ccv3.Buildpack{GUID: "a guid", Stack: ""}
   340  				updatedBuildpack = Buildpack{GUID: "a guid", Stack: "new-stack"}
   341  				fakeCloudControllerClient.GetBuildpacksReturns([]ccv3.Buildpack{foundBuildpack}, ccv3.Warnings{"warning-1"}, nil)
   342  				fakeCloudControllerClient.UpdateBuildpackReturns(ccv3.Buildpack(updatedBuildpack), ccv3.Warnings{"warning-2"}, nil)
   343  			})
   344  
   345  			It("returns the updated buildpack and warnings", func() {
   346  				Expect(executeErr).ToNot(HaveOccurred())
   347  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   348  				Expect(retBuildpack).To(Equal(updatedBuildpack))
   349  
   350  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   351  				Expect(queries).To(ConsistOf(
   352  					ccv3.Query{
   353  						Key:    ccv3.NameFilter,
   354  						Values: []string{buildpackName},
   355  					},
   356  					ccv3.Query{
   357  						Key:    ccv3.StackFilter,
   358  						Values: []string{buildpackStack},
   359  					},
   360  				))
   361  
   362  				paramBuildpack := fakeCloudControllerClient.UpdateBuildpackArgsForCall(0)
   363  				Expect(paramBuildpack).To(Equal(ccv3.Buildpack{
   364  					GUID:  "a guid",
   365  					Stack: "new-stack",
   366  				}))
   367  			})
   368  		})
   369  
   370  		When("The get fails", func() {
   371  			BeforeEach(func() {
   372  				fakeCloudControllerClient.GetBuildpacksReturns([]ccv3.Buildpack{}, ccv3.Warnings{"warning-1"}, errors.New("whoops"))
   373  			})
   374  
   375  			It("returns the error and warnings", func() {
   376  				Expect(executeErr).To(HaveOccurred())
   377  				Expect(warnings).To(ConsistOf("warning-1"))
   378  				Expect(retBuildpack).To(Equal(Buildpack{}))
   379  			})
   380  		})
   381  
   382  		When("The update fails", func() {
   383  			BeforeEach(func() {
   384  				ccBuildpack := ccv3.Buildpack{GUID: "a guid", Stack: "old-stack"}
   385  				fakeCloudControllerClient.GetBuildpacksReturns([]ccv3.Buildpack{ccBuildpack}, ccv3.Warnings{"warning-1"}, nil)
   386  				fakeCloudControllerClient.UpdateBuildpackReturns(ccv3.Buildpack{}, ccv3.Warnings{"warning-2"}, errors.New("whoops"))
   387  			})
   388  
   389  			It("returns the error and warnings", func() {
   390  				Expect(executeErr).To(HaveOccurred())
   391  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   392  				Expect(retBuildpack).To(Equal(Buildpack{}))
   393  			})
   394  		})
   395  
   396  	})
   397  
   398  	Describe("UploadBuildpack", func() {
   399  		var (
   400  			bpFile     io.Reader
   401  			bpFilePath string
   402  			fakePb     *v7actionfakes.FakeSimpleProgressBar
   403  
   404  			jobURL     ccv3.JobURL
   405  			warnings   Warnings
   406  			executeErr error
   407  		)
   408  
   409  		BeforeEach(func() {
   410  			bpFile = strings.NewReader("")
   411  			fakePb = new(v7actionfakes.FakeSimpleProgressBar)
   412  			fakePb.InitializeReturns(bpFile, 66, nil)
   413  		})
   414  
   415  		JustBeforeEach(func() {
   416  			bpFilePath = "tmp/buildpack.zip"
   417  			jobURL, warnings, executeErr = actor.UploadBuildpack("some-bp-guid", bpFilePath, fakePb)
   418  		})
   419  
   420  		It("tracks the progress of the upload", func() {
   421  			Expect(executeErr).ToNot(HaveOccurred())
   422  			Expect(fakePb.InitializeCallCount()).To(Equal(1))
   423  			Expect(fakePb.InitializeArgsForCall(0)).To(Equal(bpFilePath))
   424  			Expect(fakePb.TerminateCallCount()).To(Equal(1))
   425  		})
   426  
   427  		When("reading the file errors", func() {
   428  			BeforeEach(func() {
   429  				fakePb.InitializeReturns(bpFile, 66, os.ErrNotExist)
   430  			})
   431  
   432  			It("returns the err", func() {
   433  				Expect(executeErr).To(Equal(os.ErrNotExist))
   434  			})
   435  		})
   436  
   437  		When("the upload errors", func() {
   438  			BeforeEach(func() {
   439  				fakeCloudControllerClient.UploadBuildpackReturns(
   440  					ccv3.JobURL(""),
   441  					ccv3.Warnings{"some-upload-warning"},
   442  					errors.New("some-upload-error"),
   443  				)
   444  			})
   445  
   446  			It("returns warnings and errors", func() {
   447  				Expect(warnings).To(ConsistOf("some-upload-warning"))
   448  				Expect(executeErr).To(MatchError("some-upload-error"))
   449  			})
   450  		})
   451  
   452  		When("the cc returns an error because the buildpack and stack combo already exists", func() {
   453  			BeforeEach(func() {
   454  				fakeCloudControllerClient.UploadBuildpackReturns(
   455  					ccv3.JobURL(""),
   456  					ccv3.Warnings{"some-upload-warning"},
   457  					ccerror.BuildpackAlreadyExistsForStackError{Message: "ya blew it"},
   458  				)
   459  			})
   460  
   461  			It("returns warnings and a BuildpackAlreadyExistsForStackError", func() {
   462  				Expect(warnings).To(ConsistOf("some-upload-warning"))
   463  				Expect(executeErr).To(MatchError(actionerror.BuildpackAlreadyExistsForStackError{Message: "ya blew it"}))
   464  			})
   465  		})
   466  
   467  		When("the upload is successful", func() {
   468  			BeforeEach(func() {
   469  				fakeCloudControllerClient.UploadBuildpackReturns(
   470  					ccv3.JobURL("http://example.com/some-job-url"),
   471  					ccv3.Warnings{"some-create-warning"},
   472  					nil,
   473  				)
   474  			})
   475  
   476  			It("uploads the buildpack and returns the Job URL and any warnings", func() {
   477  				Expect(executeErr).ToNot(HaveOccurred())
   478  				Expect(fakeCloudControllerClient.UploadBuildpackCallCount()).To(Equal(1))
   479  				guid, path, pbReader, size := fakeCloudControllerClient.UploadBuildpackArgsForCall(0)
   480  				Expect(guid).To(Equal("some-bp-guid"))
   481  				Expect(size).To(Equal(int64(66)))
   482  				Expect(path).To(Equal(bpFilePath))
   483  				Expect(pbReader).To(Equal(bpFile))
   484  				Expect(jobURL).To(Equal(ccv3.JobURL("http://example.com/some-job-url")))
   485  				Expect(warnings).To(ConsistOf("some-create-warning"))
   486  			})
   487  		})
   488  	})
   489  
   490  	Describe("PrepareBuildpackBits", func() {
   491  		var (
   492  			inPath         string
   493  			outPath        string
   494  			tmpDirPath     string
   495  			fakeDownloader *v7actionfakes.FakeDownloader
   496  
   497  			executeErr error
   498  		)
   499  
   500  		BeforeEach(func() {
   501  			fakeDownloader = new(v7actionfakes.FakeDownloader)
   502  		})
   503  
   504  		JustBeforeEach(func() {
   505  			outPath, executeErr = actor.PrepareBuildpackBits(inPath, tmpDirPath, fakeDownloader)
   506  		})
   507  
   508  		When("the buildpack path is a url", func() {
   509  			BeforeEach(func() {
   510  				inPath = "http://buildpacks.com/a.zip"
   511  				fakeDownloader = new(v7actionfakes.FakeDownloader)
   512  
   513  				var err error
   514  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   515  				Expect(err).ToNot(HaveOccurred())
   516  			})
   517  
   518  			AfterEach(func() {
   519  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   520  			})
   521  
   522  			When("downloading the file succeeds", func() {
   523  				BeforeEach(func() {
   524  					fakeDownloader.DownloadReturns("/tmp/buildpackdir-100/a.zip", nil)
   525  				})
   526  
   527  				It("downloads the buildpack to a local file", func() {
   528  					Expect(executeErr).ToNot(HaveOccurred())
   529  					Expect(fakeDownloader.DownloadCallCount()).To(Equal(1))
   530  
   531  					inputPath, inputTmpDirPath := fakeDownloader.DownloadArgsForCall(0)
   532  					Expect(inputPath).To(Equal("http://buildpacks.com/a.zip"))
   533  					Expect(inputTmpDirPath).To(Equal(tmpDirPath))
   534  				})
   535  			})
   536  
   537  			When("downloading the file fails", func() {
   538  				BeforeEach(func() {
   539  					fakeDownloader.DownloadReturns("", errors.New("some-download-error"))
   540  				})
   541  
   542  				It("returns the error", func() {
   543  					Expect(executeErr).To(MatchError("some-download-error"))
   544  				})
   545  			})
   546  		})
   547  
   548  		When("the buildpack path points to a directory", func() {
   549  			var tempFile *os.File
   550  			BeforeEach(func() {
   551  				var err error
   552  				inPath, err = ioutil.TempDir("", "buildpackdir-")
   553  				Expect(err).ToNot(HaveOccurred())
   554  
   555  				tempFile, err = ioutil.TempFile(inPath, "foo")
   556  				Expect(err).ToNot(HaveOccurred())
   557  
   558  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   559  				Expect(err).ToNot(HaveOccurred())
   560  			})
   561  
   562  			AfterEach(func() {
   563  				tempFile.Close()
   564  				Expect(os.RemoveAll(inPath)).ToNot(HaveOccurred())
   565  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   566  			})
   567  
   568  			It("returns a path to the zipped directory", func() {
   569  				Expect(executeErr).ToNot(HaveOccurred())
   570  				Expect(fakeDownloader.DownloadCallCount()).To(Equal(0))
   571  
   572  				Expect(filepath.Base(outPath)).To(Equal(filepath.Base(inPath) + ".zip"))
   573  			})
   574  		})
   575  
   576  		When("the buildpack path points to an empty directory", func() {
   577  			BeforeEach(func() {
   578  				var err error
   579  				inPath, err = ioutil.TempDir("", "some-empty-dir")
   580  				Expect(err).ToNot(HaveOccurred())
   581  
   582  				tmpDirPath, err = ioutil.TempDir("", "buildpackdir-")
   583  				Expect(err).ToNot(HaveOccurred())
   584  			})
   585  
   586  			AfterEach(func() {
   587  				Expect(os.RemoveAll(inPath)).ToNot(HaveOccurred())
   588  				Expect(os.RemoveAll(tmpDirPath)).ToNot(HaveOccurred())
   589  			})
   590  
   591  			It("returns an error", func() {
   592  				Expect(executeErr).To(MatchError(actionerror.EmptyBuildpackDirectoryError{Path: inPath}))
   593  			})
   594  		})
   595  
   596  		When("the buildpack path points to a zip file", func() {
   597  			BeforeEach(func() {
   598  				inPath = "/foo/buildpacks/a.zip"
   599  			})
   600  
   601  			It("returns the local filepath", func() {
   602  				Expect(executeErr).ToNot(HaveOccurred())
   603  				Expect(fakeDownloader.DownloadCallCount()).To(Equal(0))
   604  				Expect(outPath).To(Equal("/foo/buildpacks/a.zip"))
   605  			})
   606  		})
   607  	})
   608  
   609  	Describe("Zipit", func() {
   610  		//tested in buildpack_linux_test.go and buildpack_windows_test.go
   611  		var (
   612  			source string
   613  			target string
   614  
   615  			executeErr error
   616  		)
   617  
   618  		JustBeforeEach(func() {
   619  			executeErr = Zipit(source, target, "testzip-")
   620  		})
   621  
   622  		When("the source directory does not exist", func() {
   623  			BeforeEach(func() {
   624  				source = ""
   625  				target = ""
   626  			})
   627  
   628  			It("returns an error", func() {
   629  				Expect(os.IsNotExist(executeErr)).To(BeTrue())
   630  			})
   631  		})
   632  	})
   633  
   634  	Describe("DeleteBuildpackByNameAndStack", func() {
   635  		var (
   636  			buildpackName  = "buildpack-name"
   637  			buildpackStack = "buildpack-stack"
   638  			buildpackGUID  = "buildpack-guid"
   639  			jobURL         = "buildpack-delete-job-url"
   640  			warnings       Warnings
   641  			executeErr     error
   642  		)
   643  
   644  		JustBeforeEach(func() {
   645  			warnings, executeErr = actor.DeleteBuildpackByNameAndStack(buildpackName, buildpackStack)
   646  		})
   647  
   648  		When("getting the buildpack fails", func() {
   649  			BeforeEach(func() {
   650  				fakeCloudControllerClient.GetBuildpacksReturns(
   651  					[]ccv3.Buildpack{},
   652  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   653  					errors.New("api-get-error"))
   654  			})
   655  			It("returns warnings and error", func() {
   656  				Expect(executeErr).To(MatchError("api-get-error"))
   657  				Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2"))
   658  				Expect(fakeCloudControllerClient.GetBuildpacksCallCount()).To(Equal(1))
   659  				queries := fakeCloudControllerClient.GetBuildpacksArgsForCall(0)
   660  				Expect(queries).To(ConsistOf(
   661  					ccv3.Query{
   662  						Key:    ccv3.NameFilter,
   663  						Values: []string{buildpackName},
   664  					},
   665  					ccv3.Query{
   666  						Key:    ccv3.StackFilter,
   667  						Values: []string{buildpackStack},
   668  					},
   669  				))
   670  			})
   671  		})
   672  
   673  		When("getting the buildpack succeeds", func() {
   674  			BeforeEach(func() {
   675  				fakeCloudControllerClient.GetBuildpacksReturns(
   676  					[]ccv3.Buildpack{{GUID: buildpackGUID, Name: buildpackName, Stack: buildpackStack}},
   677  					ccv3.Warnings{"some-warning-1", "some-warning-2"},
   678  					nil)
   679  			})
   680  			When("deleting a buildpack fails", func() {
   681  				BeforeEach(func() {
   682  					fakeCloudControllerClient.DeleteBuildpackReturns(
   683  						"",
   684  						ccv3.Warnings{"some-warning-3", "some-warning-4"},
   685  						errors.New("api-delete-error"))
   686  				})
   687  
   688  				It("returns warnings and error", func() {
   689  					Expect(executeErr).To(MatchError("api-delete-error"))
   690  					Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4"))
   691  					Expect(fakeCloudControllerClient.DeleteBuildpackCallCount()).To(Equal(1))
   692  					paramGUID := fakeCloudControllerClient.DeleteBuildpackArgsForCall(0)
   693  					Expect(paramGUID).To(Equal(buildpackGUID))
   694  				})
   695  			})
   696  
   697  			When("deleting the buildpack is successful", func() {
   698  				BeforeEach(func() {
   699  					fakeCloudControllerClient.DeleteBuildpackReturns(
   700  						ccv3.JobURL(jobURL),
   701  						ccv3.Warnings{"some-warning-3", "some-warning-4"},
   702  						nil)
   703  				})
   704  
   705  				When("polling the job fails", func() {
   706  					BeforeEach(func() {
   707  						fakeCloudControllerClient.PollJobReturns(
   708  							ccv3.Warnings{"some-warning-5", "some-warning-6"},
   709  							errors.New("api-poll-job-error"))
   710  					})
   711  					It("returns warnings and an error", func() {
   712  						Expect(executeErr).To(MatchError("api-poll-job-error"))
   713  						Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4", "some-warning-5", "some-warning-6"))
   714  						Expect(fakeCloudControllerClient.PollJobCallCount()).To(Equal(1))
   715  						paramURL := fakeCloudControllerClient.PollJobArgsForCall(0)
   716  						Expect(paramURL).To(Equal(ccv3.JobURL(jobURL)))
   717  					})
   718  				})
   719  
   720  				When("polling the job succeeds", func() {
   721  					BeforeEach(func() {
   722  						fakeCloudControllerClient.PollJobReturns(
   723  							ccv3.Warnings{"some-warning-5", "some-warning-6"},
   724  							nil)
   725  					})
   726  					It("returns all warnings and no error", func() {
   727  						Expect(executeErr).ToNot(HaveOccurred())
   728  						Expect(warnings).To(ConsistOf("some-warning-1", "some-warning-2", "some-warning-3", "some-warning-4", "some-warning-5", "some-warning-6"))
   729  						Expect(fakeCloudControllerClient.PollJobCallCount()).To(Equal(1))
   730  						paramURL := fakeCloudControllerClient.PollJobArgsForCall(0)
   731  						Expect(paramURL).To(Equal(ccv3.JobURL(jobURL)))
   732  
   733  					})
   734  				})
   735  			})
   736  		})
   737  
   738  	})
   739  })