github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/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([]resources.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 []resources.Package{}, 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 []resources.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(resources.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, resources.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil) 138 fakeCloudControllerClient.GetBuildReturnsOnCall(1, resources.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.GUIDFilter, Values: []string{packageGUID}}, 184 {Key: ccv3.AppGUIDFilter, Values: []string{appGUID}}, 185 {Key: ccv3.PerPage, Values: []string{"1"}}, 186 {Key: ccv3.Page, Values: []string{"1"}}, 187 })) 188 189 Expect(fakeCloudControllerClient.CreateBuildCallCount()).To(Equal(1)) 190 Expect(fakeCloudControllerClient.CreateBuildArgsForCall(0)).To(Equal(resources.Build{ 191 PackageGUID: "some-package-guid", 192 })) 193 194 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 195 Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID)) 196 Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID)) 197 198 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 199 }) 200 // }) 201 202 When("polling returns a failed build", func() { 203 BeforeEach(func() { 204 fakeCloudControllerClient.GetBuildReturnsOnCall( 205 1, 206 resources.Build{ 207 GUID: buildGUID, 208 State: constant.BuildFailed, 209 Error: "some staging error", 210 }, 211 ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, nil) 212 }) 213 214 It("returns an error and all warnings", func() { 215 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 216 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 217 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 218 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 219 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 220 stagingErr := errors.New("some staging error") 221 Eventually(errorStream).Should(Receive(&stagingErr)) 222 Eventually(dropletStream).ShouldNot(Receive()) 223 224 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 225 Expect(fakeCloudControllerClient.GetBuildArgsForCall(0)).To(Equal(buildGUID)) 226 Expect(fakeCloudControllerClient.GetBuildArgsForCall(1)).To(Equal(buildGUID)) 227 228 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 229 }) 230 }) 231 }) 232 233 When("polling times out", func() { 234 var expectedErr error 235 236 BeforeEach(func() { 237 expectedErr = actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 0} 238 fakeConfig.StagingTimeoutReturns(0) 239 }) 240 241 It("returns the error and warnings", func() { 242 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 243 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 244 }) 245 }) 246 247 When("the polling errors", func() { 248 var expectedErr error 249 250 BeforeEach(func() { 251 expectedErr = errors.New("I am a banana") 252 fakeCloudControllerClient.GetBuildReturnsOnCall(0, resources.Build{GUID: buildGUID, State: constant.BuildStaging}, ccv3.Warnings{"get-warnings-1", "get-warnings-2"}, nil) 253 fakeCloudControllerClient.GetBuildReturnsOnCall(1, resources.Build{}, ccv3.Warnings{"get-warnings-3", "get-warnings-4"}, expectedErr) 254 }) 255 256 It("returns the error and warnings", func() { 257 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 258 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 259 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 260 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-1", "get-warnings-2"))) 261 Eventually(warningsStream).Should(Receive(ConsistOf("get-warnings-3", "get-warnings-4"))) 262 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 263 }) 264 }) 265 }) 266 267 When("creation errors", func() { 268 var expectedErr error 269 270 BeforeEach(func() { 271 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{GUID: appGUID}}, ccv3.Warnings{"get-apps-warning"}, nil) 272 fakeCloudControllerClient.GetPackagesReturns( 273 []resources.Package{{GUID: packageGUID}}, 274 ccv3.Warnings{"get-packages-warning"}, 275 nil, 276 ) 277 278 expectedErr = errors.New("I am a banana") 279 fakeCloudControllerClient.CreateBuildReturns(resources.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, expectedErr) 280 }) 281 282 It("returns the error and warnings", func() { 283 Eventually(warningsStream).Should(Receive(ConsistOf("get-apps-warning"))) 284 Eventually(warningsStream).Should(Receive(ConsistOf("get-packages-warning"))) 285 Eventually(warningsStream).Should(Receive(ConsistOf("create-warnings-1", "create-warnings-2"))) 286 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 287 }) 288 }) 289 }) 290 291 Describe("StageApplicationPackage", func() { 292 var ( 293 build resources.Build 294 warnings Warnings 295 executeErr error 296 ) 297 298 JustBeforeEach(func() { 299 build, warnings, executeErr = actor.StageApplicationPackage("some-package-guid") 300 }) 301 302 When("the creation is successful", func() { 303 BeforeEach(func() { 304 fakeCloudControllerClient.CreateBuildReturns(resources.Build{GUID: "some-build-guid"}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, nil) 305 }) 306 307 It("returns the build and warnings", func() { 308 Expect(executeErr).ToNot(HaveOccurred()) 309 Expect(build).To(Equal(resources.Build{GUID: "some-build-guid"})) 310 Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2")) 311 }) 312 }) 313 314 When("the creation fails", func() { 315 BeforeEach(func() { 316 fakeCloudControllerClient.CreateBuildReturns(resources.Build{}, ccv3.Warnings{"create-warnings-1", "create-warnings-2"}, errors.New("blurp")) 317 }) 318 319 It("returns the error and warnings", func() { 320 Expect(executeErr).To(MatchError("blurp")) 321 Expect(warnings).To(ConsistOf("create-warnings-1", "create-warnings-2")) 322 }) 323 }) 324 }) 325 326 Describe("PollBuild", func() { 327 var ( 328 droplet resources.Droplet 329 warnings Warnings 330 executeErr error 331 ) 332 333 JustBeforeEach(func() { 334 droplet, warnings, executeErr = actor.PollBuild("some-build-guid", "some-app") 335 }) 336 337 When("getting the build yields a 'Staged' build", func() { 338 BeforeEach(func() { 339 fakeCloudControllerClient.GetBuildReturnsOnCall(0, resources.Build{State: constant.BuildStaging}, ccv3.Warnings{"some-get-build-warnings"}, nil) 340 fakeCloudControllerClient.GetBuildReturnsOnCall(1, resources.Build{GUID: "some-build-guid", DropletGUID: "some-droplet-guid", State: constant.BuildStaged}, ccv3.Warnings{"some-get-build-warnings"}, nil) 341 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 342 }) 343 344 It("gets the droplet", func() { 345 Expect(fakeCloudControllerClient.GetBuildCallCount()).To(Equal(2)) 346 347 Expect(fakeCloudControllerClient.GetDropletCallCount()).To(Equal(1)) 348 Expect(fakeCloudControllerClient.GetDropletArgsForCall(0)).To(Equal("some-droplet-guid")) 349 }) 350 351 When("getting the droplet is successful", func() { 352 BeforeEach(func() { 353 fakeCloudControllerClient.GetDropletReturns(resources.Droplet{GUID: "some-droplet-guid", CreatedAt: "some-droplet-time", State: constant.DropletStaged}, ccv3.Warnings{"some-get-droplet-warnings"}, nil) 354 }) 355 356 It("returns the droplet and warnings", func() { 357 Expect(executeErr).ToNot(HaveOccurred()) 358 359 Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings")) 360 Expect(droplet).To(Equal(resources.Droplet{ 361 GUID: "some-droplet-guid", 362 CreatedAt: "some-droplet-time", 363 State: constant.DropletStaged, 364 })) 365 }) 366 }) 367 368 When("getting the droplet fails", func() { 369 BeforeEach(func() { 370 fakeCloudControllerClient.GetDropletReturns(resources.Droplet{}, ccv3.Warnings{"some-get-droplet-warnings"}, errors.New("no rain")) 371 }) 372 373 It("returns the error and warnings", func() { 374 Expect(executeErr).To(MatchError("no rain")) 375 Expect(warnings).To(ConsistOf("some-get-build-warnings", "some-get-build-warnings", "some-get-droplet-warnings")) 376 }) 377 }) 378 }) 379 380 When("getting the build yields a 'Failed' build", func() { 381 BeforeEach(func() { 382 fakeCloudControllerClient.GetBuildReturnsOnCall(0, resources.Build{State: constant.BuildFailed, Error: "ded build"}, ccv3.Warnings{"some-get-build-warnings"}, nil) 383 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 384 }) 385 386 It("returns the error and warnings", func() { 387 Expect(executeErr).To(MatchError("ded build")) 388 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 389 }) 390 }) 391 392 When("getting the build fails", func() { 393 BeforeEach(func() { 394 fakeCloudControllerClient.GetBuildReturnsOnCall(0, resources.Build{}, ccv3.Warnings{"some-get-build-warnings"}, errors.New("some-poll-build-error")) 395 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 396 }) 397 398 It("returns the error and warnings", func() { 399 Expect(executeErr).To(MatchError("some-poll-build-error")) 400 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 401 }) 402 }) 403 404 When("polling the build times out", func() { 405 BeforeEach(func() { 406 fakeCloudControllerClient.GetBuildReturnsOnCall(0, resources.Build{}, ccv3.Warnings{"some-get-build-warnings"}, nil) 407 fakeConfig.StagingTimeoutReturns(500 * time.Millisecond) 408 }) 409 410 It("returns the error and warnings", func() { 411 Expect(executeErr).To(MatchError(actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 500 * time.Millisecond})) 412 Expect(warnings).To(ConsistOf("some-get-build-warnings")) 413 }) 414 }) 415 }) 416 })