github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/actor/v7action/task_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 7 . "code.cloudfoundry.org/cli/actor/v7action" 8 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 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("Task Actions", func() { 18 var ( 19 actor *Actor 20 fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient 21 fakeConfig *v7actionfakes.FakeConfig 22 ) 23 24 BeforeEach(func() { 25 fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient) 26 fakeConfig = new(v7actionfakes.FakeConfig) 27 actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil, nil, nil) 28 }) 29 30 Describe("RunTask", func() { 31 When("the application exists", func() { 32 BeforeEach(func() { 33 fakeCloudControllerClient.CreateApplicationTaskReturns( 34 resources.Task{ 35 SequenceID: 3, 36 }, 37 ccv3.Warnings{ 38 "warning-1", 39 "warning-2", 40 }, 41 nil, 42 ) 43 }) 44 45 It("creates and returns the task and all warnings", func() { 46 expectedTask := resources.Task{ 47 Command: "some command", 48 Name: "some-task-name", 49 MemoryInMB: 123, 50 DiskInMB: 321, 51 } 52 task, warnings, err := actor.RunTask("some-app-guid", expectedTask) 53 Expect(err).ToNot(HaveOccurred()) 54 55 Expect(task).To(Equal(resources.Task{ 56 SequenceID: 3, 57 })) 58 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 59 60 Expect(fakeCloudControllerClient.CreateApplicationTaskCallCount()).To(Equal(1)) 61 appGUIDArg, taskArg := fakeCloudControllerClient.CreateApplicationTaskArgsForCall(0) 62 Expect(appGUIDArg).To(Equal("some-app-guid")) 63 Expect(taskArg).To(Equal(resources.Task(expectedTask))) 64 }) 65 }) 66 67 When("the cloud controller client returns an error", func() { 68 var warnings Warnings 69 var err error 70 var expectedErr error 71 72 JustBeforeEach(func() { 73 _, warnings, err = actor.RunTask("some-app-guid", resources.Task{Command: "some command"}) 74 }) 75 76 When("the cloud controller error is generic", func() { 77 BeforeEach(func() { 78 expectedErr = errors.New("I am a CloudControllerClient Error") 79 fakeCloudControllerClient.CreateApplicationTaskReturns( 80 resources.Task{}, 81 ccv3.Warnings{"warning-1", "warning-2"}, 82 expectedErr, 83 ) 84 }) 85 86 It("returns the same error and all warnings", func() { 87 Expect(err).To(MatchError(expectedErr)) 88 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 89 }) 90 }) 91 92 When("the error is a TaskWorkersUnavailableError", func() { 93 BeforeEach(func() { 94 fakeCloudControllerClient.CreateApplicationTaskReturns( 95 resources.Task{}, 96 ccv3.Warnings{"warning-1", "warning-2"}, 97 ccerror.TaskWorkersUnavailableError{Message: "banana babans"}, 98 ) 99 }) 100 101 It("returns a TaskWorkersUnavailableError and all warnings", func() { 102 Expect(err).To(MatchError(actionerror.TaskWorkersUnavailableError{Message: "banana babans"})) 103 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 104 }) 105 }) 106 }) 107 }) 108 109 Describe("GetApplicationTasks", func() { 110 When("the application exists", func() { 111 When("there are associated tasks", func() { 112 var ( 113 task1 resources.Task 114 task2 resources.Task 115 task3 resources.Task 116 ) 117 118 BeforeEach(func() { 119 task1 = resources.Task{ 120 GUID: "task-1-guid", 121 SequenceID: 1, 122 Name: "task-1", 123 State: constant.TaskSucceeded, 124 CreatedAt: "some-time", 125 Command: "some-command", 126 } 127 task2 = resources.Task{ 128 GUID: "task-2-guid", 129 SequenceID: 2, 130 Name: "task-2", 131 State: constant.TaskFailed, 132 CreatedAt: "some-time", 133 Command: "some-command", 134 } 135 task3 = resources.Task{ 136 GUID: "task-3-guid", 137 SequenceID: 3, 138 Name: "task-3", 139 State: constant.TaskRunning, 140 CreatedAt: "some-time", 141 Command: "some-command", 142 } 143 fakeCloudControllerClient.GetApplicationTasksReturns( 144 []resources.Task{task3, task1, task2}, 145 ccv3.Warnings{"warning-1", "warning-2"}, 146 nil, 147 ) 148 }) 149 150 It("returns all tasks associated with the application and all warnings", func() { 151 tasks, warnings, err := actor.GetApplicationTasks("some-app-guid", Descending) 152 Expect(err).ToNot(HaveOccurred()) 153 154 Expect(tasks).To(Equal([]resources.Task{resources.Task(task3), resources.Task(task2), resources.Task(task1)})) 155 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 156 157 tasks, warnings, err = actor.GetApplicationTasks("some-app-guid", Ascending) 158 Expect(err).ToNot(HaveOccurred()) 159 160 Expect(tasks).To(Equal([]resources.Task{resources.Task(task1), resources.Task(task2), resources.Task(task3)})) 161 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 162 163 Expect(fakeCloudControllerClient.GetApplicationTasksCallCount()).To(Equal(2)) 164 appGUID, query := fakeCloudControllerClient.GetApplicationTasksArgsForCall(0) 165 Expect(appGUID).To(Equal("some-app-guid")) 166 Expect(query).To(BeNil()) 167 }) 168 }) 169 170 When("there are no associated tasks", func() { 171 BeforeEach(func() { 172 fakeCloudControllerClient.GetApplicationTasksReturns( 173 []resources.Task{}, 174 nil, 175 nil, 176 ) 177 }) 178 179 It("returns an empty list of tasks", func() { 180 tasks, _, err := actor.GetApplicationTasks("some-app-guid", Descending) 181 Expect(err).ToNot(HaveOccurred()) 182 Expect(tasks).To(BeEmpty()) 183 }) 184 }) 185 }) 186 187 When("the cloud controller client returns an error", func() { 188 var expectedErr error 189 190 BeforeEach(func() { 191 expectedErr = errors.New("I am a CloudControllerClient Error") 192 fakeCloudControllerClient.GetApplicationTasksReturns( 193 []resources.Task{}, 194 ccv3.Warnings{"warning-1", "warning-2"}, 195 expectedErr, 196 ) 197 }) 198 199 It("returns the same error and all warnings", func() { 200 _, warnings, err := actor.GetApplicationTasks("some-app-guid", Descending) 201 Expect(err).To(MatchError(expectedErr)) 202 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 203 }) 204 }) 205 }) 206 207 Describe("GetTaskBySequenceIDAndApplication", func() { 208 When("the cloud controller client does not return an error", func() { 209 When("the task is found", func() { 210 var task1 resources.Task 211 212 BeforeEach(func() { 213 task1 = resources.Task{ 214 GUID: "task-1-guid", 215 SequenceID: 1, 216 } 217 fakeCloudControllerClient.GetApplicationTasksReturns( 218 []resources.Task{task1}, 219 ccv3.Warnings{"get-task-warning-1"}, 220 nil, 221 ) 222 }) 223 224 It("returns the task and warnings", func() { 225 task, warnings, err := actor.GetTaskBySequenceIDAndApplication(1, "some-app-guid") 226 Expect(err).ToNot(HaveOccurred()) 227 Expect(task).To(Equal(resources.Task(task1))) 228 Expect(warnings).To(ConsistOf("get-task-warning-1")) 229 }) 230 }) 231 232 When("the task is not found", func() { 233 BeforeEach(func() { 234 fakeCloudControllerClient.GetApplicationTasksReturns( 235 []resources.Task{}, 236 ccv3.Warnings{"get-task-warning-1"}, 237 nil, 238 ) 239 }) 240 241 It("returns a TaskNotFoundError and warnings", func() { 242 _, warnings, err := actor.GetTaskBySequenceIDAndApplication(1, "some-app-guid") 243 Expect(err).To(MatchError(actionerror.TaskNotFoundError{SequenceID: 1})) 244 Expect(warnings).To(ConsistOf("get-task-warning-1")) 245 }) 246 }) 247 }) 248 249 When("the cloud controller client returns an error", func() { 250 var expectedErr error 251 252 BeforeEach(func() { 253 expectedErr = errors.New("generic-error") 254 fakeCloudControllerClient.GetApplicationTasksReturns( 255 []resources.Task{}, 256 ccv3.Warnings{"get-task-warning-1"}, 257 expectedErr, 258 ) 259 }) 260 261 It("returns the same error and warnings", func() { 262 _, warnings, err := actor.GetTaskBySequenceIDAndApplication(1, "some-app-guid") 263 Expect(err).To(Equal(expectedErr)) 264 Expect(warnings).To(ConsistOf("get-task-warning-1")) 265 }) 266 }) 267 }) 268 269 Describe("TerminateTask", func() { 270 When("the task exists", func() { 271 var returnedTask resources.Task 272 273 BeforeEach(func() { 274 returnedTask = resources.Task{ 275 GUID: "some-task-guid", 276 SequenceID: 1, 277 } 278 fakeCloudControllerClient.UpdateTaskCancelReturns( 279 returnedTask, 280 ccv3.Warnings{"update-task-warning"}, 281 nil) 282 }) 283 284 It("returns the task and warnings", func() { 285 task, warnings, err := actor.TerminateTask("some-task-guid") 286 Expect(err).NotTo(HaveOccurred()) 287 Expect(warnings).To(ConsistOf("update-task-warning")) 288 Expect(task).To(Equal(resources.Task(returnedTask))) 289 }) 290 }) 291 292 When("the cloud controller returns an error", func() { 293 var expectedErr error 294 295 BeforeEach(func() { 296 expectedErr = errors.New("cc-error") 297 fakeCloudControllerClient.UpdateTaskCancelReturns( 298 resources.Task{}, 299 ccv3.Warnings{"update-task-warning"}, 300 expectedErr) 301 }) 302 303 It("returns the same error and warnings", func() { 304 _, warnings, err := actor.TerminateTask("some-task-guid") 305 Expect(err).To(MatchError(expectedErr)) 306 Expect(warnings).To(ConsistOf("update-task-warning")) 307 }) 308 }) 309 }) 310 311 Describe("PollTask", func() { 312 313 It("polls for SUCCEDED state", func() { 314 firstTaskResponse := resources.Task{State: constant.TaskRunning} 315 secondTaskResponse := resources.Task{State: constant.TaskSucceeded} 316 317 fakeCloudControllerClient.GetTaskReturnsOnCall(0, firstTaskResponse, nil, nil) 318 fakeCloudControllerClient.GetTaskReturnsOnCall(1, secondTaskResponse, nil, nil) 319 320 task, _, _ := actor.PollTask(resources.Task{}) 321 322 Expect(task.State).To(Equal(constant.TaskSucceeded)) 323 }) 324 325 It("polls for FAILED state", func() { 326 firstTaskResponse := resources.Task{State: constant.TaskRunning} 327 secondTaskResponse := resources.Task{State: constant.TaskFailed} 328 329 fakeCloudControllerClient.GetTaskReturnsOnCall(0, firstTaskResponse, nil, nil) 330 fakeCloudControllerClient.GetTaskReturnsOnCall(1, secondTaskResponse, nil, nil) 331 332 task, _, _ := actor.PollTask(resources.Task{}) 333 334 Expect(task.State).To(Equal(constant.TaskFailed)) 335 }) 336 337 It("aggregates warnings from all requests made while polling", func() { 338 firstTaskResponse := resources.Task{State: constant.TaskRunning} 339 secondTaskResponse := resources.Task{State: constant.TaskSucceeded} 340 341 fakeCloudControllerClient.GetTaskReturnsOnCall(0, firstTaskResponse, ccv3.Warnings{"warning-1"}, nil) 342 fakeCloudControllerClient.GetTaskReturnsOnCall(1, secondTaskResponse, ccv3.Warnings{"warning-2"}, nil) 343 344 _, warnings, _ := actor.PollTask(resources.Task{}) 345 346 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 347 }) 348 349 It("handles errors from requests to cc", func() { 350 firstTaskResponse := resources.Task{State: constant.TaskSucceeded} 351 352 fakeCloudControllerClient.GetTaskReturnsOnCall(0, firstTaskResponse, nil, errors.New("request-error")) 353 354 _, _, err := actor.PollTask(resources.Task{}) 355 356 Expect(err).To(MatchError("request-error")) 357 }) 358 359 It("returns an error if the task failed", func() { 360 firstTaskResponse := resources.Task{State: constant.TaskFailed} 361 362 fakeCloudControllerClient.GetTaskReturnsOnCall(0, firstTaskResponse, nil, nil) 363 364 _, _, err := actor.PollTask(resources.Task{}) 365 366 Expect(err).To(MatchError("Task failed to complete successfully")) 367 }) 368 }) 369 })