github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+incompatible/api/cloudcontroller/ccv3/task_test.go (about)

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