github.com/cloudfoundry/cli@v7.1.0+incompatible/actor/v3action/build_test.go (about)

     1  package v3action_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	. "code.cloudfoundry.org/cli/actor/v3action"
     9  	"code.cloudfoundry.org/cli/actor/v3action/v3actionfakes"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    12  	"code.cloudfoundry.org/cli/resources"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Build Actions", func() {
    18  	var (
    19  		actor                     *Actor
    20  		fakeCloudControllerClient *v3actionfakes.FakeCloudControllerClient
    21  		fakeConfig                *v3actionfakes.FakeConfig
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		fakeCloudControllerClient = new(v3actionfakes.FakeCloudControllerClient)
    26  		fakeConfig = new(v3actionfakes.FakeConfig)
    27  		actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil)
    28  	})
    29  
    30  	Describe("StagePackage", func() {
    31  		var (
    32  			dropletStream  <-chan Droplet
    33  			warningsStream <-chan Warnings
    34  			errorStream    <-chan error
    35  
    36  			buildGUID   string
    37  			dropletGUID string
    38  		)
    39  
    40  		AfterEach(func() {
    41  			Eventually(errorStream).Should(BeClosed())
    42  			Eventually(warningsStream).Should(BeClosed())
    43  			Eventually(dropletStream).Should(BeClosed())
    44  		})
    45  
    46  		JustBeforeEach(func() {
    47  			dropletStream, warningsStream, errorStream = actor.StagePackage("some-package-guid", "some-app")
    48  		})
    49  
    50  		When("the creation is successful", func() {
    51  			BeforeEach(func() {
    52  				buildGUID = "some-build-guid"
    53  				dropletGUID = "some-droplet-guid"
    54  				fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, nil)
    55  				fakeConfig.StagingTimeoutReturns(time.Minute)
    56  			})
    57  
    58  			When("the polling is successful", func() {
    59  				BeforeEach(func() {
    60  					fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil)
    61  					fakeCloudControllerClient.GetBuildReturnsOnCall(1, ccv3.Build{CreatedAt: "some-time", GUID: buildGUID, State: constant.BuildStaged, DropletGUID: "some-droplet-guid"}, ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, nil)
    62  				})
    63  
    64  				//TODO: uncommend after #150569020
    65  				// FWhen("looking up the droplet fails", func() {
    66  				// 	BeforeEach(func() {
    67  				// 		fakeCloudControllerClient.GetDropletReturns(resources.Droplet{}, ccv3.Warnings{"droplet-warnings-1", "droplet-warnings-2"}, errors.New("some-droplet-error"))
    68  				// 	})
    69  
    70  				// 	It("returns the warnings and the droplet error", func() {
    71  				// 		Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
    72  				// 		Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2")))
    73  				// 		Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4")))
    74  				// 		Eventually(warningsStream).Should(Receive(ConsistOf("droplet-warnings-1", "droplet-warnings-2")))
    75  
    76  				// 		Eventually(errorStream).Should(Receive(MatchError("some-droplet-error")))
    77  				// 	})
    78  				// })
    79  
    80  				// When("looking up the droplet succeeds", func() {
    81  				// 	BeforeEach(func() {
    82  				// 		fakeCloudControllerClient.GetDropletReturns(resources.Droplet{GUID: dropletGUID, State: ccv3.DropletStateStaged}, ccv3.Warnings{"droplet-warnings-1", "droplet-warnings-2"}, nil)
    83  				// 	})
    84  
    85  				It("polls until build is finished and returns the final droplet", func() {
    86  					Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
    87  					Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2")))
    88  					Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4")))
    89  					// Eventually(warningsStream).Should(Receive(ConsistOf("droplet-warnings-1", "droplet-warnings-2")))
    90  
    91  					Eventually(dropletStream).Should(Receive(Equal(Droplet{GUID: dropletGUID, State: constant.DropletStaged, CreatedAt: "some-time"})))
    92  					Consistently(errorStream).ShouldNot(Receive())
    93  
    94  					Expect(fakeCloudControllerClient.CreateBuildCallCount()).To(Equal(1))
    95  					Expect(fakeCloudControllerClient.CreateBuildArgsForCall(0)).To(Equal(ccv3.Build{
    96  						PackageGUID: "some-package-guid",
    97  					}))
    98  
    99  					Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2))
   100  					Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID))
   101  					Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID))
   102  
   103  					Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1))
   104  				})
   105  				// })
   106  
   107  				When("polling returns a failed build", func() {
   108  					BeforeEach(func() {
   109  						fakeCloudControllerClient.GetBuildReturnsOnCall(
   110  							1,
   111  							ccv3.Build{
   112  								GUID:  buildGUID,
   113  								State: constant.BuildFailed,
   114  								Error: "some staging error",
   115  							},
   116  							ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, nil)
   117  					})
   118  
   119  					It("returns an error and all warnings", func() {
   120  						Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
   121  						Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2")))
   122  						Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4")))
   123  						stagingErr := errors.New("some staging error")
   124  						Eventually(errorStream).Should(Receive(&stagingErr))
   125  						Eventually(dropletStream).ShouldNot(Receive())
   126  
   127  						Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2))
   128  						Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID))
   129  						Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID))
   130  
   131  						Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1))
   132  					})
   133  				})
   134  			})
   135  
   136  			When("polling times out", func() {
   137  				var expectedErr error
   138  
   139  				BeforeEach(func() {
   140  					expectedErr = actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 0}
   141  					fakeConfig.StagingTimeoutReturns(0)
   142  				})
   143  
   144  				It("returns the error and warnings", func() {
   145  					Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
   146  					Eventually(errorStream).Should(Receive(MatchError(expectedErr)))
   147  				})
   148  			})
   149  
   150  			When("the polling errors", func() {
   151  				var expectedErr error
   152  
   153  				BeforeEach(func() {
   154  					expectedErr = errors.New("I am a banana")
   155  					fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil)
   156  					fakeCloudControllerClient.GetBuildReturnsOnCall(1, ccv3.Build{}, ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, expectedErr)
   157  				})
   158  
   159  				It("returns the error and warnings", func() {
   160  					Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
   161  					Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2")))
   162  					Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4")))
   163  					Eventually(errorStream).Should(Receive(MatchError(expectedErr)))
   164  				})
   165  			})
   166  		})
   167  
   168  		When("creation errors", func() {
   169  			var expectedErr error
   170  			BeforeEach(func() {
   171  				expectedErr = errors.New("I am a banana")
   172  				fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, expectedErr)
   173  			})
   174  
   175  			It("returns the error and warnings", func() {
   176  				Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2")))
   177  				Eventually(errorStream).Should(Receive(MatchError(expectedErr)))
   178  			})
   179  		})
   180  	})
   181  
   182  	Describe("StageApplicationPackage", func() {
   183  		var (
   184  			build      Build
   185  			warnings   Warnings
   186  			executeErr error
   187  		)
   188  
   189  		JustBeforeEach(func() {
   190  			build, warnings, executeErr = actor.StageApplicationPackage("some-package-guid")
   191  		})
   192  
   193  		When("the creation is successful", func() {
   194  			BeforeEach(func() {
   195  				fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{GUID: "some-build-guid"}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, nil)
   196  			})
   197  
   198  			It("returns the build and warnings", func() {
   199  				Expect(executeErr).ToNot(HaveOccurred())
   200  				Expect(build).To(Equal(Build{GUID: "some-build-guid"}))
   201  				Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2"))
   202  			})
   203  		})
   204  
   205  		When("the creation fails", func() {
   206  			BeforeEach(func() {
   207  				fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, errors.New("blurp"))
   208  			})
   209  
   210  			It("returns the error and warnings", func() {
   211  				Expect(executeErr).To(MatchError("blurp"))
   212  				Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2"))
   213  			})
   214  		})
   215  	})
   216  
   217  	Describe("PollBuild", func() {
   218  		var (
   219  			droplet    Droplet
   220  			warnings   Warnings
   221  			executeErr error
   222  		)
   223  
   224  		JustBeforeEach(func() {
   225  			droplet, warnings, executeErr = actor.PollBuild("some-build-guid", "some-app")
   226  		})
   227  
   228  		When("getting the build yields a 'Staged' build", func() {
   229  			BeforeEach(func() {
   230  				fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{State: constant.BuildStaging}, ccv3.Warnings{"some-get-build-warnings"}, nil)
   231  				fakeCloudControllerClient.GetBuildReturnsOnCall(1, ccv3.Build{GUID: "some-build-guid", DropletGUID: "some-droplet-guid", State: constant.BuildStaged}, ccv3.Warnings{"some-get-build-warnings"}, nil)
   232  				fakeConfig.StagingTimeoutReturns(500 * time.Millisecond)
   233  			})
   234  
   235  			It("gets the droplet", func() {
   236  				Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2))
   237  
   238  				Expect(fakeCloudControllerClient.GetDropletCallCount()).To(Equal(1))
   239  				Expect(fakeCloudControllerClient.GetDropletArgsForCall(0)).To(Equal("some-droplet-guid"))
   240  			})
   241  
   242  			When("getting the droplet is successful", func() {
   243  				BeforeEach(func() {
   244  					fakeCloudControllerClient.GetDropletReturns(resources.Droplet{GUID: "some-droplet-guid", CreatedAt: "some-droplet-time", State: constant.DropletStaged}, ccv3.Warnings{"some-get-droplet-warnings"}, nil)
   245  				})
   246  
   247  				It("returns the droplet and warnings", func() {
   248  					Expect(executeErr).ToNot(HaveOccurred())
   249  
   250  					Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings"))
   251  					Expect(droplet).To(Equal(Droplet{
   252  						GUID:      "some-droplet-guid",
   253  						CreatedAt: "some-droplet-time",
   254  						State:     constant.DropletStaged,
   255  					}))
   256  				})
   257  			})
   258  
   259  			When("getting the droplet fails", func() {
   260  				BeforeEach(func() {
   261  					fakeCloudControllerClient.GetDropletReturns(resources.Droplet{}, ccv3.Warnings{"some-get-droplet-warnings"}, errors.New("no rain"))
   262  				})
   263  
   264  				It("returns the error and warnings", func() {
   265  					Expect(executeErr).To(MatchError("no rain"))
   266  					Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings"))
   267  				})
   268  			})
   269  		})
   270  
   271  		When("getting the build yields a 'Failed' build", func() {
   272  			BeforeEach(func() {
   273  				fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{State: constant.BuildFailed, Error: "ded build"}, ccv3.Warnings{"some-get-build-warnings"}, nil)
   274  				fakeConfig.StagingTimeoutReturns(500 * time.Millisecond)
   275  			})
   276  
   277  			It("returns the error and warnings", func() {
   278  				Expect(executeErr).To(MatchError("ded build"))
   279  				Expect(warnings).To(ConsistOf("some-get-build-warnings"))
   280  			})
   281  		})
   282  
   283  		When("getting the build fails", func() {
   284  			BeforeEach(func() {
   285  				fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{}, ccv3.Warnings{"some-get-build-warnings"}, errors.New("some-poll-build-error"))
   286  				fakeConfig.StagingTimeoutReturns(500 * time.Millisecond)
   287  			})
   288  
   289  			It("returns the error and warnings", func() {
   290  				Expect(executeErr).To(MatchError("some-poll-build-error"))
   291  				Expect(warnings).To(ConsistOf("some-get-build-warnings"))
   292  			})
   293  		})
   294  
   295  		When("polling the build times out", func() {
   296  			BeforeEach(func() {
   297  				fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{}, ccv3.Warnings{"some-get-build-warnings"}, nil)
   298  				fakeConfig.StagingTimeoutReturns(500 * time.Millisecond)
   299  			})
   300  
   301  			It("returns the error and warnings", func() {
   302  				Expect(executeErr).To(MatchError(actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 500 * time.Millisecond}))
   303  				Expect(warnings).To(ConsistOf("some-get-build-warnings"))
   304  			})
   305  		})
   306  	})
   307  })