github.com/orange-cloudfoundry/cli@v7.1.0+incompatible/api/cloudcontroller/ccv3/task_test.go (about)

     1  package ccv3_test
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  	. "github.com/onsi/ginkgo"
    11  	. "github.com/onsi/gomega"
    12  	. "github.com/onsi/gomega/ghttp"
    13  )
    14  
    15  var _ = Describe("Task", func() {
    16  	var client *Client
    17  
    18  	BeforeEach(func() {
    19  		client, _ = NewTestClient()
    20  	})
    21  
    22  	Describe("CreateApplicationTask", func() {
    23  		var (
    24  			submitTask Task
    25  
    26  			task       Task
    27  			warnings   Warnings
    28  			executeErr error
    29  		)
    30  
    31  		JustBeforeEach(func() {
    32  			task, warnings, executeErr = client.CreateApplicationTask("some-app-guid", submitTask)
    33  		})
    34  
    35  		When("the application exists", func() {
    36  			var response string
    37  
    38  			BeforeEach(func() {
    39  				response = `{
    40  					"sequence_id": 3
    41  				}`
    42  			})
    43  
    44  			When("the name is empty", func() {
    45  				BeforeEach(func() {
    46  					server.AppendHandlers(
    47  						CombineHandlers(
    48  							VerifyRequest(http.MethodPost, "/v3/apps/some-app-guid/tasks"),
    49  							VerifyJSON(`{"command":"some command"}`),
    50  							RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}),
    51  						),
    52  					)
    53  
    54  					submitTask = Task{Command: "some command"}
    55  				})
    56  
    57  				It("creates and returns the task and all warnings", func() {
    58  					Expect(executeErr).ToNot(HaveOccurred())
    59  
    60  					Expect(task).To(Equal(Task{SequenceID: 3}))
    61  					Expect(warnings).To(ConsistOf("warning"))
    62  				})
    63  			})
    64  
    65  			When("the name is not empty", func() {
    66  				BeforeEach(func() {
    67  					server.AppendHandlers(
    68  						CombineHandlers(
    69  							VerifyRequest(http.MethodPost, "/v3/apps/some-app-guid/tasks"),
    70  							VerifyJSON(`{"command":"some command", "name":"some-task-name"}`),
    71  							RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}),
    72  						),
    73  					)
    74  
    75  					submitTask = Task{Command: "some command", Name: "some-task-name"}
    76  				})
    77  
    78  				It("creates and returns the task and all warnings", func() {
    79  					Expect(executeErr).ToNot(HaveOccurred())
    80  
    81  					Expect(task).To(Equal(Task{SequenceID: 3}))
    82  					Expect(warnings).To(ConsistOf("warning"))
    83  				})
    84  			})
    85  
    86  			When("the disk size is not 0", func() {
    87  				BeforeEach(func() {
    88  					response := `{
    89  						"disk_in_mb": 123,
    90  						"sequence_id": 3
    91  					}`
    92  					server.AppendHandlers(
    93  						CombineHandlers(
    94  							VerifyRequest(http.MethodPost, "/v3/apps/some-app-guid/tasks"),
    95  							VerifyJSON(`{"command":"some command", "disk_in_mb": 123}`),
    96  							RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}),
    97  						),
    98  					)
    99  					submitTask = Task{Command: "some command", DiskInMB: uint64(123)}
   100  				})
   101  
   102  				It("creates and returns the task and all warnings with the provided disk size", func() {
   103  					Expect(executeErr).ToNot(HaveOccurred())
   104  
   105  					Expect(task).To(Equal(Task{DiskInMB: uint64(123), SequenceID: 3}))
   106  					Expect(warnings).To(ConsistOf("warning"))
   107  				})
   108  			})
   109  
   110  			When("the memory is not 0", func() {
   111  				BeforeEach(func() {
   112  					response := `{
   113  						"memory_in_mb": 123,
   114  						"sequence_id": 3
   115  					}`
   116  					server.AppendHandlers(
   117  						CombineHandlers(
   118  							VerifyRequest(http.MethodPost, "/v3/apps/some-app-guid/tasks"),
   119  							VerifyJSON(`{"command":"some command", "memory_in_mb": 123}`),
   120  							RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}),
   121  						),
   122  					)
   123  
   124  					submitTask = Task{Command: "some command", MemoryInMB: uint64(123)}
   125  				})
   126  
   127  				It("creates and returns the task and all warnings with the provided memory", func() {
   128  					Expect(executeErr).ToNot(HaveOccurred())
   129  
   130  					Expect(task).To(Equal(Task{MemoryInMB: uint64(123), SequenceID: 3}))
   131  					Expect(warnings).To(ConsistOf("warning"))
   132  				})
   133  			})
   134  
   135  		})
   136  
   137  		When("the cloud controller returns errors and warnings", func() {
   138  			BeforeEach(func() {
   139  				response := `{
   140  					"errors": [
   141  						{
   142  							"code": 10008,
   143  							"detail": "The request is semantically invalid: command presence",
   144  							"title": "CF-UnprocessableEntity"
   145  						},
   146  						{
   147  							"code": 10010,
   148  							"detail": "App not found",
   149  							"title": "CF-ResourceNotFound"
   150  						}
   151  					]
   152  				}`
   153  				server.AppendHandlers(
   154  					CombineHandlers(
   155  						VerifyRequest(http.MethodPost, "/v3/apps/some-app-guid/tasks"),
   156  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"warning"}}),
   157  					),
   158  				)
   159  
   160  				submitTask = Task{Command: "some command"}
   161  			})
   162  
   163  			It("returns the errors and all warnings", func() {
   164  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   165  					ResponseCode: http.StatusTeapot,
   166  					Errors: []ccerror.V3Error{
   167  						{
   168  							Code:   10008,
   169  							Detail: "The request is semantically invalid: command presence",
   170  							Title:  "CF-UnprocessableEntity",
   171  						},
   172  						{
   173  							Code:   10010,
   174  							Detail: "App not found",
   175  							Title:  "CF-ResourceNotFound",
   176  						},
   177  					},
   178  				}))
   179  				Expect(warnings).To(ConsistOf("warning"))
   180  			})
   181  		})
   182  	})
   183  
   184  	Describe("GetApplicationTasks", func() {
   185  		var (
   186  			submitQuery Query
   187  
   188  			tasks      []Task
   189  			warnings   Warnings
   190  			executeErr error
   191  		)
   192  
   193  		JustBeforeEach(func() {
   194  			tasks, warnings, executeErr = client.GetApplicationTasks("some-app-guid", submitQuery)
   195  		})
   196  
   197  		When("the application exists", func() {
   198  			BeforeEach(func() {
   199  				response1 := fmt.Sprintf(`{
   200  					"pagination": {
   201  						"next": {
   202  							"href": "%s/v3/apps/some-app-guid/tasks?per_page=2&page=2"
   203  						}
   204  					},
   205  					"resources": [
   206  						{
   207  							"guid": "task-1-guid",
   208  							"sequence_id": 1,
   209  							"name": "task-1",
   210  							"command": "some-command",
   211  							"state": "SUCCEEDED",
   212  							"created_at": "2016-11-07T05:59:01Z"
   213  						},
   214  						{
   215  							"guid": "task-2-guid",
   216  							"sequence_id": 2,
   217  							"name": "task-2",
   218  							"command": "some-command",
   219  							"state": "FAILED",
   220  							"created_at": "2016-11-07T06:59:01Z"
   221  						}
   222  					]
   223  				}`, server.URL())
   224  				response2 := `{
   225  					"pagination": {
   226  						"next": null
   227  					},
   228  					"resources": [
   229  						{
   230  							"guid": "task-3-guid",
   231  							"sequence_id": 3,
   232  							"name": "task-3",
   233  							"command": "some-command",
   234  							"state": "RUNNING",
   235  							"created_at": "2016-11-07T07:59:01Z"
   236  						}
   237  					]
   238  				}`
   239  				server.AppendHandlers(
   240  					CombineHandlers(
   241  						VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "per_page=2"),
   242  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"warning-1"}}),
   243  					),
   244  				)
   245  				server.AppendHandlers(
   246  					CombineHandlers(
   247  						VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks", "per_page=2&page=2"),
   248  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"warning-2"}}),
   249  					),
   250  				)
   251  
   252  				submitQuery = Query{Key: PerPage, Values: []string{"2"}}
   253  			})
   254  
   255  			It("returns a list of tasks associated with the application and all warnings", func() {
   256  				Expect(executeErr).ToNot(HaveOccurred())
   257  
   258  				Expect(tasks).To(ConsistOf(
   259  					Task{
   260  						GUID:       "task-1-guid",
   261  						SequenceID: 1,
   262  						Name:       "task-1",
   263  						State:      constant.TaskSucceeded,
   264  						CreatedAt:  "2016-11-07T05:59:01Z",
   265  						Command:    "some-command",
   266  					},
   267  					Task{
   268  						GUID:       "task-2-guid",
   269  						SequenceID: 2,
   270  						Name:       "task-2",
   271  						State:      constant.TaskFailed,
   272  						CreatedAt:  "2016-11-07T06:59:01Z",
   273  						Command:    "some-command",
   274  					},
   275  					Task{
   276  						GUID:       "task-3-guid",
   277  						SequenceID: 3,
   278  						Name:       "task-3",
   279  						State:      constant.TaskRunning,
   280  						CreatedAt:  "2016-11-07T07:59:01Z",
   281  						Command:    "some-command",
   282  					},
   283  				))
   284  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   285  			})
   286  		})
   287  
   288  		When("the application does not exist", func() {
   289  			BeforeEach(func() {
   290  				response := `{
   291  					"errors": [
   292  						{
   293  							"code": 10010,
   294  							"detail": "App not found",
   295  							"title": "CF-ResourceNotFound"
   296  						}
   297  					]
   298  				}`
   299  				server.AppendHandlers(
   300  					CombineHandlers(
   301  						VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks"),
   302  						RespondWith(http.StatusNotFound, response),
   303  					),
   304  				)
   305  			})
   306  
   307  			It("returns a ResourceNotFoundError", func() {
   308  				Expect(executeErr).To(MatchError(ccerror.ApplicationNotFoundError{}))
   309  			})
   310  		})
   311  
   312  		When("the cloud controller returns errors and warnings", func() {
   313  			BeforeEach(func() {
   314  				response := `{
   315  					"errors": [
   316  						{
   317  							"code": 10008,
   318  							"detail": "The request is semantically invalid: command presence",
   319  							"title": "CF-UnprocessableEntity"
   320  						},
   321  						{
   322  							"code": 10010,
   323  							"detail": "App not found",
   324  							"title": "CF-ResourceNotFound"
   325  						}
   326  					]
   327  				}`
   328  				server.AppendHandlers(
   329  					CombineHandlers(
   330  						VerifyRequest(http.MethodGet, "/v3/apps/some-app-guid/tasks"),
   331  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"warning"}}),
   332  					),
   333  				)
   334  			})
   335  
   336  			It("returns the errors and all warnings", func() {
   337  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   338  					ResponseCode: http.StatusTeapot,
   339  					Errors: []ccerror.V3Error{
   340  						{
   341  							Code:   10008,
   342  							Detail: "The request is semantically invalid: command presence",
   343  							Title:  "CF-UnprocessableEntity",
   344  						},
   345  						{
   346  							Code:   10010,
   347  							Detail: "App not found",
   348  							Title:  "CF-ResourceNotFound",
   349  						},
   350  					},
   351  				}))
   352  				Expect(warnings).To(ConsistOf("warning"))
   353  			})
   354  		})
   355  	})
   356  
   357  	Describe("UpdateTaskCancel", func() {
   358  		var (
   359  			task       Task
   360  			warnings   Warnings
   361  			executeErr error
   362  		)
   363  
   364  		JustBeforeEach(func() {
   365  			task, warnings, executeErr = client.UpdateTaskCancel("some-task-guid")
   366  		})
   367  
   368  		When("the request succeeds", func() {
   369  			BeforeEach(func() {
   370  				response := `{
   371            "guid": "task-3-guid",
   372            "sequence_id": 3,
   373            "name": "task-3",
   374            "command": "some-command",
   375            "state": "CANCELING",
   376            "created_at": "2016-11-07T07:59:01Z"
   377          }`
   378  				server.AppendHandlers(
   379  					CombineHandlers(
   380  						VerifyRequest(http.MethodPut, "/v3/tasks/some-task-guid/cancel"),
   381  						RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}),
   382  					),
   383  				)
   384  			})
   385  
   386  			It("returns the task and warnings", func() {
   387  				Expect(executeErr).ToNot(HaveOccurred())
   388  
   389  				Expect(task).To(Equal(Task{
   390  					GUID:       "task-3-guid",
   391  					SequenceID: 3,
   392  					Name:       "task-3",
   393  					Command:    "some-command",
   394  					State:      constant.TaskCanceling,
   395  					CreatedAt:  "2016-11-07T07:59:01Z",
   396  				}))
   397  				Expect(warnings).To(ConsistOf("warning"))
   398  			})
   399  		})
   400  
   401  		When("the request fails", func() {
   402  			BeforeEach(func() {
   403  				response := `{
   404  					"errors": [
   405  						{
   406  							"code": 10008,
   407  							"detail": "The request is semantically invalid: command presence",
   408  							"title": "CF-UnprocessableEntity"
   409  						},
   410  						{
   411  							"code": 10010,
   412  							"detail": "App not found",
   413  							"title": "CF-ResourceNotFound"
   414  						}
   415  					]
   416  				}`
   417  				server.AppendHandlers(
   418  					CombineHandlers(
   419  						VerifyRequest(http.MethodPut, "/v3/tasks/some-task-guid/cancel"),
   420  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"warning"}}),
   421  					),
   422  				)
   423  			})
   424  
   425  			It("returns the errors and all warnings", func() {
   426  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   427  					ResponseCode: http.StatusTeapot,
   428  					Errors: []ccerror.V3Error{
   429  						{
   430  							Code:   10008,
   431  							Detail: "The request is semantically invalid: command presence",
   432  							Title:  "CF-UnprocessableEntity",
   433  						},
   434  						{
   435  							Code:   10010,
   436  							Detail: "App not found",
   437  							Title:  "CF-ResourceNotFound",
   438  						},
   439  					},
   440  				}))
   441  				Expect(warnings).To(ConsistOf("warning"))
   442  			})
   443  		})
   444  	})
   445  })