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  })