github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/api/cloudcontroller/ccv2/application_test.go (about)

     1  package ccv2_test
     2  
     3  import (
     4  	"net/http"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  	. "github.com/onsi/gomega/ghttp"
    12  )
    13  
    14  var _ = Describe("Application", func() {
    15  	var client *Client
    16  
    17  	BeforeEach(func() {
    18  		client = NewTestClient()
    19  	})
    20  
    21  	Describe("CreateApplication", func() {
    22  		Context("when the update is successful", func() {
    23  			Context("when setting the minimum", func() { // are we **only** encoding the things we want
    24  				BeforeEach(func() {
    25  					response := `
    26  						{
    27  							"metadata": {
    28  								"guid": "some-app-guid"
    29  							},
    30  							"entity": {
    31  								"name": "some-app-name",
    32  								"space_guid": "some-space-guid"
    33  							}
    34  						}`
    35  					requestBody := map[string]string{
    36  						"name":       "some-app-name",
    37  						"space_guid": "some-space-guid",
    38  					}
    39  					server.AppendHandlers(
    40  						CombineHandlers(
    41  							VerifyRequest(http.MethodPost, "/v2/apps"),
    42  							VerifyJSONRepresenting(requestBody),
    43  							RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    44  						),
    45  					)
    46  				})
    47  
    48  				It("returns the created object and warnings", func() {
    49  					app, warnings, err := client.CreateApplication(Application{
    50  						Name:      "some-app-name",
    51  						SpaceGUID: "some-space-guid",
    52  					})
    53  					Expect(err).NotTo(HaveOccurred())
    54  
    55  					Expect(app).To(Equal(Application{
    56  						GUID: "some-app-guid",
    57  						Name: "some-app-name",
    58  					}))
    59  					Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
    60  				})
    61  			})
    62  		})
    63  
    64  		Context("when the create returns an error", func() {
    65  			BeforeEach(func() {
    66  				response := `
    67  					{
    68  						"description": "Request invalid due to parse error: Field: name, Error: Missing field name, Field: space_guid, Error: Missing field space_guid",
    69  						"error_code": "CF-MessageParseError",
    70  						"code": 1001
    71  					}
    72  			`
    73  				server.AppendHandlers(
    74  					CombineHandlers(
    75  						VerifyRequest(http.MethodPost, "/v2/apps"),
    76  						RespondWith(http.StatusBadRequest, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    77  					),
    78  				)
    79  			})
    80  
    81  			It("returns the error and warnings", func() {
    82  				_, warnings, err := client.CreateApplication(Application{})
    83  				Expect(err).To(MatchError(ccerror.BadRequestError{Message: "Request invalid due to parse error: Field: name, Error: Missing field name, Field: space_guid, Error: Missing field space_guid"}))
    84  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
    85  			})
    86  		})
    87  	})
    88  
    89  	Describe("GetApplication", func() {
    90  		BeforeEach(func() {
    91  			response := `{
    92  						"metadata": {
    93  							"guid": "app-guid-1",
    94  							"updated_at": null
    95  						},
    96  						"entity": {
    97  							"buildpack": "ruby 1.6.29",
    98  							"detected_start_command": "echo 'I am a banana'",
    99  							"disk_quota": 586,
   100  							"detected_buildpack": null,
   101  							"docker_image": "some-docker-path",
   102  							"health_check_type": "port",
   103  							"health_check_http_endpoint": "/",
   104  							"instances": 13,
   105  							"memory": 1024,
   106  							"name": "app-name-1",
   107  							"package_state": "FAILED",
   108  							"package_updated_at": "2015-03-10T23:11:54Z",
   109  							"stack_guid": "some-stack-guid",
   110  							"staging_failed_description": "some-staging-failed-description",
   111  							"staging_failed_reason": "some-reason",
   112  							"state": "STOPPED"
   113  						}
   114  			}`
   115  			server.AppendHandlers(
   116  				CombineHandlers(
   117  					VerifyRequest(http.MethodGet, "/v2/apps/app-guid-1"),
   118  					RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   119  				),
   120  			)
   121  		})
   122  
   123  		Context("when apps exist", func() {
   124  			It("returns the app", func() {
   125  				app, warnings, err := client.GetApplication("app-guid-1")
   126  				Expect(err).NotTo(HaveOccurred())
   127  
   128  				updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z")
   129  				Expect(err).NotTo(HaveOccurred())
   130  
   131  				Expect(app).To(Equal(Application{
   132  					Buildpack:                "ruby 1.6.29",
   133  					DetectedBuildpack:        "",
   134  					DetectedStartCommand:     "echo 'I am a banana'",
   135  					DiskQuota:                586,
   136  					DockerImage:              "some-docker-path",
   137  					GUID:                     "app-guid-1",
   138  					HealthCheckType:          "port",
   139  					HealthCheckHTTPEndpoint:  "/",
   140  					Instances:                13,
   141  					Memory:                   1024,
   142  					Name:                     "app-name-1",
   143  					PackageState:             ApplicationPackageFailed,
   144  					PackageUpdatedAt:         updatedAt,
   145  					StackGUID:                "some-stack-guid",
   146  					StagingFailedDescription: "some-staging-failed-description",
   147  					StagingFailedReason:      "some-reason",
   148  					State:                    ApplicationStopped,
   149  				}))
   150  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   151  			})
   152  		})
   153  	})
   154  
   155  	Describe("GetApplications", func() {
   156  		BeforeEach(func() {
   157  			response1 := `{
   158  				"next_url": "/v2/apps?q=space_guid:some-space-guid&page=2",
   159  				"resources": [
   160  					{
   161  						"metadata": {
   162  							"guid": "app-guid-1",
   163  							"updated_at": null
   164  						},
   165  						"entity": {
   166  							"buildpack": "ruby 1.6.29",
   167  							"detected_start_command": "echo 'I am a banana'",
   168  							"disk_quota": 586,
   169  							"detected_buildpack": null,
   170  							"health_check_type": "port",
   171  							"health_check_http_endpoint": "/",
   172  							"instances": 13,
   173  							"memory": 1024,
   174  							"name": "app-name-1",
   175  							"package_state": "FAILED",
   176  							"package_updated_at": "2015-03-10T23:11:54Z",
   177  							"stack_guid": "some-stack-guid",
   178  							"staging_failed_reason": "some-reason",
   179  							"state": "STOPPED"
   180  						}
   181  					},
   182  					{
   183  						"metadata": {
   184  							"guid": "app-guid-2",
   185  							"updated_at": null
   186  						},
   187  						"entity": {
   188  							"name": "app-name-2",
   189  							"detected_buildpack": "ruby 1.6.29",
   190  							"package_updated_at": null
   191  						}
   192  					}
   193  				]
   194  			}`
   195  			response2 := `{
   196  				"next_url": null,
   197  				"resources": [
   198  					{
   199  						"metadata": {
   200  							"guid": "app-guid-3",
   201  							"updated_at": null
   202  						},
   203  						"entity": {
   204  							"name": "app-name-3"
   205  						}
   206  					},
   207  					{
   208  						"metadata": {
   209  							"guid": "app-guid-4",
   210  							"updated_at": null
   211  						},
   212  						"entity": {
   213  							"name": "app-name-4"
   214  						}
   215  					}
   216  				]
   217  			}`
   218  			server.AppendHandlers(
   219  				CombineHandlers(
   220  					VerifyRequest(http.MethodGet, "/v2/apps", "q=space_guid:some-space-guid"),
   221  					RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   222  				),
   223  			)
   224  			server.AppendHandlers(
   225  				CombineHandlers(
   226  					VerifyRequest(http.MethodGet, "/v2/apps", "q=space_guid:some-space-guid&page=2"),
   227  					RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   228  				),
   229  			)
   230  		})
   231  
   232  		Context("when apps exist", func() {
   233  			It("returns all the queried apps", func() {
   234  				apps, warnings, err := client.GetApplications([]Query{{
   235  					Filter:   SpaceGUIDFilter,
   236  					Operator: EqualOperator,
   237  					Value:    "some-space-guid",
   238  				}})
   239  				Expect(err).NotTo(HaveOccurred())
   240  
   241  				updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z")
   242  				Expect(err).NotTo(HaveOccurred())
   243  
   244  				Expect(apps).To(ConsistOf([]Application{
   245  					{
   246  						Buildpack:               "ruby 1.6.29",
   247  						DetectedBuildpack:       "",
   248  						DetectedStartCommand:    "echo 'I am a banana'",
   249  						DiskQuota:               586,
   250  						GUID:                    "app-guid-1",
   251  						HealthCheckType:         "port",
   252  						HealthCheckHTTPEndpoint: "/",
   253  						Instances:               13,
   254  						Memory:                  1024,
   255  						Name:                    "app-name-1",
   256  						PackageState:            ApplicationPackageFailed,
   257  						PackageUpdatedAt:        updatedAt,
   258  						StackGUID:               "some-stack-guid",
   259  						StagingFailedReason:     "some-reason",
   260  						State:                   ApplicationStopped,
   261  					},
   262  					{Name: "app-name-2", GUID: "app-guid-2", DetectedBuildpack: "ruby 1.6.29"},
   263  					{Name: "app-name-3", GUID: "app-guid-3"},
   264  					{Name: "app-name-4", GUID: "app-guid-4"},
   265  				}))
   266  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"}))
   267  			})
   268  		})
   269  	})
   270  
   271  	Describe("UpdateApplication", func() {
   272  		Context("when the update is successful", func() {
   273  			Context("when updating all fields", func() { //are we encoding everything correctly?
   274  				BeforeEach(func() {
   275  					response1 := `{
   276  				"metadata": {
   277  					"guid": "some-app-guid",
   278  					"updated_at": null
   279  				},
   280  				"entity": {
   281  					"buildpack": "ruby 1.6.29",
   282  					"detected_start_command": "echo 'I am a banana'",
   283  					"disk_quota": 586,
   284  					"detected_buildpack": null,
   285  					"docker_image": "some-docker-path",
   286  					"health_check_type": "some-health-check-type",
   287  					"health_check_http_endpoint": "/anything",
   288  					"instances": 13,
   289  					"memory": 1024,
   290  					"name": "app-name-1",
   291  					"package_updated_at": "2015-03-10T23:11:54Z",
   292  					"stack_guid": "some-stack-guid",
   293  					"state": "STARTED"
   294  				}
   295  			}`
   296  					expectedBody := map[string]string{
   297  						"health_check_http_endpoint": "/anything",
   298  						"health_check_type":          "some-health-check-type",
   299  						"state":                      "STARTED",
   300  						"docker_image":               "some-docker-path",
   301  					}
   302  
   303  					server.AppendHandlers(
   304  						CombineHandlers(
   305  							VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"),
   306  							VerifyJSONRepresenting(expectedBody),
   307  							RespondWith(http.StatusCreated, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   308  						),
   309  					)
   310  				})
   311  
   312  				It("returns the updated object and warnings and sends all updated field", func() {
   313  					app, warnings, err := client.UpdateApplication(Application{
   314  						DockerImage:             "some-docker-path",
   315  						GUID:                    "some-app-guid",
   316  						HealthCheckType:         "some-health-check-type",
   317  						HealthCheckHTTPEndpoint: "/anything",
   318  						State: ApplicationStarted,
   319  					})
   320  					Expect(err).NotTo(HaveOccurred())
   321  
   322  					updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z")
   323  					Expect(err).NotTo(HaveOccurred())
   324  
   325  					Expect(app).To(Equal(Application{
   326  						Buildpack:               "ruby 1.6.29",
   327  						DetectedBuildpack:       "",
   328  						DetectedStartCommand:    "echo 'I am a banana'",
   329  						DiskQuota:               586,
   330  						DockerImage:             "some-docker-path",
   331  						GUID:                    "some-app-guid",
   332  						HealthCheckType:         "some-health-check-type",
   333  						HealthCheckHTTPEndpoint: "/anything",
   334  						Instances:               13,
   335  						Memory:                  1024,
   336  						Name:                    "app-name-1",
   337  						PackageUpdatedAt:        updatedAt,
   338  						StackGUID:               "some-stack-guid",
   339  						State:                   ApplicationStarted,
   340  					}))
   341  					Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   342  				})
   343  			})
   344  
   345  			Context("when only updating one field", func() { // are we **only** encoding the things we want
   346  				BeforeEach(func() {
   347  					response1 := `{
   348  				"metadata": {
   349  					"guid": "some-app-guid",
   350  					"updated_at": null
   351  				},
   352  				"entity": {
   353  					"buildpack": "ruby 1.6.29",
   354  					"detected_start_command": "echo 'I am a banana'",
   355  					"disk_quota": 586,
   356  					"detected_buildpack": null,
   357  					"health_check_type": "some-health-check-type",
   358  					"health_check_http_endpoint": "/",
   359  					"instances": 13,
   360  					"memory": 1024,
   361  					"name": "app-name-1",
   362  					"package_updated_at": "2015-03-10T23:11:54Z",
   363  					"stack_guid": "some-stack-guid",
   364  					"state": "STOPPED"
   365  				}
   366  			}`
   367  					server.AppendHandlers(
   368  						CombineHandlers(
   369  							VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"),
   370  							VerifyBody([]byte(`{"health_check_type":"some-health-check-type"}`)),
   371  							RespondWith(http.StatusCreated, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   372  						),
   373  					)
   374  				})
   375  
   376  				It("returns the updated object and warnings and sends only updated field", func() {
   377  					app, warnings, err := client.UpdateApplication(Application{
   378  						GUID:            "some-app-guid",
   379  						HealthCheckType: "some-health-check-type",
   380  					})
   381  					Expect(err).NotTo(HaveOccurred())
   382  
   383  					updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z")
   384  					Expect(err).NotTo(HaveOccurred())
   385  
   386  					Expect(app).To(Equal(Application{
   387  						Buildpack:               "ruby 1.6.29",
   388  						DetectedBuildpack:       "",
   389  						DetectedStartCommand:    "echo 'I am a banana'",
   390  						DiskQuota:               586,
   391  						GUID:                    "some-app-guid",
   392  						HealthCheckType:         "some-health-check-type",
   393  						HealthCheckHTTPEndpoint: "/",
   394  						Instances:               13,
   395  						Memory:                  1024,
   396  						Name:                    "app-name-1",
   397  						PackageUpdatedAt:        updatedAt,
   398  						StackGUID:               "some-stack-guid",
   399  						State:                   ApplicationStopped,
   400  					}))
   401  					Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   402  				})
   403  			})
   404  		})
   405  
   406  		Context("when the update returns an error", func() {
   407  			BeforeEach(func() {
   408  				response := `
   409  {
   410    "code": 210002,
   411    "description": "The app could not be found: some-app-guid",
   412    "error_code": "CF-AppNotFound"
   413  }
   414  			`
   415  				server.AppendHandlers(
   416  					CombineHandlers(
   417  						VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"),
   418  						// VerifyBody([]byte(`{"health_check_type":"some-health-check-type"}`)),
   419  						RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   420  					),
   421  				)
   422  			})
   423  
   424  			It("returns the error and warnings", func() {
   425  				_, warnings, err := client.UpdateApplication(Application{
   426  					GUID:            "some-app-guid",
   427  					HealthCheckType: "some-health-check-type",
   428  				})
   429  				Expect(err).To(MatchError(ccerror.ResourceNotFoundError{Message: "The app could not be found: some-app-guid"}))
   430  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   431  			})
   432  		})
   433  	})
   434  
   435  	Describe("GetRouteApplications", func() {
   436  		Context("when the route guid is not found", func() {
   437  			BeforeEach(func() {
   438  				response := `
   439  {
   440    "code": 210002,
   441    "description": "The route could not be found: some-route-guid",
   442    "error_code": "CF-RouteNotFound"
   443  }
   444  			`
   445  				server.AppendHandlers(
   446  					CombineHandlers(
   447  						VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps"),
   448  						RespondWith(http.StatusNotFound, response),
   449  					),
   450  				)
   451  			})
   452  
   453  			It("returns an error", func() {
   454  				_, _, err := client.GetRouteApplications("some-route-guid", nil)
   455  				Expect(err).To(MatchError(ccerror.ResourceNotFoundError{
   456  					Message: "The route could not be found: some-route-guid",
   457  				}))
   458  			})
   459  		})
   460  
   461  		Context("when there are applications associated with this route", func() {
   462  			BeforeEach(func() {
   463  				response1 := `{
   464  				"next_url": "/v2/routes/some-route-guid/apps?q=space_guid:some-space-guid&page=2",
   465  				"resources": [
   466  					{
   467  						"metadata": {
   468  							"guid": "app-guid-1",
   469  							"updated_at": null
   470  						},
   471  						"entity": {
   472  							"name": "app-name-1"
   473  						}
   474  					},
   475  					{
   476  						"metadata": {
   477  							"guid": "app-guid-2",
   478  							"updated_at": null
   479  						},
   480  						"entity": {
   481  							"name": "app-name-2"
   482  						}
   483  					}
   484  				]
   485  			}`
   486  				response2 := `{
   487  				"next_url": null,
   488  				"resources": [
   489  					{
   490  						"metadata": {
   491  							"guid": "app-guid-3",
   492  							"updated_at": null
   493  						},
   494  						"entity": {
   495  							"name": "app-name-3"
   496  						}
   497  					},
   498  					{
   499  						"metadata": {
   500  							"guid": "app-guid-4",
   501  							"updated_at": null
   502  						},
   503  						"entity": {
   504  							"name": "app-name-4"
   505  						}
   506  					}
   507  				]
   508  			}`
   509  				server.AppendHandlers(
   510  					CombineHandlers(
   511  						VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps", "q=space_guid:some-space-guid"),
   512  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   513  					),
   514  				)
   515  				server.AppendHandlers(
   516  					CombineHandlers(
   517  						VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps", "q=space_guid:some-space-guid&page=2"),
   518  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   519  					),
   520  				)
   521  			})
   522  
   523  			It("returns all the applications and all warnings", func() {
   524  				apps, warnings, err := client.GetRouteApplications("some-route-guid", []Query{{
   525  					Filter:   SpaceGUIDFilter,
   526  					Operator: EqualOperator,
   527  					Value:    "some-space-guid",
   528  				}})
   529  				Expect(err).NotTo(HaveOccurred())
   530  				Expect(apps).To(ConsistOf([]Application{
   531  					{Name: "app-name-1", GUID: "app-guid-1"},
   532  					{Name: "app-name-2", GUID: "app-guid-2"},
   533  					{Name: "app-name-3", GUID: "app-guid-3"},
   534  					{Name: "app-name-4", GUID: "app-guid-4"},
   535  				}))
   536  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"}))
   537  			})
   538  		})
   539  
   540  		Context("when there are no applications associated with this route", func() {
   541  			BeforeEach(func() {
   542  				response := `{
   543  				"next_url": "",
   544  				"resources": []
   545  			}`
   546  				server.AppendHandlers(
   547  					CombineHandlers(
   548  						VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps"),
   549  						RespondWith(http.StatusOK, response),
   550  					),
   551  				)
   552  			})
   553  
   554  			It("returns an empty list of applications", func() {
   555  				apps, _, err := client.GetRouteApplications("some-route-guid", nil)
   556  				Expect(err).NotTo(HaveOccurred())
   557  				Expect(apps).To(BeEmpty())
   558  			})
   559  		})
   560  	})
   561  })