github.com/cloudfoundry/cli@v7.1.0+incompatible/actor/v7action/build_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 "time" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 . "code.cloudfoundry.org/cli/actor/v7action" 9 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 12 "code.cloudfoundry.org/cli/resources" 13 "code.cloudfoundry.org/clock" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Build Actions", func() { 19 var ( 20 actor *Actor 21 fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient 22 fakeConfig *v7actionfakes.FakeConfig 23 ) 24 25 BeforeEach(func() { 26 fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient) 27 fakeConfig = new(v7actionfakes.FakeConfig) 28 actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil, nil, clock.NewClock()) 29 }) 30 31 Describe("StagePackage", func() { 32 var ( 33 dropletStream <-chan resources.Droplet 34 warningsStream <-chan Warnings 35 errorStream <-chan error 36 37 appName string 38 appGUID string 39 buildGUID string 40 dropletGUID string 41 spaceGUID string 42 packageGUID string 43 ) 44 45 BeforeEach(func() { 46 appName = "some-app" 47 appGUID = "app-guid" 48 spaceGUID = "space-guid" 49 packageGUID = "some-package-guid" 50 }) 51 52 AfterEach(func() { 53 Eventually(errorStream).Should(BeClosed()) 54 Eventually(warningsStream).Should(BeClosed()) 55 Eventually(dropletStream).Should(BeClosed()) 56 }) 57 58 JustBeforeEach(func() { 59 dropletStream, warningsStream, errorStream = actor.StagePackage(packageGUID, appName, spaceGUID) 60 }) 61 62 When("finding the app fails", func() { 63 var expectedErr error 64 65 BeforeEach(func() { 66 expectedErr = errors.New("I am a tomato") 67 fakeCloudControllerClient.GetApplicationsReturns(nil, ccv3.Warnings{"get-apps-warning"}, expectedErr) 68 }) 69 70 It("returns the error and warnings", func() { 71 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 72 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 73 }) 74 }) 75 76 When("app is not found", func() { 77 BeforeEach(func() { 78 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{}, ccv3.Warnings{"get-apps-warning"}, nil) 79 }) 80 81 It("returns the error and warnings", func() { 82 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 83 Eventually(errorStream).Should(Receive(MatchError(actionerror.ApplicationNotFoundError{Name: appName}))) 84 }) 85 }) 86 87 When("finding the package fails", func() { 88 var expectedErr error 89 90 BeforeEach(func() { 91 expectedErr = errors.New("I am a passion fruit") 92 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{GUID: appGUID}}, ccv3.Warnings{"get-apps-warning"}, nil) 93 fakeCloudControllerClient.GetPackagesReturns([]ccv3.Package{}, ccv3.Warnings{"get-packages-warning"}, expectedErr) 94 }) 95 96 It("returns the error and warnings", func() { 97 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 98 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 99 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 100 }) 101 }) 102 103 When("the package does not belong to the app", func() { 104 BeforeEach(func() { 105 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{GUID: appGUID}}, ccv3.Warnings{"get-apps-warning"}, nil) 106 fakeCloudControllerClient.GetPackagesReturns( 107 []ccv3.Package{{GUID: "some-other-package-guid"}}, 108 ccv3.Warnings{"get-packages-warning"}, 109 nil, 110 ) 111 }) 112 113 It("returns a not found error and warnings", func() { 114 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 115 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 116 Eventually(errorStream).Should(Receive(MatchError(actionerror.PackageNotFoundInAppError{GUID: packageGUID, AppName: appName}))) 117 }) 118 }) 119 120 When("the creation is successful", func() { 121 BeforeEach(func() { 122 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{GUID: appGUID}}, ccv3.Warnings{"get-apps-warning"}, nil) 123 fakeCloudControllerClient.GetPackagesReturns( 124 []ccv3.Package{{GUID: packageGUID}}, 125 ccv3.Warnings{"get-packages-warning"}, 126 nil, 127 ) 128 129 buildGUID = "some-build-guid" 130 dropletGUID = "some-droplet-guid" 131 fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, nil) 132 fakeConfig.StagingTimeoutReturns(time.Minute) 133 }) 134 135 When("the polling is successful", func() { 136 BeforeEach(func() { 137 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil) 138 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) 139 }) 140 141 //TODO: uncommend after #150569020 142 // FWhen("looking up the droplet fails", func() { 143 // BeforeEach(func() { 144 // fakeCloudControllerClient.GetDropletReturns(resources.Droplet{}, ccv3.Warnings{"droplet-warnings-1", "droplet-warnings-2"}, errors.New("some-droplet-error")) 145 // }) 146 147 // It("returns the warnings and the droplet error", func() { 148 // Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 149 // Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 150 // Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 151 // Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 152 // Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 153 // Eventually(warningsStream).Should(Receive(ConsistOf("droplet-warnings-1", "droplet-warnings-2"))) 154 155 // Eventually(errorStream).Should(Receive(MatchError("some-droplet-error"))) 156 // }) 157 // }) 158 159 // When("looking up the droplet succeeds", func() { 160 // BeforeEach(func() { 161 // fakeCloudControllerClient.GetDropletReturns(resources.Droplet{GUID: dropletGUID, State: ccv3.DropletStateStaged}, ccv3.Warnings{"droplet-warnings-1", "droplet-warnings-2"}, nil) 162 // }) 163 164 It("polls until build is finished and returns the final droplet", func() { 165 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 166 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 167 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 168 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 169 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 170 // Eventually(warningsStream).Should(Receive(ConsistOf("droplet-warnings-1", "droplet-warnings-2"))) 171 172 Eventually(dropletStream).Should(Receive(Equal(resources.Droplet{GUID: dropletGUID, State: constant.DropletStaged, CreatedAt: "some-time"}))) 173 Consistently(errorStream).ShouldNot(Receive()) 174 175 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 176 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(Equal([]ccv3.Query{ 177 {Key: ccv3.NameFilter, Values: []string{appName}}, 178 {Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, 179 })) 180 181 Expect(fakeCloudControllerClient.GetPackagesCallCount()).To(Equal(1)) 182 Expect(fakeCloudControllerClient.GetPackagesArgsForCall(0)).To(Equal([]ccv3.Query{ 183 {Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, 184 })) 185 186 Expect(fakeCloudControllerClient.CreateBuildCallCount()).To(Equal(1)) 187 Expect(fakeCloudControllerClient.CreateBuildArgsForCall(0)).To(Equal(ccv3.Build{ 188 PackageGUID: "some-package-guid", 189 })) 190 191 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 192 Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID)) 193 Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID)) 194 195 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 196 }) 197 // }) 198 199 When("polling returns a failed build", func() { 200 BeforeEach(func() { 201 fakeCloudControllerClient.GetBuildReturnsOnCall( 202 1, 203 ccv3.Build{ 204 GUID: buildGUID, 205 State: constant.BuildFailed, 206 Error: "some staging error", 207 }, 208 ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, nil) 209 }) 210 211 It("returns an error and all warnings", func() { 212 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 213 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 214 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 215 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 216 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 217 stagingErr := errors.New("some staging error") 218 Eventually(errorStream).Should(Receive(&stagingErr)) 219 Eventually(dropletStream).ShouldNot(Receive()) 220 221 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 222 Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID)) 223 Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID)) 224 225 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 226 }) 227 }) 228 }) 229 230 When("polling times out", func() { 231 var expectedErr error 232 233 BeforeEach(func() { 234 expectedErr = actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 0} 235 fakeConfig.StagingTimeoutReturns(0) 236 }) 237 238 It("returns the error and warnings", func() { 239 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 240 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 241 }) 242 }) 243 244 When("the polling errors", func() { 245 var expectedErr error 246 247 BeforeEach(func() { 248 expectedErr = errors.New("I am a banana") 249 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil) 250 fakeCloudControllerClient.GetBuildReturnsOnCall(1, ccv3.Build{}, ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, expectedErr) 251 }) 252 253 It("returns the error and warnings", func() { 254 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 255 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 256 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 257 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 258 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 259 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 260 }) 261 }) 262 }) 263 264 When("creation errors", func() { 265 var expectedErr error 266 267 BeforeEach(func() { 268 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{GUID: appGUID}}, ccv3.Warnings{"get-apps-warning"}, nil) 269 fakeCloudControllerClient.GetPackagesReturns( 270 []ccv3.Package{{GUID: packageGUID}}, 271 ccv3.Warnings{"get-packages-warning"}, 272 nil, 273 ) 274 275 expectedErr = errors.New("I am a banana") 276 fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, expectedErr) 277 }) 278 279 It("returns the error and warnings", func() { 280 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 281 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 282 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 283 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 284 }) 285 }) 286 }) 287 288 Describe("StageApplicationPackage", func() { 289 var ( 290 build Build 291 warnings Warnings 292 executeErr error 293 ) 294 295 JustBeforeEach(func() { 296 build, warnings, executeErr = actor.StageApplicationPackage("some-package-guid") 297 }) 298 299 When("the creation is successful", func() { 300 BeforeEach(func() { 301 fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{GUID: "some-build-guid"}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, nil) 302 }) 303 304 It("returns the build and warnings", func() { 305 Expect(executeErr).ToNot(HaveOccurred()) 306 Expect(build).To(Equal(Build{GUID: "some-build-guid"})) 307 Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2")) 308 }) 309 }) 310 311 When("the creation fails", func() { 312 BeforeEach(func() { 313 fakeCloudControllerClient.CreateBuildReturns(ccv3.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, errors.New("blurp")) 314 }) 315 316 It("returns the error and warnings", func() { 317 Expect(executeErr).To(MatchError("blurp")) 318 Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2")) 319 }) 320 }) 321 }) 322 323 Describe("PollBuild", func() { 324 var ( 325 droplet resources.Droplet 326 warnings Warnings 327 executeErr error 328 ) 329 330 JustBeforeEach(func() { 331 droplet, warnings, executeErr = actor.PollBuild("some-build-guid", "some-app") 332 }) 333 334 When("getting the build yields a 'Staged' build", func() { 335 BeforeEach(func() { 336 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{State: constant.BuildStaging}, ccv3.Warnings{"some-get-build-warnings"}, nil) 337 fakeCloudControllerClient.GetBuildReturnsOnCall(1, ccv3.Build{GUID: "some-build-guid", DropletGUID: "some-droplet-guid", State: constant.BuildStaged}, ccv3.Warnings{"some-get-build-warnings"}, nil) 338 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 339 }) 340 341 It("gets the droplet", func() { 342 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 343 344 Expect(fakeCloudControllerClient.GetDropletCallCount()).To(Equal(1)) 345 Expect(fakeCloudControllerClient.GetDropletArgsForCall(0)).To(Equal("some-droplet-guid")) 346 }) 347 348 When("getting the droplet is successful", func() { 349 BeforeEach(func() { 350 fakeCloudControllerClient.GetDropletReturns(resources.Droplet{GUID: "some-droplet-guid", CreatedAt: "some-droplet-time", State: constant.DropletStaged}, ccv3.Warnings{"some-get-droplet-warnings"}, nil) 351 }) 352 353 It("returns the droplet and warnings", func() { 354 Expect(executeErr).ToNot(HaveOccurred()) 355 356 Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings")) 357 Expect(droplet).To(Equal(resources.Droplet{ 358 GUID: "some-droplet-guid", 359 CreatedAt: "some-droplet-time", 360 State: constant.DropletStaged, 361 })) 362 }) 363 }) 364 365 When("getting the droplet fails", func() { 366 BeforeEach(func() { 367 fakeCloudControllerClient.GetDropletReturns(resources.Droplet{}, ccv3.Warnings{"some-get-droplet-warnings"}, errors.New("no rain")) 368 }) 369 370 It("returns the error and warnings", func() { 371 Expect(executeErr).To(MatchError("no rain")) 372 Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings")) 373 }) 374 }) 375 }) 376 377 When("getting the build yields a 'Failed' build", func() { 378 BeforeEach(func() { 379 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{State: constant.BuildFailed, Error: "ded build"}, ccv3.Warnings{"some-get-build-warnings"}, nil) 380 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 381 }) 382 383 It("returns the error and warnings", func() { 384 Expect(executeErr).To(MatchError("ded build")) 385 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 386 }) 387 }) 388 389 When("getting the build fails", func() { 390 BeforeEach(func() { 391 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{}, ccv3.Warnings{"some-get-build-warnings"}, errors.New("some-poll-build-error")) 392 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 393 }) 394 395 It("returns the error and warnings", func() { 396 Expect(executeErr).To(MatchError("some-poll-build-error")) 397 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 398 }) 399 }) 400 401 When("polling the build times out", func() { 402 BeforeEach(func() { 403 fakeCloudControllerClient.GetBuildReturnsOnCall(0, ccv3.Build{}, ccv3.Warnings{"some-get-build-warnings"}, nil) 404 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 405 }) 406 407 It("returns the error and warnings", func() { 408 Expect(executeErr).To(MatchError(actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 500 * time.Millisecond})) 409 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 410 }) 411 }) 412 }) 413 })